diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/hypfs/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/hypfs/hypfs.h | 33 | ||||
-rw-r--r-- | arch/s390/hypfs/hypfs_dbfs.c | 116 | ||||
-rw-r--r-- | arch/s390/hypfs/hypfs_diag.c | 82 | ||||
-rw-r--r-- | arch/s390/hypfs/hypfs_vm.c | 62 | ||||
-rw-r--r-- | arch/s390/hypfs/inode.c | 18 |
6 files changed, 195 insertions, 118 deletions
diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile index b08d2abf6178..2e671d5004ca 100644 --- a/arch/s390/hypfs/Makefile +++ b/arch/s390/hypfs/Makefile | |||
@@ -4,4 +4,4 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o | 5 | obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o |
6 | 6 | ||
7 | s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o | 7 | s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o hypfs_dbfs.o |
diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h index fa487d4cc08b..80c1526f2af3 100644 --- a/arch/s390/hypfs/hypfs.h +++ b/arch/s390/hypfs/hypfs.h | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/debugfs.h> | 14 | #include <linux/debugfs.h> |
15 | #include <linux/workqueue.h> | ||
16 | #include <linux/kref.h> | ||
15 | 17 | ||
16 | #define REG_FILE_MODE 0440 | 18 | #define REG_FILE_MODE 0440 |
17 | #define UPDATE_FILE_MODE 0220 | 19 | #define UPDATE_FILE_MODE 0220 |
@@ -38,6 +40,33 @@ extern int hypfs_vm_init(void); | |||
38 | extern void hypfs_vm_exit(void); | 40 | extern void hypfs_vm_exit(void); |
39 | extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root); | 41 | extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root); |
40 | 42 | ||
41 | /* Directory for debugfs files */ | 43 | /* debugfs interface */ |
42 | extern struct dentry *hypfs_dbfs_dir; | 44 | struct hypfs_dbfs_file; |
45 | |||
46 | struct hypfs_dbfs_data { | ||
47 | void *buf; | ||
48 | void *buf_free_ptr; | ||
49 | size_t size; | ||
50 | struct hypfs_dbfs_file *dbfs_file;; | ||
51 | struct kref kref; | ||
52 | }; | ||
53 | |||
54 | struct hypfs_dbfs_file { | ||
55 | const char *name; | ||
56 | int (*data_create)(void **data, void **data_free_ptr, | ||
57 | size_t *size); | ||
58 | void (*data_free)(const void *buf_free_ptr); | ||
59 | |||
60 | /* Private data for hypfs_dbfs.c */ | ||
61 | struct hypfs_dbfs_data *data; | ||
62 | struct delayed_work data_free_work; | ||
63 | struct mutex lock; | ||
64 | struct dentry *dentry; | ||
65 | }; | ||
66 | |||
67 | extern int hypfs_dbfs_init(void); | ||
68 | extern void hypfs_dbfs_exit(void); | ||
69 | extern int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df); | ||
70 | extern void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df); | ||
71 | |||
43 | #endif /* _HYPFS_H_ */ | 72 | #endif /* _HYPFS_H_ */ |
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c new file mode 100644 index 000000000000..b478013b7fec --- /dev/null +++ b/arch/s390/hypfs/hypfs_dbfs.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Hypervisor filesystem for Linux on s390 - debugfs interface | ||
3 | * | ||
4 | * Copyright (C) IBM Corp. 2010 | ||
5 | * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/slab.h> | ||
9 | #include "hypfs.h" | ||
10 | |||
11 | static struct dentry *dbfs_dir; | ||
12 | |||
13 | static struct hypfs_dbfs_data *hypfs_dbfs_data_alloc(struct hypfs_dbfs_file *f) | ||
14 | { | ||
15 | struct hypfs_dbfs_data *data; | ||
16 | |||
17 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
18 | if (!data) | ||
19 | return NULL; | ||
20 | kref_init(&data->kref); | ||
21 | data->dbfs_file = f; | ||
22 | return data; | ||
23 | } | ||
24 | |||
25 | static void hypfs_dbfs_data_free(struct kref *kref) | ||
26 | { | ||
27 | struct hypfs_dbfs_data *data; | ||
28 | |||
29 | data = container_of(kref, struct hypfs_dbfs_data, kref); | ||
30 | data->dbfs_file->data_free(data->buf_free_ptr); | ||
31 | kfree(data); | ||
32 | } | ||
33 | |||
34 | static void data_free_delayed(struct work_struct *work) | ||
35 | { | ||
36 | struct hypfs_dbfs_data *data; | ||
37 | struct hypfs_dbfs_file *df; | ||
38 | |||
39 | df = container_of(work, struct hypfs_dbfs_file, data_free_work.work); | ||
40 | mutex_lock(&df->lock); | ||
41 | data = df->data; | ||
42 | df->data = NULL; | ||
43 | mutex_unlock(&df->lock); | ||
44 | kref_put(&data->kref, hypfs_dbfs_data_free); | ||
45 | } | ||
46 | |||
47 | static ssize_t dbfs_read(struct file *file, char __user *buf, | ||
48 | size_t size, loff_t *ppos) | ||
49 | { | ||
50 | struct hypfs_dbfs_data *data; | ||
51 | struct hypfs_dbfs_file *df; | ||
52 | ssize_t rc; | ||
53 | |||
54 | if (*ppos != 0) | ||
55 | return 0; | ||
56 | |||
57 | df = file->f_path.dentry->d_inode->i_private; | ||
58 | mutex_lock(&df->lock); | ||
59 | if (!df->data) { | ||
60 | data = hypfs_dbfs_data_alloc(df); | ||
61 | if (!data) { | ||
62 | mutex_unlock(&df->lock); | ||
63 | return -ENOMEM; | ||
64 | } | ||
65 | rc = df->data_create(&data->buf, &data->buf_free_ptr, | ||
66 | &data->size); | ||
67 | if (rc) { | ||
68 | mutex_unlock(&df->lock); | ||
69 | kfree(data); | ||
70 | return rc; | ||
71 | } | ||
72 | df->data = data; | ||
73 | schedule_delayed_work(&df->data_free_work, HZ); | ||
74 | } | ||
75 | data = df->data; | ||
76 | kref_get(&data->kref); | ||
77 | mutex_unlock(&df->lock); | ||
78 | |||
79 | rc = simple_read_from_buffer(buf, size, ppos, data->buf, data->size); | ||
80 | kref_put(&data->kref, hypfs_dbfs_data_free); | ||
81 | return rc; | ||
82 | } | ||
83 | |||
84 | static const struct file_operations dbfs_ops = { | ||
85 | .read = dbfs_read, | ||
86 | .llseek = no_llseek, | ||
87 | }; | ||
88 | |||
89 | int hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) | ||
90 | { | ||
91 | df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, | ||
92 | &dbfs_ops); | ||
93 | if (IS_ERR(df->dentry)) | ||
94 | return PTR_ERR(df->dentry); | ||
95 | mutex_init(&df->lock); | ||
96 | INIT_DELAYED_WORK(&df->data_free_work, data_free_delayed); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df) | ||
101 | { | ||
102 | debugfs_remove(df->dentry); | ||
103 | } | ||
104 | |||
105 | int hypfs_dbfs_init(void) | ||
106 | { | ||
107 | dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); | ||
108 | if (IS_ERR(dbfs_dir)) | ||
109 | return PTR_ERR(dbfs_dir); | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | void hypfs_dbfs_exit(void) | ||
114 | { | ||
115 | debugfs_remove(dbfs_dir); | ||
116 | } | ||
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index cd4a81be9cf8..6023c6dc1fb7 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c | |||
@@ -555,81 +555,38 @@ struct dbfs_d204 { | |||
555 | char buf[]; /* d204 buffer */ | 555 | char buf[]; /* d204 buffer */ |
556 | } __attribute__ ((packed)); | 556 | } __attribute__ ((packed)); |
557 | 557 | ||
558 | struct dbfs_d204_private { | 558 | static int dbfs_d204_create(void **data, void **data_free_ptr, size_t *size) |
559 | struct dbfs_d204 *d204; /* Aligned d204 data with header */ | ||
560 | void *base; /* Base pointer (needed for vfree) */ | ||
561 | }; | ||
562 | |||
563 | static int dbfs_d204_open(struct inode *inode, struct file *file) | ||
564 | { | 559 | { |
565 | struct dbfs_d204_private *data; | ||
566 | struct dbfs_d204 *d204; | 560 | struct dbfs_d204 *d204; |
567 | int rc, buf_size; | 561 | int rc, buf_size; |
562 | void *base; | ||
568 | 563 | ||
569 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
570 | if (!data) | ||
571 | return -ENOMEM; | ||
572 | buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr); | 564 | buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr); |
573 | data->base = vmalloc(buf_size); | 565 | base = vmalloc(buf_size); |
574 | if (!data->base) { | 566 | if (!base) |
575 | rc = -ENOMEM; | 567 | return -ENOMEM; |
576 | goto fail_kfree_data; | 568 | memset(base, 0, buf_size); |
569 | d204 = page_align_ptr(base + sizeof(d204->hdr)) - sizeof(d204->hdr); | ||
570 | rc = diag204_do_store(d204->buf, diag204_buf_pages); | ||
571 | if (rc) { | ||
572 | vfree(base); | ||
573 | return rc; | ||
577 | } | 574 | } |
578 | memset(data->base, 0, buf_size); | ||
579 | d204 = page_align_ptr(data->base + sizeof(d204->hdr)) | ||
580 | - sizeof(d204->hdr); | ||
581 | rc = diag204_do_store(&d204->buf, diag204_buf_pages); | ||
582 | if (rc) | ||
583 | goto fail_vfree_base; | ||
584 | d204->hdr.version = DBFS_D204_HDR_VERSION; | 575 | d204->hdr.version = DBFS_D204_HDR_VERSION; |
585 | d204->hdr.len = PAGE_SIZE * diag204_buf_pages; | 576 | d204->hdr.len = PAGE_SIZE * diag204_buf_pages; |
586 | d204->hdr.sc = diag204_store_sc; | 577 | d204->hdr.sc = diag204_store_sc; |
587 | data->d204 = d204; | 578 | *data = d204; |
588 | file->private_data = data; | 579 | *data_free_ptr = base; |
589 | return nonseekable_open(inode, file); | 580 | *size = d204->hdr.len + sizeof(struct dbfs_d204_hdr); |
590 | |||
591 | fail_vfree_base: | ||
592 | vfree(data->base); | ||
593 | fail_kfree_data: | ||
594 | kfree(data); | ||
595 | return rc; | ||
596 | } | ||
597 | |||
598 | static int dbfs_d204_release(struct inode *inode, struct file *file) | ||
599 | { | ||
600 | struct dbfs_d204_private *data = file->private_data; | ||
601 | |||
602 | vfree(data->base); | ||
603 | kfree(data); | ||
604 | return 0; | 581 | return 0; |
605 | } | 582 | } |
606 | 583 | ||
607 | static ssize_t dbfs_d204_read(struct file *file, char __user *buf, | 584 | static struct hypfs_dbfs_file dbfs_file_d204 = { |
608 | size_t size, loff_t *ppos) | 585 | .name = "diag_204", |
609 | { | 586 | .data_create = dbfs_d204_create, |
610 | struct dbfs_d204_private *data = file->private_data; | 587 | .data_free = vfree, |
611 | |||
612 | return simple_read_from_buffer(buf, size, ppos, data->d204, | ||
613 | data->d204->hdr.len + | ||
614 | sizeof(data->d204->hdr)); | ||
615 | } | ||
616 | |||
617 | static const struct file_operations dbfs_d204_ops = { | ||
618 | .open = dbfs_d204_open, | ||
619 | .read = dbfs_d204_read, | ||
620 | .release = dbfs_d204_release, | ||
621 | .llseek = no_llseek, | ||
622 | }; | 588 | }; |
623 | 589 | ||
624 | static int hypfs_dbfs_init(void) | ||
625 | { | ||
626 | dbfs_d204_file = debugfs_create_file("diag_204", 0400, hypfs_dbfs_dir, | ||
627 | NULL, &dbfs_d204_ops); | ||
628 | if (IS_ERR(dbfs_d204_file)) | ||
629 | return PTR_ERR(dbfs_d204_file); | ||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | __init int hypfs_diag_init(void) | 590 | __init int hypfs_diag_init(void) |
634 | { | 591 | { |
635 | int rc; | 592 | int rc; |
@@ -639,7 +596,7 @@ __init int hypfs_diag_init(void) | |||
639 | return -ENODATA; | 596 | return -ENODATA; |
640 | } | 597 | } |
641 | if (diag204_info_type == INFO_EXT) { | 598 | if (diag204_info_type == INFO_EXT) { |
642 | rc = hypfs_dbfs_init(); | 599 | rc = hypfs_dbfs_create_file(&dbfs_file_d204); |
643 | if (rc) | 600 | if (rc) |
644 | return rc; | 601 | return rc; |
645 | } | 602 | } |
@@ -660,6 +617,7 @@ void hypfs_diag_exit(void) | |||
660 | debugfs_remove(dbfs_d204_file); | 617 | debugfs_remove(dbfs_d204_file); |
661 | diag224_delete_name_table(); | 618 | diag224_delete_name_table(); |
662 | diag204_free_buffer(); | 619 | diag204_free_buffer(); |
620 | hypfs_dbfs_remove_file(&dbfs_file_d204); | ||
663 | } | 621 | } |
664 | 622 | ||
665 | /* | 623 | /* |
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c index 26cf177f6a3a..e54796002f61 100644 --- a/arch/s390/hypfs/hypfs_vm.c +++ b/arch/s390/hypfs/hypfs_vm.c | |||
@@ -20,8 +20,6 @@ static char local_guest[] = " "; | |||
20 | static char all_guests[] = "* "; | 20 | static char all_guests[] = "* "; |
21 | static char *guest_query; | 21 | static char *guest_query; |
22 | 22 | ||
23 | static struct dentry *dbfs_d2fc_file; | ||
24 | |||
25 | struct diag2fc_data { | 23 | struct diag2fc_data { |
26 | __u32 version; | 24 | __u32 version; |
27 | __u32 flags; | 25 | __u32 flags; |
@@ -104,7 +102,7 @@ static void *diag2fc_store(char *query, unsigned int *count, int offset) | |||
104 | return data; | 102 | return data; |
105 | } | 103 | } |
106 | 104 | ||
107 | static void diag2fc_free(void *data) | 105 | static void diag2fc_free(const void *data) |
108 | { | 106 | { |
109 | vfree(data); | 107 | vfree(data); |
110 | } | 108 | } |
@@ -239,43 +237,29 @@ struct dbfs_d2fc { | |||
239 | char buf[]; /* d2fc buffer */ | 237 | char buf[]; /* d2fc buffer */ |
240 | } __attribute__ ((packed)); | 238 | } __attribute__ ((packed)); |
241 | 239 | ||
242 | static int dbfs_d2fc_open(struct inode *inode, struct file *file) | 240 | static int dbfs_diag2fc_create(void **data, void **data_free_ptr, size_t *size) |
243 | { | 241 | { |
244 | struct dbfs_d2fc *data; | 242 | struct dbfs_d2fc *d2fc; |
245 | unsigned int count; | 243 | unsigned int count; |
246 | 244 | ||
247 | data = diag2fc_store(guest_query, &count, sizeof(data->hdr)); | 245 | d2fc = diag2fc_store(guest_query, &count, sizeof(d2fc->hdr)); |
248 | if (IS_ERR(data)) | 246 | if (IS_ERR(d2fc)) |
249 | return PTR_ERR(data); | 247 | return PTR_ERR(d2fc); |
250 | get_clock_ext(data->hdr.tod_ext); | 248 | get_clock_ext(d2fc->hdr.tod_ext); |
251 | data->hdr.len = count * sizeof(struct diag2fc_data); | 249 | d2fc->hdr.len = count * sizeof(struct diag2fc_data); |
252 | data->hdr.version = DBFS_D2FC_HDR_VERSION; | 250 | d2fc->hdr.version = DBFS_D2FC_HDR_VERSION; |
253 | data->hdr.count = count; | 251 | d2fc->hdr.count = count; |
254 | memset(&data->hdr.reserved, 0, sizeof(data->hdr.reserved)); | 252 | memset(&d2fc->hdr.reserved, 0, sizeof(d2fc->hdr.reserved)); |
255 | file->private_data = data; | 253 | *data = d2fc; |
256 | return nonseekable_open(inode, file); | 254 | *data_free_ptr = d2fc; |
257 | } | 255 | *size = d2fc->hdr.len + sizeof(struct dbfs_d2fc_hdr); |
258 | |||
259 | static int dbfs_d2fc_release(struct inode *inode, struct file *file) | ||
260 | { | ||
261 | diag2fc_free(file->private_data); | ||
262 | return 0; | 256 | return 0; |
263 | } | 257 | } |
264 | 258 | ||
265 | static ssize_t dbfs_d2fc_read(struct file *file, char __user *buf, | 259 | static struct hypfs_dbfs_file dbfs_file_2fc = { |
266 | size_t size, loff_t *ppos) | 260 | .name = "diag_2fc", |
267 | { | 261 | .data_create = dbfs_diag2fc_create, |
268 | struct dbfs_d2fc *data = file->private_data; | 262 | .data_free = diag2fc_free, |
269 | |||
270 | return simple_read_from_buffer(buf, size, ppos, data, data->hdr.len + | ||
271 | sizeof(struct dbfs_d2fc_hdr)); | ||
272 | } | ||
273 | |||
274 | static const struct file_operations dbfs_d2fc_ops = { | ||
275 | .open = dbfs_d2fc_open, | ||
276 | .read = dbfs_d2fc_read, | ||
277 | .release = dbfs_d2fc_release, | ||
278 | .llseek = no_llseek, | ||
279 | }; | 263 | }; |
280 | 264 | ||
281 | int hypfs_vm_init(void) | 265 | int hypfs_vm_init(void) |
@@ -288,18 +272,12 @@ int hypfs_vm_init(void) | |||
288 | guest_query = local_guest; | 272 | guest_query = local_guest; |
289 | else | 273 | else |
290 | return -EACCES; | 274 | return -EACCES; |
291 | 275 | return hypfs_dbfs_create_file(&dbfs_file_2fc); | |
292 | dbfs_d2fc_file = debugfs_create_file("diag_2fc", 0400, hypfs_dbfs_dir, | ||
293 | NULL, &dbfs_d2fc_ops); | ||
294 | if (IS_ERR(dbfs_d2fc_file)) | ||
295 | return PTR_ERR(dbfs_d2fc_file); | ||
296 | |||
297 | return 0; | ||
298 | } | 276 | } |
299 | 277 | ||
300 | void hypfs_vm_exit(void) | 278 | void hypfs_vm_exit(void) |
301 | { | 279 | { |
302 | if (!MACHINE_IS_VM) | 280 | if (!MACHINE_IS_VM) |
303 | return; | 281 | return; |
304 | debugfs_remove(dbfs_d2fc_file); | 282 | hypfs_dbfs_remove_file(&dbfs_file_2fc); |
305 | } | 283 | } |
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index 47cc446dab8f..6fe874fc5f8e 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c | |||
@@ -46,8 +46,6 @@ static const struct super_operations hypfs_s_ops; | |||
46 | /* start of list of all dentries, which have to be deleted on update */ | 46 | /* start of list of all dentries, which have to be deleted on update */ |
47 | static struct dentry *hypfs_last_dentry; | 47 | static struct dentry *hypfs_last_dentry; |
48 | 48 | ||
49 | struct dentry *hypfs_dbfs_dir; | ||
50 | |||
51 | static void hypfs_update_update(struct super_block *sb) | 49 | static void hypfs_update_update(struct super_block *sb) |
52 | { | 50 | { |
53 | struct hypfs_sb_info *sb_info = sb->s_fs_info; | 51 | struct hypfs_sb_info *sb_info = sb->s_fs_info; |
@@ -471,13 +469,12 @@ static int __init hypfs_init(void) | |||
471 | { | 469 | { |
472 | int rc; | 470 | int rc; |
473 | 471 | ||
474 | hypfs_dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); | 472 | rc = hypfs_dbfs_init(); |
475 | if (IS_ERR(hypfs_dbfs_dir)) | 473 | if (rc) |
476 | return PTR_ERR(hypfs_dbfs_dir); | 474 | return rc; |
477 | |||
478 | if (hypfs_diag_init()) { | 475 | if (hypfs_diag_init()) { |
479 | rc = -ENODATA; | 476 | rc = -ENODATA; |
480 | goto fail_debugfs_remove; | 477 | goto fail_dbfs_exit; |
481 | } | 478 | } |
482 | if (hypfs_vm_init()) { | 479 | if (hypfs_vm_init()) { |
483 | rc = -ENODATA; | 480 | rc = -ENODATA; |
@@ -499,9 +496,8 @@ fail_hypfs_vm_exit: | |||
499 | hypfs_vm_exit(); | 496 | hypfs_vm_exit(); |
500 | fail_hypfs_diag_exit: | 497 | fail_hypfs_diag_exit: |
501 | hypfs_diag_exit(); | 498 | hypfs_diag_exit(); |
502 | fail_debugfs_remove: | 499 | fail_dbfs_exit: |
503 | debugfs_remove(hypfs_dbfs_dir); | 500 | hypfs_dbfs_exit(); |
504 | |||
505 | pr_err("Initialization of hypfs failed with rc=%i\n", rc); | 501 | pr_err("Initialization of hypfs failed with rc=%i\n", rc); |
506 | return rc; | 502 | return rc; |
507 | } | 503 | } |
@@ -510,7 +506,7 @@ static void __exit hypfs_exit(void) | |||
510 | { | 506 | { |
511 | hypfs_diag_exit(); | 507 | hypfs_diag_exit(); |
512 | hypfs_vm_exit(); | 508 | hypfs_vm_exit(); |
513 | debugfs_remove(hypfs_dbfs_dir); | 509 | hypfs_dbfs_exit(); |
514 | unregister_filesystem(&hypfs_type); | 510 | unregister_filesystem(&hypfs_type); |
515 | kobject_put(s390_kobj); | 511 | kobject_put(s390_kobj); |
516 | } | 512 | } |