diff options
author | Hannes Reinecke <hare@suse.de> | 2011-08-24 04:51:15 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-08-30 15:28:30 -0400 |
commit | 6c3633d08acf514e2e89aa95d2346ce9d64d719a (patch) | |
tree | dcd1adaca314f4acb3f0979df75756b36b20e0ef /drivers/scsi/device_handler | |
parent | 2a9ab40f74eb22cdf02e8f687bef7f3eac7f6cfa (diff) |
[SCSI] scsi_dh: Implement match callback function
Some device handler types are not tied to the vendor/model
but rather to a specific capability. Eg ALUA is supported
if the 'TPGS' setting in the standard inquiry is set.
This patch implements a 'match' callback for device handler
which supersedes the original vendor/model lookup and
implements the callback for the ALUA handler.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/device_handler')
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh.c | 53 | ||||
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_alua.c | 23 |
2 files changed, 51 insertions, 25 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c index fccd0f6cfc90..3ac71cf6b7f0 100644 --- a/drivers/scsi/device_handler/scsi_dh.c +++ b/drivers/scsi/device_handler/scsi_dh.c | |||
@@ -60,6 +60,46 @@ static struct scsi_device_handler *get_device_handler_by_idx(int idx) | |||
60 | } | 60 | } |
61 | 61 | ||
62 | /* | 62 | /* |
63 | * device_handler_match_function - Match a device handler to a device | ||
64 | * @sdev - SCSI device to be tested | ||
65 | * | ||
66 | * Tests @sdev against the match function of all registered device_handler. | ||
67 | * Returns the found device handler or NULL if not found. | ||
68 | */ | ||
69 | static struct scsi_device_handler * | ||
70 | device_handler_match_function(struct scsi_device *sdev) | ||
71 | { | ||
72 | struct scsi_device_handler *tmp_dh, *found_dh = NULL; | ||
73 | |||
74 | spin_lock(&list_lock); | ||
75 | list_for_each_entry(tmp_dh, &scsi_dh_list, list) { | ||
76 | if (tmp_dh->match && tmp_dh->match(sdev)) { | ||
77 | found_dh = tmp_dh; | ||
78 | break; | ||
79 | } | ||
80 | } | ||
81 | spin_unlock(&list_lock); | ||
82 | return found_dh; | ||
83 | } | ||
84 | |||
85 | /* | ||
86 | * device_handler_match_devlist - Match a device handler to a device | ||
87 | * @sdev - SCSI device to be tested | ||
88 | * | ||
89 | * Tests @sdev against all device_handler registered in the devlist. | ||
90 | * Returns the found device handler or NULL if not found. | ||
91 | */ | ||
92 | static struct scsi_device_handler * | ||
93 | device_handler_match_devlist(struct scsi_device *sdev) | ||
94 | { | ||
95 | int idx; | ||
96 | |||
97 | idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model, | ||
98 | SCSI_DEVINFO_DH); | ||
99 | return get_device_handler_by_idx(idx); | ||
100 | } | ||
101 | |||
102 | /* | ||
63 | * device_handler_match - Attach a device handler to a device | 103 | * device_handler_match - Attach a device handler to a device |
64 | * @scsi_dh - The device handler to match against or NULL | 104 | * @scsi_dh - The device handler to match against or NULL |
65 | * @sdev - SCSI device to be tested against @scsi_dh | 105 | * @sdev - SCSI device to be tested against @scsi_dh |
@@ -72,12 +112,11 @@ static struct scsi_device_handler * | |||
72 | device_handler_match(struct scsi_device_handler *scsi_dh, | 112 | device_handler_match(struct scsi_device_handler *scsi_dh, |
73 | struct scsi_device *sdev) | 113 | struct scsi_device *sdev) |
74 | { | 114 | { |
75 | struct scsi_device_handler *found_dh = NULL; | 115 | struct scsi_device_handler *found_dh; |
76 | int idx; | ||
77 | 116 | ||
78 | idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model, | 117 | found_dh = device_handler_match_function(sdev); |
79 | SCSI_DEVINFO_DH); | 118 | if (!found_dh) |
80 | found_dh = get_device_handler_by_idx(idx); | 119 | found_dh = device_handler_match_devlist(sdev); |
81 | 120 | ||
82 | if (scsi_dh && found_dh != scsi_dh) | 121 | if (scsi_dh && found_dh != scsi_dh) |
83 | found_dh = NULL; | 122 | found_dh = NULL; |
@@ -327,7 +366,7 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) | |||
327 | list_add(&scsi_dh->list, &scsi_dh_list); | 366 | list_add(&scsi_dh->list, &scsi_dh_list); |
328 | spin_unlock(&list_lock); | 367 | spin_unlock(&list_lock); |
329 | 368 | ||
330 | for (i = 0; scsi_dh->devlist[i].vendor; i++) { | 369 | for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) { |
331 | scsi_dev_info_list_add_keyed(0, | 370 | scsi_dev_info_list_add_keyed(0, |
332 | scsi_dh->devlist[i].vendor, | 371 | scsi_dh->devlist[i].vendor, |
333 | scsi_dh->devlist[i].model, | 372 | scsi_dh->devlist[i].model, |
@@ -360,7 +399,7 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) | |||
360 | bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, | 399 | bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, |
361 | scsi_dh_notifier_remove); | 400 | scsi_dh_notifier_remove); |
362 | 401 | ||
363 | for (i = 0; scsi_dh->devlist[i].vendor; i++) { | 402 | for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) { |
364 | scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor, | 403 | scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor, |
365 | scsi_dh->devlist[i].model, | 404 | scsi_dh->devlist[i].model, |
366 | SCSI_DEVINFO_DH); | 405 | SCSI_DEVINFO_DH); |
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 432677889eae..80c5cf327b84 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c | |||
@@ -677,23 +677,10 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) | |||
677 | 677 | ||
678 | } | 678 | } |
679 | 679 | ||
680 | static const struct scsi_dh_devlist alua_dev_list[] = { | 680 | static bool alua_match(struct scsi_device *sdev) |
681 | {"HP", "MSA VOLUME" }, | 681 | { |
682 | {"HP", "HSV101" }, | 682 | return (scsi_device_tpgs(sdev) != 0); |
683 | {"HP", "HSV111" }, | 683 | } |
684 | {"HP", "HSV200" }, | ||
685 | {"HP", "HSV210" }, | ||
686 | {"HP", "HSV300" }, | ||
687 | {"IBM", "2107900" }, | ||
688 | {"IBM", "2145" }, | ||
689 | {"Pillar", "Axiom" }, | ||
690 | {"Intel", "Multi-Flex"}, | ||
691 | {"NETAPP", "LUN"}, | ||
692 | {"NETAPP", "LUN C-Mode"}, | ||
693 | {"AIX", "NVDISK"}, | ||
694 | {"Promise", "VTrak"}, | ||
695 | {NULL, NULL} | ||
696 | }; | ||
697 | 684 | ||
698 | static int alua_bus_attach(struct scsi_device *sdev); | 685 | static int alua_bus_attach(struct scsi_device *sdev); |
699 | static void alua_bus_detach(struct scsi_device *sdev); | 686 | static void alua_bus_detach(struct scsi_device *sdev); |
@@ -701,12 +688,12 @@ static void alua_bus_detach(struct scsi_device *sdev); | |||
701 | static struct scsi_device_handler alua_dh = { | 688 | static struct scsi_device_handler alua_dh = { |
702 | .name = ALUA_DH_NAME, | 689 | .name = ALUA_DH_NAME, |
703 | .module = THIS_MODULE, | 690 | .module = THIS_MODULE, |
704 | .devlist = alua_dev_list, | ||
705 | .attach = alua_bus_attach, | 691 | .attach = alua_bus_attach, |
706 | .detach = alua_bus_detach, | 692 | .detach = alua_bus_detach, |
707 | .prep_fn = alua_prep_fn, | 693 | .prep_fn = alua_prep_fn, |
708 | .check_sense = alua_check_sense, | 694 | .check_sense = alua_check_sense, |
709 | .activate = alua_activate, | 695 | .activate = alua_activate, |
696 | .match = alua_match, | ||
710 | }; | 697 | }; |
711 | 698 | ||
712 | /* | 699 | /* |