From 604283e95eb0b2f4f38238e7acec4f1d68e00e2e Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Tue, 24 Oct 2023 13:09:22 +0200 Subject: [PATCH] ice: make representor code generic Representor code needs to be independent from specific device type, like in this case VF. Make generic add / remove representor function and specific add VF / rem VF function. New device types will follow this scheme. In bridge offload code there is a need to get representor pointer based on VSI. Implement helper function to achieve that. Reviewed-by: Piotr Raczynski Reviewed-by: Wojciech Drewek Signed-off-by: Michal Swiatkowski Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_eswitch.c | 9 +- drivers/net/ethernet/intel/ice/ice_eswitch.h | 4 +- .../net/ethernet/intel/ice/ice_eswitch_br.c | 10 +- drivers/net/ethernet/intel/ice/ice_lib.c | 10 +- drivers/net/ethernet/intel/ice/ice_repr.c | 204 ++++++++++-------- drivers/net/ethernet/intel/ice/ice_repr.h | 2 + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 2 +- drivers/net/ethernet/intel/ice/ice_vf_lib.h | 2 +- 8 files changed, 141 insertions(+), 102 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index 66cbe2c80fea..67231e43ffa6 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -285,17 +285,22 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf) /** * ice_eswitch_update_repr - reconfigure port representor - * @repr: pointer to repr struct + * @repr_id: representor ID * @vsi: VSI for which port representor is configured */ -void ice_eswitch_update_repr(struct ice_repr *repr, struct ice_vsi *vsi) +void ice_eswitch_update_repr(unsigned long repr_id, struct ice_vsi *vsi) { struct ice_pf *pf = vsi->back; + struct ice_repr *repr; int ret; if (!ice_is_switchdev_running(pf)) return; + repr = xa_load(&pf->eswitch.reprs, repr_id); + if (!repr) + return; + repr->src_vsi = vsi; repr->dst->u.port_info.port_id = vsi->vsi_num; diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.h b/drivers/net/ethernet/intel/ice/ice_eswitch.h index f43db1cce3ad..ff110bd9fc4c 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.h +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.h @@ -17,7 +17,7 @@ ice_eswitch_mode_set(struct devlink *devlink, u16 mode, struct netlink_ext_ack *extack); bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf); -void ice_eswitch_update_repr(struct ice_repr *repr, struct ice_vsi *vsi); +void ice_eswitch_update_repr(unsigned long repr_id, struct ice_vsi *vsi); void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf); @@ -35,7 +35,7 @@ ice_eswitch_set_target_vsi(struct sk_buff *skb, struct ice_tx_offload_params *off) { } static inline void -ice_eswitch_update_repr(struct ice_repr *repr, struct ice_vsi *vsi) { } +ice_eswitch_update_repr(unsigned long repr_id, struct ice_vsi *vsi) { } static inline int ice_eswitch_configure(struct ice_pf *pf) { diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c index 16bbcaca8fda..ac5beecd028b 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch_br.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch_br.c @@ -893,10 +893,14 @@ ice_eswitch_br_port_deinit(struct ice_esw_br *bridge, ice_eswitch_br_fdb_entry_delete(bridge, fdb_entry); } - if (br_port->type == ICE_ESWITCH_BR_UPLINK_PORT && vsi->back) + if (br_port->type == ICE_ESWITCH_BR_UPLINK_PORT && vsi->back) { vsi->back->br_port = NULL; - else if (vsi->vf && vsi->vf->repr) - vsi->vf->repr->br_port = NULL; + } else { + struct ice_repr *repr = ice_repr_get_by_vsi(vsi); + + if (repr) + repr->br_port = NULL; + } xa_erase(&bridge->ports, br_port->vsi_idx); ice_eswitch_br_port_vlans_flush(br_port); diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 4b1e56396293..ae4b4220e1bb 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -519,16 +519,14 @@ static irqreturn_t ice_eswitch_msix_clean_rings(int __always_unused irq, void *d { struct ice_q_vector *q_vector = (struct ice_q_vector *)data; struct ice_pf *pf = q_vector->vsi->back; - struct ice_vf *vf; - unsigned int bkt; + struct ice_repr *repr; + unsigned long id; if (!q_vector->tx.tx_ring && !q_vector->rx.rx_ring) return IRQ_HANDLED; - rcu_read_lock(); - ice_for_each_vf_rcu(pf, bkt, vf) - napi_schedule(&vf->repr->q_vector->napi); - rcu_read_unlock(); + xa_for_each(&pf->eswitch.reprs, id, repr) + napi_schedule(&repr->q_vector->napi); return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c index 77cc77ab826a..fce25472d053 100644 --- a/drivers/net/ethernet/intel/ice/ice_repr.c +++ b/drivers/net/ethernet/intel/ice/ice_repr.c @@ -14,7 +14,7 @@ */ static int ice_repr_get_sw_port_id(struct ice_repr *repr) { - return repr->vf->pf->hw.port_info->lport; + return repr->src_vsi->back->hw.port_info->lport; } /** @@ -35,7 +35,7 @@ ice_repr_get_phys_port_name(struct net_device *netdev, char *buf, size_t len) return -EOPNOTSUPP; res = snprintf(buf, len, "pf%dvfr%d", ice_repr_get_sw_port_id(repr), - repr->vf->vf_id); + repr->id); if (res <= 0) return -EOPNOTSUPP; return 0; @@ -279,103 +279,28 @@ ice_repr_reg_netdev(struct net_device *netdev) } /** - * ice_repr_add - add representor for VF - * @vf: pointer to VF structure + * ice_repr_rem - remove representor from VF + * @reprs: xarray storing representors + * @repr: pointer to representor structure */ -static int ice_repr_add(struct ice_vf *vf) +static void ice_repr_rem(struct xarray *reprs, struct ice_repr *repr) { - struct ice_q_vector *q_vector; - struct ice_netdev_priv *np; - struct ice_repr *repr; - struct ice_vsi *vsi; - int err; - - vsi = ice_get_vf_vsi(vf); - if (!vsi) - return -EINVAL; - - repr = kzalloc(sizeof(*repr), GFP_KERNEL); - if (!repr) - return -ENOMEM; - - repr->netdev = alloc_etherdev(sizeof(struct ice_netdev_priv)); - if (!repr->netdev) { - err = -ENOMEM; - goto err_alloc; - } - - repr->src_vsi = vsi; - repr->vf = vf; - repr->q_id = vf->vf_id; - vf->repr = repr; - np = netdev_priv(repr->netdev); - np->repr = repr; - - q_vector = kzalloc(sizeof(*q_vector), GFP_KERNEL); - if (!q_vector) { - err = -ENOMEM; - goto err_alloc_q_vector; - } - repr->q_vector = q_vector; - - err = xa_alloc(&vf->pf->eswitch.reprs, &repr->id, repr, - xa_limit_32b, GFP_KERNEL); - if (err) - goto err_xa_alloc; - - err = ice_devlink_create_vf_port(vf); - if (err) - goto err_devlink; - - repr->netdev->min_mtu = ETH_MIN_MTU; - repr->netdev->max_mtu = ICE_MAX_MTU; - - SET_NETDEV_DEV(repr->netdev, ice_pf_to_dev(vf->pf)); - SET_NETDEV_DEVLINK_PORT(repr->netdev, &vf->devlink_port); - err = ice_repr_reg_netdev(repr->netdev); - if (err) - goto err_netdev; - - ether_addr_copy(repr->parent_mac, vf->hw_lan_addr); - ice_virtchnl_set_repr_ops(vf); - - return 0; - -err_netdev: - ice_devlink_destroy_vf_port(vf); -err_devlink: - xa_erase(&vf->pf->eswitch.reprs, repr->id); -err_xa_alloc: + xa_erase(reprs, repr->id); kfree(repr->q_vector); - vf->repr->q_vector = NULL; -err_alloc_q_vector: free_netdev(repr->netdev); - repr->netdev = NULL; -err_alloc: kfree(repr); - vf->repr = NULL; - return err; } -/** - * ice_repr_rem - remove representor from VF - * @vf: pointer to VF structure - */ -static void ice_repr_rem(struct ice_vf *vf) +static void ice_repr_rem_vf(struct ice_vf *vf) { - struct ice_repr *repr = vf->repr; + struct ice_repr *repr = xa_load(&vf->pf->eswitch.reprs, vf->repr_id); if (!repr) return; - kfree(repr->q_vector); unregister_netdev(repr->netdev); + ice_repr_rem(&vf->pf->eswitch.reprs, repr); ice_devlink_destroy_vf_port(vf); - xa_erase(&vf->pf->eswitch.reprs, repr->id); - free_netdev(repr->netdev); - kfree(repr); - vf->repr = NULL; - ice_virtchnl_set_dflt_ops(vf); } @@ -392,7 +317,7 @@ void ice_repr_rem_from_all_vfs(struct ice_pf *pf) lockdep_assert_held(&pf->vfs.table_lock); ice_for_each_vf(pf, bkt, vf) - ice_repr_rem(vf); + ice_repr_rem_vf(vf); /* since all port representors are destroyed, there is * no point in keeping the nodes @@ -403,6 +328,103 @@ void ice_repr_rem_from_all_vfs(struct ice_pf *pf) devl_unlock(devlink); } +/** + * ice_repr_add - add representor for generic VSI + * @pf: pointer to PF structure + * @src_vsi: pointer to VSI structure of device to represent + * @parent_mac: device MAC address + */ +static struct ice_repr * +ice_repr_add(struct ice_pf *pf, struct ice_vsi *src_vsi, const u8 *parent_mac) +{ + struct ice_q_vector *q_vector; + struct ice_netdev_priv *np; + struct ice_repr *repr; + int err; + + repr = kzalloc(sizeof(*repr), GFP_KERNEL); + if (!repr) + return ERR_PTR(-ENOMEM); + + repr->netdev = alloc_etherdev(sizeof(struct ice_netdev_priv)); + if (!repr->netdev) { + err = -ENOMEM; + goto err_alloc; + } + + repr->src_vsi = src_vsi; + np = netdev_priv(repr->netdev); + np->repr = repr; + + q_vector = kzalloc(sizeof(*q_vector), GFP_KERNEL); + if (!q_vector) { + err = -ENOMEM; + goto err_alloc_q_vector; + } + repr->q_vector = q_vector; + + err = xa_alloc(&pf->eswitch.reprs, &repr->id, repr, + XA_LIMIT(1, INT_MAX), GFP_KERNEL); + if (err) + goto err_xa_alloc; + repr->q_id = repr->id; + + ether_addr_copy(repr->parent_mac, parent_mac); + + return repr; + +err_xa_alloc: + kfree(repr->q_vector); +err_alloc_q_vector: + free_netdev(repr->netdev); +err_alloc: + kfree(repr); + return ERR_PTR(err); +} + +static int ice_repr_add_vf(struct ice_vf *vf) +{ + struct ice_repr *repr; + struct ice_vsi *vsi; + int err; + + vsi = ice_get_vf_vsi(vf); + if (!vsi) + return -EINVAL; + + err = ice_devlink_create_vf_port(vf); + if (err) + return err; + + repr = ice_repr_add(vf->pf, vsi, vf->hw_lan_addr); + if (IS_ERR(repr)) { + err = PTR_ERR(repr); + goto err_repr_add; + } + + vf->repr_id = repr->id; + repr->vf = vf; + + repr->netdev->min_mtu = ETH_MIN_MTU; + repr->netdev->max_mtu = ICE_MAX_MTU; + + SET_NETDEV_DEV(repr->netdev, ice_pf_to_dev(vf->pf)); + SET_NETDEV_DEVLINK_PORT(repr->netdev, &vf->devlink_port); + err = ice_repr_reg_netdev(repr->netdev); + if (err) + goto err_netdev; + + ice_virtchnl_set_repr_ops(vf); + + return 0; + +err_netdev: + ice_repr_rem(&vf->pf->eswitch.reprs, repr); +err_repr_add: + ice_devlink_destroy_vf_port(vf); + return err; +} + /** * ice_repr_add_for_all_vfs - add port representor for all VFs * @pf: pointer to PF structure @@ -417,7 +439,7 @@ int ice_repr_add_for_all_vfs(struct ice_pf *pf) lockdep_assert_held(&pf->vfs.table_lock); ice_for_each_vf(pf, bkt, vf) { - err = ice_repr_add(vf); + err = ice_repr_add_vf(vf); if (err) goto err; } @@ -437,6 +459,14 @@ int ice_repr_add_for_all_vfs(struct ice_pf *pf) return err; } +struct ice_repr *ice_repr_get_by_vsi(struct ice_vsi *vsi) +{ + if (!vsi->vf) + return NULL; + + return xa_load(&vsi->back->eswitch.reprs, vsi->vf->repr_id); +} + /** * ice_repr_start_tx_queues - start Tx queues of port representor * @repr: pointer to repr structure diff --git a/drivers/net/ethernet/intel/ice/ice_repr.h b/drivers/net/ethernet/intel/ice/ice_repr.h index 735cb556c620..a3cd256d82b7 100644 --- a/drivers/net/ethernet/intel/ice/ice_repr.h +++ b/drivers/net/ethernet/intel/ice/ice_repr.h @@ -32,4 +32,6 @@ void ice_repr_set_traffic_vsi(struct ice_repr *repr, struct ice_vsi *vsi); struct ice_repr *ice_netdev_to_repr(struct net_device *netdev); bool ice_is_port_repr_netdev(const struct net_device *netdev); + +struct ice_repr *ice_repr_get_by_vsi(struct ice_vsi *vsi); #endif diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index 462ee9fdf815..68f9de0a7a8f 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -928,7 +928,7 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) goto out_unlock; } - ice_eswitch_update_repr(vf->repr, vsi); + ice_eswitch_update_repr(vf->repr_id, vsi); /* if the VF has been reset allow it to come up again */ ice_mbx_clear_malvf(&vf->mbx_info); diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h index 93c774f2f437..35866553f288 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h @@ -130,7 +130,7 @@ struct ice_vf { struct ice_mdd_vf_events mdd_tx_events; DECLARE_BITMAP(opcodes_allowlist, VIRTCHNL_OP_MAX); - struct ice_repr *repr; + unsigned long repr_id; const struct ice_virtchnl_ops *virtchnl_ops; const struct ice_vf_ops *vf_ops;