Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * SCSI device handler infrastruture.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright IBM Corporation, 2007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *      Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *               Chandra Seetharaman <sekharan@us.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *               Mike Anderson <andmike@linux.vnet.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <scsi/scsi_dh.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include "scsi_priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) static DEFINE_SPINLOCK(list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) static LIST_HEAD(scsi_dh_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) struct scsi_dh_blist {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	const char *vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	const char *model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	const char *driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) static const struct scsi_dh_blist scsi_dh_blist[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	{"DGC", "RAID",			"emc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	{"DGC", "DISK",			"emc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	{"DGC", "VRAID",		"emc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	{"COMPAQ", "MSA1000 VOLUME",	"hp_sw" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	{"COMPAQ", "HSV110",		"hp_sw" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	{"HP", "HSV100",		"hp_sw"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	{"DEC", "HSG80",		"hp_sw"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	{"IBM", "1722",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	{"IBM", "1724",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	{"IBM", "1726",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	{"IBM", "1742",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	{"IBM", "1745",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	{"IBM", "1746",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	{"IBM", "1813",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	{"IBM", "1814",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	{"IBM", "1815",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	{"IBM", "1818",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	{"IBM", "3526",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	{"IBM", "3542",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	{"IBM", "3552",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	{"SGI", "TP9300",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	{"SGI", "TP9400",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	{"SGI", "TP9500",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	{"SGI", "TP9700",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	{"SGI", "IS",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	{"STK", "OPENstorage",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	{"STK", "FLEXLINE 380",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	{"STK", "BladeCtlr",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	{"SUN", "CSM",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	{"SUN", "LCSM100",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	{"SUN", "STK6580_6780",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	{"SUN", "SUN_6180",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	{"SUN", "ArrayStorage",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	{"DELL", "MD3",			"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	{"NETAPP", "INF-01-00",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	{"LSI", "INF-01-00",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	{"ENGENIO", "INF-01-00",	"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	{"LENOVO", "DE_Series",		"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	{"FUJITSU", "ETERNUS_AHB",	"rdac", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	{NULL, NULL,			NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static const char *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) scsi_dh_find_driver(struct scsi_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	const struct scsi_dh_blist *b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	if (scsi_device_tpgs(sdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		return "alua";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	for (b = scsi_dh_blist; b->vendor; b++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		if (!strncmp(sdev->vendor, b->vendor, strlen(b->vendor)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		    !strncmp(sdev->model, b->model, strlen(b->model))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			return b->driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static struct scsi_device_handler *__scsi_dh_lookup(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct scsi_device_handler *tmp, *found = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	spin_lock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	list_for_each_entry(tmp, &scsi_dh_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		if (!strncmp(tmp->name, name, strlen(tmp->name))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 			found = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	spin_unlock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	return found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static struct scsi_device_handler *scsi_dh_lookup(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct scsi_device_handler *dh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (!name || strlen(name) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	dh = __scsi_dh_lookup(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	if (!dh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		request_module("scsi_dh_%s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		dh = __scsi_dh_lookup(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	return dh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)  * scsi_dh_handler_attach - Attach a device handler to a device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  * @sdev - SCSI device the device handler should attach to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  * @scsi_dh - The device handler to attach
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int scsi_dh_handler_attach(struct scsi_device *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 				  struct scsi_device_handler *scsi_dh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	int error, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	if (!try_module_get(scsi_dh->module))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	error = scsi_dh->attach(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	if (error != SCSI_DH_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		switch (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		case SCSI_DH_NOMEM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		case SCSI_DH_RES_TEMP_UNAVAIL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		case SCSI_DH_DEV_UNSUPP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		case SCSI_DH_NOSYS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 			ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		if (ret != -ENODEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 				    scsi_dh->name, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		module_put(scsi_dh->module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		sdev->handler = scsi_dh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  * scsi_dh_handler_detach - Detach a device handler from a device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)  * @sdev - SCSI device the device handler should be detached from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void scsi_dh_handler_detach(struct scsi_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	sdev->handler->detach(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", sdev->handler->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	module_put(sdev->handler->module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) void scsi_dh_add_device(struct scsi_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	struct scsi_device_handler *devinfo = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	const char *drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	drv = scsi_dh_find_driver(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if (drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		devinfo = __scsi_dh_lookup(drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	 * device_handler is optional, so ignore errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	 * from scsi_dh_handler_attach()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	if (devinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		(void)scsi_dh_handler_attach(sdev, devinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) void scsi_dh_release_device(struct scsi_device *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (sdev->handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		scsi_dh_handler_detach(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  * scsi_register_device_handler - register a device handler personality
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)  *      module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  * @scsi_dh - device handler to be registered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  * Returns 0 on success, -EBUSY if handler already registered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	if (__scsi_dh_lookup(scsi_dh->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (!scsi_dh->attach || !scsi_dh->detach)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	spin_lock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	list_add(&scsi_dh->list, &scsi_dh_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	spin_unlock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	return SCSI_DH_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) EXPORT_SYMBOL_GPL(scsi_register_device_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  * scsi_unregister_device_handler - register a device handler personality
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  *      module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  * @scsi_dh - device handler to be unregistered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  * Returns 0 on success, -ENODEV if handler not registered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (!__scsi_dh_lookup(scsi_dh->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	spin_lock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	list_del(&scsi_dh->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	spin_unlock(&list_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	return SCSI_DH_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  * scsi_dh_activate - activate the path associated with the scsi_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  *      corresponding to the given request queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)  *     Returns immediately without waiting for activation to be completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)  * @q    - Request queue that is associated with the scsi_device to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)  *         activated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)  * @fn   - Function to be called upon completion of the activation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)  *         Function fn is called with data (below) and the error code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)  *         Function fn may be called from the same calling context. So,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)  *         do not hold the lock in the caller which may be needed in fn.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)  * @data - data passed to the function fn upon completion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	struct scsi_device *sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	int err = SCSI_DH_NOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	sdev = scsi_device_from_queue(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	if (!sdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		if (fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 			fn(data, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	if (!sdev->handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		goto out_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	err = SCSI_DH_NOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	if (sdev->sdev_state == SDEV_CANCEL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	    sdev->sdev_state == SDEV_DEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		goto out_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	err = SCSI_DH_DEV_OFFLINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	if (sdev->sdev_state == SDEV_OFFLINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		goto out_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	if (sdev->handler->activate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		err = sdev->handler->activate(sdev, fn, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) out_put_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	put_device(&sdev->sdev_gendev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) out_fn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	if (fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		fn(data, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	goto out_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) EXPORT_SYMBOL_GPL(scsi_dh_activate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)  * scsi_dh_set_params - set the parameters for the device as per the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)  *      string specified in params.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)  * @q - Request queue that is associated with the scsi_device for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  *      which the parameters to be set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  * @params - parameters in the following format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)  *      "no_of_params\0param1\0param2\0param3\0...\0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  *      for example, string for 2 parameters with value 10 and 21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)  *      is specified as "2\010\021\0".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) int scsi_dh_set_params(struct request_queue *q, const char *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	struct scsi_device *sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	int err = -SCSI_DH_NOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	sdev = scsi_device_from_queue(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	if (!sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	if (sdev->handler && sdev->handler->set_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		err = sdev->handler->set_params(sdev, params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	put_device(&sdev->sdev_gendev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) EXPORT_SYMBOL_GPL(scsi_dh_set_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)  * scsi_dh_attach - Attach device handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)  * @q - Request queue that is associated with the scsi_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)  *      the handler should be attached to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)  * @name - name of the handler to attach
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int scsi_dh_attach(struct request_queue *q, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	struct scsi_device *sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	struct scsi_device_handler *scsi_dh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	sdev = scsi_device_from_queue(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	if (!sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	scsi_dh = scsi_dh_lookup(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	if (!scsi_dh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		goto out_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	if (sdev->handler) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		if (sdev->handler != scsi_dh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 			err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		goto out_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	err = scsi_dh_handler_attach(sdev, scsi_dh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) out_put_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	put_device(&sdev->sdev_gendev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) EXPORT_SYMBOL_GPL(scsi_dh_attach);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)  * scsi_dh_attached_handler_name - Get attached device handler's name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)  * @q - Request queue that is associated with the scsi_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)  *      that may have a device handler attached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)  * @gfp - the GFP mask used in the kmalloc() call when allocating memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)  * Returns name of attached handler, NULL if no handler is attached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)  * Caller must take care to free the returned string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	struct scsi_device *sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	const char *handler_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	sdev = scsi_device_from_queue(q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	if (!sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	if (sdev->handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		handler_name = kstrdup(sdev->handler->name, gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	put_device(&sdev->sdev_gendev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	return handler_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name);