]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/s390/cio/chp.c
Merge branch 'master' into csb1725
[mv-sheeva.git] / drivers / s390 / cio / chp.c
index 6c9fa15aac7b2c1770afccdc2a0abef461e1eae8..2d32233943a917c7f6ae9949122a78e3f962a60c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/chp.c
  *
- *    Copyright IBM Corp. 1999,2007
+ *    Copyright IBM Corp. 1999,2010
  *    Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
  *              Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
@@ -54,12 +54,6 @@ static struct work_struct cfg_work;
 /* Wait queue for configure completion events. */
 static wait_queue_head_t cfg_wait_queue;
 
-/* Return channel_path struct for given chpid. */
-static inline struct channel_path *chpid_to_chp(struct chp_id chpid)
-{
-       return channel_subsystems[chpid.cssid]->chps[chpid.id];
-}
-
 /* Set vary state for given chpid. */
 static void set_chp_logically_online(struct chp_id chpid, int onoff)
 {
@@ -241,11 +235,13 @@ static ssize_t chp_status_show(struct device *dev,
                               struct device_attribute *attr, char *buf)
 {
        struct channel_path *chp = to_channelpath(dev);
+       int status;
 
-       if (!chp)
-               return 0;
-       return (chp_get_status(chp->chpid) ? sprintf(buf, "online\n") :
-               sprintf(buf, "offline\n"));
+       mutex_lock(&chp->lock);
+       status = chp->state;
+       mutex_unlock(&chp->lock);
+
+       return status ? sprintf(buf, "online\n") : sprintf(buf, "offline\n");
 }
 
 static ssize_t chp_status_write(struct device *dev,
@@ -261,15 +257,18 @@ static ssize_t chp_status_write(struct device *dev,
        if (!num_args)
                return count;
 
-       if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1"))
+       if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
+               mutex_lock(&cp->lock);
                error = s390_vary_chpid(cp->chpid, 1);
-       else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0"))
+               mutex_unlock(&cp->lock);
+       } else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) {
+               mutex_lock(&cp->lock);
                error = s390_vary_chpid(cp->chpid, 0);
-       else
+               mutex_unlock(&cp->lock);
+       } else
                error = -EINVAL;
 
        return error < 0 ? error : count;
-
 }
 
 static DEVICE_ATTR(status, 0644, chp_status_show, chp_status_write);
@@ -315,10 +314,12 @@ static ssize_t chp_type_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        struct channel_path *chp = to_channelpath(dev);
+       u8 type;
 
-       if (!chp)
-               return 0;
-       return sprintf(buf, "%x\n", chp->desc.desc);
+       mutex_lock(&chp->lock);
+       type = chp->desc.desc;
+       mutex_unlock(&chp->lock);
+       return sprintf(buf, "%x\n", type);
 }
 
 static DEVICE_ATTR(type, 0444, chp_type_show, NULL);
@@ -395,6 +396,7 @@ int chp_new(struct chp_id chpid)
        chp->state = 1;
        chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
        chp->dev.release = chp_release;
+       mutex_init(&chp->lock);
 
        /* Obtain channel path description and fill it in. */
        ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
@@ -464,7 +466,10 @@ void *chp_get_chp_desc(struct chp_id chpid)
        desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL);
        if (!desc)
                return NULL;
+
+       mutex_lock(&chp->lock);
        memcpy(desc, &chp->desc, sizeof(struct channel_path_desc));
+       mutex_unlock(&chp->lock);
        return desc;
 }