.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
---|
2 | 2 | /* Copyright(c) 2013 - 2018 Intel Corporation. */ |
---|
3 | 3 | |
---|
| 4 | +#include "i40e.h" |
---|
4 | 5 | #include "i40e_type.h" |
---|
5 | 6 | #include "i40e_adminq.h" |
---|
6 | 7 | #include "i40e_prototype.h" |
---|
.. | .. |
---|
13 | 14 | * This function sets the mac type of the adapter based on the |
---|
14 | 15 | * vendor ID and device ID stored in the hw structure. |
---|
15 | 16 | **/ |
---|
16 | | -static i40e_status i40e_set_mac_type(struct i40e_hw *hw) |
---|
| 17 | +i40e_status i40e_set_mac_type(struct i40e_hw *hw) |
---|
17 | 18 | { |
---|
18 | 19 | i40e_status status = 0; |
---|
19 | 20 | |
---|
.. | .. |
---|
26 | 27 | case I40E_DEV_ID_QSFP_A: |
---|
27 | 28 | case I40E_DEV_ID_QSFP_B: |
---|
28 | 29 | case I40E_DEV_ID_QSFP_C: |
---|
| 30 | + case I40E_DEV_ID_5G_BASE_T_BC: |
---|
29 | 31 | case I40E_DEV_ID_10G_BASE_T: |
---|
30 | 32 | case I40E_DEV_ID_10G_BASE_T4: |
---|
| 33 | + case I40E_DEV_ID_10G_BASE_T_BC: |
---|
| 34 | + case I40E_DEV_ID_10G_B: |
---|
| 35 | + case I40E_DEV_ID_10G_SFP: |
---|
31 | 36 | case I40E_DEV_ID_20G_KR2: |
---|
32 | 37 | case I40E_DEV_ID_20G_KR2_A: |
---|
33 | 38 | case I40E_DEV_ID_25G_B: |
---|
34 | 39 | case I40E_DEV_ID_25G_SFP28: |
---|
| 40 | + case I40E_DEV_ID_X710_N3000: |
---|
| 41 | + case I40E_DEV_ID_XXV710_N3000: |
---|
35 | 42 | hw->mac.type = I40E_MAC_XL710; |
---|
36 | 43 | break; |
---|
37 | 44 | case I40E_DEV_ID_KX_X722: |
---|
.. | .. |
---|
277 | 284 | void *buffer, u16 buf_len) |
---|
278 | 285 | { |
---|
279 | 286 | struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc; |
---|
| 287 | + u32 effective_mask = hw->debug_mask & mask; |
---|
| 288 | + char prefix[27]; |
---|
280 | 289 | u16 len; |
---|
281 | 290 | u8 *buf = (u8 *)buffer; |
---|
282 | 291 | |
---|
283 | | - if ((!(mask & hw->debug_mask)) || (desc == NULL)) |
---|
| 292 | + if (!effective_mask || !desc) |
---|
284 | 293 | return; |
---|
285 | 294 | |
---|
286 | 295 | len = le16_to_cpu(aq_desc->datalen); |
---|
287 | 296 | |
---|
288 | | - i40e_debug(hw, mask, |
---|
| 297 | + i40e_debug(hw, mask & I40E_DEBUG_AQ_DESCRIPTOR, |
---|
289 | 298 | "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n", |
---|
290 | 299 | le16_to_cpu(aq_desc->opcode), |
---|
291 | 300 | le16_to_cpu(aq_desc->flags), |
---|
292 | 301 | le16_to_cpu(aq_desc->datalen), |
---|
293 | 302 | le16_to_cpu(aq_desc->retval)); |
---|
294 | | - i40e_debug(hw, mask, "\tcookie (h,l) 0x%08X 0x%08X\n", |
---|
| 303 | + i40e_debug(hw, mask & I40E_DEBUG_AQ_DESCRIPTOR, |
---|
| 304 | + "\tcookie (h,l) 0x%08X 0x%08X\n", |
---|
295 | 305 | le32_to_cpu(aq_desc->cookie_high), |
---|
296 | 306 | le32_to_cpu(aq_desc->cookie_low)); |
---|
297 | | - i40e_debug(hw, mask, "\tparam (0,1) 0x%08X 0x%08X\n", |
---|
| 307 | + i40e_debug(hw, mask & I40E_DEBUG_AQ_DESCRIPTOR, |
---|
| 308 | + "\tparam (0,1) 0x%08X 0x%08X\n", |
---|
298 | 309 | le32_to_cpu(aq_desc->params.internal.param0), |
---|
299 | 310 | le32_to_cpu(aq_desc->params.internal.param1)); |
---|
300 | | - i40e_debug(hw, mask, "\taddr (h,l) 0x%08X 0x%08X\n", |
---|
| 311 | + i40e_debug(hw, mask & I40E_DEBUG_AQ_DESCRIPTOR, |
---|
| 312 | + "\taddr (h,l) 0x%08X 0x%08X\n", |
---|
301 | 313 | le32_to_cpu(aq_desc->params.external.addr_high), |
---|
302 | 314 | le32_to_cpu(aq_desc->params.external.addr_low)); |
---|
303 | 315 | |
---|
304 | | - if ((buffer != NULL) && (aq_desc->datalen != 0)) { |
---|
| 316 | + if (buffer && buf_len != 0 && len != 0 && |
---|
| 317 | + (effective_mask & I40E_DEBUG_AQ_DESC_BUFFER)) { |
---|
305 | 318 | i40e_debug(hw, mask, "AQ CMD Buffer:\n"); |
---|
306 | 319 | if (buf_len < len) |
---|
307 | 320 | len = buf_len; |
---|
308 | | - /* write the full 16-byte chunks */ |
---|
309 | | - if (hw->debug_mask & mask) { |
---|
310 | | - char prefix[27]; |
---|
311 | 321 | |
---|
312 | | - snprintf(prefix, sizeof(prefix), |
---|
313 | | - "i40e %02x:%02x.%x: \t0x", |
---|
314 | | - hw->bus.bus_id, |
---|
315 | | - hw->bus.device, |
---|
316 | | - hw->bus.func); |
---|
| 322 | + snprintf(prefix, sizeof(prefix), |
---|
| 323 | + "i40e %02x:%02x.%x: \t0x", |
---|
| 324 | + hw->bus.bus_id, |
---|
| 325 | + hw->bus.device, |
---|
| 326 | + hw->bus.func); |
---|
317 | 327 | |
---|
318 | | - print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, |
---|
319 | | - 16, 1, buf, len, false); |
---|
320 | | - } |
---|
| 328 | + print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, |
---|
| 329 | + 16, 1, buf, len, false); |
---|
321 | 330 | } |
---|
322 | 331 | } |
---|
323 | 332 | |
---|
.. | .. |
---|
926 | 935 | else |
---|
927 | 936 | hw->pf_id = (u8)(func_rid & 0x7); |
---|
928 | 937 | |
---|
929 | | - if (hw->mac.type == I40E_MAC_X722) |
---|
930 | | - hw->flags |= I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE | |
---|
931 | | - I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK; |
---|
932 | | - |
---|
933 | 938 | status = i40e_init_nvm(hw); |
---|
934 | 939 | return status; |
---|
935 | 940 | } |
---|
.. | .. |
---|
1109 | 1114 | */ |
---|
1110 | 1115 | pba_size--; |
---|
1111 | 1116 | if (pba_num_size < (((u32)pba_size * 2) + 1)) { |
---|
1112 | | - hw_dbg(hw, "Buffer to small for PBA data.\n"); |
---|
| 1117 | + hw_dbg(hw, "Buffer too small for PBA data.\n"); |
---|
1113 | 1118 | return I40E_ERR_PARAM; |
---|
1114 | 1119 | } |
---|
1115 | 1120 | |
---|
.. | .. |
---|
1149 | 1154 | break; |
---|
1150 | 1155 | case I40E_PHY_TYPE_100BASE_TX: |
---|
1151 | 1156 | case I40E_PHY_TYPE_1000BASE_T: |
---|
| 1157 | + case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS: |
---|
| 1158 | + case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS: |
---|
1152 | 1159 | case I40E_PHY_TYPE_10GBASE_T: |
---|
1153 | 1160 | media = I40E_MEDIA_TYPE_BASET; |
---|
1154 | 1161 | break; |
---|
.. | .. |
---|
1432 | 1439 | u32 gpio_val = 0; |
---|
1433 | 1440 | u32 port; |
---|
1434 | 1441 | |
---|
1435 | | - if (!hw->func_caps.led[idx]) |
---|
| 1442 | + if (!I40E_IS_X710TL_DEVICE(hw->device_id) && |
---|
| 1443 | + !hw->func_caps.led[idx]) |
---|
1436 | 1444 | return 0; |
---|
1437 | | - |
---|
1438 | 1445 | gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx)); |
---|
1439 | 1446 | port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >> |
---|
1440 | 1447 | I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT; |
---|
.. | .. |
---|
1449 | 1456 | return gpio_val; |
---|
1450 | 1457 | } |
---|
1451 | 1458 | |
---|
1452 | | -#define I40E_COMBINED_ACTIVITY 0xA |
---|
1453 | | -#define I40E_FILTER_ACTIVITY 0xE |
---|
1454 | | -#define I40E_LINK_ACTIVITY 0xC |
---|
1455 | | -#define I40E_MAC_ACTIVITY 0xD |
---|
| 1459 | +#define I40E_FW_LED BIT(4) |
---|
| 1460 | +#define I40E_LED_MODE_VALID (I40E_GLGEN_GPIO_CTL_LED_MODE_MASK >> \ |
---|
| 1461 | + I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) |
---|
| 1462 | + |
---|
1456 | 1463 | #define I40E_LED0 22 |
---|
| 1464 | + |
---|
| 1465 | +#define I40E_PIN_FUNC_SDP 0x0 |
---|
| 1466 | +#define I40E_PIN_FUNC_LED 0x1 |
---|
1457 | 1467 | |
---|
1458 | 1468 | /** |
---|
1459 | 1469 | * i40e_led_get - return current on/off mode |
---|
.. | .. |
---|
1466 | 1476 | **/ |
---|
1467 | 1477 | u32 i40e_led_get(struct i40e_hw *hw) |
---|
1468 | 1478 | { |
---|
1469 | | - u32 current_mode = 0; |
---|
1470 | 1479 | u32 mode = 0; |
---|
1471 | 1480 | int i; |
---|
1472 | 1481 | |
---|
.. | .. |
---|
1478 | 1487 | |
---|
1479 | 1488 | if (!gpio_val) |
---|
1480 | 1489 | continue; |
---|
1481 | | - |
---|
1482 | | - /* ignore gpio LED src mode entries related to the activity |
---|
1483 | | - * LEDs |
---|
1484 | | - */ |
---|
1485 | | - current_mode = ((gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) |
---|
1486 | | - >> I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT); |
---|
1487 | | - switch (current_mode) { |
---|
1488 | | - case I40E_COMBINED_ACTIVITY: |
---|
1489 | | - case I40E_FILTER_ACTIVITY: |
---|
1490 | | - case I40E_MAC_ACTIVITY: |
---|
1491 | | - case I40E_LINK_ACTIVITY: |
---|
1492 | | - continue; |
---|
1493 | | - default: |
---|
1494 | | - break; |
---|
1495 | | - } |
---|
1496 | 1490 | |
---|
1497 | 1491 | mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) >> |
---|
1498 | 1492 | I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT; |
---|
.. | .. |
---|
1513 | 1507 | **/ |
---|
1514 | 1508 | void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink) |
---|
1515 | 1509 | { |
---|
1516 | | - u32 current_mode = 0; |
---|
1517 | 1510 | int i; |
---|
1518 | 1511 | |
---|
1519 | | - if (mode & 0xfffffff0) |
---|
| 1512 | + if (mode & ~I40E_LED_MODE_VALID) { |
---|
1520 | 1513 | hw_dbg(hw, "invalid mode passed in %X\n", mode); |
---|
| 1514 | + return; |
---|
| 1515 | + } |
---|
1521 | 1516 | |
---|
1522 | 1517 | /* as per the documentation GPIO 22-29 are the LED |
---|
1523 | 1518 | * GPIO pins named LED0..LED7 |
---|
.. | .. |
---|
1528 | 1523 | if (!gpio_val) |
---|
1529 | 1524 | continue; |
---|
1530 | 1525 | |
---|
1531 | | - /* ignore gpio LED src mode entries related to the activity |
---|
1532 | | - * LEDs |
---|
1533 | | - */ |
---|
1534 | | - current_mode = ((gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) |
---|
1535 | | - >> I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT); |
---|
1536 | | - switch (current_mode) { |
---|
1537 | | - case I40E_COMBINED_ACTIVITY: |
---|
1538 | | - case I40E_FILTER_ACTIVITY: |
---|
1539 | | - case I40E_MAC_ACTIVITY: |
---|
1540 | | - case I40E_LINK_ACTIVITY: |
---|
1541 | | - continue; |
---|
1542 | | - default: |
---|
1543 | | - break; |
---|
1544 | | - } |
---|
| 1526 | + if (I40E_IS_X710TL_DEVICE(hw->device_id)) { |
---|
| 1527 | + u32 pin_func = 0; |
---|
1545 | 1528 | |
---|
| 1529 | + if (mode & I40E_FW_LED) |
---|
| 1530 | + pin_func = I40E_PIN_FUNC_SDP; |
---|
| 1531 | + else |
---|
| 1532 | + pin_func = I40E_PIN_FUNC_LED; |
---|
| 1533 | + |
---|
| 1534 | + gpio_val &= ~I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK; |
---|
| 1535 | + gpio_val |= ((pin_func << |
---|
| 1536 | + I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT) & |
---|
| 1537 | + I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK); |
---|
| 1538 | + } |
---|
1546 | 1539 | gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK; |
---|
1547 | 1540 | /* this & is a bit of paranoia, but serves as a range check */ |
---|
1548 | 1541 | gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) & |
---|
.. | .. |
---|
1602 | 1595 | status = i40e_asq_send_command(hw, &desc, abilities, |
---|
1603 | 1596 | abilities_size, cmd_details); |
---|
1604 | 1597 | |
---|
1605 | | - if (status) |
---|
1606 | | - break; |
---|
1607 | | - |
---|
1608 | | - if (hw->aq.asq_last_status == I40E_AQ_RC_EIO) { |
---|
| 1598 | + switch (hw->aq.asq_last_status) { |
---|
| 1599 | + case I40E_AQ_RC_EIO: |
---|
1609 | 1600 | status = I40E_ERR_UNKNOWN_PHY; |
---|
1610 | 1601 | break; |
---|
1611 | | - } else if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN) { |
---|
| 1602 | + case I40E_AQ_RC_EAGAIN: |
---|
1612 | 1603 | usleep_range(1000, 2000); |
---|
1613 | 1604 | total_delay++; |
---|
1614 | 1605 | status = I40E_ERR_TIMEOUT; |
---|
| 1606 | + break; |
---|
| 1607 | + /* also covers I40E_AQ_RC_OK */ |
---|
| 1608 | + default: |
---|
| 1609 | + break; |
---|
1615 | 1610 | } |
---|
1616 | | - } while ((hw->aq.asq_last_status != I40E_AQ_RC_OK) && |
---|
1617 | | - (total_delay < max_delay)); |
---|
| 1611 | + |
---|
| 1612 | + } while ((hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN) && |
---|
| 1613 | + (total_delay < max_delay)); |
---|
1618 | 1614 | |
---|
1619 | 1615 | if (status) |
---|
1620 | 1616 | return status; |
---|
.. | .. |
---|
1897 | 1893 | hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE) |
---|
1898 | 1894 | hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU; |
---|
1899 | 1895 | |
---|
1900 | | - if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR && |
---|
1901 | | - hw->aq.api_min_ver >= 7) { |
---|
| 1896 | + if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE && |
---|
| 1897 | + hw->mac.type != I40E_MAC_X722) { |
---|
1902 | 1898 | __le32 tmp; |
---|
1903 | 1899 | |
---|
1904 | 1900 | memcpy(&tmp, resp->link_type, sizeof(tmp)); |
---|
.. | .. |
---|
2611 | 2607 | if (status) |
---|
2612 | 2608 | return status; |
---|
2613 | 2609 | |
---|
2614 | | - hw->phy.link_info.req_fec_info = |
---|
2615 | | - abilities.fec_cfg_curr_mod_ext_info & |
---|
2616 | | - (I40E_AQ_REQUEST_FEC_KR | I40E_AQ_REQUEST_FEC_RS); |
---|
| 2610 | + if (abilities.fec_cfg_curr_mod_ext_info & |
---|
| 2611 | + I40E_AQ_ENABLE_FEC_AUTO) |
---|
| 2612 | + hw->phy.link_info.req_fec_info = |
---|
| 2613 | + (I40E_AQ_REQUEST_FEC_KR | |
---|
| 2614 | + I40E_AQ_REQUEST_FEC_RS); |
---|
| 2615 | + else |
---|
| 2616 | + hw->phy.link_info.req_fec_info = |
---|
| 2617 | + abilities.fec_cfg_curr_mod_ext_info & |
---|
| 2618 | + (I40E_AQ_REQUEST_FEC_KR | |
---|
| 2619 | + I40E_AQ_REQUEST_FEC_RS); |
---|
2617 | 2620 | |
---|
2618 | 2621 | memcpy(hw->phy.link_info.module_type, &abilities.module_type, |
---|
2619 | 2622 | sizeof(hw->phy.link_info.module_type)); |
---|
.. | .. |
---|
3687 | 3690 | } |
---|
3688 | 3691 | |
---|
3689 | 3692 | /** |
---|
| 3693 | + * i40e_aq_restore_lldp |
---|
| 3694 | + * @hw: pointer to the hw struct |
---|
| 3695 | + * @setting: pointer to factory setting variable or NULL |
---|
| 3696 | + * @restore: True if factory settings should be restored |
---|
| 3697 | + * @cmd_details: pointer to command details structure or NULL |
---|
| 3698 | + * |
---|
| 3699 | + * Restore LLDP Agent factory settings if @restore set to True. In other case |
---|
| 3700 | + * only returns factory setting in AQ response. |
---|
| 3701 | + **/ |
---|
| 3702 | +enum i40e_status_code |
---|
| 3703 | +i40e_aq_restore_lldp(struct i40e_hw *hw, u8 *setting, bool restore, |
---|
| 3704 | + struct i40e_asq_cmd_details *cmd_details) |
---|
| 3705 | +{ |
---|
| 3706 | + struct i40e_aq_desc desc; |
---|
| 3707 | + struct i40e_aqc_lldp_restore *cmd = |
---|
| 3708 | + (struct i40e_aqc_lldp_restore *)&desc.params.raw; |
---|
| 3709 | + i40e_status status; |
---|
| 3710 | + |
---|
| 3711 | + if (!(hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)) { |
---|
| 3712 | + i40e_debug(hw, I40E_DEBUG_ALL, |
---|
| 3713 | + "Restore LLDP not supported by current FW version.\n"); |
---|
| 3714 | + return I40E_ERR_DEVICE_NOT_SUPPORTED; |
---|
| 3715 | + } |
---|
| 3716 | + |
---|
| 3717 | + i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_restore); |
---|
| 3718 | + |
---|
| 3719 | + if (restore) |
---|
| 3720 | + cmd->command |= I40E_AQ_LLDP_AGENT_RESTORE; |
---|
| 3721 | + |
---|
| 3722 | + status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); |
---|
| 3723 | + |
---|
| 3724 | + if (setting) |
---|
| 3725 | + *setting = cmd->command & 1; |
---|
| 3726 | + |
---|
| 3727 | + return status; |
---|
| 3728 | +} |
---|
| 3729 | + |
---|
| 3730 | +/** |
---|
3690 | 3731 | * i40e_aq_stop_lldp |
---|
3691 | 3732 | * @hw: pointer to the hw struct |
---|
3692 | 3733 | * @shutdown_agent: True if LLDP Agent needs to be Shutdown |
---|
| 3734 | + * @persist: True if stop of LLDP should be persistent across power cycles |
---|
3693 | 3735 | * @cmd_details: pointer to command details structure or NULL |
---|
3694 | 3736 | * |
---|
3695 | 3737 | * Stop or Shutdown the embedded LLDP Agent |
---|
3696 | 3738 | **/ |
---|
3697 | 3739 | i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent, |
---|
| 3740 | + bool persist, |
---|
3698 | 3741 | struct i40e_asq_cmd_details *cmd_details) |
---|
3699 | 3742 | { |
---|
3700 | 3743 | struct i40e_aq_desc desc; |
---|
.. | .. |
---|
3707 | 3750 | if (shutdown_agent) |
---|
3708 | 3751 | cmd->command |= I40E_AQ_LLDP_AGENT_SHUTDOWN; |
---|
3709 | 3752 | |
---|
| 3753 | + if (persist) { |
---|
| 3754 | + if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) |
---|
| 3755 | + cmd->command |= I40E_AQ_LLDP_AGENT_STOP_PERSIST; |
---|
| 3756 | + else |
---|
| 3757 | + i40e_debug(hw, I40E_DEBUG_ALL, |
---|
| 3758 | + "Persistent Stop LLDP not supported by current FW version.\n"); |
---|
| 3759 | + } |
---|
| 3760 | + |
---|
3710 | 3761 | status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); |
---|
3711 | 3762 | |
---|
3712 | 3763 | return status; |
---|
.. | .. |
---|
3715 | 3766 | /** |
---|
3716 | 3767 | * i40e_aq_start_lldp |
---|
3717 | 3768 | * @hw: pointer to the hw struct |
---|
3718 | | - * @buff: buffer for result |
---|
3719 | | - * @buff_size: buffer size |
---|
| 3769 | + * @persist: True if start of LLDP should be persistent across power cycles |
---|
3720 | 3770 | * @cmd_details: pointer to command details structure or NULL |
---|
3721 | 3771 | * |
---|
3722 | 3772 | * Start the embedded LLDP Agent on all ports. |
---|
3723 | 3773 | **/ |
---|
3724 | | -i40e_status i40e_aq_start_lldp(struct i40e_hw *hw, |
---|
3725 | | - struct i40e_asq_cmd_details *cmd_details) |
---|
| 3774 | +i40e_status i40e_aq_start_lldp(struct i40e_hw *hw, bool persist, |
---|
| 3775 | + struct i40e_asq_cmd_details *cmd_details) |
---|
3726 | 3776 | { |
---|
3727 | 3777 | struct i40e_aq_desc desc; |
---|
3728 | 3778 | struct i40e_aqc_lldp_start *cmd = |
---|
.. | .. |
---|
3732 | 3782 | i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_start); |
---|
3733 | 3783 | |
---|
3734 | 3784 | cmd->command = I40E_AQ_LLDP_AGENT_START; |
---|
| 3785 | + |
---|
| 3786 | + if (persist) { |
---|
| 3787 | + if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT) |
---|
| 3788 | + cmd->command |= I40E_AQ_LLDP_AGENT_START_PERSIST; |
---|
| 3789 | + else |
---|
| 3790 | + i40e_debug(hw, I40E_DEBUG_ALL, |
---|
| 3791 | + "Persistent Start LLDP not supported by current FW version.\n"); |
---|
| 3792 | + } |
---|
| 3793 | + |
---|
3735 | 3794 | status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); |
---|
3736 | 3795 | |
---|
3737 | 3796 | return status; |
---|
.. | .. |
---|
3752 | 3811 | struct i40e_aqc_set_dcb_parameters *cmd = |
---|
3753 | 3812 | (struct i40e_aqc_set_dcb_parameters *)&desc.params.raw; |
---|
3754 | 3813 | i40e_status status; |
---|
| 3814 | + |
---|
| 3815 | + if (!(hw->flags & I40E_HW_FLAG_FW_LLDP_STOPPABLE)) |
---|
| 3816 | + return I40E_ERR_DEVICE_NOT_SUPPORTED; |
---|
3755 | 3817 | |
---|
3756 | 3818 | i40e_fill_default_direct_cmd_desc(&desc, |
---|
3757 | 3819 | i40e_aqc_opc_set_dcb_parameters); |
---|
.. | .. |
---|
4862 | 4924 | status = i40e_write_phy_register_clause22(hw, reg, phy_addr, |
---|
4863 | 4925 | value); |
---|
4864 | 4926 | break; |
---|
| 4927 | + case I40E_DEV_ID_5G_BASE_T_BC: |
---|
4865 | 4928 | case I40E_DEV_ID_10G_BASE_T: |
---|
4866 | 4929 | case I40E_DEV_ID_10G_BASE_T4: |
---|
| 4930 | + case I40E_DEV_ID_10G_BASE_T_BC: |
---|
4867 | 4931 | case I40E_DEV_ID_10G_BASE_T_X722: |
---|
4868 | 4932 | case I40E_DEV_ID_25G_B: |
---|
4869 | 4933 | case I40E_DEV_ID_25G_SFP28: |
---|
.. | .. |
---|
4898 | 4962 | status = i40e_read_phy_register_clause22(hw, reg, phy_addr, |
---|
4899 | 4963 | value); |
---|
4900 | 4964 | break; |
---|
| 4965 | + case I40E_DEV_ID_5G_BASE_T_BC: |
---|
4901 | 4966 | case I40E_DEV_ID_10G_BASE_T: |
---|
4902 | 4967 | case I40E_DEV_ID_10G_BASE_T4: |
---|
| 4968 | + case I40E_DEV_ID_10G_BASE_T_BC: |
---|
4903 | 4969 | case I40E_DEV_ID_10G_BASE_T_X722: |
---|
4904 | 4970 | case I40E_DEV_ID_25G_B: |
---|
4905 | 4971 | case I40E_DEV_ID_25G_SFP28: |
---|
.. | .. |
---|
5022 | 5088 | status = |
---|
5023 | 5089 | i40e_aq_get_phy_register(hw, |
---|
5024 | 5090 | I40E_AQ_PHY_REG_ACCESS_EXTERNAL, |
---|
5025 | | - I40E_PHY_COM_REG_PAGE, |
---|
| 5091 | + I40E_PHY_COM_REG_PAGE, true, |
---|
5026 | 5092 | I40E_PHY_LED_PROV_REG_1, |
---|
5027 | 5093 | reg_val, NULL); |
---|
5028 | 5094 | } else { |
---|
.. | .. |
---|
5055 | 5121 | status = |
---|
5056 | 5122 | i40e_aq_set_phy_register(hw, |
---|
5057 | 5123 | I40E_AQ_PHY_REG_ACCESS_EXTERNAL, |
---|
5058 | | - I40E_PHY_COM_REG_PAGE, |
---|
| 5124 | + I40E_PHY_COM_REG_PAGE, true, |
---|
5059 | 5125 | I40E_PHY_LED_PROV_REG_1, |
---|
5060 | 5126 | reg_val, NULL); |
---|
5061 | 5127 | } else { |
---|
.. | .. |
---|
5094 | 5160 | status = |
---|
5095 | 5161 | i40e_aq_get_phy_register(hw, |
---|
5096 | 5162 | I40E_AQ_PHY_REG_ACCESS_EXTERNAL, |
---|
5097 | | - I40E_PHY_COM_REG_PAGE, |
---|
| 5163 | + I40E_PHY_COM_REG_PAGE, true, |
---|
5098 | 5164 | I40E_PHY_LED_PROV_REG_1, |
---|
5099 | 5165 | ®_val_aq, NULL); |
---|
5100 | 5166 | if (status == I40E_SUCCESS) |
---|
.. | .. |
---|
5299 | 5365 | } |
---|
5300 | 5366 | |
---|
5301 | 5367 | /** |
---|
5302 | | - * i40e_aq_set_phy_register |
---|
| 5368 | + * i40e_mdio_if_number_selection - MDIO I/F number selection |
---|
| 5369 | + * @hw: pointer to the hw struct |
---|
| 5370 | + * @set_mdio: use MDIO I/F number specified by mdio_num |
---|
| 5371 | + * @mdio_num: MDIO I/F number |
---|
| 5372 | + * @cmd: pointer to PHY Register command structure |
---|
| 5373 | + **/ |
---|
| 5374 | +static void i40e_mdio_if_number_selection(struct i40e_hw *hw, bool set_mdio, |
---|
| 5375 | + u8 mdio_num, |
---|
| 5376 | + struct i40e_aqc_phy_register_access *cmd) |
---|
| 5377 | +{ |
---|
| 5378 | + if (set_mdio && cmd->phy_interface == I40E_AQ_PHY_REG_ACCESS_EXTERNAL) { |
---|
| 5379 | + if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_EXTENDED) |
---|
| 5380 | + cmd->cmd_flags |= |
---|
| 5381 | + I40E_AQ_PHY_REG_ACCESS_SET_MDIO_IF_NUMBER | |
---|
| 5382 | + ((mdio_num << |
---|
| 5383 | + I40E_AQ_PHY_REG_ACCESS_MDIO_IF_NUMBER_SHIFT) & |
---|
| 5384 | + I40E_AQ_PHY_REG_ACCESS_MDIO_IF_NUMBER_MASK); |
---|
| 5385 | + else |
---|
| 5386 | + i40e_debug(hw, I40E_DEBUG_PHY, |
---|
| 5387 | + "MDIO I/F number selection not supported by current FW version.\n"); |
---|
| 5388 | + } |
---|
| 5389 | +} |
---|
| 5390 | + |
---|
| 5391 | +/** |
---|
| 5392 | + * i40e_aq_set_phy_register_ext |
---|
5303 | 5393 | * @hw: pointer to the hw struct |
---|
5304 | 5394 | * @phy_select: select which phy should be accessed |
---|
5305 | 5395 | * @dev_addr: PHY device address |
---|
| 5396 | + * @page_change: flag to indicate if phy page should be updated |
---|
| 5397 | + * @set_mdio: use MDIO I/F number specified by mdio_num |
---|
| 5398 | + * @mdio_num: MDIO I/F number |
---|
5306 | 5399 | * @reg_addr: PHY register address |
---|
5307 | 5400 | * @reg_val: new register value |
---|
5308 | 5401 | * @cmd_details: pointer to command details structure or NULL |
---|
5309 | 5402 | * |
---|
5310 | 5403 | * Write the external PHY register. |
---|
| 5404 | + * NOTE: In common cases MDIO I/F number should not be changed, thats why you |
---|
| 5405 | + * may use simple wrapper i40e_aq_set_phy_register. |
---|
5311 | 5406 | **/ |
---|
5312 | | -i40e_status i40e_aq_set_phy_register(struct i40e_hw *hw, |
---|
5313 | | - u8 phy_select, u8 dev_addr, |
---|
5314 | | - u32 reg_addr, u32 reg_val, |
---|
5315 | | - struct i40e_asq_cmd_details *cmd_details) |
---|
| 5407 | +enum i40e_status_code i40e_aq_set_phy_register_ext(struct i40e_hw *hw, |
---|
| 5408 | + u8 phy_select, u8 dev_addr, bool page_change, |
---|
| 5409 | + bool set_mdio, u8 mdio_num, |
---|
| 5410 | + u32 reg_addr, u32 reg_val, |
---|
| 5411 | + struct i40e_asq_cmd_details *cmd_details) |
---|
5316 | 5412 | { |
---|
5317 | 5413 | struct i40e_aq_desc desc; |
---|
5318 | 5414 | struct i40e_aqc_phy_register_access *cmd = |
---|
.. | .. |
---|
5327 | 5423 | cmd->reg_address = cpu_to_le32(reg_addr); |
---|
5328 | 5424 | cmd->reg_value = cpu_to_le32(reg_val); |
---|
5329 | 5425 | |
---|
| 5426 | + i40e_mdio_if_number_selection(hw, set_mdio, mdio_num, cmd); |
---|
| 5427 | + |
---|
| 5428 | + if (!page_change) |
---|
| 5429 | + cmd->cmd_flags = I40E_AQ_PHY_REG_ACCESS_DONT_CHANGE_QSFP_PAGE; |
---|
| 5430 | + |
---|
5330 | 5431 | status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); |
---|
5331 | 5432 | |
---|
5332 | 5433 | return status; |
---|
5333 | 5434 | } |
---|
5334 | 5435 | |
---|
5335 | 5436 | /** |
---|
5336 | | - * i40e_aq_get_phy_register |
---|
| 5437 | + * i40e_aq_get_phy_register_ext |
---|
5337 | 5438 | * @hw: pointer to the hw struct |
---|
5338 | 5439 | * @phy_select: select which phy should be accessed |
---|
5339 | 5440 | * @dev_addr: PHY device address |
---|
| 5441 | + * @page_change: flag to indicate if phy page should be updated |
---|
| 5442 | + * @set_mdio: use MDIO I/F number specified by mdio_num |
---|
| 5443 | + * @mdio_num: MDIO I/F number |
---|
5340 | 5444 | * @reg_addr: PHY register address |
---|
5341 | 5445 | * @reg_val: read register value |
---|
5342 | 5446 | * @cmd_details: pointer to command details structure or NULL |
---|
5343 | 5447 | * |
---|
5344 | 5448 | * Read the external PHY register. |
---|
| 5449 | + * NOTE: In common cases MDIO I/F number should not be changed, thats why you |
---|
| 5450 | + * may use simple wrapper i40e_aq_get_phy_register. |
---|
5345 | 5451 | **/ |
---|
5346 | | -i40e_status i40e_aq_get_phy_register(struct i40e_hw *hw, |
---|
5347 | | - u8 phy_select, u8 dev_addr, |
---|
5348 | | - u32 reg_addr, u32 *reg_val, |
---|
5349 | | - struct i40e_asq_cmd_details *cmd_details) |
---|
| 5452 | +enum i40e_status_code i40e_aq_get_phy_register_ext(struct i40e_hw *hw, |
---|
| 5453 | + u8 phy_select, u8 dev_addr, bool page_change, |
---|
| 5454 | + bool set_mdio, u8 mdio_num, |
---|
| 5455 | + u32 reg_addr, u32 *reg_val, |
---|
| 5456 | + struct i40e_asq_cmd_details *cmd_details) |
---|
5350 | 5457 | { |
---|
5351 | 5458 | struct i40e_aq_desc desc; |
---|
5352 | 5459 | struct i40e_aqc_phy_register_access *cmd = |
---|
.. | .. |
---|
5359 | 5466 | cmd->phy_interface = phy_select; |
---|
5360 | 5467 | cmd->dev_address = dev_addr; |
---|
5361 | 5468 | cmd->reg_address = cpu_to_le32(reg_addr); |
---|
| 5469 | + |
---|
| 5470 | + i40e_mdio_if_number_selection(hw, set_mdio, mdio_num, cmd); |
---|
| 5471 | + |
---|
| 5472 | + if (!page_change) |
---|
| 5473 | + cmd->cmd_flags = I40E_AQ_PHY_REG_ACCESS_DONT_CHANGE_QSFP_PAGE; |
---|
5362 | 5474 | |
---|
5363 | 5475 | status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); |
---|
5364 | 5476 | if (!status) |
---|
.. | .. |
---|
5475 | 5587 | return NULL; |
---|
5476 | 5588 | } |
---|
5477 | 5589 | |
---|
| 5590 | +/* Get section table in profile */ |
---|
| 5591 | +#define I40E_SECTION_TABLE(profile, sec_tbl) \ |
---|
| 5592 | + do { \ |
---|
| 5593 | + struct i40e_profile_segment *p = (profile); \ |
---|
| 5594 | + u32 count; \ |
---|
| 5595 | + u32 *nvm; \ |
---|
| 5596 | + count = p->device_table_count; \ |
---|
| 5597 | + nvm = (u32 *)&p->device_table[count]; \ |
---|
| 5598 | + sec_tbl = (struct i40e_section_table *)&nvm[nvm[0] + 1]; \ |
---|
| 5599 | + } while (0) |
---|
| 5600 | + |
---|
| 5601 | +/* Get section header in profile */ |
---|
| 5602 | +#define I40E_SECTION_HEADER(profile, offset) \ |
---|
| 5603 | + (struct i40e_profile_section_header *)((u8 *)(profile) + (offset)) |
---|
| 5604 | + |
---|
| 5605 | +/** |
---|
| 5606 | + * i40e_find_section_in_profile |
---|
| 5607 | + * @section_type: the section type to search for (i.e., SECTION_TYPE_NOTE) |
---|
| 5608 | + * @profile: pointer to the i40e segment header to be searched |
---|
| 5609 | + * |
---|
| 5610 | + * This function searches i40e segment for a particular section type. On |
---|
| 5611 | + * success it returns a pointer to the section header, otherwise it will |
---|
| 5612 | + * return NULL. |
---|
| 5613 | + **/ |
---|
| 5614 | +struct i40e_profile_section_header * |
---|
| 5615 | +i40e_find_section_in_profile(u32 section_type, |
---|
| 5616 | + struct i40e_profile_segment *profile) |
---|
| 5617 | +{ |
---|
| 5618 | + struct i40e_profile_section_header *sec; |
---|
| 5619 | + struct i40e_section_table *sec_tbl; |
---|
| 5620 | + u32 sec_off; |
---|
| 5621 | + u32 i; |
---|
| 5622 | + |
---|
| 5623 | + if (profile->header.type != SEGMENT_TYPE_I40E) |
---|
| 5624 | + return NULL; |
---|
| 5625 | + |
---|
| 5626 | + I40E_SECTION_TABLE(profile, sec_tbl); |
---|
| 5627 | + |
---|
| 5628 | + for (i = 0; i < sec_tbl->section_count; i++) { |
---|
| 5629 | + sec_off = sec_tbl->section_offset[i]; |
---|
| 5630 | + sec = I40E_SECTION_HEADER(profile, sec_off); |
---|
| 5631 | + if (sec->section.type == section_type) |
---|
| 5632 | + return sec; |
---|
| 5633 | + } |
---|
| 5634 | + |
---|
| 5635 | + return NULL; |
---|
| 5636 | +} |
---|
| 5637 | + |
---|
| 5638 | +/** |
---|
| 5639 | + * i40e_ddp_exec_aq_section - Execute generic AQ for DDP |
---|
| 5640 | + * @hw: pointer to the hw struct |
---|
| 5641 | + * @aq: command buffer containing all data to execute AQ |
---|
| 5642 | + **/ |
---|
| 5643 | +static enum |
---|
| 5644 | +i40e_status_code i40e_ddp_exec_aq_section(struct i40e_hw *hw, |
---|
| 5645 | + struct i40e_profile_aq_section *aq) |
---|
| 5646 | +{ |
---|
| 5647 | + i40e_status status; |
---|
| 5648 | + struct i40e_aq_desc desc; |
---|
| 5649 | + u8 *msg = NULL; |
---|
| 5650 | + u16 msglen; |
---|
| 5651 | + |
---|
| 5652 | + i40e_fill_default_direct_cmd_desc(&desc, aq->opcode); |
---|
| 5653 | + desc.flags |= cpu_to_le16(aq->flags); |
---|
| 5654 | + memcpy(desc.params.raw, aq->param, sizeof(desc.params.raw)); |
---|
| 5655 | + |
---|
| 5656 | + msglen = aq->datalen; |
---|
| 5657 | + if (msglen) { |
---|
| 5658 | + desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | |
---|
| 5659 | + I40E_AQ_FLAG_RD)); |
---|
| 5660 | + if (msglen > I40E_AQ_LARGE_BUF) |
---|
| 5661 | + desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB); |
---|
| 5662 | + desc.datalen = cpu_to_le16(msglen); |
---|
| 5663 | + msg = &aq->data[0]; |
---|
| 5664 | + } |
---|
| 5665 | + |
---|
| 5666 | + status = i40e_asq_send_command(hw, &desc, msg, msglen, NULL); |
---|
| 5667 | + |
---|
| 5668 | + if (status) { |
---|
| 5669 | + i40e_debug(hw, I40E_DEBUG_PACKAGE, |
---|
| 5670 | + "unable to exec DDP AQ opcode %u, error %d\n", |
---|
| 5671 | + aq->opcode, status); |
---|
| 5672 | + return status; |
---|
| 5673 | + } |
---|
| 5674 | + |
---|
| 5675 | + /* copy returned desc to aq_buf */ |
---|
| 5676 | + memcpy(aq->param, desc.params.raw, sizeof(desc.params.raw)); |
---|
| 5677 | + |
---|
| 5678 | + return 0; |
---|
| 5679 | +} |
---|
| 5680 | + |
---|
| 5681 | +/** |
---|
| 5682 | + * i40e_validate_profile |
---|
| 5683 | + * @hw: pointer to the hardware structure |
---|
| 5684 | + * @profile: pointer to the profile segment of the package to be validated |
---|
| 5685 | + * @track_id: package tracking id |
---|
| 5686 | + * @rollback: flag if the profile is for rollback. |
---|
| 5687 | + * |
---|
| 5688 | + * Validates supported devices and profile's sections. |
---|
| 5689 | + */ |
---|
| 5690 | +static enum i40e_status_code |
---|
| 5691 | +i40e_validate_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile, |
---|
| 5692 | + u32 track_id, bool rollback) |
---|
| 5693 | +{ |
---|
| 5694 | + struct i40e_profile_section_header *sec = NULL; |
---|
| 5695 | + i40e_status status = 0; |
---|
| 5696 | + struct i40e_section_table *sec_tbl; |
---|
| 5697 | + u32 vendor_dev_id; |
---|
| 5698 | + u32 dev_cnt; |
---|
| 5699 | + u32 sec_off; |
---|
| 5700 | + u32 i; |
---|
| 5701 | + |
---|
| 5702 | + if (track_id == I40E_DDP_TRACKID_INVALID) { |
---|
| 5703 | + i40e_debug(hw, I40E_DEBUG_PACKAGE, "Invalid track_id\n"); |
---|
| 5704 | + return I40E_NOT_SUPPORTED; |
---|
| 5705 | + } |
---|
| 5706 | + |
---|
| 5707 | + dev_cnt = profile->device_table_count; |
---|
| 5708 | + for (i = 0; i < dev_cnt; i++) { |
---|
| 5709 | + vendor_dev_id = profile->device_table[i].vendor_dev_id; |
---|
| 5710 | + if ((vendor_dev_id >> 16) == PCI_VENDOR_ID_INTEL && |
---|
| 5711 | + hw->device_id == (vendor_dev_id & 0xFFFF)) |
---|
| 5712 | + break; |
---|
| 5713 | + } |
---|
| 5714 | + if (dev_cnt && i == dev_cnt) { |
---|
| 5715 | + i40e_debug(hw, I40E_DEBUG_PACKAGE, |
---|
| 5716 | + "Device doesn't support DDP\n"); |
---|
| 5717 | + return I40E_ERR_DEVICE_NOT_SUPPORTED; |
---|
| 5718 | + } |
---|
| 5719 | + |
---|
| 5720 | + I40E_SECTION_TABLE(profile, sec_tbl); |
---|
| 5721 | + |
---|
| 5722 | + /* Validate sections types */ |
---|
| 5723 | + for (i = 0; i < sec_tbl->section_count; i++) { |
---|
| 5724 | + sec_off = sec_tbl->section_offset[i]; |
---|
| 5725 | + sec = I40E_SECTION_HEADER(profile, sec_off); |
---|
| 5726 | + if (rollback) { |
---|
| 5727 | + if (sec->section.type == SECTION_TYPE_MMIO || |
---|
| 5728 | + sec->section.type == SECTION_TYPE_AQ || |
---|
| 5729 | + sec->section.type == SECTION_TYPE_RB_AQ) { |
---|
| 5730 | + i40e_debug(hw, I40E_DEBUG_PACKAGE, |
---|
| 5731 | + "Not a roll-back package\n"); |
---|
| 5732 | + return I40E_NOT_SUPPORTED; |
---|
| 5733 | + } |
---|
| 5734 | + } else { |
---|
| 5735 | + if (sec->section.type == SECTION_TYPE_RB_AQ || |
---|
| 5736 | + sec->section.type == SECTION_TYPE_RB_MMIO) { |
---|
| 5737 | + i40e_debug(hw, I40E_DEBUG_PACKAGE, |
---|
| 5738 | + "Not an original package\n"); |
---|
| 5739 | + return I40E_NOT_SUPPORTED; |
---|
| 5740 | + } |
---|
| 5741 | + } |
---|
| 5742 | + } |
---|
| 5743 | + |
---|
| 5744 | + return status; |
---|
| 5745 | +} |
---|
| 5746 | + |
---|
5478 | 5747 | /** |
---|
5479 | 5748 | * i40e_write_profile |
---|
5480 | 5749 | * @hw: pointer to the hardware structure |
---|
.. | .. |
---|
5490 | 5759 | i40e_status status = 0; |
---|
5491 | 5760 | struct i40e_section_table *sec_tbl; |
---|
5492 | 5761 | struct i40e_profile_section_header *sec = NULL; |
---|
5493 | | - u32 dev_cnt; |
---|
5494 | | - u32 vendor_dev_id; |
---|
5495 | | - u32 *nvm; |
---|
| 5762 | + struct i40e_profile_aq_section *ddp_aq; |
---|
5496 | 5763 | u32 section_size = 0; |
---|
5497 | 5764 | u32 offset = 0, info = 0; |
---|
| 5765 | + u32 sec_off; |
---|
5498 | 5766 | u32 i; |
---|
5499 | 5767 | |
---|
5500 | | - dev_cnt = profile->device_table_count; |
---|
| 5768 | + status = i40e_validate_profile(hw, profile, track_id, false); |
---|
| 5769 | + if (status) |
---|
| 5770 | + return status; |
---|
5501 | 5771 | |
---|
5502 | | - for (i = 0; i < dev_cnt; i++) { |
---|
5503 | | - vendor_dev_id = profile->device_table[i].vendor_dev_id; |
---|
5504 | | - if ((vendor_dev_id >> 16) == PCI_VENDOR_ID_INTEL) |
---|
5505 | | - if (hw->device_id == (vendor_dev_id & 0xFFFF)) |
---|
5506 | | - break; |
---|
5507 | | - } |
---|
5508 | | - if (i == dev_cnt) { |
---|
5509 | | - i40e_debug(hw, I40E_DEBUG_PACKAGE, "Device doesn't support DDP"); |
---|
5510 | | - return I40E_ERR_DEVICE_NOT_SUPPORTED; |
---|
5511 | | - } |
---|
5512 | | - |
---|
5513 | | - nvm = (u32 *)&profile->device_table[dev_cnt]; |
---|
5514 | | - sec_tbl = (struct i40e_section_table *)&nvm[nvm[0] + 1]; |
---|
| 5772 | + I40E_SECTION_TABLE(profile, sec_tbl); |
---|
5515 | 5773 | |
---|
5516 | 5774 | for (i = 0; i < sec_tbl->section_count; i++) { |
---|
5517 | | - sec = (struct i40e_profile_section_header *)((u8 *)profile + |
---|
5518 | | - sec_tbl->section_offset[i]); |
---|
| 5775 | + sec_off = sec_tbl->section_offset[i]; |
---|
| 5776 | + sec = I40E_SECTION_HEADER(profile, sec_off); |
---|
| 5777 | + /* Process generic admin command */ |
---|
| 5778 | + if (sec->section.type == SECTION_TYPE_AQ) { |
---|
| 5779 | + ddp_aq = (struct i40e_profile_aq_section *)&sec[1]; |
---|
| 5780 | + status = i40e_ddp_exec_aq_section(hw, ddp_aq); |
---|
| 5781 | + if (status) { |
---|
| 5782 | + i40e_debug(hw, I40E_DEBUG_PACKAGE, |
---|
| 5783 | + "Failed to execute aq: section %d, opcode %u\n", |
---|
| 5784 | + i, ddp_aq->opcode); |
---|
| 5785 | + break; |
---|
| 5786 | + } |
---|
| 5787 | + sec->section.type = SECTION_TYPE_RB_AQ; |
---|
| 5788 | + } |
---|
5519 | 5789 | |
---|
5520 | | - /* Skip 'AQ', 'note' and 'name' sections */ |
---|
| 5790 | + /* Skip any non-mmio sections */ |
---|
5521 | 5791 | if (sec->section.type != SECTION_TYPE_MMIO) |
---|
5522 | 5792 | continue; |
---|
5523 | 5793 | |
---|
5524 | 5794 | section_size = sec->section.size + |
---|
5525 | 5795 | sizeof(struct i40e_profile_section_header); |
---|
5526 | 5796 | |
---|
5527 | | - /* Write profile */ |
---|
| 5797 | + /* Write MMIO section */ |
---|
5528 | 5798 | status = i40e_aq_write_ddp(hw, (void *)sec, (u16)section_size, |
---|
5529 | 5799 | track_id, &offset, &info, NULL); |
---|
5530 | 5800 | if (status) { |
---|
5531 | 5801 | i40e_debug(hw, I40E_DEBUG_PACKAGE, |
---|
5532 | | - "Failed to write profile: offset %d, info %d", |
---|
5533 | | - offset, info); |
---|
| 5802 | + "Failed to write profile: section %d, offset %d, info %d\n", |
---|
| 5803 | + i, offset, info); |
---|
| 5804 | + break; |
---|
| 5805 | + } |
---|
| 5806 | + } |
---|
| 5807 | + return status; |
---|
| 5808 | +} |
---|
| 5809 | + |
---|
| 5810 | +/** |
---|
| 5811 | + * i40e_rollback_profile |
---|
| 5812 | + * @hw: pointer to the hardware structure |
---|
| 5813 | + * @profile: pointer to the profile segment of the package to be removed |
---|
| 5814 | + * @track_id: package tracking id |
---|
| 5815 | + * |
---|
| 5816 | + * Rolls back previously loaded package. |
---|
| 5817 | + */ |
---|
| 5818 | +enum i40e_status_code |
---|
| 5819 | +i40e_rollback_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile, |
---|
| 5820 | + u32 track_id) |
---|
| 5821 | +{ |
---|
| 5822 | + struct i40e_profile_section_header *sec = NULL; |
---|
| 5823 | + i40e_status status = 0; |
---|
| 5824 | + struct i40e_section_table *sec_tbl; |
---|
| 5825 | + u32 offset = 0, info = 0; |
---|
| 5826 | + u32 section_size = 0; |
---|
| 5827 | + u32 sec_off; |
---|
| 5828 | + int i; |
---|
| 5829 | + |
---|
| 5830 | + status = i40e_validate_profile(hw, profile, track_id, true); |
---|
| 5831 | + if (status) |
---|
| 5832 | + return status; |
---|
| 5833 | + |
---|
| 5834 | + I40E_SECTION_TABLE(profile, sec_tbl); |
---|
| 5835 | + |
---|
| 5836 | + /* For rollback write sections in reverse */ |
---|
| 5837 | + for (i = sec_tbl->section_count - 1; i >= 0; i--) { |
---|
| 5838 | + sec_off = sec_tbl->section_offset[i]; |
---|
| 5839 | + sec = I40E_SECTION_HEADER(profile, sec_off); |
---|
| 5840 | + |
---|
| 5841 | + /* Skip any non-rollback sections */ |
---|
| 5842 | + if (sec->section.type != SECTION_TYPE_RB_MMIO) |
---|
| 5843 | + continue; |
---|
| 5844 | + |
---|
| 5845 | + section_size = sec->section.size + |
---|
| 5846 | + sizeof(struct i40e_profile_section_header); |
---|
| 5847 | + |
---|
| 5848 | + /* Write roll-back MMIO section */ |
---|
| 5849 | + status = i40e_aq_write_ddp(hw, (void *)sec, (u16)section_size, |
---|
| 5850 | + track_id, &offset, &info, NULL); |
---|
| 5851 | + if (status) { |
---|
| 5852 | + i40e_debug(hw, I40E_DEBUG_PACKAGE, |
---|
| 5853 | + "Failed to write profile: section %d, offset %d, info %d\n", |
---|
| 5854 | + i, offset, info); |
---|
5534 | 5855 | break; |
---|
5535 | 5856 | } |
---|
5536 | 5857 | } |
---|