diff options
-rw-r--r-- | drivers/ata/sata_nv.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 9d9670a9b117..8a9473b16ec3 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
@@ -260,6 +260,7 @@ static int nv_adma_port_resume(struct ata_port *ap); | |||
260 | static void nv_adma_error_handler(struct ata_port *ap); | 260 | static void nv_adma_error_handler(struct ata_port *ap); |
261 | static void nv_adma_host_stop(struct ata_host *host); | 261 | static void nv_adma_host_stop(struct ata_host *host); |
262 | static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc); | 262 | static void nv_adma_post_internal_cmd(struct ata_queued_cmd *qc); |
263 | static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf); | ||
263 | 264 | ||
264 | enum nv_host_type | 265 | enum nv_host_type |
265 | { | 266 | { |
@@ -435,7 +436,7 @@ static const struct ata_port_operations nv_ck804_ops = { | |||
435 | static const struct ata_port_operations nv_adma_ops = { | 436 | static const struct ata_port_operations nv_adma_ops = { |
436 | .port_disable = ata_port_disable, | 437 | .port_disable = ata_port_disable, |
437 | .tf_load = ata_tf_load, | 438 | .tf_load = ata_tf_load, |
438 | .tf_read = ata_tf_read, | 439 | .tf_read = nv_adma_tf_read, |
439 | .check_atapi_dma = nv_adma_check_atapi_dma, | 440 | .check_atapi_dma = nv_adma_check_atapi_dma, |
440 | .exec_command = ata_exec_command, | 441 | .exec_command = ata_exec_command, |
441 | .check_status = ata_check_status, | 442 | .check_status = ata_check_status, |
@@ -667,6 +668,18 @@ static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc) | |||
667 | return !(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE); | 668 | return !(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE); |
668 | } | 669 | } |
669 | 670 | ||
671 | static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf) | ||
672 | { | ||
673 | /* Since commands where a result TF is requested are not | ||
674 | executed in ADMA mode, the only time this function will be called | ||
675 | in ADMA mode will be if a command fails. In this case we | ||
676 | don't care about going into register mode with ADMA commands | ||
677 | pending, as the commands will all shortly be aborted anyway. */ | ||
678 | nv_adma_register_mode(ap); | ||
679 | |||
680 | ata_tf_read(ap, tf); | ||
681 | } | ||
682 | |||
670 | static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb) | 683 | static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb) |
671 | { | 684 | { |
672 | unsigned int idx = 0; | 685 | unsigned int idx = 0; |
@@ -738,19 +751,11 @@ static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err) | |||
738 | return 1; | 751 | return 1; |
739 | } | 752 | } |
740 | 753 | ||
741 | if (flags & NV_CPB_RESP_DONE) { | 754 | if (likely(flags & NV_CPB_RESP_DONE)) { |
742 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num); | 755 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num); |
743 | VPRINTK("CPB flags done, flags=0x%x\n", flags); | 756 | VPRINTK("CPB flags done, flags=0x%x\n", flags); |
744 | if (likely(qc)) { | 757 | if (likely(qc)) { |
745 | /* Grab the ATA port status for non-NCQ commands. | 758 | DPRINTK("Completing qc from tag %d\n",cpb_num); |
746 | For NCQ commands the current status may have nothing to do with | ||
747 | the command just completed. */ | ||
748 | if (qc->tf.protocol != ATA_PROT_NCQ) { | ||
749 | u8 ata_status = readb(pp->ctl_block + (ATA_REG_STATUS * 4)); | ||
750 | qc->err_mask |= ac_err_mask(ata_status); | ||
751 | } | ||
752 | DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num, | ||
753 | qc->err_mask); | ||
754 | ata_qc_complete(qc); | 759 | ata_qc_complete(qc); |
755 | } else { | 760 | } else { |
756 | struct ata_eh_info *ehi = &ap->eh_info; | 761 | struct ata_eh_info *ehi = &ap->eh_info; |
@@ -1167,9 +1172,11 @@ static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc) | |||
1167 | struct nv_adma_port_priv *pp = qc->ap->private_data; | 1172 | struct nv_adma_port_priv *pp = qc->ap->private_data; |
1168 | 1173 | ||
1169 | /* ADMA engine can only be used for non-ATAPI DMA commands, | 1174 | /* ADMA engine can only be used for non-ATAPI DMA commands, |
1170 | or interrupt-driven no-data commands. */ | 1175 | or interrupt-driven no-data commands, where a result taskfile |
1176 | is not required. */ | ||
1171 | if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || | 1177 | if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || |
1172 | (qc->tf.flags & ATA_TFLAG_POLLING)) | 1178 | (qc->tf.flags & ATA_TFLAG_POLLING) || |
1179 | (qc->flags & ATA_QCFLAG_RESULT_TF)) | ||
1173 | return 1; | 1180 | return 1; |
1174 | 1181 | ||
1175 | if((qc->flags & ATA_QCFLAG_DMAMAP) || | 1182 | if((qc->flags & ATA_QCFLAG_DMAMAP) || |