On Wed, 2020-07-01 at 09:25 +0800, Haiyue Wang wrote:
> The PF shall track all the outstanding switch filters (filter IDs to
> be
> precise) added by the DCF.
> 
> Upon a VF reset event, the PF shall clear all outstanding switch
> filters
> for the given VF. Upon completion of either VF or PF reset, the PF
> shall
> skip replay of filters that were added by the DCF. The PF shall
> however
> continue to replay the filters that were not added by DCF for the
> VF(s).
> 
> If the trust mode of the DCF is taken away without the DCF gracefully
> relinquishing the DCF functionality (by way appropriate virtchnl
> message
> exchanges), then the PF shall remove all switch filters that were
> added
> by the DCF. The PF shall transition back from DCF mode to regular
> mode,
> the VF shall be treated as any other untrusted VF, and the PF will
> reset
> the VF.
> 
> If a designated DCF requests AVF functionality from the same VF (VF-
> ID)
> without the DCF gracefully relinquishing the DCF functionality first
> (by
> way appropriate virtchnl message exchanges), the PF shall remove all
> the
> switch filters that were added by the DCF.
> 
> Signed-off-by: Xiao Zhang <xiao.zh...@intel.com>
> Signed-off-by: Beilei Xing <beilei.x...@intel.com>
> Signed-off-by: Haiyue Wang <haiyue.w...@intel.com>
> ---
>  drivers/net/ethernet/intel/ice/ice_dcf.c      | 713
> ++++++++++++++++++
>  drivers/net/ethernet/intel/ice/ice_dcf.h      |  41 +
>  drivers/net/ethernet/intel/ice/ice_switch.c   |  16 +-
>  drivers/net/ethernet/intel/ice/ice_switch.h   |  27 +-
>  drivers/net/ethernet/intel/ice/ice_type.h     |   9 +
>  .../net/ethernet/intel/ice/ice_virtchnl_pf.c  |  40 +
>  6 files changed, 821 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/ice/ice_dcf.c
> b/drivers/net/ethernet/intel/ice/ice_dcf.c
> index e7d37735aaa5..154005f1b634 100644
> --- a/drivers/net/ethernet/intel/ice/ice_dcf.c
> +++ b/drivers/net/ethernet/intel/ice/ice_dcf.c
> @@ -124,3 +124,716 @@ void ice_dcf_set_state(struct ice_pf *pf, enum
> ice_dcf_state state)
>  
>       pf->dcf.state = state;
>  }
> +
> +/**
> + * ice_dcf_rm_sw_rule_to_vsi - remove switch rule of "forward to
> VSI"
> + * @pf: pointer to the PF struct
> + * @s_entry: pointer to switch rule entry to remove
> + */
> +static int
> +ice_dcf_rm_sw_rule_to_vsi(struct ice_pf *pf,
> +                       struct ice_dcf_sw_rule_entry *s_entry)
> +{
> +     struct ice_aqc_sw_rules_elem *s_rule;
> +     enum ice_status status;
> +
> +     s_rule = kzalloc(ICE_SW_RULE_RX_TX_NO_HDR_SIZE, GFP_KERNEL);
> +     if (!s_rule)
> +             return -ENOMEM;
> +
> +     s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX);
> +     s_rule->pdata.lkup_tx_rx.act = 0;
> +     s_rule->pdata.lkup_tx_rx.hdr_len = 0;
> +     s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(s_entry->rule_id);
> +     status = ice_aq_sw_rules(&pf->hw, s_rule,
> ICE_SW_RULE_RX_TX_NO_HDR_SIZE,
> +                              1, ice_aqc_opc_remove_sw_rules, NULL);
> +     kfree(s_rule);
> +     if (status)
> +             return -EIO;
> +
> +     list_del(&s_entry->list_entry);
> +     kfree(s_entry);
> +     return 0;
> +}
> +
> +/**
> + * ice_dcf_rm_sw_rule_to_vsi_list - remove switch rule of "forward
> to VSI list"
> + * @pf: pointer to the PF struct
> + * @s_entry: pointer to switch rule entry to remove
> + */
> +static int
> +ice_dcf_rm_sw_rule_to_vsi_list(struct ice_pf *pf,
> +                            struct ice_dcf_sw_rule_entry *s_entry)
> +{
> +     struct ice_dcf_vsi_list_info *vsi_list_info = s_entry-
> >vsi_list_info;
> +     struct ice_aqc_alloc_free_res_elem *res_buf;
> +     struct ice_aqc_sw_rules_elem *s_rule;
> +     enum ice_status status;
> +     u16 rule_sz;
> +     u16 vsi_id;
> +     int i = 0;
> +
> +     if (!vsi_list_info)
> +             return -EINVAL;
> +
> +     /* The VSI list is empty, it can be freed immediately */
> +     if (!vsi_list_info->vsi_count)
> +             goto free_vsi_list;
> +
> +     rule_sz = ICE_SW_RULE_VSI_LIST_SIZE(vsi_list_info->vsi_count);
> +     s_rule = kzalloc(rule_sz, GFP_KERNEL);
> +     if (!s_rule)
> +             return -ENOMEM;
> +
> +     s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
> +     s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_info-
> >list_id);
> +     s_rule->pdata.vsi_list.number_vsi =
> +                                     cpu_to_le16(vsi_list_info-
> >vsi_count);
> +     for_each_set_bit(vsi_id, vsi_list_info->hw_vsi_map,
> ICE_HW_VSI_ID_MAX)
> +             s_rule->pdata.vsi_list.vsi[i++] = cpu_to_le16(vsi_id);
> +
> +     bitmap_zero(vsi_list_info->hw_vsi_map, ICE_HW_VSI_ID_MAX);
> +     vsi_list_info->vsi_count = 0;
> +
> +     status = ice_aq_sw_rules(&pf->hw, s_rule, rule_sz, 1,
> +                              ice_aqc_opc_update_sw_rules, NULL);
> +     kfree(s_rule);
> +     if (status)
> +             return -EIO;
> +
> +free_vsi_list:
> +     res_buf = kzalloc(sizeof(*res_buf), GFP_KERNEL);
> +     if (!res_buf)
> +             return -ENOMEM;
> +
> +     res_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
> +     res_buf->num_elems = cpu_to_le16(1);
> +     res_buf->elem[0].e.sw_resp = cpu_to_le16(vsi_list_info-
> >list_id);
> +     status = ice_aq_alloc_free_res(&pf->hw, 1, res_buf,
> sizeof(*res_buf),
> +                                    ice_aqc_opc_free_res, NULL);
> +     kfree(res_buf);
> +     if (status)
> +             return -EIO;
> +
> +     list_del(&vsi_list_info->list_entry);
> +     kfree(vsi_list_info);
> +     s_entry->vsi_list_info = NULL;
> +
> +     return ice_dcf_rm_sw_rule_to_vsi(pf, s_entry);
> +}
> +
> +/**
> + * ice_dcf_rm_vsi_from_list - remove VSI from switch rule forward
> VSI list
> + * @pf: pointer to the PF struct
> + * @vsi_list_info: pointer to the VSI list info
> + * @hw_vsi_id: the Hardware VSI number
> + */
> +static int
> +ice_dcf_rm_vsi_from_list(struct ice_pf *pf,
> +                      struct ice_dcf_vsi_list_info *vsi_list_info,
> +                      u16 hw_vsi_id)
> +{
> +     struct ice_aqc_sw_rules_elem *s_rule;
> +     enum ice_status status;
> +
> +     if (!vsi_list_info || !vsi_list_info->vsi_count ||
> +         !test_bit(hw_vsi_id, vsi_list_info->hw_vsi_map))
> +             return -ENOENT;
> +
> +     s_rule = kzalloc(ICE_SW_RULE_VSI_LIST_SIZE(1), GFP_KERNEL);
> +     if (!s_rule)
> +             return -ENOMEM;
> +
> +     s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
> +     s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_info-
> >list_id);
> +     s_rule->pdata.vsi_list.number_vsi = cpu_to_le16(1);
> +     s_rule->pdata.vsi_list.vsi[0] = cpu_to_le16(hw_vsi_id);
> +     status = ice_aq_sw_rules(&pf->hw, s_rule,
> +                              ICE_SW_RULE_VSI_LIST_SIZE(1), 1,
> +                              ice_aqc_opc_update_sw_rules, NULL);
> +     kfree(s_rule);
> +     if (status)
> +             return -EIO;
> +
> +     /* When the VF resets gracefully, it should keep the VSI list
> and its
> +      * rule, just clears the VSI from list, so that the DCF can
> replay the
> +      * rule by updating this VF to list successfully.
> +      */
> +     vsi_list_info->vsi_count--;
> +     clear_bit(hw_vsi_id, vsi_list_info->hw_vsi_map);
> +
> +     return 0;
> +}
> +
> +/**
> + * ice_rm_dcf_sw_vsi_rule - remove switch rules added by DCF to VSI
> + * @pf: pointer to the PF struct
> + * @hw_vsi_id: hardware VSI ID of the VF
> + */
> +void ice_rm_dcf_sw_vsi_rule(struct ice_pf *pf, u16 hw_vsi_id)
> +{
> +     struct ice_dcf_sw_rule_entry *s_entry, *tmp;
> +     int ret;
> +
> +     list_for_each_entry_safe(s_entry, tmp, &pf->dcf.sw_rule_head,
> +                              list_entry)
> +             if (s_entry->fltr_act == ICE_FWD_TO_VSI_LIST) {
> +                     ret = ice_dcf_rm_vsi_from_list(pf,
> +                                                    s_entry-
> >vsi_list_info,
> +                                                    hw_vsi_id);
> +                     if (ret && ret != -ENOENT)
> +                             dev_err(ice_pf_to_dev(pf),
> +                                     "Failed to remove VSI %u from
> VSI list : %d\n",
> +                                     hw_vsi_id, ret);
> +             } else if (s_entry->fwd_id.hw_vsi_id == hw_vsi_id) {
> +                     ret = ice_dcf_rm_sw_rule_to_vsi(pf, s_entry);
> +                     if (ret)
> +                             dev_err(ice_pf_to_dev(pf),
> +                                     "Failed to remove VSI %u switch
> rule : %d\n",
> +                                     hw_vsi_id, ret);
> +             }
> +}
> +
> +/**
> + * ice_dcf_init_sw_rule_mgmt - initializes DCF rule filter mngt
> struct
> + * @pf: pointer to the PF struct
> + */
> +void ice_dcf_init_sw_rule_mgmt(struct ice_pf *pf)
> +{
> +     INIT_LIST_HEAD(&pf->dcf.sw_rule_head);
> +     INIT_LIST_HEAD(&pf->dcf.vsi_list_info_head);
> +}
> +
> +/**
> + * ice_rm_all_dcf_sw_rules - remove switch rules configured by DCF
> + * @pf: pointer to the PF struct
> + */
> +void ice_rm_all_dcf_sw_rules(struct ice_pf *pf)
> +{
> +     struct ice_dcf_vsi_list_info *vsi_list_info, *list_info_tmp;
> +     struct ice_dcf_sw_rule_entry *sw_rule, *rule_tmp;
> +     u16 rule_id, list_id;
> +     int ret;
> +
> +     list_for_each_entry_safe(sw_rule, rule_tmp, &pf-
> >dcf.sw_rule_head,
> +                              list_entry)
> +             if (sw_rule->fltr_act == ICE_FWD_TO_VSI_LIST) {
> +                     list_id = sw_rule->fwd_id.vsi_list_id;
> +                     rule_id = sw_rule->rule_id;
> +                     ret = ice_dcf_rm_sw_rule_to_vsi_list(pf,
> sw_rule);
> +                     if (ret)
> +                             dev_err(ice_pf_to_dev(pf),
> +                                     "Failed to remove switch rule
> 0x%04x with list id %u : %d\n",
> +                                     rule_id, list_id, ret);
> +             } else {
> +                     rule_id = sw_rule->rule_id;
> +                     ret = ice_dcf_rm_sw_rule_to_vsi(pf, sw_rule);
> +                     if (ret)
> +                             dev_err(ice_pf_to_dev(pf),
> +                                     "Failed to remove switch rule
> 0x%04x : %d\n",
> +                                     rule_id, ret);
> +             }
> +
> +     /* clears rule filter management data if AdminQ command has
> error */
> +     list_for_each_entry_safe(vsi_list_info, list_info_tmp,
> +                              &pf->dcf.vsi_list_info_head,
> +                              list_entry) {
> +             list_del(&vsi_list_info->list_entry);
> +             kfree(vsi_list_info);
> +     }
> +
> +     list_for_each_entry_safe(sw_rule, rule_tmp, &pf-
> >dcf.sw_rule_head,
> +                              list_entry) {
> +             list_del(&sw_rule->list_entry);
> +             kfree(sw_rule);
> +     }
> +}
> +
> +/**
> + * ice_dcf_find_vsi_list_info - find the VSI list by ID.
> + * @pf: pointer to the PF info
> + * @vsi_list_id: VSI list ID
> + */
> +static struct ice_dcf_vsi_list_info *
> +ice_dcf_find_vsi_list_info(struct ice_pf *pf, u16 vsi_list_id)
> +{
> +     struct ice_dcf_vsi_list_info *list_info;
> +
> +     list_for_each_entry(list_info, &pf->dcf.vsi_list_info_head,
> list_entry)
> +             if (list_info->list_id == vsi_list_id)
> +                     return list_info;
> +
> +     return NULL;
> +}
> +
> +/**
> + * ice_dcf_add_vsi_id - add new VSI ID into list.
> + * @vsi_list_info: pointer to the VSI list info
> + * @hw_vsi_id: the VSI ID
> + */
> +static void
> +ice_dcf_add_vsi_id(struct ice_dcf_vsi_list_info *vsi_list_info, u16
> hw_vsi_id)
> +{
> +     if (!test_and_set_bit(hw_vsi_id, vsi_list_info->hw_vsi_map))
> +             vsi_list_info->vsi_count++;
> +}
> +
> +/**
> + * ice_dcf_del_vsi_id - delete the VSI ID from list.
> + * @vsi_list_info: pointer to the VSI list info
> + * @hw_vsi_id: the VSI ID
> + */
> +static void
> +ice_dcf_del_vsi_id(struct ice_dcf_vsi_list_info *vsi_list_info, u16
> hw_vsi_id)
> +{
> +     if (test_and_clear_bit(hw_vsi_id, vsi_list_info->hw_vsi_map))
> +             vsi_list_info->vsi_count--;
> +}
> +
> +/**
> + * ice_dcf_parse_alloc_vsi_list_res - parse the allocate VSI list
> resource
> + * @pf: pointer to the PF info
> + * @res: pointer to the VSI list resource
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_alloc_vsi_list_res(struct ice_pf *pf,
> +                              struct ice_aqc_res_elem *res)
> +{
> +     struct ice_dcf_vsi_list_info *vsi_list_info;
> +     u16 list_id = le16_to_cpu(res->e.sw_resp);
> +
> +     vsi_list_info = ice_dcf_find_vsi_list_info(pf, list_id);
> +     if (vsi_list_info)
> +             return VIRTCHNL_STATUS_SUCCESS;
> +
> +     vsi_list_info = kzalloc(sizeof(*vsi_list_info), GFP_KERNEL);
> +     if (!vsi_list_info)
> +             return VIRTCHNL_STATUS_ERR_NO_MEMORY;
> +
> +     vsi_list_info->list_id = list_id;
> +     list_add(&vsi_list_info->list_entry, &pf-
> >dcf.vsi_list_info_head);
> +
> +     return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_parse_free_vsi_list_res - parse the free VSI list
> resource
> + * @pf: pointer to the PF info
> + * @res: pointer to the VSI list resource
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_free_vsi_list_res(struct ice_pf *pf,
> +                             struct ice_aqc_res_elem *res)
> +{
> +     struct ice_dcf_vsi_list_info *vsi_list_info;
> +     u16 list_id = le16_to_cpu(res->e.sw_resp);
> +
> +     vsi_list_info = ice_dcf_find_vsi_list_info(pf, list_id);
> +     if (!vsi_list_info)
> +             return VIRTCHNL_STATUS_ERR_PARAM;
> +
> +     if (vsi_list_info->vsi_count)
> +             dev_warn(ice_pf_to_dev(pf),
> +                      "VSI list %u still has %u VSIs to be
> removed!\n",
> +                      list_id, vsi_list_info->vsi_count);
> +
> +     if (vsi_list_info->sw_rule)
> +             vsi_list_info->sw_rule->vsi_list_info = NULL;
> +
> +     list_del(&vsi_list_info->list_entry);
> +     kfree(vsi_list_info);
> +
> +     return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_set_vsi_list - set the VSI to VSI list
> + * @pf: pointer to the PF info
> + * @vsi_list: pointer to the VSI ID list to be set
> + */
> +static enum virtchnl_status_code
> +ice_dcf_set_vsi_list(struct ice_pf *pf, struct ice_sw_rule_vsi_list
> *vsi_list)
> +{
> +     struct ice_dcf_vsi_list_info *vsi_list_info;
> +     int i;
> +
> +     vsi_list_info =
> +             ice_dcf_find_vsi_list_info(pf, le16_to_cpu(vsi_list-
> >index));
> +     if (!vsi_list_info)
> +             return VIRTCHNL_STATUS_ERR_PARAM;
> +
> +     for (i = 0; i < le16_to_cpu(vsi_list->number_vsi); i++)
> +             ice_dcf_add_vsi_id(vsi_list_info,
> +                                le16_to_cpu(vsi_list->vsi[i]));
> +
> +     return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_clear_vsi_list - clear the VSI from VSI list
> + * @pf: pointer to the PF info
> + * @vsi_list: pointer to the VSI ID list to be cleared
> + */
> +static enum virtchnl_status_code
> +ice_dcf_clear_vsi_list(struct ice_pf *pf, struct
> ice_sw_rule_vsi_list *vsi_list)
> +{
> +     struct ice_dcf_vsi_list_info *vsi_list_info;
> +     int i;
> +
> +     vsi_list_info =
> +             ice_dcf_find_vsi_list_info(pf, le16_to_cpu(vsi_list-
> >index));
> +     if (!vsi_list_info)
> +             return VIRTCHNL_STATUS_ERR_PARAM;
> +
> +     for (i = 0; i < le16_to_cpu(vsi_list->number_vsi); i++)
> +             ice_dcf_del_vsi_id(vsi_list_info,
> +                                le16_to_cpu(vsi_list->vsi[i]));
> +
> +     return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_find_sw_rule - find the switch rule by ID.
> + * @pf: pointer to the PF info
> + * @rule_id: switch rule ID
> + */
> +static struct ice_dcf_sw_rule_entry *
> +ice_dcf_find_sw_rule(struct ice_pf *pf, u16 rule_id)
> +{
> +     struct ice_dcf_sw_rule_entry *sw_rule;
> +
> +     list_for_each_entry(sw_rule, &pf->dcf.sw_rule_head, list_entry)
> +             if (sw_rule->rule_id == rule_id)
> +                     return sw_rule;
> +
> +     return NULL;
> +}
> +
> +/**
> + * ice_dcf_parse_add_sw_rule_data - parse the add switch rule data
> + * @pf: pointer to the PF info
> + * @lkup: pointer to the add switch rule data
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_add_sw_rule_data(struct ice_pf *pf,
> +                            struct ice_sw_rule_lkup_rx_tx *lkup)
> +{
> +     struct ice_dcf_sw_rule_entry *sw_rule;
> +     u32 act;
> +
> +     sw_rule = kzalloc(sizeof(*sw_rule), GFP_KERNEL);
> +     if (!sw_rule)
> +             return VIRTCHNL_STATUS_ERR_NO_MEMORY;
> +
> +     act = le32_to_cpu(lkup->act);
> +     sw_rule->fltr_act = ICE_FWD_TO_VSI;
> +     sw_rule->fwd_id.hw_vsi_id = (act & ICE_SINGLE_ACT_VSI_ID_M) >>
> +                                     ICE_SINGLE_ACT_VSI_ID_S;
> +     sw_rule->rule_id = le16_to_cpu(lkup->index);
> +
> +     list_add(&sw_rule->list_entry, &pf->dcf.sw_rule_head);
> +
> +     return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_parse_updt_sw_rule_data - parse the update switch rule
> data
> + * @pf: pointer to the PF info
> + * @lkup: pointer to the update switch rule data
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_updt_sw_rule_data(struct ice_pf *pf,
> +                             struct ice_sw_rule_lkup_rx_tx *lkup)
> +{
> +     struct ice_dcf_vsi_list_info *vsi_list_info;
> +     struct ice_dcf_sw_rule_entry *sw_rule;
> +     u16 vsi_list_id, rule_id;
> +     u32 act;
> +
> +     rule_id = le16_to_cpu(lkup->index);
> +     sw_rule = ice_dcf_find_sw_rule(pf, rule_id);
> +     if (!sw_rule)
> +             return VIRTCHNL_STATUS_ERR_PARAM;
> +
> +     act = le32_to_cpu(lkup->act);
> +     if (!(act & ICE_SINGLE_ACT_VSI_LIST)) {
> +             u16 vsi_hw_id = (act & ICE_SINGLE_ACT_VSI_ID_M) >>
> +                             ICE_SINGLE_ACT_VSI_ID_S;
> +
> +             sw_rule->fltr_act = ICE_FWD_TO_VSI;
> +             sw_rule->fwd_id.hw_vsi_id = vsi_hw_id;
> +
> +             return VIRTCHNL_STATUS_SUCCESS;
> +     }
> +
> +     vsi_list_id = (act & ICE_SINGLE_ACT_VSI_LIST_ID_M) >>
> +                             ICE_SINGLE_ACT_VSI_LIST_ID_S;
> +     if (sw_rule->vsi_list_info) {
> +             if (sw_rule->vsi_list_info->list_id == vsi_list_id)
> +                     return VIRTCHNL_STATUS_SUCCESS;
> +
> +             dev_err(ice_pf_to_dev(pf),
> +                     "The switch rule 0x%04x is running on VSI list
> %u\n",
> +                     rule_id, sw_rule->vsi_list_info->list_id);
> +             return VIRTCHNL_STATUS_ERR_PARAM;
> +     }
> +
> +     vsi_list_info = ice_dcf_find_vsi_list_info(pf, vsi_list_id);
> +     if (!vsi_list_info) {
> +             dev_err(ice_pf_to_dev(pf),
> +                     "No VSI list %u found to bind the switch rule
> 0x%04x\n",
> +                     vsi_list_id, rule_id);
> +             return VIRTCHNL_STATUS_ERR_PARAM;
> +     }
> +
> +     if (vsi_list_info->sw_rule) {
> +             if (vsi_list_info->sw_rule->rule_id == rule_id)
> +                     return VIRTCHNL_STATUS_SUCCESS;
> +
> +             dev_err(ice_pf_to_dev(pf),
> +                     "The VSI list %u is running on switch rule
> 0x%04x\n",
> +                     vsi_list_id, vsi_list_info->sw_rule->rule_id);
> +             return VIRTCHNL_STATUS_ERR_PARAM;
> +     }
> +
> +     vsi_list_info->sw_rule = sw_rule;
> +
> +     sw_rule->fltr_act = ICE_FWD_TO_VSI_LIST;
> +     sw_rule->fwd_id.vsi_list_id = vsi_list_id;
> +     sw_rule->vsi_list_info = vsi_list_info;
> +
> +     return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_parse_rm_sw_rule_data - parse the remove switch rule data
> + * @pf: pointer to the PF info
> + * @lkup: pointer to the remove switch rule data
> + */
> +static enum virtchnl_status_code
> +ice_dcf_parse_rm_sw_rule_data(struct ice_pf *pf,
> +                           struct ice_sw_rule_lkup_rx_tx *lkup)
> +{
> +     struct ice_dcf_sw_rule_entry *sw_rule, *tmp;
> +     u16 rule_id = le16_to_cpu(lkup->index);
> +
> +     list_for_each_entry_safe(sw_rule, tmp, &pf->dcf.sw_rule_head,
> +                              list_entry)
> +             if (sw_rule->rule_id == rule_id) {
> +                     list_del(&sw_rule->list_entry);
> +                     kfree(sw_rule);
> +             }
> +
> +     return VIRTCHNL_STATUS_SUCCESS;
> +}
> +
> +/**
> + * ice_dcf_handle_add_sw_rule_rsp - handle the add switch rule
> response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the add switch rule command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_add_sw_rule_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +     enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +     struct ice_aqc_sw_rules_elem *em =
> +                     (struct ice_aqc_sw_rules_elem *)aq_buf;
> +     u16 type = le16_to_cpu(em->type);
> +
> +     if (type == ICE_AQC_SW_RULES_T_VSI_LIST_SET)
> +             status = ice_dcf_set_vsi_list(pf, &em->pdata.vsi_list);
> +     else if (type == ICE_AQC_SW_RULES_T_LKUP_RX)
> +             status = ice_dcf_parse_add_sw_rule_data(pf,
> +                                                     &em-
> >pdata.lkup_tx_rx);
> +
> +     return status;
> +}
> +
> +/**
> + * ice_dcf_handle_updt_sw_rule_rsp - handle the update switch rule
> response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the update switch rule command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_updt_sw_rule_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +     enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +     struct ice_aqc_sw_rules_elem *em =
> +                     (struct ice_aqc_sw_rules_elem *)aq_buf;
> +     u16 type = le16_to_cpu(em->type);
> +
> +     if (type == ICE_AQC_SW_RULES_T_VSI_LIST_SET)
> +             status = ice_dcf_set_vsi_list(pf, &em->pdata.vsi_list);
> +     else if (type == ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR)
> +             status = ice_dcf_clear_vsi_list(pf, &em-
> >pdata.vsi_list);
> +     else if (type == ICE_AQC_SW_RULES_T_LKUP_RX)
> +             status = ice_dcf_parse_updt_sw_rule_data(pf,
> +                                                      &em-
> >pdata.lkup_tx_rx);
> +
> +     return status;
> +}
> +
> +/**
> + * ice_dcf_handle_rm_sw_rule_rsp - handle the remove switch rule
> response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the remove switch rule command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_rm_sw_rule_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +     enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +     struct ice_aqc_sw_rules_elem *em =
> +                     (struct ice_aqc_sw_rules_elem *)aq_buf;
> +     u16 type = le16_to_cpu(em->type);
> +
> +     if (type == ICE_AQC_SW_RULES_T_LKUP_RX)
> +             status = ice_dcf_parse_rm_sw_rule_data(pf,
> +                                                    &em-
> >pdata.lkup_tx_rx);
> +
> +     return status;
> +}
> +
> +/**
> + * ice_dcf_handle_alloc_res_rsp - handle the allocate resource
> response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the allocate resource command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_alloc_res_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +     enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +     struct ice_aqc_alloc_free_res_elem *res_buf =
> +              (struct ice_aqc_alloc_free_res_elem *)aq_buf;
> +     u16 type = (le16_to_cpu(res_buf->res_type) &
> +                 ICE_AQC_RES_TYPE_M) >> ICE_AQC_RES_TYPE_S;
> +
> +     if (type == ICE_AQC_RES_TYPE_VSI_LIST_REP)
> +             status = ice_dcf_parse_alloc_vsi_list_res(pf,
> +                                                       &res_buf-
> >elem[0]);
> +
> +     return status;
> +}
> +
> +/**
> + * ice_dcf_handle_free_res_rsp - handle the free resource response
> + * @pf: pointer to the PF info
> + * @aq_buf: pointer to the free resource command buffer
> + */
> +static enum virtchnl_status_code
> +ice_dcf_handle_free_res_rsp(struct ice_pf *pf, u8 *aq_buf)
> +{
> +     enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +     struct ice_aqc_alloc_free_res_elem *res_buf =
> +              (struct ice_aqc_alloc_free_res_elem *)aq_buf;
> +     u16 type = (le16_to_cpu(res_buf->res_type) &
> +                 ICE_AQC_RES_TYPE_M) >> ICE_AQC_RES_TYPE_S;
> +
> +     if (type == ICE_AQC_RES_TYPE_VSI_LIST_REP)
> +             status = ice_dcf_parse_free_vsi_list_res(pf,
> +                                                      &res_buf-
> >elem[0]);
> +
> +     return status;
> +}
> +
> +/**
> + * ice_dcf_post_aq_send_cmd - get the data from firmware successful
> response
> + * @pf: pointer to the PF info
> + * @aq_desc: descriptor describing the command
> + * @aq_buf: the AdminQ command buffer
> + */
> +enum virtchnl_status_code
> +ice_dcf_post_aq_send_cmd(struct ice_pf *pf, struct ice_aq_desc
> *aq_desc,
> +                      u8 *aq_buf)
> +{
> +     enum virtchnl_status_code status = VIRTCHNL_STATUS_SUCCESS;
> +     u16 opc = le16_to_cpu(aq_desc->opcode);
> +
> +     if (!aq_buf)
> +             return VIRTCHNL_STATUS_SUCCESS;
> +
> +     if (opc == ice_aqc_opc_add_sw_rules)
> +             status = ice_dcf_handle_add_sw_rule_rsp(pf, aq_buf);
> +     else if (opc == ice_aqc_opc_update_sw_rules)
> +             status = ice_dcf_handle_updt_sw_rule_rsp(pf, aq_buf);
> +     else if (opc == ice_aqc_opc_remove_sw_rules)
> +             status = ice_dcf_handle_rm_sw_rule_rsp(pf, aq_buf);
> +     else if (opc == ice_aqc_opc_alloc_res)
> +             status = ice_dcf_handle_alloc_res_rsp(pf, aq_buf);
> +     else if (opc == ice_aqc_opc_free_res)
> +             status = ice_dcf_handle_free_res_rsp(pf, aq_buf);
> +
> +     return status;
> +}
> +
> +/**
> + * ice_dcf_pre_aq_send_cmd - check if it needs to send the command
> to firmware
> + * @vf: pointer to the VF info
> + * @aq_desc: descriptor describing the command
> + * @aq_buf: the AdminQ command buffer
> + * @aq_buf_size: the AdminQ command buffer size
> + */
> +bool
> +ice_dcf_pre_aq_send_cmd(struct ice_vf *vf, struct ice_aq_desc
> *aq_desc,
> +                     u8 *aq_buf, u16 aq_buf_size)
> +{
> +     struct ice_pf *pf = vf->pf;
> +
> +     switch (le16_to_cpu(aq_desc->opcode)) {
> +     case ice_aqc_opc_update_sw_rules:
> +     {
> +             struct ice_dcf_vsi_list_info *vsi_list_info;
> +             struct ice_aqc_sw_rules_elem *s_rule;
> +             u16 list_id, vsi_id;
> +
> +             if (aq_buf_size < ICE_SW_RULE_VSI_LIST_SIZE(1))
> +                     break;
> +
> +             s_rule = (struct ice_aqc_sw_rules_elem *)aq_buf;
> +             if (le16_to_cpu(s_rule->type) !=
> +                                     ICE_AQC_SW_RULES_T_VSI_LIST_CLE
> AR ||
> +                 le16_to_cpu(s_rule->pdata.vsi_list.number_vsi) !=
> 1)
> +                     break;
> +
> +             list_id = le16_to_cpu(s_rule->pdata.vsi_list.index);
> +             vsi_list_info = ice_dcf_find_vsi_list_info(pf,
> list_id);
> +             if (!vsi_list_info)
> +                     break;
> +
> +             vsi_id = le16_to_cpu(s_rule->pdata.vsi_list.vsi[0]);
> +             if (vsi_id >= ICE_HW_VSI_ID_MAX ||
> +                 test_bit(vsi_id, vsi_list_info->hw_vsi_map))
> +                     break;
> +
> +             /* The VSI is removed from list already, no need to
> send the
> +              * command to firmware.
> +              */
> +             return true;
> +     }
> +     case ice_aqc_opc_remove_sw_rules:
> +     {
> +             struct ice_aqc_sw_rules_elem *s_rule;
> +             u16 rule_id;
> +
> +             if (aq_buf_size < ICE_SW_RULE_RX_TX_NO_HDR_SIZE)
> +                     break;
> +
> +             s_rule = (struct ice_aqc_sw_rules_elem *)aq_buf;
> +             if (le16_to_cpu(s_rule->type) !=
> ICE_AQC_SW_RULES_T_LKUP_RX)
> +                     break;
> +
> +             rule_id = le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
> +             if (ice_dcf_find_sw_rule(pf, rule_id))
> +                     break;
> +
> +             /* The switch rule is removed already, no need to send
> the
> +              * command to firmware.
> +              */
> +             return true;
> +     }
> +
> +     default:
> +             break;
> +     }
> +
> +     return false;
> +}
> diff --git a/drivers/net/ethernet/intel/ice/ice_dcf.h
> b/drivers/net/ethernet/intel/ice/ice_dcf.h
> index 1ca228f89a19..23842db0a884 100644
> --- a/drivers/net/ethernet/intel/ice/ice_dcf.h
> +++ b/drivers/net/ethernet/intel/ice/ice_dcf.h
> @@ -21,10 +21,42 @@ enum ice_dcf_state {
>       ICE_DCF_STATE_PAUSE,
>  };
>  
> +struct ice_dcf_sw_rule_entry;
> +
> +#define ICE_HW_VSI_ID_MAX    BIT(10) /* The AQ VSI number uses 10
> bits */
> +
> +struct ice_dcf_vsi_list_info {
> +     struct list_head list_entry;
> +     struct ice_dcf_sw_rule_entry *sw_rule;
> +     u16 list_id;
> +
> +     u16 vsi_count;
> +     DECLARE_BITMAP(hw_vsi_map, ICE_HW_VSI_ID_MAX);
> +};
> +
> +struct ice_dcf_sw_rule_entry {
> +     struct list_head list_entry;
> +     u16 rule_id;
> +
> +     /* Only support ICE_FWD_TO_VSI and ICE_FWD_TO_VSI_LIST */
> +     enum ice_sw_fwd_act_type fltr_act;
> +     /* Depending on filter action */
> +     union {
> +             u16 hw_vsi_id:10;
> +             u16 vsi_list_id:10;
> +     } fwd_id;
> +
> +     struct ice_dcf_vsi_list_info *vsi_list_info;
> +};
> +
>  struct ice_dcf {
>       struct ice_vf *vf;
>       enum ice_dcf_state state;
>  
> +     /* Trace the switch rules added/removed by DCF */
> +     struct list_head sw_rule_head;
> +     struct list_head vsi_list_info_head;
> +
>       /* Handle the AdminQ command between the DCF (Device Config
> Function)
>        * and the firmware.
>        */
> @@ -46,5 +78,14 @@ bool ice_check_dcf_allowed(struct ice_vf *vf);
>  bool ice_is_vf_dcf(struct ice_vf *vf);
>  enum ice_dcf_state ice_dcf_get_state(struct ice_pf *pf);
>  void ice_dcf_set_state(struct ice_pf *pf, enum ice_dcf_state state);
> +void ice_dcf_init_sw_rule_mgmt(struct ice_pf *pf);
> +void ice_rm_all_dcf_sw_rules(struct ice_pf *pf);
> +void ice_rm_dcf_sw_vsi_rule(struct ice_pf *pf, u16 hw_vsi_id);
> +bool
> +ice_dcf_pre_aq_send_cmd(struct ice_vf *vf, struct ice_aq_desc
> *aq_desc,
> +                     u8 *aq_buf, u16 aq_buf_size);
> +enum virtchnl_status_code
> +ice_dcf_post_aq_send_cmd(struct ice_pf *pf, struct ice_aq_desc
> *aq_desc,
> +                      u8 *aq_buf);
>  #endif /* CONFIG_PCI_IOV */
>  #endif /* _ICE_DCF_H_ */
> diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c
> b/drivers/net/ethernet/intel/ice/ice_switch.c
> index ccbe1cc64295..ee434b8d794d 100644
> --- a/drivers/net/ethernet/intel/ice/ice_switch.c
> +++ b/drivers/net/ethernet/intel/ice/ice_switch.c
> @@ -23,24 +23,10 @@
>   *   In case of Ether type filter it is treated as header without
> VLAN tag
>   *   and byte 12 and 13 is used to program a given Ether type
> instead
>   */
> -#define DUMMY_ETH_HDR_LEN            16
>  static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0,
> 0, 0, 0,
>                                                       0x2, 0, 0, 0,
> 0, 0,
>                                                       0x81, 0, 0, 0};
>  
> -#define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \
> -     (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) +
> \
> -      (DUMMY_ETH_HDR_LEN * \
> -       sizeof(((struct ice_sw_rule_lkup_rx_tx *)0)->hdr[0])))
> -#define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \
> -     (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr))
> -#define ICE_SW_RULE_LG_ACT_SIZE(n) \
> -     (offsetof(struct ice_aqc_sw_rules_elem, pdata.lg_act.act) + \
> -      ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act[0])))
> -#define ICE_SW_RULE_VSI_LIST_SIZE(n) \
> -     (offsetof(struct ice_aqc_sw_rules_elem, pdata.vsi_list.vsi) + \
> -      ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi[0])))
> -
>  /**
>   * ice_init_def_sw_recp - initialize the recipe book keeping tables
>   * @hw: pointer to the HW struct
> @@ -490,7 +476,7 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16
> *vsi_list_id,
>   *
>   * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands
> to firmware
>   */
> -static enum ice_status
> +enum ice_status
>  ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16
> rule_list_sz,
>               u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd
> *cd)
>  {

Hi Dave, Jakub,

This feature is only built when CONFIG_PCI_IOV is set. We end up with
this namespace issue using defconfig when checked against namespace.pl
since CONFIG_PCI_IOV is not enabled.
        Externally defined symbols with no external references
          ice_switch.o
            ice_aq_sw_rules

From a previous patch, neither of you liked the use of CONFIG_ to
control static-ness. I wanted to check that you are ok with the
namespace issue or if you have a preferred method to resolve this
issue. I appreciate your feedback.

Thanks,
Tony

Reply via email to