diff options
author | Dan Williams <dan.j.williams@gmail.com> | 2006-03-21 22:07:13 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-03-21 22:07:13 -0500 |
commit | c962990a38167aacac91738501815deffa3afbd6 (patch) | |
tree | 13f77d5d7619a4b71f2f5e0914b4b6976c54bab7 /drivers/scsi/sata_vsc.c | |
parent | 4d4681f6b994baf93dff0e4f59ab4fe38b49ef13 (diff) |
[libata] sata_vsc: fix inconsistent NULL checking
Also, cleanup interrupt mask content and note in Kconfig that this
driver supports the Intel 31244.
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/scsi/sata_vsc.c')
-rw-r--r-- | drivers/scsi/sata_vsc.c | 51 |
1 files changed, 30 insertions, 21 deletions
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 | } |