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