aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--include/scsi/scsi_dh.h2
7 files changed, 34 insertions, 174 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);
diff --git a/include/scsi/scsi_dh.h b/include/scsi/scsi_dh.h
index 966b921135b5..3a37b4c45997 100644
--- a/include/scsi/scsi_dh.h
+++ b/include/scsi/scsi_dh.h
@@ -55,7 +55,7 @@ enum {
55 SCSI_DH_NOSYS, 55 SCSI_DH_NOSYS,
56 SCSI_DH_DRIVER_MAX, 56 SCSI_DH_DRIVER_MAX,
57}; 57};
58#if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE) 58#ifdef CONFIG_SCSI_DH
59extern int scsi_dh_activate(struct request_queue *, activate_complete, void *); 59extern int scsi_dh_activate(struct request_queue *, activate_complete, void *);
60extern int scsi_dh_attach(struct request_queue *, const char *); 60extern int scsi_dh_attach(struct request_queue *, const char *);
61extern const char *scsi_dh_attached_handler_name(struct request_queue *, gfp_t); 61extern const char *scsi_dh_attached_handler_name(struct request_queue *, gfp_t);