[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>
This commit is contained in:

committed by
James Bottomley

parent
2a9ab40f74
commit
6c3633d08a
@@ -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
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
@@ -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);
|
||||
|
Reference in New Issue
Block a user