Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
[linux-drm-fsl-dcu.git] / drivers / ata / libata-scsi.c
index 836947da5b14de4f7e75859d2e500cb2001b31a4..0009818a4306e7fb5e18c717f81d57256ebda337 100644 (file)
@@ -148,6 +148,45 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
        return 0;
 }
 
+/**
+ *     ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
+ *     @sdev: SCSI device to get identify data for
+ *     @arg: User buffer area for identify data
+ *
+ *     LOCKING:
+ *     Defined by the SCSI layer.  We don't really care.
+ *
+ *     RETURNS:
+ *     Zero on success, negative errno on error.
+ */
+static int ata_get_identity(struct scsi_device *sdev, void __user *arg)
+{
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
+       u16 __user *dst = arg;
+       char buf[40];
+
+       if (!dev)
+               return -ENOMSG;
+
+       if (copy_to_user(dst, dev->id, ATA_ID_WORDS * sizeof(u16)))
+               return -EFAULT;
+
+       ata_id_string(dev->id, buf, ATA_ID_PROD, ATA_ID_PROD_LEN);
+       if (copy_to_user(dst + ATA_ID_PROD, buf, ATA_ID_PROD_LEN))
+               return -EFAULT;
+
+       ata_id_string(dev->id, buf, ATA_ID_FW_REV, ATA_ID_FW_REV_LEN);
+       if (copy_to_user(dst + ATA_ID_FW_REV, buf, ATA_ID_FW_REV_LEN))
+               return -EFAULT;
+
+       ata_id_string(dev->id, buf, ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+       if (copy_to_user(dst + ATA_ID_SERNO, buf, ATA_ID_SERNO_LEN))
+               return -EFAULT;
+
+       return 0;
+}
+
 /**
  *     ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl
  *     @scsidev: Device to which we are issuing command
@@ -159,7 +198,6 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
  *     RETURNS:
  *     Zero on success, negative errno on error.
  */
-
 int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
 {
        int rc = 0;
@@ -273,8 +311,8 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
 {
        int rc = 0;
        u8 scsi_cmd[MAX_COMMAND_SIZE];
-       u8 args[7];
-       struct scsi_sense_hdr sshdr;
+       u8 args[7], *sensebuf = NULL;
+       int cmd_result;
 
        if (arg == NULL)
                return -EINVAL;
@@ -282,10 +320,14 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
        if (copy_from_user(args, arg, sizeof(args)))
                return -EFAULT;
 
+       sensebuf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);
+       if (!sensebuf)
+               return -ENOMEM;
+
        memset(scsi_cmd, 0, sizeof(scsi_cmd));
        scsi_cmd[0]  = ATA_16;
        scsi_cmd[1]  = (3 << 1); /* Non-data */
-       /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
+       scsi_cmd[2]  = 0x20;     /* cc but no off.line or data xfer */
        scsi_cmd[4]  = args[1];
        scsi_cmd[6]  = args[2];
        scsi_cmd[8]  = args[3];
@@ -295,11 +337,46 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
 
        /* Good values for timeout and retries?  Values below
           from scsi_ioctl_send_command() for default case... */
-       if (scsi_execute_req(scsidev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr,
-                            (10*HZ), 5))
+       cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0,
+                               sensebuf, (10*HZ), 5, 0);
+
+       if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
+               u8 *desc = sensebuf + 8;
+               cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
+
+               /* If we set cc then ATA pass-through will cause a
+                * check condition even if no error. Filter that. */
+               if (cmd_result & SAM_STAT_CHECK_CONDITION) {
+                       struct scsi_sense_hdr sshdr;
+                       scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
+                                               &sshdr);
+                       if (sshdr.sense_key==0 &&
+                               sshdr.asc==0 && sshdr.ascq==0)
+                               cmd_result &= ~SAM_STAT_CHECK_CONDITION;
+               }
+
+               /* Send userspace ATA registers */
+               if (sensebuf[0] == 0x72 &&      /* format is "descriptor" */
+                               desc[0] == 0x09) {/* code is "ATA Descriptor" */
+                       args[0] = desc[13];     /* status */
+                       args[1] = desc[3];      /* error */
+                       args[2] = desc[5];      /* sector count (0:7) */
+                       args[3] = desc[7];      /* lbal */
+                       args[4] = desc[9];      /* lbam */
+                       args[5] = desc[11];     /* lbah */
+                       args[6] = desc[12];     /* select */
+                       if (copy_to_user(arg, args, sizeof(args)))
+                               rc = -EFAULT;
+               }
+       }
+
+       if (cmd_result) {
                rc = -EIO;
+               goto error;
+       }
 
-       /* Need code to retrieve data from check condition? */
+ error:
+       kfree(sensebuf);
        return rc;
 }
 
@@ -320,6 +397,9 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
                        return -EINVAL;
                return 0;
 
+       case HDIO_GET_IDENTITY:
+               return ata_get_identity(scsidev, arg);
+
        case HDIO_DRIVE_CMD:
                if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
                        return -EACCES;
@@ -358,9 +438,9 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
  *     RETURNS:
  *     Command allocated, or %NULL if none available.
  */
-struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
-                                      struct scsi_cmnd *cmd,
-                                      void (*done)(struct scsi_cmnd *))
+static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
+                                             struct scsi_cmnd *cmd,
+                                             void (*done)(struct scsi_cmnd *))
 {
        struct ata_queued_cmd *qc;
 
@@ -372,7 +452,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
                if (cmd->use_sg) {
                        qc->__sg = (struct scatterlist *) cmd->request_buffer;
                        qc->n_elem = cmd->use_sg;
-               } else {
+               } else if (cmd->request_bufflen) {
                        qc->__sg = &qc->sgent;
                        qc->n_elem = 1;
                }
@@ -396,7 +476,7 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
  *     LOCKING:
  *     inherited from caller
  */
-void ata_dump_status(unsigned id, struct ata_taskfile *tf)
+static void ata_dump_status(unsigned id, struct ata_taskfile *tf)
 {
        u8 stat = tf->command, err = tf->feature;
 
@@ -571,8 +651,8 @@ int ata_scsi_device_resume(struct scsi_device *sdev)
  *     LOCKING:
  *     spin_lock_irqsave(host lock)
  */
-void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
-                       u8 *ascq, int verbose)
+static void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk,
+                              u8 *asc, u8 *ascq, int verbose)
 {
        int i;
 
@@ -983,11 +1063,10 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
                }
 
                tf->command = ATA_CMD_VERIFY;   /* READ VERIFY */
-       } else {
-               tf->nsect = 0;  /* time period value (0 implies now) */
-               tf->command = ATA_CMD_STANDBY;
-               /* Consider: ATA STANDBY IMMEDIATE command */
-       }
+       } else
+               /* Issue ATA STANDBY IMMEDIATE command */
+               tf->command = ATA_CMD_STANDBYNOW1;
+
        /*
         * Standby and Idle condition timers could be implemented but that
         * would require libata to implement the Power condition mode page
@@ -1321,7 +1400,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                goto nothing_to_do;
 
        qc->flags |= ATA_QCFLAG_IO;
-       qc->nsect = n_block;
+       qc->nbytes = n_block * ATA_SECT_SIZE;
 
        rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,
                             qc->tag);
@@ -1660,8 +1739,8 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 
        if (buflen > 35) {
                memcpy(&rbuf[8], "ATA     ", 8);
-               ata_id_string(args->id, &rbuf[16], ATA_ID_PROD_OFS, 16);
-               ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
+               ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
+               ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
                if (rbuf[32] == 0 || rbuf[32] == ' ')
                        memcpy(&rbuf[32], "n/a ", 4);
        }
@@ -1730,13 +1809,13 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
                0,
                0x80,                   /* this page code */
                0,
-               ATA_SERNO_LEN,          /* page len */
+               ATA_ID_SERNO_LEN,       /* page len */
        };
        memcpy(rbuf, hdr, sizeof(hdr));
 
-       if (buflen > (ATA_SERNO_LEN + 4 - 1))
+       if (buflen > (ATA_ID_SERNO_LEN + 4 - 1))
                ata_id_string(args->id, (unsigned char *) &rbuf[4],
-                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
+                             ATA_ID_SERNO, ATA_ID_SERNO_LEN);
 
        return 0;
 }
@@ -1761,19 +1840,18 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
 {
        int num;
        const int sat_model_serial_desc_len = 68;
-       const int ata_model_byte_len = 40;
 
        rbuf[1] = 0x83;                 /* this page code */
        num = 4;
 
-       if (buflen > (ATA_SERNO_LEN + num + 3)) {
+       if (buflen > (ATA_ID_SERNO_LEN + num + 3)) {
                /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
                rbuf[num + 0] = 2;
-               rbuf[num + 3] = ATA_SERNO_LEN;
+               rbuf[num + 3] = ATA_ID_SERNO_LEN;
                num += 4;
                ata_id_string(args->id, (unsigned char *) rbuf + num,
-                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
-               num += ATA_SERNO_LEN;
+                             ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+               num += ATA_ID_SERNO_LEN;
        }
        if (buflen > (sat_model_serial_desc_len + num + 3)) {
                /* SAT defined lu model and serial numbers descriptor */
@@ -1785,11 +1863,11 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
                memcpy(rbuf + num, "ATA     ", 8);
                num += 8;
                ata_id_string(args->id, (unsigned char *) rbuf + num,
-                             ATA_ID_PROD_OFS, ata_model_byte_len);
-               num += ata_model_byte_len;
+                             ATA_ID_PROD, ATA_ID_PROD_LEN);
+               num += ATA_ID_PROD_LEN;
                ata_id_string(args->id, (unsigned char *) rbuf + num,
-                             ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
-               num += ATA_SERNO_LEN;
+                             ATA_ID_SERNO, ATA_ID_SERNO_LEN);
+               num += ATA_ID_SERNO_LEN;
        }
        rbuf[3] = num - 4;    /* page len (assume less than 256 bytes) */
        return 0;
@@ -1917,15 +1995,15 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
  */
 static int ata_dev_supports_fua(u16 *id)
 {
-       unsigned char model[41], fw[9];
+       unsigned char model[ATA_ID_PROD_LEN + 1], fw[ATA_ID_FW_REV_LEN + 1];
 
        if (!libata_fua)
                return 0;
        if (!ata_id_has_fua(id))
                return 0;
 
-       ata_id_c_string(id, model, ATA_ID_PROD_OFS, sizeof(model));
-       ata_id_c_string(id, fw, ATA_ID_FW_REV_OFS, sizeof(fw));
+       ata_id_c_string(id, model, ATA_ID_PROD, sizeof(model));
+       ata_id_c_string(id, fw, ATA_ID_FW_REV, sizeof(fw));
 
        if (strcmp(model, "Maxtor"))
                return 1;
@@ -2623,7 +2701,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->nsect = scmd->request_bufflen / ATA_SECT_SIZE;
+       qc->nbytes = scmd->request_bufflen;
 
        /* request result TF */
        qc->flags |= ATA_QCFLAG_RESULT_TF;
@@ -3021,7 +3099,8 @@ void ata_scsi_hotplug(struct work_struct *work)
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
                struct ata_device *dev = &ap->device[i];
                if (ata_dev_enabled(dev) && !dev->sdev) {
-                       queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ);
+                       queue_delayed_work(ata_aux_wq, &ap->hotplug_task,
+                               round_jiffies_relative(HZ));
                        break;
                }
        }
@@ -3226,7 +3305,8 @@ EXPORT_SYMBOL_GPL(ata_sas_port_init);
 
 void ata_sas_port_destroy(struct ata_port *ap)
 {
-       ap->ops->port_stop(ap);
+       if (ap->ops->port_stop)
+               ap->ops->port_stop(ap);
        kfree(ap);
 }
 EXPORT_SYMBOL_GPL(ata_sas_port_destroy);