0001
0002
0003
0004
0005
0006
0007
0008
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
0121
0122
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
0161
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
0180
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
0194
0195
0196
0197
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
0219
0220
0221
0222
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
0240
0241
0242
0243
0244
0245
0246
0247
0248
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
0290
0291
0292
0293
0294
0295
0296
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
0316
0317
0318
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
0352
0353
0354
0355
0356
0357
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);