diff options
author | Gerald Schaefer <geraldsc@de.ibm.com> | 2007-02-05 15:17:11 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2007-02-05 15:17:11 -0500 |
commit | 444f0e5489e7ac4bca5c4748d7d846c352a5cd03 (patch) | |
tree | 4d2bd832b9a0b99eb81b99d2d509205ef0311709 | |
parent | 18374d376c7eb30b6359759e767cd99397b377d2 (diff) |
[S390] Show loaded DCSS segments under /proc/iomem.
Currently loaded DCSS segments are now listed in /proc/iomem with
their name followed by a trailing "(DCSS)".
Signed-off-by: Gerald Schaefer <geraldsc@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r-- | arch/s390/mm/extmem.c | 64 | ||||
-rw-r--r-- | drivers/s390/block/dcssblk.c | 4 |
2 files changed, 56 insertions, 12 deletions
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 775bf19e742b..8bffadb5e537 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/bootmem.h> | 16 | #include <linux/bootmem.h> |
17 | #include <linux/ctype.h> | 17 | #include <linux/ctype.h> |
18 | #include <linux/ioport.h> | ||
18 | #include <asm/page.h> | 19 | #include <asm/page.h> |
19 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
20 | #include <asm/ebcdic.h> | 21 | #include <asm/ebcdic.h> |
@@ -70,6 +71,7 @@ struct qin64 { | |||
70 | struct dcss_segment { | 71 | struct dcss_segment { |
71 | struct list_head list; | 72 | struct list_head list; |
72 | char dcss_name[8]; | 73 | char dcss_name[8]; |
74 | char res_name[15]; | ||
73 | unsigned long start_addr; | 75 | unsigned long start_addr; |
74 | unsigned long end; | 76 | unsigned long end; |
75 | atomic_t ref_count; | 77 | atomic_t ref_count; |
@@ -77,6 +79,7 @@ struct dcss_segment { | |||
77 | unsigned int vm_segtype; | 79 | unsigned int vm_segtype; |
78 | struct qrange range[6]; | 80 | struct qrange range[6]; |
79 | int segcnt; | 81 | int segcnt; |
82 | struct resource *res; | ||
80 | }; | 83 | }; |
81 | 84 | ||
82 | static DEFINE_MUTEX(dcss_lock); | 85 | static DEFINE_MUTEX(dcss_lock); |
@@ -303,6 +306,29 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long | |||
303 | goto out_free; | 306 | goto out_free; |
304 | } | 307 | } |
305 | 308 | ||
309 | seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL); | ||
310 | if (seg->res == NULL) { | ||
311 | rc = -ENOMEM; | ||
312 | goto out_shared; | ||
313 | } | ||
314 | seg->res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; | ||
315 | seg->res->start = seg->start_addr; | ||
316 | seg->res->end = seg->end; | ||
317 | memcpy(&seg->res_name, seg->dcss_name, 8); | ||
318 | EBCASC(seg->res_name, 8); | ||
319 | seg->res_name[8] = '\0'; | ||
320 | strncat(seg->res_name, " (DCSS)", 7); | ||
321 | seg->res->name = seg->res_name; | ||
322 | rc = seg->vm_segtype; | ||
323 | if (rc == SEG_TYPE_SC || | ||
324 | ((rc == SEG_TYPE_SR || rc == SEG_TYPE_ER) && !do_nonshared)) | ||
325 | seg->res->flags |= IORESOURCE_READONLY; | ||
326 | if (request_resource(&iomem_resource, seg->res)) { | ||
327 | rc = -EBUSY; | ||
328 | kfree(seg->res); | ||
329 | goto out_shared; | ||
330 | } | ||
331 | |||
306 | if (do_nonshared) | 332 | if (do_nonshared) |
307 | dcss_command = DCSS_LOADNSR; | 333 | dcss_command = DCSS_LOADNSR; |
308 | else | 334 | else |
@@ -316,12 +342,11 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long | |||
316 | rc = dcss_diag_translate_rc (seg->end); | 342 | rc = dcss_diag_translate_rc (seg->end); |
317 | dcss_diag(DCSS_PURGESEG, seg->dcss_name, | 343 | dcss_diag(DCSS_PURGESEG, seg->dcss_name, |
318 | &seg->start_addr, &seg->end); | 344 | &seg->start_addr, &seg->end); |
319 | goto out_shared; | 345 | goto out_resource; |
320 | } | 346 | } |
321 | seg->do_nonshared = do_nonshared; | 347 | seg->do_nonshared = do_nonshared; |
322 | atomic_set(&seg->ref_count, 1); | 348 | atomic_set(&seg->ref_count, 1); |
323 | list_add(&seg->list, &dcss_list); | 349 | list_add(&seg->list, &dcss_list); |
324 | rc = seg->vm_segtype; | ||
325 | *addr = seg->start_addr; | 350 | *addr = seg->start_addr; |
326 | *end = seg->end; | 351 | *end = seg->end; |
327 | if (do_nonshared) | 352 | if (do_nonshared) |
@@ -329,12 +354,16 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long | |||
329 | "type %s in non-shared mode\n", name, | 354 | "type %s in non-shared mode\n", name, |
330 | (void*)seg->start_addr, (void*)seg->end, | 355 | (void*)seg->start_addr, (void*)seg->end, |
331 | segtype_string[seg->vm_segtype]); | 356 | segtype_string[seg->vm_segtype]); |
332 | else | 357 | else { |
333 | PRINT_INFO ("segment_load: loaded segment %s range %p .. %p " | 358 | PRINT_INFO ("segment_load: loaded segment %s range %p .. %p " |
334 | "type %s in shared mode\n", name, | 359 | "type %s in shared mode\n", name, |
335 | (void*)seg->start_addr, (void*)seg->end, | 360 | (void*)seg->start_addr, (void*)seg->end, |
336 | segtype_string[seg->vm_segtype]); | 361 | segtype_string[seg->vm_segtype]); |
362 | } | ||
337 | goto out; | 363 | goto out; |
364 | out_resource: | ||
365 | release_resource(seg->res); | ||
366 | kfree(seg->res); | ||
338 | out_shared: | 367 | out_shared: |
339 | remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1); | 368 | remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1); |
340 | out_free: | 369 | out_free: |
@@ -401,6 +430,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr, | |||
401 | * -ENOENT : no such segment (segment gone!) | 430 | * -ENOENT : no such segment (segment gone!) |
402 | * -EAGAIN : segment is in use by other exploiters, try later | 431 | * -EAGAIN : segment is in use by other exploiters, try later |
403 | * -EINVAL : no segment with the given name is currently loaded - name invalid | 432 | * -EINVAL : no segment with the given name is currently loaded - name invalid |
433 | * -EBUSY : segment can temporarily not be used (overlaps with dcss) | ||
404 | * 0 : operation succeeded | 434 | * 0 : operation succeeded |
405 | */ | 435 | */ |
406 | int | 436 | int |
@@ -428,12 +458,24 @@ segment_modify_shared (char *name, int do_nonshared) | |||
428 | rc = -EAGAIN; | 458 | rc = -EAGAIN; |
429 | goto out_unlock; | 459 | goto out_unlock; |
430 | } | 460 | } |
431 | dcss_diag(DCSS_PURGESEG, seg->dcss_name, | 461 | release_resource(seg->res); |
432 | &dummy, &dummy); | 462 | if (do_nonshared) { |
433 | if (do_nonshared) | ||
434 | dcss_command = DCSS_LOADNSR; | 463 | dcss_command = DCSS_LOADNSR; |
435 | else | 464 | seg->res->flags &= ~IORESOURCE_READONLY; |
436 | dcss_command = DCSS_LOADNOLY; | 465 | } else { |
466 | dcss_command = DCSS_LOADNOLY; | ||
467 | if (seg->vm_segtype == SEG_TYPE_SR || | ||
468 | seg->vm_segtype == SEG_TYPE_ER) | ||
469 | seg->res->flags |= IORESOURCE_READONLY; | ||
470 | } | ||
471 | if (request_resource(&iomem_resource, seg->res)) { | ||
472 | PRINT_WARN("segment_modify_shared: could not reload segment %s" | ||
473 | " - overlapping resources\n", name); | ||
474 | rc = -EBUSY; | ||
475 | kfree(seg->res); | ||
476 | goto out_del; | ||
477 | } | ||
478 | dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); | ||
437 | diag_cc = dcss_diag(dcss_command, seg->dcss_name, | 479 | diag_cc = dcss_diag(dcss_command, seg->dcss_name, |
438 | &seg->start_addr, &seg->end); | 480 | &seg->start_addr, &seg->end); |
439 | if (diag_cc > 1) { | 481 | if (diag_cc > 1) { |
@@ -446,9 +488,9 @@ segment_modify_shared (char *name, int do_nonshared) | |||
446 | rc = 0; | 488 | rc = 0; |
447 | goto out_unlock; | 489 | goto out_unlock; |
448 | out_del: | 490 | out_del: |
491 | remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1); | ||
449 | list_del(&seg->list); | 492 | list_del(&seg->list); |
450 | dcss_diag(DCSS_PURGESEG, seg->dcss_name, | 493 | dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); |
451 | &dummy, &dummy); | ||
452 | kfree(seg); | 494 | kfree(seg); |
453 | out_unlock: | 495 | out_unlock: |
454 | mutex_unlock(&dcss_lock); | 496 | mutex_unlock(&dcss_lock); |
@@ -478,6 +520,8 @@ segment_unload(char *name) | |||
478 | } | 520 | } |
479 | if (atomic_dec_return(&seg->ref_count) != 0) | 521 | if (atomic_dec_return(&seg->ref_count) != 0) |
480 | goto out_unlock; | 522 | goto out_unlock; |
523 | release_resource(seg->res); | ||
524 | kfree(seg->res); | ||
481 | remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1); | 525 | remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1); |
482 | list_del(&seg->list); | 526 | list_del(&seg->list); |
483 | dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); | 527 | dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); |
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index be9b05347b4f..bd1b66a54c21 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
@@ -230,7 +230,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch | |||
230 | SEGMENT_SHARED); | 230 | SEGMENT_SHARED); |
231 | if (rc < 0) { | 231 | if (rc < 0) { |
232 | BUG_ON(rc == -EINVAL); | 232 | BUG_ON(rc == -EINVAL); |
233 | if (rc == -EIO || rc == -ENOENT) | 233 | if (rc != -EAGAIN) |
234 | goto removeseg; | 234 | goto removeseg; |
235 | } else { | 235 | } else { |
236 | dev_info->is_shared = 1; | 236 | dev_info->is_shared = 1; |
@@ -253,7 +253,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch | |||
253 | SEGMENT_EXCLUSIVE); | 253 | SEGMENT_EXCLUSIVE); |
254 | if (rc < 0) { | 254 | if (rc < 0) { |
255 | BUG_ON(rc == -EINVAL); | 255 | BUG_ON(rc == -EINVAL); |
256 | if (rc == -EIO || rc == -ENOENT) | 256 | if (rc != -EAGAIN) |
257 | goto removeseg; | 257 | goto removeseg; |
258 | } else { | 258 | } else { |
259 | dev_info->is_shared = 0; | 259 | dev_info->is_shared = 0; |