]> err.no Git - linux-2.6/blobdiff - drivers/scsi/libata-scsi.c
[SCSI] hptiop: HighPoint RocketRAID 3xxx controller driver
[linux-2.6] / drivers / scsi / libata-scsi.c
index cebf9b31b516ee5a5ae75d19df22a75f3d692cca..994015726ec8af0309217e2d9c4101c2dd55ec4d 100644 (file)
@@ -41,6 +41,7 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_request.h>
+#include <scsi/scsi_transport.h>
 #include <linux/libata.h>
 #include <linux/hdreg.h>
 #include <asm/uaccess.h>
@@ -52,6 +53,8 @@
 typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
 static struct ata_device *
 ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
+static void ata_scsi_error(struct Scsi_Host *host);
+enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
 
 #define RW_RECOVERY_MPAGE 0x1
 #define RW_RECOVERY_MPAGE_LEN 12
@@ -92,6 +95,15 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
        0, 30   /* extended self test time, see 05-359r1 */
 };
 
+/*
+ * libata transport template.  libata doesn't do real transport stuff.
+ * It just needs the eh_timed_out hook.
+ */
+struct scsi_transport_template ata_scsi_transport_template = {
+       .eh_strategy_handler    = ata_scsi_error,
+       .eh_timed_out           = ata_scsi_timed_out,
+};
+
 
 static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
                                   void (*done)(struct scsi_cmnd *))
@@ -246,7 +258,7 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
        scsi_cmd[14] = args[0];
 
        /* Good values for timeout and retries?  Values below
-          from scsi_ioctl_send_command() for default case... */        
+          from scsi_ioctl_send_command() for default case... */
        if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr,
                             (10*HZ), 5))
                rc = -EIO;
@@ -257,20 +269,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
 
 int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
 {
-       struct ata_port *ap;
-       struct ata_device *dev;
        int val = -EINVAL, rc = -EINVAL;
 
-       ap = (struct ata_port *) &scsidev->host->hostdata[0];
-       if (!ap)
-               goto out;
-
-       dev = ata_scsi_find_dev(ap, scsidev);
-       if (!dev) {
-               rc = -ENODEV;
-               goto out;
-       }
-
        switch (cmd) {
        case ATA_IOC_GET_IO32:
                val = 0;
@@ -299,7 +299,6 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
                break;
        }
 
-out:
        return rc;
 }
 
@@ -404,12 +403,12 @@ int ata_scsi_device_resume(struct scsi_device *sdev)
        return ata_device_resume(ap, dev);
 }
 
-int ata_scsi_device_suspend(struct scsi_device *sdev)
+int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
 {
        struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
        struct ata_device *dev = &ap->device[sdev->id];
 
-       return ata_device_suspend(ap, dev);
+       return ata_device_suspend(ap, dev, state);
 }
 
 /**
@@ -428,7 +427,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev)
  *     LOCKING:
  *     spin_lock_irqsave(host_set lock)
  */
-void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, 
+void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
                        u8 *ascq)
 {
        int i;
@@ -485,7 +484,7 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
                /* Look for drv_err */
                for (i = 0; sense_table[i][0] != 0xFF; i++) {
                        /* Look for best matches first */
-                       if ((sense_table[i][0] & drv_err) == 
+                       if ((sense_table[i][0] & drv_err) ==
                            sense_table[i][0]) {
                                *sk = sense_table[i][1];
                                *asc = sense_table[i][2];
@@ -508,16 +507,14 @@ void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
                }
        }
        /* No error?  Undecoded? */
-       printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", 
+       printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n",
               id, drv_stat);
 
-       /* For our last chance pick, use medium read error because
-        * it's much more common than an ATA drive telling you a write
-        * has failed.
-        */
-       *sk = MEDIUM_ERROR;
-       *asc = 0x11; /* "unrecovered read error" */
-       *ascq = 0x04; /*  "auto-reallocation failed" */
+       /* We need a sensible error return here, which is tricky, and one
+          that won't cause people to do things like return a disk wrongly */
+       *sk = ABORTED_COMMAND;
+       *asc = 0x00;
+       *ascq = 0x00;
 
  translate_done:
        printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to "
@@ -662,6 +659,41 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
        }
 }
 
+static void ata_scsi_sdev_config(struct scsi_device *sdev)
+{
+       sdev->use_10_for_rw = 1;
+       sdev->use_10_for_ms = 1;
+}
+
+static void ata_scsi_dev_config(struct scsi_device *sdev,
+                               struct ata_device *dev)
+{
+       unsigned int max_sectors;
+
+       /* TODO: 2048 is an arbitrary number, not the
+        * hardware maximum.  This should be increased to
+        * 65534 when Jens Axboe's patch for dynamically
+        * determining max_sectors is merged.
+        */
+       max_sectors = ATA_MAX_SECTORS;
+       if (dev->flags & ATA_DFLAG_LBA48)
+               max_sectors = 2048;
+       if (dev->max_sectors)
+               max_sectors = dev->max_sectors;
+
+       blk_queue_max_sectors(sdev->request_queue, max_sectors);
+
+       /*
+        * SATA DMA transfers must be multiples of 4 byte, so
+        * we need to pad ATAPI transfers using an extra sg.
+        * Decrement max hw segments accordingly.
+        */
+       if (dev->class == ATA_DEV_ATAPI) {
+               request_queue_t *q = sdev->request_queue;
+               blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
+       }
+}
+
 /**
  *     ata_scsi_slave_config - Set SCSI device attributes
  *     @sdev: SCSI device to examine
@@ -676,41 +708,18 @@ void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
 
 int ata_scsi_slave_config(struct scsi_device *sdev)
 {
-       sdev->use_10_for_rw = 1;
-       sdev->use_10_for_ms = 1;
+       ata_scsi_sdev_config(sdev);
 
        blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD);
 
        if (sdev->id < ATA_MAX_DEVICES) {
                struct ata_port *ap;
                struct ata_device *dev;
-               unsigned int max_sectors;
 
                ap = (struct ata_port *) &sdev->host->hostdata[0];
                dev = &ap->device[sdev->id];
 
-               /* TODO: 2048 is an arbitrary number, not the
-                * hardware maximum.  This should be increased to
-                * 65534 when Jens Axboe's patch for dynamically
-                * determining max_sectors is merged.
-                */
-               max_sectors = ATA_MAX_SECTORS;
-               if (dev->flags & ATA_DFLAG_LBA48)
-                       max_sectors = 2048;
-               if (dev->max_sectors)
-                       max_sectors = dev->max_sectors;
-
-               blk_queue_max_sectors(sdev->request_queue, max_sectors);
-
-               /*
-                * SATA DMA transfers must be multiples of 4 byte, so
-                * we need to pad ATAPI transfers using an extra sg.
-                * Decrement max hw segments accordingly.
-                */
-               if (dev->class == ATA_DEV_ATAPI) {
-                       request_queue_t *q = sdev->request_queue;
-                       blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
-               }
+               ata_scsi_dev_config(sdev, dev);
        }
 
        return 0;       /* scsi layer doesn't check return value, sigh */
@@ -765,12 +774,9 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
  *
  *     LOCKING:
  *     Inherited from SCSI layer (none, can sleep)
- *
- *     RETURNS:
- *     Zero.
  */
 
-int ata_scsi_error(struct Scsi_Host *host)
+static void ata_scsi_error(struct Scsi_Host *host)
 {
        struct ata_port *ap;
        unsigned long flags;
@@ -798,7 +804,6 @@ int ata_scsi_error(struct Scsi_Host *host)
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
        DPRINTK("EXIT\n");
-       return 0;
 }
 
 static void ata_eh_scsidone(struct scsi_cmnd *scmd)
@@ -1130,14 +1135,14 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc
 
                DPRINTK("block %u track %u cyl %u head %u sect %u\n",
                        (u32)block, track, cyl, head, sect);
-               
-               /* Check whether the converted CHS can fit. 
-                  Cylinder: 0-65535 
+
+               /* Check whether the converted CHS can fit.
+                  Cylinder: 0-65535
                   Head: 0-15
                   Sector: 1-255*/
-               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) 
+               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
                        goto out_of_range;
-               
+
                tf->command = ATA_CMD_VERIFY;
                tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
                tf->lbal = sect;
@@ -1269,7 +1274,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
                tf->lbal = block & 0xff;
 
                tf->device |= ATA_LBA;
-       } else { 
+       } else {
                /* CHS */
                u32 sect, head, cyl, track;
 
@@ -1289,8 +1294,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
                DPRINTK("block %u track %u cyl %u head %u sect %u\n",
                        (u32)block, track, cyl, head, sect);
 
-               /* Check whether the converted CHS can fit. 
-                  Cylinder: 0-65535 
+               /* Check whether the converted CHS can fit.
+                  Cylinder: 0-65535
                   Head: 0-15
                   Sector: 1-255*/
                if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
@@ -1424,9 +1429,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
                goto early_finish;
 
        /* select device, send command to hardware */
-       qc->err_mask = ata_qc_issue(qc);
-       if (qc->err_mask)
-               ata_qc_complete(qc);
+       ata_qc_issue(qc);
 
        VPRINTK("EXIT\n");
        return;
@@ -1677,7 +1680,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
 
        if (buflen > (ATA_SERNO_LEN + num + 3)) {
                /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
-               rbuf[num + 0] = 2;      
+               rbuf[num + 0] = 2;
                rbuf[num + 3] = ATA_SERNO_LEN;
                num += 4;
                ata_id_string(args->id, (unsigned char *) rbuf + num,
@@ -1687,8 +1690,8 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
        if (buflen > (sat_model_serial_desc_len + num + 3)) {
                /* SAT defined lu model and serial numbers descriptor */
                /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
-               rbuf[num + 0] = 2;      
-               rbuf[num + 1] = 1;      
+               rbuf[num + 0] = 2;
+               rbuf[num + 1] = 1;
                rbuf[num + 3] = sat_model_serial_desc_len;
                num += 4;
                memcpy(rbuf + num, "ATA     ", 8);
@@ -2192,9 +2195,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
 
        qc->complete_fn = atapi_sense_complete;
 
-       qc->err_mask = ata_qc_issue(qc);
-       if (qc->err_mask)
-               ata_qc_complete(qc);
+       ata_qc_issue(qc);
 
        DPRINTK("EXIT\n");
 }
@@ -2309,7 +2310,7 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, const u8 *scsicmd)
 #endif
        }
 
-       qc->nbytes = cmd->bufflen;
+       qc->nbytes = cmd->request_bufflen;
 
        return 0;
 }
@@ -2499,7 +2500,7 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd)
         * TODO: find out if we need to do more here to
         *       cover scatter/gather case.
         */
-       qc->nsect = cmd->bufflen / ATA_SECT_SIZE;
+       qc->nsect = cmd->request_bufflen / ATA_SECT_SIZE;
 
        return 0;
 
@@ -2577,6 +2578,21 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
 #endif
 }
 
+static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
+                                      struct ata_port *ap, struct ata_device *dev)
+{
+       if (dev->class == ATA_DEV_ATA) {
+               ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
+                                                             cmd->cmnd[0]);
+
+               if (xlat_func)
+                       ata_scsi_translate(ap, dev, cmd, done, xlat_func);
+               else
+                       ata_scsi_simulate(ap, dev, cmd, done);
+       } else
+               ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
+}
+
 /**
  *     ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device
  *     @cmd: SCSI command to be sent
@@ -2611,24 +2627,13 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
        ata_scsi_dump_cdb(ap, cmd);
 
        dev = ata_scsi_find_dev(ap, scsidev);
-       if (unlikely(!dev)) {
+       if (likely(dev))
+               __ata_scsi_queuecmd(cmd, done, ap, dev);
+       else {
                cmd->result = (DID_BAD_TARGET << 16);
                done(cmd);
-               goto out_unlock;
        }
 
-       if (dev->class == ATA_DEV_ATA) {
-               ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
-                                                             cmd->cmnd[0]);
-
-               if (xlat_func)
-                       ata_scsi_translate(ap, dev, cmd, done, xlat_func);
-               else
-                       ata_scsi_simulate(ap, dev, cmd, done);
-       } else
-               ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
-
-out_unlock:
        spin_unlock(&ap->host_set->lock);
        spin_lock(shost->host_lock);
        return 0;