Merge branch 'intx' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6
[pandora-kernel.git] / 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 inline 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 inline 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 {
206                         MESSAGE(KERN_WARNING,
207                                 "unsupported feature: %*s, "
208                                 "ignoring setting", len, str);
209                         rc = -EINVAL;
210                 }
211                 str += len;
212                 if (*str != ':')
213                         break;
214                 str++;
215         }
216         if (*str != ')') {
217                 MESSAGE(KERN_WARNING, "%s",
218                         "missing ')' in dasd parameter string\n");
219                 rc = -EINVAL;
220         } else
221                 str++;
222         *endp = str;
223         if (rc != 0)
224                 return rc;
225         return features;
226 }
227
228 /*
229  * Try to match the first element on the comma separated parse string
230  * with one of the known keywords. If a keyword is found, take the approprate
231  * action and return a pointer to the residual string. If the first element
232  * could not be matched to any keyword then return an error code.
233  */
234 static char *
235 dasd_parse_keyword( char *parsestring ) {
236
237         char *nextcomma, *residual_str;
238         int length;
239
240         nextcomma = strchr(parsestring,',');
241         if (nextcomma) {
242                 length = nextcomma - parsestring;
243                 residual_str = nextcomma + 1;
244         } else {
245                 length = strlen(parsestring);
246                 residual_str = parsestring + length;
247         }
248         if (strncmp("autodetect", parsestring, length) == 0) {
249                 dasd_autodetect = 1;
250                 MESSAGE (KERN_INFO, "%s",
251                          "turning to autodetection mode");
252                 return residual_str;
253         }
254         if (strncmp("probeonly", parsestring, length) == 0) {
255                 dasd_probeonly = 1;
256                 MESSAGE(KERN_INFO, "%s",
257                         "turning to probeonly mode");
258                 return residual_str;
259         }
260         if (strncmp("nopav", parsestring, length) == 0) {
261                 if (MACHINE_IS_VM)
262                         MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM");
263                 else {
264                         dasd_nopav = 1;
265                         MESSAGE(KERN_INFO, "%s", "disable PAV mode");
266                 }
267                 return residual_str;
268         }
269         if (strncmp("fixedbuffers", parsestring, length) == 0) {
270                 if (dasd_page_cache)
271                         return residual_str;
272                 dasd_page_cache =
273                         kmem_cache_create("dasd_page_cache", PAGE_SIZE,
274                                           PAGE_SIZE, SLAB_CACHE_DMA,
275                                           NULL, NULL );
276                 if (!dasd_page_cache)
277                         MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
278                                 "fixed buffer mode disabled.");
279                 else
280                         MESSAGE (KERN_INFO, "%s",
281                                  "turning on fixed buffer mode");
282                 return residual_str;
283         }
284         return ERR_PTR(-EINVAL);
285 }
286
287 /*
288  * Try to interprete the first element on the comma separated parse string
289  * as a device number or a range of devices. If the interpretation is
290  * successfull, create the matching dasd_devmap entries and return a pointer
291  * to the residual string.
292  * If interpretation fails or in case of an error, return an error code.
293  */
294 static char *
295 dasd_parse_range( char *parsestring ) {
296
297         struct dasd_devmap *devmap;
298         int from, from_id0, from_id1;
299         int to, to_id0, to_id1;
300         int features, rc;
301         char bus_id[BUS_ID_SIZE+1], *str;
302
303         str = parsestring;
304         rc = dasd_busid(&str, &from_id0, &from_id1, &from);
305         if (rc == 0) {
306                 to = from;
307                 to_id0 = from_id0;
308                 to_id1 = from_id1;
309                 if (*str == '-') {
310                         str++;
311                         rc = dasd_busid(&str, &to_id0, &to_id1, &to);
312                 }
313         }
314         if (rc == 0 &&
315             (from_id0 != to_id0 || from_id1 != to_id1 || from > to))
316                 rc = -EINVAL;
317         if (rc) {
318                 MESSAGE(KERN_ERR, "Invalid device range %s", parsestring);
319                 return ERR_PTR(rc);
320         }
321         features = dasd_feature_list(str, &str);
322         if (features < 0)
323                 return ERR_PTR(-EINVAL);
324         /* each device in dasd= parameter should be set initially online */
325         features |= DASD_FEATURE_INITIAL_ONLINE;
326         while (from <= to) {
327                 sprintf(bus_id, "%01x.%01x.%04x",
328                         from_id0, from_id1, from++);
329                 devmap = dasd_add_busid(bus_id, features);
330                 if (IS_ERR(devmap))
331                         return (char *)devmap;
332         }
333         if (*str == ',')
334                 return str + 1;
335         if (*str == '\0')
336                 return str;
337         MESSAGE(KERN_WARNING,
338                 "junk at end of dasd parameter string: %s\n", str);
339         return ERR_PTR(-EINVAL);
340 }
341
342 static inline char *
343 dasd_parse_next_element( char *parsestring ) {
344         char * residual_str;
345         residual_str = dasd_parse_keyword(parsestring);
346         if (!IS_ERR(residual_str))
347                 return residual_str;
348         residual_str = dasd_parse_range(parsestring);
349         return residual_str;
350 }
351
352 /*
353  * Parse parameters stored in dasd[]
354  * The 'dasd=...' parameter allows to specify a comma separated list of
355  * keywords and device ranges. When the dasd driver is build into the kernel,
356  * the complete list will be stored as one element of the dasd[] array.
357  * When the dasd driver is build as a module, then the list is broken into
358  * it's elements and each dasd[] entry contains one element.
359  */
360 int
361 dasd_parse(void)
362 {
363         int rc, i;
364         char *parsestring;
365
366         rc = 0;
367         for (i = 0; i < 256; i++) {
368                 if (dasd[i] == NULL)
369                         break;
370                 parsestring = dasd[i];
371                 /* loop over the comma separated list in the parsestring */
372                 while (*parsestring) {
373                         parsestring = dasd_parse_next_element(parsestring);
374                         if(IS_ERR(parsestring)) {
375                                 rc = PTR_ERR(parsestring);
376                                 break;
377                         }
378                 }
379                 if (rc) {
380                         DBF_EVENT(DBF_ALERT, "%s", "invalid range found");
381                         break;
382                 }
383         }
384         return rc;
385 }
386
387 /*
388  * Add a devmap for the device specified by busid. It is possible that
389  * the devmap already exists (dasd= parameter). The order of the devices
390  * added through this function will define the kdevs for the individual
391  * devices.
392  */
393 static struct dasd_devmap *
394 dasd_add_busid(char *bus_id, int features)
395 {
396         struct dasd_devmap *devmap, *new, *tmp;
397         int hash;
398
399         new = (struct dasd_devmap *)
400                 kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
401         if (!new)
402                 return ERR_PTR(-ENOMEM);
403         spin_lock(&dasd_devmap_lock);
404         devmap = NULL;
405         hash = dasd_hash_busid(bus_id);
406         list_for_each_entry(tmp, &dasd_hashlists[hash], list)
407                 if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
408                         devmap = tmp;
409                         break;
410                 }
411         if (!devmap) {
412                 /* This bus_id is new. */
413                 new->devindex = dasd_max_devindex++;
414                 strncpy(new->bus_id, bus_id, BUS_ID_SIZE);
415                 new->features = features;
416                 new->device = NULL;
417                 list_add(&new->list, &dasd_hashlists[hash]);
418                 devmap = new;
419                 new = NULL;
420         }
421         spin_unlock(&dasd_devmap_lock);
422         kfree(new);
423         return devmap;
424 }
425
426 /*
427  * Find devmap for device with given bus_id.
428  */
429 static struct dasd_devmap *
430 dasd_find_busid(char *bus_id)
431 {
432         struct dasd_devmap *devmap, *tmp;
433         int hash;
434
435         spin_lock(&dasd_devmap_lock);
436         devmap = ERR_PTR(-ENODEV);
437         hash = dasd_hash_busid(bus_id);
438         list_for_each_entry(tmp, &dasd_hashlists[hash], list) {
439                 if (strncmp(tmp->bus_id, bus_id, BUS_ID_SIZE) == 0) {
440                         devmap = tmp;
441                         break;
442                 }
443         }
444         spin_unlock(&dasd_devmap_lock);
445         return devmap;
446 }
447
448 /*
449  * Check if busid has been added to the list of dasd ranges.
450  */
451 int
452 dasd_busid_known(char *bus_id)
453 {
454         return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0;
455 }
456
457 /*
458  * Forget all about the device numbers added so far.
459  * This may only be called at module unload or system shutdown.
460  */
461 static void
462 dasd_forget_ranges(void)
463 {
464         struct dasd_devmap *devmap, *n;
465         int i;
466
467         spin_lock(&dasd_devmap_lock);
468         for (i = 0; i < 256; i++) {
469                 list_for_each_entry_safe(devmap, n, &dasd_hashlists[i], list) {
470                         BUG_ON(devmap->device != NULL);
471                         list_del(&devmap->list);
472                         kfree(devmap);
473                 }
474         }
475         spin_unlock(&dasd_devmap_lock);
476 }
477
478 /*
479  * Find the device struct by its device index.
480  */
481 struct dasd_device *
482 dasd_device_from_devindex(int devindex)
483 {
484         struct dasd_devmap *devmap, *tmp;
485         struct dasd_device *device;
486         int i;
487
488         spin_lock(&dasd_devmap_lock);
489         devmap = NULL;
490         for (i = 0; (i < 256) && !devmap; i++)
491                 list_for_each_entry(tmp, &dasd_hashlists[i], list)
492                         if (tmp->devindex == devindex) {
493                                 /* Found the devmap for the device. */
494                                 devmap = tmp;
495                                 break;
496                         }
497         if (devmap && devmap->device) {
498                 device = devmap->device;
499                 dasd_get_device(device);
500         } else
501                 device = ERR_PTR(-ENODEV);
502         spin_unlock(&dasd_devmap_lock);
503         return device;
504 }
505
506 /*
507  * Return devmap for cdev. If no devmap exists yet, create one and
508  * connect it to the cdev.
509  */
510 static struct dasd_devmap *
511 dasd_devmap_from_cdev(struct ccw_device *cdev)
512 {
513         struct dasd_devmap *devmap;
514
515         devmap = dasd_find_busid(cdev->dev.bus_id);
516         if (IS_ERR(devmap))
517                 devmap = dasd_add_busid(cdev->dev.bus_id,
518                                         DASD_FEATURE_DEFAULT);
519         return devmap;
520 }
521
522 /*
523  * Create a dasd device structure for cdev.
524  */
525 struct dasd_device *
526 dasd_create_device(struct ccw_device *cdev)
527 {
528         struct dasd_devmap *devmap;
529         struct dasd_device *device;
530         unsigned long flags;
531         int rc;
532
533         devmap = dasd_devmap_from_cdev(cdev);
534         if (IS_ERR(devmap))
535                 return (void *) devmap;
536
537         device = dasd_alloc_device();
538         if (IS_ERR(device))
539                 return device;
540         atomic_set(&device->ref_count, 3);
541
542         spin_lock(&dasd_devmap_lock);
543         if (!devmap->device) {
544                 devmap->device = device;
545                 device->devindex = devmap->devindex;
546                 device->features = devmap->features;
547                 get_device(&cdev->dev);
548                 device->cdev = cdev;
549                 rc = 0;
550         } else
551                 /* Someone else was faster. */
552                 rc = -EBUSY;
553         spin_unlock(&dasd_devmap_lock);
554
555         if (rc) {
556                 dasd_free_device(device);
557                 return ERR_PTR(rc);
558         }
559
560         spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
561         cdev->dev.driver_data = device;
562         spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
563
564         return device;
565 }
566
567 /*
568  * Wait queue for dasd_delete_device waits.
569  */
570 static DECLARE_WAIT_QUEUE_HEAD(dasd_delete_wq);
571
572 /*
573  * Remove a dasd device structure. The passed referenced
574  * is destroyed.
575  */
576 void
577 dasd_delete_device(struct dasd_device *device)
578 {
579         struct ccw_device *cdev;
580         struct dasd_devmap *devmap;
581         unsigned long flags;
582
583         /* First remove device pointer from devmap. */
584         devmap = dasd_find_busid(device->cdev->dev.bus_id);
585         BUG_ON(IS_ERR(devmap));
586         spin_lock(&dasd_devmap_lock);
587         if (devmap->device != device) {
588                 spin_unlock(&dasd_devmap_lock);
589                 dasd_put_device(device);
590                 return;
591         }
592         devmap->device = NULL;
593         spin_unlock(&dasd_devmap_lock);
594
595         /* Disconnect dasd_device structure from ccw_device structure. */
596         spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
597         device->cdev->dev.driver_data = NULL;
598         spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
599
600         /*
601          * Drop ref_count by 3, one for the devmap reference, one for
602          * the cdev reference and one for the passed reference.
603          */
604         atomic_sub(3, &device->ref_count);
605
606         /* Wait for reference counter to drop to zero. */
607         wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0);
608
609         /* Disconnect dasd_device structure from ccw_device structure. */
610         cdev = device->cdev;
611         device->cdev = NULL;
612
613         /* Put ccw_device structure. */
614         put_device(&cdev->dev);
615
616         /* Now the device structure can be freed. */
617         dasd_free_device(device);
618 }
619
620 /*
621  * Reference counter dropped to zero. Wake up waiter
622  * in dasd_delete_device.
623  */
624 void
625 dasd_put_device_wake(struct dasd_device *device)
626 {
627         wake_up(&dasd_delete_wq);
628 }
629
630 /*
631  * Return dasd_device structure associated with cdev.
632  * This function needs to be called with the ccw device
633  * lock held. It can be used from interrupt context.
634  */
635 struct dasd_device *
636 dasd_device_from_cdev_locked(struct ccw_device *cdev)
637 {
638         struct dasd_device *device = cdev->dev.driver_data;
639
640         if (!device)
641                 return ERR_PTR(-ENODEV);
642         dasd_get_device(device);
643         return device;
644 }
645
646 /*
647  * Return dasd_device structure associated with cdev.
648  */
649 struct dasd_device *
650 dasd_device_from_cdev(struct ccw_device *cdev)
651 {
652         struct dasd_device *device;
653         unsigned long flags;
654
655         spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
656         device = dasd_device_from_cdev_locked(cdev);
657         spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
658         return device;
659 }
660
661 /*
662  * SECTION: files in sysfs
663  */
664
665 /*
666  * readonly controls the readonly status of a dasd
667  */
668 static ssize_t
669 dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
670 {
671         struct dasd_devmap *devmap;
672         int ro_flag;
673
674         devmap = dasd_find_busid(dev->bus_id);
675         if (!IS_ERR(devmap))
676                 ro_flag = (devmap->features & DASD_FEATURE_READONLY) != 0;
677         else
678                 ro_flag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_READONLY) != 0;
679         return snprintf(buf, PAGE_SIZE, ro_flag ? "1\n" : "0\n");
680 }
681
682 static ssize_t
683 dasd_ro_store(struct device *dev, struct device_attribute *attr,
684               const char *buf, size_t count)
685 {
686         struct dasd_devmap *devmap;
687         int val;
688         char *endp;
689
690         devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
691         if (IS_ERR(devmap))
692                 return PTR_ERR(devmap);
693
694         val = simple_strtoul(buf, &endp, 0);
695         if (((endp + 1) < (buf + count)) || (val > 1))
696                 return -EINVAL;
697
698         spin_lock(&dasd_devmap_lock);
699         if (val)
700                 devmap->features |= DASD_FEATURE_READONLY;
701         else
702                 devmap->features &= ~DASD_FEATURE_READONLY;
703         if (devmap->device)
704                 devmap->device->features = devmap->features;
705         if (devmap->device && devmap->device->gdp)
706                 set_disk_ro(devmap->device->gdp, val);
707         spin_unlock(&dasd_devmap_lock);
708         return count;
709 }
710
711 static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
712
713 /*
714  * use_diag controls whether the driver should use diag rather than ssch
715  * to talk to the device
716  */
717 static ssize_t
718 dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
719 {
720         struct dasd_devmap *devmap;
721         int use_diag;
722
723         devmap = dasd_find_busid(dev->bus_id);
724         if (!IS_ERR(devmap))
725                 use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
726         else
727                 use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
728         return sprintf(buf, use_diag ? "1\n" : "0\n");
729 }
730
731 static ssize_t
732 dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
733                     const char *buf, size_t count)
734 {
735         struct dasd_devmap *devmap;
736         ssize_t rc;
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         /* Changing diag discipline flag is only allowed in offline state. */
750         rc = count;
751         if (!devmap->device) {
752                 if (val)
753                         devmap->features |= DASD_FEATURE_USEDIAG;
754                 else
755                         devmap->features &= ~DASD_FEATURE_USEDIAG;
756         } else
757                 rc = -EPERM;
758         spin_unlock(&dasd_devmap_lock);
759         return rc;
760 }
761
762 static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
763
764 static ssize_t
765 dasd_discipline_show(struct device *dev, struct device_attribute *attr,
766                      char *buf)
767 {
768         struct dasd_device *device;
769         ssize_t len;
770
771         device = dasd_device_from_cdev(to_ccwdev(dev));
772         if (!IS_ERR(device) && device->discipline) {
773                 len = snprintf(buf, PAGE_SIZE, "%s\n",
774                                device->discipline->name);
775                 dasd_put_device(device);
776         } else
777                 len = snprintf(buf, PAGE_SIZE, "none\n");
778         return len;
779 }
780
781 static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
782
783 static ssize_t
784 dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
785 {
786         struct dasd_devmap *devmap;
787         int alias;
788
789         devmap = dasd_find_busid(dev->bus_id);
790         spin_lock(&dasd_devmap_lock);
791         if (!IS_ERR(devmap))
792                 alias = devmap->uid.alias;
793         else
794                 alias = 0;
795         spin_unlock(&dasd_devmap_lock);
796
797         return sprintf(buf, alias ? "1\n" : "0\n");
798 }
799
800 static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
801
802 static ssize_t
803 dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
804 {
805         struct dasd_devmap *devmap;
806         char *vendor;
807
808         devmap = dasd_find_busid(dev->bus_id);
809         spin_lock(&dasd_devmap_lock);
810         if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
811                 vendor = devmap->uid.vendor;
812         else
813                 vendor = "";
814         spin_unlock(&dasd_devmap_lock);
815
816         return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
817 }
818
819 static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
820
821 #define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial    */ 14 + 1 +\
822                      /* SSID   */ 4 + 1 + /* unit addr */ 2 + 1)
823
824 static ssize_t
825 dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
826 {
827         struct dasd_devmap *devmap;
828         char uid[UID_STRLEN];
829
830         devmap = dasd_find_busid(dev->bus_id);
831         spin_lock(&dasd_devmap_lock);
832         if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
833                 snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
834                          devmap->uid.vendor, devmap->uid.serial,
835                          devmap->uid.ssid, devmap->uid.unit_addr);
836         else
837                 uid[0] = 0;
838         spin_unlock(&dasd_devmap_lock);
839
840         return snprintf(buf, PAGE_SIZE, "%s\n", uid);
841 }
842
843 static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
844
845 /*
846  * extended error-reporting
847  */
848 static ssize_t
849 dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
850 {
851         struct dasd_devmap *devmap;
852         int eer_flag;
853
854         devmap = dasd_find_busid(dev->bus_id);
855         if (!IS_ERR(devmap) && devmap->device)
856                 eer_flag = dasd_eer_enabled(devmap->device);
857         else
858                 eer_flag = 0;
859         return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
860 }
861
862 static ssize_t
863 dasd_eer_store(struct device *dev, struct device_attribute *attr,
864                const char *buf, size_t count)
865 {
866         struct dasd_devmap *devmap;
867         int val, rc;
868         char *endp;
869
870         devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
871         if (IS_ERR(devmap))
872                 return PTR_ERR(devmap);
873         if (!devmap->device)
874                 return -ENODEV;
875
876         val = simple_strtoul(buf, &endp, 0);
877         if (((endp + 1) < (buf + count)) || (val > 1))
878                 return -EINVAL;
879
880         if (val) {
881                 rc = dasd_eer_enable(devmap->device);
882                 if (rc)
883                         return rc;
884         } else
885                 dasd_eer_disable(devmap->device);
886         return count;
887 }
888
889 static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
890
891 static struct attribute * dasd_attrs[] = {
892         &dev_attr_readonly.attr,
893         &dev_attr_discipline.attr,
894         &dev_attr_alias.attr,
895         &dev_attr_vendor.attr,
896         &dev_attr_uid.attr,
897         &dev_attr_use_diag.attr,
898         &dev_attr_eer_enabled.attr,
899         NULL,
900 };
901
902 static struct attribute_group dasd_attr_group = {
903         .attrs = dasd_attrs,
904 };
905
906 /*
907  * Return copy of the device unique identifier.
908  */
909 int
910 dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
911 {
912         struct dasd_devmap *devmap;
913
914         devmap = dasd_find_busid(cdev->dev.bus_id);
915         if (IS_ERR(devmap))
916                 return PTR_ERR(devmap);
917         spin_lock(&dasd_devmap_lock);
918         *uid = devmap->uid;
919         spin_unlock(&dasd_devmap_lock);
920         return 0;
921 }
922
923 /*
924  * Register the given device unique identifier into devmap struct.
925  * In addition check if the related storage server subsystem ID is already
926  * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
927  * create new entry.
928  * Return 0 if server was already in serverlist,
929  *        1 if the server was added successful
930  *       <0 in case of error.
931  */
932 int
933 dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
934 {
935         struct dasd_devmap *devmap;
936         struct dasd_server_ssid_map *srv, *tmp;
937
938         devmap = dasd_find_busid(cdev->dev.bus_id);
939         if (IS_ERR(devmap))
940                 return PTR_ERR(devmap);
941
942         /* generate entry for server_ssid_map */
943         srv = (struct dasd_server_ssid_map *)
944                 kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL);
945         if (!srv)
946                 return -ENOMEM;
947         strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1);
948         strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1);
949         srv->sid.ssid = uid->ssid;
950
951         /* server is already contained ? */
952         spin_lock(&dasd_devmap_lock);
953         devmap->uid = *uid;
954         list_for_each_entry(tmp, &dasd_server_ssid_list, list) {
955                 if (!memcmp(&srv->sid, &tmp->sid,
956                             sizeof(struct system_id))) {
957                         kfree(srv);
958                         srv = NULL;
959                         break;
960                 }
961         }
962
963         /* add servermap to serverlist */
964         if (srv)
965                 list_add(&srv->list, &dasd_server_ssid_list);
966         spin_unlock(&dasd_devmap_lock);
967
968         return (srv ? 1 : 0);
969 }
970 EXPORT_SYMBOL_GPL(dasd_set_uid);
971
972 /*
973  * Return value of the specified feature.
974  */
975 int
976 dasd_get_feature(struct ccw_device *cdev, int feature)
977 {
978         struct dasd_devmap *devmap;
979
980         devmap = dasd_find_busid(cdev->dev.bus_id);
981         if (IS_ERR(devmap))
982                 return PTR_ERR(devmap);
983
984         return ((devmap->features & feature) != 0);
985 }
986
987 /*
988  * Set / reset given feature.
989  * Flag indicates wether to set (!=0) or the reset (=0) the feature.
990  */
991 int
992 dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
993 {
994         struct dasd_devmap *devmap;
995
996         devmap = dasd_find_busid(cdev->dev.bus_id);
997         if (IS_ERR(devmap))
998                 return PTR_ERR(devmap);
999
1000         spin_lock(&dasd_devmap_lock);
1001         if (flag)
1002                 devmap->features |= feature;
1003         else
1004                 devmap->features &= ~feature;
1005         if (devmap->device)
1006                 devmap->device->features = devmap->features;
1007         spin_unlock(&dasd_devmap_lock);
1008         return 0;
1009 }
1010
1011
1012 int
1013 dasd_add_sysfs_files(struct ccw_device *cdev)
1014 {
1015         return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
1016 }
1017
1018 void
1019 dasd_remove_sysfs_files(struct ccw_device *cdev)
1020 {
1021         sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
1022 }
1023
1024
1025 int
1026 dasd_devmap_init(void)
1027 {
1028         int i;
1029
1030         /* Initialize devmap structures. */
1031         dasd_max_devindex = 0;
1032         for (i = 0; i < 256; i++)
1033                 INIT_LIST_HEAD(&dasd_hashlists[i]);
1034
1035         /* Initialize servermap structure. */
1036         INIT_LIST_HEAD(&dasd_server_ssid_list);
1037         return 0;
1038 }
1039
1040 void
1041 dasd_devmap_exit(void)
1042 {
1043         dasd_forget_ranges();
1044 }