Message ID | 20241022041707.27402-5-neescoba@cisco.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | Use all the resources configured on VIC | expand |
On Mon, Oct 21, 2024 at 09:17:06PM -0700, Nelson Escobar wrote: > Allocate wq, rq, cq, intr, and napi arrays based on the number of > resources configured in the VIC. > > Signed-off-by: Nelson Escobar <neescoba@cisco.com> > Signed-off-by: John Daley <johndale@cisco.com> > Signed-off-by: Satish Kharat <satishkh@cisco.com> Reviewed-by: Simon Horman <horms@kernel.org>
On Tue, Oct 22, 2024 at 9:49 AM Nelson Escobar <neescoba@cisco.com> wrote: > > Allocate wq, rq, cq, intr, and napi arrays based on the number of > resources configured in the VIC. > > Signed-off-by: Nelson Escobar <neescoba@cisco.com> > Signed-off-by: John Daley <johndale@cisco.com> > Signed-off-by: Satish Kharat <satishkh@cisco.com> > --- > drivers/net/ethernet/cisco/enic/enic.h | 24 ++--- > drivers/net/ethernet/cisco/enic/enic_main.c | 102 ++++++++++++++++++-- > 2 files changed, 105 insertions(+), 21 deletions(-) > > diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h > index 1f32413a8f7c..cfb4667953de 100644 > --- a/drivers/net/ethernet/cisco/enic/enic.h > +++ b/drivers/net/ethernet/cisco/enic/enic.h > @@ -23,10 +23,8 @@ > > #define ENIC_BARS_MAX 6 > > -#define ENIC_WQ_MAX 8 > -#define ENIC_RQ_MAX 8 > -#define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX) > -#define ENIC_INTR_MAX (ENIC_CQ_MAX + 2) > +#define ENIC_WQ_MAX 256 > +#define ENIC_RQ_MAX 256 > > #define ENIC_WQ_NAPI_BUDGET 256 > > @@ -184,8 +182,8 @@ struct enic { > struct work_struct reset; > struct work_struct tx_hang_reset; > struct work_struct change_mtu_work; > - struct msix_entry msix_entry[ENIC_INTR_MAX]; > - struct enic_msix_entry msix[ENIC_INTR_MAX]; > + struct msix_entry *msix_entry; > + struct enic_msix_entry *msix; > u32 msg_enable; > spinlock_t devcmd_lock; > u8 mac_addr[ETH_ALEN]; > @@ -204,28 +202,24 @@ struct enic { > bool enic_api_busy; > struct enic_port_profile *pp; > > - /* work queue cache line section */ > - ____cacheline_aligned struct enic_wq wq[ENIC_WQ_MAX]; > + struct enic_wq *wq; > unsigned int wq_avail; > unsigned int wq_count; > u16 loop_enable; > u16 loop_tag; > > - /* receive queue cache line section */ > - ____cacheline_aligned struct enic_rq rq[ENIC_RQ_MAX]; > + struct enic_rq *rq; > unsigned int rq_avail; > unsigned int rq_count; > struct vxlan_offload vxlan; > - struct napi_struct napi[ENIC_RQ_MAX + ENIC_WQ_MAX]; > + struct napi_struct *napi; > > - /* interrupt resource cache line section */ > - ____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX]; > + struct vnic_intr *intr; > unsigned int intr_avail; > unsigned int intr_count; > u32 __iomem *legacy_pba; /* memory-mapped */ > > - /* completion queue cache line section */ > - ____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX]; > + struct vnic_cq *cq; > unsigned int cq_avail; > unsigned int cq_count; > struct enic_rfs_flw_tbl rfs_h; > diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c > index eb00058b6c68..a5d607be66b7 100644 > --- a/drivers/net/ethernet/cisco/enic/enic_main.c > +++ b/drivers/net/ethernet/cisco/enic/enic_main.c > @@ -940,7 +940,7 @@ static void enic_get_stats(struct net_device *netdev, > net_stats->rx_errors = stats->rx.rx_errors; > net_stats->multicast = stats->rx.rx_multicast_frames_ok; > > - for (i = 0; i < ENIC_RQ_MAX; i++) { > + for (i = 0; i < enic->rq_count; i++) { > struct enic_rq_stats *rqs = &enic->rq[i].stats; > > if (!enic->rq[i].vrq.ctrl) > @@ -1792,7 +1792,7 @@ static void enic_free_intr(struct enic *enic) > free_irq(enic->pdev->irq, enic); > break; > case VNIC_DEV_INTR_MODE_MSIX: > - for (i = 0; i < ARRAY_SIZE(enic->msix); i++) > + for (i = 0; i < enic->intr_count; i++) > if (enic->msix[i].requested) > free_irq(enic->msix_entry[i].vector, > enic->msix[i].devid); > @@ -1859,7 +1859,7 @@ static int enic_request_intr(struct enic *enic) > enic->msix[intr].isr = enic_isr_msix_notify; > enic->msix[intr].devid = enic; > > - for (i = 0; i < ARRAY_SIZE(enic->msix); i++) > + for (i = 0; i < enic->intr_count; i++) > enic->msix[i].requested = 0; > > for (i = 0; i < enic->intr_count; i++) { > @@ -2456,8 +2456,7 @@ static int enic_set_intr_mode(struct enic *enic) > * (the last INTR is used for notifications) > */ > > - BUG_ON(ARRAY_SIZE(enic->msix_entry) < n + m + 2); > - for (i = 0; i < n + m + 2; i++) > + for (i = 0; i < enic->intr_avail; i++) > enic->msix_entry[i].entry = i; > > /* Use multiple RQs if RSS is enabled > @@ -2674,6 +2673,89 @@ static const struct netdev_stat_ops enic_netdev_stat_ops = { > .get_base_stats = enic_get_base_stats, > }; > > +static void enic_free_enic_resources(struct enic *enic) > +{ > + kfree(enic->wq); > + enic->wq = NULL; > + > + kfree(enic->rq); > + enic->rq = NULL; > + > + kfree(enic->cq); > + enic->cq = NULL; > + > + kfree(enic->napi); > + enic->napi = NULL; > + > + kfree(enic->msix_entry); > + enic->msix_entry = NULL; > + > + kfree(enic->msix); > + enic->msix = NULL; > + > + kfree(enic->intr); > + enic->intr = NULL; > +} > + > +static int enic_alloc_enic_resources(struct enic *enic) > +{ > + int ret; [Kalesh] There is no need for a local variable here. You can return -ENOMEM in the error path directly. > + > + enic->wq = NULL; > + enic->rq = NULL; > + enic->cq = NULL; > + enic->napi = NULL; > + enic->msix_entry = NULL; > + enic->msix = NULL; > + enic->intr = NULL; [Kalesh] Looks like the above NULL pointer assignments are redundant. all those fields will be 0 anyway. > + > + enic->wq = kcalloc(enic->wq_avail, sizeof(struct enic_wq), GFP_KERNEL); > + if (!enic->wq) { > + ret = -ENOMEM; > + goto free_queues; > + } > + enic->rq = kcalloc(enic->rq_avail, sizeof(struct enic_rq), GFP_KERNEL); > + if (!enic->rq) { > + ret = -ENOMEM; > + goto free_queues; > + } > + enic->cq = kcalloc(enic->cq_avail, sizeof(struct vnic_cq), GFP_KERNEL); > + if (!enic->cq) { > + ret = -ENOMEM; > + goto free_queues; > + } > + enic->napi = kcalloc(enic->wq_avail + enic->rq_avail, > + sizeof(struct napi_struct), GFP_KERNEL); > + if (!enic->napi) { > + ret = -ENOMEM; > + goto free_queues; > + } > + enic->msix_entry = kcalloc(enic->intr_avail, sizeof(struct msix_entry), > + GFP_KERNEL); > + if (!enic->msix_entry) { > + ret = -ENOMEM; > + goto free_queues; > + } > + enic->msix = kcalloc(enic->intr_avail, sizeof(struct enic_msix_entry), > + GFP_KERNEL); > + if (!enic->msix) { > + ret = -ENOMEM; > + goto free_queues; > + } > + enic->intr = kcalloc(enic->intr_avail, sizeof(struct vnic_intr), > + GFP_KERNEL); > + if (!enic->intr) { > + ret = -ENOMEM; > + goto free_queues; > + } > + > + return 0; > + > +free_queues: > + enic_free_enic_resources(enic); > + return ret; > +} > + > static void enic_dev_deinit(struct enic *enic) > { > unsigned int i; > @@ -2691,6 +2773,7 @@ static void enic_dev_deinit(struct enic *enic) > enic_free_vnic_resources(enic); > enic_clear_intr_mode(enic); > enic_free_affinity_hint(enic); > + enic_free_enic_resources(enic); > } > > static void enic_kdump_kernel_config(struct enic *enic) > @@ -2734,6 +2817,12 @@ static int enic_dev_init(struct enic *enic) > > enic_get_res_counts(enic); > > + err = enic_alloc_enic_resources(enic); > + if (err) { > + dev_err(dev, "Failed to allocate queues, aborting\n"); [Kalesh] You can drop this error log in case you want as memory allocation failure will be logged by OOM. > + return err; > + } > + > /* modify resource count if we are in kdump_kernel > */ > enic_kdump_kernel_config(enic); > @@ -2746,7 +2835,7 @@ static int enic_dev_init(struct enic *enic) > if (err) { > dev_err(dev, "Failed to set intr mode based on resource " > "counts and system capabilities, aborting\n"); > - return err; > + goto err_out_free_vnic_resources; > } > > /* Allocate and configure vNIC resources > @@ -2788,6 +2877,7 @@ static int enic_dev_init(struct enic *enic) > enic_free_affinity_hint(enic); > enic_clear_intr_mode(enic); > enic_free_vnic_resources(enic); > + enic_free_enic_resources(enic); > > return err; > } > -- > 2.35.2 > >
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h index 1f32413a8f7c..cfb4667953de 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -23,10 +23,8 @@ #define ENIC_BARS_MAX 6 -#define ENIC_WQ_MAX 8 -#define ENIC_RQ_MAX 8 -#define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX) -#define ENIC_INTR_MAX (ENIC_CQ_MAX + 2) +#define ENIC_WQ_MAX 256 +#define ENIC_RQ_MAX 256 #define ENIC_WQ_NAPI_BUDGET 256 @@ -184,8 +182,8 @@ struct enic { struct work_struct reset; struct work_struct tx_hang_reset; struct work_struct change_mtu_work; - struct msix_entry msix_entry[ENIC_INTR_MAX]; - struct enic_msix_entry msix[ENIC_INTR_MAX]; + struct msix_entry *msix_entry; + struct enic_msix_entry *msix; u32 msg_enable; spinlock_t devcmd_lock; u8 mac_addr[ETH_ALEN]; @@ -204,28 +202,24 @@ struct enic { bool enic_api_busy; struct enic_port_profile *pp; - /* work queue cache line section */ - ____cacheline_aligned struct enic_wq wq[ENIC_WQ_MAX]; + struct enic_wq *wq; unsigned int wq_avail; unsigned int wq_count; u16 loop_enable; u16 loop_tag; - /* receive queue cache line section */ - ____cacheline_aligned struct enic_rq rq[ENIC_RQ_MAX]; + struct enic_rq *rq; unsigned int rq_avail; unsigned int rq_count; struct vxlan_offload vxlan; - struct napi_struct napi[ENIC_RQ_MAX + ENIC_WQ_MAX]; + struct napi_struct *napi; - /* interrupt resource cache line section */ - ____cacheline_aligned struct vnic_intr intr[ENIC_INTR_MAX]; + struct vnic_intr *intr; unsigned int intr_avail; unsigned int intr_count; u32 __iomem *legacy_pba; /* memory-mapped */ - /* completion queue cache line section */ - ____cacheline_aligned struct vnic_cq cq[ENIC_CQ_MAX]; + struct vnic_cq *cq; unsigned int cq_avail; unsigned int cq_count; struct enic_rfs_flw_tbl rfs_h; diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index eb00058b6c68..a5d607be66b7 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -940,7 +940,7 @@ static void enic_get_stats(struct net_device *netdev, net_stats->rx_errors = stats->rx.rx_errors; net_stats->multicast = stats->rx.rx_multicast_frames_ok; - for (i = 0; i < ENIC_RQ_MAX; i++) { + for (i = 0; i < enic->rq_count; i++) { struct enic_rq_stats *rqs = &enic->rq[i].stats; if (!enic->rq[i].vrq.ctrl) @@ -1792,7 +1792,7 @@ static void enic_free_intr(struct enic *enic) free_irq(enic->pdev->irq, enic); break; case VNIC_DEV_INTR_MODE_MSIX: - for (i = 0; i < ARRAY_SIZE(enic->msix); i++) + for (i = 0; i < enic->intr_count; i++) if (enic->msix[i].requested) free_irq(enic->msix_entry[i].vector, enic->msix[i].devid); @@ -1859,7 +1859,7 @@ static int enic_request_intr(struct enic *enic) enic->msix[intr].isr = enic_isr_msix_notify; enic->msix[intr].devid = enic; - for (i = 0; i < ARRAY_SIZE(enic->msix); i++) + for (i = 0; i < enic->intr_count; i++) enic->msix[i].requested = 0; for (i = 0; i < enic->intr_count; i++) { @@ -2456,8 +2456,7 @@ static int enic_set_intr_mode(struct enic *enic) * (the last INTR is used for notifications) */ - BUG_ON(ARRAY_SIZE(enic->msix_entry) < n + m + 2); - for (i = 0; i < n + m + 2; i++) + for (i = 0; i < enic->intr_avail; i++) enic->msix_entry[i].entry = i; /* Use multiple RQs if RSS is enabled @@ -2674,6 +2673,89 @@ static const struct netdev_stat_ops enic_netdev_stat_ops = { .get_base_stats = enic_get_base_stats, }; +static void enic_free_enic_resources(struct enic *enic) +{ + kfree(enic->wq); + enic->wq = NULL; + + kfree(enic->rq); + enic->rq = NULL; + + kfree(enic->cq); + enic->cq = NULL; + + kfree(enic->napi); + enic->napi = NULL; + + kfree(enic->msix_entry); + enic->msix_entry = NULL; + + kfree(enic->msix); + enic->msix = NULL; + + kfree(enic->intr); + enic->intr = NULL; +} + +static int enic_alloc_enic_resources(struct enic *enic) +{ + int ret; + + enic->wq = NULL; + enic->rq = NULL; + enic->cq = NULL; + enic->napi = NULL; + enic->msix_entry = NULL; + enic->msix = NULL; + enic->intr = NULL; + + enic->wq = kcalloc(enic->wq_avail, sizeof(struct enic_wq), GFP_KERNEL); + if (!enic->wq) { + ret = -ENOMEM; + goto free_queues; + } + enic->rq = kcalloc(enic->rq_avail, sizeof(struct enic_rq), GFP_KERNEL); + if (!enic->rq) { + ret = -ENOMEM; + goto free_queues; + } + enic->cq = kcalloc(enic->cq_avail, sizeof(struct vnic_cq), GFP_KERNEL); + if (!enic->cq) { + ret = -ENOMEM; + goto free_queues; + } + enic->napi = kcalloc(enic->wq_avail + enic->rq_avail, + sizeof(struct napi_struct), GFP_KERNEL); + if (!enic->napi) { + ret = -ENOMEM; + goto free_queues; + } + enic->msix_entry = kcalloc(enic->intr_avail, sizeof(struct msix_entry), + GFP_KERNEL); + if (!enic->msix_entry) { + ret = -ENOMEM; + goto free_queues; + } + enic->msix = kcalloc(enic->intr_avail, sizeof(struct enic_msix_entry), + GFP_KERNEL); + if (!enic->msix) { + ret = -ENOMEM; + goto free_queues; + } + enic->intr = kcalloc(enic->intr_avail, sizeof(struct vnic_intr), + GFP_KERNEL); + if (!enic->intr) { + ret = -ENOMEM; + goto free_queues; + } + + return 0; + +free_queues: + enic_free_enic_resources(enic); + return ret; +} + static void enic_dev_deinit(struct enic *enic) { unsigned int i; @@ -2691,6 +2773,7 @@ static void enic_dev_deinit(struct enic *enic) enic_free_vnic_resources(enic); enic_clear_intr_mode(enic); enic_free_affinity_hint(enic); + enic_free_enic_resources(enic); } static void enic_kdump_kernel_config(struct enic *enic) @@ -2734,6 +2817,12 @@ static int enic_dev_init(struct enic *enic) enic_get_res_counts(enic); + err = enic_alloc_enic_resources(enic); + if (err) { + dev_err(dev, "Failed to allocate queues, aborting\n"); + return err; + } + /* modify resource count if we are in kdump_kernel */ enic_kdump_kernel_config(enic); @@ -2746,7 +2835,7 @@ static int enic_dev_init(struct enic *enic) if (err) { dev_err(dev, "Failed to set intr mode based on resource " "counts and system capabilities, aborting\n"); - return err; + goto err_out_free_vnic_resources; } /* Allocate and configure vNIC resources @@ -2788,6 +2877,7 @@ static int enic_dev_init(struct enic *enic) enic_free_affinity_hint(enic); enic_clear_intr_mode(enic); enic_free_vnic_resources(enic); + enic_free_enic_resources(enic); return err; }