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