xref: /dpdk/drivers/net/txgbe/base/txgbe_mng.c (revision e389504ed46d84c6a5a6a32b09d6750a182f8725)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5 
6 #include "txgbe_type.h"
7 #include "txgbe_mng.h"
8 
9 /**
10  *  txgbe_calculate_checksum - Calculate checksum for buffer
11  *  @buffer: pointer to EEPROM
12  *  @length: size of EEPROM to calculate a checksum for
13  *  Calculates the checksum for some buffer on a specified length.  The
14  *  checksum calculated is returned.
15  **/
16 static u8
17 txgbe_calculate_checksum(u8 *buffer, u32 length)
18 {
19 	u32 i;
20 	u8 sum = 0;
21 
22 	for (i = 0; i < length; i++)
23 		sum += buffer[i];
24 
25 	return (u8)(0 - sum);
26 }
27 
28 /**
29  *  txgbe_hic_unlocked - Issue command to manageability block unlocked
30  *  @hw: pointer to the HW structure
31  *  @buffer: command to write and where the return status will be placed
32  *  @length: length of buffer, must be multiple of 4 bytes
33  *  @timeout: time in ms to wait for command completion
34  *
35  *  Communicates with the manageability block. On success return 0
36  *  else returns semaphore error when encountering an error acquiring
37  *  semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
38  *
39  *  This function assumes that the TXGBE_MNGSEM_SWMBX semaphore is held
40  *  by the caller.
41  **/
42 static s32
43 txgbe_hic_unlocked(struct txgbe_hw *hw, u32 *buffer, u32 length, u32 timeout)
44 {
45 	u32 value, loop;
46 	u16 i, dword_len;
47 
48 	if (!length || length > TXGBE_PMMBX_BSIZE) {
49 		DEBUGOUT("Buffer length failure buffersize=%d.", length);
50 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
51 	}
52 
53 	/* Calculate length in DWORDs. We must be DWORD aligned */
54 	if (length % sizeof(u32)) {
55 		DEBUGOUT("Buffer length failure, not aligned to dword");
56 		return TXGBE_ERR_INVALID_ARGUMENT;
57 	}
58 
59 	dword_len = length >> 2;
60 
61 	txgbe_flush(hw);
62 	/* The device driver writes the relevant command block
63 	 * into the ram area.
64 	 */
65 	for (i = 0; i < dword_len; i++) {
66 		wr32a(hw, TXGBE_MNGMBX, i, cpu_to_le32(buffer[i]));
67 		buffer[i] = rd32a(hw, TXGBE_MNGMBX, i);
68 	}
69 	txgbe_flush(hw);
70 
71 	/* Setting this bit tells the ARC that a new command is pending. */
72 	wr32m(hw, TXGBE_MNGMBXCTL,
73 	      TXGBE_MNGMBXCTL_SWRDY, TXGBE_MNGMBXCTL_SWRDY);
74 
75 	/* Check command completion */
76 	loop = po32m(hw, TXGBE_MNGMBXCTL,
77 		TXGBE_MNGMBXCTL_FWRDY, TXGBE_MNGMBXCTL_FWRDY,
78 		&value, timeout, 1000);
79 	if (!loop || !(value & TXGBE_MNGMBXCTL_FWACK)) {
80 		DEBUGOUT("Command has failed with no status valid.");
81 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
82 	}
83 
84 	if ((rd32(hw, TXGBE_MNGMBX) & 0xff0000) >> 16 == 0x80) {
85 		DEBUGOUT("It's unknown command.");
86 		return TXGBE_ERR_MNG_ACCESS_FAILED;
87 	}
88 
89 	return 0;
90 }
91 
92 /**
93  *  txgbe_host_interface_command - Issue command to manageability block
94  *  @hw: pointer to the HW structure
95  *  @buffer: contains the command to write and where the return status will
96  *   be placed
97  *  @length: length of buffer, must be multiple of 4 bytes
98  *  @timeout: time in ms to wait for command completion
99  *  @return_data: read and return data from the buffer (true) or not (false)
100  *   Needed because FW structures are big endian and decoding of
101  *   these fields can be 8 bit or 16 bit based on command. Decoding
102  *   is not easily understood without making a table of commands.
103  *   So we will leave this up to the caller to read back the data
104  *   in these cases.
105  *
106  *  Communicates with the manageability block. On success return 0
107  *  else returns semaphore error when encountering an error acquiring
108  *  semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
109  **/
110 static s32
111 txgbe_host_interface_command(struct txgbe_hw *hw, u32 *buffer,
112 				 u32 length, u32 timeout, bool return_data)
113 {
114 	u32 hdr_size = sizeof(struct txgbe_hic_hdr);
115 	struct txgbe_hic_hdr *resp = (struct txgbe_hic_hdr *)buffer;
116 	u16 buf_len;
117 	s32 err;
118 	u32 bi;
119 	u32 dword_len;
120 
121 	if (length == 0 || length > TXGBE_PMMBX_BSIZE) {
122 		DEBUGOUT("Buffer length failure buffersize=%d.", length);
123 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
124 	}
125 
126 	/* Take management host interface semaphore */
127 	err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWMBX);
128 	if (err)
129 		return err;
130 
131 	err = txgbe_hic_unlocked(hw, buffer, length, timeout);
132 	if (err)
133 		goto rel_out;
134 
135 	if (!return_data)
136 		goto rel_out;
137 
138 	/* Calculate length in DWORDs */
139 	dword_len = hdr_size >> 2;
140 
141 	/* first pull in the header so we know the buffer length */
142 	for (bi = 0; bi < dword_len; bi++)
143 		buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi);
144 
145 	buf_len = resp->buf_len;
146 	if (!buf_len)
147 		goto rel_out;
148 
149 	if (length < buf_len + hdr_size) {
150 		DEBUGOUT("Buffer not large enough for reply message.");
151 		err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
152 		goto rel_out;
153 	}
154 
155 	/* Calculate length in DWORDs, add 3 for odd lengths */
156 	dword_len = (buf_len + 3) >> 2;
157 
158 	/* Pull in the rest of the buffer (bi is where we left off) */
159 	for (; bi <= dword_len; bi++)
160 		buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi);
161 
162 rel_out:
163 	hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWMBX);
164 
165 	return err;
166 }
167 
168 /**
169  *  txgbe_hic_sr_read - Read EEPROM word using a host interface cmd
170  *  assuming that the semaphore is already obtained.
171  *  @hw: pointer to hardware structure
172  *  @offset: offset of  word in the EEPROM to read
173  *  @data: word read from the EEPROM
174  *
175  *  Reads a 16 bit word from the EEPROM using the hostif.
176  **/
177 s32 txgbe_hic_sr_read(struct txgbe_hw *hw, u32 addr, u8 *buf, int len)
178 {
179 	struct txgbe_hic_read_shadow_ram command;
180 	u32 value;
181 	int err, i = 0, j = 0;
182 
183 	if (len > TXGBE_PMMBX_DATA_SIZE)
184 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
185 
186 	memset(&command, 0, sizeof(command));
187 	command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
188 	command.hdr.req.buf_lenh = 0;
189 	command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
190 	command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
191 	command.address = cpu_to_be32(addr);
192 	command.length = cpu_to_be16(len);
193 
194 	err = txgbe_hic_unlocked(hw, (u32 *)&command,
195 			sizeof(command), TXGBE_HI_COMMAND_TIMEOUT);
196 	if (err)
197 		return err;
198 
199 	while (i < (len >> 2)) {
200 		value = rd32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
201 		((u32 *)buf)[i] = value;
202 		i++;
203 	}
204 
205 	value = rd32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
206 	for (i <<= 2; i < len; i++)
207 		((u8 *)buf)[i] = ((u8 *)&value)[j++];
208 
209 	return 0;
210 }
211 
212 /**
213  *  txgbe_hic_sr_write - Write EEPROM word using hostif
214  *  @hw: pointer to hardware structure
215  *  @offset: offset of  word in the EEPROM to write
216  *  @data: word write to the EEPROM
217  *
218  *  Write a 16 bit word to the EEPROM using the hostif.
219  **/
220 s32 txgbe_hic_sr_write(struct txgbe_hw *hw, u32 addr, u8 *buf, int len)
221 {
222 	struct txgbe_hic_write_shadow_ram command;
223 	u32 value;
224 	int err = 0, i = 0, j = 0;
225 
226 	if (len > TXGBE_PMMBX_DATA_SIZE)
227 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
228 
229 	memset(&command, 0, sizeof(command));
230 	command.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
231 	command.hdr.req.buf_lenh = 0;
232 	command.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
233 	command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
234 	command.address = cpu_to_be32(addr);
235 	command.length = cpu_to_be16(len);
236 
237 	while (i < (len >> 2)) {
238 		value = ((u32 *)buf)[i];
239 		wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value);
240 		i++;
241 	}
242 
243 	for (i <<= 2; i < len; i++)
244 		((u8 *)&value)[j++] = ((u8 *)buf)[i];
245 
246 	wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value);
247 
248 	UNREFERENCED_PARAMETER(&command);
249 
250 	return err;
251 }
252 
253 s32 txgbe_close_notify(struct txgbe_hw *hw)
254 {
255 	u32 tmp;
256 	s32 status;
257 	struct txgbe_hic_write_shadow_ram buffer;
258 
259 	buffer.hdr.req.cmd = FW_DW_CLOSE_NOTIFY;
260 	buffer.hdr.req.buf_lenh = 0;
261 	buffer.hdr.req.buf_lenl = 0;
262 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
263 
264 	/* one word */
265 	buffer.length = 0;
266 	buffer.address = 0;
267 
268 	status = txgbe_host_interface_command(hw, (u32 *)&buffer,
269 					      sizeof(buffer),
270 					      TXGBE_HI_COMMAND_TIMEOUT, false);
271 	if (status)
272 		return status;
273 
274 	tmp = rd32a(hw, TXGBE_MNGMBX, 1);
275 	if (tmp == TXGBE_CHECKSUM_CAP_ST_PASS)
276 		status = 0;
277 	else
278 		status = TXGBE_ERR_EEPROM_CHECKSUM;
279 
280 	return status;
281 }
282 
283 s32 txgbe_open_notify(struct txgbe_hw *hw)
284 {
285 	u32 tmp;
286 	s32 status;
287 	struct txgbe_hic_write_shadow_ram buffer;
288 
289 	buffer.hdr.req.cmd = FW_DW_OPEN_NOTIFY;
290 	buffer.hdr.req.buf_lenh = 0;
291 	buffer.hdr.req.buf_lenl = 0;
292 	buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
293 
294 	/* one word */
295 	buffer.length = 0;
296 	buffer.address = 0;
297 
298 	status = txgbe_host_interface_command(hw, (u32 *)&buffer,
299 					      sizeof(buffer),
300 					      TXGBE_HI_COMMAND_TIMEOUT, false);
301 	if (status)
302 		return status;
303 
304 	tmp = rd32a(hw, TXGBE_MNGMBX, 1);
305 	if (tmp == TXGBE_CHECKSUM_CAP_ST_PASS)
306 		status = 0;
307 	else
308 		status = TXGBE_ERR_EEPROM_CHECKSUM;
309 
310 	return status;
311 }
312 
313 /**
314  *  txgbe_hic_set_drv_ver - Sends driver version to firmware
315  *  @hw: pointer to the HW structure
316  *  @maj: driver version major number
317  *  @min: driver version minor number
318  *  @build: driver version build number
319  *  @sub: driver version sub build number
320  *  @len: unused
321  *  @driver_ver: unused
322  *
323  *  Sends driver version number to firmware through the manageability
324  *  block.  On success return 0
325  *  else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring
326  *  semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
327  **/
328 s32 txgbe_hic_set_drv_ver(struct txgbe_hw *hw, u8 maj, u8 min,
329 				 u8 build, u8 sub, u16 len,
330 				 const char *driver_ver)
331 {
332 	struct txgbe_hic_drv_info fw_cmd;
333 	int i;
334 	s32 ret_val = 0;
335 
336 	UNREFERENCED_PARAMETER(len, driver_ver);
337 
338 	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
339 	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
340 	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
341 	fw_cmd.port_num = (u8)hw->bus.func;
342 	fw_cmd.ver_maj = maj;
343 	fw_cmd.ver_min = min;
344 	fw_cmd.ver_build = build;
345 	fw_cmd.ver_sub = sub;
346 	fw_cmd.hdr.checksum = 0;
347 	fw_cmd.pad = 0;
348 	fw_cmd.pad2 = 0;
349 	fw_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&fw_cmd,
350 				(FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
351 
352 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
353 		ret_val = txgbe_host_interface_command(hw, (u32 *)&fw_cmd,
354 						       sizeof(fw_cmd),
355 						       TXGBE_HI_COMMAND_TIMEOUT,
356 						       true);
357 		if (ret_val != 0)
358 			continue;
359 
360 		if (fw_cmd.hdr.cmd_or_resp.ret_status ==
361 		    FW_CEM_RESP_STATUS_SUCCESS)
362 			ret_val = 0;
363 		else
364 			ret_val = TXGBE_ERR_HOST_INTERFACE_COMMAND;
365 
366 		break;
367 	}
368 
369 	return ret_val;
370 }
371 
372 /**
373  *  txgbe_hic_reset - send reset cmd to fw
374  *  @hw: pointer to hardware structure
375  *
376  *  Sends reset cmd to firmware through the manageability
377  *  block.  On success return 0
378  *  else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring
379  *  semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
380  **/
381 s32
382 txgbe_hic_reset(struct txgbe_hw *hw)
383 {
384 	struct txgbe_hic_reset reset_cmd;
385 	int i;
386 	s32 err = 0;
387 
388 	reset_cmd.hdr.cmd = FW_RESET_CMD;
389 	reset_cmd.hdr.buf_len = FW_RESET_LEN;
390 	reset_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
391 	reset_cmd.lan_id = hw->bus.lan_id;
392 	reset_cmd.reset_type = (u16)hw->reset_type;
393 	reset_cmd.hdr.checksum = 0;
394 	reset_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&reset_cmd,
395 				(FW_CEM_HDR_LEN + reset_cmd.hdr.buf_len));
396 
397 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
398 		err = txgbe_host_interface_command(hw, (u32 *)&reset_cmd,
399 						       sizeof(reset_cmd),
400 						       TXGBE_HI_COMMAND_TIMEOUT,
401 						       true);
402 		if (err != 0)
403 			continue;
404 
405 		if (reset_cmd.hdr.cmd_or_resp.ret_status ==
406 		    FW_CEM_RESP_STATUS_SUCCESS)
407 			err = 0;
408 		else
409 			err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
410 
411 		break;
412 	}
413 
414 	return err;
415 }
416 
417 /**
418  * txgbe_mng_present - returns true when management capability is present
419  * @hw: pointer to hardware structure
420  */
421 bool
422 txgbe_mng_present(struct txgbe_hw *hw)
423 {
424 	if (hw->mac.type == txgbe_mac_unknown)
425 		return false;
426 
427 	return !!rd32m(hw, TXGBE_STAT, TXGBE_STAT_MNGINIT);
428 }
429 
430 /**
431  * txgbe_mng_enabled - Is the manageability engine enabled?
432  * @hw: pointer to hardware structure
433  *
434  * Returns true if the manageability engine is enabled.
435  **/
436 bool
437 txgbe_mng_enabled(struct txgbe_hw *hw)
438 {
439 	UNREFERENCED_PARAMETER(hw);
440 	/* firmware does not control laser */
441 	return false;
442 }
443 
444 s32 txgbe_hic_get_lldp(struct txgbe_hw *hw)
445 {
446 	struct txgbe_hic_write_lldp buffer;
447 	s32 err = 0;
448 
449 	buffer.hdr.cmd = FW_LLDP_GET_CMD;
450 	buffer.hdr.buf_len = 0x1;
451 	buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
452 	buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
453 	buffer.func = hw->bus.lan_id;
454 
455 	err = txgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
456 					   TXGBE_HI_COMMAND_TIMEOUT, true);
457 	if (err)
458 		return err;
459 
460 	if (buffer.hdr.cmd_or_resp.ret_status == FW_CEM_RESP_STATUS_SUCCESS) {
461 		/* this field returns the status of LLDP */
462 		if (buffer.func)
463 			hw->lldp_enabled = true;
464 		else
465 			hw->lldp_enabled = false;
466 	} else {
467 		err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
468 	}
469 
470 	return err;
471 }
472 
473 s32 txgbe_hic_set_lldp(struct txgbe_hw *hw, bool on)
474 {
475 	struct txgbe_hic_write_lldp buffer;
476 
477 	if (on)
478 		buffer.hdr.cmd = FW_LLDP_SET_CMD_ON;
479 	else
480 		buffer.hdr.cmd = FW_LLDP_SET_CMD_OFF;
481 	buffer.hdr.buf_len = 0x1;
482 	buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
483 	buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
484 	buffer.func = hw->bus.lan_id;
485 
486 	return txgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
487 					    TXGBE_HI_COMMAND_TIMEOUT, false);
488 }
489