aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Jones <pjones@redhat.com>2011-01-06 15:38:24 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-01-24 13:02:09 -0500
commit940d7faa4818f386fcdf1b7266ec7b62bf07a7d0 (patch)
tree3a5acb8d4a9b0d6806724e71e6c7f9e23d39bfad
parent38a039be2e7bda32517642ecfce54c9317292a9c (diff)
[SCSI] scsi_dh: Use scsi_devinfo functions to do matching of device_handler tables.
Previously we were using strncmp in order to avoid having to include whitespace in the devlist, but this means "HSV1000" matches a device list entry that says "HSV100", which is wrong. This patch changes scsi_dh.c to use scsi_devinfo's matching functions instead, since they handle these cases correctly. Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/device_handler/scsi_dh.c112
-rw-r--r--drivers/scsi/scsi_priv.h1
-rw-r--r--include/scsi/scsi_device.h1
3 files changed, 39 insertions, 75 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index b837c5b3c8f9..564e6ecd17c2 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -25,16 +25,9 @@
25#include <scsi/scsi_dh.h> 25#include <scsi/scsi_dh.h>
26#include "../scsi_priv.h" 26#include "../scsi_priv.h"
27 27
28struct scsi_dh_devinfo_list {
29 struct list_head node;
30 char vendor[9];
31 char model[17];
32 struct scsi_device_handler *handler;
33};
34
35static DEFINE_SPINLOCK(list_lock); 28static DEFINE_SPINLOCK(list_lock);
36static LIST_HEAD(scsi_dh_list); 29static LIST_HEAD(scsi_dh_list);
37static LIST_HEAD(scsi_dh_dev_list); 30static int scsi_dh_list_idx = 1;
38 31
39static struct scsi_device_handler *get_device_handler(const char *name) 32static struct scsi_device_handler *get_device_handler(const char *name)
40{ 33{
@@ -51,40 +44,18 @@ static struct scsi_device_handler *get_device_handler(const char *name)
51 return found; 44 return found;
52} 45}
53 46
54 47static struct scsi_device_handler *get_device_handler_by_idx(int idx)
55static struct scsi_device_handler *
56scsi_dh_cache_lookup(struct scsi_device *sdev)
57{ 48{
58 struct scsi_dh_devinfo_list *tmp; 49 struct scsi_device_handler *tmp, *found = NULL;
59 struct scsi_device_handler *found_dh = NULL;
60 50
61 spin_lock(&list_lock); 51 spin_lock(&list_lock);
62 list_for_each_entry(tmp, &scsi_dh_dev_list, node) { 52 list_for_each_entry(tmp, &scsi_dh_list, list) {
63 if (!strncmp(sdev->vendor, tmp->vendor, strlen(tmp->vendor)) && 53 if (tmp->idx == idx) {
64 !strncmp(sdev->model, tmp->model, strlen(tmp->model))) { 54 found = tmp;
65 found_dh = tmp->handler;
66 break; 55 break;
67 } 56 }
68 } 57 }
69 spin_unlock(&list_lock); 58 spin_unlock(&list_lock);
70
71 return found_dh;
72}
73
74static int scsi_dh_handler_lookup(struct scsi_device_handler *scsi_dh,
75 struct scsi_device *sdev)
76{
77 int i, found = 0;
78
79 for(i = 0; scsi_dh->devlist[i].vendor; i++) {
80 if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor,
81 strlen(scsi_dh->devlist[i].vendor)) &&
82 !strncmp(sdev->model, scsi_dh->devlist[i].model,
83 strlen(scsi_dh->devlist[i].model))) {
84 found = 1;
85 break;
86 }
87 }
88 return found; 59 return found;
89} 60}
90 61
@@ -102,41 +73,14 @@ device_handler_match(struct scsi_device_handler *scsi_dh,
102 struct scsi_device *sdev) 73 struct scsi_device *sdev)
103{ 74{
104 struct scsi_device_handler *found_dh = NULL; 75 struct scsi_device_handler *found_dh = NULL;
105 struct scsi_dh_devinfo_list *tmp; 76 int idx;
106 77
107 found_dh = scsi_dh_cache_lookup(sdev); 78 idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
108 if (found_dh) 79 SCSI_DEVINFO_DH);
109 return found_dh; 80 found_dh = get_device_handler_by_idx(idx);
110 81
111 if (scsi_dh) { 82 if (scsi_dh && found_dh != scsi_dh)
112 if (scsi_dh_handler_lookup(scsi_dh, sdev)) 83 found_dh = NULL;
113 found_dh = scsi_dh;
114 } else {
115 struct scsi_device_handler *tmp_dh;
116
117 spin_lock(&list_lock);
118 list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
119 if (scsi_dh_handler_lookup(tmp_dh, sdev))
120 found_dh = tmp_dh;
121 }
122 spin_unlock(&list_lock);
123 }
124
125 if (found_dh) { /* If device is found, add it to the cache */
126 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
127 if (tmp) {
128 strncpy(tmp->vendor, sdev->vendor, 8);
129 strncpy(tmp->model, sdev->model, 16);
130 tmp->vendor[8] = '\0';
131 tmp->model[16] = '\0';
132 tmp->handler = found_dh;
133 spin_lock(&list_lock);
134 list_add(&tmp->node, &scsi_dh_dev_list);
135 spin_unlock(&list_lock);
136 } else {
137 found_dh = NULL;
138 }
139 }
140 84
141 return found_dh; 85 return found_dh;
142} 86}
@@ -373,12 +317,25 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data)
373 */ 317 */
374int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) 318int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
375{ 319{
320 int i;
321
376 if (get_device_handler(scsi_dh->name)) 322 if (get_device_handler(scsi_dh->name))
377 return -EBUSY; 323 return -EBUSY;
378 324
379 spin_lock(&list_lock); 325 spin_lock(&list_lock);
326 scsi_dh->idx = scsi_dh_list_idx++;
380 list_add(&scsi_dh->list, &scsi_dh_list); 327 list_add(&scsi_dh->list, &scsi_dh_list);
381 spin_unlock(&list_lock); 328 spin_unlock(&list_lock);
329
330 for (i = 0; scsi_dh->devlist[i].vendor; i++) {
331 scsi_dev_info_list_add_keyed(0,
332 scsi_dh->devlist[i].vendor,
333 scsi_dh->devlist[i].model,
334 NULL,
335 scsi_dh->idx,
336 SCSI_DEVINFO_DH);
337 }
338
382 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add); 339 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
383 printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name); 340 printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
384 341
@@ -395,7 +352,7 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler);
395 */ 352 */
396int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) 353int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
397{ 354{
398 struct scsi_dh_devinfo_list *tmp, *pos; 355 int i;
399 356
400 if (!get_device_handler(scsi_dh->name)) 357 if (!get_device_handler(scsi_dh->name))
401 return -ENODEV; 358 return -ENODEV;
@@ -403,14 +360,14 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
403 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, 360 bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
404 scsi_dh_notifier_remove); 361 scsi_dh_notifier_remove);
405 362
363 for (i = 0; scsi_dh->devlist[i].vendor; i++) {
364 scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor,
365 scsi_dh->devlist[i].model,
366 SCSI_DEVINFO_DH);
367 }
368
406 spin_lock(&list_lock); 369 spin_lock(&list_lock);
407 list_del(&scsi_dh->list); 370 list_del(&scsi_dh->list);
408 list_for_each_entry_safe(pos, tmp, &scsi_dh_dev_list, node) {
409 if (pos->handler == scsi_dh) {
410 list_del(&pos->node);
411 kfree(pos);
412 }
413 }
414 spin_unlock(&list_lock); 371 spin_unlock(&list_lock);
415 printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name); 372 printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
416 373
@@ -576,6 +533,10 @@ static int __init scsi_dh_init(void)
576{ 533{
577 int r; 534 int r;
578 535
536 r = scsi_dev_info_add_list(SCSI_DEVINFO_DH, "SCSI Device Handler");
537 if (r)
538 return r;
539
579 r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb); 540 r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);
580 541
581 if (!r) 542 if (!r)
@@ -590,6 +551,7 @@ static void __exit scsi_dh_exit(void)
590 bus_for_each_dev(&scsi_bus_type, NULL, NULL, 551 bus_for_each_dev(&scsi_bus_type, NULL, NULL,
591 scsi_dh_sysfs_attr_remove); 552 scsi_dh_sysfs_attr_remove);
592 bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb); 553 bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
554 scsi_dev_info_remove_list(SCSI_DEVINFO_DH);
593} 555}
594 556
595module_init(scsi_dh_init); 557module_init(scsi_dh_init);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index ce9e0adc8df8..9868afdb24e2 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -45,6 +45,7 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
45enum { 45enum {
46 SCSI_DEVINFO_GLOBAL = 0, 46 SCSI_DEVINFO_GLOBAL = 0,
47 SCSI_DEVINFO_SPI, 47 SCSI_DEVINFO_SPI,
48 SCSI_DEVINFO_DH,
48}; 49};
49 50
50extern int scsi_get_device_flags(struct scsi_device *sdev, 51extern int scsi_get_device_flags(struct scsi_device *sdev,
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 85867dcde335..f171c65dc5a8 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -184,6 +184,7 @@ typedef void (*activate_complete)(void *, int);
184struct scsi_device_handler { 184struct scsi_device_handler {
185 /* Used by the infrastructure */ 185 /* Used by the infrastructure */
186 struct list_head list; /* list of scsi_device_handlers */ 186 struct list_head list; /* list of scsi_device_handlers */
187 int idx;
187 188
188 /* Filled by the hardware handler */ 189 /* Filled by the hardware handler */
189 struct module *module; 190 struct module *module;