RE: [PATCH] hpsa: use pci_alloc_irq_vectors and automatic irq affinity

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Christoph Hellwig [mailto:hch@xxxxxx]
> Sent: Wednesday, November 09, 2016 12:42 PM
> To: Don Brace
> Cc: hare@xxxxxxx; linux-scsi@xxxxxxxxxxxxxxx
> Subject: [PATCH] hpsa: use pci_alloc_irq_vectors and automatic irq affinity
> 
> EXTERNAL EMAIL
> 
> 
> This patch converts over hpsa to use the pci_alloc_irq_vectors including
> the PCI_IRQ_AFFINITY flag that automatically assigns spread out
> irq affinity to the I/O queues.
> 
> It also cleans up the per-ctrl interrupt state due to the use of the
> pci_irq_vector and pci_free_irq_vectors helpers that don't need to know
> the exact irq type.  Additionally it changes a little oddity in the
> existing code that was using different array indixes into the per-vector
> arrays depending on wether a controller is using a single INTx or single
> MSI irq.
> 
> Signed-off-by: Christoph Hellwig <hch@xxxxxx>

Acked-by: Don Brace <don.brace@xxxxxxxxxxxxx>
Tested-by: Don Brace <don.brace@xxxxxxxxxxxxx>

> ---
>  drivers/scsi/hpsa.c | 143 ++++++++++++++++++----------------------------------
>  drivers/scsi/hpsa.h |   6 +--
>  2 files changed, 52 insertions(+), 97 deletions(-)
> 
> diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
> index d007ec1..dce8f80 100644
> --- a/drivers/scsi/hpsa.c
> +++ b/drivers/scsi/hpsa.c
> @@ -1001,7 +1001,7 @@ static void set_performant_mode(struct ctlr_info
> *h, struct CommandList *c,
>  {
>         if (likely(h->transMethod & CFGTBL_Trans_Performant)) {
>                 c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
> -               if (unlikely(!h->msix_vector))
> +               if (unlikely(!h->msix_vectors))
>                         return;
>                 if (likely(reply_queue == DEFAULT_REPLY_QUEUE))
>                         c->Header.ReplyQueue =
> @@ -5618,7 +5618,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h)
>         sh->sg_tablesize = h->maxsgentries;
>         sh->transportt = hpsa_sas_transport_template;
>         sh->hostdata[0] = (unsigned long) h;
> -       sh->irq = h->intr[h->intr_mode];
> +       sh->irq = pci_irq_vector(h->pdev, 0);
>         sh->unique_id = sh->irq;
> 
>         h->scsi_host = sh;
> @@ -7652,67 +7652,41 @@ static int find_PCI_BAR_index(struct pci_dev
> *pdev, unsigned long pci_bar_addr)
> 
>  static void hpsa_disable_interrupt_mode(struct ctlr_info *h)
>  {
> -       if (h->msix_vector) {
> -               if (h->pdev->msix_enabled)
> -                       pci_disable_msix(h->pdev);
> -               h->msix_vector = 0;
> -       } else if (h->msi_vector) {
> -               if (h->pdev->msi_enabled)
> -                       pci_disable_msi(h->pdev);
> -               h->msi_vector = 0;
> -       }
> +       pci_free_irq_vectors(h->pdev);
> +       h->msix_vectors = 0;
>  }
> 
>  /* If MSI/MSI-X is supported by the kernel we will try to enable it on
>   * controllers that are capable. If not, we use legacy INTx mode.
>   */
> -static void hpsa_interrupt_mode(struct ctlr_info *h)
> +static int hpsa_interrupt_mode(struct ctlr_info *h)
>  {
> -#ifdef CONFIG_PCI_MSI
> -       int err, i;
> -       struct msix_entry hpsa_msix_entries[MAX_REPLY_QUEUES];
> -
> -       for (i = 0; i < MAX_REPLY_QUEUES; i++) {
> -               hpsa_msix_entries[i].vector = 0;
> -               hpsa_msix_entries[i].entry = i;
> -       }
> +       unsigned int flags = PCI_IRQ_LEGACY;
> +       int ret;
> 
>         /* Some boards advertise MSI but don't really support it */
> -       if ((h->board_id == 0x40700E11) || (h->board_id == 0x40800E11) ||
> -           (h->board_id == 0x40820E11) || (h->board_id == 0x40830E11))
> -               goto default_int_mode;
> -       if (pci_find_capability(h->pdev, PCI_CAP_ID_MSIX)) {
> -               dev_info(&h->pdev->dev, "MSI-X capable controller\n");
> -               h->msix_vector = MAX_REPLY_QUEUES;
> -               if (h->msix_vector > num_online_cpus())
> -                       h->msix_vector = num_online_cpus();
> -               err = pci_enable_msix_range(h->pdev, hpsa_msix_entries,
> -                                           1, h->msix_vector);
> -               if (err < 0) {
> -                       dev_warn(&h->pdev->dev, "MSI-X init failed %d\n", err);
> -                       h->msix_vector = 0;
> -                       goto single_msi_mode;
> -               } else if (err < h->msix_vector) {
> -                       dev_warn(&h->pdev->dev, "only %d MSI-X vectors "
> -                              "available\n", err);
> +       switch (h->board_id) {
> +       case 0x40700E11:
> +       case 0x40800E11:
> +       case 0x40820E11:
> +       case 0x40830E11:
> +               break;
> +       default:
> +               ret = pci_alloc_irq_vectors(h->pdev, 1, MAX_REPLY_QUEUES,
> +                               PCI_IRQ_MSIX | PCI_IRQ_AFFINITY);
> +               if (ret > 0) {
> +                       h->msix_vectors = ret;
> +                       return 0;
>                 }
> -               h->msix_vector = err;
> -               for (i = 0; i < h->msix_vector; i++)
> -                       h->intr[i] = hpsa_msix_entries[i].vector;
> -               return;
> -       }
> -single_msi_mode:
> -       if (pci_find_capability(h->pdev, PCI_CAP_ID_MSI)) {
> -               dev_info(&h->pdev->dev, "MSI capable controller\n");
> -               if (!pci_enable_msi(h->pdev))
> -                       h->msi_vector = 1;
> -               else
> -                       dev_warn(&h->pdev->dev, "MSI init failed\n");
> +
> +               flags |= PCI_IRQ_MSI;
> +               break;
>         }
> -default_int_mode:
> -#endif                         /* CONFIG_PCI_MSI */
> -       /* if we get here we're going to use the default interrupt mode */
> -       h->intr[h->intr_mode] = h->pdev->irq;
> +
> +       ret = pci_alloc_irq_vectors(h->pdev, 1, 1, flags);
> +       if (ret < 0)
> +               return ret;
> +       return 0;
>  }
> 
>  static int hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
> @@ -8068,7 +8042,9 @@ static int hpsa_pci_init(struct ctlr_info *h)
> 
>         pci_set_master(h->pdev);
> 
> -       hpsa_interrupt_mode(h);
> +       err = hpsa_interrupt_mode(h);
> +       if (err)
> +               goto clean1;
>         err = hpsa_pci_find_memory_BAR(h->pdev, &h->paddr);
>         if (err)
>                 goto clean2;    /* intmode+region, pci */
> @@ -8104,6 +8080,7 @@ static int hpsa_pci_init(struct ctlr_info *h)
>         h->vaddr = NULL;
>  clean2:        /* intmode+region, pci */
>         hpsa_disable_interrupt_mode(h);
> +clean1:
>         /*
>          * call pci_disable_device before pci_release_regions per
>          * Documentation/PCI/pci.txt
> @@ -8237,34 +8214,20 @@ static int hpsa_alloc_cmd_pool(struct ctlr_info
> *h)
>         return -ENOMEM;
>  }
> 
> -static void hpsa_irq_affinity_hints(struct ctlr_info *h)
> -{
> -       int i, cpu;
> -
> -       cpu = cpumask_first(cpu_online_mask);
> -       for (i = 0; i < h->msix_vector; i++) {
> -               irq_set_affinity_hint(h->intr[i], get_cpu_mask(cpu));
> -               cpu = cpumask_next(cpu, cpu_online_mask);
> -       }
> -}
> -
>  /* clear affinity hints and free MSI-X, MSI, or legacy INTx vectors */
>  static void hpsa_free_irqs(struct ctlr_info *h)
>  {
>         int i;
> 
> -       if (!h->msix_vector || h->intr_mode != PERF_MODE_INT) {
> +       if (!h->msix_vectors || h->intr_mode != PERF_MODE_INT) {
>                 /* Single reply queue, only one irq to free */
> -               i = h->intr_mode;
> -               irq_set_affinity_hint(h->intr[i], NULL);
> -               free_irq(h->intr[i], &h->q[i]);
> -               h->q[i] = 0;
> +               free_irq(pci_irq_vector(h->pdev, 0), &h->q[i]);
> +               h->q[h->intr_mode] = 0;
>                 return;
>         }
> 
> -       for (i = 0; i < h->msix_vector; i++) {
> -               irq_set_affinity_hint(h->intr[i], NULL);
> -               free_irq(h->intr[i], &h->q[i]);
> +       for (i = 0; i < h->msix_vectors; i++) {
> +               free_irq(pci_irq_vector(h->pdev, i), &h->q[i]);
>                 h->q[i] = 0;
>         }
>         for (; i < MAX_REPLY_QUEUES; i++)
> @@ -8285,11 +8248,11 @@ static int hpsa_request_irqs(struct ctlr_info *h,
>         for (i = 0; i < MAX_REPLY_QUEUES; i++)
>                 h->q[i] = (u8) i;
> 
> -       if (h->intr_mode == PERF_MODE_INT && h->msix_vector > 0) {
> +       if (h->intr_mode == PERF_MODE_INT && h->msix_vectors > 0) {
>                 /* If performant mode and MSI-X, use multiple reply queues */
> -               for (i = 0; i < h->msix_vector; i++) {
> +               for (i = 0; i < h->msix_vectors; i++) {
>                         sprintf(h->intrname[i], "%s-msix%d", h->devname, i);
> -                       rc = request_irq(h->intr[i], msixhandler,
> +                       rc = request_irq(pci_irq_vector(h->pdev, i), msixhandler,
>                                         0, h->intrname[i],
>                                         &h->q[i]);
>                         if (rc) {
> @@ -8297,9 +8260,9 @@ static int hpsa_request_irqs(struct ctlr_info *h,
> 
>                                 dev_err(&h->pdev->dev,
>                                         "failed to get irq %d for %s\n",
> -                                      h->intr[i], h->devname);
> +                                      pci_irq_vector(h->pdev, i), h->devname);
>                                 for (j = 0; j < i; j++) {
> -                                       free_irq(h->intr[j], &h->q[j]);
> +                                       free_irq(pci_irq_vector(h->pdev, j), &h->q[j]);
>                                         h->q[j] = 0;
>                                 }
>                                 for (; j < MAX_REPLY_QUEUES; j++)
> @@ -8307,33 +8270,27 @@ static int hpsa_request_irqs(struct ctlr_info *h,
>                                 return rc;
>                         }
>                 }
> -               hpsa_irq_affinity_hints(h);
>         } else {
>                 /* Use single reply pool */
> -               if (h->msix_vector > 0 || h->msi_vector) {
> -                       if (h->msix_vector)
> -                               sprintf(h->intrname[h->intr_mode],
> -                                       "%s-msix", h->devname);
> -                       else
> -                               sprintf(h->intrname[h->intr_mode],
> -                                       "%s-msi", h->devname);
> -                       rc = request_irq(h->intr[h->intr_mode],
> +               if (h->msix_vectors > 0 || h->pdev->msi_enabled) {
> +                       sprintf(h->intrname[0], "%s-msi%s", h->devname,
> +                               h->msix_vectors ? "x" : "");
> +                       rc = request_irq(pci_irq_vector(h->pdev, 0),
>                                 msixhandler, 0,
> -                               h->intrname[h->intr_mode],
> +                               h->intrname[0],
>                                 &h->q[h->intr_mode]);
>                 } else {
>                         sprintf(h->intrname[h->intr_mode],
>                                 "%s-intx", h->devname);
> -                       rc = request_irq(h->intr[h->intr_mode],
> +                       rc = request_irq(pci_irq_vector(h->pdev, 0),
>                                 intxhandler, IRQF_SHARED,
> -                               h->intrname[h->intr_mode],
> +                               h->intrname[0],
>                                 &h->q[h->intr_mode]);
>                 }
> -               irq_set_affinity_hint(h->intr[h->intr_mode], NULL);
>         }
>         if (rc) {
>                 dev_err(&h->pdev->dev, "failed to get irq %d for %s\n",
> -                      h->intr[h->intr_mode], h->devname);
> +                      pci_irq_vector(h->pdev, 0), h->devname);
>                 hpsa_free_irqs(h);
>                 return -ENODEV;
>         }
> @@ -9519,7 +9476,7 @@ static int
> hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
>                         return rc;
>         }
> 
> -       h->nreply_queues = h->msix_vector > 0 ? h->msix_vector : 1;
> +       h->nreply_queues = h->msix_vectors > 0 ? h->msix_vectors : 1;
>         hpsa_get_max_perf_mode_cmds(h);
>         /* Performant mode ring buffer and supporting data structures */
>         h->reply_queue_size = h->max_commands * sizeof(u64);
> diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
> index 82cdfad..3faf6cf 100644
> --- a/drivers/scsi/hpsa.h
> +++ b/drivers/scsi/hpsa.h
> @@ -175,9 +175,7 @@ struct ctlr_info {
>  #      define DOORBELL_INT     1
>  #      define SIMPLE_MODE_INT  2
>  #      define MEMQ_MODE_INT    3
> -       unsigned int intr[MAX_REPLY_QUEUES];
> -       unsigned int msix_vector;
> -       unsigned int msi_vector;
> +       unsigned int msix_vectors;
>         int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
>         struct access_method access;
> 
> @@ -464,7 +462,7 @@ static unsigned long
> SA5_performant_completed(struct ctlr_info *h, u8 q)
>         unsigned long register_value = FIFO_EMPTY;
> 
>         /* msi auto clears the interrupt pending bit. */
> -       if (unlikely(!(h->msi_vector || h->msix_vector))) {
> +       if (unlikely(!(h->pdev->msi_enabled || h->msix_vectors))) {
>                 /* flush the controller write of the reply queue by reading
>                  * outbound doorbell status register.
>                  */
> --
> 2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux