Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+46 −7
Original line number Diff line number Diff line
@@ -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);
+5 −18
Original line number Diff line number Diff line
@@ -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[] = {
	{"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);
@@ -701,12 +688,12 @@ 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,
};

/*
+1 −0
Original line number Diff line number Diff line
@@ -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 {