Re: [PATCH RFC 1/1] AHCI: Optimize interrupt processing

2013-04-03 Thread Jeff Garzik

On 03/06/2013 06:26 AM, Alexander Gordeev wrote:

Split interrupt service routine into hardware context handler and
threaded context handler. That allows to protect ports with individual
locks rather than with a single host-wide lock, which results in better
parallelism.

Signed-off-by: Alexander Gordeev 
---
  drivers/ata/acard-ahci.c|8 ++---
  drivers/ata/ahci.c  |   54 ++-
  drivers/ata/ahci.h  |   10 +++--
  drivers/ata/ahci_platform.c |3 +-
  drivers/ata/libahci.c   |   74 +--
  5 files changed, 85 insertions(+), 64 deletions(-)


applied



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH RFC 1/1] AHCI: Optimize interrupt processing

2013-04-02 Thread Alexander Gordeev
On Wed, Mar 06, 2013 at 12:26:47PM +0100, Alexander Gordeev wrote:
> Split interrupt service routine into hardware context handler and
> threaded context handler. That allows to protect ports with individual
> locks rather than with a single host-wide lock, which results in better
> parallelism.

Hi Jeff,

Any comment on this change?
Thanks!

-- 
Regards,
Alexander Gordeev
agord...@redhat.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RFC 1/1] AHCI: Optimize interrupt processing

2013-03-06 Thread Alexander Gordeev
Split interrupt service routine into hardware context handler and
threaded context handler. That allows to protect ports with individual
locks rather than with a single host-wide lock, which results in better
parallelism.

Signed-off-by: Alexander Gordeev 
---
 drivers/ata/acard-ahci.c|8 ++---
 drivers/ata/ahci.c  |   54 ++-
 drivers/ata/ahci.h  |   10 +++--
 drivers/ata/ahci_platform.c |3 +-
 drivers/ata/libahci.c   |   74 +--
 5 files changed, 85 insertions(+), 64 deletions(-)

diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c
index 4e94ba2..e429225 100644
--- a/drivers/ata/acard-ahci.c
+++ b/drivers/ata/acard-ahci.c
@@ -409,7 +409,7 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const 
struct pci_device_id
struct device *dev = &pdev->dev;
struct ahci_host_priv *hpriv;
struct ata_host *host;
-   int n_ports, i, rc;
+   int n_ports, n_msis, i, rc;
 
VPRINTK("ENTER\n");
 
@@ -436,8 +436,7 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const 
struct pci_device_id
return -ENOMEM;
hpriv->flags |= (unsigned long)pi.private_data;
 
-   if (!(hpriv->flags & AHCI_HFLAG_NO_MSI))
-   pci_enable_msi(pdev);
+   n_msis = ahci_init_interrupts(pdev, hpriv);
 
hpriv->mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
 
@@ -499,8 +498,7 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const 
struct pci_device_id
acard_ahci_pci_print_info(host);
 
pci_set_master(pdev);
-   return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED,
-&acard_ahci_sht);
+   return ahci_host_activate(host, pdev->irq, n_msis, &acard_ahci_sht);
 }
 
 module_pci_driver(acard_ahci_pci_driver);
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 29ed8a8..7ab3173 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1080,14 +1080,14 @@ int ahci_init_interrupts(struct pci_dev *pdev, struct 
ahci_host_priv *hpriv)
pci_intx(pdev, 1);
return 0;
 }
+EXPORT_SYMBOL_GPL(ahci_init_interrupts);
 
 /**
  * ahci_host_activate - start AHCI host, request IRQs and register it
  * @host: target ATA host
  * @irq: base IRQ number to request
  * @n_msis: number of MSIs allocated for this host
- * @irq_handler: irq_handler used when requesting IRQs
- * @irq_flags: irq_flags used when requesting IRQs
+ * @sht: scsi_host_template to use when registering the host
  *
  * Similar to ata_host_activate, but requests IRQs according to AHCI-1.1
  * when multiple MSIs were allocated. That is one MSI per port, starting
@@ -1099,43 +1099,59 @@ int ahci_init_interrupts(struct pci_dev *pdev, struct 
ahci_host_priv *hpriv)
  * RETURNS:
  * 0 on success, -errno otherwise.
  */
-int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis)
+int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis,
+  struct scsi_host_template *sht)
 {
int i, rc;
-
-   /* Sharing Last Message among several ports is not supported */
-   if (n_msis < host->n_ports)
-   return -EINVAL;
+   unsigned int n_irqs;
 
rc = ata_host_start(host);
if (rc)
return rc;
 
-   for (i = 0; i < host->n_ports; i++) {
-   rc = devm_request_threaded_irq(host->dev,
-   irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED,
-   dev_driver_string(host->dev), host->ports[i]);
+   n_irqs = min(host->n_ports, n_msis);
+   n_irqs = max(n_irqs, 1u);
+
+   if (n_irqs > 1) {
+   /* Sharing Last Message among several ports is not supported */
+   if (n_irqs < host->n_ports)
+   return -EINVAL;
+
+   for (i = 0; i < n_irqs; i++) {
+   rc = devm_request_threaded_irq(host->dev, irq + i,
+   ahci_multi_irqs_intr, ahci_port_thread_fn,
+   IRQF_SHARED, dev_driver_string(host->dev),
+   host->ports[i]);
+   if (rc)
+   goto out_free_irqs;
+   }
+   } else {
+   rc = devm_request_threaded_irq(host->dev, irq,
+   ahci_single_irq_intr, ahci_thread_fn, IRQF_SHARED,
+   dev_driver_string(host->dev), host);
if (rc)
-   goto out_free_irqs;
+   goto out;
}
 
-   for (i = 0; i < host->n_ports; i++)
+   for (i = 0; i < n_irqs; i++)
ata_port_desc(host->ports[i], "irq %d", irq + i);
 
-   rc = ata_host_register(host, &ahci_sht);
+   rc = ata_host_register(host, sht);
if (rc)
goto out_free_all_irqs;
 
return 0;