aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuman Tripathi <stripathi@apm.com>2016-02-06 00:55:22 -0500
committerTejun Heo <tj@kernel.org>2016-02-11 09:53:51 -0500
commitf070d6715509dafc0af223577c896fe3d204ca88 (patch)
tree28f542f74592ccbd4e044af338931d20d53065a8
parent342decff2b846b46fa61eb5ee40986fab79a9a32 (diff)
libahci: Implement the capability to override the generic ahci interrupt handler.
This patch implements the capability to override the generic AHCI interrupt handler so that specific ahci drivers can implement their own custom interrupt handler routines. It also exports ahci_handle_port_intr so that custom irq_handler implementations can use it. tj: s/ahci_irq_handler/irq_handler/ and updated description. Signed-off-by: Suman Tripathi <stripathi@apm.com> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--drivers/ata/ahci.h2
-rw-r--r--drivers/ata/libahci.c27
2 files changed, 22 insertions, 7 deletions
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index a44c75d4c284..cf48e3ed234a 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -361,6 +361,7 @@ struct ahci_host_priv {
361 * be overridden anytime before the host is activated. 361 * be overridden anytime before the host is activated.
362 */ 362 */
363 void (*start_engine)(struct ata_port *ap); 363 void (*start_engine)(struct ata_port *ap);
364 irqreturn_t (*irq_handler)(int irq, void *dev_instance);
364}; 365};
365 366
366#ifdef CONFIG_PCI_MSI 367#ifdef CONFIG_PCI_MSI
@@ -424,6 +425,7 @@ int ahci_reset_em(struct ata_host *host);
424void ahci_print_info(struct ata_host *host, const char *scc_s); 425void ahci_print_info(struct ata_host *host, const char *scc_s);
425int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht); 426int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht);
426void ahci_error_handler(struct ata_port *ap); 427void ahci_error_handler(struct ata_port *ap);
428u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked);
427 429
428static inline void __iomem *__ahci_port_base(struct ata_host *host, 430static inline void __iomem *__ahci_port_base(struct ata_host *host,
429 unsigned int port_no) 431 unsigned int port_no)
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 402967902cbe..cbfe8a2de4c5 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -113,6 +113,9 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
113 const char *buf, size_t size); 113 const char *buf, size_t size);
114static ssize_t ahci_show_em_supported(struct device *dev, 114static ssize_t ahci_show_em_supported(struct device *dev,
115 struct device_attribute *attr, char *buf); 115 struct device_attribute *attr, char *buf);
116static irqreturn_t ahci_single_edge_irq_intr(int irq, void *dev_instance);
117
118static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance);
116 119
117static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); 120static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
118static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL); 121static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
@@ -512,6 +515,11 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
512 515
513 if (!hpriv->start_engine) 516 if (!hpriv->start_engine)
514 hpriv->start_engine = ahci_start_engine; 517 hpriv->start_engine = ahci_start_engine;
518
519 if (!hpriv->irq_handler)
520 hpriv->irq_handler = (hpriv->flags & AHCI_HFLAG_EDGE_IRQ) ?
521 ahci_single_edge_irq_intr :
522 ahci_single_level_irq_intr;
515} 523}
516EXPORT_SYMBOL_GPL(ahci_save_initial_config); 524EXPORT_SYMBOL_GPL(ahci_save_initial_config);
517 525
@@ -1846,7 +1854,7 @@ static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance)
1846 return IRQ_HANDLED; 1854 return IRQ_HANDLED;
1847} 1855}
1848 1856
1849static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked) 1857u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
1850{ 1858{
1851 unsigned int i, handled = 0; 1859 unsigned int i, handled = 0;
1852 1860
@@ -1872,6 +1880,7 @@ static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
1872 1880
1873 return handled; 1881 return handled;
1874} 1882}
1883EXPORT_SYMBOL_GPL(ahci_handle_port_intr);
1875 1884
1876static irqreturn_t ahci_single_edge_irq_intr(int irq, void *dev_instance) 1885static irqreturn_t ahci_single_edge_irq_intr(int irq, void *dev_instance)
1877{ 1886{
@@ -2535,14 +2544,18 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht)
2535 int irq = hpriv->irq; 2544 int irq = hpriv->irq;
2536 int rc; 2545 int rc;
2537 2546
2538 if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) 2547 if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) {
2548 if (hpriv->irq_handler)
2549 dev_warn(host->dev, "both AHCI_HFLAG_MULTI_MSI flag set \
2550 and custom irq handler implemented\n");
2551
2539 rc = ahci_host_activate_multi_irqs(host, sht); 2552 rc = ahci_host_activate_multi_irqs(host, sht);
2540 else if (hpriv->flags & AHCI_HFLAG_EDGE_IRQ) 2553 } else {
2541 rc = ata_host_activate(host, irq, ahci_single_edge_irq_intr, 2554 rc = ata_host_activate(host, irq, hpriv->irq_handler,
2542 IRQF_SHARED, sht);
2543 else
2544 rc = ata_host_activate(host, irq, ahci_single_level_irq_intr,
2545 IRQF_SHARED, sht); 2555 IRQF_SHARED, sht);
2556 }
2557
2558
2546 return rc; 2559 return rc;
2547} 2560}
2548EXPORT_SYMBOL_GPL(ahci_host_activate); 2561EXPORT_SYMBOL_GPL(ahci_host_activate);