Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * SCSI device handler infrastructure.
0004  *
0005  * Copyright IBM Corporation, 2007
0006  *      Authors:
0007  *               Chandra Seetharaman <sekharan@us.ibm.com>
0008  *               Mike Anderson <andmike@linux.vnet.ibm.com>
0009  */
0010 
0011 #include <linux/slab.h>
0012 #include <linux/module.h>
0013 #include <scsi/scsi_dh.h>
0014 #include "scsi_priv.h"
0015 
0016 static DEFINE_SPINLOCK(list_lock);
0017 static LIST_HEAD(scsi_dh_list);
0018 
0019 struct scsi_dh_blist {
0020     const char *vendor;
0021     const char *model;
0022     const char *driver;
0023 };
0024 
0025 static const struct scsi_dh_blist scsi_dh_blist[] = {
0026     {"DGC", "RAID",         "emc" },
0027     {"DGC", "DISK",         "emc" },
0028     {"DGC", "VRAID",        "emc" },
0029 
0030     {"COMPAQ", "MSA1000 VOLUME",    "hp_sw" },
0031     {"COMPAQ", "HSV110",        "hp_sw" },
0032     {"HP", "HSV100",        "hp_sw"},
0033     {"DEC", "HSG80",        "hp_sw"},
0034 
0035     {"IBM", "1722",         "rdac", },
0036     {"IBM", "1724",         "rdac", },
0037     {"IBM", "1726",         "rdac", },
0038     {"IBM", "1742",         "rdac", },
0039     {"IBM", "1745",         "rdac", },
0040     {"IBM", "1746",         "rdac", },
0041     {"IBM", "1813",         "rdac", },
0042     {"IBM", "1814",         "rdac", },
0043     {"IBM", "1815",         "rdac", },
0044     {"IBM", "1818",         "rdac", },
0045     {"IBM", "3526",         "rdac", },
0046     {"IBM", "3542",         "rdac", },
0047     {"IBM", "3552",         "rdac", },
0048     {"SGI", "TP9300",       "rdac", },
0049     {"SGI", "TP9400",       "rdac", },
0050     {"SGI", "TP9500",       "rdac", },
0051     {"SGI", "TP9700",       "rdac", },
0052     {"SGI", "IS",           "rdac", },
0053     {"STK", "OPENstorage",      "rdac", },
0054     {"STK", "FLEXLINE 380",     "rdac", },
0055     {"STK", "BladeCtlr",        "rdac", },
0056     {"SUN", "CSM",          "rdac", },
0057     {"SUN", "LCSM100",      "rdac", },
0058     {"SUN", "STK6580_6780",     "rdac", },
0059     {"SUN", "SUN_6180",     "rdac", },
0060     {"SUN", "ArrayStorage",     "rdac", },
0061     {"DELL", "MD3",         "rdac", },
0062     {"NETAPP", "INF-01-00",     "rdac", },
0063     {"LSI", "INF-01-00",        "rdac", },
0064     {"ENGENIO", "INF-01-00",    "rdac", },
0065     {"LENOVO", "DE_Series",     "rdac", },
0066     {"FUJITSU", "ETERNUS_AHB",  "rdac", },
0067     {NULL, NULL,            NULL },
0068 };
0069 
0070 static const char *
0071 scsi_dh_find_driver(struct scsi_device *sdev)
0072 {
0073     const struct scsi_dh_blist *b;
0074 
0075     if (scsi_device_tpgs(sdev))
0076         return "alua";
0077 
0078     for (b = scsi_dh_blist; b->vendor; b++) {
0079         if (!strncmp(sdev->vendor, b->vendor, strlen(b->vendor)) &&
0080             !strncmp(sdev->model, b->model, strlen(b->model))) {
0081             return b->driver;
0082         }
0083     }
0084     return NULL;
0085 }
0086 
0087 
0088 static struct scsi_device_handler *__scsi_dh_lookup(const char *name)
0089 {
0090     struct scsi_device_handler *tmp, *found = NULL;
0091 
0092     spin_lock(&list_lock);
0093     list_for_each_entry(tmp, &scsi_dh_list, list) {
0094         if (!strncmp(tmp->name, name, strlen(tmp->name))) {
0095             found = tmp;
0096             break;
0097         }
0098     }
0099     spin_unlock(&list_lock);
0100     return found;
0101 }
0102 
0103 static struct scsi_device_handler *scsi_dh_lookup(const char *name)
0104 {
0105     struct scsi_device_handler *dh;
0106 
0107     if (!name || strlen(name) == 0)
0108         return NULL;
0109 
0110     dh = __scsi_dh_lookup(name);
0111     if (!dh) {
0112         request_module("scsi_dh_%s", name);
0113         dh = __scsi_dh_lookup(name);
0114     }
0115 
0116     return dh;
0117 }
0118 
0119 /*
0120  * scsi_dh_handler_attach - Attach a device handler to a device
0121  * @sdev - SCSI device the device handler should attach to
0122  * @scsi_dh - The device handler to attach
0123  */
0124 static int scsi_dh_handler_attach(struct scsi_device *sdev,
0125                   struct scsi_device_handler *scsi_dh)
0126 {
0127     int error, ret = 0;
0128 
0129     if (!try_module_get(scsi_dh->module))
0130         return -EINVAL;
0131 
0132     error = scsi_dh->attach(sdev);
0133     if (error != SCSI_DH_OK) {
0134         switch (error) {
0135         case SCSI_DH_NOMEM:
0136             ret = -ENOMEM;
0137             break;
0138         case SCSI_DH_RES_TEMP_UNAVAIL:
0139             ret = -EAGAIN;
0140             break;
0141         case SCSI_DH_DEV_UNSUPP:
0142         case SCSI_DH_NOSYS:
0143             ret = -ENODEV;
0144             break;
0145         default:
0146             ret = -EINVAL;
0147             break;
0148         }
0149         if (ret != -ENODEV)
0150             sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%d)\n",
0151                     scsi_dh->name, error);
0152         module_put(scsi_dh->module);
0153     } else
0154         sdev->handler = scsi_dh;
0155 
0156     return ret;
0157 }
0158 
0159 /*
0160  * scsi_dh_handler_detach - Detach a device handler from a device
0161  * @sdev - SCSI device the device handler should be detached from
0162  */
0163 static void scsi_dh_handler_detach(struct scsi_device *sdev)
0164 {
0165     sdev->handler->detach(sdev);
0166     sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", sdev->handler->name);
0167     module_put(sdev->handler->module);
0168 }
0169 
0170 void scsi_dh_add_device(struct scsi_device *sdev)
0171 {
0172     struct scsi_device_handler *devinfo = NULL;
0173     const char *drv;
0174 
0175     drv = scsi_dh_find_driver(sdev);
0176     if (drv)
0177         devinfo = __scsi_dh_lookup(drv);
0178     /*
0179      * device_handler is optional, so ignore errors
0180      * from scsi_dh_handler_attach()
0181      */
0182     if (devinfo)
0183         (void)scsi_dh_handler_attach(sdev, devinfo);
0184 }
0185 
0186 void scsi_dh_release_device(struct scsi_device *sdev)
0187 {
0188     if (sdev->handler)
0189         scsi_dh_handler_detach(sdev);
0190 }
0191 
0192 /*
0193  * scsi_register_device_handler - register a device handler personality
0194  *      module.
0195  * @scsi_dh - device handler to be registered.
0196  *
0197  * Returns 0 on success, -EBUSY if handler already registered.
0198  */
0199 int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
0200 {
0201     if (__scsi_dh_lookup(scsi_dh->name))
0202         return -EBUSY;
0203 
0204     if (!scsi_dh->attach || !scsi_dh->detach)
0205         return -EINVAL;
0206 
0207     spin_lock(&list_lock);
0208     list_add(&scsi_dh->list, &scsi_dh_list);
0209     spin_unlock(&list_lock);
0210 
0211     printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
0212 
0213     return SCSI_DH_OK;
0214 }
0215 EXPORT_SYMBOL_GPL(scsi_register_device_handler);
0216 
0217 /*
0218  * scsi_unregister_device_handler - register a device handler personality
0219  *      module.
0220  * @scsi_dh - device handler to be unregistered.
0221  *
0222  * Returns 0 on success, -ENODEV if handler not registered.
0223  */
0224 int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
0225 {
0226     if (!__scsi_dh_lookup(scsi_dh->name))
0227         return -ENODEV;
0228 
0229     spin_lock(&list_lock);
0230     list_del(&scsi_dh->list);
0231     spin_unlock(&list_lock);
0232     printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
0233 
0234     return SCSI_DH_OK;
0235 }
0236 EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
0237 
0238 /*
0239  * scsi_dh_activate - activate the path associated with the scsi_device
0240  *      corresponding to the given request queue.
0241  *     Returns immediately without waiting for activation to be completed.
0242  * @q    - Request queue that is associated with the scsi_device to be
0243  *         activated.
0244  * @fn   - Function to be called upon completion of the activation.
0245  *         Function fn is called with data (below) and the error code.
0246  *         Function fn may be called from the same calling context. So,
0247  *         do not hold the lock in the caller which may be needed in fn.
0248  * @data - data passed to the function fn upon completion.
0249  *
0250  */
0251 int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
0252 {
0253     struct scsi_device *sdev;
0254     int err = SCSI_DH_NOSYS;
0255 
0256     sdev = scsi_device_from_queue(q);
0257     if (!sdev) {
0258         if (fn)
0259             fn(data, err);
0260         return err;
0261     }
0262 
0263     if (!sdev->handler)
0264         goto out_fn;
0265     err = SCSI_DH_NOTCONN;
0266     if (sdev->sdev_state == SDEV_CANCEL ||
0267         sdev->sdev_state == SDEV_DEL)
0268         goto out_fn;
0269 
0270     err = SCSI_DH_DEV_OFFLINED;
0271     if (sdev->sdev_state == SDEV_OFFLINE)
0272         goto out_fn;
0273 
0274     if (sdev->handler->activate)
0275         err = sdev->handler->activate(sdev, fn, data);
0276 
0277 out_put_device:
0278     put_device(&sdev->sdev_gendev);
0279     return err;
0280 
0281 out_fn:
0282     if (fn)
0283         fn(data, err);
0284     goto out_put_device;
0285 }
0286 EXPORT_SYMBOL_GPL(scsi_dh_activate);
0287 
0288 /*
0289  * scsi_dh_set_params - set the parameters for the device as per the
0290  *      string specified in params.
0291  * @q - Request queue that is associated with the scsi_device for
0292  *      which the parameters to be set.
0293  * @params - parameters in the following format
0294  *      "no_of_params\0param1\0param2\0param3\0...\0"
0295  *      for example, string for 2 parameters with value 10 and 21
0296  *      is specified as "2\010\021\0".
0297  */
0298 int scsi_dh_set_params(struct request_queue *q, const char *params)
0299 {
0300     struct scsi_device *sdev;
0301     int err = -SCSI_DH_NOSYS;
0302 
0303     sdev = scsi_device_from_queue(q);
0304     if (!sdev)
0305         return err;
0306 
0307     if (sdev->handler && sdev->handler->set_params)
0308         err = sdev->handler->set_params(sdev, params);
0309     put_device(&sdev->sdev_gendev);
0310     return err;
0311 }
0312 EXPORT_SYMBOL_GPL(scsi_dh_set_params);
0313 
0314 /*
0315  * scsi_dh_attach - Attach device handler
0316  * @q - Request queue that is associated with the scsi_device
0317  *      the handler should be attached to
0318  * @name - name of the handler to attach
0319  */
0320 int scsi_dh_attach(struct request_queue *q, const char *name)
0321 {
0322     struct scsi_device *sdev;
0323     struct scsi_device_handler *scsi_dh;
0324     int err = 0;
0325 
0326     sdev = scsi_device_from_queue(q);
0327     if (!sdev)
0328         return -ENODEV;
0329 
0330     scsi_dh = scsi_dh_lookup(name);
0331     if (!scsi_dh) {
0332         err = -EINVAL;
0333         goto out_put_device;
0334     }
0335 
0336     if (sdev->handler) {
0337         if (sdev->handler != scsi_dh)
0338             err = -EBUSY;
0339         goto out_put_device;
0340     }
0341 
0342     err = scsi_dh_handler_attach(sdev, scsi_dh);
0343 
0344 out_put_device:
0345     put_device(&sdev->sdev_gendev);
0346     return err;
0347 }
0348 EXPORT_SYMBOL_GPL(scsi_dh_attach);
0349 
0350 /*
0351  * scsi_dh_attached_handler_name - Get attached device handler's name
0352  * @q - Request queue that is associated with the scsi_device
0353  *      that may have a device handler attached
0354  * @gfp - the GFP mask used in the kmalloc() call when allocating memory
0355  *
0356  * Returns name of attached handler, NULL if no handler is attached.
0357  * Caller must take care to free the returned string.
0358  */
0359 const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp)
0360 {
0361     struct scsi_device *sdev;
0362     const char *handler_name = NULL;
0363 
0364     sdev = scsi_device_from_queue(q);
0365     if (!sdev)
0366         return NULL;
0367 
0368     if (sdev->handler)
0369         handler_name = kstrdup(sdev->handler->name, gfp);
0370     put_device(&sdev->sdev_gendev);
0371     return handler_name;
0372 }
0373 EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name);