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