Skip to content

Commit

Permalink
ice: allow process VF opcodes in different ways
Browse files Browse the repository at this point in the history
In switchdev driver shouldn't add MAC, VLAN and promisc
filters on iavf demand but should return success to not
break normal iavf flow.

Achieve that by creating table of functions pointer with
default functions used to parse iavf command. While parse
iavf command, call correct function from table instead of
calling function direct.

When port representors are being created change functions
in table to new one that behaves correctly for switchdev
puprose (ignoring new filters).

Change back to default ops when representors are being
removed.

Co-developed-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Wojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Tested-by: Sandeep Penigalapati <sandeep.penigalapati@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
  • Loading branch information
Michal Swiatkowski authored and Tony Nguyen committed Oct 7, 2021
1 parent 37165e3 commit ac19e03
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 37 deletions.
23 changes: 18 additions & 5 deletions drivers/net/ethernet/intel/ice/ice_repr.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,15 +228,24 @@ int ice_repr_add_for_all_vfs(struct ice_pf *pf)
int i;

ice_for_each_vf(pf, i) {
err = ice_repr_add(&pf->vf[i]);
struct ice_vf *vf = &pf->vf[i];

err = ice_repr_add(vf);
if (err)
goto err;

ice_vc_change_ops_to_repr(&vf->vc_ops);
}

return 0;

err:
for (i = i - 1; i >= 0; i--)
ice_repr_rem(&pf->vf[i]);
for (i = i - 1; i >= 0; i--) {
struct ice_vf *vf = &pf->vf[i];

ice_repr_rem(vf);
ice_vc_set_dflt_vf_ops(&vf->vc_ops);
}

return err;
}
Expand All @@ -249,6 +258,10 @@ void ice_repr_rem_from_all_vfs(struct ice_pf *pf)
{
int i;

ice_for_each_vf(pf, i)
ice_repr_rem(&pf->vf[i]);
ice_for_each_vf(pf, i) {
struct ice_vf *vf = &pf->vf[i];

ice_repr_rem(vf);
ice_vc_set_dflt_vf_ops(&vf->vc_ops);
}
}
207 changes: 175 additions & 32 deletions drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,8 @@ static void ice_set_dflt_settings_vfs(struct ice_pf *pf)
*/
ice_vf_ctrl_invalidate_vsi(vf);
ice_vf_fdir_init(vf);

ice_vc_set_dflt_vf_ops(&vf->vc_ops);
}
}

Expand Down Expand Up @@ -3801,6 +3803,26 @@ static bool ice_is_legacy_umac_expired(struct ice_time_mac *last_added_umac)
ICE_LEGACY_VF_MAC_CHANGE_EXPIRE_TIME);
}

/**
* ice_update_legacy_cached_mac - update cached hardware MAC for legacy VF
* @vf: VF to update
* @vc_ether_addr: structure from VIRTCHNL with MAC to check
*
* only update cached hardware MAC for legacy VF drivers on delete
* because we cannot guarantee order/type of MAC from the VF driver
*/
static void
ice_update_legacy_cached_mac(struct ice_vf *vf,
struct virtchnl_ether_addr *vc_ether_addr)
{
if (!ice_is_vc_addr_legacy(vc_ether_addr) ||
ice_is_legacy_umac_expired(&vf->legacy_last_added_umac))
return;

ether_addr_copy(vf->dev_lan_addr.addr, vf->legacy_last_added_umac.addr);
ether_addr_copy(vf->hw_lan_addr.addr, vf->legacy_last_added_umac.addr);
}

/**
* ice_vfhw_mac_del - update the VF's cached hardware MAC if allowed
* @vf: VF to update
Expand All @@ -3822,16 +3844,7 @@ ice_vfhw_mac_del(struct ice_vf *vf, struct virtchnl_ether_addr *vc_ether_addr)
*/
eth_zero_addr(vf->dev_lan_addr.addr);

/* only update cached hardware MAC for legacy VF drivers on delete
* because we cannot guarantee order/type of MAC from the VF driver
*/
if (ice_is_vc_addr_legacy(vc_ether_addr) &&
!ice_is_legacy_umac_expired(&vf->legacy_last_added_umac)) {
ether_addr_copy(vf->dev_lan_addr.addr,
vf->legacy_last_added_umac.addr);
ether_addr_copy(vf->hw_lan_addr.addr,
vf->legacy_last_added_umac.addr);
}
ice_update_legacy_cached_mac(vf, vc_ether_addr);
}

/**
Expand Down Expand Up @@ -4400,6 +4413,133 @@ static int ice_vf_init_vlan_stripping(struct ice_vf *vf)
return ice_vsi_manage_vlan_stripping(vsi, false);
}

static struct ice_vc_vf_ops ice_vc_vf_dflt_ops = {
.get_ver_msg = ice_vc_get_ver_msg,
.get_vf_res_msg = ice_vc_get_vf_res_msg,
.reset_vf = ice_vc_reset_vf_msg,
.add_mac_addr_msg = ice_vc_add_mac_addr_msg,
.del_mac_addr_msg = ice_vc_del_mac_addr_msg,
.cfg_qs_msg = ice_vc_cfg_qs_msg,
.ena_qs_msg = ice_vc_ena_qs_msg,
.dis_qs_msg = ice_vc_dis_qs_msg,
.request_qs_msg = ice_vc_request_qs_msg,
.cfg_irq_map_msg = ice_vc_cfg_irq_map_msg,
.config_rss_key = ice_vc_config_rss_key,
.config_rss_lut = ice_vc_config_rss_lut,
.get_stats_msg = ice_vc_get_stats_msg,
.cfg_promiscuous_mode_msg = ice_vc_cfg_promiscuous_mode_msg,
.add_vlan_msg = ice_vc_add_vlan_msg,
.remove_vlan_msg = ice_vc_remove_vlan_msg,
.ena_vlan_stripping = ice_vc_ena_vlan_stripping,
.dis_vlan_stripping = ice_vc_dis_vlan_stripping,
.handle_rss_cfg_msg = ice_vc_handle_rss_cfg,
.add_fdir_fltr_msg = ice_vc_add_fdir_fltr,
.del_fdir_fltr_msg = ice_vc_del_fdir_fltr,
};

void ice_vc_set_dflt_vf_ops(struct ice_vc_vf_ops *ops)
{
*ops = ice_vc_vf_dflt_ops;
}

static int
ice_vc_repr_no_action_msg(struct ice_vf __always_unused *vf,
u8 __always_unused *msg)
{
return 0;
}

/**
* ice_vc_repr_add_mac
* @vf: pointer to VF
* @msg: virtchannel message
*
* When port representors are created, we do not add MAC rule
* to firmware, we store it so that PF could report same
* MAC as VF.
*/
static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg)
{
enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
struct virtchnl_ether_addr_list *al =
(struct virtchnl_ether_addr_list *)msg;
struct ice_vsi *vsi;
struct ice_pf *pf;
int i;

if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) ||
!ice_vc_isvalid_vsi_id(vf, al->vsi_id)) {
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
goto handle_mac_exit;
}

pf = vf->pf;

vsi = ice_get_vf_vsi(vf);
if (!vsi) {
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
goto handle_mac_exit;
}

for (i = 0; i < al->num_elements; i++) {
u8 *mac_addr = al->list[i].addr;

if (!is_unicast_ether_addr(mac_addr) ||
ether_addr_equal(mac_addr, vf->hw_lan_addr.addr))
continue;

if (vf->pf_set_mac) {
dev_err(ice_pf_to_dev(pf), "VF attempting to override administratively set MAC address\n");
v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
goto handle_mac_exit;
}

ice_vfhw_mac_add(vf, &al->list[i]);
vf->num_mac++;
break;
}

handle_mac_exit:
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR,
v_ret, NULL, 0);
}

/**
* ice_vc_repr_del_mac - response with success for deleting MAC
* @vf: pointer to VF
* @msg: virtchannel message
*
* Respond with success to not break normal VF flow.
* For legacy VF driver try to update cached MAC address.
*/
static int
ice_vc_repr_del_mac(struct ice_vf __always_unused *vf, u8 __always_unused *msg)
{
struct virtchnl_ether_addr_list *al =
(struct virtchnl_ether_addr_list *)msg;

ice_update_legacy_cached_mac(vf, &al->list[0]);

return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR,
VIRTCHNL_STATUS_SUCCESS, NULL, 0);
}

static int ice_vc_repr_no_action(struct ice_vf __always_unused *vf)
{
return 0;
}

void ice_vc_change_ops_to_repr(struct ice_vc_vf_ops *ops)
{
ops->add_mac_addr_msg = ice_vc_repr_add_mac;
ops->del_mac_addr_msg = ice_vc_repr_del_mac;
ops->add_vlan_msg = ice_vc_repr_no_action_msg;
ops->remove_vlan_msg = ice_vc_repr_no_action_msg;
ops->ena_vlan_stripping = ice_vc_repr_no_action;
ops->dis_vlan_stripping = ice_vc_repr_no_action;
ops->cfg_promiscuous_mode_msg = ice_vc_repr_no_action_msg;
}

/**
* ice_vc_process_vf_msg - Process request from VF
* @pf: pointer to the PF structure
Expand All @@ -4413,6 +4553,7 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
u32 v_opcode = le32_to_cpu(event->desc.cookie_high);
s16 vf_id = le16_to_cpu(event->desc.retval);
u16 msglen = event->msg_len;
struct ice_vc_vf_ops *ops;
u8 *msg = event->msg_buf;
struct ice_vf *vf = NULL;
struct device *dev;
Expand All @@ -4436,6 +4577,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
goto error_handler;
}

ops = &vf->vc_ops;

/* Perform basic checks on the msg */
err = virtchnl_vc_validate_vf_msg(&vf->vf_ver, v_opcode, msg, msglen);
if (err) {
Expand Down Expand Up @@ -4463,75 +4606,75 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)

switch (v_opcode) {
case VIRTCHNL_OP_VERSION:
err = ice_vc_get_ver_msg(vf, msg);
err = ops->get_ver_msg(vf, msg);
break;
case VIRTCHNL_OP_GET_VF_RESOURCES:
err = ice_vc_get_vf_res_msg(vf, msg);
err = ops->get_vf_res_msg(vf, msg);
if (ice_vf_init_vlan_stripping(vf))
dev_err(dev, "Failed to initialize VLAN stripping for VF %d\n",
vf->vf_id);
ice_vc_notify_vf_link_state(vf);
break;
case VIRTCHNL_OP_RESET_VF:
ice_vc_reset_vf_msg(vf);
ops->reset_vf(vf);
break;
case VIRTCHNL_OP_ADD_ETH_ADDR:
err = ice_vc_add_mac_addr_msg(vf, msg);
err = ops->add_mac_addr_msg(vf, msg);
break;
case VIRTCHNL_OP_DEL_ETH_ADDR:
err = ice_vc_del_mac_addr_msg(vf, msg);
err = ops->del_mac_addr_msg(vf, msg);
break;
case VIRTCHNL_OP_CONFIG_VSI_QUEUES:
err = ice_vc_cfg_qs_msg(vf, msg);
err = ops->cfg_qs_msg(vf, msg);
break;
case VIRTCHNL_OP_ENABLE_QUEUES:
err = ice_vc_ena_qs_msg(vf, msg);
err = ops->ena_qs_msg(vf, msg);
ice_vc_notify_vf_link_state(vf);
break;
case VIRTCHNL_OP_DISABLE_QUEUES:
err = ice_vc_dis_qs_msg(vf, msg);
err = ops->dis_qs_msg(vf, msg);
break;
case VIRTCHNL_OP_REQUEST_QUEUES:
err = ice_vc_request_qs_msg(vf, msg);
err = ops->request_qs_msg(vf, msg);
break;
case VIRTCHNL_OP_CONFIG_IRQ_MAP:
err = ice_vc_cfg_irq_map_msg(vf, msg);
err = ops->cfg_irq_map_msg(vf, msg);
break;
case VIRTCHNL_OP_CONFIG_RSS_KEY:
err = ice_vc_config_rss_key(vf, msg);
err = ops->config_rss_key(vf, msg);
break;
case VIRTCHNL_OP_CONFIG_RSS_LUT:
err = ice_vc_config_rss_lut(vf, msg);
err = ops->config_rss_lut(vf, msg);
break;
case VIRTCHNL_OP_GET_STATS:
err = ice_vc_get_stats_msg(vf, msg);
err = ops->get_stats_msg(vf, msg);
break;
case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
err = ice_vc_cfg_promiscuous_mode_msg(vf, msg);
err = ops->cfg_promiscuous_mode_msg(vf, msg);
break;
case VIRTCHNL_OP_ADD_VLAN:
err = ice_vc_add_vlan_msg(vf, msg);
err = ops->add_vlan_msg(vf, msg);
break;
case VIRTCHNL_OP_DEL_VLAN:
err = ice_vc_remove_vlan_msg(vf, msg);
err = ops->remove_vlan_msg(vf, msg);
break;
case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
err = ice_vc_ena_vlan_stripping(vf);
err = ops->ena_vlan_stripping(vf);
break;
case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
err = ice_vc_dis_vlan_stripping(vf);
err = ops->dis_vlan_stripping(vf);
break;
case VIRTCHNL_OP_ADD_FDIR_FILTER:
err = ice_vc_add_fdir_fltr(vf, msg);
err = ops->add_fdir_fltr_msg(vf, msg);
break;
case VIRTCHNL_OP_DEL_FDIR_FILTER:
err = ice_vc_del_fdir_fltr(vf, msg);
err = ops->del_fdir_fltr_msg(vf, msg);
break;
case VIRTCHNL_OP_ADD_RSS_CFG:
err = ice_vc_handle_rss_cfg(vf, msg, true);
err = ops->handle_rss_cfg_msg(vf, msg, true);
break;
case VIRTCHNL_OP_DEL_RSS_CFG:
err = ice_vc_handle_rss_cfg(vf, msg, false);
err = ops->handle_rss_cfg_msg(vf, msg, false);
break;
case VIRTCHNL_OP_UNKNOWN:
default:
Expand Down
Loading

0 comments on commit ac19e03

Please sign in to comment.