diff options
author | Michael Ernst <mernst@de.ibm.com> | 2008-04-17 09:46:01 +0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-04-17 09:46:57 +0400 |
commit | 8284fb19efa1f11ea8dd213e9e227fc1fcb20586 (patch) | |
tree | f91933a4ee9e253bd25c3a98df0d67ee946bb41e | |
parent | fe6173d9b33dba18ec462051750fb1b9abcd796d (diff) | |
download | linux-8284fb19efa1f11ea8dd213e9e227fc1fcb20586.tar.xz |
[S390] cio: fix parallel cm_enable processing.
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>
-rw-r--r-- | drivers/s390/cio/chsc.c | 3 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 10 |
2 files changed, 9 insertions, 4 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index b6a40c20780d..5de86908b0d0 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -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; } diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 3e829c827493..c1afab5f72d6 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -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; |