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 fccd0f6cfc9..3ac71cf6b7f 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 432677889ea..80c5cf327b8 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 | /* |
