From: Tejun Heo <htejun@gmail.com>
To: jgarzik@pobox.com, alan@lxorguk.ukuu.org.uk, axboe@suse.de,
albertcc@tw.ibm.com, lkosewsk@gmail.com,
linux-ide@vger.kernel.org
Cc: Tejun Heo <htejun@gmail.com>
Subject: [PATCH 12/15] sata_sil: new interrupt handler
Date: Tue, 11 Apr 2006 23:14:08 +0900 [thread overview]
Message-ID: <11447648483027-git-send-email-htejun@gmail.com> (raw)
In-Reply-To: <1144764846705-git-send-email-htejun@gmail.com>
The DMA complete bit of these controllers reflects ATA IRQ status
while no DMA command is in progress. So, we can tell whether the
controller is raising an interrupt or not in deterministic manner.
This patch gives sata_sil its own interrupt handler which behaves much
better than the original one in terms of error detection and handling.
This change is also necessary for later hotplug support.
Further improvements are possible, in both 2 and 4 ports versions, we
can get all status with only one readl and using custom bmdma
operations can further cut down register accesses.
Signed-off-by: Tejun Heo <htejun@gmail.com>
---
drivers/scsi/sata_sil.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 81 insertions(+), 1 deletions(-)
cae31a3e780bd2cef46e299e6bf681af88d7f51d
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index e46c044..0b72585 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -112,6 +112,8 @@ static u32 sil_scr_read (struct ata_port
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static int sil_probe_reset(struct ata_port *ap, unsigned int *classes);
static void sil_post_set_mode (struct ata_port *ap);
+static irqreturn_t sil_interrupt(int irq, void *dev_instance,
+ struct pt_regs *regs);
static void sil_freeze(struct ata_port *ap);
static void sil_error_handler(struct ata_port *ap);
@@ -197,7 +199,7 @@ static const struct ata_port_operations
.freeze = sil_freeze,
.error_handler = sil_error_handler,
.post_internal_cmd = ata_bmdma_post_internal_cmd,
- .irq_handler = ata_interrupt,
+ .irq_handler = sil_interrupt,
.irq_clear = ata_bmdma_irq_clear,
.scr_read = sil_scr_read,
.scr_write = sil_scr_write,
@@ -357,6 +359,84 @@ static int sil_probe_reset(struct ata_po
sil_postreset, classes);
}
+static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+{
+ struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+ u8 status;
+
+ if (unlikely(!qc || qc->tf.ctl & ATA_NIEN))
+ goto freeze;
+
+ switch (qc->tf.protocol) {
+ case ATA_PROT_DMA:
+ case ATA_PROT_ATAPI_DMA:
+ case ATA_PROT_ATAPI:
+ if (bmdma2 & SIL_DMA_ERROR) {
+ qc->err_mask |= AC_ERR_HOST_BUS;
+ goto freeze;
+ }
+
+ /* clear DMA-Start bit */
+ ap->ops->bmdma_stop(qc);
+
+ /* fall through */
+ case ATA_PROT_ATAPI_NODATA:
+ case ATA_PROT_NODATA:
+ /* check main status, clearing INTRQ */
+ status = ata_chk_status(ap);
+ if (unlikely(status & ATA_BUSY)) {
+ qc->err_mask |= AC_ERR_HSM;
+ goto freeze;
+ }
+
+ /* ack bmdma irq events */
+ ap->ops->irq_clear(ap);
+
+ /* complete taskfile transaction */
+ qc->err_mask |= ac_err_mask(status);
+ ata_qc_complete(qc);
+ break;
+
+ default:
+ goto freeze;
+ }
+ return;
+
+ freeze:
+ ata_eh_schedule_port(ap, ATA_EH_FREEZE);
+}
+
+static irqreturn_t sil_interrupt(int irq, void *dev_instance,
+ struct pt_regs *regs)
+{
+ struct ata_host_set *host_set = dev_instance;
+ void __iomem *mmio_base = host_set->mmio_base;
+ int handled = 0;
+ unsigned long flags;
+ int i;
+
+ /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
+ spin_lock_irqsave(&host_set->lock, flags);
+
+ for (i = 0; i < host_set->n_ports; i++) {
+ struct ata_port *ap = host_set->ports[i];
+ u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2);
+
+ if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
+ continue;
+
+ if (!(bmdma2 & SIL_DMA_COMPLETE))
+ continue;
+
+ sil_host_intr(ap, bmdma2);
+ handled = 1;
+ }
+
+ spin_unlock_irqrestore(&host_set->lock, flags);
+
+ return IRQ_RETVAL(handled);
+}
+
static void sil_freeze(struct ata_port *ap)
{
void __iomem *mmio_base = ap->host_set->mmio_base;
--
1.2.4
next prev parent reply other threads:[~2006-04-11 14:14 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-04-11 14:14 [PATCHSET 9/9] add hotplug support Tejun Heo
2006-04-11 14:14 ` [PATCH 07/15] libata-hp: implement transportt->user_scan Tejun Heo
2006-04-11 14:14 ` [PATCH 05/15] libata-hp: implement ata_scsi_slave_destroy() Tejun Heo
2006-04-12 5:27 ` Tejun Heo
2006-04-12 22:32 ` Jeff Garzik
2006-04-13 3:46 ` Tejun Heo
2006-04-11 14:14 ` [PATCH 03/15] libata-hp: implement ata_eh_scsi_hotplug() Tejun Heo
2006-04-11 14:14 ` [PATCH 06/15] libata-hp: use ata_scsi_slave_destroy() in low level drivers Tejun Heo
2006-04-11 14:14 ` [PATCH 04/15] libata-hp: connect ATA hotplug events to SCSI hotplug Tejun Heo
2006-04-11 14:14 ` [PATCH 08/15] libata-hp: add hotplug hooks into regular EH Tejun Heo
2006-04-11 14:14 ` [PATCH 09/15] libata-hp: activate hotplug by adding a call to ata_eh_hotplug() from EH Tejun Heo
2006-04-13 8:18 ` zhao, forrest
2006-04-13 8:45 ` Tejun Heo
2006-04-13 9:00 ` zhao, forrest
2006-04-13 9:30 ` Tejun Heo
2006-04-11 14:14 ` [PATCH 02/15] libata-hp: implement ata_eh_hotplug() Tejun Heo
2006-04-11 14:14 ` [PATCH 01/15] libata-hp: implement ata_eh_detach_dev() Tejun Heo
2006-04-11 14:14 ` [PATCH 10/15] libata-hp: skip EH reset if no device to recover and hotplug pending Tejun Heo
2006-04-11 14:14 ` [PATCH 13/15] sata_sil: add hotplug support Tejun Heo
2006-04-11 14:14 ` Tejun Heo [this message]
2006-04-11 14:14 ` [PATCH 15/15] sata_sil24: " Tejun Heo
2006-04-11 14:14 ` [PATCH 11/15] sata_sil: add new constants in preparation for new interrupt handler Tejun Heo
2006-04-11 14:14 ` [PATCH 14/15] ahci: add hotplug support Tejun Heo
2006-04-12 1:49 ` [PATCHSET 9/9] " Tejun Heo
2006-04-13 7:53 ` zhao, forrest
2006-04-13 8:49 ` Tejun Heo
2006-04-13 16:07 ` Jeff Garzik
2006-04-13 16:50 ` Tejun Heo
2006-04-27 9:29 ` Jeff Garzik
2006-04-27 10:53 ` Tejun Heo
2006-04-27 11:29 ` Jeff Garzik
2006-04-27 12:38 ` Tejun Heo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=11447648483027-git-send-email-htejun@gmail.com \
--to=htejun@gmail.com \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=albertcc@tw.ibm.com \
--cc=axboe@suse.de \
--cc=jgarzik@pobox.com \
--cc=linux-ide@vger.kernel.org \
--cc=lkosewsk@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).