Branch data Line data Source code
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 [ # # # # ]: 0 : for (i = 0; i < length; i++)
23 : 0 : sum += buffer[i];
24 : :
25 : 0 : 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 : 0 : 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 [ # # # ]: 0 : dword_len = length >> 2;
49 : :
50 : : txgbe_flush(hw);
51 : : /* The device driver writes the relevant command block
52 : : * into the ram area.
53 : : */
54 [ # # ]: 0 : for (i = 0; i < dword_len; i++) {
55 : 0 : wr32a(hw, TXGBE_MNGMBX, i, cpu_to_le32(buffer[i]));
56 : 0 : buffer[i] = rd32a(hw, TXGBE_MNGMBX, i);
57 : : }
58 : : txgbe_flush(hw);
59 : :
60 : : /* Setting this bit tells the ARC that a new command is pending. */
61 : : wr32m(hw, TXGBE_MNGMBXCTL,
62 : : TXGBE_MNGMBXCTL_SWRDY, TXGBE_MNGMBXCTL_SWRDY);
63 : :
64 : : /* Check command completion */
65 : 0 : loop = po32m(hw, TXGBE_MNGMBXCTL,
66 : : TXGBE_MNGMBXCTL_FWRDY, TXGBE_MNGMBXCTL_FWRDY,
67 : : &value, timeout, 1000);
68 [ # # # # ]: 0 : if (!loop || !(value & TXGBE_MNGMBXCTL_FWACK)) {
69 : 0 : DEBUGOUT("Command has failed with no status valid.");
70 : 0 : return TXGBE_ERR_HOST_INTERFACE_COMMAND;
71 : : }
72 : :
73 [ # # ]: 0 : if ((rd32(hw, TXGBE_MNGMBX) & 0xff0000) >> 16 == 0x80) {
74 : 0 : DEBUGOUT("It's unknown command.");
75 : 0 : return TXGBE_ERR_MNG_ACCESS_FAILED;
76 : : }
77 : :
78 : : return 0;
79 : : }
80 : :
81 : : /**
82 : : * txgbe_host_interface_command - Issue command to manageability block
83 : : * @hw: pointer to the HW structure
84 : : * @buffer: contains the command to write and where the return status will
85 : : * be placed
86 : : * @length: length of buffer, must be multiple of 4 bytes
87 : : * @timeout: time in ms to wait for command completion
88 : : * @return_data: read and return data from the buffer (true) or not (false)
89 : : * Needed because FW structures are big endian and decoding of
90 : : * these fields can be 8 bit or 16 bit based on command. Decoding
91 : : * is not easily understood without making a table of commands.
92 : : * So we will leave this up to the caller to read back the data
93 : : * in these cases.
94 : : *
95 : : * Communicates with the manageability block. On success return 0
96 : : * else returns semaphore error when encountering an error acquiring
97 : : * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
98 : : **/
99 : : static s32
100 : 0 : txgbe_host_interface_command(struct txgbe_hw *hw, u32 *buffer,
101 : : u32 length, u32 timeout, bool return_data)
102 : : {
103 : : u32 hdr_size = sizeof(struct txgbe_hic_hdr);
104 : : struct txgbe_hic_hdr *resp = (struct txgbe_hic_hdr *)buffer;
105 : : u16 buf_len;
106 : : s32 err = 0;
107 : : u32 bi;
108 : : u32 dword_len;
109 : :
110 [ # # ]: 0 : if (length == 0 || length > TXGBE_PMMBX_BSIZE) {
111 : 0 : DEBUGOUT("Buffer length failure buffersize=%d.", length);
112 : 0 : return TXGBE_ERR_HOST_INTERFACE_COMMAND;
113 : : }
114 : :
115 : : /* Calculate length in DWORDs. We must be DWORD aligned */
116 [ # # ]: 0 : if (length % sizeof(u32)) {
117 : 0 : DEBUGOUT("Buffer length failure, not aligned to dword");
118 : 0 : return TXGBE_ERR_INVALID_ARGUMENT;
119 : : }
120 : :
121 : : /* Take management host interface semaphore */
122 : 0 : err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWMBX);
123 [ # # ]: 0 : if (err)
124 : : return err;
125 : :
126 : 0 : err = txgbe_hic_unlocked(hw, buffer, length, timeout);
127 [ # # ]: 0 : if (err)
128 : 0 : goto rel_out;
129 : :
130 [ # # ]: 0 : if (!return_data)
131 : 0 : goto rel_out;
132 : :
133 : : /* Calculate length in DWORDs */
134 : : dword_len = hdr_size >> 2;
135 : :
136 : : /* first pull in the header so we know the buffer length */
137 [ # # ]: 0 : for (bi = 0; bi < dword_len; bi++)
138 : 0 : buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi);
139 : :
140 : 0 : buf_len = resp->buf_len;
141 [ # # ]: 0 : if (!buf_len)
142 : 0 : goto rel_out;
143 : :
144 [ # # ]: 0 : if (length < buf_len + hdr_size) {
145 : 0 : DEBUGOUT("Buffer not large enough for reply message.");
146 : : err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
147 : 0 : goto rel_out;
148 : : }
149 : :
150 : : /* Calculate length in DWORDs, add 3 for odd lengths */
151 : 0 : dword_len = (buf_len + 3) >> 2;
152 : :
153 : : /* Pull in the rest of the buffer (bi is where we left off) */
154 [ # # ]: 0 : for (; bi <= dword_len; bi++)
155 : 0 : buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi);
156 : :
157 : 0 : rel_out:
158 : 0 : hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWMBX);
159 : :
160 : 0 : return err;
161 : : }
162 : :
163 : : static s32
164 : 0 : txgbe_host_interface_command_aml(struct txgbe_hw *hw, u32 *buffer,
165 : : u32 length, u32 timeout, bool return_data)
166 : : {
167 : : u32 hdr_size = sizeof(struct txgbe_hic_hdr);
168 : : struct txgbe_hic_hdr *resp = (struct txgbe_hic_hdr *)buffer;
169 : : struct txgbe_hic_hdr *recv_hdr;
170 : : u16 buf_len;
171 : : s32 err = 0;
172 : : u32 bi, i;
173 : : u32 dword_len;
174 : : u8 send_cmd;
175 : :
176 [ # # ]: 0 : if (length == 0 || length > TXGBE_PMMBX_BSIZE) {
177 : 0 : DEBUGOUT("Buffer length failure buffersize=%d.", length);
178 : 0 : return TXGBE_ERR_HOST_INTERFACE_COMMAND;
179 : : }
180 : :
181 : : /* Calculate length in DWORDs. We must be DWORD aligned */
182 [ # # ]: 0 : if (length % sizeof(u32)) {
183 : 0 : DEBUGOUT("Buffer length failure, not aligned to dword");
184 : 0 : return TXGBE_ERR_INVALID_ARGUMENT;
185 : : }
186 : :
187 : : /* try to get lock */
188 [ # # ]: 0 : while (rte_atomic32_test_and_set(&hw->swfw_busy)) {
189 : 0 : timeout--;
190 [ # # ]: 0 : if (!timeout)
191 : : return TXGBE_ERR_TIMEOUT;
192 : 0 : usec_delay(1000);
193 : : }
194 : :
195 : : /* index to unique seq id for each mbox message */
196 : 0 : resp->index = hw->swfw_index;
197 : 0 : send_cmd = resp->cmd;
198 : :
199 : : /* Calculate length in DWORDs */
200 : 0 : dword_len = length >> 2;
201 : :
202 : : /* write data to SW-FW mbox array */
203 [ # # ]: 0 : for (i = 0; i < dword_len; i++) {
204 : 0 : wr32a(hw, TXGBE_AML_MNG_MBOX_SW2FW,
205 : : i, rte_cpu_to_le_32(buffer[i]));
206 : : /* write flush */
207 : : rd32a(hw, TXGBE_AML_MNG_MBOX_SW2FW, i);
208 : : }
209 : :
210 : : /* amlite: generate interrupt to notify FW */
211 : : wr32m(hw, TXGBE_AML_MNG_MBOX_CTL_SW2FW,
212 : : TXGBE_AML_MNG_MBOX_NOTIFY, 0);
213 : : wr32m(hw, TXGBE_AML_MNG_MBOX_CTL_SW2FW,
214 : : TXGBE_AML_MNG_MBOX_NOTIFY, TXGBE_AML_MNG_MBOX_NOTIFY);
215 : :
216 : : /* Calculate length in DWORDs */
217 : : dword_len = hdr_size >> 2;
218 : :
219 : : /* polling reply from FW */
220 : : timeout = 50;
221 : : do {
222 : 0 : timeout--;
223 : 0 : usec_delay(1000);
224 : :
225 : : /* read hdr */
226 [ # # ]: 0 : for (bi = 0; bi < dword_len; bi++)
227 : 0 : buffer[bi] = rd32a(hw, TXGBE_AML_MNG_MBOX_FW2SW, bi);
228 : :
229 : : /* check hdr */
230 : : recv_hdr = (struct txgbe_hic_hdr *)buffer;
231 : :
232 [ # # ]: 0 : if (recv_hdr->cmd == send_cmd &&
233 [ # # ]: 0 : recv_hdr->index == hw->swfw_index)
234 : : break;
235 [ # # ]: 0 : } while (timeout);
236 : :
237 [ # # ]: 0 : if (!timeout) {
238 : 0 : PMD_DRV_LOG(ERR, "Polling from FW messages timeout, cmd is 0x%x, index is %d",
239 : : send_cmd, hw->swfw_index);
240 : : err = TXGBE_ERR_TIMEOUT;
241 : 0 : goto rel_out;
242 : : }
243 : :
244 : : /* expect no reply from FW then return */
245 : : /* release lock if return */
246 [ # # ]: 0 : if (!return_data)
247 : 0 : goto rel_out;
248 : :
249 : : /* If there is any thing in data position pull it in */
250 : 0 : buf_len = recv_hdr->buf_len;
251 [ # # ]: 0 : if (buf_len == 0)
252 : 0 : goto rel_out;
253 : :
254 [ # # ]: 0 : if (length < buf_len + hdr_size) {
255 : 0 : DEBUGOUT("Buffer not large enough for reply message.");
256 : : err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
257 : 0 : goto rel_out;
258 : : }
259 : :
260 : : /* Calculate length in DWORDs, add 3 for odd lengths */
261 : 0 : dword_len = (buf_len + 3) >> 2;
262 [ # # ]: 0 : for (; bi <= dword_len; bi++)
263 : 0 : buffer[bi] = rd32a(hw, TXGBE_AML_MNG_MBOX_FW2SW, bi);
264 : :
265 : 0 : rel_out:
266 : : /* index++, index replace txgbe_hic_hdr.checksum */
267 [ # # ]: 0 : hw->swfw_index = resp->index == TXGBE_HIC_HDR_INDEX_MAX ?
268 : : 0 : resp->index + 1;
269 : : rte_atomic32_clear(&hw->swfw_busy);
270 : :
271 : 0 : return err;
272 : : }
273 : :
274 : : /**
275 : : * txgbe_hic_sr_read - Read EEPROM word using a host interface cmd
276 : : * assuming that the semaphore is already obtained.
277 : : * @hw: pointer to hardware structure
278 : : * @offset: offset of word in the EEPROM to read
279 : : * @data: word read from the EEPROM
280 : : *
281 : : * Reads a 16 bit word from the EEPROM using the hostif.
282 : : **/
283 : 0 : s32 txgbe_hic_sr_read(struct txgbe_hw *hw, u32 addr, u8 *buf, int len)
284 : : {
285 : : struct txgbe_hic_read_shadow_ram command;
286 : : u32 value;
287 : : int err, i = 0, j = 0;
288 : : u32 mngmbx_addr;
289 : :
290 [ # # ]: 0 : if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40)
291 : : mngmbx_addr = TXGBE_AML_MNG_MBOX_FW2SW;
292 : : else
293 : : mngmbx_addr = TXGBE_MNGMBX;
294 : :
295 [ # # ]: 0 : if (len > TXGBE_PMMBX_DATA_SIZE)
296 : : return TXGBE_ERR_HOST_INTERFACE_COMMAND;
297 : :
298 : : memset(&command, 0, sizeof(command));
299 : 0 : command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD;
300 : : command.hdr.req.buf_lenh = 0;
301 : 0 : command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN;
302 : 0 : command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
303 [ # # ]: 0 : command.address = cpu_to_be32(addr);
304 [ # # ]: 0 : command.length = cpu_to_be16(len);
305 : :
306 [ # # ]: 0 : if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40)
307 : 0 : err = txgbe_host_interface_command_aml(hw, (u32 *)&command,
308 : : sizeof(command), TXGBE_HI_COMMAND_TIMEOUT, false);
309 : : else
310 : 0 : err = txgbe_hic_unlocked(hw, (u32 *)&command,
311 : : sizeof(command), TXGBE_HI_COMMAND_TIMEOUT);
312 [ # # ]: 0 : if (err)
313 : : return err;
314 : :
315 [ # # ]: 0 : while (i < (len >> 2)) {
316 : 0 : value = rd32a(hw, mngmbx_addr, FW_NVM_DATA_OFFSET + i);
317 : 0 : ((u32 *)buf)[i] = value;
318 : 0 : i++;
319 : : }
320 : :
321 : 0 : value = rd32a(hw, mngmbx_addr, FW_NVM_DATA_OFFSET + i);
322 [ # # ]: 0 : for (i <<= 2; i < len; i++)
323 : 0 : ((u8 *)buf)[i] = ((u8 *)&value)[j++];
324 : :
325 : : return 0;
326 : : }
327 : :
328 : : /**
329 : : * txgbe_hic_sr_write - Write EEPROM word using hostif
330 : : * @hw: pointer to hardware structure
331 : : * @offset: offset of word in the EEPROM to write
332 : : * @data: word write to the EEPROM
333 : : *
334 : : * Write a 16 bit word to the EEPROM using the hostif.
335 : : **/
336 : 0 : s32 txgbe_hic_sr_write(struct txgbe_hw *hw, u32 addr, u8 *buf, int len)
337 : : {
338 : : struct txgbe_hic_write_shadow_ram command;
339 : : u32 value;
340 : : int err = 0, i = 0, j = 0;
341 : :
342 [ # # ]: 0 : if (len > TXGBE_PMMBX_DATA_SIZE)
343 : : return TXGBE_ERR_HOST_INTERFACE_COMMAND;
344 : :
345 : : memset(&command, 0, sizeof(command));
346 : 0 : command.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD;
347 : : command.hdr.req.buf_lenh = 0;
348 : 0 : command.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN;
349 : 0 : command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
350 [ # # ]: 0 : command.address = cpu_to_be32(addr);
351 [ # # ]: 0 : command.length = cpu_to_be16(len);
352 : :
353 [ # # ]: 0 : while (i < (len >> 2)) {
354 : 0 : value = ((u32 *)buf)[i];
355 : 0 : wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value);
356 : 0 : i++;
357 : : }
358 : :
359 [ # # ]: 0 : for (i <<= 2; i < len; i++)
360 : 0 : ((u8 *)&value)[j++] = ((u8 *)buf)[i];
361 : :
362 : 0 : wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value);
363 : :
364 : : UNREFERENCED_PARAMETER(&command);
365 : :
366 : 0 : return err;
367 : : }
368 : :
369 : 0 : s32 txgbe_close_notify(struct txgbe_hw *hw)
370 : : {
371 : : u32 tmp;
372 : : s32 status;
373 : : struct txgbe_hic_write_shadow_ram buffer;
374 : :
375 : 0 : buffer.hdr.req.cmd = FW_DW_CLOSE_NOTIFY;
376 : 0 : buffer.hdr.req.buf_lenh = 0;
377 : 0 : buffer.hdr.req.buf_lenl = 0;
378 : 0 : buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
379 : :
380 : : /* one word */
381 : 0 : buffer.length = 0;
382 : 0 : buffer.address = 0;
383 : :
384 : 0 : status = txgbe_host_interface_command(hw, (u32 *)&buffer,
385 : : sizeof(buffer),
386 : : TXGBE_HI_COMMAND_TIMEOUT, false);
387 [ # # ]: 0 : if (status)
388 : : return status;
389 : :
390 : : tmp = rd32a(hw, TXGBE_MNGMBX, 1);
391 [ # # ]: 0 : if (tmp == TXGBE_CHECKSUM_CAP_ST_PASS)
392 : : status = 0;
393 : : else
394 : : status = TXGBE_ERR_EEPROM_CHECKSUM;
395 : :
396 : : return status;
397 : : }
398 : :
399 : 0 : s32 txgbe_open_notify(struct txgbe_hw *hw)
400 : : {
401 : : u32 tmp;
402 : : s32 status;
403 : : struct txgbe_hic_write_shadow_ram buffer;
404 : :
405 : 0 : buffer.hdr.req.cmd = FW_DW_OPEN_NOTIFY;
406 : 0 : buffer.hdr.req.buf_lenh = 0;
407 : 0 : buffer.hdr.req.buf_lenl = 0;
408 : 0 : buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
409 : :
410 : : /* one word */
411 : 0 : buffer.length = 0;
412 : 0 : buffer.address = 0;
413 : :
414 : 0 : status = txgbe_host_interface_command(hw, (u32 *)&buffer,
415 : : sizeof(buffer),
416 : : TXGBE_HI_COMMAND_TIMEOUT, false);
417 [ # # ]: 0 : if (status)
418 : : return status;
419 : :
420 : : tmp = rd32a(hw, TXGBE_MNGMBX, 1);
421 [ # # ]: 0 : if (tmp == TXGBE_CHECKSUM_CAP_ST_PASS)
422 : : status = 0;
423 : : else
424 : : status = TXGBE_ERR_EEPROM_CHECKSUM;
425 : :
426 : : return status;
427 : : }
428 : :
429 : : /**
430 : : * txgbe_hic_set_drv_ver - Sends driver version to firmware
431 : : * @hw: pointer to the HW structure
432 : : * @maj: driver version major number
433 : : * @min: driver version minor number
434 : : * @build: driver version build number
435 : : * @sub: driver version sub build number
436 : : * @len: unused
437 : : * @driver_ver: unused
438 : : *
439 : : * Sends driver version number to firmware through the manageability
440 : : * block. On success return 0
441 : : * else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring
442 : : * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
443 : : **/
444 : 0 : s32 txgbe_hic_set_drv_ver(struct txgbe_hw *hw, u8 maj, u8 min,
445 : : u8 build, u8 sub, u16 len,
446 : : const char *driver_ver)
447 : : {
448 : : struct txgbe_hic_drv_info fw_cmd;
449 : : int i;
450 : : s32 ret_val = 0;
451 : :
452 : : UNREFERENCED_PARAMETER(len, driver_ver);
453 : :
454 : 0 : fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
455 : 0 : fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
456 : 0 : fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
457 : 0 : fw_cmd.port_num = (u8)hw->bus.func;
458 : 0 : fw_cmd.ver_maj = maj;
459 : 0 : fw_cmd.ver_min = min;
460 : 0 : fw_cmd.ver_build = build;
461 : 0 : fw_cmd.ver_sub = sub;
462 : 0 : fw_cmd.hdr.checksum = 0;
463 : 0 : fw_cmd.pad = 0;
464 : 0 : fw_cmd.pad2 = 0;
465 : 0 : fw_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&fw_cmd,
466 : : (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
467 : :
468 [ # # ]: 0 : for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
469 : 0 : ret_val = txgbe_host_interface_command(hw, (u32 *)&fw_cmd,
470 : : sizeof(fw_cmd),
471 : : TXGBE_HI_COMMAND_TIMEOUT,
472 : : true);
473 [ # # ]: 0 : if (ret_val != 0)
474 : : continue;
475 : :
476 [ # # ]: 0 : if (fw_cmd.hdr.cmd_or_resp.ret_status ==
477 : : FW_CEM_RESP_STATUS_SUCCESS)
478 : : ret_val = 0;
479 : : else
480 : : ret_val = TXGBE_ERR_HOST_INTERFACE_COMMAND;
481 : :
482 : : break;
483 : : }
484 : :
485 : 0 : return ret_val;
486 : : }
487 : :
488 : : /**
489 : : * txgbe_hic_reset - send reset cmd to fw
490 : : * @hw: pointer to hardware structure
491 : : *
492 : : * Sends reset cmd to firmware through the manageability
493 : : * block. On success return 0
494 : : * else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring
495 : : * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
496 : : **/
497 : : s32
498 : 0 : txgbe_hic_reset(struct txgbe_hw *hw)
499 : : {
500 : : struct txgbe_hic_reset reset_cmd;
501 : : int i;
502 : : s32 err = 0;
503 : :
504 : 0 : reset_cmd.hdr.cmd = FW_RESET_CMD;
505 : 0 : reset_cmd.hdr.buf_len = FW_RESET_LEN;
506 : 0 : reset_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
507 : 0 : reset_cmd.lan_id = hw->bus.lan_id;
508 : 0 : reset_cmd.reset_type = (u16)hw->reset_type;
509 : 0 : reset_cmd.hdr.checksum = 0;
510 : 0 : reset_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&reset_cmd,
511 : : (FW_CEM_HDR_LEN + reset_cmd.hdr.buf_len));
512 : :
513 [ # # ]: 0 : for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
514 : 0 : err = txgbe_host_interface_command(hw, (u32 *)&reset_cmd,
515 : : sizeof(reset_cmd),
516 : : TXGBE_HI_COMMAND_TIMEOUT,
517 : : true);
518 [ # # ]: 0 : if (err != 0)
519 : : continue;
520 : :
521 [ # # ]: 0 : if (reset_cmd.hdr.cmd_or_resp.ret_status ==
522 : : FW_CEM_RESP_STATUS_SUCCESS)
523 : : err = 0;
524 : : else
525 : : err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
526 : :
527 : : break;
528 : : }
529 : :
530 : 0 : return err;
531 : : }
532 : :
533 : : /**
534 : : * txgbe_mng_present - returns true when management capability is present
535 : : * @hw: pointer to hardware structure
536 : : */
537 : : bool
538 : 0 : txgbe_mng_present(struct txgbe_hw *hw)
539 : : {
540 [ # # ]: 0 : if (hw->mac.type == txgbe_mac_unknown)
541 : : return false;
542 : :
543 : 0 : return !!rd32m(hw, TXGBE_STAT, TXGBE_STAT_MNGINIT);
544 : : }
545 : :
546 : : /**
547 : : * txgbe_mng_enabled - Is the manageability engine enabled?
548 : : * @hw: pointer to hardware structure
549 : : *
550 : : * Returns true if the manageability engine is enabled.
551 : : **/
552 : : bool
553 : 0 : txgbe_mng_enabled(struct txgbe_hw *hw)
554 : : {
555 : : UNREFERENCED_PARAMETER(hw);
556 : : /* firmware does not control laser */
557 : 0 : return false;
558 : : }
559 : :
560 : 0 : s32 txgbe_hic_get_lldp(struct txgbe_hw *hw)
561 : : {
562 : : struct txgbe_hic_write_lldp buffer;
563 : : s32 err = 0;
564 : :
565 : 0 : buffer.hdr.cmd = FW_LLDP_GET_CMD;
566 : 0 : buffer.hdr.buf_len = 0x1;
567 : 0 : buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
568 : 0 : buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
569 : 0 : buffer.func = hw->bus.lan_id;
570 : :
571 : 0 : err = txgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
572 : : TXGBE_HI_COMMAND_TIMEOUT, true);
573 [ # # ]: 0 : if (err)
574 : : return err;
575 : :
576 [ # # ]: 0 : if (buffer.hdr.cmd_or_resp.ret_status == FW_CEM_RESP_STATUS_SUCCESS) {
577 : : /* this field returns the status of LLDP */
578 [ # # ]: 0 : if (buffer.func)
579 : 0 : hw->lldp_enabled = true;
580 : : else
581 : 0 : hw->lldp_enabled = false;
582 : : } else {
583 : : err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
584 : : }
585 : :
586 : : return err;
587 : : }
588 : :
589 : 0 : s32 txgbe_hic_set_lldp(struct txgbe_hw *hw, bool on)
590 : : {
591 : : struct txgbe_hic_write_lldp buffer;
592 : :
593 [ # # ]: 0 : if (on)
594 : 0 : buffer.hdr.cmd = FW_LLDP_SET_CMD_ON;
595 : : else
596 : 0 : buffer.hdr.cmd = FW_LLDP_SET_CMD_OFF;
597 : 0 : buffer.hdr.buf_len = 0x1;
598 : 0 : buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
599 : 0 : buffer.hdr.checksum = FW_DEFAULT_CHECKSUM;
600 : 0 : buffer.func = hw->bus.lan_id;
601 : :
602 : 0 : return txgbe_host_interface_command(hw, (u32 *)&buffer, sizeof(buffer),
603 : : TXGBE_HI_COMMAND_TIMEOUT, false);
604 : : }
605 : :
606 : 0 : s32 txgbe_hic_ephy_set_link(struct txgbe_hw *hw, u8 speed, u8 autoneg, u8 duplex)
607 : : {
608 : : struct txgbe_hic_ephy_setlink buffer;
609 : : s32 status;
610 : : int i;
611 : :
612 : 0 : buffer.hdr.cmd = FW_PHY_CONFIG_LINK_CMD;
613 : 0 : buffer.hdr.buf_len = sizeof(struct txgbe_hic_ephy_setlink) - sizeof(struct txgbe_hic_hdr);
614 : 0 : buffer.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
615 : :
616 : 0 : buffer.fec_mode = hw->fec_mode;
617 : 0 : buffer.speed = speed;
618 : 0 : buffer.autoneg = autoneg;
619 : 0 : buffer.duplex = duplex;
620 : :
621 [ # # ]: 0 : for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
622 : 0 : status = txgbe_host_interface_command(hw, (u32 *)&buffer,
623 : : sizeof(buffer),
624 : : TXGBE_HI_COMMAND_TIMEOUT_SHORT, true);
625 [ # # ]: 0 : if (status != 0) {
626 : : msleep(1);
627 : : continue;
628 : : }
629 : :
630 [ # # ]: 0 : if (buffer.hdr.cmd_or_resp.ret_status ==
631 : : FW_CEM_RESP_STATUS_SUCCESS)
632 : : status = 0;
633 : : else
634 : : status = TXGBE_ERR_HOST_INTERFACE_COMMAND;
635 : :
636 : : break;
637 : : }
638 : :
639 : 0 : return status;
640 : : }
|