/** * ice_eswitch_cfg_vsi - configure VSI to work in slow-path * @vsi: VSI structure of representee * @mac: representee MAC * * Return: 0 on success, non-zero on error.
*/ int ice_eswitch_cfg_vsi(struct ice_vsi *vsi, const u8 *mac)
{ int err;
ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx);
err = ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof); if (err) goto err_update_security;
err = ice_vsi_add_vlan_zero(vsi); if (err) goto err_vlan_zero;
/** * ice_eswitch_decfg_vsi - unroll changes done to VSI for switchdev * @vsi: VSI structure of representee * @mac: representee MAC
*/ void ice_eswitch_decfg_vsi(struct ice_vsi *vsi, const u8 *mac)
{
ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
ice_fltr_add_mac_and_broadcast(vsi, mac, ICE_FWD_TO_VSI);
}
/** * ice_eswitch_update_repr - reconfigure port representor * @repr_id: representor ID * @vsi: VSI for which port representor is configured
*/ void ice_eswitch_update_repr(unsignedlong *repr_id, struct ice_vsi *vsi)
{ struct ice_pf *pf = vsi->back; struct ice_repr *repr; int err;
if (!ice_is_switchdev_running(pf)) return;
repr = xa_load(&pf->eswitch.reprs, *repr_id); if (!repr) return;
err = ice_eswitch_cfg_vsi(vsi, repr->parent_mac); if (err)
dev_err(ice_pf_to_dev(pf), "Failed to update VSI of port representor %d",
repr->id);
/* The VSI number is different, reload the PR with new id */ if (repr->id != vsi->vsi_num) {
xa_erase(&pf->eswitch.reprs, repr->id);
repr->id = vsi->vsi_num; if (xa_insert(&pf->eswitch.reprs, repr->id, repr, GFP_KERNEL))
dev_err(ice_pf_to_dev(pf), "Failed to reload port representor %d",
repr->id);
*repr_id = repr->id;
}
}
/** * ice_eswitch_port_start_xmit - callback for packets transmit * @skb: send buffer * @netdev: network interface device structure * * Returns NETDEV_TX_OK if sent, else an error code
*/
netdev_tx_t
ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{ struct ice_repr *repr = ice_netdev_to_repr(netdev); unsignedint len = skb->len; int ret;
/** * ice_eswitch_mode_set - set new eswitch mode * @devlink: pointer to devlink structure * @mode: eswitch mode to switch to * @extack: pointer to extack structure
*/ int
ice_eswitch_mode_set(struct devlink *devlink, u16 mode, struct netlink_ext_ack *extack)
{ struct ice_pf *pf = devlink_priv(devlink);
if (pf->eswitch_mode == mode) return 0;
if (ice_has_vfs(pf)) {
dev_info(ice_pf_to_dev(pf), "Changing eswitch mode is allowed only if there is no VFs created");
NL_SET_ERR_MSG_MOD(extack, "Changing eswitch mode is allowed only if there is no VFs created"); return -EOPNOTSUPP;
}
switch (mode) { case DEVLINK_ESWITCH_MODE_LEGACY:
dev_info(ice_pf_to_dev(pf), "PF %d changed eswitch mode to legacy",
pf->hw.pf_id);
xa_destroy(&pf->eswitch.reprs);
NL_SET_ERR_MSG_MOD(extack, "Changed eswitch mode to legacy"); break; case DEVLINK_ESWITCH_MODE_SWITCHDEV:
{ if (ice_is_adq_active(pf)) {
dev_err(ice_pf_to_dev(pf), "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root");
NL_SET_ERR_MSG_MOD(extack, "Couldn't change eswitch mode to switchdev - ADQ is active. Delete ADQ configs and try again, e.g. tc qdisc del dev $PF root"); return -EOPNOTSUPP;
}
/** * ice_eswitch_mode_get - get current eswitch mode * @devlink: pointer to devlink structure * @mode: output parameter for current eswitch mode
*/ int ice_eswitch_mode_get(struct devlink *devlink, u16 *mode)
{ struct ice_pf *pf = devlink_priv(devlink);
*mode = pf->eswitch_mode; return 0;
}
/** * ice_is_eswitch_mode_switchdev - check if eswitch mode is set to switchdev * @pf: pointer to PF structure * * Returns true if eswitch mode is set to DEVLINK_ESWITCH_MODE_SWITCHDEV, * false otherwise.
*/ bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf)
{ return pf->eswitch_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV;
}
/** * ice_eswitch_start_all_tx_queues - start Tx queues of all port representors * @pf: pointer to PF structure
*/ staticvoid ice_eswitch_start_all_tx_queues(struct ice_pf *pf)
{ struct ice_repr *repr; unsignedlong id;
if (pf->eswitch_mode == DEVLINK_ESWITCH_MODE_LEGACY) return 0;
if (xa_empty(&pf->eswitch.reprs)) {
err = ice_eswitch_enable_switchdev(pf); if (err) return err;
}
ice_eswitch_stop_reprs(pf);
err = repr->ops.add(repr); if (err) goto err_create_repr;
err = ice_eswitch_setup_repr(pf, repr); if (err) goto err_setup_repr;
err = xa_insert(&pf->eswitch.reprs, repr->id, repr, GFP_KERNEL); if (err) goto err_xa_alloc;
*id = repr->id;
ice_eswitch_start_reprs(pf);
return 0;
err_xa_alloc:
ice_eswitch_release_repr(pf, repr);
err_setup_repr:
repr->ops.rem(repr);
err_create_repr: if (xa_empty(&pf->eswitch.reprs))
ice_eswitch_disable_switchdev(pf);
ice_eswitch_start_reprs(pf);
return err;
}
/** * ice_eswitch_attach_vf - attach VF to a eswitch * @pf: pointer to PF structure * @vf: pointer to VF structure to be attached * * During attaching port representor for VF is created. * * Return: zero on success or an error code on failure.
*/ int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf)
{ struct devlink *devlink = priv_to_devlink(pf); struct ice_repr *repr; int err;
if (!ice_is_eswitch_mode_switchdev(pf)) return 0;
repr = ice_repr_create_vf(vf); if (IS_ERR(repr)) return PTR_ERR(repr);
devl_lock(devlink);
err = ice_eswitch_attach(pf, repr, &vf->repr_id); if (err)
ice_repr_destroy(repr);
devl_unlock(devlink);
return err;
}
/** * ice_eswitch_attach_sf - attach SF to a eswitch * @pf: pointer to PF structure * @sf: pointer to SF structure to be attached * * During attaching port representor for SF is created. * * Return: zero on success or an error code on failure.
*/ int ice_eswitch_attach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf)
{ struct ice_repr *repr = ice_repr_create_sf(sf); int err;
if (IS_ERR(repr)) return PTR_ERR(repr);
err = ice_eswitch_attach(pf, repr, &sf->repr_id); if (err)
ice_repr_destroy(repr);
if (xa_empty(&pf->eswitch.reprs)) { struct devlink *devlink = priv_to_devlink(pf);
/* since all port representors are destroyed, there is * no point in keeping the nodes
*/
ice_devlink_rate_clear_tx_topology(ice_get_main_vsi(pf));
devl_rate_nodes_destroy(devlink);
} else {
ice_eswitch_start_reprs(pf);
}
}
/** * ice_eswitch_detach_vf - detach VF from a eswitch * @pf: pointer to PF structure * @vf: pointer to VF structure to be detached
*/ void ice_eswitch_detach_vf(struct ice_pf *pf, struct ice_vf *vf)
{ struct ice_repr *repr = xa_load(&pf->eswitch.reprs, vf->repr_id); struct devlink *devlink = priv_to_devlink(pf);
/** * ice_eswitch_detach_sf - detach SF from a eswitch * @pf: pointer to PF structure * @sf: pointer to SF structure to be detached
*/ void ice_eswitch_detach_sf(struct ice_pf *pf, struct ice_dynamic_port *sf)
{ struct ice_repr *repr = xa_load(&pf->eswitch.reprs, sf->repr_id);
if (!repr) return;
ice_eswitch_detach(pf, repr);
}
/** * ice_eswitch_get_target - get netdev based on src_vsi from descriptor * @rx_ring: ring used to receive the packet * @rx_desc: descriptor used to get src_vsi value * * Get src_vsi value from descriptor and load correct representor. If it isn't * found return rx_ring->netdev.
*/ struct net_device *ice_eswitch_get_target(struct ice_rx_ring *rx_ring, union ice_32b_rx_flex_desc *rx_desc)
{ struct ice_eswitch *eswitch = &rx_ring->vsi->back->eswitch; struct ice_32b_rx_flex_desc_nic_2 *desc; struct ice_repr *repr;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.