[S390] cio: fix parallel cm_enable processing.
authorMichael Ernst <mernst@de.ibm.com>
Thu, 17 Apr 2008 05:46:01 +0000 (07:46 +0200)
committerHeiko Carstens <heiko.carstens@de.ibm.com>
Thu, 17 Apr 2008 05:46:57 +0000 (07:46 +0200)
It is now possible to trigger cm_enable processing several times in
parallel without causing a kernel panic.

Signed-off-by: Michael Ernst <mernst@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
drivers/s390/cio/chsc.c
drivers/s390/cio/css.c

index b6a40c2..5de8690 100644 (file)
@@ -766,7 +766,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
        if (!secm_area)
                return -ENOMEM;
 
-       mutex_lock(&css->mutex);
        if (enable && !css->cm_enabled) {
                css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
                css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -774,7 +773,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
                        free_page((unsigned long)css->cub_addr1);
                        free_page((unsigned long)css->cub_addr2);
                        free_page((unsigned long)secm_area);
-                       mutex_unlock(&css->mutex);
                        return -ENOMEM;
                }
        }
@@ -795,7 +793,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
                free_page((unsigned long)css->cub_addr1);
                free_page((unsigned long)css->cub_addr2);
        }
-       mutex_unlock(&css->mutex);
        free_page((unsigned long)secm_area);
        return ret;
 }
index 3e829c8..c1afab5 100644 (file)
@@ -689,10 +689,14 @@ css_cm_enable_show(struct device *dev, struct device_attribute *attr,
                   char *buf)
 {
        struct channel_subsystem *css = to_css(dev);
+       int ret;
 
        if (!css)
                return 0;
-       return sprintf(buf, "%x\n", css->cm_enabled);
+       mutex_lock(&css->mutex);
+       ret = sprintf(buf, "%x\n", css->cm_enabled);
+       mutex_unlock(&css->mutex);
+       return ret;
 }
 
 static ssize_t
@@ -702,6 +706,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
        struct channel_subsystem *css = to_css(dev);
        int ret;
 
+       mutex_lock(&css->mutex);
        switch (buf[0]) {
        case '0':
                ret = css->cm_enabled ? chsc_secm(css, 0) : 0;
@@ -712,6 +717,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
        default:
                ret = -EINVAL;
        }
+       mutex_unlock(&css->mutex);
        return ret < 0 ? ret : count;
 }
 
@@ -758,9 +764,11 @@ static int css_reboot_event(struct notifier_block *this,
                struct channel_subsystem *css;
 
                css = channel_subsystems[i];
+               mutex_lock(&css->mutex);
                if (css->cm_enabled)
                        if (chsc_secm(css, 0))
                                ret = NOTIFY_BAD;
+               mutex_unlock(&css->mutex);
        }
 
        return ret;