xref: /f-stack/dpdk/drivers/net/txgbe/base/txgbe_mng.c (revision 2d9fd380)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015-2020
3  */
4 
5 #include "txgbe_type.h"
6 #include "txgbe_mng.h"
7 
8 /**
9  *  txgbe_calculate_checksum - Calculate checksum for buffer
10  *  @buffer: pointer to EEPROM
11  *  @length: size of EEPROM to calculate a checksum for
12  *  Calculates the checksum for some buffer on a specified length.  The
13  *  checksum calculated is returned.
14  **/
15 static u8
txgbe_calculate_checksum(u8 * buffer,u32 length)16 txgbe_calculate_checksum(u8 *buffer, u32 length)
17 {
18 	u32 i;
19 	u8 sum = 0;
20 
21 	for (i = 0; i < length; i++)
22 		sum += buffer[i];
23 
24 	return (u8)(0 - sum);
25 }
26 
27 /**
28  *  txgbe_hic_unlocked - Issue command to manageability block unlocked
29  *  @hw: pointer to the HW structure
30  *  @buffer: command to write and where the return status will be placed
31  *  @length: length of buffer, must be multiple of 4 bytes
32  *  @timeout: time in ms to wait for command completion
33  *
34  *  Communicates with the manageability block. On success return 0
35  *  else returns semaphore error when encountering an error acquiring
36  *  semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
37  *
38  *  This function assumes that the TXGBE_MNGSEM_SWMBX semaphore is held
39  *  by the caller.
40  **/
41 static s32
txgbe_hic_unlocked(struct txgbe_hw * hw,u32 * buffer,u32 length,u32 timeout)42 txgbe_hic_unlocked(struct txgbe_hw *hw, u32 *buffer, u32 length, u32 timeout)
43 {
44 	u32 value, loop;
45 	u16 i, dword_len;
46 
47 	DEBUGFUNC("txgbe_hic_unlocked");
48 
49 	if (!length || length > TXGBE_PMMBX_BSIZE) {
50 		DEBUGOUT("Buffer length failure buffersize=%d.\n", length);
51 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
52 	}
53 
54 	/* Calculate length in DWORDs. We must be DWORD aligned */
55 	if (length % sizeof(u32)) {
56 		DEBUGOUT("Buffer length failure, not aligned to dword");
57 		return TXGBE_ERR_INVALID_ARGUMENT;
58 	}
59 
60 	dword_len = length >> 2;
61 
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.\n");
81 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
82 	}
83 
84 	return 0;
85 }
86 
87 /**
88  *  txgbe_host_interface_command - Issue command to manageability block
89  *  @hw: pointer to the HW structure
90  *  @buffer: contains the command to write and where the return status will
91  *   be placed
92  *  @length: length of buffer, must be multiple of 4 bytes
93  *  @timeout: time in ms to wait for command completion
94  *  @return_data: read and return data from the buffer (true) or not (false)
95  *   Needed because FW structures are big endian and decoding of
96  *   these fields can be 8 bit or 16 bit based on command. Decoding
97  *   is not easily understood without making a table of commands.
98  *   So we will leave this up to the caller to read back the data
99  *   in these cases.
100  *
101  *  Communicates with the manageability block. On success return 0
102  *  else returns semaphore error when encountering an error acquiring
103  *  semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
104  **/
105 static s32
txgbe_host_interface_command(struct txgbe_hw * hw,u32 * buffer,u32 length,u32 timeout,bool return_data)106 txgbe_host_interface_command(struct txgbe_hw *hw, u32 *buffer,
107 				 u32 length, u32 timeout, bool return_data)
108 {
109 	u32 hdr_size = sizeof(struct txgbe_hic_hdr);
110 	struct txgbe_hic_hdr *resp = (struct txgbe_hic_hdr *)buffer;
111 	u16 buf_len;
112 	s32 err;
113 	u32 bi;
114 	u32 dword_len;
115 
116 	DEBUGFUNC("txgbe_host_interface_command");
117 
118 	if (length == 0 || length > TXGBE_PMMBX_BSIZE) {
119 		DEBUGOUT("Buffer length failure buffersize=%d.\n", length);
120 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
121 	}
122 
123 	/* Take management host interface semaphore */
124 	err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWMBX);
125 	if (err)
126 		return err;
127 
128 	err = txgbe_hic_unlocked(hw, buffer, length, timeout);
129 	if (err)
130 		goto rel_out;
131 
132 	if (!return_data)
133 		goto rel_out;
134 
135 	/* Calculate length in DWORDs */
136 	dword_len = hdr_size >> 2;
137 
138 	/* first pull in the header so we know the buffer length */
139 	for (bi = 0; bi < dword_len; bi++)
140 		buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi);
141 
142 	/*
143 	 * If there is any thing in data position pull it in
144 	 * Read Flash command requires reading buffer length from
145 	 * two byes instead of one byte
146 	 */
147 	if (resp->cmd == 0x30) {
148 		for (; bi < dword_len + 2; bi++)
149 			buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi);
150 
151 		buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3)
152 				  & 0xF00) | resp->buf_len;
153 		hdr_size += (2 << 2);
154 	} else {
155 		buf_len = resp->buf_len;
156 	}
157 	if (!buf_len)
158 		goto rel_out;
159 
160 	if (length < buf_len + hdr_size) {
161 		DEBUGOUT("Buffer not large enough for reply message.\n");
162 		err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
163 		goto rel_out;
164 	}
165 
166 	/* Calculate length in DWORDs, add 3 for odd lengths */
167 	dword_len = (buf_len + 3) >> 2;
168 
169 	/* Pull in the rest of the buffer (bi is where we left off) */
170 	for (; bi <= dword_len; bi++)
171 		buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi);
172 
173 rel_out:
174 	hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWMBX);
175 
176 	return err;
177 }
178 
179 /**
180  *  txgbe_hic_sr_read - Read EEPROM word using a host interface cmd
181  *  assuming that the semaphore is already obtained.
182  *  @hw: pointer to hardware structure
183  *  @offset: offset of  word in the EEPROM to read
184  *  @data: word read from the EEPROM
185  *
186  *  Reads a 16 bit word from the EEPROM using the hostif.
187  **/
txgbe_hic_sr_read(struct txgbe_hw * hw,u32 addr,u8 * buf,int len)188 s32 txgbe_hic_sr_read(struct txgbe_hw *hw, u32 addr, u8 *buf, int len)
189 {
190 	struct txgbe_hic_read_shadow_ram command;
191 	u32 value;
192 	int err, i = 0, j = 0;
193 
194 	if (len > TXGBE_PMMBX_DATA_SIZE)
195 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
196 
197 	memset(&command, 0, sizeof(command));
198 	command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
199 	command.hdr.req.buf_lenh = 0;
200 	command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
201 	command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
202 	command.address = cpu_to_be32(addr);
203 	command.length = cpu_to_be16(len);
204 
205 	err = txgbe_hic_unlocked(hw, (u32 *)&command,
206 			sizeof(command), TXGBE_HI_COMMAND_TIMEOUT);
207 	if (err)
208 		return err;
209 
210 	while (i < (len >> 2)) {
211 		value = rd32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
212 		((u32 *)buf)[i] = value;
213 		i++;
214 	}
215 
216 	value = rd32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
217 	for (i <<= 2; i < len; i++)
218 		((u8 *)buf)[i] = ((u8 *)&value)[j++];
219 
220 	return 0;
221 }
222 
223 /**
224  *  txgbe_hic_sr_write - Write EEPROM word using hostif
225  *  @hw: pointer to hardware structure
226  *  @offset: offset of  word in the EEPROM to write
227  *  @data: word write to the EEPROM
228  *
229  *  Write a 16 bit word to the EEPROM using the hostif.
230  **/
txgbe_hic_sr_write(struct txgbe_hw * hw,u32 addr,u8 * buf,int len)231 s32 txgbe_hic_sr_write(struct txgbe_hw *hw, u32 addr, u8 *buf, int len)
232 {
233 	struct txgbe_hic_write_shadow_ram command;
234 	u32 value;
235 	int err = 0, i = 0, j = 0;
236 
237 	if (len > TXGBE_PMMBX_DATA_SIZE)
238 		return TXGBE_ERR_HOST_INTERFACE_COMMAND;
239 
240 	memset(&command, 0, sizeof(command));
241 	command.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
242 	command.hdr.req.buf_lenh = 0;
243 	command.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
244 	command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
245 	command.address = cpu_to_be32(addr);
246 	command.length = cpu_to_be16(len);
247 
248 	while (i < (len >> 2)) {
249 		value = ((u32 *)buf)[i];
250 		wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value);
251 		i++;
252 	}
253 
254 	for (i <<= 2; i < len; i++)
255 		((u8 *)&value)[j++] = ((u8 *)buf)[i];
256 
257 	wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value);
258 
259 	UNREFERENCED_PARAMETER(&command);
260 
261 	return err;
262 }
263 
264 /**
265  *  txgbe_hic_set_drv_ver - Sends driver version to firmware
266  *  @hw: pointer to the HW structure
267  *  @maj: driver version major number
268  *  @min: driver version minor number
269  *  @build: driver version build number
270  *  @sub: driver version sub build number
271  *  @len: unused
272  *  @driver_ver: unused
273  *
274  *  Sends driver version number to firmware through the manageability
275  *  block.  On success return 0
276  *  else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring
277  *  semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
278  **/
txgbe_hic_set_drv_ver(struct txgbe_hw * hw,u8 maj,u8 min,u8 build,u8 sub,u16 len,const char * driver_ver)279 s32 txgbe_hic_set_drv_ver(struct txgbe_hw *hw, u8 maj, u8 min,
280 				 u8 build, u8 sub, u16 len,
281 				 const char *driver_ver)
282 {
283 	struct txgbe_hic_drv_info fw_cmd;
284 	int i;
285 	s32 ret_val = 0;
286 
287 	DEBUGFUNC("txgbe_hic_set_drv_ver");
288 	UNREFERENCED_PARAMETER(len, driver_ver);
289 
290 	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
291 	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
292 	fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
293 	fw_cmd.port_num = (u8)hw->bus.func;
294 	fw_cmd.ver_maj = maj;
295 	fw_cmd.ver_min = min;
296 	fw_cmd.ver_build = build;
297 	fw_cmd.ver_sub = sub;
298 	fw_cmd.hdr.checksum = 0;
299 	fw_cmd.pad = 0;
300 	fw_cmd.pad2 = 0;
301 	fw_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&fw_cmd,
302 				(FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
303 
304 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
305 		ret_val = txgbe_host_interface_command(hw, (u32 *)&fw_cmd,
306 						       sizeof(fw_cmd),
307 						       TXGBE_HI_COMMAND_TIMEOUT,
308 						       true);
309 		if (ret_val != 0)
310 			continue;
311 
312 		if (fw_cmd.hdr.cmd_or_resp.ret_status ==
313 		    FW_CEM_RESP_STATUS_SUCCESS)
314 			ret_val = 0;
315 		else
316 			ret_val = TXGBE_ERR_HOST_INTERFACE_COMMAND;
317 
318 		break;
319 	}
320 
321 	return ret_val;
322 }
323 
324 /**
325  *  txgbe_hic_reset - send reset cmd to fw
326  *  @hw: pointer to hardware structure
327  *
328  *  Sends reset cmd to firmware through the manageability
329  *  block.  On success return 0
330  *  else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring
331  *  semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
332  **/
333 s32
txgbe_hic_reset(struct txgbe_hw * hw)334 txgbe_hic_reset(struct txgbe_hw *hw)
335 {
336 	struct txgbe_hic_reset reset_cmd;
337 	int i;
338 	s32 err = 0;
339 
340 	DEBUGFUNC("\n");
341 
342 	reset_cmd.hdr.cmd = FW_RESET_CMD;
343 	reset_cmd.hdr.buf_len = FW_RESET_LEN;
344 	reset_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
345 	reset_cmd.lan_id = hw->bus.lan_id;
346 	reset_cmd.reset_type = (u16)hw->reset_type;
347 	reset_cmd.hdr.checksum = 0;
348 	reset_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&reset_cmd,
349 				(FW_CEM_HDR_LEN + reset_cmd.hdr.buf_len));
350 
351 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
352 		err = txgbe_host_interface_command(hw, (u32 *)&reset_cmd,
353 						       sizeof(reset_cmd),
354 						       TXGBE_HI_COMMAND_TIMEOUT,
355 						       true);
356 		if (err != 0)
357 			continue;
358 
359 		if (reset_cmd.hdr.cmd_or_resp.ret_status ==
360 		    FW_CEM_RESP_STATUS_SUCCESS)
361 			err = 0;
362 		else
363 			err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
364 
365 		break;
366 	}
367 
368 	return err;
369 }
370 
371 /**
372  * txgbe_mng_present - returns true when management capability is present
373  * @hw: pointer to hardware structure
374  */
375 bool
txgbe_mng_present(struct txgbe_hw * hw)376 txgbe_mng_present(struct txgbe_hw *hw)
377 {
378 	if (hw->mac.type == txgbe_mac_unknown)
379 		return false;
380 
381 	return !!rd32m(hw, TXGBE_STAT, TXGBE_STAT_MNGINIT);
382 }
383 
384 /**
385  * txgbe_mng_enabled - Is the manageability engine enabled?
386  * @hw: pointer to hardware structure
387  *
388  * Returns true if the manageability engine is enabled.
389  **/
390 bool
txgbe_mng_enabled(struct txgbe_hw * hw)391 txgbe_mng_enabled(struct txgbe_hw *hw)
392 {
393 	UNREFERENCED_PARAMETER(hw);
394 	/* firmware does not control laser */
395 	return false;
396 }
397