aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-08-27 08:16:57 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-08-28 16:14:56 -0400
commit086b91d052ebe4ead5d28021afe3bdfd70af15bf (patch)
treef168084b13c2fbf924f45567c7b749962eff5f4d /drivers/scsi
parentdaaa858b7a6bb497f11c2aae555053b9c047824b (diff)
scsi_dh: integrate into the core SCSI code
Stop building scsi_dh as a separate module and integrate it fully into the core SCSI code with explicit callouts at bus scan time. For now the callouts are placed at the same point as the old bus notifiers were called, but in the future we will be able to look at ALUA INQUIRY data earlier on. Note that this also means that the device handler modules need to be loaded by the time we scan the bus. The next patches will add support for autoloading device handlers at bus scan time to make sure they are always loaded if they are enabled in the kernel config. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Acked-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/device_handler/Kconfig2
-rw-r--r--drivers/scsi/device_handler/Makefile1
-rw-r--r--drivers/scsi/scsi_dh.c183
-rw-r--r--drivers/scsi/scsi_priv.h9
-rw-r--r--drivers/scsi/scsi_sysfs.c10
6 files changed, 33 insertions, 173 deletions
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 471d08791766..1a8c9b53fafa 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -172,6 +172,7 @@ scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o
172scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o 172scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o
173scsi_mod-y += scsi_trace.o scsi_logging.o 173scsi_mod-y += scsi_trace.o scsi_logging.o
174scsi_mod-$(CONFIG_PM) += scsi_pm.o 174scsi_mod-$(CONFIG_PM) += scsi_pm.o
175scsi_mod-$(CONFIG_SCSI_DH) += scsi_dh.o
175 176
176hv_storvsc-y := storvsc_drv.o 177hv_storvsc-y := storvsc_drv.o
177 178
diff --git a/drivers/scsi/device_handler/Kconfig b/drivers/scsi/device_handler/Kconfig
index 69abd0ad48e2..e5647d59224f 100644
--- a/drivers/scsi/device_handler/Kconfig
+++ b/drivers/scsi/device_handler/Kconfig
@@ -3,7 +3,7 @@
3# 3#
4 4
5menuconfig SCSI_DH 5menuconfig SCSI_DH
6 tristate "SCSI Device Handlers" 6 bool "SCSI Device Handlers"
7 depends on SCSI 7 depends on SCSI
8 default n 8 default n
9 help 9 help
diff --git a/drivers/scsi/device_handler/Makefile b/drivers/scsi/device_handler/Makefile
index e1d2ea083e15..09866c50fbb4 100644
--- a/drivers/scsi/device_handler/Makefile
+++ b/drivers/scsi/device_handler/Makefile
@@ -1,7 +1,6 @@
1# 1#
2# SCSI Device Handler 2# SCSI Device Handler
3# 3#
4obj-$(CONFIG_SCSI_DH) += scsi_dh.o
5obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o 4obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o
6obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o 5obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o
7obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o 6obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o
diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index 3de9b6767be4..f0dfdccc060e 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -57,15 +57,8 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name)
57 return dh; 57 return dh;
58} 58}
59 59
60/*
61 * device_handler_match_function - Match a device handler to a device
62 * @sdev - SCSI device to be tested
63 *
64 * Tests @sdev against the match function of all registered device_handler.
65 * Returns the found device handler or NULL if not found.
66 */
67static struct scsi_device_handler * 60static struct scsi_device_handler *
68device_handler_match_function(struct scsi_device *sdev) 61device_handler_match(struct scsi_device *sdev)
69{ 62{
70 struct scsi_device_handler *tmp_dh, *found_dh = NULL; 63 struct scsi_device_handler *tmp_dh, *found_dh = NULL;
71 64
@@ -81,29 +74,6 @@ device_handler_match_function(struct scsi_device *sdev)
81} 74}
82 75
83/* 76/*
84 * device_handler_match - Attach a device handler to a device
85 * @scsi_dh - The device handler to match against or NULL
86 * @sdev - SCSI device to be tested against @scsi_dh
87 *
88 * Tests @sdev against the device handler @scsi_dh or against
89 * all registered device_handler if @scsi_dh == NULL.
90 * Returns the found device handler or NULL if not found.
91 */
92static struct scsi_device_handler *
93device_handler_match(struct scsi_device_handler *scsi_dh,
94 struct scsi_device *sdev)
95{
96 struct scsi_device_handler *found_dh;
97
98 found_dh = device_handler_match_function(sdev);
99
100 if (scsi_dh && found_dh != scsi_dh)
101 found_dh = NULL;
102
103 return found_dh;
104}
105
106/*
107 * scsi_dh_handler_attach - Attach a device handler to a device 77 * scsi_dh_handler_attach - Attach a device handler to a device
108 * @sdev - SCSI device the device handler should attach to 78 * @sdev - SCSI device the device handler should attach to
109 * @scsi_dh - The device handler to attach 79 * @scsi_dh - The device handler to attach
@@ -212,119 +182,26 @@ static struct device_attribute scsi_dh_state_attr =
212 __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state, 182 __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state,
213 store_dh_state); 183 store_dh_state);
214 184
215/* 185int scsi_dh_add_device(struct scsi_device *sdev)
216 * scsi_dh_sysfs_attr_add - Callback for scsi_init_dh
217 */
218static int scsi_dh_sysfs_attr_add(struct device *dev, void *data)
219{ 186{
220 struct scsi_device *sdev; 187 struct scsi_device_handler *devinfo;
221 int err; 188 int err;
222 189
223 if (!scsi_is_sdev_device(dev)) 190 err = device_create_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
224 return 0; 191 if (err)
225 192 return err;
226 sdev = to_scsi_device(dev);
227
228 err = device_create_file(&sdev->sdev_gendev,
229 &scsi_dh_state_attr);
230
231 return 0;
232}
233
234/*
235 * scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh
236 */
237static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data)
238{
239 struct scsi_device *sdev;
240
241 if (!scsi_is_sdev_device(dev))
242 return 0;
243
244 sdev = to_scsi_device(dev);
245
246 device_remove_file(&sdev->sdev_gendev,
247 &scsi_dh_state_attr);
248
249 return 0;
250}
251 193
252/* 194 devinfo = device_handler_match(sdev);
253 * scsi_dh_notifier - notifier chain callback 195 if (devinfo)
254 */ 196 err = scsi_dh_handler_attach(sdev, devinfo);
255static int scsi_dh_notifier(struct notifier_block *nb,
256 unsigned long action, void *data)
257{
258 struct device *dev = data;
259 struct scsi_device *sdev;
260 int err = 0;
261 struct scsi_device_handler *devinfo = NULL;
262
263 if (!scsi_is_sdev_device(dev))
264 return 0;
265
266 sdev = to_scsi_device(dev);
267
268 if (action == BUS_NOTIFY_ADD_DEVICE) {
269 err = device_create_file(dev, &scsi_dh_state_attr);
270 /* don't care about err */
271 devinfo = device_handler_match(NULL, sdev);
272 if (devinfo)
273 err = scsi_dh_handler_attach(sdev, devinfo);
274 } else if (action == BUS_NOTIFY_DEL_DEVICE) {
275 device_remove_file(dev, &scsi_dh_state_attr);
276 if (sdev->scsi_dh_data)
277 scsi_dh_handler_detach(sdev);
278 }
279 return err; 197 return err;
280} 198}
281 199
282/* 200void scsi_dh_remove_device(struct scsi_device *sdev)
283 * scsi_dh_notifier_add - Callback for scsi_register_device_handler
284 */
285static int scsi_dh_notifier_add(struct device *dev, void *data)
286{ 201{
287 struct scsi_device_handler *scsi_dh = data; 202 if (sdev->scsi_dh_data)
288 struct scsi_device *sdev;
289
290 if (!scsi_is_sdev_device(dev))
291 return 0;
292
293 if (!get_device(dev))
294 return 0;
295
296 sdev = to_scsi_device(dev);
297
298 if (device_handler_match(scsi_dh, sdev))
299 scsi_dh_handler_attach(sdev, scsi_dh);
300
301 put_device(dev);
302
303 return 0;
304}
305
306/*
307 * scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler
308 */
309static int scsi_dh_notifier_remove(struct device *dev, void *data)
310{
311 struct scsi_device_handler *scsi_dh = data;
312 struct scsi_device *sdev;
313
314 if (!scsi_is_sdev_device(dev))
315 return 0;
316
317 if (!get_device(dev))
318 return 0;
319
320 sdev = to_scsi_device(dev);
321
322 if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh == scsi_dh)
323 scsi_dh_handler_detach(sdev); 203 scsi_dh_handler_detach(sdev);
324 204 device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
325 put_device(dev);
326
327 return 0;
328} 205}
329 206
330/* 207/*
@@ -346,7 +223,6 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
346 list_add(&scsi_dh->list, &scsi_dh_list); 223 list_add(&scsi_dh->list, &scsi_dh_list);
347 spin_unlock(&list_lock); 224 spin_unlock(&list_lock);
348 225
349 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
350 printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name); 226 printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
351 227
352 return SCSI_DH_OK; 228 return SCSI_DH_OK;
@@ -362,13 +238,9 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler);
362 */ 238 */
363int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) 239int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
364{ 240{
365
366 if (!__scsi_dh_lookup(scsi_dh->name)) 241 if (!__scsi_dh_lookup(scsi_dh->name))
367 return -ENODEV; 242 return -ENODEV;
368 243
369 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
370 scsi_dh_notifier_remove);
371
372 spin_lock(&list_lock); 244 spin_lock(&list_lock);
373 list_del(&scsi_dh->list); 245 list_del(&scsi_dh->list);
374 spin_unlock(&list_lock); 246 spin_unlock(&list_lock);
@@ -538,34 +410,3 @@ const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp)
538 return handler_name; 410 return handler_name;
539} 411}
540EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name); 412EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name);
541
542static struct notifier_block scsi_dh_nb = {
543 .notifier_call = scsi_dh_notifier
544};
545
546static int __init scsi_dh_init(void)
547{
548 int r;
549
550 r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);
551
552 if (!r)
553 bus_for_each_dev(&scsi_bus_type, NULL, NULL,
554 scsi_dh_sysfs_attr_add);
555
556 return r;
557}
558
559static void __exit scsi_dh_exit(void)
560{
561 bus_for_each_dev(&scsi_bus_type, NULL, NULL,
562 scsi_dh_sysfs_attr_remove);
563 bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
564}
565
566module_init(scsi_dh_init);
567module_exit(scsi_dh_exit);
568
569MODULE_DESCRIPTION("SCSI device handler");
570MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>");
571MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index e3902fc66278..644bb7339b55 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -170,6 +170,15 @@ static inline void scsi_autopm_put_host(struct Scsi_Host *h) {}
170extern struct async_domain scsi_sd_pm_domain; 170extern struct async_domain scsi_sd_pm_domain;
171extern struct async_domain scsi_sd_probe_domain; 171extern struct async_domain scsi_sd_probe_domain;
172 172
173/* scsi_dh.c */
174#ifdef CONFIG_SCSI_DH
175int scsi_dh_add_device(struct scsi_device *sdev);
176void scsi_dh_remove_device(struct scsi_device *sdev);
177#else
178static inline int scsi_dh_add_device(struct scsi_device *sdev) { return 0; }
179static inline void scsi_dh_remove_device(struct scsi_device *sdev) { }
180#endif
181
173/* 182/*
174 * internal scsi timeout functions: for use by mid-layer and transport 183 * internal scsi timeout functions: for use by mid-layer and transport
175 * classes. 184 * classes.
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 9ad41168d26d..b333389f248f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1030,11 +1030,20 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
1030 "failed to add device: %d\n", error); 1030 "failed to add device: %d\n", error);
1031 return error; 1031 return error;
1032 } 1032 }
1033
1034 error = scsi_dh_add_device(sdev);
1035 if (error) {
1036 sdev_printk(KERN_INFO, sdev,
1037 "failed to add device handler: %d\n", error);
1038 return error;
1039 }
1040
1033 device_enable_async_suspend(&sdev->sdev_dev); 1041 device_enable_async_suspend(&sdev->sdev_dev);
1034 error = device_add(&sdev->sdev_dev); 1042 error = device_add(&sdev->sdev_dev);
1035 if (error) { 1043 if (error) {
1036 sdev_printk(KERN_INFO, sdev, 1044 sdev_printk(KERN_INFO, sdev,
1037 "failed to add class device: %d\n", error); 1045 "failed to add class device: %d\n", error);
1046 scsi_dh_remove_device(sdev);
1038 device_del(&sdev->sdev_gendev); 1047 device_del(&sdev->sdev_gendev);
1039 return error; 1048 return error;
1040 } 1049 }
@@ -1074,6 +1083,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
1074 bsg_unregister_queue(sdev->request_queue); 1083 bsg_unregister_queue(sdev->request_queue);
1075 device_unregister(&sdev->sdev_dev); 1084 device_unregister(&sdev->sdev_dev);
1076 transport_remove_device(dev); 1085 transport_remove_device(dev);
1086 scsi_dh_remove_device(sdev);
1077 device_del(dev); 1087 device_del(dev);
1078 } else 1088 } else
1079 put_device(&sdev->sdev_dev); 1089 put_device(&sdev->sdev_dev);