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