xref: /f-stack/dpdk/drivers/net/igc/base/igc_manage.c (revision 2d9fd380)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2020 Intel Corporation
3  */
4 
5 #include "igc_api.h"
6 #include "igc_manage.h"
7 
8 /**
9  *  igc_calculate_checksum - Calculate checksum for buffer
10  *  @buffer: pointer to EEPROM
11  *  @length: size of EEPROM to calculate a checksum for
12  *
13  *  Calculates the checksum for some buffer on a specified length.  The
14  *  checksum calculated is returned.
15  **/
igc_calculate_checksum(u8 * buffer,u32 length)16 u8 igc_calculate_checksum(u8 *buffer, u32 length)
17 {
18 	u32 i;
19 	u8 sum = 0;
20 
21 	DEBUGFUNC("igc_calculate_checksum");
22 
23 	if (!buffer)
24 		return 0;
25 
26 	for (i = 0; i < length; i++)
27 		sum += buffer[i];
28 
29 	return (u8)(0 - sum);
30 }
31 
32 /**
33  *  igc_mng_enable_host_if_generic - Checks host interface is enabled
34  *  @hw: pointer to the HW structure
35  *
36  *  Returns IGC_success upon success, else IGC_ERR_HOST_INTERFACE_COMMAND
37  *
38  *  This function checks whether the HOST IF is enabled for command operation
39  *  and also checks whether the previous command is completed.  It busy waits
40  *  in case of previous command is not completed.
41  **/
igc_mng_enable_host_if_generic(struct igc_hw * hw)42 s32 igc_mng_enable_host_if_generic(struct igc_hw *hw)
43 {
44 	u32 hicr;
45 	u8 i;
46 
47 	DEBUGFUNC("igc_mng_enable_host_if_generic");
48 
49 	if (!hw->mac.arc_subsystem_valid) {
50 		DEBUGOUT("ARC subsystem not valid.\n");
51 		return -IGC_ERR_HOST_INTERFACE_COMMAND;
52 	}
53 
54 	/* Check that the host interface is enabled. */
55 	hicr = IGC_READ_REG(hw, IGC_HICR);
56 	if (!(hicr & IGC_HICR_EN)) {
57 		DEBUGOUT("IGC_HOST_EN bit disabled.\n");
58 		return -IGC_ERR_HOST_INTERFACE_COMMAND;
59 	}
60 	/* check the previous command is completed */
61 	for (i = 0; i < IGC_MNG_DHCP_COMMAND_TIMEOUT; i++) {
62 		hicr = IGC_READ_REG(hw, IGC_HICR);
63 		if (!(hicr & IGC_HICR_C))
64 			break;
65 		msec_delay_irq(1);
66 	}
67 
68 	if (i == IGC_MNG_DHCP_COMMAND_TIMEOUT) {
69 		DEBUGOUT("Previous command timeout failed .\n");
70 		return -IGC_ERR_HOST_INTERFACE_COMMAND;
71 	}
72 
73 	return IGC_SUCCESS;
74 }
75 
76 /**
77  *  igc_check_mng_mode_generic - Generic check management mode
78  *  @hw: pointer to the HW structure
79  *
80  *  Reads the firmware semaphore register and returns true (>0) if
81  *  manageability is enabled, else false (0).
82  **/
igc_check_mng_mode_generic(struct igc_hw * hw)83 bool igc_check_mng_mode_generic(struct igc_hw *hw)
84 {
85 	u32 fwsm = IGC_READ_REG(hw, IGC_FWSM);
86 
87 	DEBUGFUNC("igc_check_mng_mode_generic");
88 
89 
90 	return (fwsm & IGC_FWSM_MODE_MASK) ==
91 		(IGC_MNG_IAMT_MODE << IGC_FWSM_MODE_SHIFT);
92 }
93 
94 /**
95  *  igc_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
96  *  @hw: pointer to the HW structure
97  *
98  *  Enables packet filtering on transmit packets if manageability is enabled
99  *  and host interface is enabled.
100  **/
igc_enable_tx_pkt_filtering_generic(struct igc_hw * hw)101 bool igc_enable_tx_pkt_filtering_generic(struct igc_hw *hw)
102 {
103 	struct igc_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
104 	u32 *buffer = (u32 *)&hw->mng_cookie;
105 	u32 offset;
106 	s32 ret_val, hdr_csum, csum;
107 	u8 i, len;
108 
109 	DEBUGFUNC("igc_enable_tx_pkt_filtering_generic");
110 
111 	hw->mac.tx_pkt_filtering = true;
112 
113 	/* No manageability, no filtering */
114 	if (!hw->mac.ops.check_mng_mode(hw)) {
115 		hw->mac.tx_pkt_filtering = false;
116 		return hw->mac.tx_pkt_filtering;
117 	}
118 
119 	/* If we can't read from the host interface for whatever
120 	 * reason, disable filtering.
121 	 */
122 	ret_val = igc_mng_enable_host_if_generic(hw);
123 	if (ret_val != IGC_SUCCESS) {
124 		hw->mac.tx_pkt_filtering = false;
125 		return hw->mac.tx_pkt_filtering;
126 	}
127 
128 	/* Read in the header.  Length and offset are in dwords. */
129 	len    = IGC_MNG_DHCP_COOKIE_LENGTH >> 2;
130 	offset = IGC_MNG_DHCP_COOKIE_OFFSET >> 2;
131 	for (i = 0; i < len; i++)
132 		*(buffer + i) = IGC_READ_REG_ARRAY_DWORD(hw, IGC_HOST_IF,
133 							   offset + i);
134 	hdr_csum = hdr->checksum;
135 	hdr->checksum = 0;
136 	csum = igc_calculate_checksum((u8 *)hdr,
137 					IGC_MNG_DHCP_COOKIE_LENGTH);
138 	/* If either the checksums or signature don't match, then
139 	 * the cookie area isn't considered valid, in which case we
140 	 * take the safe route of assuming Tx filtering is enabled.
141 	 */
142 	if (hdr_csum != csum || hdr->signature != IGC_IAMT_SIGNATURE) {
143 		hw->mac.tx_pkt_filtering = true;
144 		return hw->mac.tx_pkt_filtering;
145 	}
146 
147 	/* Cookie area is valid, make the final check for filtering. */
148 	if (!(hdr->status & IGC_MNG_DHCP_COOKIE_STATUS_PARSING))
149 		hw->mac.tx_pkt_filtering = false;
150 
151 	return hw->mac.tx_pkt_filtering;
152 }
153 
154 /**
155  *  igc_mng_write_cmd_header_generic - Writes manageability command header
156  *  @hw: pointer to the HW structure
157  *  @hdr: pointer to the host interface command header
158  *
159  *  Writes the command header after does the checksum calculation.
160  **/
igc_mng_write_cmd_header_generic(struct igc_hw * hw,struct igc_host_mng_command_header * hdr)161 s32 igc_mng_write_cmd_header_generic(struct igc_hw *hw,
162 				      struct igc_host_mng_command_header *hdr)
163 {
164 	u16 i, length = sizeof(struct igc_host_mng_command_header);
165 
166 	DEBUGFUNC("igc_mng_write_cmd_header_generic");
167 
168 	/* Write the whole command header structure with new checksum. */
169 
170 	hdr->checksum = igc_calculate_checksum((u8 *)hdr, length);
171 
172 	length >>= 2;
173 	/* Write the relevant command block into the ram area. */
174 	for (i = 0; i < length; i++) {
175 		IGC_WRITE_REG_ARRAY_DWORD(hw, IGC_HOST_IF, i,
176 					*((u32 *)hdr + i));
177 		IGC_WRITE_FLUSH(hw);
178 	}
179 
180 	return IGC_SUCCESS;
181 }
182 
183 /**
184  *  igc_mng_host_if_write_generic - Write to the manageability host interface
185  *  @hw: pointer to the HW structure
186  *  @buffer: pointer to the host interface buffer
187  *  @length: size of the buffer
188  *  @offset: location in the buffer to write to
189  *  @sum: sum of the data (not checksum)
190  *
191  *  This function writes the buffer content at the offset given on the host if.
192  *  It also does alignment considerations to do the writes in most efficient
193  *  way.  Also fills up the sum of the buffer in *buffer parameter.
194  **/
igc_mng_host_if_write_generic(struct igc_hw * hw,u8 * buffer,u16 length,u16 offset,u8 * sum)195 s32 igc_mng_host_if_write_generic(struct igc_hw *hw, u8 *buffer,
196 				    u16 length, u16 offset, u8 *sum)
197 {
198 	u8 *tmp;
199 	u8 *bufptr = buffer;
200 	u32 data = 0;
201 	u16 remaining, i, j, prev_bytes;
202 
203 	DEBUGFUNC("igc_mng_host_if_write_generic");
204 
205 	/* sum = only sum of the data and it is not checksum */
206 
207 	if (length == 0 || offset + length > IGC_HI_MAX_MNG_DATA_LENGTH)
208 		return -IGC_ERR_PARAM;
209 
210 	tmp = (u8 *)&data;
211 	prev_bytes = offset & 0x3;
212 	offset >>= 2;
213 
214 	if (prev_bytes) {
215 		data = IGC_READ_REG_ARRAY_DWORD(hw, IGC_HOST_IF, offset);
216 		for (j = prev_bytes; j < sizeof(u32); j++) {
217 			*(tmp + j) = *bufptr++;
218 			*sum += *(tmp + j);
219 		}
220 		IGC_WRITE_REG_ARRAY_DWORD(hw, IGC_HOST_IF, offset, data);
221 		length -= j - prev_bytes;
222 		offset++;
223 	}
224 
225 	remaining = length & 0x3;
226 	length -= remaining;
227 
228 	/* Calculate length in DWORDs */
229 	length >>= 2;
230 
231 	/* The device driver writes the relevant command block into the
232 	 * ram area.
233 	 */
234 	for (i = 0; i < length; i++) {
235 		for (j = 0; j < sizeof(u32); j++) {
236 			*(tmp + j) = *bufptr++;
237 			*sum += *(tmp + j);
238 		}
239 
240 		IGC_WRITE_REG_ARRAY_DWORD(hw, IGC_HOST_IF, offset + i,
241 					    data);
242 	}
243 	if (remaining) {
244 		for (j = 0; j < sizeof(u32); j++) {
245 			if (j < remaining)
246 				*(tmp + j) = *bufptr++;
247 			else
248 				*(tmp + j) = 0;
249 
250 			*sum += *(tmp + j);
251 		}
252 		IGC_WRITE_REG_ARRAY_DWORD(hw, IGC_HOST_IF, offset + i,
253 					    data);
254 	}
255 
256 	return IGC_SUCCESS;
257 }
258 
259 /**
260  *  igc_mng_write_dhcp_info_generic - Writes DHCP info to host interface
261  *  @hw: pointer to the HW structure
262  *  @buffer: pointer to the host interface
263  *  @length: size of the buffer
264  *
265  *  Writes the DHCP information to the host interface.
266  **/
igc_mng_write_dhcp_info_generic(struct igc_hw * hw,u8 * buffer,u16 length)267 s32 igc_mng_write_dhcp_info_generic(struct igc_hw *hw, u8 *buffer,
268 				      u16 length)
269 {
270 	struct igc_host_mng_command_header hdr;
271 	s32 ret_val;
272 	u32 hicr;
273 
274 	DEBUGFUNC("igc_mng_write_dhcp_info_generic");
275 
276 	hdr.command_id = IGC_MNG_DHCP_TX_PAYLOAD_CMD;
277 	hdr.command_length = length;
278 	hdr.reserved1 = 0;
279 	hdr.reserved2 = 0;
280 	hdr.checksum = 0;
281 
282 	/* Enable the host interface */
283 	ret_val = igc_mng_enable_host_if_generic(hw);
284 	if (ret_val)
285 		return ret_val;
286 
287 	/* Populate the host interface with the contents of "buffer". */
288 	ret_val = igc_mng_host_if_write_generic(hw, buffer, length,
289 						sizeof(hdr), &hdr.checksum);
290 	if (ret_val)
291 		return ret_val;
292 
293 	/* Write the manageability command header */
294 	ret_val = igc_mng_write_cmd_header_generic(hw, &hdr);
295 	if (ret_val)
296 		return ret_val;
297 
298 	/* Tell the ARC a new command is pending. */
299 	hicr = IGC_READ_REG(hw, IGC_HICR);
300 	IGC_WRITE_REG(hw, IGC_HICR, hicr | IGC_HICR_C);
301 
302 	return IGC_SUCCESS;
303 }
304 
305 /**
306  *  igc_enable_mng_pass_thru - Check if management passthrough is needed
307  *  @hw: pointer to the HW structure
308  *
309  *  Verifies the hardware needs to leave interface enabled so that frames can
310  *  be directed to and from the management interface.
311  **/
igc_enable_mng_pass_thru(struct igc_hw * hw)312 bool igc_enable_mng_pass_thru(struct igc_hw *hw)
313 {
314 	u32 manc;
315 	u32 fwsm, factps;
316 
317 	DEBUGFUNC("igc_enable_mng_pass_thru");
318 
319 	if (!hw->mac.asf_firmware_present)
320 		return false;
321 
322 	manc = IGC_READ_REG(hw, IGC_MANC);
323 
324 	if (!(manc & IGC_MANC_RCV_TCO_EN))
325 		return false;
326 
327 	if (hw->mac.has_fwsm) {
328 		fwsm = IGC_READ_REG(hw, IGC_FWSM);
329 		factps = IGC_READ_REG(hw, IGC_FACTPS);
330 
331 		if (!(factps & IGC_FACTPS_MNGCG) &&
332 		    ((fwsm & IGC_FWSM_MODE_MASK) ==
333 		     (igc_mng_mode_pt << IGC_FWSM_MODE_SHIFT)))
334 			return true;
335 	} else if ((hw->mac.type == igc_82574) ||
336 		   (hw->mac.type == igc_82583)) {
337 		u16 data;
338 		s32 ret_val;
339 
340 		factps = IGC_READ_REG(hw, IGC_FACTPS);
341 		ret_val = igc_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
342 		if (ret_val)
343 			return false;
344 
345 		if (!(factps & IGC_FACTPS_MNGCG) &&
346 		    ((data & IGC_NVM_INIT_CTRL2_MNGM) ==
347 		     (igc_mng_mode_pt << 13)))
348 			return true;
349 	} else if ((manc & IGC_MANC_SMBUS_EN) &&
350 		   !(manc & IGC_MANC_ASF_EN)) {
351 		return true;
352 	}
353 
354 	return false;
355 }
356 
357 /**
358  *  igc_host_interface_command - Writes buffer to host interface
359  *  @hw: pointer to the HW structure
360  *  @buffer: contains a command to write
361  *  @length: the byte length of the buffer, must be multiple of 4 bytes
362  *
363  *  Writes a buffer to the Host Interface.  Upon success, returns IGC_SUCCESS
364  *  else returns IGC_ERR_HOST_INTERFACE_COMMAND.
365  **/
igc_host_interface_command(struct igc_hw * hw,u8 * buffer,u32 length)366 s32 igc_host_interface_command(struct igc_hw *hw, u8 *buffer, u32 length)
367 {
368 	u32 hicr, i;
369 
370 	DEBUGFUNC("igc_host_interface_command");
371 
372 	if (!(hw->mac.arc_subsystem_valid)) {
373 		DEBUGOUT("Hardware doesn't support host interface command.\n");
374 		return IGC_SUCCESS;
375 	}
376 
377 	if (!hw->mac.asf_firmware_present) {
378 		DEBUGOUT("Firmware is not present.\n");
379 		return IGC_SUCCESS;
380 	}
381 
382 	if (length == 0 || length & 0x3 ||
383 	    length > IGC_HI_MAX_BLOCK_BYTE_LENGTH) {
384 		DEBUGOUT("Buffer length failure.\n");
385 		return -IGC_ERR_HOST_INTERFACE_COMMAND;
386 	}
387 
388 	/* Check that the host interface is enabled. */
389 	hicr = IGC_READ_REG(hw, IGC_HICR);
390 	if (!(hicr & IGC_HICR_EN)) {
391 		DEBUGOUT("IGC_HOST_EN bit disabled.\n");
392 		return -IGC_ERR_HOST_INTERFACE_COMMAND;
393 	}
394 
395 	/* Calculate length in DWORDs */
396 	length >>= 2;
397 
398 	/* The device driver writes the relevant command block
399 	 * into the ram area.
400 	 */
401 	for (i = 0; i < length; i++)
402 		IGC_WRITE_REG_ARRAY_DWORD(hw, IGC_HOST_IF, i,
403 					    *((u32 *)buffer + i));
404 
405 	/* Setting this bit tells the ARC that a new command is pending. */
406 	IGC_WRITE_REG(hw, IGC_HICR, hicr | IGC_HICR_C);
407 
408 	for (i = 0; i < IGC_HI_COMMAND_TIMEOUT; i++) {
409 		hicr = IGC_READ_REG(hw, IGC_HICR);
410 		if (!(hicr & IGC_HICR_C))
411 			break;
412 		msec_delay(1);
413 	}
414 
415 	/* Check command successful completion. */
416 	if (i == IGC_HI_COMMAND_TIMEOUT ||
417 	    (!(IGC_READ_REG(hw, IGC_HICR) & IGC_HICR_SV))) {
418 		DEBUGOUT("Command has failed with no status valid.\n");
419 		return -IGC_ERR_HOST_INTERFACE_COMMAND;
420 	}
421 
422 	for (i = 0; i < length; i++)
423 		*((u32 *)buffer + i) = IGC_READ_REG_ARRAY_DWORD(hw,
424 								  IGC_HOST_IF,
425 								  i);
426 
427 	return IGC_SUCCESS;
428 }
429 
430 /**
431  *  igc_load_firmware - Writes proxy FW code buffer to host interface
432  *                        and execute.
433  *  @hw: pointer to the HW structure
434  *  @buffer: contains a firmware to write
435  *  @length: the byte length of the buffer, must be multiple of 4 bytes
436  *
437  *  Upon success returns IGC_SUCCESS, returns IGC_ERR_CONFIG if not enabled
438  *  in HW else returns IGC_ERR_HOST_INTERFACE_COMMAND.
439  **/
igc_load_firmware(struct igc_hw * hw,u8 * buffer,u32 length)440 s32 igc_load_firmware(struct igc_hw *hw, u8 *buffer, u32 length)
441 {
442 	u32 hicr, hibba, fwsm, icr, i;
443 
444 	DEBUGFUNC("igc_load_firmware");
445 
446 	if (hw->mac.type < igc_i210) {
447 		DEBUGOUT("Hardware doesn't support loading FW by the driver\n");
448 		return -IGC_ERR_CONFIG;
449 	}
450 
451 	/* Check that the host interface is enabled. */
452 	hicr = IGC_READ_REG(hw, IGC_HICR);
453 	if (!(hicr & IGC_HICR_EN)) {
454 		DEBUGOUT("IGC_HOST_EN bit disabled.\n");
455 		return -IGC_ERR_CONFIG;
456 	}
457 	if (!(hicr & IGC_HICR_MEMORY_BASE_EN)) {
458 		DEBUGOUT("IGC_HICR_MEMORY_BASE_EN bit disabled.\n");
459 		return -IGC_ERR_CONFIG;
460 	}
461 
462 	if (length == 0 || length & 0x3 || length > IGC_HI_FW_MAX_LENGTH) {
463 		DEBUGOUT("Buffer length failure.\n");
464 		return -IGC_ERR_INVALID_ARGUMENT;
465 	}
466 
467 	/* Clear notification from ROM-FW by reading ICR register */
468 	icr = IGC_READ_REG(hw, IGC_ICR_V2);
469 
470 	/* Reset ROM-FW */
471 	hicr = IGC_READ_REG(hw, IGC_HICR);
472 	hicr |= IGC_HICR_FW_RESET_ENABLE;
473 	IGC_WRITE_REG(hw, IGC_HICR, hicr);
474 	hicr |= IGC_HICR_FW_RESET;
475 	IGC_WRITE_REG(hw, IGC_HICR, hicr);
476 	IGC_WRITE_FLUSH(hw);
477 
478 	/* Wait till MAC notifies about its readiness after ROM-FW reset */
479 	for (i = 0; i < (IGC_HI_COMMAND_TIMEOUT * 2); i++) {
480 		icr = IGC_READ_REG(hw, IGC_ICR_V2);
481 		if (icr & IGC_ICR_MNG)
482 			break;
483 		msec_delay(1);
484 	}
485 
486 	/* Check for timeout */
487 	if (i == IGC_HI_COMMAND_TIMEOUT) {
488 		DEBUGOUT("FW reset failed.\n");
489 		return -IGC_ERR_HOST_INTERFACE_COMMAND;
490 	}
491 
492 	/* Wait till MAC is ready to accept new FW code */
493 	for (i = 0; i < IGC_HI_COMMAND_TIMEOUT; i++) {
494 		fwsm = IGC_READ_REG(hw, IGC_FWSM);
495 		if ((fwsm & IGC_FWSM_FW_VALID) &&
496 		    ((fwsm & IGC_FWSM_MODE_MASK) >> IGC_FWSM_MODE_SHIFT ==
497 		    IGC_FWSM_HI_EN_ONLY_MODE))
498 			break;
499 		msec_delay(1);
500 	}
501 
502 	/* Check for timeout */
503 	if (i == IGC_HI_COMMAND_TIMEOUT) {
504 		DEBUGOUT("FW reset failed.\n");
505 		return -IGC_ERR_HOST_INTERFACE_COMMAND;
506 	}
507 
508 	/* Calculate length in DWORDs */
509 	length >>= 2;
510 
511 	/* The device driver writes the relevant FW code block
512 	 * into the ram area in DWORDs via 1kB ram addressing window.
513 	 */
514 	for (i = 0; i < length; i++) {
515 		if (!(i % IGC_HI_FW_BLOCK_DWORD_LENGTH)) {
516 			/* Point to correct 1kB ram window */
517 			hibba = IGC_HI_FW_BASE_ADDRESS +
518 				((IGC_HI_FW_BLOCK_DWORD_LENGTH << 2) *
519 				(i / IGC_HI_FW_BLOCK_DWORD_LENGTH));
520 
521 			IGC_WRITE_REG(hw, IGC_HIBBA, hibba);
522 		}
523 
524 		IGC_WRITE_REG_ARRAY_DWORD(hw, IGC_HOST_IF,
525 					    i % IGC_HI_FW_BLOCK_DWORD_LENGTH,
526 					    *((u32 *)buffer + i));
527 	}
528 
529 	/* Setting this bit tells the ARC that a new FW is ready to execute. */
530 	hicr = IGC_READ_REG(hw, IGC_HICR);
531 	IGC_WRITE_REG(hw, IGC_HICR, hicr | IGC_HICR_C);
532 
533 	for (i = 0; i < IGC_HI_COMMAND_TIMEOUT; i++) {
534 		hicr = IGC_READ_REG(hw, IGC_HICR);
535 		if (!(hicr & IGC_HICR_C))
536 			break;
537 		msec_delay(1);
538 	}
539 
540 	/* Check for successful FW start. */
541 	if (i == IGC_HI_COMMAND_TIMEOUT) {
542 		DEBUGOUT("New FW did not start within timeout period.\n");
543 		return -IGC_ERR_HOST_INTERFACE_COMMAND;
544 	}
545 
546 	return IGC_SUCCESS;
547 }
548