Merge branch 'master' into 83xx
[linux-2.6] / drivers / s390 / block / dasd_devmap.c
1 /*
2  * File...........: linux/drivers/s390/block/dasd_devmap.c
3  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
4  *                  Horst Hummel <Horst.Hummel@de.ibm.com>
5  *                  Carsten Otte <Cotte@de.ibm.com>
6  *                  Martin Schwidefsky <schwidefsky@de.ibm.com>
7  * Bugreports.to..: <Linux390@de.ibm.com>
8  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
9  *
10  * Device mapping and dasd= parameter parsing functions. All devmap
11  * functions may not be called from interrupt context. In particular
12  * dasd_get_device is a no-no from interrupt context.
13  *
14  */
15
16 #include <linux/ctype.h>
17 #include <linux/init.h>
18 #include <linux/module.h>
19
20 #include <asm/debug.h>
21 #include <asm/uaccess.h>
22
23 /* This is ugly... */
24 #define PRINTK_HEADER "dasd_devmap:"
25
26 #include "dasd_int.h"
27
28 struct kmem_cache *dasd_page_cache;
29 EXPORT_SYMBOL_GPL(dasd_page_cache);
30
31 /*
32  * dasd_devmap_t is used to store the features and the relation
33  * between device number and device index. To find a dasd_devmap_t
34  * that corresponds to a device number of a device index each
35  * dasd_devmap_t is added to two linked lists, one to search by
36  * the device number and one to search by the device index. As
37  * soon as big minor numbers are available the device index list
38  * can be removed since the device number will then be identical
39  * to the device index.
40  */
41 struct dasd_devmap {
42         struct list_head list;
43         char bus_id[BUS_ID_SIZE];
44         unsigned int devindex;
45         unsigned short features;
46         struct dasd_device *device;
47         struct dasd_uid uid;
48 };
49
50 /*
51  * dasd_server_ssid_map contains a globally unique storage server subsystem ID.
52  * dasd_server_ssid_list contains the list of all subsystem IDs accessed by
53  * the DASD device driver.
54  */
55 struct dasd_server_ssid_map {
56         struct list_head list;
57         struct system_id {
58                 char vendor[4];
59                 char serial[15];
60                 __u16 ssid;
61         } sid;
62 };
63
64 static struct list_head dasd_server_ssid_list;
65
66 /*
67  * Parameter parsing functions for dasd= parameter. The syntax is:
68  *   <devno>            : (0x)?[0-9a-fA-F]+
69  *   <busid>            : [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+
70  *   <feature>          : ro
71  *   <feature_list>     : \(<feature>(:<feature>)*\)
72  *   <devno-range>      : <devno>(-<devno>)?<feature_list>?
73  *   <busid-range>      : <busid>(-<busid>)?<feature_list>?
74  *   <devices>          : <devno-range>|<busid-range>
75  *   <dasd_module>      : dasd_diag_mod|dasd_eckd_mod|dasd_fba_mod
76  *
77  *   <dasd>             : autodetect|probeonly|<devices>(,<devices>)*
78  */
79
80 int dasd_probeonly =  0;        /* is true, when probeonly mode is active */
81 int dasd_autodetect = 0;        /* is true, when autodetection is active */
82 int dasd_nopav = 0;             /* is true, when PAV is disabled */
83 EXPORT_SYMBOL_GPL(dasd_nopav);
84
85 /*
86  * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
87  * it is named 'dasd' to directly be filled by insmod with the comma separated
88  * strings when running as a module.
89  */
90 static char *dasd[256];
91 module_param_array(dasd, charp, NULL, 0);
92
93 /*
94  * Single spinlock to protect devmap and servermap structures and lists.
95  */
96 static DEFINE_SPINLOCK(dasd_devmap_lock);
97
98 /*
99  * Hash lists for devmap structures.
100  */
101 static struct list_head dasd_hashlists[256];
102 int dasd_max_devindex;
103
104 static struct dasd_devmap *dasd_add_busid(char *, int);
105
106 static inline int
107 dasd_hash_busid(char *bus_id)
108 {
109         int hash, i;
110
111         hash = 0;
112         for (i = 0; (i < BUS_ID_SIZE) && *bus_id; i++, bus_id++)
113                 hash += *bus_id;
114         return hash & 0xff;
115 }
116
117 #ifndef MODULE
118 /*
119  * The parameter parsing functions for builtin-drivers are called
120  * before kmalloc works. Store the pointers to the parameters strings
121  * into dasd[] for later processing.
122  */
123 static int __init
124 dasd_call_setup(char *str)
125 {
126         static int count = 0;
127
128         if (count < 256)
129                 dasd[count++] = str;
130         return 1;
131 }
132
133 __setup ("dasd=", dasd_call_setup);
134 #endif  /* #ifndef MODULE */
135
136 /*
137  * Read a device busid/devno from a string.
138  */
139 static int
140 dasd_busid(char **str, int *id0, int *id1, int *devno)
141 {
142         int val, old_style;
143
144         /* check for leading '0x' */
145         old_style = 0;
146         if ((*str)[0] == '0' && (*str)[1] == 'x') {
147                 *str += 2;
148                 old_style = 1;
149         }
150         if (!isxdigit((*str)[0]))       /* We require at least one hex digit */
151                 return -EINVAL;
152         val = simple_strtoul(*str, str, 16);
153         if (old_style || (*str)[0] != '.') {
154                 *id0 = *id1 = 0;
155                 if (val < 0 || val > 0xffff)
156                         return -EINVAL;
157                 *devno = val;
158                 return 0;
159         }
160         /* New style x.y.z busid */
161         if (val < 0 || val > 0xff)
162                 return -EINVAL;
163         *id0 = val;
164         (*str)++;
165         if (!isxdigit((*str)[0]))       /* We require at least one hex digit */
166                 return -EINVAL;
167         val = simple_strtoul(*str, str, 16);
168         if (val < 0 || val > 0xff || (*str)++[0] != '.')
169                 return -EINVAL;
170         *id1 = val;
171         if (!isxdigit((*str)[0]))       /* We require at least one hex digit */
172                 return -EINVAL;
173         val = simple_strtoul(*str, str, 16);
174         if (val < 0 || val > 0xffff)
175                 return -EINVAL;
176         *devno = val;
177         return 0;
178 }
179
180 /*
181  * Read colon separated list of dasd features. Currently there is
182  * only one: "ro" for read-only devices. The default feature set
183  * is empty (value 0).
184  */
185 static int
186 dasd_feature_list(char *str, char **endp)
187 {
188         int features, len, rc;
189
190         rc = 0;
191         if (*str != '(') {
192                 *endp = str;
193                 return DASD_FEATURE_DEFAULT;
194         }
195         str++;
196         features = 0;
197
198         while (1) {
199                 for (len = 0;
200                      str[len] && str[len] != ':' && str[len] != ')'; len++);
201                 if (len == 2 && !strncmp(str, "ro", 2))
202                         features |= DASD_FEATURE_READONLY;
203                 else if (len == 4 && !strncmp(str, "diag", 4))
204                         features |= DASD_FEATURE_USEDIAG;
205                 else if (len == 6 && !strncmp(str, "erplog", 6))
206                         features |= DASD_FEATURE_ERPLOG;
207                 else {
208                         MESSAGE(KERN_WARNING,
209                                 "unsupported feature: %*s, "
210                                 "ignoring setting", len, str);
211                         rc = -EINVAL;
212                 }
213                 str += len;
214                 if (*str != ':')
215                         break;
216                 str++;
217         }
218         if (*str != ')') {
219                 MESSAGE(KERN_WARNING, "%s",
220                         "missing ')' in dasd parameter string\n");
221                 rc = -EINVAL;
222         } else
223                 str++;
224         *endp = str;
225         if (rc != 0)
226                 return rc;
227         return features;
228 }
229
230 /*
231  * Try to match the first element on the comma separated parse string
232  * with one of the known keywords. If a keyword is found, take the approprate
233  * action and return a pointer to the residual string. If the first element
234  * could not be matched to any keyword then return an error code.
235  */
236 static char *
237 dasd_parse_keyword( char *parsestring ) {
238
239         char *nextcomma, *residual_str;
240         int length;
241
242         nextcomma = strchr(parsestring,',');
243         if (nextcomma) {
244                 length = nextcomma - parsestring;
245                 residual_str = nextcomma + 1;
246         } else {
247                 length = strlen(parsestring);
248                 residual_str = parsestring + length;
249         }
250         if (strncmp("autodetect", parsestring, length) == 0) {
251                 dasd_autodetect = 1;
252                 MESSAGE (KERN_INFO, "%s",
253                          "turning to autodetection mode");
254                 return residual_str;
255         }
256         if (strncmp("probeonly", parsestring, length) == 0) {
257                 dasd_probeonly = 1;
258                 MESSAGE(KERN_INFO, "%s",
259                         "turning to probeonly mode");
260                 return residual_str;
261         }
262         if (strncmp("nopav", parsestring, length) == 0) {
263                 if (MACHINE_IS_VM)
264                         MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM");
265                 else {
266                         dasd_nopav = 1;
267                         MESSAGE(KERN_INFO, "%s", "disable PAV mode");
268                 }
269                 return residual_str;
270         }
271         if (strncmp("fixedbuffers", parsestring, length) == 0) {
272                 if (dasd_page_cache)
273                         return residual_str;
274                 dasd_page_cache =
275                         kmem_cache_create("dasd_page_cache", PAGE_SIZE,
276                                           PAGE_SIZE, SLAB_CACHE_DMA,
277                                           NULL, NULL );
278                 if (!dasd_page_cache)
279                         MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
280                                 "fixed buffer mode disabled.");
281                 else
282                         MESSAGE (KERN_INFO, "%s",
283                                  "turning on fixed buffer mode");
284                 return residual_str;
285         }
286         return ERR_PTR(-EINVAL);
287 }
288
289 /*
290  * Try to interprete the first element on the comma separated parse string
291  * as a device number or a range of devices. If the interpretation is
292  * successfull, create the matching dasd_devmap entries and return a pointer
293  * to the residual string.
294  * If interpretation fails or in case of an error, return an error code.
295  */
296 static char *
297 dasd_parse_range( char *parsestring ) {
298
299         struct dasd_devmap *devmap;
300         int from, from_id0, from_id1;
301         int to, to_id0, to_id1;
302         int features, rc;
303         char bus_id[BUS_ID_SIZE+1], *str;
304
305         str = parsestring;
306         rc = dasd_busid(&str, &from_id0, &from_id1, &from);
307         if (rc == 0) {
308                 to = from;
309                 to_id0 = from_id0;
310                 to_id1 = from_id1;
311                 if (*str == '-') {
312                         str++;
313                         rc = dasd_busid(&str, &to_id0, &to_id1, &to);
314                 }
315         }
316         if (rc == 0 &&
317             (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
318                 rc = -EINVAL;
319         if (rc) {
320                 MESSAGE(KERN_ERR, "Invalid device range %s", parsestring);
321                 return ERR_PTR(rc);
322         }
323         features = dasd_feature_list(str, &str);
324         if (features < 0)
325                 return ERR_PTR(-EINVAL);
326         /* each device in dasd= parameter should be set initially online */
327         features |= DASD_FEATURE_INITIAL_ONLINE;
328         while (from <= to) {
329                 sprintf(bus_id, "%01x.%01x.%04x",
330                         from_id0, from_id1, from++);
331                 devmap = dasd_add_busid(bus_id, features);
332                 if (IS_ERR(devmap))
333                         return (char *)devmap;
334         }
335         if (*str == ',')
336                 return str + 1;
337         if (*str == '\0')
338                 return str;
339         MESSAGE(KERN_WARNING,
340                 "junk at end of dasd parameter string: %s\n", str);
341         return ERR_PTR(-EINVAL);
342 }
343
344 static char *
345 dasd_parse_next_element( char *parsestring ) {
346         char * residual_str;
347         residual_str = dasd_parse_keyword(parsestring);
348         if (!IS_ERR(residual_str))
349                 return residual_str;
350         residual_str = dasd_parse_range(parsestring);
351         return residual_str;
352 }
353
354 /*
355  * Parse parameters stored in dasd[]
356  * The 'dasd=...' parameter allows to specify a comma separated list of
357  * keywords and device ranges. When the dasd driver is build into the kernel,
358  * the complete list will be stored as one element of the dasd[] array.
359  * When the dasd driver is build as a module, then the list is broken into
360  * it's elements and each dasd[] entry contains one element.
361  */
362 int
363 dasd_parse(void)
364 {
365         int rc, i;
366         char *parsestring;
367
368         rc = 0;
369         for (i = 0; i < 256; i++) {
370                 if (dasd[i] == NULL)
371                         break;
372                 parsestring = dasd[i];
373                 /* loop over the comma separated list in the parsestring */
374                 while (*parsestring) {
375                         parsestring = dasd_parse_next_element(parsestring);
376                         if(IS_ERR(parsestring)) {
377                                 rc = PTR_ERR(parsestring);
378                                 break;
379                         }
380                 }
381                 if (rc) {
382                         DBF_EVENT(DBF_ALERT, "%s", "invalid range found");
383                         break;
384                 }
385         }
386         return rc;
387 }
388
389 /*
390  * Add a devmap for the device specified by busid. It is possible that
391  * the devmap already exists (dasd= parameter). The order of the devices
392  * added through this function will define the kdevs for the individual
393  * devices.
394  */
395 static struct dasd_devmap *
396 dasd_add_busid(char *bus_id, int features)
397 {
398         struct dasd_devmap *devmap, *new, *tmp;
399         int hash;
400
401         new = (struct dasd_devmap *)
402                 kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
403         if (!new)
404                 return ERR_PTR(-ENOMEM);
405         spin_lock(&dasd_devmap_lock);
406         devmap = NULL;
407         hash = dasd_hash_busid(bus_id);
408         list_for_each_entry(tmp, &dasd_hashlists[hash], list)
409                 if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
410                         devmap = tmp;
411                         break;
412                 }
413         if (!devmap) {
414                 /* This bus_id is new. */
415                 new->devindex = dasd_max_devindex++;
416                 strncpy(new->bus_id, bus_id, BUS_ID_SIZE);
417                 new->features = features;
418                 new->device = NULL;
419                 list_add(&new->list, &dasd_hashlists[hash]);
420                 devmap = new;
421                 new = NULL;
422         }
423         spin_unlock(&dasd_devmap_lock);
424         kfree(new);
425         return devmap;
426 }
427
428 /*
429  * Find devmap for device with given bus_id.
430  */
431 static struct dasd_devmap *
432 dasd_find_busid(char *bus_id)
433 {
434         struct dasd_devmap *devmap, *tmp;
435         int hash;
436
437         spin_lock(&dasd_devmap_lock);
438         devmap = ERR_PTR(-ENODEV);
439         hash = dasd_hash_busid(bus_id);
440         list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
441                 if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
442                         devmap = tmp;
443                         break;
444                 }
445         }
446         spin_unlock(&dasd_devmap_lock);
447         return devmap;
448 }
449
450 /*
451  * Check if busid has been added to the list of dasd ranges.
452  */
453 int
454 dasd_busid_known(char *bus_id)
455 {
456         return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
457 }
458
459 /*
460  * Forget all about the device numbers added so far.
461  * This may only be called at module unload or system shutdown.
462  */
463 static void
464 dasd_forget_ranges(void)
465 {
466         struct dasd_devmap *devmap, *n;
467         int i;
468
469         spin_lock(&dasd_devmap_lock);
470         for (i = 0; i < 256; i++) {
471                 list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
472                         BUG_ON(devmap->device != NULL);
473                         list_del(&devmap->list);
474                         kfree(devmap);
475                 }
476         }
477         spin_unlock(&dasd_devmap_lock);
478 }
479
480 /*
481  * Find the device struct by its device index.
482  */
483 struct dasd_device *
484 dasd_device_from_devindex(int devindex)
485 {
486         struct dasd_devmap *devmap, *tmp;
487         struct dasd_device *device;
488         int i;
489
490         spin_lock(&dasd_devmap_lock);
491         devmap = NULL;
492         for (i = 0; (i < 256) && !devmap; i++)
493                 list_for_each_entry(tmp, &dasd_hashlists[i], list)
494                         if (tmp->devindex == devindex) {
495                                 /* Found the devmap for the device. */
496                                 devmap = tmp;
497                                 break;
498                         }
499         if (devmap && devmap->device) {
500                 device = devmap->device;
501                 dasd_get_device(device);
502         } else
503                 device = ERR_PTR(-ENODEV);
504         spin_unlock(&dasd_devmap_lock);
505         return device;
506 }
507
508 /*
509  * Return devmap for cdev. If no devmap exists yet, create one and
510  * connect it to the cdev.
511  */
512 static struct dasd_devmap *
513 dasd_devmap_from_cdev(struct ccw_device *cdev)
514 {
515         struct dasd_devmap *devmap;
516
517         devmap = dasd_find_busid(cdev->dev.bus_id);
518         if (IS_ERR(devmap))
519                 devmap = dasd_add_busid(cdev->dev.bus_id,
520                                         DASD_FEATURE_DEFAULT);
521         return devmap;
522 }
523
524 /*
525  * Create a dasd device structure for cdev.
526  */
527 struct dasd_device *
528 dasd_create_device(struct ccw_device *cdev)
529 {
530         struct dasd_devmap *devmap;
531         struct dasd_device *device;
532         unsigned long flags;
533         int rc;
534
535         devmap = dasd_devmap_from_cdev(cdev);
536         if (IS_ERR(devmap))
537                 return (void *) devmap;
538
539         device = dasd_alloc_device();
540         if (IS_ERR(device))
541                 return device;
542         atomic_set(&device->ref_count, 3);
543
544         spin_lock(&dasd_devmap_lock);
545         if (!devmap->device) {
546                 devmap->device = device;
547                 device->devindex = devmap->devindex;
548                 device->features = devmap->features;
549                 get_device(&cdev->dev);
550                 device->cdev = cdev;
551                 rc = 0;
552         } else
553                 /* Someone else was faster. */
554                 rc = -EBUSY;
555         spin_unlock(&dasd_devmap_lock);
556
557         if (rc) {
558                 dasd_free_device(device);
559                 return ERR_PTR(rc);
560         }
561
562         spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
563         cdev->dev.driver_data = device;
564         spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
565
566         return device;
567 }
568
569 /*
570  * Wait queue for dasd_delete_device waits.
571  */
572 static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
573
574 /*
575  * Remove a dasd device structure. The passed referenced
576  * is destroyed.
577  */
578 void
579 dasd_delete_device(struct dasd_device *device)
580 {
581         struct ccw_device *cdev;
582         struct dasd_devmap *devmap;
583         unsigned long flags;
584
585         /* First remove device pointer from devmap. */
586         devmap = dasd_find_busid(device->cdev->dev.bus_id);
587         BUG_ON(IS_ERR(devmap));
588         spin_lock(&dasd_devmap_lock);
589         if (devmap->device != device) {
590                 spin_unlock(&dasd_devmap_lock);
591                 dasd_put_device(device);
592                 return;
593         }
594         devmap->device = NULL;
595         spin_unlock(&dasd_devmap_lock);
596
597         /* Disconnect dasd_device structure from ccw_device structure. */
598         spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
599         device->cdev->dev.driver_data = NULL;
600         spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
601
602         /*
603          * Drop ref_count by 3, one for the devmap reference, one for
604          * the cdev reference and one for the passed reference.
605          */
606         atomic_sub(3, &device->ref_count);
607
608         /* Wait for reference counter to drop to zero. */
609         wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
610
611         /* Disconnect dasd_device structure from ccw_device structure. */
612         cdev = device->cdev;
613         device->cdev = NULL;
614
615         /* Put ccw_device structure. */
616         put_device(&cdev->dev);
617
618         /* Now the device structure can be freed. */
619         dasd_free_device(device);
620 }
621
622 /*
623  * Reference counter dropped to zero. Wake up waiter
624  * in dasd_delete_device.
625  */
626 void
627 dasd_put_device_wake(struct dasd_device *device)
628 {
629         wake_up(&dasd_delete_wq);
630 }
631
632 /*
633  * Return dasd_device structure associated with cdev.
634  * This function needs to be called with the ccw device
635  * lock held. It can be used from interrupt context.
636  */
637 struct dasd_device *
638 dasd_device_from_cdev_locked(struct ccw_device *cdev)
639 {
640         struct dasd_device *device = cdev->dev.driver_data;
641
642         if (!device)
643                 return ERR_PTR(-ENODEV);
644         dasd_get_device(device);
645         return device;
646 }
647
648 /*
649  * Return dasd_device structure associated with cdev.
650  */
651 struct dasd_device *
652 dasd_device_from_cdev(struct ccw_device *cdev)
653 {
654         struct dasd_device *device;
655         unsigned long flags;
656
657         spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
658         device = dasd_device_from_cdev_locked(cdev);
659         spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
660         return device;
661 }
662
663 /*
664  * SECTION: files in sysfs
665  */
666
667 /*
668  * readonly controls the readonly status of a dasd
669  */
670 static ssize_t
671 dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
672 {
673         struct dasd_devmap *devmap;
674         int ro_flag;
675
676         devmap = dasd_find_busid(dev->bus_id);
677         if (!IS_ERR(devmap))
678                 ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
679         else
680                 ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
681         return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
682 }
683
684 static ssize_t
685 dasd_ro_store(struct device *dev, struct device_attribute *attr,
686               const char *buf, size_t count)
687 {
688         struct dasd_devmap *devmap;
689         int val;
690         char *endp;
691
692         devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
693         if (IS_ERR(devmap))
694                 return PTR_ERR(devmap);
695
696         val = simple_strtoul(buf, &endp, 0);
697         if (((endp + 1) < (buf + count)) || (val > 1))
698                 return -EINVAL;
699
700         spin_lock(&dasd_devmap_lock);
701         if (val)
702                 devmap->features |= DASD_FEATURE_READONLY;
703         else
704                 devmap->features &= ~DASD_FEATURE_READONLY;
705         if (devmap->device)
706                 devmap->device->features = devmap->features;
707         if (devmap->device && devmap->device->gdp)
708                 set_disk_ro(devmap->device->gdp, val);
709         spin_unlock(&dasd_devmap_lock);
710         return count;
711 }
712
713 static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
714 /*
715  * erplog controls the logging of ERP related data
716  * (e.g. failing channel programs).
717  */
718 static ssize_t
719 dasd_erplog_show(struct device *dev, struct device_attribute *attr, char *buf)
720 {
721         struct dasd_devmap *devmap;
722         int erplog;
723
724         devmap = dasd_find_busid(dev->bus_id);
725         if (!IS_ERR(devmap))
726                 erplog = (devmap->features & DASD_FEATURE_ERPLOG) != 0;
727         else
728                 erplog = (DASD_FEATURE_DEFAULT & DASD_FEATURE_ERPLOG) != 0;
729         return snprintf(buf, PAGE_SIZE, erplog ? "1\n" : "0\n");
730 }
731
732 static ssize_t
733 dasd_erplog_store(struct device *dev, struct device_attribute *attr,
734               const char *buf, size_t count)
735 {
736         struct dasd_devmap *devmap;
737         int val;
738         char *endp;
739
740         devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
741         if (IS_ERR(devmap))
742                 return PTR_ERR(devmap);
743
744         val = simple_strtoul(buf, &endp, 0);
745         if (((endp + 1) < (buf + count)) || (val > 1))
746                 return -EINVAL;
747
748         spin_lock(&dasd_devmap_lock);
749         if (val)
750                 devmap->features |= DASD_FEATURE_ERPLOG;
751         else
752                 devmap->features &= ~DASD_FEATURE_ERPLOG;
753         if (devmap->device)
754                 devmap->device->features = devmap->features;
755         spin_unlock(&dasd_devmap_lock);
756         return count;
757 }
758
759 static DEVICE_ATTR(erplog, 0644, dasd_erplog_show, dasd_erplog_store);
760
761 /*
762  * use_diag controls whether the driver should use diag rather than ssch
763  * to talk to the device
764  */
765 static ssize_t
766 dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
767 {
768         struct dasd_devmap *devmap;
769         int use_diag;
770
771         devmap = dasd_find_busid(dev->bus_id);
772         if (!IS_ERR(devmap))
773                 use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
774         else
775                 use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
776         return sprintf(buf, use_diag ? "1\n" : "0\n");
777 }
778
779 static ssize_t
780 dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
781                     const char *buf, size_t count)
782 {
783         struct dasd_devmap *devmap;
784         ssize_t rc;
785         int val;
786         char *endp;
787
788         devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
789         if (IS_ERR(devmap))
790                 return PTR_ERR(devmap);
791
792         val = simple_strtoul(buf, &endp, 0);
793         if (((endp + 1) < (buf + count)) || (val > 1))
794                 return -EINVAL;
795
796         spin_lock(&dasd_devmap_lock);
797         /* Changing diag discipline flag is only allowed in offline state. */
798         rc = count;
799         if (!devmap->device) {
800                 if (val)
801                         devmap->features |= DASD_FEATURE_USEDIAG;
802                 else
803                         devmap->features &= ~DASD_FEATURE_USEDIAG;
804         } else
805                 rc = -EPERM;
806         spin_unlock(&dasd_devmap_lock);
807         return rc;
808 }
809
810 static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
811
812 static ssize_t
813 dasd_discipline_show(struct device *dev, struct device_attribute *attr,
814                      char *buf)
815 {
816         struct dasd_device *device;
817         ssize_t len;
818
819         device = dasd_device_from_cdev(to_ccwdev(dev));
820         if (!IS_ERR(device) && device->discipline) {
821                 len = snprintf(buf, PAGE_SIZE, "%s\n",
822                                device->discipline->name);
823                 dasd_put_device(device);
824         } else
825                 len = snprintf(buf, PAGE_SIZE, "none\n");
826         return len;
827 }
828
829 static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
830
831 static ssize_t
832 dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
833 {
834         struct dasd_devmap *devmap;
835         int alias;
836
837         devmap = dasd_find_busid(dev->bus_id);
838         spin_lock(&dasd_devmap_lock);
839         if (!IS_ERR(devmap))
840                 alias = devmap->uid.alias;
841         else
842                 alias = 0;
843         spin_unlock(&dasd_devmap_lock);
844
845         return sprintf(buf, alias ? "1\n" : "0\n");
846 }
847
848 static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
849
850 static ssize_t
851 dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
852 {
853         struct dasd_devmap *devmap;
854         char *vendor;
855
856         devmap = dasd_find_busid(dev->bus_id);
857         spin_lock(&dasd_devmap_lock);
858         if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
859                 vendor = devmap->uid.vendor;
860         else
861                 vendor = "";
862         spin_unlock(&dasd_devmap_lock);
863
864         return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
865 }
866
867 static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
868
869 #define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial    */ 14 + 1 +\
870                      /* SSID   */ 4 + 1 + /* unit addr */ 2 + 1)
871
872 static ssize_t
873 dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
874 {
875         struct dasd_devmap *devmap;
876         char uid[UID_STRLEN];
877
878         devmap = dasd_find_busid(dev->bus_id);
879         spin_lock(&dasd_devmap_lock);
880         if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
881                 snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
882                          devmap->uid.vendor, devmap->uid.serial,
883                          devmap->uid.ssid, devmap->uid.unit_addr);
884         else
885                 uid[0] = 0;
886         spin_unlock(&dasd_devmap_lock);
887
888         return snprintf(buf, PAGE_SIZE, "%s\n", uid);
889 }
890
891 static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
892
893 /*
894  * extended error-reporting
895  */
896 static ssize_t
897 dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
898 {
899         struct dasd_devmap *devmap;
900         int eer_flag;
901
902         devmap = dasd_find_busid(dev->bus_id);
903         if (!IS_ERR(devmap) && devmap->device)
904                 eer_flag = dasd_eer_enabled(devmap->device);
905         else
906                 eer_flag = 0;
907         return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
908 }
909
910 static ssize_t
911 dasd_eer_store(struct device *dev, struct device_attribute *attr,
912                const char *buf, size_t count)
913 {
914         struct dasd_devmap *devmap;
915         int val, rc;
916         char *endp;
917
918         devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
919         if (IS_ERR(devmap))
920                 return PTR_ERR(devmap);
921         if (!devmap->device)
922                 return -ENODEV;
923
924         val = simple_strtoul(buf, &endp, 0);
925         if (((endp + 1) < (buf + count)) || (val > 1))
926                 return -EINVAL;
927
928         if (val) {
929                 rc = dasd_eer_enable(devmap->device);
930                 if (rc)
931                         return rc;
932         } else
933                 dasd_eer_disable(devmap->device);
934         return count;
935 }
936
937 static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
938
939 static struct attribute * dasd_attrs[] = {
940         &dev_attr_readonly.attr,
941         &dev_attr_discipline.attr,
942         &dev_attr_alias.attr,
943         &dev_attr_vendor.attr,
944         &dev_attr_uid.attr,
945         &dev_attr_use_diag.attr,
946         &dev_attr_eer_enabled.attr,
947         &dev_attr_erplog.attr,
948         NULL,
949 };
950
951 static struct attribute_group dasd_attr_group = {
952         .attrs = dasd_attrs,
953 };
954
955 /*
956  * Return copy of the device unique identifier.
957  */
958 int
959 dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
960 {
961         struct dasd_devmap *devmap;
962
963         devmap = dasd_find_busid(cdev->dev.bus_id);
964         if (IS_ERR(devmap))
965                 return PTR_ERR(devmap);
966         spin_lock(&dasd_devmap_lock);
967         *uid = devmap->uid;
968         spin_unlock(&dasd_devmap_lock);
969         return 0;
970 }
971
972 /*
973  * Register the given device unique identifier into devmap struct.
974  * In addition check if the related storage server subsystem ID is already
975  * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
976  * create new entry.
977  * Return 0 if server was already in serverlist,
978  *        1 if the server was added successful
979  *       <0 in case of error.
980  */
981 int
982 dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
983 {
984         struct dasd_devmap *devmap;
985         struct dasd_server_ssid_map *srv, *tmp;
986
987         devmap = dasd_find_busid(cdev->dev.bus_id);
988         if (IS_ERR(devmap))
989                 return PTR_ERR(devmap);
990
991         /* generate entry for server_ssid_map */
992         srv = (struct dasd_server_ssid_map *)
993                 kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL);
994         if (!srv)
995                 return -ENOMEM;
996         strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1);
997         strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1);
998         srv->sid.ssid = uid->ssid;
999
1000         /* server is already contained ? */
1001         spin_lock(&dasd_devmap_lock);
1002         devmap->uid = *uid;
1003         list_for_each_entry(tmp, &dasd_server_ssid_list, list) {
1004                 if (!memcmp(&srv->sid, &tmp->sid,
1005                             sizeof(struct system_id))) {
1006                         kfree(srv);
1007                         srv = NULL;
1008                         break;
1009                 }
1010         }
1011
1012         /* add servermap to serverlist */
1013         if (srv)
1014                 list_add(&srv->list, &dasd_server_ssid_list);
1015         spin_unlock(&dasd_devmap_lock);
1016
1017         return (srv ? 1 : 0);
1018 }
1019 EXPORT_SYMBOL_GPL(dasd_set_uid);
1020
1021 /*
1022  * Return value of the specified feature.
1023  */
1024 int
1025 dasd_get_feature(struct ccw_device *cdev, int feature)
1026 {
1027         struct dasd_devmap *devmap;
1028
1029         devmap = dasd_find_busid(cdev->dev.bus_id);
1030         if (IS_ERR(devmap))
1031                 return PTR_ERR(devmap);
1032
1033         return ((devmap->features & feature) != 0);
1034 }
1035
1036 /*
1037  * Set / reset given feature.
1038  * Flag indicates wether to set (!=0) or the reset (=0) the feature.
1039  */
1040 int
1041 dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
1042 {
1043         struct dasd_devmap *devmap;
1044
1045         devmap = dasd_find_busid(cdev->dev.bus_id);
1046         if (IS_ERR(devmap))
1047                 return PTR_ERR(devmap);
1048
1049         spin_lock(&dasd_devmap_lock);
1050         if (flag)
1051                 devmap->features |= feature;
1052         else
1053                 devmap->features &= ~feature;
1054         if (devmap->device)
1055                 devmap->device->features = devmap->features;
1056         spin_unlock(&dasd_devmap_lock);
1057         return 0;
1058 }
1059
1060
1061 int
1062 dasd_add_sysfs_files(struct ccw_device *cdev)
1063 {
1064         return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
1065 }
1066
1067 void
1068 dasd_remove_sysfs_files(struct ccw_device *cdev)
1069 {
1070         sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
1071 }
1072
1073
1074 int
1075 dasd_devmap_init(void)
1076 {
1077         int i;
1078
1079         /* Initialize devmap structures. */
1080         dasd_max_devindex = 0;
1081         for (i = 0; i < 256; i++)
1082                 INIT_LIST_HEAD(&dasd_hashlists[i]);
1083
1084         /* Initialize servermap structure. */
1085         INIT_LIST_HEAD(&dasd_server_ssid_list);
1086         return 0;
1087 }
1088
1089 void
1090 dasd_devmap_exit(void)
1091 {
1092         dasd_forget_ranges();
1093 }