]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ata/libata-scsi.c
libata: fix boot panic with SATAPI devices on non-SFF HBAs
[linux-2.6-omap-h63xx.git] / drivers / ata / libata-scsi.c
index 8f0e8f2bc628a283c0000b5cab3e43287aa4bb58..c16e3cea1d28b2e941773f95bfc8368e86b774de 100644 (file)
@@ -527,6 +527,14 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
        return qc;
 }
 
+static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc)
+{
+       struct scsi_cmnd *scmd = qc->scsicmd;
+
+       qc->extrabytes = scmd->request->extra_len;
+       qc->nbytes = scsi_bufflen(scmd) + qc->extrabytes;
+}
+
 /**
  *     ata_dump_status - user friendly display of error info
  *     @id: id of the port in question
@@ -2385,7 +2393,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
        /* FIXME: is this needed? */
        memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 
-       ap->ops->tf_read(ap, &qc->tf);
+#ifdef CONFIG_ATA_SFF
+       if (ap->ops->sff_tf_read)
+               ap->ops->sff_tf_read(ap, &qc->tf);
+#endif
 
        /* fill these in, for the case where they are -not- overwritten */
        cmd->sense_buffer[0] = 0x70;
@@ -2539,7 +2550,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
        }
 
        qc->tf.command = ATA_CMD_PACKET;
-       qc->nbytes = scsi_bufflen(scmd) + scmd->request->extra_len;
+       ata_qc_set_pc_nbytes(qc);
 
        /* check whether ATAPI DMA is safe */
        if (!using_pio && ata_check_atapi_dma(qc))
@@ -2550,7 +2561,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
         * want to set it properly, and for DMA where it is
         * effectively meaningless.
         */
-       nbytes = min(scmd->request->data_len, (unsigned int)63 * 1024);
+       nbytes = min(ata_qc_raw_nbytes(qc), (unsigned int)63 * 1024);
 
        /* Most ATAPI devices which honor transfer chunk size don't
         * behave according to the spec when odd chunk size which
@@ -2607,7 +2618,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
 
 static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
 {
-       if (ap->nr_pmp_links == 0) {
+       if (!sata_pmp_attached(ap)) {
                if (likely(devno < ata_link_max_devices(&ap->link)))
                        return &ap->link.device[devno];
        } else {
@@ -2624,7 +2635,7 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
        int devno;
 
        /* skip commands not addressed to targets we simulate */
-       if (ap->nr_pmp_links == 0) {
+       if (!sata_pmp_attached(ap)) {
                if (unlikely(scsidev->channel || scsidev->lun))
                        return NULL;
                devno = scsidev->id;
@@ -2876,7 +2887,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
         * TODO: find out if we need to do more here to
         *       cover scatter/gather case.
         */
-       qc->nbytes = scsi_bufflen(scmd) + scmd->request->extra_len;
+       ata_qc_set_pc_nbytes(qc);
 
        /* request result TF and be quiet about device error */
        qc->flags |= ATA_QCFLAG_RESULT_TF | ATA_QCFLAG_QUIET;
@@ -3482,7 +3493,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
        if (lun != SCAN_WILD_CARD && lun)
                return -EINVAL;
 
-       if (ap->nr_pmp_links == 0) {
+       if (!sata_pmp_attached(ap)) {
                if (channel != SCAN_WILD_CARD && channel)
                        return -EINVAL;
                devno = id;
@@ -3499,8 +3510,8 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
 
                ata_port_for_each_link(link, ap) {
                        struct ata_eh_info *ehi = &link->eh_info;
-                       ehi->probe_mask |= (1 << ata_link_max_devices(link)) - 1;
-                       ehi->action |= ATA_EH_SOFTRESET;
+                       ehi->probe_mask |= ATA_ALL_DEVICES;
+                       ehi->action |= ATA_EH_RESET;
                }
        } else {
                struct ata_device *dev = ata_find_dev(ap, devno);
@@ -3508,8 +3519,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
                if (dev) {
                        struct ata_eh_info *ehi = &dev->link->eh_info;
                        ehi->probe_mask |= 1 << dev->devno;
-                       ehi->action |= ATA_EH_SOFTRESET;
-                       ehi->flags |= ATA_EHI_RESUME_LINK;
+                       ehi->action |= ATA_EH_RESET;
                } else
                        rc = -EINVAL;
        }