|
@@ -48,6 +48,7 @@
|
|
#include <linux/delay.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/string_helpers.h>
|
|
#include <linux/string_helpers.h>
|
|
|
|
+#include <linux/async.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/uaccess.h>
|
|
|
|
|
|
#include <scsi/scsi.h>
|
|
#include <scsi/scsi.h>
|
|
@@ -1802,6 +1803,71 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * The asynchronous part of sd_probe
|
|
|
|
+ */
|
|
|
|
+static void sd_probe_async(void *data, async_cookie_t cookie)
|
|
|
|
+{
|
|
|
|
+ struct scsi_disk *sdkp = data;
|
|
|
|
+ struct scsi_device *sdp;
|
|
|
|
+ struct gendisk *gd;
|
|
|
|
+ u32 index;
|
|
|
|
+ struct device *dev;
|
|
|
|
+
|
|
|
|
+ sdp = sdkp->device;
|
|
|
|
+ gd = sdkp->disk;
|
|
|
|
+ index = sdkp->index;
|
|
|
|
+ dev = &sdp->sdev_gendev;
|
|
|
|
+
|
|
|
|
+ if (!sdp->request_queue->rq_timeout) {
|
|
|
|
+ if (sdp->type != TYPE_MOD)
|
|
|
|
+ blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT);
|
|
|
|
+ else
|
|
|
|
+ blk_queue_rq_timeout(sdp->request_queue,
|
|
|
|
+ SD_MOD_TIMEOUT);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ device_initialize(&sdkp->dev);
|
|
|
|
+ sdkp->dev.parent = &sdp->sdev_gendev;
|
|
|
|
+ sdkp->dev.class = &sd_disk_class;
|
|
|
|
+ strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
|
|
|
|
+
|
|
|
|
+ if (device_add(&sdkp->dev))
|
|
|
|
+ goto out_free_index;
|
|
|
|
+
|
|
|
|
+ get_device(&sdp->sdev_gendev);
|
|
|
|
+
|
|
|
|
+ if (index < SD_MAX_DISKS) {
|
|
|
|
+ gd->major = sd_major((index & 0xf0) >> 4);
|
|
|
|
+ gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
|
|
|
|
+ gd->minors = SD_MINORS;
|
|
|
|
+ }
|
|
|
|
+ gd->fops = &sd_fops;
|
|
|
|
+ gd->private_data = &sdkp->driver;
|
|
|
|
+ gd->queue = sdkp->device->request_queue;
|
|
|
|
+
|
|
|
|
+ sd_revalidate_disk(gd);
|
|
|
|
+
|
|
|
|
+ blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
|
|
|
|
+
|
|
|
|
+ gd->driverfs_dev = &sdp->sdev_gendev;
|
|
|
|
+ gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS;
|
|
|
|
+ if (sdp->removable)
|
|
|
|
+ gd->flags |= GENHD_FL_REMOVABLE;
|
|
|
|
+
|
|
|
|
+ dev_set_drvdata(dev, sdkp);
|
|
|
|
+ add_disk(gd);
|
|
|
|
+ sd_dif_config_host(sdkp);
|
|
|
|
+
|
|
|
|
+ sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
|
|
|
|
+ sdp->removable ? "removable " : "");
|
|
|
|
+
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ out_free_index:
|
|
|
|
+ ida_remove(&sd_index_ida, index);
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* sd_probe - called during driver initialization and whenever a
|
|
* sd_probe - called during driver initialization and whenever a
|
|
* new scsi device is attached to the system. It is called once
|
|
* new scsi device is attached to the system. It is called once
|
|
@@ -1865,48 +1931,7 @@ static int sd_probe(struct device *dev)
|
|
sdkp->openers = 0;
|
|
sdkp->openers = 0;
|
|
sdkp->previous_state = 1;
|
|
sdkp->previous_state = 1;
|
|
|
|
|
|
- if (!sdp->request_queue->rq_timeout) {
|
|
|
|
- if (sdp->type != TYPE_MOD)
|
|
|
|
- blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT);
|
|
|
|
- else
|
|
|
|
- blk_queue_rq_timeout(sdp->request_queue,
|
|
|
|
- SD_MOD_TIMEOUT);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- device_initialize(&sdkp->dev);
|
|
|
|
- sdkp->dev.parent = &sdp->sdev_gendev;
|
|
|
|
- sdkp->dev.class = &sd_disk_class;
|
|
|
|
- strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
|
|
|
|
-
|
|
|
|
- if (device_add(&sdkp->dev))
|
|
|
|
- goto out_free_index;
|
|
|
|
-
|
|
|
|
- get_device(&sdp->sdev_gendev);
|
|
|
|
-
|
|
|
|
- if (index < SD_MAX_DISKS) {
|
|
|
|
- gd->major = sd_major((index & 0xf0) >> 4);
|
|
|
|
- gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
|
|
|
|
- gd->minors = SD_MINORS;
|
|
|
|
- }
|
|
|
|
- gd->fops = &sd_fops;
|
|
|
|
- gd->private_data = &sdkp->driver;
|
|
|
|
- gd->queue = sdkp->device->request_queue;
|
|
|
|
-
|
|
|
|
- sd_revalidate_disk(gd);
|
|
|
|
-
|
|
|
|
- blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
|
|
|
|
-
|
|
|
|
- gd->driverfs_dev = &sdp->sdev_gendev;
|
|
|
|
- gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS;
|
|
|
|
- if (sdp->removable)
|
|
|
|
- gd->flags |= GENHD_FL_REMOVABLE;
|
|
|
|
-
|
|
|
|
- dev_set_drvdata(dev, sdkp);
|
|
|
|
- add_disk(gd);
|
|
|
|
- sd_dif_config_host(sdkp);
|
|
|
|
-
|
|
|
|
- sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
|
|
|
|
- sdp->removable ? "removable " : "");
|
|
|
|
|
|
+ async_schedule(sd_probe_async, sdkp);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|