diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/libata-core.c | 96 | ||||
-rw-r--r-- | drivers/scsi/scsi_scan.c | 3 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 109 |
3 files changed, 121 insertions, 87 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index fecca4223f8e..f178a450ec08 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/workqueue.h> | 56 | #include <linux/workqueue.h> |
57 | #include <linux/scatterlist.h> | 57 | #include <linux/scatterlist.h> |
58 | #include <linux/io.h> | 58 | #include <linux/io.h> |
59 | #include <linux/async.h> | ||
59 | #include <scsi/scsi.h> | 60 | #include <scsi/scsi.h> |
60 | #include <scsi/scsi_cmnd.h> | 61 | #include <scsi/scsi_cmnd.h> |
61 | #include <scsi/scsi_host.h> | 62 | #include <scsi/scsi_host.h> |
@@ -5909,6 +5910,54 @@ void ata_host_init(struct ata_host *host, struct device *dev, | |||
5909 | host->ops = ops; | 5910 | host->ops = ops; |
5910 | } | 5911 | } |
5911 | 5912 | ||
5913 | |||
5914 | static void async_port_probe(void *data, async_cookie_t cookie) | ||
5915 | { | ||
5916 | int rc; | ||
5917 | struct ata_port *ap = data; | ||
5918 | /* probe */ | ||
5919 | if (ap->ops->error_handler) { | ||
5920 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
5921 | unsigned long flags; | ||
5922 | |||
5923 | ata_port_probe(ap); | ||
5924 | |||
5925 | /* kick EH for boot probing */ | ||
5926 | spin_lock_irqsave(ap->lock, flags); | ||
5927 | |||
5928 | ehi->probe_mask |= ATA_ALL_DEVICES; | ||
5929 | ehi->action |= ATA_EH_RESET | ATA_EH_LPM; | ||
5930 | ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; | ||
5931 | |||
5932 | ap->pflags &= ~ATA_PFLAG_INITIALIZING; | ||
5933 | ap->pflags |= ATA_PFLAG_LOADING; | ||
5934 | ata_port_schedule_eh(ap); | ||
5935 | |||
5936 | spin_unlock_irqrestore(ap->lock, flags); | ||
5937 | |||
5938 | /* wait for EH to finish */ | ||
5939 | ata_port_wait_eh(ap); | ||
5940 | } else { | ||
5941 | DPRINTK("ata%u: bus probe begin\n", ap->print_id); | ||
5942 | rc = ata_bus_probe(ap); | ||
5943 | DPRINTK("ata%u: bus probe end\n", ap->print_id); | ||
5944 | |||
5945 | if (rc) { | ||
5946 | /* FIXME: do something useful here? | ||
5947 | * Current libata behavior will | ||
5948 | * tear down everything when | ||
5949 | * the module is removed | ||
5950 | * or the h/w is unplugged. | ||
5951 | */ | ||
5952 | } | ||
5953 | } | ||
5954 | |||
5955 | /* in order to keep device order, we need to synchronize at this point */ | ||
5956 | async_synchronize_cookie(cookie); | ||
5957 | |||
5958 | ata_scsi_scan_host(ap, 1); | ||
5959 | |||
5960 | } | ||
5912 | /** | 5961 | /** |
5913 | * ata_host_register - register initialized ATA host | 5962 | * ata_host_register - register initialized ATA host |
5914 | * @host: ATA host to register | 5963 | * @host: ATA host to register |
@@ -5988,52 +6037,9 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) | |||
5988 | DPRINTK("probe begin\n"); | 6037 | DPRINTK("probe begin\n"); |
5989 | for (i = 0; i < host->n_ports; i++) { | 6038 | for (i = 0; i < host->n_ports; i++) { |
5990 | struct ata_port *ap = host->ports[i]; | 6039 | struct ata_port *ap = host->ports[i]; |
5991 | 6040 | async_schedule(async_port_probe, ap); | |
5992 | /* probe */ | ||
5993 | if (ap->ops->error_handler) { | ||
5994 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
5995 | unsigned long flags; | ||
5996 | |||
5997 | ata_port_probe(ap); | ||
5998 | |||
5999 | /* kick EH for boot probing */ | ||
6000 | spin_lock_irqsave(ap->lock, flags); | ||
6001 | |||
6002 | ehi->probe_mask |= ATA_ALL_DEVICES; | ||
6003 | ehi->action |= ATA_EH_RESET | ATA_EH_LPM; | ||
6004 | ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; | ||
6005 | |||
6006 | ap->pflags &= ~ATA_PFLAG_INITIALIZING; | ||
6007 | ap->pflags |= ATA_PFLAG_LOADING; | ||
6008 | ata_port_schedule_eh(ap); | ||
6009 | |||
6010 | spin_unlock_irqrestore(ap->lock, flags); | ||
6011 | |||
6012 | /* wait for EH to finish */ | ||
6013 | ata_port_wait_eh(ap); | ||
6014 | } else { | ||
6015 | DPRINTK("ata%u: bus probe begin\n", ap->print_id); | ||
6016 | rc = ata_bus_probe(ap); | ||
6017 | DPRINTK("ata%u: bus probe end\n", ap->print_id); | ||
6018 | |||
6019 | if (rc) { | ||
6020 | /* FIXME: do something useful here? | ||
6021 | * Current libata behavior will | ||
6022 | * tear down everything when | ||
6023 | * the module is removed | ||
6024 | * or the h/w is unplugged. | ||
6025 | */ | ||
6026 | } | ||
6027 | } | ||
6028 | } | ||
6029 | |||
6030 | /* probes are done, now scan each port's disk(s) */ | ||
6031 | DPRINTK("host probe begin\n"); | ||
6032 | for (i = 0; i < host->n_ports; i++) { | ||
6033 | struct ata_port *ap = host->ports[i]; | ||
6034 | |||
6035 | ata_scsi_scan_host(ap, 1); | ||
6036 | } | 6041 | } |
6042 | DPRINTK("probe end\n"); | ||
6037 | 6043 | ||
6038 | return 0; | 6044 | return 0; |
6039 | } | 6045 | } |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 18486b51668d..17914a346f71 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/kthread.h> | 33 | #include <linux/kthread.h> |
34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
35 | #include <linux/async.h> | ||
35 | 36 | ||
36 | #include <scsi/scsi.h> | 37 | #include <scsi/scsi.h> |
37 | #include <scsi/scsi_cmnd.h> | 38 | #include <scsi/scsi_cmnd.h> |
@@ -179,6 +180,8 @@ int scsi_complete_async_scans(void) | |||
179 | spin_unlock(&async_scan_lock); | 180 | spin_unlock(&async_scan_lock); |
180 | 181 | ||
181 | kfree(data); | 182 | kfree(data); |
183 | /* Synchronize async operations globally */ | ||
184 | async_synchronize_full(); | ||
182 | return 0; | 185 | return 0; |
183 | } | 186 | } |
184 | 187 | ||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 62b28d58e65e..e035c1114010 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
50 | #include <linux/string_helpers.h> | 50 | #include <linux/string_helpers.h> |
51 | #include <linux/async.h> | ||
51 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
52 | 53 | ||
53 | #include <scsi/scsi.h> | 54 | #include <scsi/scsi.h> |
@@ -1802,6 +1803,71 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen) | |||
1802 | return 0; | 1803 | return 0; |
1803 | } | 1804 | } |
1804 | 1805 | ||
1806 | /* | ||
1807 | * The asynchronous part of sd_probe | ||
1808 | */ | ||
1809 | static void sd_probe_async(void *data, async_cookie_t cookie) | ||
1810 | { | ||
1811 | struct scsi_disk *sdkp = data; | ||
1812 | struct scsi_device *sdp; | ||
1813 | struct gendisk *gd; | ||
1814 | u32 index; | ||
1815 | struct device *dev; | ||
1816 | |||
1817 | sdp = sdkp->device; | ||
1818 | gd = sdkp->disk; | ||
1819 | index = sdkp->index; | ||
1820 | dev = &sdp->sdev_gendev; | ||
1821 | |||
1822 | if (!sdp->request_queue->rq_timeout) { | ||
1823 | if (sdp->type != TYPE_MOD) | ||
1824 | blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); | ||
1825 | else | ||
1826 | blk_queue_rq_timeout(sdp->request_queue, | ||
1827 | SD_MOD_TIMEOUT); | ||
1828 | } | ||
1829 | |||
1830 | device_initialize(&sdkp->dev); | ||
1831 | sdkp->dev.parent = &sdp->sdev_gendev; | ||
1832 | sdkp->dev.class = &sd_disk_class; | ||
1833 | strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE); | ||
1834 | |||
1835 | if (device_add(&sdkp->dev)) | ||
1836 | goto out_free_index; | ||
1837 | |||
1838 | get_device(&sdp->sdev_gendev); | ||
1839 | |||
1840 | if (index < SD_MAX_DISKS) { | ||
1841 | gd->major = sd_major((index & 0xf0) >> 4); | ||
1842 | gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); | ||
1843 | gd->minors = SD_MINORS; | ||
1844 | } | ||
1845 | gd->fops = &sd_fops; | ||
1846 | gd->private_data = &sdkp->driver; | ||
1847 | gd->queue = sdkp->device->request_queue; | ||
1848 | |||
1849 | sd_revalidate_disk(gd); | ||
1850 | |||
1851 | blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); | ||
1852 | |||
1853 | gd->driverfs_dev = &sdp->sdev_gendev; | ||
1854 | gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS; | ||
1855 | if (sdp->removable) | ||
1856 | gd->flags |= GENHD_FL_REMOVABLE; | ||
1857 | |||
1858 | dev_set_drvdata(dev, sdkp); | ||
1859 | add_disk(gd); | ||
1860 | sd_dif_config_host(sdkp); | ||
1861 | |||
1862 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", | ||
1863 | sdp->removable ? "removable " : ""); | ||
1864 | |||
1865 | return; | ||
1866 | |||
1867 | out_free_index: | ||
1868 | ida_remove(&sd_index_ida, index); | ||
1869 | } | ||
1870 | |||
1805 | /** | 1871 | /** |
1806 | * sd_probe - called during driver initialization and whenever a | 1872 | * sd_probe - called during driver initialization and whenever a |
1807 | * new scsi device is attached to the system. It is called once | 1873 | * new scsi device is attached to the system. It is called once |
@@ -1865,48 +1931,7 @@ static int sd_probe(struct device *dev) | |||
1865 | sdkp->openers = 0; | 1931 | sdkp->openers = 0; |
1866 | sdkp->previous_state = 1; | 1932 | sdkp->previous_state = 1; |
1867 | 1933 | ||
1868 | if (!sdp->request_queue->rq_timeout) { | 1934 | async_schedule(sd_probe_async, sdkp); |
1869 | if (sdp->type != TYPE_MOD) | ||
1870 | blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); | ||
1871 | else | ||
1872 | blk_queue_rq_timeout(sdp->request_queue, | ||
1873 | SD_MOD_TIMEOUT); | ||
1874 | } | ||
1875 | |||
1876 | device_initialize(&sdkp->dev); | ||
1877 | sdkp->dev.parent = &sdp->sdev_gendev; | ||
1878 | sdkp->dev.class = &sd_disk_class; | ||
1879 | strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE); | ||
1880 | |||
1881 | if (device_add(&sdkp->dev)) | ||
1882 | goto out_free_index; | ||
1883 | |||
1884 | get_device(&sdp->sdev_gendev); | ||
1885 | |||
1886 | if (index < SD_MAX_DISKS) { | ||
1887 | gd->major = sd_major((index & 0xf0) >> 4); | ||
1888 | gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); | ||
1889 | gd->minors = SD_MINORS; | ||
1890 | } | ||
1891 | gd->fops = &sd_fops; | ||
1892 | gd->private_data = &sdkp->driver; | ||
1893 | gd->queue = sdkp->device->request_queue; | ||
1894 | |||
1895 | sd_revalidate_disk(gd); | ||
1896 | |||
1897 | blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); | ||
1898 | |||
1899 | gd->driverfs_dev = &sdp->sdev_gendev; | ||
1900 | gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS; | ||
1901 | if (sdp->removable) | ||
1902 | gd->flags |= GENHD_FL_REMOVABLE; | ||
1903 | |||
1904 | dev_set_drvdata(dev, sdkp); | ||
1905 | add_disk(gd); | ||
1906 | sd_dif_config_host(sdkp); | ||
1907 | |||
1908 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", | ||
1909 | sdp->removable ? "removable " : ""); | ||
1910 | 1935 | ||
1911 | return 0; | 1936 | return 0; |
1912 | 1937 | ||