]> err.no Git - linux-2.6/blobdiff - drivers/s390/block/dasd_devmap.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
[linux-2.6] / drivers / s390 / block / dasd_devmap.c
index ed70852cc9154666a0bffeb95d813c2cbd762268..f4fb40257348e3bd3e42b59b1061332233e1eed0 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <asm/debug.h>
 #include <asm/uaccess.h>
+#include <asm/ipl.h>
 
 /* This is ugly... */
 #define PRINTK_HEADER "dasd_devmap:"
@@ -47,22 +48,6 @@ struct dasd_devmap {
        struct dasd_uid uid;
 };
 
-/*
- * dasd_server_ssid_map contains a globally unique storage server subsystem ID.
- * dasd_server_ssid_list contains the list of all subsystem IDs accessed by
- * the DASD device driver.
- */
-struct dasd_server_ssid_map {
-       struct list_head list;
-       struct system_id {
-               char vendor[4];
-               char serial[15];
-               __u16 ssid;
-       } sid;
-};
-
-static struct list_head dasd_server_ssid_list;
-
 /*
  * Parameter parsing functions for dasd= parameter. The syntax is:
  *   <devno>           : (0x)?[0-9a-fA-F]+
@@ -133,6 +118,8 @@ dasd_call_setup(char *str)
 __setup ("dasd=", dasd_call_setup);
 #endif /* #ifndef MODULE */
 
+#define        DASD_IPLDEV     "ipldev"
+
 /*
  * Read a device busid/devno from a string.
  */
@@ -141,6 +128,20 @@ dasd_busid(char **str, int *id0, int *id1, int *devno)
 {
        int val, old_style;
 
+       /* Interpret ipldev busid */
+       if (strncmp(DASD_IPLDEV, *str, strlen(DASD_IPLDEV)) == 0) {
+               if (ipl_info.type != IPL_TYPE_CCW) {
+                       MESSAGE(KERN_ERR, "%s", "ipl device is not a ccw "
+                               "device");
+                       return -EINVAL;
+               }
+               *id0 = 0;
+               *id1 = ipl_info.data.ccw.dev_id.ssid;
+               *devno = ipl_info.data.ccw.dev_id.devno;
+               *str += strlen(DASD_IPLDEV);
+
+               return 0;
+       }
        /* check for leading '0x' */
        old_style = 0;
        if ((*str)[0] == '0' && (*str)[1] == 'x') {
@@ -274,7 +275,7 @@ dasd_parse_keyword( char *parsestring ) {
                dasd_page_cache =
                        kmem_cache_create("dasd_page_cache", PAGE_SIZE,
                                          PAGE_SIZE, SLAB_CACHE_DMA,
-                                         NULL, NULL );
+                                         NULL);
                if (!dasd_page_cache)
                        MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
                                "fixed buffer mode disabled.");
@@ -704,8 +705,9 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr,
                devmap->features &= ~DASD_FEATURE_READONLY;
        if (devmap->device)
                devmap->device->features = devmap->features;
-       if (devmap->device && devmap->device->gdp)
-               set_disk_ro(devmap->device->gdp, val);
+       if (devmap->device && devmap->device->block
+           && devmap->device->block->gdp)
+               set_disk_ro(devmap->device->block->gdp, val);
        spin_unlock(&dasd_devmap_lock);
        return count;
 }
@@ -828,6 +830,46 @@ dasd_discipline_show(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL);
 
+static ssize_t
+dasd_device_status_show(struct device *dev, struct device_attribute *attr,
+                    char *buf)
+{
+       struct dasd_device *device;
+       ssize_t len;
+
+       device = dasd_device_from_cdev(to_ccwdev(dev));
+       if (!IS_ERR(device)) {
+               switch (device->state) {
+               case DASD_STATE_NEW:
+                       len = snprintf(buf, PAGE_SIZE, "new\n");
+                       break;
+               case DASD_STATE_KNOWN:
+                       len = snprintf(buf, PAGE_SIZE, "detected\n");
+                       break;
+               case DASD_STATE_BASIC:
+                       len = snprintf(buf, PAGE_SIZE, "basic\n");
+                       break;
+               case DASD_STATE_UNFMT:
+                       len = snprintf(buf, PAGE_SIZE, "unformatted\n");
+                       break;
+               case DASD_STATE_READY:
+                       len = snprintf(buf, PAGE_SIZE, "ready\n");
+                       break;
+               case DASD_STATE_ONLINE:
+                       len = snprintf(buf, PAGE_SIZE, "online\n");
+                       break;
+               default:
+                       len = snprintf(buf, PAGE_SIZE, "no stat\n");
+                       break;
+               }
+               dasd_put_device(device);
+       } else
+               len = snprintf(buf, PAGE_SIZE, "unknown\n");
+       return len;
+}
+
+static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL);
+
 static ssize_t
 dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -836,12 +878,16 @@ dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf)
 
        devmap = dasd_find_busid(dev->bus_id);
        spin_lock(&dasd_devmap_lock);
-       if (!IS_ERR(devmap))
-               alias = devmap->uid.alias;
+       if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
+               spin_unlock(&dasd_devmap_lock);
+               return sprintf(buf, "0\n");
+       }
+       if (devmap->uid.type == UA_BASE_PAV_ALIAS ||
+           devmap->uid.type == UA_HYPER_PAV_ALIAS)
+               alias = 1;
        else
                alias = 0;
        spin_unlock(&dasd_devmap_lock);
-
        return sprintf(buf, alias ? "1\n" : "0\n");
 }
 
@@ -873,19 +919,36 @@ static ssize_t
 dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct dasd_devmap *devmap;
-       char uid[UID_STRLEN];
+       char uid_string[UID_STRLEN];
+       char ua_string[3];
+       struct dasd_uid *uid;
 
        devmap = dasd_find_busid(dev->bus_id);
        spin_lock(&dasd_devmap_lock);
-       if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0)
-               snprintf(uid, sizeof(uid), "%s.%s.%04x.%02x",
-                        devmap->uid.vendor, devmap->uid.serial,
-                        devmap->uid.ssid, devmap->uid.unit_addr);
-       else
-               uid[0] = 0;
+       if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) {
+               spin_unlock(&dasd_devmap_lock);
+               return sprintf(buf, "\n");
+       }
+       uid = &devmap->uid;
+       switch (uid->type) {
+       case UA_BASE_DEVICE:
+               sprintf(ua_string, "%02x", uid->real_unit_addr);
+               break;
+       case UA_BASE_PAV_ALIAS:
+               sprintf(ua_string, "%02x", uid->base_unit_addr);
+               break;
+       case UA_HYPER_PAV_ALIAS:
+               sprintf(ua_string, "xx");
+               break;
+       default:
+               /* should not happen, treat like base device */
+               sprintf(ua_string, "%02x", uid->real_unit_addr);
+               break;
+       }
+       snprintf(uid_string, sizeof(uid_string), "%s.%s.%04x.%s",
+                uid->vendor, uid->serial, uid->ssid, ua_string);
        spin_unlock(&dasd_devmap_lock);
-
-       return snprintf(buf, PAGE_SIZE, "%s\n", uid);
+       return snprintf(buf, PAGE_SIZE, "%s\n", uid_string);
 }
 
 static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL);
@@ -939,6 +1002,7 @@ static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
 static struct attribute * dasd_attrs[] = {
        &dev_attr_readonly.attr,
        &dev_attr_discipline.attr,
+       &dev_attr_status.attr,
        &dev_attr_alias.attr,
        &dev_attr_vendor.attr,
        &dev_attr_uid.attr,
@@ -982,39 +1046,16 @@ int
 dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
 {
        struct dasd_devmap *devmap;
-       struct dasd_server_ssid_map *srv, *tmp;
 
        devmap = dasd_find_busid(cdev->dev.bus_id);
        if (IS_ERR(devmap))
                return PTR_ERR(devmap);
 
-       /* generate entry for server_ssid_map */
-       srv = (struct dasd_server_ssid_map *)
-               kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL);
-       if (!srv)
-               return -ENOMEM;
-       strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1);
-       strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1);
-       srv->sid.ssid = uid->ssid;
-
-       /* server is already contained ? */
        spin_lock(&dasd_devmap_lock);
        devmap->uid = *uid;
-       list_for_each_entry(tmp, &dasd_server_ssid_list, list) {
-               if (!memcmp(&srv->sid, &tmp->sid,
-                           sizeof(struct system_id))) {
-                       kfree(srv);
-                       srv = NULL;
-                       break;
-               }
-       }
-
-       /* add servermap to serverlist */
-       if (srv)
-               list_add(&srv->list, &dasd_server_ssid_list);
        spin_unlock(&dasd_devmap_lock);
 
-       return (srv ? 1 : 0);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(dasd_set_uid);
 
@@ -1080,9 +1121,6 @@ dasd_devmap_init(void)
        dasd_max_devindex = 0;
        for (i = 0; i < 256; i++)
                INIT_LIST_HEAD(&dasd_hashlists[i]);
-
-       /* Initialize servermap structure. */
-       INIT_LIST_HEAD(&dasd_server_ssid_list);
        return 0;
 }