diff options
Diffstat (limited to 'drivers/scsi/scsi_scan.c')
-rw-r--r-- | drivers/scsi/scsi_scan.c | 97 |
1 files changed, 50 insertions, 47 deletions
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index c44783801402..087821fac8fe 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -33,6 +33,7 @@ | |||
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 | #include <linux/async.h> |
36 | #include <linux/slab.h> | ||
36 | 37 | ||
37 | #include <scsi/scsi.h> | 38 | #include <scsi/scsi.h> |
38 | #include <scsi/scsi_cmnd.h> | 39 | #include <scsi/scsi_cmnd.h> |
@@ -251,6 +252,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, | |||
251 | sdev->model = scsi_null_device_strs; | 252 | sdev->model = scsi_null_device_strs; |
252 | sdev->rev = scsi_null_device_strs; | 253 | sdev->rev = scsi_null_device_strs; |
253 | sdev->host = shost; | 254 | sdev->host = shost; |
255 | sdev->queue_ramp_up_period = SCSI_DEFAULT_RAMP_UP_PERIOD; | ||
254 | sdev->id = starget->id; | 256 | sdev->id = starget->id; |
255 | sdev->lun = lun; | 257 | sdev->lun = lun; |
256 | sdev->channel = starget->channel; | 258 | sdev->channel = starget->channel; |
@@ -317,6 +319,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, | |||
317 | out_device_destroy: | 319 | out_device_destroy: |
318 | scsi_device_set_state(sdev, SDEV_DEL); | 320 | scsi_device_set_state(sdev, SDEV_DEL); |
319 | transport_destroy_device(&sdev->sdev_gendev); | 321 | transport_destroy_device(&sdev->sdev_gendev); |
322 | put_device(&sdev->sdev_dev); | ||
320 | put_device(&sdev->sdev_gendev); | 323 | put_device(&sdev->sdev_gendev); |
321 | out: | 324 | out: |
322 | if (display_failure_msg) | 325 | if (display_failure_msg) |
@@ -414,9 +417,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, | |||
414 | starget->reap_ref = 1; | 417 | starget->reap_ref = 1; |
415 | dev->parent = get_device(parent); | 418 | dev->parent = get_device(parent); |
416 | dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id); | 419 | dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id); |
417 | #ifndef CONFIG_SYSFS_DEPRECATED | ||
418 | dev->bus = &scsi_bus_type; | 420 | dev->bus = &scsi_bus_type; |
419 | #endif | ||
420 | dev->type = &scsi_target_type; | 421 | dev->type = &scsi_target_type; |
421 | starget->id = id; | 422 | starget->id = id; |
422 | starget->channel = channel; | 423 | starget->channel = channel; |
@@ -456,8 +457,7 @@ static struct scsi_target *scsi_alloc_target(struct device *parent, | |||
456 | found_target->reap_ref++; | 457 | found_target->reap_ref++; |
457 | spin_unlock_irqrestore(shost->host_lock, flags); | 458 | spin_unlock_irqrestore(shost->host_lock, flags); |
458 | if (found_target->state != STARGET_DEL) { | 459 | if (found_target->state != STARGET_DEL) { |
459 | put_device(parent); | 460 | put_device(dev); |
460 | kfree(starget); | ||
461 | return found_target; | 461 | return found_target; |
462 | } | 462 | } |
463 | /* Unfortunately, we found a dying target; need to | 463 | /* Unfortunately, we found a dying target; need to |
@@ -490,19 +490,20 @@ void scsi_target_reap(struct scsi_target *starget) | |||
490 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 490 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
491 | unsigned long flags; | 491 | unsigned long flags; |
492 | enum scsi_target_state state; | 492 | enum scsi_target_state state; |
493 | int empty; | 493 | int empty = 0; |
494 | 494 | ||
495 | spin_lock_irqsave(shost->host_lock, flags); | 495 | spin_lock_irqsave(shost->host_lock, flags); |
496 | state = starget->state; | 496 | state = starget->state; |
497 | empty = --starget->reap_ref == 0 && | 497 | if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { |
498 | list_empty(&starget->devices) ? 1 : 0; | 498 | empty = 1; |
499 | starget->state = STARGET_DEL; | ||
500 | } | ||
499 | spin_unlock_irqrestore(shost->host_lock, flags); | 501 | spin_unlock_irqrestore(shost->host_lock, flags); |
500 | 502 | ||
501 | if (!empty) | 503 | if (!empty) |
502 | return; | 504 | return; |
503 | 505 | ||
504 | BUG_ON(state == STARGET_DEL); | 506 | BUG_ON(state == STARGET_DEL); |
505 | starget->state = STARGET_DEL; | ||
506 | if (state == STARGET_CREATED) | 507 | if (state == STARGET_CREATED) |
507 | scsi_target_destroy(starget); | 508 | scsi_target_destroy(starget); |
508 | else | 509 | else |
@@ -877,7 +878,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
877 | * broken RA4x00 Compaq Disk Array | 878 | * broken RA4x00 Compaq Disk Array |
878 | */ | 879 | */ |
879 | if (*bflags & BLIST_MAX_512) | 880 | if (*bflags & BLIST_MAX_512) |
880 | blk_queue_max_sectors(sdev->request_queue, 512); | 881 | blk_queue_max_hw_sectors(sdev->request_queue, 512); |
881 | 882 | ||
882 | /* | 883 | /* |
883 | * Some devices may not want to have a start command automatically | 884 | * Some devices may not want to have a start command automatically |
@@ -940,6 +941,8 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
940 | } | 941 | } |
941 | } | 942 | } |
942 | 943 | ||
944 | sdev->max_queue_depth = sdev->queue_depth; | ||
945 | |||
943 | /* | 946 | /* |
944 | * Ok, the device is now all set up, we can | 947 | * Ok, the device is now all set up, we can |
945 | * register it and tell the rest of the kernel | 948 | * register it and tell the rest of the kernel |
@@ -951,15 +954,6 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
951 | return SCSI_SCAN_LUN_PRESENT; | 954 | return SCSI_SCAN_LUN_PRESENT; |
952 | } | 955 | } |
953 | 956 | ||
954 | static inline void scsi_destroy_sdev(struct scsi_device *sdev) | ||
955 | { | ||
956 | scsi_device_set_state(sdev, SDEV_DEL); | ||
957 | if (sdev->host->hostt->slave_destroy) | ||
958 | sdev->host->hostt->slave_destroy(sdev); | ||
959 | transport_destroy_device(&sdev->sdev_gendev); | ||
960 | put_device(&sdev->sdev_gendev); | ||
961 | } | ||
962 | |||
963 | #ifdef CONFIG_SCSI_LOGGING | 957 | #ifdef CONFIG_SCSI_LOGGING |
964 | /** | 958 | /** |
965 | * scsi_inq_str - print INQUIRY data from min to max index, strip trailing whitespace | 959 | * scsi_inq_str - print INQUIRY data from min to max index, strip trailing whitespace |
@@ -1137,7 +1131,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
1137 | } | 1131 | } |
1138 | } | 1132 | } |
1139 | } else | 1133 | } else |
1140 | scsi_destroy_sdev(sdev); | 1134 | __scsi_remove_device(sdev); |
1141 | out: | 1135 | out: |
1142 | return res; | 1136 | return res; |
1143 | } | 1137 | } |
@@ -1225,7 +1219,7 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, | |||
1225 | } | 1219 | } |
1226 | 1220 | ||
1227 | /** | 1221 | /** |
1228 | * scsilun_to_int: convert a scsi_lun to an int | 1222 | * scsilun_to_int - convert a scsi_lun to an int |
1229 | * @scsilun: struct scsi_lun to be converted. | 1223 | * @scsilun: struct scsi_lun to be converted. |
1230 | * | 1224 | * |
1231 | * Description: | 1225 | * Description: |
@@ -1257,7 +1251,7 @@ int scsilun_to_int(struct scsi_lun *scsilun) | |||
1257 | EXPORT_SYMBOL(scsilun_to_int); | 1251 | EXPORT_SYMBOL(scsilun_to_int); |
1258 | 1252 | ||
1259 | /** | 1253 | /** |
1260 | * int_to_scsilun: reverts an int into a scsi_lun | 1254 | * int_to_scsilun - reverts an int into a scsi_lun |
1261 | * @lun: integer to be reverted | 1255 | * @lun: integer to be reverted |
1262 | * @scsilun: struct scsi_lun to be set. | 1256 | * @scsilun: struct scsi_lun to be set. |
1263 | * | 1257 | * |
@@ -1344,8 +1338,10 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, | |||
1344 | sdev = scsi_alloc_sdev(starget, 0, NULL); | 1338 | sdev = scsi_alloc_sdev(starget, 0, NULL); |
1345 | if (!sdev) | 1339 | if (!sdev) |
1346 | return 0; | 1340 | return 0; |
1347 | if (scsi_device_get(sdev)) | 1341 | if (scsi_device_get(sdev)) { |
1342 | __scsi_remove_device(sdev); | ||
1348 | return 0; | 1343 | return 0; |
1344 | } | ||
1349 | } | 1345 | } |
1350 | 1346 | ||
1351 | sprintf(devname, "host %d channel %d id %d", | 1347 | sprintf(devname, "host %d channel %d id %d", |
@@ -1498,7 +1494,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, | |||
1498 | /* | 1494 | /* |
1499 | * the sdev we used didn't appear in the report luns scan | 1495 | * the sdev we used didn't appear in the report luns scan |
1500 | */ | 1496 | */ |
1501 | scsi_destroy_sdev(sdev); | 1497 | __scsi_remove_device(sdev); |
1502 | return ret; | 1498 | return ret; |
1503 | } | 1499 | } |
1504 | 1500 | ||
@@ -1515,14 +1511,18 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, | |||
1515 | starget = scsi_alloc_target(parent, channel, id); | 1511 | starget = scsi_alloc_target(parent, channel, id); |
1516 | if (!starget) | 1512 | if (!starget) |
1517 | return ERR_PTR(-ENOMEM); | 1513 | return ERR_PTR(-ENOMEM); |
1514 | scsi_autopm_get_target(starget); | ||
1518 | 1515 | ||
1519 | mutex_lock(&shost->scan_mutex); | 1516 | mutex_lock(&shost->scan_mutex); |
1520 | if (!shost->async_scan) | 1517 | if (!shost->async_scan) |
1521 | scsi_complete_async_scans(); | 1518 | scsi_complete_async_scans(); |
1522 | 1519 | ||
1523 | if (scsi_host_scan_allowed(shost)) | 1520 | if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { |
1524 | scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); | 1521 | scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); |
1522 | scsi_autopm_put_host(shost); | ||
1523 | } | ||
1525 | mutex_unlock(&shost->scan_mutex); | 1524 | mutex_unlock(&shost->scan_mutex); |
1525 | scsi_autopm_put_target(starget); | ||
1526 | scsi_target_reap(starget); | 1526 | scsi_target_reap(starget); |
1527 | put_device(&starget->dev); | 1527 | put_device(&starget->dev); |
1528 | 1528 | ||
@@ -1576,6 +1576,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, | |||
1576 | starget = scsi_alloc_target(parent, channel, id); | 1576 | starget = scsi_alloc_target(parent, channel, id); |
1577 | if (!starget) | 1577 | if (!starget) |
1578 | return; | 1578 | return; |
1579 | scsi_autopm_get_target(starget); | ||
1579 | 1580 | ||
1580 | if (lun != SCAN_WILD_CARD) { | 1581 | if (lun != SCAN_WILD_CARD) { |
1581 | /* | 1582 | /* |
@@ -1601,6 +1602,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, | |||
1601 | } | 1602 | } |
1602 | 1603 | ||
1603 | out_reap: | 1604 | out_reap: |
1605 | scsi_autopm_put_target(starget); | ||
1604 | /* now determine if the target has any children at all | 1606 | /* now determine if the target has any children at all |
1605 | * and if not, nuke it */ | 1607 | * and if not, nuke it */ |
1606 | scsi_target_reap(starget); | 1608 | scsi_target_reap(starget); |
@@ -1635,8 +1637,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel, | |||
1635 | if (!shost->async_scan) | 1637 | if (!shost->async_scan) |
1636 | scsi_complete_async_scans(); | 1638 | scsi_complete_async_scans(); |
1637 | 1639 | ||
1638 | if (scsi_host_scan_allowed(shost)) | 1640 | if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { |
1639 | __scsi_scan_target(parent, channel, id, lun, rescan); | 1641 | __scsi_scan_target(parent, channel, id, lun, rescan); |
1642 | scsi_autopm_put_host(shost); | ||
1643 | } | ||
1640 | mutex_unlock(&shost->scan_mutex); | 1644 | mutex_unlock(&shost->scan_mutex); |
1641 | } | 1645 | } |
1642 | EXPORT_SYMBOL(scsi_scan_target); | 1646 | EXPORT_SYMBOL(scsi_scan_target); |
@@ -1688,7 +1692,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
1688 | if (!shost->async_scan) | 1692 | if (!shost->async_scan) |
1689 | scsi_complete_async_scans(); | 1693 | scsi_complete_async_scans(); |
1690 | 1694 | ||
1691 | if (scsi_host_scan_allowed(shost)) { | 1695 | if (scsi_host_scan_allowed(shost) && scsi_autopm_get_host(shost) == 0) { |
1692 | if (channel == SCAN_WILD_CARD) | 1696 | if (channel == SCAN_WILD_CARD) |
1693 | for (channel = 0; channel <= shost->max_channel; | 1697 | for (channel = 0; channel <= shost->max_channel; |
1694 | channel++) | 1698 | channel++) |
@@ -1696,6 +1700,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
1696 | rescan); | 1700 | rescan); |
1697 | else | 1701 | else |
1698 | scsi_scan_channel(shost, channel, id, lun, rescan); | 1702 | scsi_scan_channel(shost, channel, id, lun, rescan); |
1703 | scsi_autopm_put_host(shost); | ||
1699 | } | 1704 | } |
1700 | mutex_unlock(&shost->scan_mutex); | 1705 | mutex_unlock(&shost->scan_mutex); |
1701 | 1706 | ||
@@ -1708,7 +1713,7 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) | |||
1708 | shost_for_each_device(sdev, shost) { | 1713 | shost_for_each_device(sdev, shost) { |
1709 | if (!scsi_host_scan_allowed(shost) || | 1714 | if (!scsi_host_scan_allowed(shost) || |
1710 | scsi_sysfs_add_sdev(sdev) != 0) | 1715 | scsi_sysfs_add_sdev(sdev) != 0) |
1711 | scsi_destroy_sdev(sdev); | 1716 | __scsi_remove_device(sdev); |
1712 | } | 1717 | } |
1713 | } | 1718 | } |
1714 | 1719 | ||
@@ -1833,8 +1838,11 @@ static void do_scsi_scan_host(struct Scsi_Host *shost) | |||
1833 | static int do_scan_async(void *_data) | 1838 | static int do_scan_async(void *_data) |
1834 | { | 1839 | { |
1835 | struct async_scan_data *data = _data; | 1840 | struct async_scan_data *data = _data; |
1836 | do_scsi_scan_host(data->shost); | 1841 | struct Scsi_Host *shost = data->shost; |
1842 | |||
1843 | do_scsi_scan_host(shost); | ||
1837 | scsi_finish_async_scan(data); | 1844 | scsi_finish_async_scan(data); |
1845 | scsi_autopm_put_host(shost); | ||
1838 | return 0; | 1846 | return 0; |
1839 | } | 1847 | } |
1840 | 1848 | ||
@@ -1849,16 +1857,20 @@ void scsi_scan_host(struct Scsi_Host *shost) | |||
1849 | 1857 | ||
1850 | if (strncmp(scsi_scan_type, "none", 4) == 0) | 1858 | if (strncmp(scsi_scan_type, "none", 4) == 0) |
1851 | return; | 1859 | return; |
1860 | if (scsi_autopm_get_host(shost) < 0) | ||
1861 | return; | ||
1852 | 1862 | ||
1853 | data = scsi_prep_async_scan(shost); | 1863 | data = scsi_prep_async_scan(shost); |
1854 | if (!data) { | 1864 | if (!data) { |
1855 | do_scsi_scan_host(shost); | 1865 | do_scsi_scan_host(shost); |
1866 | scsi_autopm_put_host(shost); | ||
1856 | return; | 1867 | return; |
1857 | } | 1868 | } |
1858 | 1869 | ||
1859 | p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); | 1870 | p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); |
1860 | if (IS_ERR(p)) | 1871 | if (IS_ERR(p)) |
1861 | do_scan_async(data); | 1872 | do_scan_async(data); |
1873 | /* scsi_autopm_put_host(shost) is called in do_scan_async() */ | ||
1862 | } | 1874 | } |
1863 | EXPORT_SYMBOL(scsi_scan_host); | 1875 | EXPORT_SYMBOL(scsi_scan_host); |
1864 | 1876 | ||
@@ -1879,12 +1891,9 @@ void scsi_forget_host(struct Scsi_Host *shost) | |||
1879 | spin_unlock_irqrestore(shost->host_lock, flags); | 1891 | spin_unlock_irqrestore(shost->host_lock, flags); |
1880 | } | 1892 | } |
1881 | 1893 | ||
1882 | /* | 1894 | /** |
1883 | * Function: scsi_get_host_dev() | 1895 | * scsi_get_host_dev - Create a scsi_device that points to the host adapter itself |
1884 | * | 1896 | * @shost: Host that needs a scsi_device |
1885 | * Purpose: Create a scsi_device that points to the host adapter itself. | ||
1886 | * | ||
1887 | * Arguments: SHpnt - Host that needs a scsi_device | ||
1888 | * | 1897 | * |
1889 | * Lock status: None assumed. | 1898 | * Lock status: None assumed. |
1890 | * | 1899 | * |
@@ -1897,7 +1906,7 @@ void scsi_forget_host(struct Scsi_Host *shost) | |||
1897 | * | 1906 | * |
1898 | * Note - this device is not accessible from any high-level | 1907 | * Note - this device is not accessible from any high-level |
1899 | * drivers (including generics), which is probably not | 1908 | * drivers (including generics), which is probably not |
1900 | * optimal. We can add hooks later to attach | 1909 | * optimal. We can add hooks later to attach. |
1901 | */ | 1910 | */ |
1902 | struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | 1911 | struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) |
1903 | { | 1912 | { |
@@ -1912,10 +1921,9 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | |||
1912 | goto out; | 1921 | goto out; |
1913 | 1922 | ||
1914 | sdev = scsi_alloc_sdev(starget, 0, NULL); | 1923 | sdev = scsi_alloc_sdev(starget, 0, NULL); |
1915 | if (sdev) { | 1924 | if (sdev) |
1916 | sdev->sdev_gendev.parent = get_device(&starget->dev); | ||
1917 | sdev->borken = 0; | 1925 | sdev->borken = 0; |
1918 | } else | 1926 | else |
1919 | scsi_target_reap(starget); | 1927 | scsi_target_reap(starget); |
1920 | put_device(&starget->dev); | 1928 | put_device(&starget->dev); |
1921 | out: | 1929 | out: |
@@ -1924,24 +1932,19 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | |||
1924 | } | 1932 | } |
1925 | EXPORT_SYMBOL(scsi_get_host_dev); | 1933 | EXPORT_SYMBOL(scsi_get_host_dev); |
1926 | 1934 | ||
1927 | /* | 1935 | /** |
1928 | * Function: scsi_free_host_dev() | 1936 | * scsi_free_host_dev - Free a scsi_device that points to the host adapter itself |
1929 | * | 1937 | * @sdev: Host device to be freed |
1930 | * Purpose: Free a scsi_device that points to the host adapter itself. | ||
1931 | * | ||
1932 | * Arguments: SHpnt - Host that needs a scsi_device | ||
1933 | * | 1938 | * |
1934 | * Lock status: None assumed. | 1939 | * Lock status: None assumed. |
1935 | * | 1940 | * |
1936 | * Returns: Nothing | 1941 | * Returns: Nothing |
1937 | * | ||
1938 | * Notes: | ||
1939 | */ | 1942 | */ |
1940 | void scsi_free_host_dev(struct scsi_device *sdev) | 1943 | void scsi_free_host_dev(struct scsi_device *sdev) |
1941 | { | 1944 | { |
1942 | BUG_ON(sdev->id != sdev->host->this_id); | 1945 | BUG_ON(sdev->id != sdev->host->this_id); |
1943 | 1946 | ||
1944 | scsi_destroy_sdev(sdev); | 1947 | __scsi_remove_device(sdev); |
1945 | } | 1948 | } |
1946 | EXPORT_SYMBOL(scsi_free_host_dev); | 1949 | EXPORT_SYMBOL(scsi_free_host_dev); |
1947 | 1950 | ||