diff options
author | Tejun Heo <htejun@gmail.com> | 2007-11-27 05:28:53 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-01-23 05:24:10 -0500 |
commit | 405e66b38797875e80669eaf72d313dbb76533c3 (patch) | |
tree | a069f0bb4ae1e81a58bc8f8965a2443d25186f0d | |
parent | f20ded38aa54b92dd0af32578b8916d0aa2d9e05 (diff) |
libata: implement protocol tests
Implement protocol tests - ata_is_atapi(), ata_is_nodata(),
ata_is_pio(), ata_is_dma(), ata_is_ncq() and ata_is_data() and use
them to replace is_atapi_taskfile() and hard coded protocol tests.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/ata/ahci.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 36 | ||||
-rw-r--r-- | drivers/ata/sata_fsl.c | 2 | ||||
-rw-r--r-- | drivers/ata/sata_sil.c | 10 | ||||
-rw-r--r-- | drivers/ata/sata_sil24.c | 24 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 2 | ||||
-rw-r--r-- | include/linux/ata.h | 71 |
7 files changed, 82 insertions, 65 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ef5e6b6e6e69..5eee91c73c90 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -1511,7 +1511,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) | |||
1511 | { | 1511 | { |
1512 | struct ata_port *ap = qc->ap; | 1512 | struct ata_port *ap = qc->ap; |
1513 | struct ahci_port_priv *pp = ap->private_data; | 1513 | struct ahci_port_priv *pp = ap->private_data; |
1514 | int is_atapi = is_atapi_taskfile(&qc->tf); | 1514 | int is_atapi = ata_is_atapi(qc->tf.protocol); |
1515 | void *cmd_tbl; | 1515 | void *cmd_tbl; |
1516 | u32 opts; | 1516 | u32 opts; |
1517 | const u32 cmd_fis_len = 5; /* five dwords */ | 1517 | const u32 cmd_fis_len = 5; /* five dwords */ |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index bb9e025522ba..8c7af2c8e8d4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -5358,7 +5358,7 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *q | |||
5358 | (qc->tf.flags & ATA_TFLAG_WRITE)) | 5358 | (qc->tf.flags & ATA_TFLAG_WRITE)) |
5359 | return 1; | 5359 | return 1; |
5360 | 5360 | ||
5361 | if (is_atapi_taskfile(&qc->tf) && | 5361 | if (ata_is_atapi(qc->tf.protocol) && |
5362 | !(qc->dev->flags & ATA_DFLAG_CDB_INTR)) | 5362 | !(qc->dev->flags & ATA_DFLAG_CDB_INTR)) |
5363 | return 1; | 5363 | return 1; |
5364 | } | 5364 | } |
@@ -5955,30 +5955,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active, | |||
5955 | return nr_done; | 5955 | return nr_done; |
5956 | } | 5956 | } |
5957 | 5957 | ||
5958 | static inline int ata_should_dma_map(struct ata_queued_cmd *qc) | ||
5959 | { | ||
5960 | struct ata_port *ap = qc->ap; | ||
5961 | |||
5962 | switch (qc->tf.protocol) { | ||
5963 | case ATA_PROT_NCQ: | ||
5964 | case ATA_PROT_DMA: | ||
5965 | case ATA_PROT_ATAPI_DMA: | ||
5966 | return 1; | ||
5967 | |||
5968 | case ATA_PROT_ATAPI: | ||
5969 | case ATA_PROT_PIO: | ||
5970 | if (ap->flags & ATA_FLAG_PIO_DMA) | ||
5971 | return 1; | ||
5972 | |||
5973 | /* fall through */ | ||
5974 | |||
5975 | default: | ||
5976 | return 0; | ||
5977 | } | ||
5978 | |||
5979 | /* never reached */ | ||
5980 | } | ||
5981 | |||
5982 | /** | 5958 | /** |
5983 | * ata_qc_issue - issue taskfile to device | 5959 | * ata_qc_issue - issue taskfile to device |
5984 | * @qc: command to issue to device | 5960 | * @qc: command to issue to device |
@@ -5995,6 +5971,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) | |||
5995 | { | 5971 | { |
5996 | struct ata_port *ap = qc->ap; | 5972 | struct ata_port *ap = qc->ap; |
5997 | struct ata_link *link = qc->dev->link; | 5973 | struct ata_link *link = qc->dev->link; |
5974 | u8 prot = qc->tf.protocol; | ||
5998 | 5975 | ||
5999 | /* Make sure only one non-NCQ command is outstanding. The | 5976 | /* Make sure only one non-NCQ command is outstanding. The |
6000 | * check is skipped for old EH because it reuses active qc to | 5977 | * check is skipped for old EH because it reuses active qc to |
@@ -6002,7 +5979,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) | |||
6002 | */ | 5979 | */ |
6003 | WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag)); | 5980 | WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag)); |
6004 | 5981 | ||
6005 | if (qc->tf.protocol == ATA_PROT_NCQ) { | 5982 | if (prot == ATA_PROT_NCQ) { |
6006 | WARN_ON(link->sactive & (1 << qc->tag)); | 5983 | WARN_ON(link->sactive & (1 << qc->tag)); |
6007 | 5984 | ||
6008 | if (!link->sactive) | 5985 | if (!link->sactive) |
@@ -6018,7 +5995,8 @@ void ata_qc_issue(struct ata_queued_cmd *qc) | |||
6018 | qc->flags |= ATA_QCFLAG_ACTIVE; | 5995 | qc->flags |= ATA_QCFLAG_ACTIVE; |
6019 | ap->qc_active |= 1 << qc->tag; | 5996 | ap->qc_active |= 1 << qc->tag; |
6020 | 5997 | ||
6021 | if (ata_should_dma_map(qc)) { | 5998 | if (ata_is_dma(prot) || (ata_is_pio(prot) && |
5999 | (ap->flags & ATA_FLAG_PIO_DMA))) { | ||
6022 | if (qc->flags & ATA_QCFLAG_SG) { | 6000 | if (qc->flags & ATA_QCFLAG_SG) { |
6023 | if (ata_sg_setup(qc)) | 6001 | if (ata_sg_setup(qc)) |
6024 | goto sg_err; | 6002 | goto sg_err; |
@@ -6217,8 +6195,8 @@ inline unsigned int ata_host_intr(struct ata_port *ap, | |||
6217 | */ | 6195 | */ |
6218 | 6196 | ||
6219 | /* Check the ATA_DFLAG_CDB_INTR flag is enough here. | 6197 | /* Check the ATA_DFLAG_CDB_INTR flag is enough here. |
6220 | * The flag was turned on only for atapi devices. | 6198 | * The flag was turned on only for atapi devices. No |
6221 | * No need to check is_atapi_taskfile(&qc->tf) again. | 6199 | * need to check ata_is_atapi(qc->tf.protocol) again. |
6222 | */ | 6200 | */ |
6223 | if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) | 6201 | if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) |
6224 | goto idle_irq; | 6202 | goto idle_irq; |
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index d015b4adcfe0..a3c33f165427 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c | |||
@@ -417,7 +417,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc) | |||
417 | } | 417 | } |
418 | 418 | ||
419 | /* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */ | 419 | /* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */ |
420 | if (is_atapi_taskfile(&qc->tf)) { | 420 | if (ata_is_atapi(qc->tf.protocol)) { |
421 | desc_info |= ATAPI_CMD; | 421 | desc_info |= ATAPI_CMD; |
422 | memset((void *)&cd->acmd, 0, 32); | 422 | memset((void *)&cd->acmd, 0, 32); |
423 | memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len); | 423 | memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len); |
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index f5119bf40c24..0b8191b52f97 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c | |||
@@ -416,15 +416,14 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) | |||
416 | */ | 416 | */ |
417 | 417 | ||
418 | /* Check the ATA_DFLAG_CDB_INTR flag is enough here. | 418 | /* Check the ATA_DFLAG_CDB_INTR flag is enough here. |
419 | * The flag was turned on only for atapi devices. | 419 | * The flag was turned on only for atapi devices. No |
420 | * No need to check is_atapi_taskfile(&qc->tf) again. | 420 | * need to check ata_is_atapi(qc->tf.protocol) again. |
421 | */ | 421 | */ |
422 | if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) | 422 | if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) |
423 | goto err_hsm; | 423 | goto err_hsm; |
424 | break; | 424 | break; |
425 | case HSM_ST_LAST: | 425 | case HSM_ST_LAST: |
426 | if (qc->tf.protocol == ATA_PROT_DMA || | 426 | if (ata_is_dma(qc->tf.protocol)) { |
427 | qc->tf.protocol == ATA_PROT_ATAPI_DMA) { | ||
428 | /* clear DMA-Start bit */ | 427 | /* clear DMA-Start bit */ |
429 | ap->ops->bmdma_stop(qc); | 428 | ap->ops->bmdma_stop(qc); |
430 | 429 | ||
@@ -451,8 +450,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) | |||
451 | /* kick HSM in the ass */ | 450 | /* kick HSM in the ass */ |
452 | ata_hsm_move(ap, qc, status, 0); | 451 | ata_hsm_move(ap, qc, status, 0); |
453 | 452 | ||
454 | if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || | 453 | if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol)) |
455 | qc->tf.protocol == ATA_PROT_ATAPI_DMA)) | ||
456 | ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2); | 454 | ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2); |
457 | 455 | ||
458 | return; | 456 | return; |
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 864c1c1b8511..fdd3ceac329b 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c | |||
@@ -852,9 +852,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc) | |||
852 | * set. | 852 | * set. |
853 | * | 853 | * |
854 | */ | 854 | */ |
855 | int is_excl = (prot == ATA_PROT_ATAPI || | 855 | int is_excl = (ata_is_atapi(prot) || |
856 | prot == ATA_PROT_ATAPI_NODATA || | ||
857 | prot == ATA_PROT_ATAPI_DMA || | ||
858 | (qc->flags & ATA_QCFLAG_RESULT_TF)); | 856 | (qc->flags & ATA_QCFLAG_RESULT_TF)); |
859 | 857 | ||
860 | if (unlikely(ap->excl_link)) { | 858 | if (unlikely(ap->excl_link)) { |
@@ -885,35 +883,21 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) | |||
885 | 883 | ||
886 | cb = &pp->cmd_block[sil24_tag(qc->tag)]; | 884 | cb = &pp->cmd_block[sil24_tag(qc->tag)]; |
887 | 885 | ||
888 | switch (qc->tf.protocol) { | 886 | if (!ata_is_atapi(qc->tf.protocol)) { |
889 | case ATA_PROT_PIO: | ||
890 | case ATA_PROT_DMA: | ||
891 | case ATA_PROT_NCQ: | ||
892 | case ATA_PROT_NODATA: | ||
893 | prb = &cb->ata.prb; | 887 | prb = &cb->ata.prb; |
894 | sge = cb->ata.sge; | 888 | sge = cb->ata.sge; |
895 | break; | 889 | } else { |
896 | |||
897 | case ATA_PROT_ATAPI: | ||
898 | case ATA_PROT_ATAPI_DMA: | ||
899 | case ATA_PROT_ATAPI_NODATA: | ||
900 | prb = &cb->atapi.prb; | 890 | prb = &cb->atapi.prb; |
901 | sge = cb->atapi.sge; | 891 | sge = cb->atapi.sge; |
902 | memset(cb->atapi.cdb, 0, 32); | 892 | memset(cb->atapi.cdb, 0, 32); |
903 | memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); | 893 | memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); |
904 | 894 | ||
905 | if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { | 895 | if (ata_is_data(qc->tf.protocol)) { |
906 | if (qc->tf.flags & ATA_TFLAG_WRITE) | 896 | if (qc->tf.flags & ATA_TFLAG_WRITE) |
907 | ctrl = PRB_CTRL_PACKET_WRITE; | 897 | ctrl = PRB_CTRL_PACKET_WRITE; |
908 | else | 898 | else |
909 | ctrl = PRB_CTRL_PACKET_READ; | 899 | ctrl = PRB_CTRL_PACKET_READ; |
910 | } | 900 | } |
911 | break; | ||
912 | |||
913 | default: | ||
914 | prb = NULL; /* shut up, gcc */ | ||
915 | sge = NULL; | ||
916 | BUG(); | ||
917 | } | 901 | } |
918 | 902 | ||
919 | prb->ctrl = cpu_to_le16(ctrl); | 903 | prb->ctrl = cpu_to_le16(ctrl); |
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 0829b55c64d2..831294de1d8d 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
@@ -176,7 +176,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) | |||
176 | 176 | ||
177 | ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); | 177 | ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); |
178 | task->uldd_task = qc; | 178 | task->uldd_task = qc; |
179 | if (is_atapi_taskfile(&qc->tf)) { | 179 | if (ata_is_atapi(qc->tf.protocol)) { |
180 | memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); | 180 | memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); |
181 | task->total_xfer_len = qc->nbytes + qc->pad_len; | 181 | task->total_xfer_len = qc->nbytes + qc->pad_len; |
182 | task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem; | 182 | task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem; |
diff --git a/include/linux/ata.h b/include/linux/ata.h index 3fbe6d7784ab..43fecf62773a 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
@@ -324,6 +324,13 @@ enum { | |||
324 | ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ | 324 | ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ |
325 | ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ | 325 | ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ |
326 | ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */ | 326 | ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */ |
327 | |||
328 | /* protocol flags */ | ||
329 | ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */ | ||
330 | ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */ | ||
331 | ATA_PROT_FLAG_DATA = ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA, | ||
332 | ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */ | ||
333 | ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */ | ||
327 | }; | 334 | }; |
328 | 335 | ||
329 | enum ata_tf_protocols { | 336 | enum ata_tf_protocols { |
@@ -373,6 +380,63 @@ struct ata_taskfile { | |||
373 | u8 command; /* IO operation */ | 380 | u8 command; /* IO operation */ |
374 | }; | 381 | }; |
375 | 382 | ||
383 | /* | ||
384 | * protocol tests | ||
385 | */ | ||
386 | static inline unsigned int ata_prot_flags(u8 prot) | ||
387 | { | ||
388 | switch (prot) { | ||
389 | case ATA_PROT_NODATA: | ||
390 | return 0; | ||
391 | case ATA_PROT_PIO: | ||
392 | return ATA_PROT_FLAG_PIO; | ||
393 | case ATA_PROT_DMA: | ||
394 | return ATA_PROT_FLAG_DMA; | ||
395 | case ATA_PROT_NCQ: | ||
396 | return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ; | ||
397 | case ATA_PROT_ATAPI_NODATA: | ||
398 | return ATA_PROT_FLAG_ATAPI; | ||
399 | case ATA_PROT_ATAPI: | ||
400 | return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO; | ||
401 | case ATA_PROT_ATAPI_DMA: | ||
402 | return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA; | ||
403 | } | ||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | static inline int ata_is_atapi(u8 prot) | ||
408 | { | ||
409 | return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI; | ||
410 | } | ||
411 | |||
412 | static inline int ata_is_nodata(u8 prot) | ||
413 | { | ||
414 | return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA); | ||
415 | } | ||
416 | |||
417 | static inline int ata_is_pio(u8 prot) | ||
418 | { | ||
419 | return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO; | ||
420 | } | ||
421 | |||
422 | static inline int ata_is_dma(u8 prot) | ||
423 | { | ||
424 | return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA; | ||
425 | } | ||
426 | |||
427 | static inline int ata_is_ncq(u8 prot) | ||
428 | { | ||
429 | return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ; | ||
430 | } | ||
431 | |||
432 | static inline int ata_is_data(u8 prot) | ||
433 | { | ||
434 | return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA; | ||
435 | } | ||
436 | |||
437 | /* | ||
438 | * id tests | ||
439 | */ | ||
376 | #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) | 440 | #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) |
377 | #define ata_id_has_lba(id) ((id)[49] & (1 << 9)) | 441 | #define ata_id_has_lba(id) ((id)[49] & (1 << 9)) |
378 | #define ata_id_has_dma(id) ((id)[49] & (1 << 8)) | 442 | #define ata_id_has_dma(id) ((id)[49] & (1 << 8)) |
@@ -594,13 +658,6 @@ static inline int atapi_command_packet_set(const u16 *dev_id) | |||
594 | return (dev_id[0] >> 8) & 0x1f; | 658 | return (dev_id[0] >> 8) & 0x1f; |
595 | } | 659 | } |
596 | 660 | ||
597 | static inline int is_atapi_taskfile(const struct ata_taskfile *tf) | ||
598 | { | ||
599 | return (tf->protocol == ATA_PROT_ATAPI) || | ||
600 | (tf->protocol == ATA_PROT_ATAPI_NODATA) || | ||
601 | (tf->protocol == ATA_PROT_ATAPI_DMA); | ||
602 | } | ||
603 | |||
604 | static inline int is_multi_taskfile(struct ata_taskfile *tf) | 661 | static inline int is_multi_taskfile(struct ata_taskfile *tf) |
605 | { | 662 | { |
606 | return (tf->command == ATA_CMD_READ_MULTI) || | 663 | return (tf->command == ATA_CMD_READ_MULTI) || |