xref: /dpdk/drivers/net/ngbe/base/ngbe_mng.c (revision 91e64c0e5d7ee7eaf39df9510bfc60bbcae14ca9)
1f501a195SJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause
2f501a195SJiawen Wu  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3f501a195SJiawen Wu  * Copyright(c) 2010-2017 Intel Corporation
4f501a195SJiawen Wu  */
5f501a195SJiawen Wu 
6f501a195SJiawen Wu #include "ngbe_type.h"
7f501a195SJiawen Wu #include "ngbe_mng.h"
8f501a195SJiawen Wu 
9f501a195SJiawen Wu /**
10f501a195SJiawen Wu  *  ngbe_hic_unlocked - Issue command to manageability block unlocked
11f501a195SJiawen Wu  *  @hw: pointer to the HW structure
12f501a195SJiawen Wu  *  @buffer: command to write and where the return status will be placed
13f501a195SJiawen Wu  *  @length: length of buffer, must be multiple of 4 bytes
14f501a195SJiawen Wu  *  @timeout: time in ms to wait for command completion
15f501a195SJiawen Wu  *
16f501a195SJiawen Wu  *  Communicates with the manageability block. On success return 0
17f501a195SJiawen Wu  *  else returns semaphore error when encountering an error acquiring
18f501a195SJiawen Wu  *  semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
19f501a195SJiawen Wu  *
20f501a195SJiawen Wu  *  This function assumes that the NGBE_MNGSEM_SWMBX semaphore is held
21f501a195SJiawen Wu  *  by the caller.
22f501a195SJiawen Wu  **/
23f501a195SJiawen Wu static s32
24f501a195SJiawen Wu ngbe_hic_unlocked(struct ngbe_hw *hw, u32 *buffer, u32 length, u32 timeout)
25f501a195SJiawen Wu {
26f501a195SJiawen Wu 	u32 value, loop;
27f501a195SJiawen Wu 	u16 i, dword_len;
28f501a195SJiawen Wu 
29f501a195SJiawen Wu 	if (!length || length > NGBE_PMMBX_BSIZE) {
30c811e6a4SJiawen Wu 		DEBUGOUT("Buffer length failure buffersize=%d.", length);
31f501a195SJiawen Wu 		return NGBE_ERR_HOST_INTERFACE_COMMAND;
32f501a195SJiawen Wu 	}
33f501a195SJiawen Wu 
34f501a195SJiawen Wu 	/* Calculate length in DWORDs. We must be DWORD aligned */
35f501a195SJiawen Wu 	if (length % sizeof(u32)) {
36f501a195SJiawen Wu 		DEBUGOUT("Buffer length failure, not aligned to dword");
37f501a195SJiawen Wu 		return NGBE_ERR_INVALID_ARGUMENT;
38f501a195SJiawen Wu 	}
39f501a195SJiawen Wu 
40f501a195SJiawen Wu 	dword_len = length >> 2;
41f501a195SJiawen Wu 
42f501a195SJiawen Wu 	/* The device driver writes the relevant command block
43f501a195SJiawen Wu 	 * into the ram area.
44f501a195SJiawen Wu 	 */
45f501a195SJiawen Wu 	for (i = 0; i < dword_len; i++) {
46f501a195SJiawen Wu 		wr32a(hw, NGBE_MNGMBX, i, cpu_to_le32(buffer[i]));
47f501a195SJiawen Wu 		buffer[i] = rd32a(hw, NGBE_MNGMBX, i);
48f501a195SJiawen Wu 	}
49f501a195SJiawen Wu 	ngbe_flush(hw);
50f501a195SJiawen Wu 
51f501a195SJiawen Wu 	/* Setting this bit tells the ARC that a new command is pending. */
52f501a195SJiawen Wu 	wr32m(hw, NGBE_MNGMBXCTL,
53f501a195SJiawen Wu 	      NGBE_MNGMBXCTL_SWRDY, NGBE_MNGMBXCTL_SWRDY);
54f501a195SJiawen Wu 
55f501a195SJiawen Wu 	/* Check command completion */
56f501a195SJiawen Wu 	loop = po32m(hw, NGBE_MNGMBXCTL,
57f501a195SJiawen Wu 		NGBE_MNGMBXCTL_FWRDY, NGBE_MNGMBXCTL_FWRDY,
58f501a195SJiawen Wu 		&value, timeout, 1000);
59f501a195SJiawen Wu 	if (!loop || !(value & NGBE_MNGMBXCTL_FWACK)) {
60c811e6a4SJiawen Wu 		DEBUGOUT("Command has failed with no status valid.");
61f501a195SJiawen Wu 		return NGBE_ERR_HOST_INTERFACE_COMMAND;
62f501a195SJiawen Wu 	}
63f501a195SJiawen Wu 
64f501a195SJiawen Wu 	return 0;
65f501a195SJiawen Wu }
66f501a195SJiawen Wu 
67f501a195SJiawen Wu /**
68f501a195SJiawen Wu  *  ngbe_host_interface_command - Issue command to manageability block
69f501a195SJiawen Wu  *  @hw: pointer to the HW structure
70f501a195SJiawen Wu  *  @buffer: contains the command to write and where the return status will
71f501a195SJiawen Wu  *   be placed
72f501a195SJiawen Wu  *  @length: length of buffer, must be multiple of 4 bytes
73f501a195SJiawen Wu  *  @timeout: time in ms to wait for command completion
74f501a195SJiawen Wu  *  @return_data: read and return data from the buffer (true) or not (false)
75f501a195SJiawen Wu  *   Needed because FW structures are big endian and decoding of
76f501a195SJiawen Wu  *   these fields can be 8 bit or 16 bit based on command. Decoding
77f501a195SJiawen Wu  *   is not easily understood without making a table of commands.
78f501a195SJiawen Wu  *   So we will leave this up to the caller to read back the data
79f501a195SJiawen Wu  *   in these cases.
80f501a195SJiawen Wu  *
81f501a195SJiawen Wu  *  Communicates with the manageability block. On success return 0
82f501a195SJiawen Wu  *  else returns semaphore error when encountering an error acquiring
83f501a195SJiawen Wu  *  semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
84f501a195SJiawen Wu  **/
85f501a195SJiawen Wu static s32
86f501a195SJiawen Wu ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer,
87f501a195SJiawen Wu 				 u32 length, u32 timeout, bool return_data)
88f501a195SJiawen Wu {
89f501a195SJiawen Wu 	u32 hdr_size = sizeof(struct ngbe_hic_hdr);
90f501a195SJiawen Wu 	struct ngbe_hic_hdr *resp = (struct ngbe_hic_hdr *)buffer;
91f501a195SJiawen Wu 	u16 buf_len;
92f501a195SJiawen Wu 	s32 err;
93f501a195SJiawen Wu 	u32 bi;
94f501a195SJiawen Wu 	u32 dword_len;
95f501a195SJiawen Wu 
96f501a195SJiawen Wu 	if (length == 0 || length > NGBE_PMMBX_BSIZE) {
97c811e6a4SJiawen Wu 		DEBUGOUT("Buffer length failure buffersize=%d.", length);
98f501a195SJiawen Wu 		return NGBE_ERR_HOST_INTERFACE_COMMAND;
99f501a195SJiawen Wu 	}
100f501a195SJiawen Wu 
101f501a195SJiawen Wu 	/* Take management host interface semaphore */
102f501a195SJiawen Wu 	err = hw->mac.acquire_swfw_sync(hw, NGBE_MNGSEM_SWMBX);
103f501a195SJiawen Wu 	if (err)
104f501a195SJiawen Wu 		return err;
105f501a195SJiawen Wu 
106f501a195SJiawen Wu 	err = ngbe_hic_unlocked(hw, buffer, length, timeout);
107f501a195SJiawen Wu 	if (err)
108f501a195SJiawen Wu 		goto rel_out;
109f501a195SJiawen Wu 
110f501a195SJiawen Wu 	if (!return_data)
111f501a195SJiawen Wu 		goto rel_out;
112f501a195SJiawen Wu 
113f501a195SJiawen Wu 	/* Calculate length in DWORDs */
114f501a195SJiawen Wu 	dword_len = hdr_size >> 2;
115f501a195SJiawen Wu 
116f501a195SJiawen Wu 	/* first pull in the header so we know the buffer length */
117f501a195SJiawen Wu 	for (bi = 0; bi < dword_len; bi++)
118f501a195SJiawen Wu 		buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);
119f501a195SJiawen Wu 
120f501a195SJiawen Wu 	buf_len = resp->buf_len;
121f501a195SJiawen Wu 	if (!buf_len)
122f501a195SJiawen Wu 		goto rel_out;
123f501a195SJiawen Wu 
124f501a195SJiawen Wu 	if (length < buf_len + hdr_size) {
125c811e6a4SJiawen Wu 		DEBUGOUT("Buffer not large enough for reply message.");
126f501a195SJiawen Wu 		err = NGBE_ERR_HOST_INTERFACE_COMMAND;
127f501a195SJiawen Wu 		goto rel_out;
128f501a195SJiawen Wu 	}
129f501a195SJiawen Wu 
130f501a195SJiawen Wu 	/* Calculate length in DWORDs, add 3 for odd lengths */
131f501a195SJiawen Wu 	dword_len = (buf_len + 3) >> 2;
132f501a195SJiawen Wu 
133f501a195SJiawen Wu 	/* Pull in the rest of the buffer (bi is where we left off) */
134f501a195SJiawen Wu 	for (; bi <= dword_len; bi++)
135f501a195SJiawen Wu 		buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);
136f501a195SJiawen Wu 
137f501a195SJiawen Wu rel_out:
138f501a195SJiawen Wu 	hw->mac.release_swfw_sync(hw, NGBE_MNGSEM_SWMBX);
139f501a195SJiawen Wu 
140f501a195SJiawen Wu 	return err;
141f501a195SJiawen Wu }
142f501a195SJiawen Wu 
143506abd4aSJiawen Wu /**
144506abd4aSJiawen Wu  *  ngbe_hic_sr_read - Read EEPROM word using a host interface cmd
145506abd4aSJiawen Wu  *  assuming that the semaphore is already obtained.
146506abd4aSJiawen Wu  *  @hw: pointer to hardware structure
147506abd4aSJiawen Wu  *  @offset: offset of  word in the EEPROM to read
148506abd4aSJiawen Wu  *  @data: word read from the EEPROM
149506abd4aSJiawen Wu  *
150506abd4aSJiawen Wu  *  Reads a 16 bit word from the EEPROM using the hostif.
151506abd4aSJiawen Wu  **/
152506abd4aSJiawen Wu s32 ngbe_hic_sr_read(struct ngbe_hw *hw, u32 addr, u8 *buf, int len)
153506abd4aSJiawen Wu {
154506abd4aSJiawen Wu 	struct ngbe_hic_read_shadow_ram command;
155506abd4aSJiawen Wu 	u32 value;
156506abd4aSJiawen Wu 	int err, i = 0, j = 0;
157506abd4aSJiawen Wu 
158506abd4aSJiawen Wu 	if (len > NGBE_PMMBX_DATA_SIZE)
159506abd4aSJiawen Wu 		return NGBE_ERR_HOST_INTERFACE_COMMAND;
160506abd4aSJiawen Wu 
161506abd4aSJiawen Wu 	memset(&command, 0, sizeof(command));
162506abd4aSJiawen Wu 	command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
163506abd4aSJiawen Wu 	command.hdr.req.buf_lenh = 0;
164506abd4aSJiawen Wu 	command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
165506abd4aSJiawen Wu 	command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
166506abd4aSJiawen Wu 	command.address = cpu_to_be32(addr);
167506abd4aSJiawen Wu 	command.length = cpu_to_be16(len);
168506abd4aSJiawen Wu 
169506abd4aSJiawen Wu 	err = ngbe_hic_unlocked(hw, (u32 *)&command,
170506abd4aSJiawen Wu 			sizeof(command), NGBE_HI_COMMAND_TIMEOUT);
171506abd4aSJiawen Wu 	if (err)
172506abd4aSJiawen Wu 		return err;
173506abd4aSJiawen Wu 
174506abd4aSJiawen Wu 	while (i < (len >> 2)) {
175506abd4aSJiawen Wu 		value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
176506abd4aSJiawen Wu 		((u32 *)buf)[i] = value;
177506abd4aSJiawen Wu 		i++;
178506abd4aSJiawen Wu 	}
179506abd4aSJiawen Wu 
180506abd4aSJiawen Wu 	value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
181506abd4aSJiawen Wu 	for (i <<= 2; i < len; i++)
182506abd4aSJiawen Wu 		((u8 *)buf)[i] = ((u8 *)&value)[j++];
183506abd4aSJiawen Wu 
184506abd4aSJiawen Wu 	return 0;
185506abd4aSJiawen Wu }
186506abd4aSJiawen Wu 
1879459ea29SJiawen Wu /**
1889459ea29SJiawen Wu  *  ngbe_hic_sr_write - Write EEPROM word using hostif
1899459ea29SJiawen Wu  *  @hw: pointer to hardware structure
1909459ea29SJiawen Wu  *  @offset: offset of  word in the EEPROM to write
1919459ea29SJiawen Wu  *  @data: word write to the EEPROM
1929459ea29SJiawen Wu  *
1939459ea29SJiawen Wu  *  Write a 16 bit word to the EEPROM using the hostif.
1949459ea29SJiawen Wu  **/
1959459ea29SJiawen Wu s32 ngbe_hic_sr_write(struct ngbe_hw *hw, u32 addr, u8 *buf, int len)
1969459ea29SJiawen Wu {
1979459ea29SJiawen Wu 	struct ngbe_hic_write_shadow_ram command;
1989459ea29SJiawen Wu 	u32 value;
1999459ea29SJiawen Wu 	int err = 0, i = 0, j = 0;
2009459ea29SJiawen Wu 
2019459ea29SJiawen Wu 	if (len > NGBE_PMMBX_DATA_SIZE)
2029459ea29SJiawen Wu 		return NGBE_ERR_HOST_INTERFACE_COMMAND;
2039459ea29SJiawen Wu 
2049459ea29SJiawen Wu 	memset(&command, 0, sizeof(command));
2059459ea29SJiawen Wu 	command.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
2069459ea29SJiawen Wu 	command.hdr.req.buf_lenh = 0;
2079459ea29SJiawen Wu 	command.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
2089459ea29SJiawen Wu 	command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
2099459ea29SJiawen Wu 	command.address = cpu_to_be32(addr);
2109459ea29SJiawen Wu 	command.length = cpu_to_be16(len);
2119459ea29SJiawen Wu 
2129459ea29SJiawen Wu 	while (i < (len >> 2)) {
2139459ea29SJiawen Wu 		value = ((u32 *)buf)[i];
2149459ea29SJiawen Wu 		wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value);
2159459ea29SJiawen Wu 		i++;
2169459ea29SJiawen Wu 	}
2179459ea29SJiawen Wu 
2189459ea29SJiawen Wu 	for (i <<= 2; i < len; i++)
2199459ea29SJiawen Wu 		((u8 *)&value)[j++] = ((u8 *)buf)[i];
2209459ea29SJiawen Wu 
2219459ea29SJiawen Wu 	wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value);
2229459ea29SJiawen Wu 
2239459ea29SJiawen Wu 	UNREFERENCED_PARAMETER(&command);
2249459ea29SJiawen Wu 
2259459ea29SJiawen Wu 	return err;
2269459ea29SJiawen Wu }
2279459ea29SJiawen Wu 
228ac6c5e9aSJiawen Wu s32 ngbe_hic_pcie_read(struct ngbe_hw *hw, u16 addr, u32 *buf, int len)
229ac6c5e9aSJiawen Wu {
230ac6c5e9aSJiawen Wu 	struct ngbe_hic_read_pcie command;
231ac6c5e9aSJiawen Wu 	u32 value = 0;
232ac6c5e9aSJiawen Wu 	int err, i = 0;
233ac6c5e9aSJiawen Wu 
234ac6c5e9aSJiawen Wu 	if (len > NGBE_PMMBX_DATA_SIZE)
235ac6c5e9aSJiawen Wu 		return NGBE_ERR_HOST_INTERFACE_COMMAND;
236ac6c5e9aSJiawen Wu 
237ac6c5e9aSJiawen Wu 	memset(&command, 0, sizeof(command));
238ac6c5e9aSJiawen Wu 	command.hdr.cmd = FW_PCIE_READ_CMD;
239ac6c5e9aSJiawen Wu 	command.hdr.buf_len = sizeof(command) - sizeof(command.hdr);
240ac6c5e9aSJiawen Wu 	command.hdr.checksum = FW_DEFAULT_CHECKSUM;
241ac6c5e9aSJiawen Wu 	command.lan_id = hw->bus.lan_id;
242ac6c5e9aSJiawen Wu 	command.addr = addr;
243ac6c5e9aSJiawen Wu 
244ac6c5e9aSJiawen Wu 	err = ngbe_host_interface_command(hw, (u32 *)&command,
245ac6c5e9aSJiawen Wu 			sizeof(command), NGBE_HI_COMMAND_TIMEOUT, false);
246ac6c5e9aSJiawen Wu 	if (err)
247ac6c5e9aSJiawen Wu 		return err;
248ac6c5e9aSJiawen Wu 
249ac6c5e9aSJiawen Wu 	while (i < (len >> 2)) {
250ac6c5e9aSJiawen Wu 		value = rd32a(hw, NGBE_MNGMBX, FW_PCIE_BUSMASTER_OFFSET + i);
251ac6c5e9aSJiawen Wu 		((u32 *)buf)[i] = value;
252ac6c5e9aSJiawen Wu 		i++;
253ac6c5e9aSJiawen Wu 	}
254ac6c5e9aSJiawen Wu 
255ac6c5e9aSJiawen Wu 	return 0;
256ac6c5e9aSJiawen Wu }
257ac6c5e9aSJiawen Wu 
258ac6c5e9aSJiawen Wu s32 ngbe_hic_pcie_write(struct ngbe_hw *hw, u16 addr, u32 *buf, int len)
259ac6c5e9aSJiawen Wu {
260ac6c5e9aSJiawen Wu 	struct ngbe_hic_write_pcie command;
261ac6c5e9aSJiawen Wu 	u32 value = 0;
262ac6c5e9aSJiawen Wu 	int err, i = 0;
263ac6c5e9aSJiawen Wu 
264ac6c5e9aSJiawen Wu 	while (i < (len >> 2)) {
265ac6c5e9aSJiawen Wu 		value = ((u32 *)buf)[i];
266ac6c5e9aSJiawen Wu 		i++;
267ac6c5e9aSJiawen Wu 	}
268ac6c5e9aSJiawen Wu 
269ac6c5e9aSJiawen Wu 	memset(&command, 0, sizeof(command));
270ac6c5e9aSJiawen Wu 	command.hdr.cmd = FW_PCIE_WRITE_CMD;
271ac6c5e9aSJiawen Wu 	command.hdr.buf_len = sizeof(command) - sizeof(command.hdr);
272ac6c5e9aSJiawen Wu 	command.hdr.checksum = FW_DEFAULT_CHECKSUM;
273ac6c5e9aSJiawen Wu 	command.lan_id = hw->bus.lan_id;
274ac6c5e9aSJiawen Wu 	command.addr = addr;
275ac6c5e9aSJiawen Wu 	command.data = value;
276ac6c5e9aSJiawen Wu 
277ac6c5e9aSJiawen Wu 	err = ngbe_host_interface_command(hw, (u32 *)&command,
278ac6c5e9aSJiawen Wu 			sizeof(command), NGBE_HI_COMMAND_TIMEOUT, false);
279ac6c5e9aSJiawen Wu 	if (err)
280ac6c5e9aSJiawen Wu 		return err;
281ac6c5e9aSJiawen Wu 
282ac6c5e9aSJiawen Wu 	return 0;
283ac6c5e9aSJiawen Wu }
284ac6c5e9aSJiawen Wu 
285f501a195SJiawen Wu s32 ngbe_hic_check_cap(struct ngbe_hw *hw)
286f501a195SJiawen Wu {
287f501a195SJiawen Wu 	struct ngbe_hic_read_shadow_ram command;
288f501a195SJiawen Wu 	s32 err;
289f501a195SJiawen Wu 	int i;
290f501a195SJiawen Wu 
291f501a195SJiawen Wu 	command.hdr.req.cmd = FW_EEPROM_CHECK_STATUS;
292f501a195SJiawen Wu 	command.hdr.req.buf_lenh = 0;
293f501a195SJiawen Wu 	command.hdr.req.buf_lenl = 0;
294f501a195SJiawen Wu 	command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
295f501a195SJiawen Wu 
296f501a195SJiawen Wu 	/* convert offset from words to bytes */
297f501a195SJiawen Wu 	command.address = 0;
298f501a195SJiawen Wu 	/* one word */
299f501a195SJiawen Wu 	command.length = 0;
300f501a195SJiawen Wu 
301f501a195SJiawen Wu 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
302f501a195SJiawen Wu 		err = ngbe_host_interface_command(hw, (u32 *)&command,
303f501a195SJiawen Wu 				sizeof(command),
304f501a195SJiawen Wu 				NGBE_HI_COMMAND_TIMEOUT, true);
305f501a195SJiawen Wu 		if (err)
306f501a195SJiawen Wu 			continue;
307f501a195SJiawen Wu 
308f501a195SJiawen Wu 		command.hdr.rsp.ret_status &= 0x1F;
309f501a195SJiawen Wu 		if (command.hdr.rsp.ret_status !=
310f501a195SJiawen Wu 			FW_CEM_RESP_STATUS_SUCCESS)
311f501a195SJiawen Wu 			err = NGBE_ERR_HOST_INTERFACE_COMMAND;
312f501a195SJiawen Wu 
313f501a195SJiawen Wu 		break;
314f501a195SJiawen Wu 	}
315f501a195SJiawen Wu 
316f501a195SJiawen Wu 	if (!err && command.address != FW_CHECKSUM_CAP_ST_PASS)
317f501a195SJiawen Wu 		err = NGBE_ERR_EEPROM_CHECKSUM;
318f501a195SJiawen Wu 
319f501a195SJiawen Wu 	return err;
320f501a195SJiawen Wu }
321fbd5ceb0SJiawen Wu 
322fbd5ceb0SJiawen Wu s32 ngbe_phy_led_oem_chk(struct ngbe_hw *hw, u32 *data)
323fbd5ceb0SJiawen Wu {
324fbd5ceb0SJiawen Wu 	struct ngbe_hic_read_shadow_ram command;
325fbd5ceb0SJiawen Wu 	s32 err;
326fbd5ceb0SJiawen Wu 	int i;
327fbd5ceb0SJiawen Wu 
328fbd5ceb0SJiawen Wu 	command.hdr.req.cmd = FW_PHY_LED_CONF;
329fbd5ceb0SJiawen Wu 	command.hdr.req.buf_lenh = 0;
330fbd5ceb0SJiawen Wu 	command.hdr.req.buf_lenl = 0;
331fbd5ceb0SJiawen Wu 	command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
332fbd5ceb0SJiawen Wu 
333fbd5ceb0SJiawen Wu 	/* convert offset from words to bytes */
334fbd5ceb0SJiawen Wu 	command.address = 0;
335fbd5ceb0SJiawen Wu 	/* one word */
336fbd5ceb0SJiawen Wu 	command.length = 0;
337fbd5ceb0SJiawen Wu 
338fbd5ceb0SJiawen Wu 	for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
339fbd5ceb0SJiawen Wu 		err = ngbe_host_interface_command(hw, (u32 *)&command,
340fbd5ceb0SJiawen Wu 				sizeof(command),
341fbd5ceb0SJiawen Wu 				NGBE_HI_COMMAND_TIMEOUT, true);
342fbd5ceb0SJiawen Wu 		if (err)
343fbd5ceb0SJiawen Wu 			continue;
344fbd5ceb0SJiawen Wu 
345fbd5ceb0SJiawen Wu 		command.hdr.rsp.ret_status &= 0x1F;
346fbd5ceb0SJiawen Wu 		if (command.hdr.rsp.ret_status !=
347fbd5ceb0SJiawen Wu 			FW_CEM_RESP_STATUS_SUCCESS)
348fbd5ceb0SJiawen Wu 			err = NGBE_ERR_HOST_INTERFACE_COMMAND;
349fbd5ceb0SJiawen Wu 
350fbd5ceb0SJiawen Wu 		break;
351fbd5ceb0SJiawen Wu 	}
352fbd5ceb0SJiawen Wu 
353fbd5ceb0SJiawen Wu 	if (err)
354fbd5ceb0SJiawen Wu 		return err;
355fbd5ceb0SJiawen Wu 
356fbd5ceb0SJiawen Wu 	if (command.address == FW_CHECKSUM_CAP_ST_PASS) {
357fbd5ceb0SJiawen Wu 		*data = ((u32 *)&command)[2];
358fbd5ceb0SJiawen Wu 		err = 0;
359fbd5ceb0SJiawen Wu 	} else if (command.address == FW_CHECKSUM_CAP_ST_FAIL) {
360fbd5ceb0SJiawen Wu 		*data = FW_CHECKSUM_CAP_ST_FAIL;
361fbd5ceb0SJiawen Wu 		err = -1;
362fbd5ceb0SJiawen Wu 	} else {
363fbd5ceb0SJiawen Wu 		err = NGBE_ERR_EEPROM_CHECKSUM;
364fbd5ceb0SJiawen Wu 	}
365fbd5ceb0SJiawen Wu 
366fbd5ceb0SJiawen Wu 	return err;
367fbd5ceb0SJiawen Wu }
368*91e64c0eSJiawen Wu 
369*91e64c0eSJiawen Wu s32 ngbe_hic_get_lldp(struct ngbe_hw *hw)
370*91e64c0eSJiawen Wu {
371*91e64c0eSJiawen Wu 	struct ngbe_hic_write_lldp buffer;
372*91e64c0eSJiawen Wu 	s32 err = 0;
373*91e64c0eSJiawen Wu 
374*91e64c0eSJiawen Wu 	buffer.hdr.cmd = FW_LLDP_GET_CMD;
375*91e64c0eSJiawen Wu 	buffer.hdr.buf_len = 0x1;
376*91e64c0eSJiawen Wu 	buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
377*91e64c0eSJiawen Wu 	buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
378*91e64c0eSJiawen Wu 	buffer.func = hw->bus.lan_id;
379*91e64c0eSJiawen Wu 
380*91e64c0eSJiawen Wu 	err = ngbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
381*91e64c0eSJiawen Wu 					  NGBE_HI_COMMAND_TIMEOUT, true);
382*91e64c0eSJiawen Wu 	if (err)
383*91e64c0eSJiawen Wu 		return err;
384*91e64c0eSJiawen Wu 
385*91e64c0eSJiawen Wu 	if (buffer.hdr.cmd_or_resp.ret_status == FW_CEM_RESP_STATUS_SUCCESS) {
386*91e64c0eSJiawen Wu 		/* this field returns the status of LLDP */
387*91e64c0eSJiawen Wu 		if (buffer.func)
388*91e64c0eSJiawen Wu 			hw->lldp_enabled = true;
389*91e64c0eSJiawen Wu 		else
390*91e64c0eSJiawen Wu 			hw->lldp_enabled = false;
391*91e64c0eSJiawen Wu 	} else {
392*91e64c0eSJiawen Wu 		err = NGBE_ERR_HOST_INTERFACE_COMMAND;
393*91e64c0eSJiawen Wu 	}
394*91e64c0eSJiawen Wu 
395*91e64c0eSJiawen Wu 	return err;
396*91e64c0eSJiawen Wu }
397*91e64c0eSJiawen Wu 
398*91e64c0eSJiawen Wu s32 ngbe_hic_set_lldp(struct ngbe_hw *hw, bool on)
399*91e64c0eSJiawen Wu {
400*91e64c0eSJiawen Wu 	struct ngbe_hic_write_lldp buffer;
401*91e64c0eSJiawen Wu 
402*91e64c0eSJiawen Wu 	if (on)
403*91e64c0eSJiawen Wu 		buffer.hdr.cmd = FW_LLDP_SET_CMD_ON;
404*91e64c0eSJiawen Wu 	else
405*91e64c0eSJiawen Wu 		buffer.hdr.cmd = FW_LLDP_SET_CMD_OFF;
406*91e64c0eSJiawen Wu 	buffer.hdr.buf_len = 0x1;
407*91e64c0eSJiawen Wu 	buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
408*91e64c0eSJiawen Wu 	buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
409*91e64c0eSJiawen Wu 	buffer.func = hw->bus.lan_id;
410*91e64c0eSJiawen Wu 
411*91e64c0eSJiawen Wu 	return ngbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
412*91e64c0eSJiawen Wu 					   NGBE_HI_COMMAND_TIMEOUT, false);
413*91e64c0eSJiawen Wu }
414