i40e/base: support WOL config for X722
[dpdk.git] / drivers / net / i40e / base / i40e_common.c
index 20bbce1..43ca970 100644 (file)
@@ -70,6 +70,22 @@ STATIC enum i40e_status_code i40e_set_mac_type(struct i40e_hw *hw)
                case I40E_DEV_ID_20G_KR2_A:
                        hw->mac.type = I40E_MAC_XL710;
                        break;
+#ifdef X722_SUPPORT
+#ifdef X722_A0_SUPPORT
+               case I40E_DEV_ID_X722_A0:
+#endif
+               case I40E_DEV_ID_SFP_X722:
+               case I40E_DEV_ID_1G_BASE_T_X722:
+               case I40E_DEV_ID_10G_BASE_T_X722:
+                       hw->mac.type = I40E_MAC_X722;
+                       break;
+#endif
+#ifdef X722_SUPPORT
+               case I40E_DEV_ID_X722_VF:
+               case I40E_DEV_ID_X722_VF_HV:
+                       hw->mac.type = I40E_MAC_X722_VF;
+                       break;
+#endif
                case I40E_DEV_ID_VF:
                case I40E_DEV_ID_VF_HV:
                        hw->mac.type = I40E_MAC_VF;
@@ -371,9 +387,27 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,
 bool i40e_check_asq_alive(struct i40e_hw *hw)
 {
        if (hw->aq.asq.len)
-               return !!(rd32(hw, hw->aq.asq.len) & I40E_PF_ATQLEN_ATQENABLE_MASK);
-       else
-               return false;
+#ifdef PF_DRIVER
+#ifdef INTEGRATED_VF
+               if (!i40e_is_vf(hw))
+                       return !!(rd32(hw, hw->aq.asq.len) &
+                               I40E_PF_ATQLEN_ATQENABLE_MASK);
+#else
+               return !!(rd32(hw, hw->aq.asq.len) &
+                       I40E_PF_ATQLEN_ATQENABLE_MASK);
+#endif /* INTEGRATED_VF */
+#endif /* PF_DRIVER */
+#ifdef VF_DRIVER
+#ifdef INTEGRATED_VF
+               if (i40e_is_vf(hw))
+                       return !!(rd32(hw, hw->aq.asq.len) &
+                               I40E_VF_ATQLEN1_ATQENABLE_MASK);
+#else
+               return !!(rd32(hw, hw->aq.asq.len) &
+                       I40E_VF_ATQLEN1_ATQENABLE_MASK);
+#endif /* INTEGRATED_VF */
+#endif /* VF_DRIVER */
+       return false;
 }
 
 /**
@@ -401,6 +435,166 @@ enum i40e_status_code i40e_aq_queue_shutdown(struct i40e_hw *hw,
 
        return status;
 }
+#ifdef X722_SUPPORT
+
+/**
+ * i40e_aq_get_set_rss_lut
+ * @hw: pointer to the hardware structure
+ * @vsi_id: vsi fw index
+ * @pf_lut: for PF table set true, for VSI table set false
+ * @lut: pointer to the lut buffer provided by the caller
+ * @lut_size: size of the lut buffer
+ * @set: set true to set the table, false to get the table
+ *
+ * Internal function to get or set RSS look up table
+ **/
+STATIC enum i40e_status_code i40e_aq_get_set_rss_lut(struct i40e_hw *hw,
+                                                    u16 vsi_id, bool pf_lut,
+                                                    u8 *lut, u16 lut_size,
+                                                    bool set)
+{
+       enum i40e_status_code status;
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_get_set_rss_lut *cmd_resp =
+                  (struct i40e_aqc_get_set_rss_lut *)&desc.params.raw;
+
+       if (set)
+               i40e_fill_default_direct_cmd_desc(&desc,
+                                                 i40e_aqc_opc_set_rss_lut);
+       else
+               i40e_fill_default_direct_cmd_desc(&desc,
+                                                 i40e_aqc_opc_get_rss_lut);
+
+       /* Indirect command */
+       desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
+       desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
+
+       cmd_resp->vsi_id =
+                       CPU_TO_LE16((u16)((vsi_id <<
+                                         I40E_AQC_SET_RSS_LUT_VSI_ID_SHIFT) &
+                                         I40E_AQC_SET_RSS_LUT_VSI_ID_MASK));
+       cmd_resp->vsi_id |= CPU_TO_LE16((u16)I40E_AQC_SET_RSS_LUT_VSI_VALID);
+
+       if (pf_lut)
+               cmd_resp->flags |= CPU_TO_LE16((u16)
+                                       ((I40E_AQC_SET_RSS_LUT_TABLE_TYPE_PF <<
+                                       I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) &
+                                       I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK));
+       else
+               cmd_resp->flags |= CPU_TO_LE16((u16)
+                                       ((I40E_AQC_SET_RSS_LUT_TABLE_TYPE_VSI <<
+                                       I40E_AQC_SET_RSS_LUT_TABLE_TYPE_SHIFT) &
+                                       I40E_AQC_SET_RSS_LUT_TABLE_TYPE_MASK));
+
+       status = i40e_asq_send_command(hw, &desc, lut, lut_size, NULL);
+
+       return status;
+}
+
+/**
+ * i40e_aq_get_rss_lut
+ * @hw: pointer to the hardware structure
+ * @vsi_id: vsi fw index
+ * @pf_lut: for PF table set true, for VSI table set false
+ * @lut: pointer to the lut buffer provided by the caller
+ * @lut_size: size of the lut buffer
+ *
+ * get the RSS lookup table, PF or VSI type
+ **/
+enum i40e_status_code i40e_aq_get_rss_lut(struct i40e_hw *hw, u16 vsi_id,
+                                         bool pf_lut, u8 *lut, u16 lut_size)
+{
+       return i40e_aq_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size,
+                                      false);
+}
+
+/**
+ * i40e_aq_set_rss_lut
+ * @hw: pointer to the hardware structure
+ * @vsi_id: vsi fw index
+ * @pf_lut: for PF table set true, for VSI table set false
+ * @lut: pointer to the lut buffer provided by the caller
+ * @lut_size: size of the lut buffer
+ *
+ * set the RSS lookup table, PF or VSI type
+ **/
+enum i40e_status_code i40e_aq_set_rss_lut(struct i40e_hw *hw, u16 vsi_id,
+                                         bool pf_lut, u8 *lut, u16 lut_size)
+{
+       return i40e_aq_get_set_rss_lut(hw, vsi_id, pf_lut, lut, lut_size, true);
+}
+
+/**
+ * i40e_aq_get_set_rss_key
+ * @hw: pointer to the hw struct
+ * @vsi_id: vsi fw index
+ * @key: pointer to key info struct
+ * @set: set true to set the key, false to get the key
+ *
+ * get the RSS key per VSI
+ **/
+STATIC enum i40e_status_code i40e_aq_get_set_rss_key(struct i40e_hw *hw,
+                                     u16 vsi_id,
+                                     struct i40e_aqc_get_set_rss_key_data *key,
+                                     bool set)
+{
+       enum i40e_status_code status;
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_get_set_rss_key *cmd_resp =
+                       (struct i40e_aqc_get_set_rss_key *)&desc.params.raw;
+       u16 key_size = sizeof(struct i40e_aqc_get_set_rss_key_data);
+
+       if (set)
+               i40e_fill_default_direct_cmd_desc(&desc,
+                                                 i40e_aqc_opc_set_rss_key);
+       else
+               i40e_fill_default_direct_cmd_desc(&desc,
+                                                 i40e_aqc_opc_get_rss_key);
+
+       /* Indirect command */
+       desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_BUF);
+       desc.flags |= CPU_TO_LE16((u16)I40E_AQ_FLAG_RD);
+
+       cmd_resp->vsi_id =
+                       CPU_TO_LE16((u16)((vsi_id <<
+                                         I40E_AQC_SET_RSS_KEY_VSI_ID_SHIFT) &
+                                         I40E_AQC_SET_RSS_KEY_VSI_ID_MASK));
+       cmd_resp->vsi_id |= CPU_TO_LE16((u16)I40E_AQC_SET_RSS_KEY_VSI_VALID);
+
+       status = i40e_asq_send_command(hw, &desc, key, key_size, NULL);
+
+       return status;
+}
+
+/**
+ * i40e_aq_get_rss_key
+ * @hw: pointer to the hw struct
+ * @vsi_id: vsi fw index
+ * @key: pointer to key info struct
+ *
+ **/
+enum i40e_status_code i40e_aq_get_rss_key(struct i40e_hw *hw,
+                                     u16 vsi_id,
+                                     struct i40e_aqc_get_set_rss_key_data *key)
+{
+       return i40e_aq_get_set_rss_key(hw, vsi_id, key, false);
+}
+
+/**
+ * i40e_aq_set_rss_key
+ * @hw: pointer to the hw struct
+ * @vsi_id: vsi fw index
+ * @key: pointer to key info struct
+ *
+ * set the RSS key per VSI
+ **/
+enum i40e_status_code i40e_aq_set_rss_key(struct i40e_hw *hw,
+                                     u16 vsi_id,
+                                     struct i40e_aqc_get_set_rss_key_data *key)
+{
+       return i40e_aq_get_set_rss_key(hw, vsi_id, key, true);
+}
+#endif /* X722_SUPPORT */
 
 /* The i40e_ptype_lookup table is used to convert from the 8-bit ptype in the
  * hardware to a bit-field that can be used by SW to more easily determine the
@@ -816,6 +1010,9 @@ enum i40e_status_code i40e_init_shared_code(struct i40e_hw *hw)
 
        switch (hw->mac.type) {
        case I40E_MAC_XL710:
+#ifdef X722_SUPPORT
+       case I40E_MAC_X722:
+#endif
                break;
        default:
                return I40E_ERR_DEVICE_NOT_SUPPORTED;
@@ -1084,7 +1281,7 @@ STATIC enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
        return media;
 }
 
-#define I40E_PF_RESET_WAIT_COUNT       110
+#define I40E_PF_RESET_WAIT_COUNT       200
 /**
  * i40e_pf_reset - Reset the PF
  * @hw: pointer to the hardware structure
@@ -1106,7 +1303,11 @@ enum i40e_status_code i40e_pf_reset(struct i40e_hw *hw)
        grst_del = (rd32(hw, I40E_GLGEN_RSTCTL) &
                        I40E_GLGEN_RSTCTL_GRSTDEL_MASK) >>
                        I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT;
-       for (cnt = 0; cnt < grst_del + 2; cnt++) {
+#ifdef I40E_ESS_SUPPORT
+       /* It can take upto 15 secs for GRST steady state */
+       grst_del = grst_del * 20; /* bump it to 16 secs max to be safe */
+#endif
+       for (cnt = 0; cnt < grst_del + 10; cnt++) {
                reg = rd32(hw, I40E_GLGEN_RSTAT);
                if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK))
                        break;
@@ -1393,9 +1594,9 @@ void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink)
                        blink = false;
 
                if (blink)
-                       gpio_val |= (1 << I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT);
+                       gpio_val |= BIT(I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT);
                else
-                       gpio_val &= ~(1 << I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT);
+                       gpio_val &= ~BIT(I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT);
 
                wr32(hw, I40E_GLGEN_GPIO_CTL(i), gpio_val);
                break;
@@ -1447,6 +1648,9 @@ enum i40e_status_code i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
        if (hw->aq.asq_last_status == I40E_AQ_RC_EIO)
                status = I40E_ERR_UNKNOWN_PHY;
 
+       if (report_init)
+               hw->phy.phy_types = LE32_TO_CPU(abilities->phy_type);
+
        return status;
 }
 
@@ -3146,7 +3350,7 @@ i40e_aq_erase_nvm_exit:
 #define I40E_DEV_FUNC_CAP_MSIX_VF      0x44
 #define I40E_DEV_FUNC_CAP_FLOW_DIRECTOR        0x45
 #define I40E_DEV_FUNC_CAP_IEEE_1588    0x46
-#define I40E_DEV_FUNC_CAP_MFP_MODE_1   0xF1
+#define I40E_DEV_FUNC_CAP_FLEX10       0xF1
 #define I40E_DEV_FUNC_CAP_CEM          0xF2
 #define I40E_DEV_FUNC_CAP_IWARP                0x51
 #define I40E_DEV_FUNC_CAP_LED          0x61
@@ -3170,6 +3374,7 @@ STATIC void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
        u32 valid_functions, num_functions;
        u32 number, logical_id, phys_id;
        struct i40e_hw_capabilities *p;
+       u8 major_rev;
        u32 i = 0;
        u16 id;
 
@@ -3187,6 +3392,7 @@ STATIC void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
                number = LE32_TO_CPU(cap->number);
                logical_id = LE32_TO_CPU(cap->logical_id);
                phys_id = LE32_TO_CPU(cap->phys_id);
+               major_rev = cap->major_rev;
 
                switch (id) {
                case I40E_DEV_FUNC_CAP_SWITCH_MODE:
@@ -3261,9 +3467,21 @@ STATIC void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
                case I40E_DEV_FUNC_CAP_MSIX_VF:
                        p->num_msix_vectors_vf = number;
                        break;
-               case I40E_DEV_FUNC_CAP_MFP_MODE_1:
-                       if (number == 1)
-                               p->mfp_mode_1 = true;
+               case I40E_DEV_FUNC_CAP_FLEX10:
+                       if (major_rev == 1) {
+                               if (number == 1) {
+                                       p->flex10_enable = true;
+                                       p->flex10_capable = true;
+                               }
+                       } else {
+                               /* Capability revision >= 2 */
+                               if (number & 1)
+                                       p->flex10_enable = true;
+                               if (number & 2)
+                                       p->flex10_capable = true;
+                       }
+                       p->flex10_mode = logical_id;
+                       p->flex10_status = phys_id;
                        break;
                case I40E_DEV_FUNC_CAP_CEM:
                        if (number == 1)
@@ -3301,11 +3519,14 @@ STATIC void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
                }
        }
 
+       if (p->fcoe)
+               i40e_debug(hw, I40E_DEBUG_ALL, "device is FCoE capable\n");
+
 #ifdef I40E_FCOE_ENA
        /* Software override ensuring FCoE is disabled if npar or mfp
         * mode because it is not supported in these modes.
         */
-       if (p->npar_enable || p->mfp_mode_1)
+       if (p->npar_enable || p->flex10_enable)
                p->fcoe = false;
 #else
        /* Always disable FCoE if compiled without the I40E_FCOE_ENA flag */
@@ -5081,8 +5302,6 @@ enum i40e_status_code i40e_aq_alternate_write_indirect(struct i40e_hw *hw,
 
        cmd_resp->address = CPU_TO_LE32(addr);
        cmd_resp->length = CPU_TO_LE32(dw_count);
-       cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_WORD((u64)buffer));
-       cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)buffer));
 
        status = i40e_asq_send_command(hw, &desc, buffer,
                                       I40E_LO_DWORD(4*dw_count), NULL);
@@ -5164,8 +5383,6 @@ enum i40e_status_code i40e_aq_alternate_read_indirect(struct i40e_hw *hw,
 
        cmd_resp->address = CPU_TO_LE32(addr);
        cmd_resp->length = CPU_TO_LE32(dw_count);
-       cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_DWORD((u64)buffer));
-       cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)buffer));
 
        status = i40e_asq_send_command(hw, &desc, buffer,
                                       I40E_LO_DWORD(4*dw_count), NULL);
@@ -5551,3 +5768,162 @@ enum i40e_status_code i40e_vf_reset(struct i40e_hw *hw)
                                      I40E_SUCCESS, NULL, 0, NULL);
 }
 #endif /* VF_DRIVER */
+#ifdef X722_SUPPORT
+
+/**
+ * i40e_aq_set_arp_proxy_config
+ * @hw: pointer to the HW structure
+ * @proxy_config - pointer to proxy config command table struct
+ * @cmd_details: pointer to command details
+ *
+ * Set ARP offload parameters from pre-populated
+ * i40e_aqc_arp_proxy_data struct
+ **/
+enum i40e_status_code i40e_aq_set_arp_proxy_config(struct i40e_hw *hw,
+                               struct i40e_aqc_arp_proxy_data *proxy_config,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_set_proxy_config *cmd =
+               (struct i40e_aqc_set_proxy_config *) &desc.params.raw;
+       enum i40e_status_code status;
+
+       if (!proxy_config)
+               return I40E_ERR_PARAM;
+
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_proxy_config);
+
+       cmd->address_high = CPU_TO_LE32(I40E_HI_DWORD((u64)proxy_config));
+       cmd->address_low = CPU_TO_LE32(I40E_LO_DWORD((u64)proxy_config));
+
+       status = i40e_asq_send_command(hw, &desc, proxy_config,
+                                      sizeof(struct i40e_aqc_arp_proxy_data),
+                                      cmd_details);
+
+       return status;
+}
+
+/**
+ * i40e_aq_opc_set_ns_proxy_table_entry
+ * @hw: pointer to the HW structure
+ * @ns_proxy_table_entry: pointer to NS table entry command struct
+ * @cmd_details: pointer to command details
+ *
+ * Set IPv6 Neighbor Solicitation (NS) protocol offload parameters
+ * from pre-populated i40e_aqc_ns_proxy_data struct
+ **/
+enum i40e_status_code i40e_aq_set_ns_proxy_table_entry(struct i40e_hw *hw,
+                       struct i40e_aqc_ns_proxy_data *ns_proxy_table_entry,
+                       struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_set_ns_proxy_table_entry *cmd =
+               (struct i40e_aqc_set_ns_proxy_table_entry *) &desc.params.raw;
+       enum i40e_status_code status;
+
+       if (!ns_proxy_table_entry)
+               return I40E_ERR_PARAM;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                               i40e_aqc_opc_set_ns_proxy_table_entry);
+
+       cmd->address_high =
+               CPU_TO_LE32(I40E_HI_DWORD((u64)ns_proxy_table_entry));
+       cmd->address_low =
+               CPU_TO_LE32(I40E_LO_DWORD((u64)ns_proxy_table_entry));
+
+       status = i40e_asq_send_command(hw, &desc, ns_proxy_table_entry,
+                                      sizeof(struct i40e_aqc_ns_proxy_data),
+                                      cmd_details);
+
+       return status;
+}
+
+/**
+ * i40e_aq_set_clear_wol_filter
+ * @hw: pointer to the hw struct
+ * @filter_index: index of filter to modify (0-7)
+ * @filter: buffer containing filter to be set
+ * @set_filter: true to set filter, false to clear filter
+ * @no_wol_tco: if true, pass through packets cannot cause wake-up
+ *             if false, pass through packets may cause wake-up
+ * @filter_valid: true if filter action is valid
+ * @no_wol_tco_valid: true if no WoL in TCO traffic action valid
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Set or clear WoL filter for port attached to the PF
+ **/
+enum i40e_status_code i40e_aq_set_clear_wol_filter(struct i40e_hw *hw,
+                               u8 filter_index,
+                               struct i40e_aqc_set_wol_filter_data *filter,
+                               bool set_filter, bool no_wol_tco,
+                               bool filter_valid, bool no_wol_tco_valid,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_set_wol_filter *cmd =
+               (struct i40e_aqc_set_wol_filter *)&desc.params.raw;
+       enum i40e_status_code status;
+       u16 cmd_flags = 0;
+       u16 valid_flags = 0;
+       u16 buff_len = 0;
+
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_set_wol_filter);
+
+       if (filter_index >= I40E_AQC_MAX_NUM_WOL_FILTERS)
+               return  I40E_ERR_PARAM;
+       cmd->filter_index = CPU_TO_LE16(filter_index);
+
+       if (set_filter) {
+               if (!filter)
+                       return  I40E_ERR_PARAM;
+               cmd_flags |= I40E_AQC_SET_WOL_FILTER;
+               buff_len = sizeof(*filter);
+       }
+       if (no_wol_tco)
+               cmd_flags |= I40E_AQC_SET_WOL_FILTER_NO_TCO_WOL;
+       cmd->cmd_flags = CPU_TO_LE16(cmd_flags);
+
+       if (filter_valid)
+               valid_flags |= I40E_AQC_SET_WOL_FILTER_ACTION_VALID;
+       if (no_wol_tco_valid)
+               valid_flags |= I40E_AQC_SET_WOL_FILTER_NO_TCO_ACTION_VALID;
+       cmd->valid_flags = CPU_TO_LE16(valid_flags);
+
+       cmd->address_high = CPU_TO_LE32(I40E_HI_DWORD((u64)filter));
+       cmd->address_low = CPU_TO_LE32(I40E_LO_DWORD((u64)filter));
+
+       status = i40e_asq_send_command(hw, &desc, filter,
+                                      buff_len, cmd_details);
+
+       return status;
+}
+
+/**
+ * i40e_aq_get_wake_event_reason
+ * @hw: pointer to the hw struct
+ * @wake_reason: return value, index of matching filter
+ * @cmd_details: pointer to command details structure or NULL
+ *
+ * Get information for the reason of a Wake Up event
+ **/
+enum i40e_status_code i40e_aq_get_wake_event_reason(struct i40e_hw *hw,
+                               u16 *wake_reason,
+                               struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_get_wake_reason_completion *resp =
+               (struct i40e_aqc_get_wake_reason_completion *)&desc.params.raw;
+       enum i40e_status_code status;
+
+       i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_wake_reason);
+
+       status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+       if (status == I40E_SUCCESS)
+               *wake_reason = LE16_TO_CPU(resp->wake_reason);
+
+       return status;
+}
+
+#endif /* X722_SUPPORT */