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