summaryrefslogtreecommitdiff
path: root/drivers/ata/libahci.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-09-05 18:21:45 +0300
committerTejun Heo <tj@kernel.org>2016-09-06 19:38:17 +0300
commit0b9e2988ab2261fd6d4a0039edf81ed1e3662be8 (patch)
tree75dbefd4076fca402d2c62b4e62bd0e4469439e0 /drivers/ata/libahci.c
parent2536524a91fe5c5a9fddd282fd4e79ee0976aefe (diff)
downloadlinux-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.c11
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 {