Commit 6c3633d0 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by James Bottomley

[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: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 2a9ab40f
...@@ -59,6 +59,46 @@ static struct scsi_device_handler *get_device_handler_by_idx(int idx) ...@@ -59,6 +59,46 @@ static struct scsi_device_handler *get_device_handler_by_idx(int idx)
return found; return found;
} }
/*
* device_handler_match_function - Match a device handler to a device
* @sdev - SCSI device to be tested
*
* Tests @sdev against the match function of all registered device_handler.
* Returns the found device handler or NULL if not found.
*/
static struct scsi_device_handler *
device_handler_match_function(struct scsi_device *sdev)
{
struct scsi_device_handler *tmp_dh, *found_dh = NULL;
spin_lock(&list_lock);
list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
if (tmp_dh->match && tmp_dh->match(sdev)) {
found_dh = tmp_dh;
break;
}
}
spin_unlock(&list_lock);
return found_dh;
}
/*
* device_handler_match_devlist - Match a device handler to a device
* @sdev - SCSI device to be tested
*
* Tests @sdev against all device_handler registered in the devlist.
* Returns the found device handler or NULL if not found.
*/
static struct scsi_device_handler *
device_handler_match_devlist(struct scsi_device *sdev)
{
int idx;
idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
SCSI_DEVINFO_DH);
return get_device_handler_by_idx(idx);
}
/* /*
* device_handler_match - Attach a device handler to a device * device_handler_match - Attach a device handler to a device
* @scsi_dh - The device handler to match against or NULL * @scsi_dh - The device handler to match against or NULL
...@@ -72,12 +112,11 @@ static struct scsi_device_handler * ...@@ -72,12 +112,11 @@ static struct scsi_device_handler *
device_handler_match(struct scsi_device_handler *scsi_dh, device_handler_match(struct scsi_device_handler *scsi_dh,
struct scsi_device *sdev) struct scsi_device *sdev)
{ {
struct scsi_device_handler *found_dh = NULL; struct scsi_device_handler *found_dh;
int idx;
idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model, found_dh = device_handler_match_function(sdev);
SCSI_DEVINFO_DH); if (!found_dh)
found_dh = get_device_handler_by_idx(idx); found_dh = device_handler_match_devlist(sdev);
if (scsi_dh && found_dh != scsi_dh) if (scsi_dh && found_dh != scsi_dh)
found_dh = NULL; found_dh = NULL;
...@@ -327,7 +366,7 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) ...@@ -327,7 +366,7 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
list_add(&scsi_dh->list, &scsi_dh_list); list_add(&scsi_dh->list, &scsi_dh_list);
spin_unlock(&list_lock); spin_unlock(&list_lock);
for (i = 0; scsi_dh->devlist[i].vendor; i++) { for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) {
scsi_dev_info_list_add_keyed(0, scsi_dev_info_list_add_keyed(0,
scsi_dh->devlist[i].vendor, scsi_dh->devlist[i].vendor,
scsi_dh->devlist[i].model, scsi_dh->devlist[i].model,
...@@ -360,7 +399,7 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) ...@@ -360,7 +399,7 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
scsi_dh_notifier_remove); scsi_dh_notifier_remove);
for (i = 0; scsi_dh->devlist[i].vendor; i++) { for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) {
scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor, scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor,
scsi_dh->devlist[i].model, scsi_dh->devlist[i].model,
SCSI_DEVINFO_DH); SCSI_DEVINFO_DH);
......
...@@ -677,23 +677,10 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) ...@@ -677,23 +677,10 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
} }
static const struct scsi_dh_devlist alua_dev_list[] = { static bool alua_match(struct scsi_device *sdev)
{"HP", "MSA VOLUME" }, {
{"HP", "HSV101" }, return (scsi_device_tpgs(sdev) != 0);
{"HP", "HSV111" }, }
{"HP", "HSV200" },
{"HP", "HSV210" },
{"HP", "HSV300" },
{"IBM", "2107900" },
{"IBM", "2145" },
{"Pillar", "Axiom" },
{"Intel", "Multi-Flex"},
{"NETAPP", "LUN"},
{"NETAPP", "LUN C-Mode"},
{"AIX", "NVDISK"},
{"Promise", "VTrak"},
{NULL, NULL}
};
static int alua_bus_attach(struct scsi_device *sdev); static int alua_bus_attach(struct scsi_device *sdev);
static void alua_bus_detach(struct scsi_device *sdev); static void alua_bus_detach(struct scsi_device *sdev);
...@@ -701,12 +688,12 @@ static void alua_bus_detach(struct scsi_device *sdev); ...@@ -701,12 +688,12 @@ static void alua_bus_detach(struct scsi_device *sdev);
static struct scsi_device_handler alua_dh = { static struct scsi_device_handler alua_dh = {
.name = ALUA_DH_NAME, .name = ALUA_DH_NAME,
.module = THIS_MODULE, .module = THIS_MODULE,
.devlist = alua_dev_list,
.attach = alua_bus_attach, .attach = alua_bus_attach,
.detach = alua_bus_detach, .detach = alua_bus_detach,
.prep_fn = alua_prep_fn, .prep_fn = alua_prep_fn,
.check_sense = alua_check_sense, .check_sense = alua_check_sense,
.activate = alua_activate, .activate = alua_activate,
.match = alua_match,
}; };
/* /*
......
...@@ -197,6 +197,7 @@ struct scsi_device_handler { ...@@ -197,6 +197,7 @@ struct scsi_device_handler {
int (*activate)(struct scsi_device *, activate_complete, void *); int (*activate)(struct scsi_device *, activate_complete, void *);
int (*prep_fn)(struct scsi_device *, struct request *); int (*prep_fn)(struct scsi_device *, struct request *);
int (*set_params)(struct scsi_device *, const char *); int (*set_params)(struct scsi_device *, const char *);
bool (*match)(struct scsi_device *);
}; };
struct scsi_dh_data { struct scsi_dh_data {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment