diff options
Diffstat (limited to 'drivers/s390/cio/chp.c')
-rw-r--r-- | drivers/s390/cio/chp.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 6c9fa15aac7b..2d32233943a9 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/cio/chp.c | 2 | * drivers/s390/cio/chp.c |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 1999,2007 | 4 | * Copyright IBM Corp. 1999,2010 |
5 | * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) | 5 | * Author(s): Cornelia Huck (cornelia.huck@de.ibm.com) |
6 | * Arnd Bergmann (arndb@de.ibm.com) | 6 | * Arnd Bergmann (arndb@de.ibm.com) |
7 | * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> | 7 | * Peter Oberparleiter <peter.oberparleiter@de.ibm.com> |
@@ -54,12 +54,6 @@ static struct work_struct cfg_work; | |||
54 | /* Wait queue for configure completion events. */ | 54 | /* Wait queue for configure completion events. */ |
55 | static wait_queue_head_t cfg_wait_queue; | 55 | static wait_queue_head_t cfg_wait_queue; |
56 | 56 | ||
57 | /* Return channel_path struct for given chpid. */ | ||
58 | static inline struct channel_path *chpid_to_chp(struct chp_id chpid) | ||
59 | { | ||
60 | return channel_subsystems[chpid.cssid]->chps[chpid.id]; | ||
61 | } | ||
62 | |||
63 | /* Set vary state for given chpid. */ | 57 | /* Set vary state for given chpid. */ |
64 | static void set_chp_logically_online(struct chp_id chpid, int onoff) | 58 | static void set_chp_logically_online(struct chp_id chpid, int onoff) |
65 | { | 59 | { |
@@ -241,11 +235,13 @@ static ssize_t chp_status_show(struct device *dev, | |||
241 | struct device_attribute *attr, char *buf) | 235 | struct device_attribute *attr, char *buf) |
242 | { | 236 | { |
243 | struct channel_path *chp = to_channelpath(dev); | 237 | struct channel_path *chp = to_channelpath(dev); |
238 | int status; | ||
244 | 239 | ||
245 | if (!chp) | 240 | mutex_lock(&chp->lock); |
246 | return 0; | 241 | status = chp->state; |
247 | return (chp_get_status(chp->chpid) ? sprintf(buf, "online\n") : | 242 | mutex_unlock(&chp->lock); |
248 | sprintf(buf, "offline\n")); | 243 | |
244 | return status ? sprintf(buf, "online\n") : sprintf(buf, "offline\n"); | ||
249 | } | 245 | } |
250 | 246 | ||
251 | static ssize_t chp_status_write(struct device *dev, | 247 | static ssize_t chp_status_write(struct device *dev, |
@@ -261,15 +257,18 @@ static ssize_t chp_status_write(struct device *dev, | |||
261 | if (!num_args) | 257 | if (!num_args) |
262 | return count; | 258 | return count; |
263 | 259 | ||
264 | if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) | 260 | if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) { |
261 | mutex_lock(&cp->lock); | ||
265 | error = s390_vary_chpid(cp->chpid, 1); | 262 | error = s390_vary_chpid(cp->chpid, 1); |
266 | else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) | 263 | mutex_unlock(&cp->lock); |
264 | } else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) { | ||
265 | mutex_lock(&cp->lock); | ||
267 | error = s390_vary_chpid(cp->chpid, 0); | 266 | error = s390_vary_chpid(cp->chpid, 0); |
268 | else | 267 | mutex_unlock(&cp->lock); |
268 | } else | ||
269 | error = -EINVAL; | 269 | error = -EINVAL; |
270 | 270 | ||
271 | return error < 0 ? error : count; | 271 | return error < 0 ? error : count; |
272 | |||
273 | } | 272 | } |
274 | 273 | ||
275 | static DEVICE_ATTR(status, 0644, chp_status_show, chp_status_write); | 274 | 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, | |||
315 | char *buf) | 314 | char *buf) |
316 | { | 315 | { |
317 | struct channel_path *chp = to_channelpath(dev); | 316 | struct channel_path *chp = to_channelpath(dev); |
317 | u8 type; | ||
318 | 318 | ||
319 | if (!chp) | 319 | mutex_lock(&chp->lock); |
320 | return 0; | 320 | type = chp->desc.desc; |
321 | return sprintf(buf, "%x\n", chp->desc.desc); | 321 | mutex_unlock(&chp->lock); |
322 | return sprintf(buf, "%x\n", type); | ||
322 | } | 323 | } |
323 | 324 | ||
324 | static DEVICE_ATTR(type, 0444, chp_type_show, NULL); | 325 | static DEVICE_ATTR(type, 0444, chp_type_show, NULL); |
@@ -395,6 +396,7 @@ int chp_new(struct chp_id chpid) | |||
395 | chp->state = 1; | 396 | chp->state = 1; |
396 | chp->dev.parent = &channel_subsystems[chpid.cssid]->device; | 397 | chp->dev.parent = &channel_subsystems[chpid.cssid]->device; |
397 | chp->dev.release = chp_release; | 398 | chp->dev.release = chp_release; |
399 | mutex_init(&chp->lock); | ||
398 | 400 | ||
399 | /* Obtain channel path description and fill it in. */ | 401 | /* Obtain channel path description and fill it in. */ |
400 | ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc); | 402 | ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc); |
@@ -464,7 +466,10 @@ void *chp_get_chp_desc(struct chp_id chpid) | |||
464 | desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL); | 466 | desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL); |
465 | if (!desc) | 467 | if (!desc) |
466 | return NULL; | 468 | return NULL; |
469 | |||
470 | mutex_lock(&chp->lock); | ||
467 | memcpy(desc, &chp->desc, sizeof(struct channel_path_desc)); | 471 | memcpy(desc, &chp->desc, sizeof(struct channel_path_desc)); |
472 | mutex_unlock(&chp->lock); | ||
468 | return desc; | 473 | return desc; |
469 | } | 474 | } |
470 | 475 | ||