hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/net/ethernet/intel/i40e/i40e_common.c
....@@ -1,6 +1,7 @@
11 // SPDX-License-Identifier: GPL-2.0
22 /* Copyright(c) 2013 - 2018 Intel Corporation. */
33
4
+#include "i40e.h"
45 #include "i40e_type.h"
56 #include "i40e_adminq.h"
67 #include "i40e_prototype.h"
....@@ -13,7 +14,7 @@
1314 * This function sets the mac type of the adapter based on the
1415 * vendor ID and device ID stored in the hw structure.
1516 **/
16
-static i40e_status i40e_set_mac_type(struct i40e_hw *hw)
17
+i40e_status i40e_set_mac_type(struct i40e_hw *hw)
1718 {
1819 i40e_status status = 0;
1920
....@@ -26,12 +27,18 @@
2627 case I40E_DEV_ID_QSFP_A:
2728 case I40E_DEV_ID_QSFP_B:
2829 case I40E_DEV_ID_QSFP_C:
30
+ case I40E_DEV_ID_5G_BASE_T_BC:
2931 case I40E_DEV_ID_10G_BASE_T:
3032 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:
3136 case I40E_DEV_ID_20G_KR2:
3237 case I40E_DEV_ID_20G_KR2_A:
3338 case I40E_DEV_ID_25G_B:
3439 case I40E_DEV_ID_25G_SFP28:
40
+ case I40E_DEV_ID_X710_N3000:
41
+ case I40E_DEV_ID_XXV710_N3000:
3542 hw->mac.type = I40E_MAC_XL710;
3643 break;
3744 case I40E_DEV_ID_KX_X722:
....@@ -277,47 +284,49 @@
277284 void *buffer, u16 buf_len)
278285 {
279286 struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc;
287
+ u32 effective_mask = hw->debug_mask & mask;
288
+ char prefix[27];
280289 u16 len;
281290 u8 *buf = (u8 *)buffer;
282291
283
- if ((!(mask & hw->debug_mask)) || (desc == NULL))
292
+ if (!effective_mask || !desc)
284293 return;
285294
286295 len = le16_to_cpu(aq_desc->datalen);
287296
288
- i40e_debug(hw, mask,
297
+ i40e_debug(hw, mask & I40E_DEBUG_AQ_DESCRIPTOR,
289298 "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
290299 le16_to_cpu(aq_desc->opcode),
291300 le16_to_cpu(aq_desc->flags),
292301 le16_to_cpu(aq_desc->datalen),
293302 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",
295305 le32_to_cpu(aq_desc->cookie_high),
296306 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",
298309 le32_to_cpu(aq_desc->params.internal.param0),
299310 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",
301313 le32_to_cpu(aq_desc->params.external.addr_high),
302314 le32_to_cpu(aq_desc->params.external.addr_low));
303315
304
- if ((buffer != NULL) && (aq_desc->datalen != 0)) {
316
+ if (buffer && buf_len != 0 && len != 0 &&
317
+ (effective_mask & I40E_DEBUG_AQ_DESC_BUFFER)) {
305318 i40e_debug(hw, mask, "AQ CMD Buffer:\n");
306319 if (buf_len < len)
307320 len = buf_len;
308
- /* write the full 16-byte chunks */
309
- if (hw->debug_mask & mask) {
310
- char prefix[27];
311321
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);
317327
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);
321330 }
322331 }
323332
....@@ -926,10 +935,6 @@
926935 else
927936 hw->pf_id = (u8)(func_rid & 0x7);
928937
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
-
933938 status = i40e_init_nvm(hw);
934939 return status;
935940 }
....@@ -1109,7 +1114,7 @@
11091114 */
11101115 pba_size--;
11111116 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");
11131118 return I40E_ERR_PARAM;
11141119 }
11151120
....@@ -1149,6 +1154,8 @@
11491154 break;
11501155 case I40E_PHY_TYPE_100BASE_TX:
11511156 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:
11521159 case I40E_PHY_TYPE_10GBASE_T:
11531160 media = I40E_MEDIA_TYPE_BASET;
11541161 break;
....@@ -1432,9 +1439,9 @@
14321439 u32 gpio_val = 0;
14331440 u32 port;
14341441
1435
- if (!hw->func_caps.led[idx])
1442
+ if (!I40E_IS_X710TL_DEVICE(hw->device_id) &&
1443
+ !hw->func_caps.led[idx])
14361444 return 0;
1437
-
14381445 gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx));
14391446 port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >>
14401447 I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
....@@ -1449,11 +1456,14 @@
14491456 return gpio_val;
14501457 }
14511458
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
+
14561463 #define I40E_LED0 22
1464
+
1465
+#define I40E_PIN_FUNC_SDP 0x0
1466
+#define I40E_PIN_FUNC_LED 0x1
14571467
14581468 /**
14591469 * i40e_led_get - return current on/off mode
....@@ -1466,7 +1476,6 @@
14661476 **/
14671477 u32 i40e_led_get(struct i40e_hw *hw)
14681478 {
1469
- u32 current_mode = 0;
14701479 u32 mode = 0;
14711480 int i;
14721481
....@@ -1478,21 +1487,6 @@
14781487
14791488 if (!gpio_val)
14801489 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
- }
14961490
14971491 mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) >>
14981492 I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT;
....@@ -1513,11 +1507,12 @@
15131507 **/
15141508 void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink)
15151509 {
1516
- u32 current_mode = 0;
15171510 int i;
15181511
1519
- if (mode & 0xfffffff0)
1512
+ if (mode & ~I40E_LED_MODE_VALID) {
15201513 hw_dbg(hw, "invalid mode passed in %X\n", mode);
1514
+ return;
1515
+ }
15211516
15221517 /* as per the documentation GPIO 22-29 are the LED
15231518 * GPIO pins named LED0..LED7
....@@ -1528,21 +1523,19 @@
15281523 if (!gpio_val)
15291524 continue;
15301525
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;
15451528
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
+ }
15461539 gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;
15471540 /* this & is a bit of paranoia, but serves as a range check */
15481541 gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) &
....@@ -1602,19 +1595,22 @@
16021595 status = i40e_asq_send_command(hw, &desc, abilities,
16031596 abilities_size, cmd_details);
16041597
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:
16091600 status = I40E_ERR_UNKNOWN_PHY;
16101601 break;
1611
- } else if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN) {
1602
+ case I40E_AQ_RC_EAGAIN:
16121603 usleep_range(1000, 2000);
16131604 total_delay++;
16141605 status = I40E_ERR_TIMEOUT;
1606
+ break;
1607
+ /* also covers I40E_AQ_RC_OK */
1608
+ default:
1609
+ break;
16151610 }
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));
16181614
16191615 if (status)
16201616 return status;
....@@ -1897,8 +1893,8 @@
18971893 hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
18981894 hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
18991895
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) {
19021898 __le32 tmp;
19031899
19041900 memcpy(&tmp, resp->link_type, sizeof(tmp));
....@@ -2611,9 +2607,16 @@
26112607 if (status)
26122608 return status;
26132609
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);
26172620
26182621 memcpy(hw->phy.link_info.module_type, &abilities.module_type,
26192622 sizeof(hw->phy.link_info.module_type));
....@@ -3687,14 +3690,54 @@
36873690 }
36883691
36893692 /**
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
+/**
36903731 * i40e_aq_stop_lldp
36913732 * @hw: pointer to the hw struct
36923733 * @shutdown_agent: True if LLDP Agent needs to be Shutdown
3734
+ * @persist: True if stop of LLDP should be persistent across power cycles
36933735 * @cmd_details: pointer to command details structure or NULL
36943736 *
36953737 * Stop or Shutdown the embedded LLDP Agent
36963738 **/
36973739 i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
3740
+ bool persist,
36983741 struct i40e_asq_cmd_details *cmd_details)
36993742 {
37003743 struct i40e_aq_desc desc;
....@@ -3707,6 +3750,14 @@
37073750 if (shutdown_agent)
37083751 cmd->command |= I40E_AQ_LLDP_AGENT_SHUTDOWN;
37093752
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
+
37103761 status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
37113762
37123763 return status;
....@@ -3715,14 +3766,13 @@
37153766 /**
37163767 * i40e_aq_start_lldp
37173768 * @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
37203770 * @cmd_details: pointer to command details structure or NULL
37213771 *
37223772 * Start the embedded LLDP Agent on all ports.
37233773 **/
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)
37263776 {
37273777 struct i40e_aq_desc desc;
37283778 struct i40e_aqc_lldp_start *cmd =
....@@ -3732,6 +3782,15 @@
37323782 i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_start);
37333783
37343784 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
+
37353794 status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
37363795
37373796 return status;
....@@ -3752,6 +3811,9 @@
37523811 struct i40e_aqc_set_dcb_parameters *cmd =
37533812 (struct i40e_aqc_set_dcb_parameters *)&desc.params.raw;
37543813 i40e_status status;
3814
+
3815
+ if (!(hw->flags & I40E_HW_FLAG_FW_LLDP_STOPPABLE))
3816
+ return I40E_ERR_DEVICE_NOT_SUPPORTED;
37553817
37563818 i40e_fill_default_direct_cmd_desc(&desc,
37573819 i40e_aqc_opc_set_dcb_parameters);
....@@ -4862,8 +4924,10 @@
48624924 status = i40e_write_phy_register_clause22(hw, reg, phy_addr,
48634925 value);
48644926 break;
4927
+ case I40E_DEV_ID_5G_BASE_T_BC:
48654928 case I40E_DEV_ID_10G_BASE_T:
48664929 case I40E_DEV_ID_10G_BASE_T4:
4930
+ case I40E_DEV_ID_10G_BASE_T_BC:
48674931 case I40E_DEV_ID_10G_BASE_T_X722:
48684932 case I40E_DEV_ID_25G_B:
48694933 case I40E_DEV_ID_25G_SFP28:
....@@ -4898,8 +4962,10 @@
48984962 status = i40e_read_phy_register_clause22(hw, reg, phy_addr,
48994963 value);
49004964 break;
4965
+ case I40E_DEV_ID_5G_BASE_T_BC:
49014966 case I40E_DEV_ID_10G_BASE_T:
49024967 case I40E_DEV_ID_10G_BASE_T4:
4968
+ case I40E_DEV_ID_10G_BASE_T_BC:
49034969 case I40E_DEV_ID_10G_BASE_T_X722:
49044970 case I40E_DEV_ID_25G_B:
49054971 case I40E_DEV_ID_25G_SFP28:
....@@ -5022,7 +5088,7 @@
50225088 status =
50235089 i40e_aq_get_phy_register(hw,
50245090 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
5025
- I40E_PHY_COM_REG_PAGE,
5091
+ I40E_PHY_COM_REG_PAGE, true,
50265092 I40E_PHY_LED_PROV_REG_1,
50275093 reg_val, NULL);
50285094 } else {
....@@ -5055,7 +5121,7 @@
50555121 status =
50565122 i40e_aq_set_phy_register(hw,
50575123 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
5058
- I40E_PHY_COM_REG_PAGE,
5124
+ I40E_PHY_COM_REG_PAGE, true,
50595125 I40E_PHY_LED_PROV_REG_1,
50605126 reg_val, NULL);
50615127 } else {
....@@ -5094,7 +5160,7 @@
50945160 status =
50955161 i40e_aq_get_phy_register(hw,
50965162 I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
5097
- I40E_PHY_COM_REG_PAGE,
5163
+ I40E_PHY_COM_REG_PAGE, true,
50985164 I40E_PHY_LED_PROV_REG_1,
50995165 &reg_val_aq, NULL);
51005166 if (status == I40E_SUCCESS)
....@@ -5299,20 +5365,50 @@
52995365 }
53005366
53015367 /**
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
53035393 * @hw: pointer to the hw struct
53045394 * @phy_select: select which phy should be accessed
53055395 * @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
53065399 * @reg_addr: PHY register address
53075400 * @reg_val: new register value
53085401 * @cmd_details: pointer to command details structure or NULL
53095402 *
53105403 * 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.
53115406 **/
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)
53165412 {
53175413 struct i40e_aq_desc desc;
53185414 struct i40e_aqc_phy_register_access *cmd =
....@@ -5327,26 +5423,37 @@
53275423 cmd->reg_address = cpu_to_le32(reg_addr);
53285424 cmd->reg_value = cpu_to_le32(reg_val);
53295425
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
+
53305431 status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
53315432
53325433 return status;
53335434 }
53345435
53355436 /**
5336
- * i40e_aq_get_phy_register
5437
+ * i40e_aq_get_phy_register_ext
53375438 * @hw: pointer to the hw struct
53385439 * @phy_select: select which phy should be accessed
53395440 * @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
53405444 * @reg_addr: PHY register address
53415445 * @reg_val: read register value
53425446 * @cmd_details: pointer to command details structure or NULL
53435447 *
53445448 * 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.
53455451 **/
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)
53505457 {
53515458 struct i40e_aq_desc desc;
53525459 struct i40e_aqc_phy_register_access *cmd =
....@@ -5359,6 +5466,11 @@
53595466 cmd->phy_interface = phy_select;
53605467 cmd->dev_address = dev_addr;
53615468 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;
53625474
53635475 status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
53645476 if (!status)
....@@ -5475,6 +5587,163 @@
54755587 return NULL;
54765588 }
54775589
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
+
54785747 /**
54795748 * i40e_write_profile
54805749 * @hw: pointer to the hardware structure
....@@ -5490,47 +5759,99 @@
54905759 i40e_status status = 0;
54915760 struct i40e_section_table *sec_tbl;
54925761 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;
54965763 u32 section_size = 0;
54975764 u32 offset = 0, info = 0;
5765
+ u32 sec_off;
54985766 u32 i;
54995767
5500
- dev_cnt = profile->device_table_count;
5768
+ status = i40e_validate_profile(hw, profile, track_id, false);
5769
+ if (status)
5770
+ return status;
55015771
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);
55155773
55165774 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
+ }
55195789
5520
- /* Skip 'AQ', 'note' and 'name' sections */
5790
+ /* Skip any non-mmio sections */
55215791 if (sec->section.type != SECTION_TYPE_MMIO)
55225792 continue;
55235793
55245794 section_size = sec->section.size +
55255795 sizeof(struct i40e_profile_section_header);
55265796
5527
- /* Write profile */
5797
+ /* Write MMIO section */
55285798 status = i40e_aq_write_ddp(hw, (void *)sec, (u16)section_size,
55295799 track_id, &offset, &info, NULL);
55305800 if (status) {
55315801 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);
55345855 break;
55355856 }
55365857 }