aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sata_vsc.c
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2006-02-20 02:16:23 -0500
committerJeff Garzik <jgarzik@pobox.com>2006-02-20 02:16:23 -0500
commit5b2ffed906a3ebd4e52a5bbef06b99a517c53e4b (patch)
tree2f900f89d93db6b0822d8bdf4f49851c581c12a6 /drivers/scsi/sata_vsc.c
parentf1b318793dcd2d9ff6b5ac06e7762098fa079cee (diff)
parentbd71c2b17468a2531fb4c81ec1d73520845e97e1 (diff)
Merge branch 'master'
Diffstat (limited to 'drivers/scsi/sata_vsc.c')
-rw-r--r--drivers/scsi/sata_vsc.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index e124db8e8284..b574379a7a82 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -81,6 +81,19 @@
81/* Port stride */ 81/* Port stride */
82#define VSC_SATA_PORT_OFFSET 0x200 82#define VSC_SATA_PORT_OFFSET 0x200
83 83
84/* Error interrupt status bit offsets */
85#define VSC_SATA_INT_ERROR_E_OFFSET 2
86#define VSC_SATA_INT_ERROR_P_OFFSET 4
87#define VSC_SATA_INT_ERROR_T_OFFSET 5
88#define VSC_SATA_INT_ERROR_M_OFFSET 1
89#define is_vsc_sata_int_err(port_idx, int_status) \
90 (int_status & ((1 << (VSC_SATA_INT_ERROR_E_OFFSET + (8 * port_idx))) | \
91 (1 << (VSC_SATA_INT_ERROR_P_OFFSET + (8 * port_idx))) | \
92 (1 << (VSC_SATA_INT_ERROR_T_OFFSET + (8 * port_idx))) | \
93 (1 << (VSC_SATA_INT_ERROR_M_OFFSET + (8 * port_idx))) \
94 )\
95 )
96
84 97
85static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) 98static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
86{ 99{
@@ -201,13 +214,28 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
201 struct ata_port *ap; 214 struct ata_port *ap;
202 215
203 ap = host_set->ports[i]; 216 ap = host_set->ports[i];
217
218 if (is_vsc_sata_int_err(i, int_status)) {
219 u32 err_status;
220 printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
221 err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0;
222 vsc_sata_scr_write(ap, SCR_ERROR, err_status);
223 handled++;
224 }
225
204 if (ap && !(ap->flags & 226 if (ap && !(ap->flags &
205 (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { 227 (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
206 struct ata_queued_cmd *qc; 228 struct ata_queued_cmd *qc;
207 229
208 qc = ata_qc_from_tag(ap, ap->active_tag); 230 qc = ata_qc_from_tag(ap, ap->active_tag);
209 if (qc && (!(qc->tf.ctl & ATA_NIEN))) 231 if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
210 handled += ata_host_intr(ap, qc); 232 handled += ata_host_intr(ap, qc);
233 } else {
234 printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
235 ata_chk_status(ap);
236 handled++;
237 }
238
211 } 239 }
212 } 240 }
213 } 241 }