Skip to content

Commit

Permalink
[SCSI] scsi_dh: Implement match callback function
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
  • Loading branch information
hreinecke authored and James Bottomley committed Aug 30, 2011
1 parent 2a9ab40 commit 6c3633d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 25 deletions.
53 changes: 46 additions & 7 deletions drivers/scsi/device_handler/scsi_dh.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,46 @@ static struct scsi_device_handler *get_device_handler_by_idx(int idx)
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
* @scsi_dh - The device handler to match against or NULL
Expand All @@ -72,12 +112,11 @@ static struct scsi_device_handler *
device_handler_match(struct scsi_device_handler *scsi_dh,
struct scsi_device *sdev)
{
struct scsi_device_handler *found_dh = NULL;
int idx;
struct scsi_device_handler *found_dh;

idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
SCSI_DEVINFO_DH);
found_dh = get_device_handler_by_idx(idx);
found_dh = device_handler_match_function(sdev);
if (!found_dh)
found_dh = device_handler_match_devlist(sdev);

if (scsi_dh && found_dh != scsi_dh)
found_dh = NULL;
Expand Down Expand Up @@ -327,7 +366,7 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
list_add(&scsi_dh->list, &scsi_dh_list);
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_dh->devlist[i].vendor,
scsi_dh->devlist[i].model,
Expand Down Expand Up @@ -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,
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_dh->devlist[i].model,
SCSI_DEVINFO_DH);
Expand Down
23 changes: 5 additions & 18 deletions drivers/scsi/device_handler/scsi_dh_alua.c
Original file line number Diff line number Diff line change
Expand Up @@ -677,36 +677,23 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req)

}

static const struct scsi_dh_devlist alua_dev_list[] = {
{"HP", "MSA VOLUME" },
{"HP", "HSV101" },
{"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 bool alua_match(struct scsi_device *sdev)
{
return (scsi_device_tpgs(sdev) != 0);
}

static int alua_bus_attach(struct scsi_device *sdev);
static void alua_bus_detach(struct scsi_device *sdev);

static struct scsi_device_handler alua_dh = {
.name = ALUA_DH_NAME,
.module = THIS_MODULE,
.devlist = alua_dev_list,
.attach = alua_bus_attach,
.detach = alua_bus_detach,
.prep_fn = alua_prep_fn,
.check_sense = alua_check_sense,
.activate = alua_activate,
.match = alua_match,
};

/*
Expand Down
1 change: 1 addition & 0 deletions include/scsi/scsi_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ struct scsi_device_handler {
int (*activate)(struct scsi_device *, activate_complete, void *);
int (*prep_fn)(struct scsi_device *, struct request *);
int (*set_params)(struct scsi_device *, const char *);
bool (*match)(struct scsi_device *);
};

struct scsi_dh_data {
Expand Down

0 comments on commit 6c3633d

Please sign in to comment.