[PATCH] libata: fold ata_dev_config() into ata_dev_configure()
[sfrench/cifs-2.6.git] / drivers / scsi / libata-core.c
index ab3257a6b8606672aee71793a120bba6d63a27a6..10803f72c57da4b0f1a8dbd3713248f251024c20 100644 (file)
@@ -78,6 +78,10 @@ int atapi_enabled = 0;
 module_param(atapi_enabled, int, 0444);
 MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
 
+int libata_fua = 0;
+module_param_named(fua, libata_fua, int, 0444);
+MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -907,7 +911,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
  *     @dev: target device
  *     @p_class: pointer to class of the target device (may be changed)
  *     @post_reset: is this read ID post-reset?
- *     @id: buffer to fill IDENTIFY page into
+ *     @p_id: read IDENTIFY page (newly allocated)
  *
  *     Read ID data from the specified device.  ATA_CMD_ID_ATA is
  *     performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
@@ -922,12 +926,13 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev)
  *     0 on success, -errno otherwise.
  */
 static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
-                          unsigned int *p_class, int post_reset, u16 *id)
+                          unsigned int *p_class, int post_reset, u16 **p_id)
 {
        unsigned int class = *p_class;
        unsigned int using_edd;
        struct ata_taskfile tf;
        unsigned int err_mask = 0;
+       u16 *id;
        const char *reason;
        int rc;
 
@@ -941,6 +946,13 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
 
        ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
 
+       id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL);
+       if (id == NULL) {
+               rc = -ENOMEM;
+               reason = "out of memory";
+               goto err_out;
+       }
+
  retry:
        ata_tf_init(ap, &tf, dev->devno);
 
@@ -1031,6 +1043,7 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
        }
 
        *p_class = class;
+       *p_id = id;
        return 0;
 
  err_out:
@@ -1040,45 +1053,38 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
        return rc;
 }
 
+static inline u8 ata_dev_knobble(const struct ata_port *ap,
+                                struct ata_device *dev)
+{
+       return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+}
+
 /**
- *     ata_dev_identify - obtain IDENTIFY x DEVICE page
- *     @ap: port on which device we wish to probe resides
- *     @device: device bus address, starting at zero
- *
- *     Following bus reset, we issue the IDENTIFY [PACKET] DEVICE
- *     command, and read back the 512-byte device information page.
- *     The device information page is fed to us via the standard
- *     PIO-IN protocol, but we hand-code it here. (TODO: investigate
- *     using standard PIO-IN paths)
- *
- *     After reading the device information page, we use several
- *     bits of information from it to initialize data structures
- *     that will be used during the lifetime of the ata_device.
- *     Other data from the info page is used to disqualify certain
- *     older ATA devices we do not wish to support.
+ *     ata_dev_configure - Configure the specified ATA/ATAPI device
+ *     @ap: Port on which target device resides
+ *     @dev: Target device to configure
+ *
+ *     Configure @dev according to @dev->id.  Generic and low-level
+ *     driver specific fixups are also applied.
  *
  *     LOCKING:
- *     Inherited from caller.  Some functions called by this function
- *     obtain the host_set lock.
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 on success, -errno otherwise
  */
-
-static void ata_dev_identify(struct ata_port *ap, unsigned int device)
+static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev)
 {
-       struct ata_device *dev = &ap->device[device];
        unsigned long xfer_modes;
        int i, rc;
 
        if (!ata_dev_present(dev)) {
                DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
-                       ap->id, device);
-               return;
+                       ap->id, dev->devno);
+               return 0;
        }
 
-       DPRINTK("ENTER, host %u, dev %u\n", ap->id, device);
-
-       rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id);
-       if (rc)
-               goto err_out;
+       DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
 
        /*
         * common ATA, ATAPI feature tests
@@ -1087,6 +1093,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
        /* we require DMA support (bits 8 of word 49) */
        if (!ata_id_has_dma(dev->id)) {
                printk(KERN_DEBUG "ata%u: no dma\n", ap->id);
+               rc = -EINVAL;
                goto err_out_nosup;
        }
 
@@ -1111,12 +1118,12 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 
                        /* print device info to dmesg */
                        printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n",
-                              ap->id, device,
+                              ap->id, dev->devno,
                               ata_id_major_version(dev->id),
                               ata_mode_string(xfer_modes),
                               (unsigned long long)dev->n_sectors,
                               dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA");
-               } else { 
+               } else {
                        /* CHS */
 
                        /* Default translation */
@@ -1133,7 +1140,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 
                        /* print device info to dmesg */
                        printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n",
-                              ap->id, device,
+                              ap->id, dev->devno,
                               ata_id_major_version(dev->id),
                               ata_mode_string(xfer_modes),
                               (unsigned long long)dev->n_sectors,
@@ -1149,13 +1156,14 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
                rc = atapi_cdb_len(dev->id);
                if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
                        printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);
+                       rc = -EINVAL;
                        goto err_out_nosup;
                }
                dev->cdb_len = (unsigned int) rc;
 
                /* print device info to dmesg */
                printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
-                      ap->id, device,
+                      ap->id, dev->devno,
                       ata_mode_string(xfer_modes));
        }
 
@@ -1165,44 +1173,25 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
                                              ap->host->max_cmd_len,
                                              ap->device[i].cdb_len);
 
-       DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
-       return;
-
-err_out_nosup:
-       printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
-              ap->id, device);
-err_out:
-       dev->class++;   /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */
-       DPRINTK("EXIT, err\n");
-}
-
-
-static inline u8 ata_dev_knobble(const struct ata_port *ap,
-                                struct ata_device *dev)
-{
-       return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
-}
-
-/**
- * ata_dev_config - Run device specific handlers & check for SATA->PATA bridges
- * @ap: Bus
- * @i:  Device
- *
- * LOCKING:
- */
-
-void ata_dev_config(struct ata_port *ap, unsigned int i)
-{
        /* limit bridge transfers to udma5, 200 sectors */
-       if (ata_dev_knobble(ap, &ap->device[i])) {
+       if (ata_dev_knobble(ap, dev)) {
                printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
-                      ap->id, i);
+                      ap->id, dev->devno);
                ap->udma_mask &= ATA_UDMA5;
-               ap->device[i].max_sectors = ATA_MAX_SECTORS;
+               dev->max_sectors = ATA_MAX_SECTORS;
        }
 
        if (ap->ops->dev_config)
-               ap->ops->dev_config(ap, &ap->device[i]);
+               ap->ops->dev_config(ap, dev);
+
+       DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
+       return 0;
+
+err_out_nosup:
+       printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
+              ap->id, dev->devno);
+       DPRINTK("EXIT, err\n");
+       return rc;
 }
 
 /**
@@ -1249,11 +1238,23 @@ static int ata_bus_probe(struct ata_port *ap)
                goto err_out;
 
        for (i = 0; i < ATA_MAX_DEVICES; i++) {
-               ata_dev_identify(ap, i);
-               if (ata_dev_present(&ap->device[i])) {
-                       found = 1;
-                       ata_dev_config(ap,i);
+               struct ata_device *dev = &ap->device[i];
+
+               if (!ata_dev_present(dev))
+                       continue;
+
+               WARN_ON(dev->id != NULL);
+               if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) {
+                       dev->class = ATA_DEV_NONE;
+                       continue;
+               }
+
+               if (ata_dev_configure(ap, dev)) {
+                       dev->class++;   /* disable device */
+                       continue;
                }
+
+               found = 1;
        }
 
        if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED))
@@ -4729,11 +4730,14 @@ void ata_host_set_remove(struct ata_host_set *host_set)
 int ata_scsi_release(struct Scsi_Host *host)
 {
        struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
+       int i;
 
        DPRINTK("ENTER\n");
 
        ap->ops->port_disable(ap);
        ata_host_remove(ap, 0);
+       for (i = 0; i < ATA_MAX_DEVICES; i++)
+               kfree(ap->device[i].id);
 
        DPRINTK("EXIT\n");
        return 1;
@@ -4950,7 +4954,6 @@ EXPORT_SYMBOL_GPL(ata_host_intr);
 EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_id_string);
 EXPORT_SYMBOL_GPL(ata_id_c_string);
-EXPORT_SYMBOL_GPL(ata_dev_config);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
 EXPORT_SYMBOL_GPL(ata_eh_qc_retry);