scsi_dh: move to drivers/scsi
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / scsi_dh.c
1 /*
2  * SCSI device handler infrastruture.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  * Copyright IBM Corporation, 2007
19  *      Authors:
20  *               Chandra Seetharaman <sekharan@us.ibm.com>
21  *               Mike Anderson <andmike@linux.vnet.ibm.com>
22  */
23
24 #include <linux/slab.h>
25 #include <linux/module.h>
26 #include <scsi/scsi_dh.h>
27 #include "scsi_priv.h"
28
29 static DEFINE_SPINLOCK(list_lock);
30 static LIST_HEAD(scsi_dh_list);
31
32 static struct scsi_device_handler *__scsi_dh_lookup(const char *name)
33 {
34         struct scsi_device_handler *tmp, *found = NULL;
35
36         spin_lock(&list_lock);
37         list_for_each_entry(tmp, &scsi_dh_list, list) {
38                 if (!strncmp(tmp->name, name, strlen(tmp->name))) {
39                         found = tmp;
40                         break;
41                 }
42         }
43         spin_unlock(&list_lock);
44         return found;
45 }
46
47 static struct scsi_device_handler *scsi_dh_lookup(const char *name)
48 {
49         struct scsi_device_handler *dh;
50
51         dh = __scsi_dh_lookup(name);
52         if (!dh) {
53                 request_module(name);
54                 dh = __scsi_dh_lookup(name);
55         }
56
57         return dh;
58 }
59
60 /*
61  * device_handler_match_function - Match a device handler to a device
62  * @sdev - SCSI device to be tested
63  *
64  * Tests @sdev against the match function of all registered device_handler.
65  * Returns the found device handler or NULL if not found.
66  */
67 static struct scsi_device_handler *
68 device_handler_match_function(struct scsi_device *sdev)
69 {
70         struct scsi_device_handler *tmp_dh, *found_dh = NULL;
71
72         spin_lock(&list_lock);
73         list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
74                 if (tmp_dh->match && tmp_dh->match(sdev)) {
75                         found_dh = tmp_dh;
76                         break;
77                 }
78         }
79         spin_unlock(&list_lock);
80         return found_dh;
81 }
82
83 /*
84  * device_handler_match - Attach a device handler to a device
85  * @scsi_dh - The device handler to match against or NULL
86  * @sdev - SCSI device to be tested against @scsi_dh
87  *
88  * Tests @sdev against the device handler @scsi_dh or against
89  * all registered device_handler if @scsi_dh == NULL.
90  * Returns the found device handler or NULL if not found.
91  */
92 static struct scsi_device_handler *
93 device_handler_match(struct scsi_device_handler *scsi_dh,
94                      struct scsi_device *sdev)
95 {
96         struct scsi_device_handler *found_dh;
97
98         found_dh = device_handler_match_function(sdev);
99
100         if (scsi_dh && found_dh != scsi_dh)
101                 found_dh = NULL;
102
103         return found_dh;
104 }
105
106 /*
107  * scsi_dh_handler_attach - Attach a device handler to a device
108  * @sdev - SCSI device the device handler should attach to
109  * @scsi_dh - The device handler to attach
110  */
111 static int scsi_dh_handler_attach(struct scsi_device *sdev,
112                                   struct scsi_device_handler *scsi_dh)
113 {
114         struct scsi_dh_data *d;
115
116         if (!try_module_get(scsi_dh->module))
117                 return -EINVAL;
118
119         d = scsi_dh->attach(sdev);
120         if (IS_ERR(d)) {
121                 sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%ld)\n",
122                             scsi_dh->name, PTR_ERR(d));
123                 module_put(scsi_dh->module);
124                 return PTR_ERR(d);
125         }
126
127         d->scsi_dh = scsi_dh;
128         d->sdev = sdev;
129
130         spin_lock_irq(sdev->request_queue->queue_lock);
131         sdev->scsi_dh_data = d;
132         spin_unlock_irq(sdev->request_queue->queue_lock);
133         return 0;
134 }
135
136 /*
137  * scsi_dh_handler_detach - Detach a device handler from a device
138  * @sdev - SCSI device the device handler should be detached from
139  */
140 static void scsi_dh_handler_detach(struct scsi_device *sdev)
141 {
142         struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
143         struct scsi_device_handler *scsi_dh = scsi_dh_data->scsi_dh;
144
145         scsi_dh->detach(sdev);
146
147         spin_lock_irq(sdev->request_queue->queue_lock);
148         sdev->scsi_dh_data = NULL;
149         spin_unlock_irq(sdev->request_queue->queue_lock);
150
151         sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", scsi_dh->name);
152         module_put(scsi_dh->module);
153 }
154
155 /*
156  * Functions for sysfs attribute 'dh_state'
157  */
158 static ssize_t
159 store_dh_state(struct device *dev, struct device_attribute *attr,
160                const char *buf, size_t count)
161 {
162         struct scsi_device *sdev = to_scsi_device(dev);
163         struct scsi_device_handler *scsi_dh;
164         int err = -EINVAL;
165
166         if (sdev->sdev_state == SDEV_CANCEL ||
167             sdev->sdev_state == SDEV_DEL)
168                 return -ENODEV;
169
170         if (!sdev->scsi_dh_data) {
171                 /*
172                  * Attach to a device handler
173                  */
174                 scsi_dh = scsi_dh_lookup(buf);
175                 if (!scsi_dh)
176                         return err;
177                 err = scsi_dh_handler_attach(sdev, scsi_dh);
178         } else {
179                 scsi_dh = sdev->scsi_dh_data->scsi_dh;
180                 if (!strncmp(buf, "detach", 6)) {
181                         /*
182                          * Detach from a device handler
183                          */
184                         scsi_dh_handler_detach(sdev);
185                         err = 0;
186                 } else if (!strncmp(buf, "activate", 8)) {
187                         /*
188                          * Activate a device handler
189                          */
190                         if (scsi_dh->activate)
191                                 err = scsi_dh->activate(sdev, NULL, NULL);
192                         else
193                                 err = 0;
194                 }
195         }
196
197         return err<0?err:count;
198 }
199
200 static ssize_t
201 show_dh_state(struct device *dev, struct device_attribute *attr, char *buf)
202 {
203         struct scsi_device *sdev = to_scsi_device(dev);
204
205         if (!sdev->scsi_dh_data)
206                 return snprintf(buf, 20, "detached\n");
207
208         return snprintf(buf, 20, "%s\n", sdev->scsi_dh_data->scsi_dh->name);
209 }
210
211 static struct device_attribute scsi_dh_state_attr =
212         __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state,
213                store_dh_state);
214
215 /*
216  * scsi_dh_sysfs_attr_add - Callback for scsi_init_dh
217  */
218 static int scsi_dh_sysfs_attr_add(struct device *dev, void *data)
219 {
220         struct scsi_device *sdev;
221         int err;
222
223         if (!scsi_is_sdev_device(dev))
224                 return 0;
225
226         sdev = to_scsi_device(dev);
227
228         err = device_create_file(&sdev->sdev_gendev,
229                                  &scsi_dh_state_attr);
230
231         return 0;
232 }
233
234 /*
235  * scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh
236  */
237 static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data)
238 {
239         struct scsi_device *sdev;
240
241         if (!scsi_is_sdev_device(dev))
242                 return 0;
243
244         sdev = to_scsi_device(dev);
245
246         device_remove_file(&sdev->sdev_gendev,
247                            &scsi_dh_state_attr);
248
249         return 0;
250 }
251
252 /*
253  * scsi_dh_notifier - notifier chain callback
254  */
255 static int scsi_dh_notifier(struct notifier_block *nb,
256                             unsigned long action, void *data)
257 {
258         struct device *dev = data;
259         struct scsi_device *sdev;
260         int err = 0;
261         struct scsi_device_handler *devinfo = NULL;
262
263         if (!scsi_is_sdev_device(dev))
264                 return 0;
265
266         sdev = to_scsi_device(dev);
267
268         if (action == BUS_NOTIFY_ADD_DEVICE) {
269                 err = device_create_file(dev, &scsi_dh_state_attr);
270                 /* don't care about err */
271                 devinfo = device_handler_match(NULL, sdev);
272                 if (devinfo)
273                         err = scsi_dh_handler_attach(sdev, devinfo);
274         } else if (action == BUS_NOTIFY_DEL_DEVICE) {
275                 device_remove_file(dev, &scsi_dh_state_attr);
276                 if (sdev->scsi_dh_data)
277                         scsi_dh_handler_detach(sdev);
278         }
279         return err;
280 }
281
282 /*
283  * scsi_dh_notifier_add - Callback for scsi_register_device_handler
284  */
285 static int scsi_dh_notifier_add(struct device *dev, void *data)
286 {
287         struct scsi_device_handler *scsi_dh = data;
288         struct scsi_device *sdev;
289
290         if (!scsi_is_sdev_device(dev))
291                 return 0;
292
293         if (!get_device(dev))
294                 return 0;
295
296         sdev = to_scsi_device(dev);
297
298         if (device_handler_match(scsi_dh, sdev))
299                 scsi_dh_handler_attach(sdev, scsi_dh);
300
301         put_device(dev);
302
303         return 0;
304 }
305
306 /*
307  * scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler
308  */
309 static int scsi_dh_notifier_remove(struct device *dev, void *data)
310 {
311         struct scsi_device_handler *scsi_dh = data;
312         struct scsi_device *sdev;
313
314         if (!scsi_is_sdev_device(dev))
315                 return 0;
316
317         if (!get_device(dev))
318                 return 0;
319
320         sdev = to_scsi_device(dev);
321
322         if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh == scsi_dh)
323                 scsi_dh_handler_detach(sdev);
324
325         put_device(dev);
326
327         return 0;
328 }
329
330 /*
331  * scsi_register_device_handler - register a device handler personality
332  *      module.
333  * @scsi_dh - device handler to be registered.
334  *
335  * Returns 0 on success, -EBUSY if handler already registered.
336  */
337 int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
338 {
339         if (__scsi_dh_lookup(scsi_dh->name))
340                 return -EBUSY;
341
342         if (!scsi_dh->attach || !scsi_dh->detach)
343                 return -EINVAL;
344
345         spin_lock(&list_lock);
346         list_add(&scsi_dh->list, &scsi_dh_list);
347         spin_unlock(&list_lock);
348
349         bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
350         printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
351
352         return SCSI_DH_OK;
353 }
354 EXPORT_SYMBOL_GPL(scsi_register_device_handler);
355
356 /*
357  * scsi_unregister_device_handler - register a device handler personality
358  *      module.
359  * @scsi_dh - device handler to be unregistered.
360  *
361  * Returns 0 on success, -ENODEV if handler not registered.
362  */
363 int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
364 {
365
366         if (!__scsi_dh_lookup(scsi_dh->name))
367                 return -ENODEV;
368
369         bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
370                          scsi_dh_notifier_remove);
371
372         spin_lock(&list_lock);
373         list_del(&scsi_dh->list);
374         spin_unlock(&list_lock);
375         printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
376
377         return SCSI_DH_OK;
378 }
379 EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
380
381 /*
382  * scsi_dh_activate - activate the path associated with the scsi_device
383  *      corresponding to the given request queue.
384  *     Returns immediately without waiting for activation to be completed.
385  * @q    - Request queue that is associated with the scsi_device to be
386  *         activated.
387  * @fn   - Function to be called upon completion of the activation.
388  *         Function fn is called with data (below) and the error code.
389  *         Function fn may be called from the same calling context. So,
390  *         do not hold the lock in the caller which may be needed in fn.
391  * @data - data passed to the function fn upon completion.
392  *
393  */
394 int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
395 {
396         int err = 0;
397         unsigned long flags;
398         struct scsi_device *sdev;
399         struct scsi_device_handler *scsi_dh = NULL;
400         struct device *dev = NULL;
401
402         spin_lock_irqsave(q->queue_lock, flags);
403         sdev = q->queuedata;
404         if (!sdev) {
405                 spin_unlock_irqrestore(q->queue_lock, flags);
406                 err = SCSI_DH_NOSYS;
407                 if (fn)
408                         fn(data, err);
409                 return err;
410         }
411
412         if (sdev->scsi_dh_data)
413                 scsi_dh = sdev->scsi_dh_data->scsi_dh;
414         dev = get_device(&sdev->sdev_gendev);
415         if (!scsi_dh || !dev ||
416             sdev->sdev_state == SDEV_CANCEL ||
417             sdev->sdev_state == SDEV_DEL)
418                 err = SCSI_DH_NOSYS;
419         if (sdev->sdev_state == SDEV_OFFLINE)
420                 err = SCSI_DH_DEV_OFFLINED;
421         spin_unlock_irqrestore(q->queue_lock, flags);
422
423         if (err) {
424                 if (fn)
425                         fn(data, err);
426                 goto out;
427         }
428
429         if (scsi_dh->activate)
430                 err = scsi_dh->activate(sdev, fn, data);
431 out:
432         put_device(dev);
433         return err;
434 }
435 EXPORT_SYMBOL_GPL(scsi_dh_activate);
436
437 /*
438  * scsi_dh_set_params - set the parameters for the device as per the
439  *      string specified in params.
440  * @q - Request queue that is associated with the scsi_device for
441  *      which the parameters to be set.
442  * @params - parameters in the following format
443  *      "no_of_params\0param1\0param2\0param3\0...\0"
444  *      for example, string for 2 parameters with value 10 and 21
445  *      is specified as "2\010\021\0".
446  */
447 int scsi_dh_set_params(struct request_queue *q, const char *params)
448 {
449         int err = -SCSI_DH_NOSYS;
450         unsigned long flags;
451         struct scsi_device *sdev;
452         struct scsi_device_handler *scsi_dh = NULL;
453
454         spin_lock_irqsave(q->queue_lock, flags);
455         sdev = q->queuedata;
456         if (sdev && sdev->scsi_dh_data)
457                 scsi_dh = sdev->scsi_dh_data->scsi_dh;
458         if (scsi_dh && scsi_dh->set_params && get_device(&sdev->sdev_gendev))
459                 err = 0;
460         spin_unlock_irqrestore(q->queue_lock, flags);
461
462         if (err)
463                 return err;
464         err = scsi_dh->set_params(sdev, params);
465         put_device(&sdev->sdev_gendev);
466         return err;
467 }
468 EXPORT_SYMBOL_GPL(scsi_dh_set_params);
469
470 /*
471  * scsi_dh_attach - Attach device handler
472  * @q - Request queue that is associated with the scsi_device
473  *      the handler should be attached to
474  * @name - name of the handler to attach
475  */
476 int scsi_dh_attach(struct request_queue *q, const char *name)
477 {
478         unsigned long flags;
479         struct scsi_device *sdev;
480         struct scsi_device_handler *scsi_dh;
481         int err = 0;
482
483         scsi_dh = scsi_dh_lookup(name);
484         if (!scsi_dh)
485                 return -EINVAL;
486
487         spin_lock_irqsave(q->queue_lock, flags);
488         sdev = q->queuedata;
489         if (!sdev || !get_device(&sdev->sdev_gendev))
490                 err = -ENODEV;
491         spin_unlock_irqrestore(q->queue_lock, flags);
492
493         if (err)
494                 return err;
495
496         if (sdev->scsi_dh_data) {
497                 if (sdev->scsi_dh_data->scsi_dh != scsi_dh)
498                         err = -EBUSY;
499                 goto out_put_device;
500         }
501
502         err = scsi_dh_handler_attach(sdev, scsi_dh);
503
504 out_put_device:
505         put_device(&sdev->sdev_gendev);
506         return err;
507 }
508 EXPORT_SYMBOL_GPL(scsi_dh_attach);
509
510 /*
511  * scsi_dh_attached_handler_name - Get attached device handler's name
512  * @q - Request queue that is associated with the scsi_device
513  *      that may have a device handler attached
514  * @gfp - the GFP mask used in the kmalloc() call when allocating memory
515  *
516  * Returns name of attached handler, NULL if no handler is attached.
517  * Caller must take care to free the returned string.
518  */
519 const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp)
520 {
521         unsigned long flags;
522         struct scsi_device *sdev;
523         const char *handler_name = NULL;
524
525         spin_lock_irqsave(q->queue_lock, flags);
526         sdev = q->queuedata;
527         if (!sdev || !get_device(&sdev->sdev_gendev))
528                 sdev = NULL;
529         spin_unlock_irqrestore(q->queue_lock, flags);
530
531         if (!sdev)
532                 return NULL;
533
534         if (sdev->scsi_dh_data)
535                 handler_name = kstrdup(sdev->scsi_dh_data->scsi_dh->name, gfp);
536
537         put_device(&sdev->sdev_gendev);
538         return handler_name;
539 }
540 EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name);
541
542 static struct notifier_block scsi_dh_nb = {
543         .notifier_call = scsi_dh_notifier
544 };
545
546 static int __init scsi_dh_init(void)
547 {
548         int r;
549
550         r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);
551
552         if (!r)
553                 bus_for_each_dev(&scsi_bus_type, NULL, NULL,
554                                  scsi_dh_sysfs_attr_add);
555
556         return r;
557 }
558
559 static void __exit scsi_dh_exit(void)
560 {
561         bus_for_each_dev(&scsi_bus_type, NULL, NULL,
562                          scsi_dh_sysfs_attr_remove);
563         bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
564 }
565
566 module_init(scsi_dh_init);
567 module_exit(scsi_dh_exit);
568
569 MODULE_DESCRIPTION("SCSI device handler");
570 MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>");
571 MODULE_LICENSE("GPL");