diff options
Diffstat (limited to 'drivers/scsi/scsi.c')
-rw-r--r-- | drivers/scsi/scsi.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index b332caddd5b3..c51b5769eac8 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -96,24 +96,40 @@ unsigned int scsi_logging_level; | |||
96 | EXPORT_SYMBOL(scsi_logging_level); | 96 | EXPORT_SYMBOL(scsi_logging_level); |
97 | #endif | 97 | #endif |
98 | 98 | ||
99 | const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] = { | 99 | static const char *const scsi_device_types[] = { |
100 | "Direct-Access ", | 100 | "Direct access ", |
101 | "Sequential-Access", | 101 | "Sequential access", |
102 | "Printer ", | 102 | "Printer ", |
103 | "Processor ", | 103 | "Processor ", |
104 | "WORM ", | 104 | "WORM ", |
105 | "CD-ROM ", | 105 | "CD/DVD ", |
106 | "Scanner ", | 106 | "Scanner ", |
107 | "Optical Device ", | 107 | "Optical memory ", |
108 | "Medium Changer ", | 108 | "Media changer ", |
109 | "Communications ", | 109 | "Communications ", |
110 | "Unknown ", | 110 | "ASC IT8 ", |
111 | "Unknown ", | 111 | "ASC IT8 ", |
112 | "RAID ", | 112 | "RAID ", |
113 | "Enclosure ", | 113 | "Enclosure ", |
114 | "Direct-Access-RBC", | 114 | "Direct access RBC", |
115 | "Optical card ", | ||
116 | "Bridge controller", | ||
117 | "Object storage ", | ||
118 | "Automation/Drive ", | ||
115 | }; | 119 | }; |
116 | EXPORT_SYMBOL(scsi_device_types); | 120 | |
121 | const char * scsi_device_type(unsigned type) | ||
122 | { | ||
123 | if (type == 0x1e) | ||
124 | return "Well-known LUN "; | ||
125 | if (type == 0x1f) | ||
126 | return "No Device "; | ||
127 | if (type > ARRAY_SIZE(scsi_device_types)) | ||
128 | return "Unknown "; | ||
129 | return scsi_device_types[type]; | ||
130 | } | ||
131 | |||
132 | EXPORT_SYMBOL(scsi_device_type); | ||
117 | 133 | ||
118 | struct scsi_host_cmd_pool { | 134 | struct scsi_host_cmd_pool { |
119 | kmem_cache_t *slab; | 135 | kmem_cache_t *slab; |
@@ -835,14 +851,14 @@ EXPORT_SYMBOL(scsi_track_queue_full); | |||
835 | */ | 851 | */ |
836 | int scsi_device_get(struct scsi_device *sdev) | 852 | int scsi_device_get(struct scsi_device *sdev) |
837 | { | 853 | { |
838 | if (sdev->sdev_state == SDEV_DEL || sdev->sdev_state == SDEV_CANCEL) | 854 | if (sdev->sdev_state == SDEV_DEL) |
839 | return -ENXIO; | 855 | return -ENXIO; |
840 | if (!get_device(&sdev->sdev_gendev)) | 856 | if (!get_device(&sdev->sdev_gendev)) |
841 | return -ENXIO; | 857 | return -ENXIO; |
842 | if (!try_module_get(sdev->host->hostt->module)) { | 858 | /* We can fail this if we're doing SCSI operations |
843 | put_device(&sdev->sdev_gendev); | 859 | * from module exit (like cache flush) */ |
844 | return -ENXIO; | 860 | try_module_get(sdev->host->hostt->module); |
845 | } | 861 | |
846 | return 0; | 862 | return 0; |
847 | } | 863 | } |
848 | EXPORT_SYMBOL(scsi_device_get); | 864 | EXPORT_SYMBOL(scsi_device_get); |
@@ -857,7 +873,14 @@ EXPORT_SYMBOL(scsi_device_get); | |||
857 | */ | 873 | */ |
858 | void scsi_device_put(struct scsi_device *sdev) | 874 | void scsi_device_put(struct scsi_device *sdev) |
859 | { | 875 | { |
860 | module_put(sdev->host->hostt->module); | 876 | struct module *module = sdev->host->hostt->module; |
877 | |||
878 | #ifdef CONFIG_MODULE_UNLOAD | ||
879 | /* The module refcount will be zero if scsi_device_get() | ||
880 | * was called from a module removal routine */ | ||
881 | if (module && module_refcount(module) != 0) | ||
882 | module_put(module); | ||
883 | #endif | ||
861 | put_device(&sdev->sdev_gendev); | 884 | put_device(&sdev->sdev_gendev); |
862 | } | 885 | } |
863 | EXPORT_SYMBOL(scsi_device_put); | 886 | EXPORT_SYMBOL(scsi_device_put); |
@@ -1099,6 +1122,8 @@ static int __init init_scsi(void) | |||
1099 | for_each_possible_cpu(i) | 1122 | for_each_possible_cpu(i) |
1100 | INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); | 1123 | INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); |
1101 | 1124 | ||
1125 | scsi_netlink_init(); | ||
1126 | |||
1102 | printk(KERN_NOTICE "SCSI subsystem initialized\n"); | 1127 | printk(KERN_NOTICE "SCSI subsystem initialized\n"); |
1103 | return 0; | 1128 | return 0; |
1104 | 1129 | ||
@@ -1119,6 +1144,7 @@ cleanup_queue: | |||
1119 | 1144 | ||
1120 | static void __exit exit_scsi(void) | 1145 | static void __exit exit_scsi(void) |
1121 | { | 1146 | { |
1147 | scsi_netlink_exit(); | ||
1122 | scsi_sysfs_unregister(); | 1148 | scsi_sysfs_unregister(); |
1123 | scsi_exit_sysctl(); | 1149 | scsi_exit_sysctl(); |
1124 | scsi_exit_hosts(); | 1150 | scsi_exit_hosts(); |