On Wed, May 28, 2025 at 07:52:35PM +0100, Simon Horman wrote:
> On Tue, May 27, 2025 at 08:59:03AM -0700, Shradha Gupta wrote:
> > Currently, the MANA driver allocates MSI-X vectors statically based on
> > MANA_MAX_NUM_QUEUES and num_online_cpus() values and in some cases ends
> > up allocating more vectors than it needs. This is because, by this time
> > we do not have a HW channel and do not know how many IRQs should be
> > allocated.
> > 
> > To avoid this, we allocate 1 MSI-X vector during the creation of HWC and
> > after getting the value supported by hardware, dynamically add the
> > remaining MSI-X vectors.
> > 
> > Signed-off-by: Shradha Gupta <shradhagu...@linux.microsoft.com>
> > Reviewed-by: Haiyang Zhang <haiya...@microsoft.com>
> 
> ...
> 
> > +static int mana_gd_setup_irqs(struct pci_dev *pdev, int nvec)
> > +{
> > +   struct gdma_context *gc = pci_get_drvdata(pdev);
> > +   struct gdma_irq_context *gic;
> > +   int *irqs, *start_irqs, irq;
> > +   unsigned int cpu;
> > +   int err, i;
> > +
> > +   cpus_read_lock();
> > +
> > +   irqs = kmalloc_array(nvec, sizeof(int), GFP_KERNEL);
> > +   if (!irqs) {
> >             err = -ENOMEM;
> > -           goto free_irq_array;
> > +           goto free_irq_vector;
> >     }
> >  
> >     for (i = 0; i < nvec; i++) {
> > -           gic = &gc->irq_contexts[i];
> > +           gic = kzalloc(sizeof(*gic), GFP_KERNEL);
> > +           if (!gic) {
> > +                   err = -ENOMEM;
> > +                   goto free_irq;
> > +           }
> > +
> >             gic->handler = mana_gd_process_eq_events;
> >             INIT_LIST_HEAD(&gic->eq_list);
> >             spin_lock_init(&gic->lock);
> > @@ -1418,69 +1498,128 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
> >                     snprintf(gic->name, MANA_IRQ_NAME_SZ, "mana_q%d@pci:%s",
> >                              i - 1, pci_name(pdev));
> >  
> > -           irq = pci_irq_vector(pdev, i);
> > -           if (irq < 0) {
> > -                   err = irq;
> > -                   goto free_irq;
> > +           irqs[i] = pci_irq_vector(pdev, i);
> > +           if (irqs[i] < 0) {
> > +                   err = irqs[i];
> > +                   goto free_current_gic;
> >             }
> >  
> > -           if (!i) {
> > -                   err = request_irq(irq, mana_gd_intr, 0, gic->name, gic);
> > -                   if (err)
> > -                           goto free_irq;
> > -
> > -                   /* If number of IRQ is one extra than number of online 
> > CPUs,
> > -                    * then we need to assign IRQ0 (hwc irq) and IRQ1 to
> > -                    * same CPU.
> > -                    * Else we will use different CPUs for IRQ0 and IRQ1.
> > -                    * Also we are using cpumask_local_spread instead of
> > -                    * cpumask_first for the node, because the node can be
> > -                    * mem only.
> > -                    */
> > -                   if (start_irq_index) {
> > -                           cpu = cpumask_local_spread(i, gc->numa_node);
> > -                           irq_set_affinity_and_hint(irq, cpumask_of(cpu));
> > -                   } else {
> > -                           irqs[start_irq_index] = irq;
> > -                   }
> > -           } else {
> > -                   irqs[i - start_irq_index] = irq;
> > -                   err = request_irq(irqs[i - start_irq_index], 
> > mana_gd_intr, 0,
> > -                                     gic->name, gic);
> > -                   if (err)
> > -                           goto free_irq;
> > -           }
> > +           err = request_irq(irqs[i], mana_gd_intr, 0, gic->name, gic);
> > +           if (err)
> > +                   goto free_current_gic;
> 
> Jumping to free_current_gic will free start_irqs.
> However, start_irqs isn't initialised until a few lines below.
> 
> Flagged by Smatch.
> 

Thanks Simon, I'll get this in next version

> > +
> > +           xa_store(&gc->irq_contexts, i, gic, GFP_KERNEL);
> >     }
> >  
> > -   err = irq_setup(irqs, nvec - start_irq_index, gc->numa_node, false);
> > +   /* If number of IRQ is one extra than number of online CPUs,
> > +    * then we need to assign IRQ0 (hwc irq) and IRQ1 to
> > +    * same CPU.
> > +    * Else we will use different CPUs for IRQ0 and IRQ1.
> > +    * Also we are using cpumask_local_spread instead of
> > +    * cpumask_first for the node, because the node can be
> > +    * mem only.
> > +    */
> > +   start_irqs = irqs;
> > +   if (nvec > num_online_cpus()) {
> > +           cpu = cpumask_local_spread(0, gc->numa_node);
> > +           irq_set_affinity_and_hint(irqs[0], cpumask_of(cpu));
> > +           irqs++;
> > +           nvec -= 1;
> > +   }
> > +
> > +   err = irq_setup(irqs, nvec, gc->numa_node, false);
> >     if (err)
> >             goto free_irq;
> >  
> > -   gc->max_num_msix = nvec;
> > -   gc->num_msix_usable = nvec;
> >     cpus_read_unlock();
> > -   kfree(irqs);
> > +   kfree(start_irqs);
> >     return 0;
> >  
> > +free_current_gic:
> > +   kfree(gic);
> >  free_irq:
> > -   for (j = i - 1; j >= 0; j--) {
> > -           irq = pci_irq_vector(pdev, j);
> > -           gic = &gc->irq_contexts[j];
> > +   for (i -= 1; i >= 0; i--) {
> > +           irq = pci_irq_vector(pdev, i);
> > +           gic = xa_load(&gc->irq_contexts, i);
> > +           if (WARN_ON(!gic))
> > +                   continue;
> >  
> >             irq_update_affinity_hint(irq, NULL);
> >             free_irq(irq, gic);
> > +           xa_erase(&gc->irq_contexts, i);
> > +           kfree(gic);
> >     }
> >  
> > -   kfree(gc->irq_contexts);
> > -   gc->irq_contexts = NULL;
> > -free_irq_array:
> > -   kfree(irqs);
> > +   kfree(start_irqs);
> >  free_irq_vector:
> >     cpus_read_unlock();
> > -   pci_free_irq_vectors(pdev);
> >     return err;
> >  }
> 
> ...

Reply via email to