aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 9a6aacf467b..c92439fe5da 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -3350,11 +3350,13 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
3350 break; 3350 break;
3351 3351
3352 case ATA_PROT_ATAPI_NODATA: 3352 case ATA_PROT_ATAPI_NODATA:
3353 ap->flags |= ATA_FLAG_NOINTR;
3353 ata_tf_to_host_nolock(ap, &qc->tf); 3354 ata_tf_to_host_nolock(ap, &qc->tf);
3354 queue_work(ata_wq, &ap->packet_task); 3355 queue_work(ata_wq, &ap->packet_task);
3355 break; 3356 break;
3356 3357
3357 case ATA_PROT_ATAPI_DMA: 3358 case ATA_PROT_ATAPI_DMA:
3359 ap->flags |= ATA_FLAG_NOINTR;
3358 ap->ops->tf_load(ap, &qc->tf); /* load tf registers */ 3360 ap->ops->tf_load(ap, &qc->tf); /* load tf registers */
3359 ap->ops->bmdma_setup(qc); /* set up bmdma */ 3361 ap->ops->bmdma_setup(qc); /* set up bmdma */
3360 queue_work(ata_wq, &ap->packet_task); 3362 queue_work(ata_wq, &ap->packet_task);
@@ -3708,7 +3710,8 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
3708 struct ata_port *ap; 3710 struct ata_port *ap;
3709 3711
3710 ap = host_set->ports[i]; 3712 ap = host_set->ports[i];
3711 if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { 3713 if (ap &&
3714 !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
3712 struct ata_queued_cmd *qc; 3715 struct ata_queued_cmd *qc;
3713 3716
3714 qc = ata_qc_from_tag(ap, ap->active_tag); 3717 qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -3760,19 +3763,27 @@ static void atapi_packet_task(void *_data)
3760 /* send SCSI cdb */ 3763 /* send SCSI cdb */
3761 DPRINTK("send cdb\n"); 3764 DPRINTK("send cdb\n");
3762 assert(ap->cdb_len >= 12); 3765 assert(ap->cdb_len >= 12);
3763 ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
3764 3766
3765 /* if we are DMA'ing, irq handler takes over from here */ 3767 if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
3766 if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) 3768 qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
3767 ap->ops->bmdma_start(qc); /* initiate bmdma */ 3769 unsigned long flags;
3768 3770
3769 /* non-data commands are also handled via irq */ 3771 /* Once we're done issuing command and kicking bmdma,
3770 else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { 3772 * irq handler takes over. To not lose irq, we need
3771 /* do nothing */ 3773 * to clear NOINTR flag before sending cdb, but
3772 } 3774 * interrupt handler shouldn't be invoked before we're
3775 * finished. Hence, the following locking.
3776 */
3777 spin_lock_irqsave(&ap->host_set->lock, flags);
3778 ap->flags &= ~ATA_FLAG_NOINTR;
3779 ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
3780 if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
3781 ap->ops->bmdma_start(qc); /* initiate bmdma */
3782 spin_unlock_irqrestore(&ap->host_set->lock, flags);
3783 } else {
3784 ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
3773 3785
3774 /* PIO commands are handled by polling */ 3786 /* PIO commands are handled by polling */
3775 else {
3776 ap->pio_task_state = PIO_ST; 3787 ap->pio_task_state = PIO_ST;
3777 queue_work(ata_wq, &ap->pio_task); 3788 queue_work(ata_wq, &ap->pio_task);
3778 } 3789 }