diff mbox

[v2,4/6] AHCI: Conserve interrupts with pci_enable_msi_block_part() interface

Message ID cb77da9322a63c609dc5aa49aa57c9706bf37a24.1378383792.git.agordeev@redhat.com (mailing list archive)
State New, archived
Delegated to: Bjorn Helgaas
Headers show

Commit Message

Alexander Gordeev Sept. 5, 2013, 12:53 p.m. UTC
Make use of the new pci_enable_msi_block_part() interface
and conserve on othewise wasted interrupt resources for 10
of 16 unused MSI vectors on Intel chipsets.

Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
---
 drivers/ata/ahci.c |   46 +++++++++++++++++++++++++++-------------------
 1 files changed, 27 insertions(+), 19 deletions(-)

Comments

Tejun Heo Sept. 5, 2013, 1:10 p.m. UTC | #1
Hello,

On Thu, Sep 05, 2013 at 02:53:47PM +0200, Alexander Gordeev wrote:
> Make use of the new pci_enable_msi_block_part() interface
> and conserve on othewise wasted interrupt resources for 10
> of 16 unused MSI vectors on Intel chipsets.
> 
> Signed-off-by: Alexander Gordeev <agordeev@redhat.com>

 Acked-by: Tejun Heo <tj@kernel.org>

One more question tho.  How much does saving some interrupt vectors
matter?  Are int vectors contrained resource on some configurations?

Thanks.
Alexander Gordeev Sept. 5, 2013, 3:23 p.m. UTC | #2
On Thu, Sep 05, 2013 at 09:10:50AM -0400, Tejun Heo wrote:
> One more question tho.  How much does saving some interrupt vectors
> matter?  Are int vectors contrained resource on some configurations?

Honestly, I am not aware of any configuration struggling with interrupt
vectors. However, conserving on x86 interrupt vector space is always a
good idea IMO. Also, PPC pSeries has a concept of MSI quota, so..

> Thanks.
> 
> -- 
> tejun
diff mbox

Patch

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index db4380d..a6bb618 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1091,26 +1091,34 @@  static inline void ahci_gtf_filter_workaround(struct ata_host *host)
 {}
 #endif
 
-int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
+int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
+			 struct ahci_host_priv *hpriv)
 {
 	int rc;
 	unsigned int maxvec;
 
-	if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) {
-		rc = pci_enable_msi_block_auto(pdev, &maxvec);
-		if (rc > 0) {
-			if ((rc == maxvec) || (rc == 1))
-				return rc;
-			/*
-			 * Assume that advantage of multipe MSIs is negated,
-			 * so fallback to single MSI mode to save resources
-			 */
-			pci_disable_msi(pdev);
-			if (!pci_enable_msi(pdev))
-				return 1;
-		}
-	}
+	if (hpriv->flags & AHCI_HFLAG_NO_MSI)
+		goto intx;
+
+	maxvec = pci_get_msi_cap(pdev);
+	if (maxvec < 0)
+		goto intx;
+	if (maxvec < n_ports)
+		goto single_msi;
+
+	rc = pci_enable_msi_block_part(pdev, n_ports, maxvec);
+	if (rc < 0)
+		goto intx;
+	if (rc)
+		goto single_msi;
+
+	return maxvec;
 
+single_msi:
+	if (!pci_enable_msi(pdev))
+		return 1;
+
+intx:
 	pci_intx(pdev, 1);
 	return 0;
 }
@@ -1277,10 +1285,6 @@  static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
 
-	n_msis = ahci_init_interrupts(pdev, hpriv);
-	if (n_msis > 1)
-		hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
-
 	/* save initial config */
 	ahci_pci_save_initial_config(pdev, hpriv);
 
@@ -1327,6 +1331,10 @@  static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 */
 	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
 
+	n_msis = ahci_init_interrupts(pdev, n_ports, hpriv);
+	if (n_msis > 1)
+		hpriv->flags |= AHCI_HFLAG_MULTI_MSI;
+
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
 	if (!host)
 		return -ENOMEM;