diff options
author | Albert Lee <albertcc@tw.ibm.com> | 2005-09-27 05:39:50 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-28 12:07:13 -0400 |
commit | e50362eccd8809a224cda5f71714a088ba37b2ab (patch) | |
tree | 762b753691ef8c4645efaa677b32c57fd33ecbc0 | |
parent | 312f7da2824c82800ee78d6190f12854456957af (diff) |
[PATCH] libata: interrupt driven pio for LLD
libata.h:
libata-core:
Add ATA_FLAG_PIO_POLLING flag for LLDs that expect interrupt for
command completion only.
sata_nv.c:
sata_vsc.c:
irq handler is wrapper around ata_host_intr(), can handle PIO interrupts.
sata_promise.c:
sata_sx4.c:
sata_qstor.c:
sata_mv.c:
Private irq handler.
Polling mode ATA_FLAG_PIO_POLLING used for compatibility.
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r-- | drivers/scsi/libata-core.c | 19 | ||||
-rw-r--r-- | drivers/scsi/sata_mv.c | 7 | ||||
-rw-r--r-- | drivers/scsi/sata_nv.c | 4 | ||||
-rw-r--r-- | drivers/scsi/sata_promise.c | 13 | ||||
-rw-r--r-- | drivers/scsi/sata_qstor.c | 11 | ||||
-rw-r--r-- | drivers/scsi/sata_sx4.c | 7 | ||||
-rw-r--r-- | drivers/scsi/sata_vsc.c | 6 | ||||
-rw-r--r-- | include/linux/libata.h | 2 |
8 files changed, 48 insertions, 21 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index cc2d1308826e..f8a590e59f10 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -3356,6 +3356,25 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) | |||
3356 | { | 3356 | { |
3357 | struct ata_port *ap = qc->ap; | 3357 | struct ata_port *ap = qc->ap; |
3358 | 3358 | ||
3359 | /* Use polling pio if the LLD doesn't handle | ||
3360 | * interrupt driven pio and atapi CDB interrupt. | ||
3361 | */ | ||
3362 | if (ap->flags & ATA_FLAG_PIO_POLLING) { | ||
3363 | switch (qc->tf.protocol) { | ||
3364 | case ATA_PROT_PIO: | ||
3365 | case ATA_PROT_ATAPI: | ||
3366 | case ATA_PROT_ATAPI_NODATA: | ||
3367 | qc->tf.flags |= ATA_TFLAG_POLLING; | ||
3368 | break; | ||
3369 | case ATA_PROT_ATAPI_DMA: | ||
3370 | if (qc->dev->flags & ATA_DFLAG_CDB_INTR) | ||
3371 | BUG(); | ||
3372 | break; | ||
3373 | default: | ||
3374 | break; | ||
3375 | } | ||
3376 | } | ||
3377 | |||
3359 | /* select the device */ | 3378 | /* select the device */ |
3360 | ata_dev_select(ap, qc->dev->devno, 1, 0); | 3379 | ata_dev_select(ap, qc->dev->devno, 1, 0); |
3361 | 3380 | ||
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index ea76fe44585e..b8f1f6963179 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c | |||
@@ -241,7 +241,8 @@ static struct ata_port_info mv_port_info[] = { | |||
241 | { /* chip_504x */ | 241 | { /* chip_504x */ |
242 | .sht = &mv_sht, | 242 | .sht = &mv_sht, |
243 | .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 243 | .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
244 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO), | 244 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | |
245 | ATA_FLAG_PIO_POLLING), | ||
245 | .pio_mask = 0x1f, /* pio4-0 */ | 246 | .pio_mask = 0x1f, /* pio4-0 */ |
246 | .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ | 247 | .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ |
247 | .port_ops = &mv_ops, | 248 | .port_ops = &mv_ops, |
@@ -250,7 +251,7 @@ static struct ata_port_info mv_port_info[] = { | |||
250 | .sht = &mv_sht, | 251 | .sht = &mv_sht, |
251 | .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 252 | .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
252 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | | 253 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | |
253 | MV_FLAG_DUAL_HC), | 254 | ATA_FLAG_PIO_POLLING | MV_FLAG_DUAL_HC), |
254 | .pio_mask = 0x1f, /* pio4-0 */ | 255 | .pio_mask = 0x1f, /* pio4-0 */ |
255 | .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ | 256 | .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ |
256 | .port_ops = &mv_ops, | 257 | .port_ops = &mv_ops, |
@@ -259,6 +260,7 @@ static struct ata_port_info mv_port_info[] = { | |||
259 | .sht = &mv_sht, | 260 | .sht = &mv_sht, |
260 | .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 261 | .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
261 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | | 262 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | |
263 | ATA_FLAG_PIO_POLLING | | ||
262 | MV_FLAG_IRQ_COALESCE | MV_FLAG_BDMA), | 264 | MV_FLAG_IRQ_COALESCE | MV_FLAG_BDMA), |
263 | .pio_mask = 0x1f, /* pio4-0 */ | 265 | .pio_mask = 0x1f, /* pio4-0 */ |
264 | .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ | 266 | .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ |
@@ -268,6 +270,7 @@ static struct ata_port_info mv_port_info[] = { | |||
268 | .sht = &mv_sht, | 270 | .sht = &mv_sht, |
269 | .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 271 | .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
270 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | | 272 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | |
273 | ATA_FLAG_PIO_POLLING | | ||
271 | MV_FLAG_IRQ_COALESCE | MV_FLAG_DUAL_HC | | 274 | MV_FLAG_IRQ_COALESCE | MV_FLAG_DUAL_HC | |
272 | MV_FLAG_BDMA), | 275 | MV_FLAG_BDMA), |
273 | .pio_mask = 0x1f, /* pio4-0 */ | 276 | .pio_mask = 0x1f, /* pio4-0 */ |
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index c05653c7779d..8b7e871ea0bf 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c | |||
@@ -304,11 +304,11 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, | |||
304 | 304 | ||
305 | ap = host_set->ports[i]; | 305 | ap = host_set->ports[i]; |
306 | if (ap && | 306 | if (ap && |
307 | !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { | 307 | !(ap->flags & ATA_FLAG_PORT_DISABLED)) { |
308 | struct ata_queued_cmd *qc; | 308 | struct ata_queued_cmd *qc; |
309 | 309 | ||
310 | qc = ata_qc_from_tag(ap, ap->active_tag); | 310 | qc = ata_qc_from_tag(ap, ap->active_tag); |
311 | if (qc && (!(qc->tf.ctl & ATA_NIEN))) | 311 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) |
312 | handled += ata_host_intr(ap, qc); | 312 | handled += ata_host_intr(ap, qc); |
313 | } | 313 | } |
314 | 314 | ||
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index def7e0d9dacb..f67deb0a55c9 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c | |||
@@ -162,7 +162,8 @@ static struct ata_port_info pdc_port_info[] = { | |||
162 | { | 162 | { |
163 | .sht = &pdc_ata_sht, | 163 | .sht = &pdc_ata_sht, |
164 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 164 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
165 | ATA_FLAG_SRST | ATA_FLAG_MMIO, | 165 | ATA_FLAG_SRST | ATA_FLAG_MMIO | |
166 | ATA_FLAG_PIO_POLLING, | ||
166 | .pio_mask = 0x1f, /* pio0-4 */ | 167 | .pio_mask = 0x1f, /* pio0-4 */ |
167 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 168 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
168 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 169 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
@@ -173,7 +174,8 @@ static struct ata_port_info pdc_port_info[] = { | |||
173 | { | 174 | { |
174 | .sht = &pdc_ata_sht, | 175 | .sht = &pdc_ata_sht, |
175 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 176 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
176 | ATA_FLAG_SRST | ATA_FLAG_MMIO, | 177 | ATA_FLAG_SRST | ATA_FLAG_MMIO | |
178 | ATA_FLAG_PIO_POLLING, | ||
177 | .pio_mask = 0x1f, /* pio0-4 */ | 179 | .pio_mask = 0x1f, /* pio0-4 */ |
178 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 180 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
179 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 181 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
@@ -184,7 +186,8 @@ static struct ata_port_info pdc_port_info[] = { | |||
184 | { | 186 | { |
185 | .sht = &pdc_ata_sht, | 187 | .sht = &pdc_ata_sht, |
186 | .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | | 188 | .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | |
187 | ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS, | 189 | ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS | |
190 | ATA_FLAG_PIO_POLLING, | ||
188 | .pio_mask = 0x1f, /* pio0-4 */ | 191 | .pio_mask = 0x1f, /* pio0-4 */ |
189 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 192 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
190 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 193 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
@@ -493,11 +496,11 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r | |||
493 | ap = host_set->ports[i]; | 496 | ap = host_set->ports[i]; |
494 | tmp = mask & (1 << (i + 1)); | 497 | tmp = mask & (1 << (i + 1)); |
495 | if (tmp && ap && | 498 | if (tmp && ap && |
496 | !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { | 499 | !(ap->flags & ATA_FLAG_PORT_DISABLED)) { |
497 | struct ata_queued_cmd *qc; | 500 | struct ata_queued_cmd *qc; |
498 | 501 | ||
499 | qc = ata_qc_from_tag(ap, ap->active_tag); | 502 | qc = ata_qc_from_tag(ap, ap->active_tag); |
500 | if (qc && (!(qc->tf.ctl & ATA_NIEN))) | 503 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) |
501 | handled += pdc_host_intr(ap, qc); | 504 | handled += pdc_host_intr(ap, qc); |
502 | } | 505 | } |
503 | } | 506 | } |
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index ffcdeb68641c..a604afafaecc 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c | |||
@@ -175,7 +175,7 @@ static struct ata_port_info qs_port_info[] = { | |||
175 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 175 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
176 | ATA_FLAG_SATA_RESET | | 176 | ATA_FLAG_SATA_RESET | |
177 | //FIXME ATA_FLAG_SRST | | 177 | //FIXME ATA_FLAG_SRST | |
178 | ATA_FLAG_MMIO, | 178 | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, |
179 | .pio_mask = 0x10, /* pio4 */ | 179 | .pio_mask = 0x10, /* pio4 */ |
180 | .udma_mask = 0x7f, /* udma0-6 */ | 180 | .udma_mask = 0x7f, /* udma0-6 */ |
181 | .port_ops = &qs_ata_ops, | 181 | .port_ops = &qs_ata_ops, |
@@ -389,14 +389,13 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set) | |||
389 | DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n", | 389 | DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n", |
390 | sff1, sff0, port_no, sHST, sDST); | 390 | sff1, sff0, port_no, sHST, sDST); |
391 | handled = 1; | 391 | handled = 1; |
392 | if (ap && !(ap->flags & | 392 | if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) { |
393 | (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { | ||
394 | struct ata_queued_cmd *qc; | 393 | struct ata_queued_cmd *qc; |
395 | struct qs_port_priv *pp = ap->private_data; | 394 | struct qs_port_priv *pp = ap->private_data; |
396 | if (!pp || pp->state != qs_state_pkt) | 395 | if (!pp || pp->state != qs_state_pkt) |
397 | continue; | 396 | continue; |
398 | qc = ata_qc_from_tag(ap, ap->active_tag); | 397 | qc = ata_qc_from_tag(ap, ap->active_tag); |
399 | if (qc && (!(qc->tf.ctl & ATA_NIEN))) { | 398 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { |
400 | switch (sHST) { | 399 | switch (sHST) { |
401 | case 0: /* sucessful CPB */ | 400 | case 0: /* sucessful CPB */ |
402 | case 3: /* device error */ | 401 | case 3: /* device error */ |
@@ -422,13 +421,13 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) | |||
422 | struct ata_port *ap; | 421 | struct ata_port *ap; |
423 | ap = host_set->ports[port_no]; | 422 | ap = host_set->ports[port_no]; |
424 | if (ap && | 423 | if (ap && |
425 | !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { | 424 | !(ap->flags & ATA_FLAG_PORT_DISABLED)) { |
426 | struct ata_queued_cmd *qc; | 425 | struct ata_queued_cmd *qc; |
427 | struct qs_port_priv *pp = ap->private_data; | 426 | struct qs_port_priv *pp = ap->private_data; |
428 | if (!pp || pp->state != qs_state_mmio) | 427 | if (!pp || pp->state != qs_state_mmio) |
429 | continue; | 428 | continue; |
430 | qc = ata_qc_from_tag(ap, ap->active_tag); | 429 | qc = ata_qc_from_tag(ap, ap->active_tag); |
431 | if (qc && (!(qc->tf.ctl & ATA_NIEN))) { | 430 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { |
432 | 431 | ||
433 | /* check main status, clearing INTRQ */ | 432 | /* check main status, clearing INTRQ */ |
434 | u8 status = ata_chk_status(ap); | 433 | u8 status = ata_chk_status(ap); |
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 540a85191172..a9f9f7685a59 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c | |||
@@ -219,7 +219,8 @@ static struct ata_port_info pdc_port_info[] = { | |||
219 | { | 219 | { |
220 | .sht = &pdc_sata_sht, | 220 | .sht = &pdc_sata_sht, |
221 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | | 221 | .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | |
222 | ATA_FLAG_SRST | ATA_FLAG_MMIO, | 222 | ATA_FLAG_SRST | ATA_FLAG_MMIO | |
223 | ATA_FLAG_PIO_POLLING, | ||
223 | .pio_mask = 0x1f, /* pio0-4 */ | 224 | .pio_mask = 0x1f, /* pio0-4 */ |
224 | .mwdma_mask = 0x07, /* mwdma0-2 */ | 225 | .mwdma_mask = 0x07, /* mwdma0-2 */ |
225 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ | 226 | .udma_mask = 0x7f, /* udma0-6 ; FIXME */ |
@@ -832,11 +833,11 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re | |||
832 | tmp = mask & (1 << i); | 833 | tmp = mask & (1 << i); |
833 | VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); | 834 | VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); |
834 | if (tmp && ap && | 835 | if (tmp && ap && |
835 | !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { | 836 | !(ap->flags & ATA_FLAG_PORT_DISABLED)) { |
836 | struct ata_queued_cmd *qc; | 837 | struct ata_queued_cmd *qc; |
837 | 838 | ||
838 | qc = ata_qc_from_tag(ap, ap->active_tag); | 839 | qc = ata_qc_from_tag(ap, ap->active_tag); |
839 | if (qc && (!(qc->tf.ctl & ATA_NIEN))) | 840 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) |
840 | handled += pdc20621_host_intr(ap, qc, (i > 4), | 841 | handled += pdc20621_host_intr(ap, qc, (i > 4), |
841 | mmio_base); | 842 | mmio_base); |
842 | } | 843 | } |
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index cf94e0158a8d..92378d768c86 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c | |||
@@ -193,12 +193,12 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, | |||
193 | struct ata_port *ap; | 193 | struct ata_port *ap; |
194 | 194 | ||
195 | ap = host_set->ports[i]; | 195 | ap = host_set->ports[i]; |
196 | if (ap && !(ap->flags & | 196 | if (ap && |
197 | (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { | 197 | !(ap->flags & ATA_FLAG_PORT_DISABLED)) { |
198 | struct ata_queued_cmd *qc; | 198 | struct ata_queued_cmd *qc; |
199 | 199 | ||
200 | qc = ata_qc_from_tag(ap, ap->active_tag); | 200 | qc = ata_qc_from_tag(ap, ap->active_tag); |
201 | if (qc && (!(qc->tf.ctl & ATA_NIEN))) | 201 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) |
202 | handled += ata_host_intr(ap, qc); | 202 | handled += ata_host_intr(ap, qc); |
203 | } | 203 | } |
204 | } | 204 | } |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 9ac2b69df3c1..ea8ab29aa92e 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -116,6 +116,8 @@ enum { | |||
116 | ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ | 116 | ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ |
117 | ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ | 117 | ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ |
118 | ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ | 118 | ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ |
119 | ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD | ||
120 | * doesn't handle PIO interrupts */ | ||
119 | 121 | ||
120 | ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ | 122 | ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ |
121 | ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ | 123 | ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ |