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