]> err.no Git - linux-2.6/blobdiff - drivers/scsi/scsi_scan.c
Merge master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / drivers / scsi / scsi_scan.c
index 84f01fd0c8fde8fbc7c5a404bfbc775c6d286280..1a5474bd11a19d0eb32f434d2556ee64b1bb3c52 100644 (file)
@@ -251,6 +251,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
                /* release fn is set up in scsi_sysfs_device_initialise, so
                 * have to free and put manually here */
                put_device(&starget->dev);
+               kfree(sdev);
                goto out;
        }
 
@@ -287,10 +288,7 @@ static void scsi_target_dev_release(struct device *dev)
 {
        struct device *parent = dev->parent;
        struct scsi_target *starget = to_scsi_target(dev);
-       struct Scsi_Host *shost = dev_to_shost(parent);
 
-       if (shost->hostt->target_destroy)
-               shost->hostt->target_destroy(starget);
        kfree(starget);
        put_device(parent);
 }
@@ -332,6 +330,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
                + shost->transportt->target_size;
        struct scsi_target *starget;
        struct scsi_target *found_target;
+       int error;
 
        starget = kzalloc(size, GFP_KERNEL);
        if (!starget) {
@@ -361,10 +360,20 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
        spin_unlock_irqrestore(shost->host_lock, flags);
        /* allocate and add */
        transport_setup_device(dev);
-       device_add(dev);
+       error = device_add(dev);
+       if (error) {
+               dev_err(dev, "target device_add failed, error %d\n", error);
+               spin_lock_irqsave(shost->host_lock, flags);
+               list_del_init(&starget->siblings);
+               spin_unlock_irqrestore(shost->host_lock, flags);
+               transport_destroy_device(dev);
+               put_device(parent);
+               kfree(starget);
+               return NULL;
+       }
        transport_add_device(dev);
        if (shost->hostt->target_alloc) {
-               int error = shost->hostt->target_alloc(starget);
+               error = shost->hostt->target_alloc(starget);
 
                if(error) {
                        dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
@@ -404,6 +413,8 @@ static void scsi_target_reap_usercontext(void *data)
        device_del(&starget->dev);
        transport_destroy_device(&starget->dev);
        spin_lock_irqsave(shost->host_lock, flags);
+       if (shost->hostt->target_destroy)
+               shost->hostt->target_destroy(starget);
        list_del_init(&starget->siblings);
        spin_unlock_irqrestore(shost->host_lock, flags);
        put_device(&starget->dev);
@@ -662,6 +673,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
        case TYPE_MEDIUM_CHANGER:
        case TYPE_ENCLOSURE:
        case TYPE_COMM:
+       case TYPE_RAID:
        case TYPE_RBC:
                sdev->writeable = 1;
                break;
@@ -726,6 +738,13 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
        if (*bflags & BLIST_SELECT_NO_ATN)
                sdev->select_no_atn = 1;
 
+       /*
+        * Maximum 512 sector transfer length
+        * broken RA4x00 Compaq Disk Array
+        */
+       if (*bflags & BLIST_MAX_512)
+               blk_queue_max_sectors(sdev->request_queue, 512);
+
        /*
         * Some devices may not want to have a start command automatically
         * issued when a device is added.
@@ -763,8 +782,20 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
 
        transport_configure_device(&sdev->sdev_gendev);
 
-       if (sdev->host->hostt->slave_configure)
-               sdev->host->hostt->slave_configure(sdev);
+       if (sdev->host->hostt->slave_configure) {
+               int ret = sdev->host->hostt->slave_configure(sdev);
+               if (ret) {
+                       /*
+                        * if LLDD reports slave not present, don't clutter
+                        * console with alloc failure messages
+                        */
+                       if (ret != -ENXIO) {
+                               sdev_printk(KERN_ERR, sdev,
+                                       "failed to configure device\n");
+                       }
+                       return SCSI_SCAN_NO_RESPONSE;
+               }
+       }
 
        /*
         * Ok, the device is now all set up, we can
@@ -1100,10 +1131,13 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags,
         * Also allow SCSI-2 if BLIST_REPORTLUN2 is set and host adapter does
         * support more than 8 LUNs.
         */
-       if ((bflags & BLIST_NOREPORTLUN) || 
-            starget->scsi_level < SCSI_2 ||
-           (starget->scsi_level < SCSI_3 && 
-            (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8)) )
+       if (bflags & BLIST_NOREPORTLUN)
+               return 1;
+       if (starget->scsi_level < SCSI_2 &&
+           starget->scsi_level != SCSI_UNKNOWN)
+               return 1;
+       if (starget->scsi_level < SCSI_3 &&
+           (!(bflags & BLIST_REPORTLUN2) || shost->max_lun <= 8))
                return 1;
        if (bflags & BLIST_NOLUN)
                return 0;