Commit 405e66b3 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

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: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent f20ded38
...@@ -1511,7 +1511,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc) ...@@ -1511,7 +1511,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct ahci_port_priv *pp = ap->private_data; struct ahci_port_priv *pp = ap->private_data;
int is_atapi = is_atapi_taskfile(&qc->tf); int is_atapi = ata_is_atapi(qc->tf.protocol);
void *cmd_tbl; void *cmd_tbl;
u32 opts; u32 opts;
const u32 cmd_fis_len = 5; /* five dwords */ const u32 cmd_fis_len = 5; /* five dwords */
......
...@@ -5358,7 +5358,7 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *q ...@@ -5358,7 +5358,7 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *q
(qc->tf.flags & ATA_TFLAG_WRITE)) (qc->tf.flags & ATA_TFLAG_WRITE))
return 1; return 1;
if (is_atapi_taskfile(&qc->tf) && if (ata_is_atapi(qc->tf.protocol) &&
!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
return 1; return 1;
} }
...@@ -5955,30 +5955,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active, ...@@ -5955,30 +5955,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
return nr_done; return nr_done;
} }
static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
switch (qc->tf.protocol) {
case ATA_PROT_NCQ:
case ATA_PROT_DMA:
case ATA_PROT_ATAPI_DMA:
return 1;
case ATA_PROT_ATAPI:
case ATA_PROT_PIO:
if (ap->flags & ATA_FLAG_PIO_DMA)
return 1;
/* fall through */
default:
return 0;
}
/* never reached */
}
/** /**
* ata_qc_issue - issue taskfile to device * ata_qc_issue - issue taskfile to device
* @qc: command to issue to device * @qc: command to issue to device
...@@ -5995,6 +5971,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) ...@@ -5995,6 +5971,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
struct ata_link *link = qc->dev->link; struct ata_link *link = qc->dev->link;
u8 prot = qc->tf.protocol;
/* Make sure only one non-NCQ command is outstanding. The /* Make sure only one non-NCQ command is outstanding. The
* check is skipped for old EH because it reuses active qc to * 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,7 +5979,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
*/ */
WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag)); WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag));
if (qc->tf.protocol == ATA_PROT_NCQ) { if (prot == ATA_PROT_NCQ) {
WARN_ON(link->sactive & (1 << qc->tag)); WARN_ON(link->sactive & (1 << qc->tag));
if (!link->sactive) if (!link->sactive)
...@@ -6018,7 +5995,8 @@ void ata_qc_issue(struct ata_queued_cmd *qc) ...@@ -6018,7 +5995,8 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
qc->flags |= ATA_QCFLAG_ACTIVE; qc->flags |= ATA_QCFLAG_ACTIVE;
ap->qc_active |= 1 << qc->tag; ap->qc_active |= 1 << qc->tag;
if (ata_should_dma_map(qc)) { if (ata_is_dma(prot) || (ata_is_pio(prot) &&
(ap->flags & ATA_FLAG_PIO_DMA))) {
if (qc->flags & ATA_QCFLAG_SG) { if (qc->flags & ATA_QCFLAG_SG) {
if (ata_sg_setup(qc)) if (ata_sg_setup(qc))
goto sg_err; goto sg_err;
...@@ -6217,8 +6195,8 @@ inline unsigned int ata_host_intr(struct ata_port *ap, ...@@ -6217,8 +6195,8 @@ inline unsigned int ata_host_intr(struct ata_port *ap,
*/ */
/* Check the ATA_DFLAG_CDB_INTR flag is enough here. /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
* The flag was turned on only for atapi devices. * The flag was turned on only for atapi devices. No
* No need to check is_atapi_taskfile(&qc->tf) again. * need to check ata_is_atapi(qc->tf.protocol) again.
*/ */
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
goto idle_irq; goto idle_irq;
......
...@@ -417,7 +417,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc) ...@@ -417,7 +417,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
} }
/* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */ /* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */
if (is_atapi_taskfile(&qc->tf)) { if (ata_is_atapi(qc->tf.protocol)) {
desc_info |= ATAPI_CMD; desc_info |= ATAPI_CMD;
memset((void *)&cd->acmd, 0, 32); memset((void *)&cd->acmd, 0, 32);
memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len); memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len);
......
...@@ -416,15 +416,14 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) ...@@ -416,15 +416,14 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
*/ */
/* Check the ATA_DFLAG_CDB_INTR flag is enough here. /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
* The flag was turned on only for atapi devices. * The flag was turned on only for atapi devices. No
* No need to check is_atapi_taskfile(&qc->tf) again. * need to check ata_is_atapi(qc->tf.protocol) again.
*/ */
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
goto err_hsm; goto err_hsm;
break; break;
case HSM_ST_LAST: case HSM_ST_LAST:
if (qc->tf.protocol == ATA_PROT_DMA || if (ata_is_dma(qc->tf.protocol)) {
qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
/* clear DMA-Start bit */ /* clear DMA-Start bit */
ap->ops->bmdma_stop(qc); ap->ops->bmdma_stop(qc);
...@@ -451,8 +450,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) ...@@ -451,8 +450,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
/* kick HSM in the ass */ /* kick HSM in the ass */
ata_hsm_move(ap, qc, status, 0); ata_hsm_move(ap, qc, status, 0);
if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
qc->tf.protocol == ATA_PROT_ATAPI_DMA))
ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2); ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
return; return;
......
...@@ -852,9 +852,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc) ...@@ -852,9 +852,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
* set. * set.
* *
*/ */
int is_excl = (prot == ATA_PROT_ATAPI || int is_excl = (ata_is_atapi(prot) ||
prot == ATA_PROT_ATAPI_NODATA ||
prot == ATA_PROT_ATAPI_DMA ||
(qc->flags & ATA_QCFLAG_RESULT_TF)); (qc->flags & ATA_QCFLAG_RESULT_TF));
if (unlikely(ap->excl_link)) { if (unlikely(ap->excl_link)) {
...@@ -885,35 +883,21 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) ...@@ -885,35 +883,21 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
cb = &pp->cmd_block[sil24_tag(qc->tag)]; cb = &pp->cmd_block[sil24_tag(qc->tag)];
switch (qc->tf.protocol) { if (!ata_is_atapi(qc->tf.protocol)) {
case ATA_PROT_PIO:
case ATA_PROT_DMA:
case ATA_PROT_NCQ:
case ATA_PROT_NODATA:
prb = &cb->ata.prb; prb = &cb->ata.prb;
sge = cb->ata.sge; sge = cb->ata.sge;
break; } else {
case ATA_PROT_ATAPI:
case ATA_PROT_ATAPI_DMA:
case ATA_PROT_ATAPI_NODATA:
prb = &cb->atapi.prb; prb = &cb->atapi.prb;
sge = cb->atapi.sge; sge = cb->atapi.sge;
memset(cb->atapi.cdb, 0, 32); memset(cb->atapi.cdb, 0, 32);
memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len); memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { if (ata_is_data(qc->tf.protocol)) {
if (qc->tf.flags & ATA_TFLAG_WRITE) if (qc->tf.flags & ATA_TFLAG_WRITE)
ctrl = PRB_CTRL_PACKET_WRITE; ctrl = PRB_CTRL_PACKET_WRITE;
else else
ctrl = PRB_CTRL_PACKET_READ; ctrl = PRB_CTRL_PACKET_READ;
} }
break;
default:
prb = NULL; /* shut up, gcc */
sge = NULL;
BUG();
} }
prb->ctrl = cpu_to_le16(ctrl); prb->ctrl = cpu_to_le16(ctrl);
......
...@@ -176,7 +176,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) ...@@ -176,7 +176,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc)
ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis);
task->uldd_task = qc; task->uldd_task = qc;
if (is_atapi_taskfile(&qc->tf)) { if (ata_is_atapi(qc->tf.protocol)) {
memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len);
task->total_xfer_len = qc->nbytes + qc->pad_len; task->total_xfer_len = qc->nbytes + qc->pad_len;
task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem; task->num_scatter = qc->pad_len ? qc->n_elem + 1 : qc->n_elem;
......
...@@ -324,6 +324,13 @@ enum { ...@@ -324,6 +324,13 @@ enum {
ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ ATA_TFLAG_LBA = (1 << 4), /* enable LBA */
ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ ATA_TFLAG_FUA = (1 << 5), /* enable FUA */
ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */ ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */
/* protocol flags */
ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */
ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */
ATA_PROT_FLAG_DATA = ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA,
ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */
ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */
}; };
enum ata_tf_protocols { enum ata_tf_protocols {
...@@ -373,6 +380,63 @@ struct ata_taskfile { ...@@ -373,6 +380,63 @@ struct ata_taskfile {
u8 command; /* IO operation */ u8 command; /* IO operation */
}; };
/*
* protocol tests
*/
static inline unsigned int ata_prot_flags(u8 prot)
{
switch (prot) {
case ATA_PROT_NODATA:
return 0;
case ATA_PROT_PIO:
return ATA_PROT_FLAG_PIO;
case ATA_PROT_DMA:
return ATA_PROT_FLAG_DMA;
case ATA_PROT_NCQ:
return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ;
case ATA_PROT_ATAPI_NODATA:
return ATA_PROT_FLAG_ATAPI;
case ATA_PROT_ATAPI:
return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO;
case ATA_PROT_ATAPI_DMA:
return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA;
}
return 0;
}
static inline int ata_is_atapi(u8 prot)
{
return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI;
}
static inline int ata_is_nodata(u8 prot)
{
return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA);
}
static inline int ata_is_pio(u8 prot)
{
return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO;
}
static inline int ata_is_dma(u8 prot)
{
return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA;
}
static inline int ata_is_ncq(u8 prot)
{
return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ;
}
static inline int ata_is_data(u8 prot)
{
return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA;
}
/*
* id tests
*/
#define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0)
#define ata_id_has_lba(id) ((id)[49] & (1 << 9)) #define ata_id_has_lba(id) ((id)[49] & (1 << 9))
#define ata_id_has_dma(id) ((id)[49] & (1 << 8)) #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,13 +658,6 @@ static inline int atapi_command_packet_set(const u16 *dev_id)
return (dev_id[0] >> 8) & 0x1f; return (dev_id[0] >> 8) & 0x1f;
} }
static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
{
return (tf->protocol == ATA_PROT_ATAPI) ||
(tf->protocol == ATA_PROT_ATAPI_NODATA) ||
(tf->protocol == ATA_PROT_ATAPI_DMA);
}
static inline int is_multi_taskfile(struct ata_taskfile *tf) static inline int is_multi_taskfile(struct ata_taskfile *tf)
{ {
return (tf->command == ATA_CMD_READ_MULTI) || return (tf->command == ATA_CMD_READ_MULTI) ||
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment