igb: move timesync init into a seperate function
[safe/jmp/linux-2.6] / drivers / scsi / sd.c
index e4ef11a..8dd96dc 100644 (file)
@@ -956,7 +956,7 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
 }
 #endif
 
-static struct block_device_operations sd_fops = {
+static const struct block_device_operations sd_fops = {
        .owner                  = THIS_MODULE,
        .open                   = sd_open,
        .release                = sd_release,
@@ -1840,6 +1840,18 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
        kfree(buffer);
 }
 
+static int sd_try_extended_inquiry(struct scsi_device *sdp)
+{
+       /*
+        * Although VPD inquiries can go to SCSI-2 type devices,
+        * some USB ones crash on receiving them, and the pages
+        * we currently ask for are for SPC-3 and beyond
+        */
+       if (sdp->scsi_level > SCSI_SPC_2)
+               return 1;
+       return 0;
+}
+
 /**
  *     sd_revalidate_disk - called the first time a new disk is seen,
  *     performs disk spin up, read_capacity, etc.
@@ -1877,8 +1889,12 @@ static int sd_revalidate_disk(struct gendisk *disk)
         */
        if (sdkp->media_present) {
                sd_read_capacity(sdkp, buffer);
-               sd_read_block_limits(sdkp);
-               sd_read_block_characteristics(sdkp);
+
+               if (sd_try_extended_inquiry(sdp)) {
+                       sd_read_block_limits(sdkp);
+                       sd_read_block_characteristics(sdkp);
+               }
+
                sd_read_write_protect_flag(sdkp, buffer);
                sd_read_cache_type(sdkp, buffer);
                sd_read_app_tag_own(sdkp, buffer);
@@ -2005,6 +2021,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
 
        sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
                  sdp->removable ? "removable " : "");
+       put_device(&sdkp->dev);
 }
 
 /**
@@ -2090,6 +2107,7 @@ static int sd_probe(struct device *dev)
 
        get_device(&sdp->sdev_gendev);
 
+       get_device(&sdkp->dev); /* prevent release before async_schedule */
        async_schedule(sd_probe_async, sdkp);
 
        return 0;
@@ -2123,6 +2141,7 @@ static int sd_remove(struct device *dev)
 
        async_synchronize_full();
        sdkp = dev_get_drvdata(dev);
+       blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn);
        device_del(&sdkp->dev);
        del_gendisk(sdkp->disk);
        sd_shutdown(dev);