aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/Kconfig4
-rw-r--r--drivers/scsi/sata_vsc.c51
2 files changed, 32 insertions, 23 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 5c94a5d4efc0..4035920ce3d8 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -595,10 +595,10 @@ config SCSI_SATA_VIA
595 If unsure, say N. 595 If unsure, say N.
596 596
597config SCSI_SATA_VITESSE 597config SCSI_SATA_VITESSE
598 tristate "VITESSE VSC-7174 SATA support" 598 tristate "VITESSE VSC-7174 / INTEL 31244 SATA support"
599 depends on SCSI_SATA && PCI 599 depends on SCSI_SATA && PCI
600 help 600 help
601 This option enables support for Vitesse VSC7174 Serial ATA. 601 This option enables support for Vitesse VSC7174 and Intel 31244 Serial ATA.
602 602
603 If unsure, say N. 603 If unsure, say N.
604 604
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index b574379a7a82..b7b6c807346d 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -82,17 +82,20 @@
82#define VSC_SATA_PORT_OFFSET 0x200 82#define VSC_SATA_PORT_OFFSET 0x200
83 83
84/* Error interrupt status bit offsets */ 84/* Error interrupt status bit offsets */
85#define VSC_SATA_INT_ERROR_E_OFFSET 2 85#define VSC_SATA_INT_ERROR_CRC 0x40
86#define VSC_SATA_INT_ERROR_P_OFFSET 4 86#define VSC_SATA_INT_ERROR_T 0x20
87#define VSC_SATA_INT_ERROR_T_OFFSET 5 87#define VSC_SATA_INT_ERROR_P 0x10
88#define VSC_SATA_INT_ERROR_M_OFFSET 1 88#define VSC_SATA_INT_ERROR_R 0x8
89#define VSC_SATA_INT_ERROR_E 0x4
90#define VSC_SATA_INT_ERROR_M 0x2
91#define VSC_SATA_INT_PHY_CHANGE 0x1
92#define VSC_SATA_INT_ERROR (VSC_SATA_INT_ERROR_CRC | VSC_SATA_INT_ERROR_T | \
93 VSC_SATA_INT_ERROR_P | VSC_SATA_INT_ERROR_R | \
94 VSC_SATA_INT_ERROR_E | VSC_SATA_INT_ERROR_M | \
95 VSC_SATA_INT_PHY_CHANGE)
96
89#define is_vsc_sata_int_err(port_idx, int_status) \ 97#define is_vsc_sata_int_err(port_idx, int_status) \
90 (int_status & ((1 << (VSC_SATA_INT_ERROR_E_OFFSET + (8 * port_idx))) | \ 98 (int_status & (VSC_SATA_INT_ERROR << (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 99
97 100
98static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) 101static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
@@ -215,14 +218,6 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
215 218
216 ap = host_set->ports[i]; 219 ap = host_set->ports[i];
217 220
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
226 if (ap && !(ap->flags & 221 if (ap && !(ap->flags &
227 (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { 222 (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
228 struct ata_queued_cmd *qc; 223 struct ata_queued_cmd *qc;
@@ -230,12 +225,26 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance,
230 qc = ata_qc_from_tag(ap, ap->active_tag); 225 qc = ata_qc_from_tag(ap, ap->active_tag);
231 if (qc && (!(qc->tf.ctl & ATA_NIEN))) { 226 if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
232 handled += ata_host_intr(ap, qc); 227 handled += ata_host_intr(ap, qc);
233 } else { 228 } else if (is_vsc_sata_int_err(i, int_status)) {
234 printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__); 229 /*
230 * On some chips (i.e. Intel 31244), an error
231 * interrupt will sneak in at initialization
232 * time (phy state changes). Clearing the SCR
233 * error register is not required, but it prevents
234 * the phy state change interrupts from recurring
235 * later.
236 */
237 u32 err_status;
238 err_status = vsc_sata_scr_read(ap, SCR_ERROR);
239 printk(KERN_DEBUG "%s: clearing interrupt, "
240 "status %x; sata err status %x\n",
241 __FUNCTION__,
242 int_status, err_status);
243 vsc_sata_scr_write(ap, SCR_ERROR, err_status);
244 /* Clear interrupt status */
235 ata_chk_status(ap); 245 ata_chk_status(ap);
236 handled++; 246 handled++;
237 } 247 }
238
239 } 248 }
240 } 249 }
241 } 250 }