diff options
author | Christoph Hellwig <hch@lst.de> | 2016-09-05 18:21:45 +0300 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2016-09-06 19:38:17 +0300 |
commit | 0b9e2988ab2261fd6d4a0039edf81ed1e3662be8 (patch) | |
tree | 75dbefd4076fca402d2c62b4e62bd0e4469439e0 /drivers/ata/libahci.c | |
parent | 2536524a91fe5c5a9fddd282fd4e79ee0976aefe (diff) | |
download | linux-0b9e2988ab2261fd6d4a0039edf81ed1e3662be8.tar.xz |
ahci: use pci_alloc_irq_vectors
Use the new pci_alloc_irq_vectors API to allocate MSI-X and MSI vectors.
The big advantage over the old code is that we can use the same API for
MSI and MSI-X, and that we don't need to store the MSI-X vector mapping
in driver-private data structures.
This first conversion keeps the probe order as-is: MSI-X multi vector,
MSI multi vector, MSI single vector, MSI-X single vector and last a
single least legacy interrupt line. There is one small change of
behavior: we now check the "MSI Revert to Single Message" flag for
MSI-X in addition to MSI.
Because the API to find the Linux IRQ number for a MSI/MSI-X vector
is PCI specific, but libahaci is bus-agnostic I had to a
get_irq_vector function pointer to struct ahci_host_priv. The
alternative would be to move the multi-vector case of ahci_host_activate
to ahci.c and just call ata_host_activate directly from the others
users of ahci_host_activate.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata/libahci.c')
-rw-r--r-- | drivers/ata/libahci.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 5a1329e31609..0d028ead99e8 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -2378,7 +2378,7 @@ static int ahci_port_start(struct ata_port *ap) /* * Switch to per-port locking in case each port has its own MSI vector. */ - if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) { + if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) { spin_lock_init(&pp->lock); ap->lock = &pp->lock; } @@ -2520,7 +2520,7 @@ static int ahci_host_activate_multi_irqs(struct ata_host *host, */ for (i = 0; i < host->n_ports; i++) { struct ahci_port_priv *pp = host->ports[i]->private_data; - int irq = ahci_irq_vector(hpriv, i); + int irq = hpriv->get_irq_vector(host, i); /* Do not receive interrupts sent by dummy ports */ if (!pp) { @@ -2556,10 +2556,15 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht) int irq = hpriv->irq; int rc; - if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) { + if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) { if (hpriv->irq_handler) dev_warn(host->dev, "both AHCI_HFLAG_MULTI_MSI flag set and custom irq handler implemented\n"); + if (!hpriv->get_irq_vector) { + dev_err(host->dev, + "AHCI_HFLAG_MULTI_MSI requires ->get_irq_vector!\n"); + return -EIO; + } rc = ahci_host_activate_multi_irqs(host, sht); } else { |