diff options
| -rw-r--r-- | drivers/scsi/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/scsi/sata_vsc.c | 51 |
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 | ||
| 597 | config SCSI_SATA_VITESSE | 597 | config 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 | ||
| 98 | static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) | 101 | static 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 | } |
