pata_legacy: wait for async probing
[safe/jmp/linux-2.6] / drivers / ata / libata-scsi.c
index 4b95c43..3423160 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/libata.h>
 #include <linux/hdreg.h>
 #include <linux/uaccess.h>
+#include <linux/suspend.h>
 
 #include "libata.h"
 
@@ -190,7 +191,7 @@ static ssize_t ata_scsi_park_show(struct device *device,
        struct ata_port *ap;
        struct ata_link *link;
        struct ata_device *dev;
-       unsigned long flags;
+       unsigned long flags, now;
        unsigned int uninitialized_var(msecs);
        int rc = 0;
 
@@ -208,10 +209,11 @@ static ssize_t ata_scsi_park_show(struct device *device,
        }
 
        link = dev->link;
+       now = jiffies;
        if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS &&
            link->eh_context.unloaded_mask & (1 << dev->devno) &&
-           time_after(dev->unpark_deadline, jiffies))
-               msecs = jiffies_to_msecs(dev->unpark_deadline - jiffies);
+           time_after(dev->unpark_deadline, now))
+               msecs = jiffies_to_msecs(dev->unpark_deadline - now);
        else
                msecs = 0;
 
@@ -311,7 +313,7 @@ ata_scsi_em_message_show(struct device *dev, struct device_attribute *attr,
                return ap->ops->em_show(ap, buf);
        return -EINVAL;
 }
-DEVICE_ATTR(em_message, S_IRUGO | S_IWUGO,
+DEVICE_ATTR(em_message, S_IRUGO | S_IWUSR,
                ata_scsi_em_message_show, ata_scsi_em_message_store);
 EXPORT_SYMBOL_GPL(dev_attr_em_message);
 
@@ -364,7 +366,7 @@ ata_scsi_activity_store(struct device *dev, struct device_attribute *attr,
        }
        return -EINVAL;
 }
-DEVICE_ATTR(sw_activity, S_IWUGO | S_IRUGO, ata_scsi_activity_show,
+DEVICE_ATTR(sw_activity, S_IWUSR | S_IRUGO, ata_scsi_activity_show,
                        ata_scsi_activity_store);
 EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
 
@@ -413,6 +415,7 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
 
 /**
  *     ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
+ *     @ap: target port
  *     @sdev: SCSI device to get identify data for
  *     @arg: User buffer area for identify data
  *
@@ -422,9 +425,9 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
  *     RETURNS:
  *     Zero on success, negative errno on error.
  */
-static int ata_get_identity(struct scsi_device *sdev, void __user *arg)
+static int ata_get_identity(struct ata_port *ap, 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];
@@ -516,7 +519,7 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
        /* Good values for timeout and retries?  Values below
           from scsi_ioctl_send_command() for default case... */
        cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,
-                                 sensebuf, (10*HZ), 5, 0);
+                                 sensebuf, (10*HZ), 5, 0, NULL);
 
        if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
                u8 *desc = sensebuf + 8;
@@ -602,7 +605,7 @@ 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... */
        cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0,
-                               sensebuf, (10*HZ), 5, 0);
+                               sensebuf, (10*HZ), 5, 0, NULL);
 
        if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
                u8 *desc = sensebuf + 8;
@@ -644,25 +647,48 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
        return rc;
 }
 
-int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+static int ata_ioc32(struct ata_port *ap)
+{
+       if (ap->flags & ATA_FLAG_PIO_DMA)
+               return 1;
+       if (ap->pflags & ATA_PFLAG_PIO32)
+               return 1;
+       return 0;
+}
+
+int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
+                    int cmd, void __user *arg)
 {
        int val = -EINVAL, rc = -EINVAL;
+       unsigned long flags;
 
        switch (cmd) {
        case ATA_IOC_GET_IO32:
-               val = 0;
+               spin_lock_irqsave(ap->lock, flags);
+               val = ata_ioc32(ap);
+               spin_unlock_irqrestore(ap->lock, flags);
                if (copy_to_user(arg, &val, 1))
                        return -EFAULT;
                return 0;
 
        case ATA_IOC_SET_IO32:
                val = (unsigned long) arg;
-               if (val != 0)
-                       return -EINVAL;
-               return 0;
+               rc = 0;
+               spin_lock_irqsave(ap->lock, flags);
+               if (ap->pflags & ATA_PFLAG_PIO32CHANGE) {
+                       if (val)
+                               ap->pflags |= ATA_PFLAG_PIO32;
+                       else
+                               ap->pflags &= ~ATA_PFLAG_PIO32;
+               } else {
+                       if (val != ata_ioc32(ap))
+                               rc = -EINVAL;
+               }
+               spin_unlock_irqrestore(ap->lock, flags);
+               return rc;
 
        case HDIO_GET_IDENTITY:
-               return ata_get_identity(scsidev, arg);
+               return ata_get_identity(ap, scsidev, arg);
 
        case HDIO_DRIVE_CMD:
                if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
@@ -681,6 +707,14 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
 
        return rc;
 }
+EXPORT_SYMBOL_GPL(ata_sas_scsi_ioctl);
+
+int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+{
+       return ata_sas_scsi_ioctl(ata_shost_to_port(scsidev->host),
+                               scsidev, cmd, arg);
+}
+EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 
 /**
  *     ata_scsi_qc_new - acquire new ata_queued_cmd reference
@@ -708,11 +742,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
 {
        struct ata_queued_cmd *qc;
 
-       if (cmd->request->tag != -1)
-               qc = ata_qc_new_init(dev, cmd->request->tag);
-       else
-               qc = ata_qc_new_init(dev, 0);
-
+       qc = ata_qc_new_init(dev);
        if (qc) {
                qc->scsicmd = cmd;
                qc->scsidone = done;
@@ -1107,8 +1137,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
 
                depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
                depth = min(ATA_MAX_QUEUE - 1, depth);
-               scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
-               scsi_activate_tcq(sdev, depth);
+               scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
        }
 
        return 0;
@@ -1298,6 +1327,17 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
 
                tf->command = ATA_CMD_VERIFY;   /* READ VERIFY */
        } else {
+               /* Some odd clown BIOSen issue spindown on power off (ACPI S4
+                * or S5) causing some drives to spin up and down again.
+                */
+               if ((qc->ap->flags & ATA_FLAG_NO_POWEROFF_SPINDOWN) &&
+                   system_state == SYSTEM_POWER_OFF)
+                       goto skip;
+
+               if ((qc->ap->flags & ATA_FLAG_NO_HIBERNATE_SPINDOWN) &&
+                    system_entering_hibernation())
+                       goto skip;
+
                /* XXX: This is for backward compatibility, will be
                 * removed.  Read Documentation/feature-removal-schedule.txt
                 * for more info.
@@ -1321,8 +1361,7 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
                                scmd->scsi_done = qc->scsidone;
                                qc->scsidone = ata_delayed_done;
                        }
-                       scmd->result = SAM_STAT_GOOD;
-                       return 1;
+                       goto skip;
                }
 
                /* Issue ATA STANDBY IMMEDIATE command */
@@ -1338,10 +1377,13 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
 
        return 0;
 
-invalid_fld:
+ invalid_fld:
        ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
        /* "Invalid field in cbd" */
        return 1;
+ skip:
+       scmd->result = SAM_STAT_GOOD;
+       return 1;
 }
 
 
@@ -1948,11 +1990,6 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
                hdr[1] |= (1 << 7);
 
        memcpy(rbuf, hdr, sizeof(hdr));
-
-       /* if ncq, set tags supported */
-       if (ata_id_has_ncq(args->id))
-               rbuf[7] |= (1 << 1);
-
        memcpy(&rbuf[8], "ATA     ", 8);
        ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
        ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
@@ -2105,13 +2142,14 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
 
 static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
 {
+       int form_factor = ata_id_form_factor(args->id);
+       int media_rotation_rate = ata_id_rotation_rate(args->id);
+
        rbuf[1] = 0xb1;
        rbuf[3] = 0x3c;
-       if (ata_id_major_version(args->id) > 7) {
-               rbuf[4] = args->id[217] >> 8;
-               rbuf[5] = args->id[217];
-               rbuf[7] = args->id[168] & 0xf;
-       }
+       rbuf[4] = media_rotation_rate >> 8;
+       rbuf[5] = media_rotation_rate;
+       rbuf[7] = form_factor;
 
        return 0;
 }
@@ -2339,7 +2377,23 @@ saving_not_supp:
  */
 static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
 {
-       u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
+       struct ata_device *dev = args->dev;
+       u64 last_lba = dev->n_sectors - 1; /* LBA of the last block */
+       u8 log_per_phys = 0;
+       u16 lowest_aligned = 0;
+       u16 word_106 = dev->id[106];
+       u16 word_209 = dev->id[209];
+
+       if ((word_106 & 0xc000) == 0x4000) {
+               /* Number and offset of logical sectors per physical sector */
+               if (word_106 & (1 << 13))
+                       log_per_phys = word_106 & 0xf;
+               if ((word_209 & 0xc000) == 0x4000) {
+                       u16 first = dev->id[209] & 0x3fff;
+                       if (first > 0)
+                               lowest_aligned = (1 << log_per_phys) - first;
+               }
+       }
 
        VPRINTK("ENTER\n");
 
@@ -2370,6 +2424,11 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
                /* sector size */
                rbuf[10] = ATA_SECT_SIZE >> 8;
                rbuf[11] = ATA_SECT_SIZE & 0xff;
+
+               rbuf[12] = 0;
+               rbuf[13] = log_per_phys;
+               rbuf[14] = (lowest_aligned >> 8) & 0x3f;
+               rbuf[15] = lowest_aligned;
        }
 
        return 0;
@@ -3238,12 +3297,12 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
                return;
 
  repeat:
-       ata_port_for_each_link(link, ap) {
-               ata_link_for_each_dev(dev, link) {
+       ata_for_each_link(link, ap, EDGE) {
+               ata_for_each_dev(dev, link, ENABLED) {
                        struct scsi_device *sdev;
                        int channel = 0, id = 0;
 
-                       if (!ata_dev_enabled(dev) || dev->sdev)
+                       if (dev->sdev)
                                continue;
 
                        if (ata_is_host_link(link))
@@ -3264,9 +3323,9 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
         * failure occurred, scan would have failed silently.  Check
         * whether all devices are attached.
         */
-       ata_port_for_each_link(link, ap) {
-               ata_link_for_each_dev(dev, link) {
-                       if (ata_dev_enabled(dev) && !dev->sdev)
+       ata_for_each_link(link, ap, EDGE) {
+               ata_for_each_dev(dev, link, ENABLED) {
+                       if (!dev->sdev)
                                goto exit_loop;
                }
        }
@@ -3378,7 +3437,7 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
 
        if (sdev) {
                ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
-                              sdev->sdev_gendev.bus_id);
+                              dev_name(&sdev->sdev_gendev));
 
                scsi_remove_device(sdev);
                scsi_device_put(sdev);
@@ -3390,7 +3449,7 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)
        struct ata_port *ap = link->ap;
        struct ata_device *dev;
 
-       ata_link_for_each_dev(dev, link) {
+       ata_for_each_dev(dev, link, ALL) {
                unsigned long flags;
 
                if (!(dev->flags & ATA_DFLAG_DETACHED))
@@ -3505,7 +3564,7 @@ static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
        if (devno == SCAN_WILD_CARD) {
                struct ata_link *link;
 
-               ata_port_for_each_link(link, ap) {
+               ata_for_each_link(link, ap, EDGE) {
                        struct ata_eh_info *ehi = &link->eh_info;
                        ehi->probe_mask |= ATA_ALL_DEVICES;
                        ehi->action |= ATA_EH_RESET;
@@ -3553,11 +3612,11 @@ void ata_scsi_dev_rescan(struct work_struct *work)
 
        spin_lock_irqsave(ap->lock, flags);
 
-       ata_port_for_each_link(link, ap) {
-               ata_link_for_each_dev(dev, link) {
+       ata_for_each_link(link, ap, EDGE) {
+               ata_for_each_dev(dev, link, ENABLED) {
                        struct scsi_device *sdev = dev->sdev;
 
-                       if (!ata_dev_enabled(dev) || !sdev)
+                       if (!sdev)
                                continue;
                        if (scsi_device_get(sdev))
                                continue;