Merge tag 'r8169-20060920-00' of git://electric-eye.fr.zoreil.com/home/romieu/linux...
[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 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                 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 ro_flag;
688
689         devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
690         if (IS_ERR(devmap))
691                 return PTR_ERR(devmap);
692         ro_flag = buf[0] == '1';
693         spin_lock(&dasd_devmap_lock);
694         if (ro_flag)
695                 devmap->features |= DASD_FEATURE_READONLY;
696         else
697                 devmap->features &= ~DASD_FEATURE_READONLY;
698         if (devmap->device)
699                 devmap->device->features = devmap->features;
700         if (devmap->device && devmap->device->gdp)
701                 set_disk_ro(devmap->device->gdp, ro_flag);
702         spin_unlock(&dasd_devmap_lock);
703         return count;
704 }
705
706 static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
707
708 /*
709  * use_diag controls whether the driver should use diag rather than ssch
710  * to talk to the device
711  */
712 static ssize_t
713 dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
714 {
715         struct dasd_devmap *devmap;
716         int use_diag;
717
718         devmap = dasd_find_busid(dev->bus_id);
719         if (!IS_ERR(devmap))
720                 use_diag = (devmap->features & DASD_FEATURE_USEDIAG) != 0;
721         else
722                 use_diag = (DASD_FEATURE_DEFAULT & DASD_FEATURE_USEDIAG) != 0;
723         return sprintf(buf, use_diag ? "1\n" : "0\n");
724 }
725
726 static ssize_t
727 dasd_use_diag_store(struct device *dev, struct device_attribute *attr,
728                     const char *buf, size_t count)
729 {
730         struct dasd_devmap *devmap;
731         ssize_t rc;
732         int use_diag;
733
734         devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
735         if (IS_ERR(devmap))
736                 return PTR_ERR(devmap);
737         use_diag = buf[0] == '1';
738         spin_lock(&dasd_devmap_lock);
739         /* Changing diag discipline flag is only allowed in offline state. */
740         rc = count;
741         if (!devmap->device) {
742                 if (use_diag)
743                         devmap->features |= DASD_FEATURE_USEDIAG;
744                 else
745                         devmap->features &= ~DASD_FEATURE_USEDIAG;
746         } else
747                 rc = -EPERM;
748         spin_unlock(&dasd_devmap_lock);
749         return rc;
750 }
751
752 static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
753
754 static ssize_t
755 dasd_discipline_show(struct device *dev, struct device_attribute *attr,
756                      char *buf)
757 {
758         struct dasd_device *device;
759         ssize_t len;
760
761         device = dasd_device_from_cdev(to_ccwdev(dev));
762         if (!IS_ERR(device) && device->discipline) {
763                 len = snprintf(buf, PAGE_SIZE, "%s\n",
764                                device->discipline->name);
765                 dasd_put_device(device);
766         } else
767                 len = snprintf(buf, PAGE_SIZE, "none\n");
768         return len;
769 }
770
771 static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
772
773 static ssize_t
774 dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
775 {
776         struct dasd_devmap *devmap;
777         int alias;
778
779         devmap = dasd_find_busid(dev->bus_id);
780         spin_lock(&dasd_devmap_lock);
781         if (!IS_ERR(devmap))
782                 alias = devmap->uid.alias;
783         else
784                 alias = 0;
785         spin_unlock(&dasd_devmap_lock);
786
787         return sprintf(buf, alias ? "1\n" : "0\n");
788 }
789
790 static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL);
791
792 static ssize_t
793 dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf)
794 {
795         struct dasd_devmap *devmap;
796         char *vendor;
797
798         devmap = dasd_find_busid(dev->bus_id);
799         spin_lock(&dasd_devmap_lock);
800         if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
801                 vendor = devmap->uid.vendor;
802         else
803                 vendor = "";
804         spin_unlock(&dasd_devmap_lock);
805
806         return snprintf(buf, PAGE_SIZE, "%s\n", vendor);
807 }
808
809 static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL);
810
811 #define UID_STRLEN ( /* vendor */ 3 + 1 + /* serial    */ 14 + 1 +\
812                      /* SSID   */ 4 + 1 + /* unit addr */ 2 + 1)
813
814 static ssize_t
815 dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
816 {
817         struct dasd_devmap *devmap;
818         char uid[UID_STRLEN];
819
820         devmap = dasd_find_busid(dev->bus_id);
821         spin_lock(&dasd_devmap_lock);
822         if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
823                 snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
824                          devmap->uid.vendor, devmap->uid.serial,
825                          devmap->uid.ssid, devmap->uid.unit_addr);
826         else
827                 uid[0] = 0;
828         spin_unlock(&dasd_devmap_lock);
829
830         return snprintf(buf, PAGE_SIZE, "%s\n", uid);
831 }
832
833 static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
834
835 /*
836  * extended error-reporting
837  */
838 static ssize_t
839 dasd_eer_show(struct device *dev, struct device_attribute *attr, char *buf)
840 {
841         struct dasd_devmap *devmap;
842         int eer_flag;
843
844         devmap = dasd_find_busid(dev->bus_id);
845         if (!IS_ERR(devmap) && devmap->device)
846                 eer_flag = dasd_eer_enabled(devmap->device);
847         else
848                 eer_flag = 0;
849         return snprintf(buf, PAGE_SIZE, eer_flag ? "1\n" : "0\n");
850 }
851
852 static ssize_t
853 dasd_eer_store(struct device *dev, struct device_attribute *attr,
854                const char *buf, size_t count)
855 {
856         struct dasd_devmap *devmap;
857         int rc;
858
859         devmap = dasd_devmap_from_cdev(to_ccwdev(dev));
860         if (IS_ERR(devmap))
861                 return PTR_ERR(devmap);
862         if (!devmap->device)
863                 return count;
864         if (buf[0] == '1') {
865                 rc = dasd_eer_enable(devmap->device);
866                 if (rc)
867                         return rc;
868         } else
869                 dasd_eer_disable(devmap->device);
870         return count;
871 }
872
873 static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
874
875 static struct attribute * dasd_attrs[] = {
876         &dev_attr_readonly.attr,
877         &dev_attr_discipline.attr,
878         &dev_attr_alias.attr,
879         &dev_attr_vendor.attr,
880         &dev_attr_uid.attr,
881         &dev_attr_use_diag.attr,
882         &dev_attr_eer_enabled.attr,
883         NULL,
884 };
885
886 static struct attribute_group dasd_attr_group = {
887         .attrs = dasd_attrs,
888 };
889
890 /*
891  * Return copy of the device unique identifier.
892  */
893 int
894 dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid)
895 {
896         struct dasd_devmap *devmap;
897
898         devmap = dasd_find_busid(cdev->dev.bus_id);
899         if (IS_ERR(devmap))
900                 return PTR_ERR(devmap);
901         spin_lock(&dasd_devmap_lock);
902         *uid = devmap->uid;
903         spin_unlock(&dasd_devmap_lock);
904         return 0;
905 }
906
907 /*
908  * Register the given device unique identifier into devmap struct.
909  * In addition check if the related storage server subsystem ID is already
910  * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
911  * create new entry.
912  * Return 0 if server was already in serverlist,
913  *        1 if the server was added successful
914  *       <0 in case of error.
915  */
916 int
917 dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
918 {
919         struct dasd_devmap *devmap;
920         struct dasd_server_ssid_map *srv, *tmp;
921
922         devmap = dasd_find_busid(cdev->dev.bus_id);
923         if (IS_ERR(devmap))
924                 return PTR_ERR(devmap);
925
926         /* generate entry for server_ssid_map */
927         srv = (struct dasd_server_ssid_map *)
928                 kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL);
929         if (!srv)
930                 return -ENOMEM;
931         strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1);
932         strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1);
933         srv->sid.ssid = uid->ssid;
934
935         /* server is already contained ? */
936         spin_lock(&dasd_devmap_lock);
937         devmap->uid = *uid;
938         list_for_each_entry(tmp, &dasd_server_ssid_list, list) {
939                 if (!memcmp(&srv->sid, &tmp->sid,
940                             sizeof(struct system_id))) {
941                         kfree(srv);
942                         srv = NULL;
943                         break;
944                 }
945         }
946
947         /* add servermap to serverlist */
948         if (srv)
949                 list_add(&srv->list, &dasd_server_ssid_list);
950         spin_unlock(&dasd_devmap_lock);
951
952         return (srv ? 1 : 0);
953 }
954 EXPORT_SYMBOL_GPL(dasd_set_uid);
955
956 /*
957  * Return value of the specified feature.
958  */
959 int
960 dasd_get_feature(struct ccw_device *cdev, int feature)
961 {
962         struct dasd_devmap *devmap;
963
964         devmap = dasd_find_busid(cdev->dev.bus_id);
965         if (IS_ERR(devmap))
966                 return PTR_ERR(devmap);
967
968         return ((devmap->features & feature) != 0);
969 }
970
971 /*
972  * Set / reset given feature.
973  * Flag indicates wether to set (!=0) or the reset (=0) the feature.
974  */
975 int
976 dasd_set_feature(struct ccw_device *cdev, int feature, int flag)
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         spin_lock(&dasd_devmap_lock);
985         if (flag)
986                 devmap->features |= feature;
987         else
988                 devmap->features &= ~feature;
989         if (devmap->device)
990                 devmap->device->features = devmap->features;
991         spin_unlock(&dasd_devmap_lock);
992         return 0;
993 }
994
995
996 int
997 dasd_add_sysfs_files(struct ccw_device *cdev)
998 {
999         return sysfs_create_group(&cdev->dev.kobj, &dasd_attr_group);
1000 }
1001
1002 void
1003 dasd_remove_sysfs_files(struct ccw_device *cdev)
1004 {
1005         sysfs_remove_group(&cdev->dev.kobj, &dasd_attr_group);
1006 }
1007
1008
1009 int
1010 dasd_devmap_init(void)
1011 {
1012         int i;
1013
1014         /* Initialize devmap structures. */
1015         dasd_max_devindex = 0;
1016         for (i = 0; i < 256; i++)
1017                 INIT_LIST_HEAD(&dasd_hashlists[i]);
1018
1019         /* Initialize servermap structure. */
1020         INIT_LIST_HEAD(&dasd_server_ssid_list);
1021         return 0;
1022 }
1023
1024 void
1025 dasd_devmap_exit(void)
1026 {
1027         dasd_forget_ranges();
1028 }