net/i40e/base: support LLDP agent
[dpdk.git] / drivers / net / i40e / base / i40e_common.c
index 0affa98..8ebf8b8 100644 (file)
@@ -35,10 +35,13 @@ STATIC enum i40e_status_code i40e_set_mac_type(struct i40e_hw *hw)
                case I40E_DEV_ID_QSFP_C:
                case I40E_DEV_ID_10G_BASE_T:
                case I40E_DEV_ID_10G_BASE_T4:
+               case I40E_DEV_ID_10G_BASE_T_BC:
                case I40E_DEV_ID_20G_KR2:
                case I40E_DEV_ID_20G_KR2_A:
                case I40E_DEV_ID_25G_B:
                case I40E_DEV_ID_25G_SFP28:
+               case I40E_DEV_ID_X710_N3000:
+               case I40E_DEV_ID_XXV710_N3000:
                        hw->mac.type = I40E_MAC_XL710;
                        break;
 #ifdef X722_A0_SUPPORT
@@ -1011,6 +1014,17 @@ enum i40e_status_code i40e_init_shared_code(struct i40e_hw *hw)
        if (hw->mac.type == I40E_MAC_X722)
                hw->flags |= I40E_HW_FLAG_AQ_SRCTL_ACCESS_ENABLE |
                             I40E_HW_FLAG_NVM_READ_REQUIRES_LOCK;
+       /* NVMUpdate features structure initialization */
+       hw->nvmupd_features.major = I40E_NVMUPD_FEATURES_API_VER_MAJOR;
+       hw->nvmupd_features.minor = I40E_NVMUPD_FEATURES_API_VER_MINOR;
+       hw->nvmupd_features.size = sizeof(hw->nvmupd_features);
+       i40e_memset(hw->nvmupd_features.features, 0x0,
+                   I40E_NVMUPD_FEATURES_API_FEATURES_ARRAY_LEN *
+                   sizeof(*hw->nvmupd_features.features),
+                   I40E_NONDMA_MEM);
+
+       /* No features supported at the moment */
+       hw->nvmupd_features.features[0] = 0;
 
        status = i40e_init_nvm(hw);
        return status;
@@ -1260,6 +1274,8 @@ STATIC enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
                break;
        case I40E_PHY_TYPE_100BASE_TX:
        case I40E_PHY_TYPE_1000BASE_T:
+       case I40E_PHY_TYPE_2_5GBASE_T:
+       case I40E_PHY_TYPE_5GBASE_T:
        case I40E_PHY_TYPE_10GBASE_T:
                media = I40E_MEDIA_TYPE_BASET;
                break;
@@ -1342,7 +1358,7 @@ enum i40e_status_code i40e_pf_reset(struct i40e_hw *hw)
                        I40E_GLGEN_RSTCTL_GRSTDEL_MASK) >>
                        I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT;
 
-       grst_del = grst_del * 20;
+       grst_del = min(grst_del * 20, 160U);
 
        for (cnt = 0; cnt < grst_del; cnt++) {
                reg = rd32(hw, I40E_GLGEN_RSTAT);
@@ -1876,6 +1892,10 @@ enum i40e_status_code i40e_aq_set_mac_config(struct i40e_hw *hw,
        if (crc_en)
                cmd->params |= I40E_AQ_SET_MAC_CONFIG_CRC_EN;
 
+#define I40E_AQ_SET_MAC_CONFIG_FC_DEFAULT_THRESHOLD    0x7FFF
+       cmd->fc_refresh_threshold =
+               CPU_TO_LE16(I40E_AQ_SET_MAC_CONFIG_FC_DEFAULT_THRESHOLD);
+
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
        return status;
@@ -4147,6 +4167,43 @@ i40e_aq_update_nvm_exit:
        return status;
 }
 
+/**
+ * i40e_aq_rearrange_nvm
+ * @hw: pointer to the hw struct
+ * @rearrange_nvm: defines direction of rearrangement
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Rearrange NVM structure, available only for transition FW
+ **/
+enum i40e_status_code i40e_aq_rearrange_nvm(struct i40e_hw *hw,
+                               u8 rearrange_nvm,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aqc_nvm_update *cmd;
+       enum i40e_status_code status;
+       struct i40e_aq_desc desc;
+
+       DEBUGFUNC("i40e_aq_rearrange_nvm");
+
+       cmd = (struct i40e_aqc_nvm_update *)&desc.params.raw;
+
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_update);
+
+       rearrange_nvm &= (I40E_AQ_NVM_REARRANGE_TO_FLAT |
+                        I40E_AQ_NVM_REARRANGE_TO_STRUCT);
+
+       if (!rearrange_nvm) {
+               status = I40E_ERR_PARAM;
+               goto i40e_aq_rearrange_nvm_exit;
+       }
+
+       cmd->command_flags |= rearrange_nvm;
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+i40e_aq_rearrange_nvm_exit:
+       return status;
+}
+
 /**
  * i40e_aq_nvm_progress
  * @hw: pointer to the hw struct
@@ -4254,7 +4311,7 @@ enum i40e_status_code i40e_aq_set_lldp_mib(struct i40e_hw *hw,
 
        cmd->type = mib_type;
        cmd->length = CPU_TO_LE16(buff_size);
-       cmd->address_high = CPU_TO_LE32(I40E_HI_WORD((u64)buff));
+       cmd->address_high = CPU_TO_LE32(I40E_HI_DWORD((u64)buff));
        cmd->address_low =  CPU_TO_LE32(I40E_LO_DWORD((u64)buff));
 
        status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
@@ -4290,151 +4347,39 @@ enum i40e_status_code i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw,
 }
 
 /**
- * i40e_aq_add_lldp_tlv
- * @hw: pointer to the hw struct
- * @bridge_type: type of bridge
- * @buff: buffer with TLV to add
- * @buff_size: length of the buffer
- * @tlv_len: length of the TLV to be added
- * @mib_len: length of the LLDP MIB returned in response
- * @cmd_details: pointer to command details structure or NULL
- *
- * Add the specified TLV to LLDP Local MIB for the given bridge type,
- * it is responsibility of the caller to make sure that the TLV is not
- * already present in the LLDPDU.
- * In return firmware will write the complete LLDP MIB with the newly
- * added TLV in the response buffer.
- **/
-enum i40e_status_code i40e_aq_add_lldp_tlv(struct i40e_hw *hw, u8 bridge_type,
-                               void *buff, u16 buff_size, u16 tlv_len,
-                               u16 *mib_len,
-                               struct i40e_asq_cmd_details *cmd_details)
-{
-       struct i40e_aq_desc desc;
-       struct i40e_aqc_lldp_add_tlv *cmd =
-               (struct i40e_aqc_lldp_add_tlv *)&desc.params.raw;
-       enum i40e_status_code status;
-
-       if (buff_size == 0 || !buff || tlv_len == 0)
-               return I40E_ERR_PARAM;
-
-       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_add_tlv);
-
-       /* Indirect Command */
-       desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
-       if (buff_size > I40E_AQ_LARGE_BUF)
-               desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
-       desc.datalen = CPU_TO_LE16(buff_size);
-
-       cmd->type = ((bridge_type << I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) &
-                     I40E_AQ_LLDP_BRIDGE_TYPE_MASK);
-       cmd->len = CPU_TO_LE16(tlv_len);
-
-       status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
-       if (!status) {
-               if (mib_len != NULL)
-                       *mib_len = LE16_TO_CPU(desc.datalen);
-       }
-
-       return status;
-}
-
-/**
- * i40e_aq_update_lldp_tlv
+ * i40e_aq_restore_lldp
  * @hw: pointer to the hw struct
- * @bridge_type: type of bridge
- * @buff: buffer with TLV to update
- * @buff_size: size of the buffer holding original and updated TLVs
- * @old_len: Length of the Original TLV
- * @new_len: Length of the Updated TLV
- * @offset: offset of the updated TLV in the buff
- * @mib_len: length of the returned LLDP MIB
+ * @setting: pointer to factory setting variable or NULL
+ * @restore: True if factory settings should be restored
  * @cmd_details: pointer to command details structure or NULL
  *
- * Update the specified TLV to the LLDP Local MIB for the given bridge type.
- * Firmware will place the complete LLDP MIB in response buffer with the
- * updated TLV.
+ * Restore LLDP Agent factory settings if @restore set to True. In other case
+ * only returns factory setting in AQ response.
  **/
-enum i40e_status_code i40e_aq_update_lldp_tlv(struct i40e_hw *hw,
-                               u8 bridge_type, void *buff, u16 buff_size,
-                               u16 old_len, u16 new_len, u16 offset,
-                               u16 *mib_len,
-                               struct i40e_asq_cmd_details *cmd_details)
+enum i40e_status_code
+i40e_aq_restore_lldp(struct i40e_hw *hw, u8 *setting, bool restore,
+                    struct i40e_asq_cmd_details *cmd_details)
 {
        struct i40e_aq_desc desc;
-       struct i40e_aqc_lldp_update_tlv *cmd =
-               (struct i40e_aqc_lldp_update_tlv *)&desc.params.raw;
+       struct i40e_aqc_lldp_restore *cmd =
+               (struct i40e_aqc_lldp_restore *)&desc.params.raw;
        enum i40e_status_code status;
 
-       if (buff_size == 0 || !buff || offset == 0 ||
-           old_len == 0 || new_len == 0)
-               return I40E_ERR_PARAM;
-
-       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_update_tlv);
-
-       /* Indirect Command */
-       desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
-       if (buff_size > I40E_AQ_LARGE_BUF)
-               desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
-       desc.datalen = CPU_TO_LE16(buff_size);
-
-       cmd->type = ((bridge_type << I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) &
-                     I40E_AQ_LLDP_BRIDGE_TYPE_MASK);
-       cmd->old_len = CPU_TO_LE16(old_len);
-       cmd->new_offset = CPU_TO_LE16(offset);
-       cmd->new_len = CPU_TO_LE16(new_len);
-
-       status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
-       if (!status) {
-               if (mib_len != NULL)
-                       *mib_len = LE16_TO_CPU(desc.datalen);
+       if (!(hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)) {
+               i40e_debug(hw, I40E_DEBUG_ALL,
+                          "Restore LLDP not supported by current FW version.\n");
+               return I40E_ERR_DEVICE_NOT_SUPPORTED;
        }
 
-       return status;
-}
-
-/**
- * i40e_aq_delete_lldp_tlv
- * @hw: pointer to the hw struct
- * @bridge_type: type of bridge
- * @buff: pointer to a user supplied buffer that has the TLV
- * @buff_size: length of the buffer
- * @tlv_len: length of the TLV to be deleted
- * @mib_len: length of the returned LLDP MIB
- * @cmd_details: pointer to command details structure or NULL
- *
- * Delete the specified TLV from LLDP Local MIB for the given bridge type.
- * The firmware places the entire LLDP MIB in the response buffer.
- **/
-enum i40e_status_code i40e_aq_delete_lldp_tlv(struct i40e_hw *hw,
-                               u8 bridge_type, void *buff, u16 buff_size,
-                               u16 tlv_len, u16 *mib_len,
-                               struct i40e_asq_cmd_details *cmd_details)
-{
-       struct i40e_aq_desc desc;
-       struct i40e_aqc_lldp_add_tlv *cmd =
-               (struct i40e_aqc_lldp_add_tlv *)&desc.params.raw;
-       enum i40e_status_code status;
-
-       if (buff_size == 0 || !buff)
-               return I40E_ERR_PARAM;
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_restore);
 
-       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_delete_tlv);
+       if (restore)
+               cmd->command |= I40E_AQ_LLDP_AGENT_RESTORE;
 
-       /* Indirect Command */
-       desc.flags |= CPU_TO_LE16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD));
-       if (buff_size > I40E_AQ_LARGE_BUF)
-               desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_LB);
-       desc.datalen = CPU_TO_LE16(buff_size);
-       cmd->len = CPU_TO_LE16(tlv_len);
-       cmd->type = ((bridge_type << I40E_AQ_LLDP_BRIDGE_TYPE_SHIFT) &
-                     I40E_AQ_LLDP_BRIDGE_TYPE_MASK);
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
-       status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
-       if (!status) {
-               if (mib_len != NULL)
-                       *mib_len = LE16_TO_CPU(desc.datalen);
-       }
+       if (setting)
+               *setting = cmd->command & 1;
 
        return status;
 }
@@ -4443,11 +4388,13 @@ enum i40e_status_code i40e_aq_delete_lldp_tlv(struct i40e_hw *hw,
  * i40e_aq_stop_lldp
  * @hw: pointer to the hw struct
  * @shutdown_agent: True if LLDP Agent needs to be Shutdown
+ * @persist: True if stop of LLDP should be persistent across power cycles
  * @cmd_details: pointer to command details structure or NULL
  *
  * Stop or Shutdown the embedded LLDP Agent
  **/
 enum i40e_status_code i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
+                               bool persist,
                                struct i40e_asq_cmd_details *cmd_details)
 {
        struct i40e_aq_desc desc;
@@ -4460,6 +4407,14 @@ enum i40e_status_code i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
        if (shutdown_agent)
                cmd->command |= I40E_AQ_LLDP_AGENT_SHUTDOWN;
 
+       if (persist) {
+               if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)
+                       cmd->command |= I40E_AQ_LLDP_AGENT_STOP_PERSIST;
+               else
+                       i40e_debug(hw, I40E_DEBUG_ALL,
+                                  "Persistent Stop LLDP not supported by current FW version.\n");
+       }
+
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
        return status;
@@ -4468,11 +4423,13 @@ enum i40e_status_code i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
 /**
  * i40e_aq_start_lldp
  * @hw: pointer to the hw struct
+ * @persist: True if start of LLDP should be persistent across power cycles
  * @cmd_details: pointer to command details structure or NULL
  *
  * Start the embedded LLDP Agent on all ports.
  **/
 enum i40e_status_code i40e_aq_start_lldp(struct i40e_hw *hw,
+                               bool persist,
                                struct i40e_asq_cmd_details *cmd_details)
 {
        struct i40e_aq_desc desc;
@@ -4483,6 +4440,15 @@ enum i40e_status_code i40e_aq_start_lldp(struct i40e_hw *hw,
        i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_start);
 
        cmd->command = I40E_AQ_LLDP_AGENT_START;
+
+       if (persist) {
+               if (hw->flags & I40E_HW_FLAG_FW_LLDP_PERSISTENT)
+                       cmd->command |= I40E_AQ_LLDP_AGENT_START_PERSIST;
+               else
+                       i40e_debug(hw, I40E_DEBUG_ALL,
+                                  "Persistent Start LLDP not supported by current FW version.\n");
+       }
+
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
        return status;
@@ -4504,6 +4470,9 @@ i40e_aq_set_dcb_parameters(struct i40e_hw *hw, bool dcb_enable,
                (struct i40e_aqc_set_dcb_parameters *)&desc.params.raw;
        enum i40e_status_code status;
 
+       if (!(hw->flags & I40E_HW_FLAG_FW_LLDP_STOPPABLE))
+               return I40E_ERR_DEVICE_NOT_SUPPORTED;
+
        i40e_fill_default_direct_cmd_desc(&desc,
                                          i40e_aqc_opc_set_dcb_parameters);
 
@@ -5939,6 +5908,14 @@ i40e_status_code i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
        enum i40e_status_code status = I40E_SUCCESS;
        int i = 0;
 
+       /* X722 doesn't support this command */
+       if (hw->mac.type == I40E_MAC_X722)
+               return I40E_ERR_DEVICE_NOT_SUPPORTED;
+
+       /* need FW version greater than 6.00 */
+       if (hw->aq.fw_maj_ver < 6)
+               return I40E_NOT_SUPPORTED;
+
        i40e_fill_default_direct_cmd_desc(&desc,
                                          i40e_aqc_opc_replace_cloud_filters);
 
@@ -5948,6 +5925,7 @@ i40e_status_code i40e_aq_replace_cloud_filters(struct i40e_hw *hw,
        cmd->new_filter_type = filters->new_filter_type;
        cmd->valid_flags = filters->valid_flags;
        cmd->tr_bit = filters->tr_bit;
+       cmd->tr_bit2 = filters->tr_bit2;
 
        status = i40e_asq_send_command(hw, &desc, cmd_buf,
                sizeof(struct i40e_aqc_replace_cloud_filters_cmd_buf),  NULL);
@@ -6641,6 +6619,7 @@ enum i40e_status_code i40e_write_phy_register(struct i40e_hw *hw,
                break;
        case I40E_DEV_ID_10G_BASE_T:
        case I40E_DEV_ID_10G_BASE_T4:
+       case I40E_DEV_ID_10G_BASE_T_BC:
        case I40E_DEV_ID_10G_BASE_T_X722:
        case I40E_DEV_ID_25G_B:
        case I40E_DEV_ID_25G_SFP28:
@@ -6796,7 +6775,7 @@ static enum i40e_status_code i40e_led_get_reg(struct i40e_hw *hw, u16 led_addr,
        if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
                status = i40e_aq_get_phy_register(hw,
                                                I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
-                                               I40E_PHY_COM_REG_PAGE,
+                                               I40E_PHY_COM_REG_PAGE, true,
                                                I40E_PHY_LED_PROV_REG_1,
                                                reg_val, NULL);
        } else {
@@ -6824,7 +6803,7 @@ static enum i40e_status_code i40e_led_set_reg(struct i40e_hw *hw, u16 led_addr,
        if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
                status = i40e_aq_set_phy_register(hw,
                                                I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
-                                               I40E_PHY_COM_REG_PAGE,
+                                               I40E_PHY_COM_REG_PAGE, true,
                                                I40E_PHY_LED_PROV_REG_1,
                                                reg_val, NULL);
        } else {
@@ -6858,7 +6837,7 @@ enum i40e_status_code i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
        if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
                status = i40e_aq_get_phy_register(hw,
                                                I40E_AQ_PHY_REG_ACCESS_EXTERNAL,
-                                               I40E_PHY_COM_REG_PAGE,
+                                               I40E_PHY_COM_REG_PAGE, true,
                                                I40E_PHY_LED_PROV_REG_1,
                                                &reg_val_aq, NULL);
                if (status == I40E_SUCCESS)
@@ -7059,11 +7038,13 @@ do_retry:
                wr32(hw, reg_addr, reg_val);
 }
 
+#ifdef PF_DRIVER
 /**
  * i40e_aq_set_phy_register
  * @hw: pointer to the hw struct
  * @phy_select: select which phy should be accessed
  * @dev_addr: PHY device address
+ * @page_change: enable auto page change
  * @reg_addr: PHY register address
  * @reg_val: new register value
  * @cmd_details: pointer to command details structure or NULL
@@ -7071,7 +7052,7 @@ do_retry:
  * Write the external PHY register.
  **/
 enum i40e_status_code i40e_aq_set_phy_register(struct i40e_hw *hw,
-                               u8 phy_select, u8 dev_addr,
+                               u8 phy_select, u8 dev_addr, bool page_change,
                                u32 reg_addr, u32 reg_val,
                                struct i40e_asq_cmd_details *cmd_details)
 {
@@ -7088,6 +7069,9 @@ enum i40e_status_code i40e_aq_set_phy_register(struct i40e_hw *hw,
        cmd->reg_address = CPU_TO_LE32(reg_addr);
        cmd->reg_value = CPU_TO_LE32(reg_val);
 
+       if (!page_change)
+               cmd->cmd_flags = I40E_AQ_PHY_REG_ACCESS_DONT_CHANGE_QSFP_PAGE;
+
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
 
        return status;
@@ -7098,6 +7082,7 @@ enum i40e_status_code i40e_aq_set_phy_register(struct i40e_hw *hw,
  * @hw: pointer to the hw struct
  * @phy_select: select which phy should be accessed
  * @dev_addr: PHY device address
+ * @page_change: enable auto page change
  * @reg_addr: PHY register address
  * @reg_val: read register value
  * @cmd_details: pointer to command details structure or NULL
@@ -7105,7 +7090,7 @@ enum i40e_status_code i40e_aq_set_phy_register(struct i40e_hw *hw,
  * Read the external PHY register.
  **/
 enum i40e_status_code i40e_aq_get_phy_register(struct i40e_hw *hw,
-                               u8 phy_select, u8 dev_addr,
+                               u8 phy_select, u8 dev_addr, bool page_change,
                                u32 reg_addr, u32 *reg_val,
                                struct i40e_asq_cmd_details *cmd_details)
 {
@@ -7121,6 +7106,9 @@ enum i40e_status_code i40e_aq_get_phy_register(struct i40e_hw *hw,
        cmd->dev_addres = dev_addr;
        cmd->reg_address = CPU_TO_LE32(reg_addr);
 
+       if (!page_change)
+               cmd->cmd_flags = I40E_AQ_PHY_REG_ACCESS_DONT_CHANGE_QSFP_PAGE;
+
        status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
        if (!status)
                *reg_val = LE32_TO_CPU(cmd->reg_value);
@@ -7128,6 +7116,7 @@ enum i40e_status_code i40e_aq_get_phy_register(struct i40e_hw *hw,
        return status;
 }
 
+#endif /* PF_DRIVER */
 #ifdef VF_DRIVER
 
 /**