Commit ac19e03e authored by Michal Swiatkowski's avatar Michal Swiatkowski Committed by Tony Nguyen

ice: allow process VF opcodes in different ways

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: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Signed-off-by: default avatarMichal Swiatkowski <michal.swiatkowski@linux.intel.com>
Tested-by: default avatarSandeep Penigalapati <sandeep.penigalapati@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 37165e3f
......@@ -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;
}
......@@ -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);
}
}
......@@ -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);
}
}
......@@ -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
......@@ -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);
}
/**
......@@ -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
......@@ -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;
......@@ -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) {
......@@ -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:
......
......@@ -70,6 +70,32 @@ struct ice_mdd_vf_events {
u16 last_printed;
};
struct ice_vf;
struct ice_vc_vf_ops {
int (*get_ver_msg)(struct ice_vf *vf, u8 *msg);
int (*get_vf_res_msg)(struct ice_vf *vf, u8 *msg);
void (*reset_vf)(struct ice_vf *vf);
int (*add_mac_addr_msg)(struct ice_vf *vf, u8 *msg);
int (*del_mac_addr_msg)(struct ice_vf *vf, u8 *msg);
int (*cfg_qs_msg)(struct ice_vf *vf, u8 *msg);
int (*ena_qs_msg)(struct ice_vf *vf, u8 *msg);
int (*dis_qs_msg)(struct ice_vf *vf, u8 *msg);
int (*request_qs_msg)(struct ice_vf *vf, u8 *msg);
int (*cfg_irq_map_msg)(struct ice_vf *vf, u8 *msg);
int (*config_rss_key)(struct ice_vf *vf, u8 *msg);
int (*config_rss_lut)(struct ice_vf *vf, u8 *msg);
int (*get_stats_msg)(struct ice_vf *vf, u8 *msg);
int (*cfg_promiscuous_mode_msg)(struct ice_vf *vf, u8 *msg);
int (*add_vlan_msg)(struct ice_vf *vf, u8 *msg);
int (*remove_vlan_msg)(struct ice_vf *vf, u8 *msg);
int (*ena_vlan_stripping)(struct ice_vf *vf);
int (*dis_vlan_stripping)(struct ice_vf *vf);
int (*handle_rss_cfg_msg)(struct ice_vf *vf, u8 *msg, bool add);
int (*add_fdir_fltr_msg)(struct ice_vf *vf, u8 *msg);
int (*del_fdir_fltr_msg)(struct ice_vf *vf, u8 *msg);
};
/* VF information structure */
struct ice_vf {
struct ice_pf *pf;
......@@ -114,6 +140,8 @@ struct ice_vf {
struct ice_repr *repr;
struct ice_vc_vf_ops vc_ops;
/* devlink port data */
struct devlink_port devlink_port;
};
......@@ -131,6 +159,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event);
void ice_vc_notify_link_state(struct ice_pf *pf);
void ice_vc_notify_reset(struct ice_pf *pf);
void ice_vc_notify_vf_link_state(struct ice_vf *vf);
void ice_vc_change_ops_to_repr(struct ice_vc_vf_ops *ops);
void ice_vc_set_dflt_vf_ops(struct ice_vc_vf_ops *ops);
bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr);
bool ice_reset_vf(struct ice_vf *vf, bool is_vflr);
void ice_restore_all_vfs_msi_state(struct pci_dev *pdev);
......@@ -172,6 +202,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event) {
static inline void ice_vc_notify_link_state(struct ice_pf *pf) { }
static inline void ice_vc_notify_reset(struct ice_pf *pf) { }
static inline void ice_vc_notify_vf_link_state(struct ice_vf *vf) { }
static inline void ice_vc_change_ops_to_repr(struct ice_vc_vf_ops *ops) { }
static inline void ice_vc_set_dflt_vf_ops(struct ice_vc_vf_ops *ops) { }
static inline void ice_set_vf_state_qs_dis(struct ice_vf *vf) { }
static inline
void ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event) { }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment