diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-08-22 14:12:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-08-22 14:12:08 -0400 |
commit | 53ce2dc2718c57346c543dab254fc900c6fe6c65 (patch) | |
tree | 451fcbc89084b1d9b83c105294794f29bf6d59f3 | |
parent | 8b14cb9953c6b569327e9372718cff09a98f9589 (diff) | |
parent | c51b9621796c31810fb66509ea1faee4597d9c03 (diff) |
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
[S390] Change atomic_read/set to inline functions with barrier semantics.
[S390] kprobes: fix instruction length calculation
[S390] hypfs: inode corruption due to missing locking
[S390] disassembler: fix b2 opcodes like srst, bsg, and others
[S390] vmur: fix reference counting for vmur device structure
[S390] vmur: fix diag14 exceptions with addresses > 2GB.
[S390] qdio: Refresh buffer states for IQDIO Asynchronous output queue
[S390] qdio: fix EQBS handling on CCQ96
[S390] cio: change confusing message in cmf.
[S390] cio: dont forget to set last slot to NULL in ccw_uevent().
-rw-r--r-- | arch/s390/hypfs/inode.c | 33 | ||||
-rw-r--r-- | arch/s390/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kernel/diag.c | 102 | ||||
-rw-r--r-- | arch/s390/kernel/dis.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/kprobes.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/s390_ksyms.c | 1 | ||||
-rw-r--r-- | arch/s390/mm/cmm.c | 1 | ||||
-rw-r--r-- | arch/s390/mm/init.c | 17 | ||||
-rw-r--r-- | drivers/s390/block/dasd_diag.c | 1 | ||||
-rw-r--r-- | drivers/s390/char/raw3270.c | 1 | ||||
-rw-r--r-- | drivers/s390/char/vmur.c | 250 | ||||
-rw-r--r-- | drivers/s390/char/vmur.h | 1 | ||||
-rw-r--r-- | drivers/s390/cio/cmf.c | 10 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 5 | ||||
-rw-r--r-- | drivers/s390/cio/device_id.c | 48 | ||||
-rw-r--r-- | drivers/s390/cio/qdio.c | 5 | ||||
-rw-r--r-- | include/asm-s390/atomic.h | 26 | ||||
-rw-r--r-- | include/asm-s390/cio.h | 15 | ||||
-rw-r--r-- | include/asm-s390/diag.h | 39 | ||||
-rw-r--r-- | include/asm-s390/pgalloc.h | 2 |
20 files changed, 371 insertions, 192 deletions
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index ad4ca75c0f04..5245717295b8 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c | |||
@@ -60,17 +60,28 @@ static void hypfs_add_dentry(struct dentry *dentry) | |||
60 | hypfs_last_dentry = dentry; | 60 | hypfs_last_dentry = dentry; |
61 | } | 61 | } |
62 | 62 | ||
63 | static inline int hypfs_positive(struct dentry *dentry) | ||
64 | { | ||
65 | return dentry->d_inode && !d_unhashed(dentry); | ||
66 | } | ||
67 | |||
63 | static void hypfs_remove(struct dentry *dentry) | 68 | static void hypfs_remove(struct dentry *dentry) |
64 | { | 69 | { |
65 | struct dentry *parent; | 70 | struct dentry *parent; |
66 | 71 | ||
67 | parent = dentry->d_parent; | 72 | parent = dentry->d_parent; |
68 | if (S_ISDIR(dentry->d_inode->i_mode)) | 73 | if (!parent || !parent->d_inode) |
69 | simple_rmdir(parent->d_inode, dentry); | 74 | return; |
70 | else | 75 | mutex_lock(&parent->d_inode->i_mutex); |
71 | simple_unlink(parent->d_inode, dentry); | 76 | if (hypfs_positive(dentry)) { |
77 | if (S_ISDIR(dentry->d_inode->i_mode)) | ||
78 | simple_rmdir(parent->d_inode, dentry); | ||
79 | else | ||
80 | simple_unlink(parent->d_inode, dentry); | ||
81 | } | ||
72 | d_delete(dentry); | 82 | d_delete(dentry); |
73 | dput(dentry); | 83 | dput(dentry); |
84 | mutex_unlock(&parent->d_inode->i_mutex); | ||
74 | } | 85 | } |
75 | 86 | ||
76 | static void hypfs_delete_tree(struct dentry *root) | 87 | static void hypfs_delete_tree(struct dentry *root) |
@@ -315,6 +326,7 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent) | |||
315 | } | 326 | } |
316 | hypfs_update_update(sb); | 327 | hypfs_update_update(sb); |
317 | sb->s_root = root_dentry; | 328 | sb->s_root = root_dentry; |
329 | printk(KERN_INFO "hypfs: Hypervisor filesystem mounted\n"); | ||
318 | return 0; | 330 | return 0; |
319 | 331 | ||
320 | err_tree: | 332 | err_tree: |
@@ -356,13 +368,17 @@ static struct dentry *hypfs_create_file(struct super_block *sb, | |||
356 | qname.name = name; | 368 | qname.name = name; |
357 | qname.len = strlen(name); | 369 | qname.len = strlen(name); |
358 | qname.hash = full_name_hash(name, qname.len); | 370 | qname.hash = full_name_hash(name, qname.len); |
371 | mutex_lock(&parent->d_inode->i_mutex); | ||
359 | dentry = lookup_one_len(name, parent, strlen(name)); | 372 | dentry = lookup_one_len(name, parent, strlen(name)); |
360 | if (IS_ERR(dentry)) | 373 | if (IS_ERR(dentry)) { |
361 | return ERR_PTR(-ENOMEM); | 374 | dentry = ERR_PTR(-ENOMEM); |
375 | goto fail; | ||
376 | } | ||
362 | inode = hypfs_make_inode(sb, mode); | 377 | inode = hypfs_make_inode(sb, mode); |
363 | if (!inode) { | 378 | if (!inode) { |
364 | dput(dentry); | 379 | dput(dentry); |
365 | return ERR_PTR(-ENOMEM); | 380 | dentry = ERR_PTR(-ENOMEM); |
381 | goto fail; | ||
366 | } | 382 | } |
367 | if (mode & S_IFREG) { | 383 | if (mode & S_IFREG) { |
368 | inode->i_fop = &hypfs_file_ops; | 384 | inode->i_fop = &hypfs_file_ops; |
@@ -379,6 +395,8 @@ static struct dentry *hypfs_create_file(struct super_block *sb, | |||
379 | inode->i_private = data; | 395 | inode->i_private = data; |
380 | d_instantiate(dentry, inode); | 396 | d_instantiate(dentry, inode); |
381 | dget(dentry); | 397 | dget(dentry); |
398 | fail: | ||
399 | mutex_unlock(&parent->d_inode->i_mutex); | ||
382 | return dentry; | 400 | return dentry; |
383 | } | 401 | } |
384 | 402 | ||
@@ -391,7 +409,6 @@ struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent, | |||
391 | if (IS_ERR(dentry)) | 409 | if (IS_ERR(dentry)) |
392 | return dentry; | 410 | return dentry; |
393 | hypfs_add_dentry(dentry); | 411 | hypfs_add_dentry(dentry); |
394 | parent->d_inode->i_nlink++; | ||
395 | return dentry; | 412 | return dentry; |
396 | } | 413 | } |
397 | 414 | ||
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 3195d375bd51..56cb71007cd9 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional | |||
6 | 6 | ||
7 | obj-y := bitmap.o traps.o time.o process.o base.o early.o \ | 7 | obj-y := bitmap.o traps.o time.o process.o base.o early.o \ |
8 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ | 8 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ |
9 | semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o | 9 | semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o diag.o |
10 | 10 | ||
11 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) | 11 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) |
12 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) | 12 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) |
diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c new file mode 100644 index 000000000000..c032d11da8a1 --- /dev/null +++ b/arch/s390/kernel/diag.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * Implementation of s390 diagnose codes | ||
3 | * | ||
4 | * Copyright IBM Corp. 2007 | ||
5 | * Author(s): Michael Holzheu <holzheu@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <asm/diag.h> | ||
10 | |||
11 | /* | ||
12 | * Diagnose 10: Release pages | ||
13 | */ | ||
14 | void diag10(unsigned long addr) | ||
15 | { | ||
16 | if (addr >= 0x7ff00000) | ||
17 | return; | ||
18 | asm volatile( | ||
19 | #ifdef CONFIG_64BIT | ||
20 | " sam31\n" | ||
21 | " diag %0,%0,0x10\n" | ||
22 | "0: sam64\n" | ||
23 | #else | ||
24 | " diag %0,%0,0x10\n" | ||
25 | "0:\n" | ||
26 | #endif | ||
27 | EX_TABLE(0b, 0b) | ||
28 | : : "a" (addr)); | ||
29 | } | ||
30 | EXPORT_SYMBOL(diag10); | ||
31 | |||
32 | /* | ||
33 | * Diagnose 14: Input spool file manipulation | ||
34 | */ | ||
35 | int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode) | ||
36 | { | ||
37 | register unsigned long _ry1 asm("2") = ry1; | ||
38 | register unsigned long _ry2 asm("3") = subcode; | ||
39 | int rc = 0; | ||
40 | |||
41 | asm volatile( | ||
42 | #ifdef CONFIG_64BIT | ||
43 | " sam31\n" | ||
44 | " diag %2,2,0x14\n" | ||
45 | " sam64\n" | ||
46 | #else | ||
47 | " diag %2,2,0x14\n" | ||
48 | #endif | ||
49 | " ipm %0\n" | ||
50 | " srl %0,28\n" | ||
51 | : "=d" (rc), "+d" (_ry2) | ||
52 | : "d" (rx), "d" (_ry1) | ||
53 | : "cc"); | ||
54 | |||
55 | return rc; | ||
56 | } | ||
57 | EXPORT_SYMBOL(diag14); | ||
58 | |||
59 | /* | ||
60 | * Diagnose 210: Get information about a virtual device | ||
61 | */ | ||
62 | int diag210(struct diag210 *addr) | ||
63 | { | ||
64 | /* | ||
65 | * diag 210 needs its data below the 2GB border, so we | ||
66 | * use a static data area to be sure | ||
67 | */ | ||
68 | static struct diag210 diag210_tmp; | ||
69 | static DEFINE_SPINLOCK(diag210_lock); | ||
70 | unsigned long flags; | ||
71 | int ccode; | ||
72 | |||
73 | spin_lock_irqsave(&diag210_lock, flags); | ||
74 | diag210_tmp = *addr; | ||
75 | |||
76 | #ifdef CONFIG_64BIT | ||
77 | asm volatile( | ||
78 | " lhi %0,-1\n" | ||
79 | " sam31\n" | ||
80 | " diag %1,0,0x210\n" | ||
81 | "0: ipm %0\n" | ||
82 | " srl %0,28\n" | ||
83 | "1: sam64\n" | ||
84 | EX_TABLE(0b, 1b) | ||
85 | : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); | ||
86 | #else | ||
87 | asm volatile( | ||
88 | " lhi %0,-1\n" | ||
89 | " diag %1,0,0x210\n" | ||
90 | "0: ipm %0\n" | ||
91 | " srl %0,28\n" | ||
92 | "1:\n" | ||
93 | EX_TABLE(0b, 1b) | ||
94 | : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); | ||
95 | #endif | ||
96 | |||
97 | *addr = diag210_tmp; | ||
98 | spin_unlock_irqrestore(&diag210_lock, flags); | ||
99 | |||
100 | return ccode; | ||
101 | } | ||
102 | EXPORT_SYMBOL(diag210); | ||
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index d3057318f2bf..50d2235df732 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c | |||
@@ -577,7 +577,7 @@ static struct insn opcode_b2[] = { | |||
577 | { "esta", 0x4a, INSTR_RRE_RR }, | 577 | { "esta", 0x4a, INSTR_RRE_RR }, |
578 | { "lura", 0x4b, INSTR_RRE_RR }, | 578 | { "lura", 0x4b, INSTR_RRE_RR }, |
579 | { "tar", 0x4c, INSTR_RRE_AR }, | 579 | { "tar", 0x4c, INSTR_RRE_AR }, |
580 | { "cpya", INSTR_RRE_AA }, | 580 | { "cpya", 0x4d, INSTR_RRE_AA }, |
581 | { "sar", 0x4e, INSTR_RRE_AR }, | 581 | { "sar", 0x4e, INSTR_RRE_AR }, |
582 | { "ear", 0x4f, INSTR_RRE_RA }, | 582 | { "ear", 0x4f, INSTR_RRE_RA }, |
583 | { "csp", 0x50, INSTR_RRE_RR }, | 583 | { "csp", 0x50, INSTR_RRE_RR }, |
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 358d2bbbc481..e40373d9fbce 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -85,7 +85,7 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn) | |||
85 | ainsn->reg = (*ainsn->insn & 0xf0) >> 4; | 85 | ainsn->reg = (*ainsn->insn & 0xf0) >> 4; |
86 | 86 | ||
87 | /* save the instruction length (pop 5-5) in bytes */ | 87 | /* save the instruction length (pop 5-5) in bytes */ |
88 | switch (*(__u8 *) (ainsn->insn) >> 4) { | 88 | switch (*(__u8 *) (ainsn->insn) >> 6) { |
89 | case 0: | 89 | case 0: |
90 | ainsn->ilen = 2; | 90 | ainsn->ilen = 2; |
91 | break; | 91 | break; |
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 90b5ef529eb7..7234c737f825 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c | |||
@@ -25,7 +25,6 @@ EXPORT_SYMBOL(_oi_bitmap); | |||
25 | EXPORT_SYMBOL(_ni_bitmap); | 25 | EXPORT_SYMBOL(_ni_bitmap); |
26 | EXPORT_SYMBOL(_zb_findmap); | 26 | EXPORT_SYMBOL(_zb_findmap); |
27 | EXPORT_SYMBOL(_sb_findmap); | 27 | EXPORT_SYMBOL(_sb_findmap); |
28 | EXPORT_SYMBOL(diag10); | ||
29 | 28 | ||
30 | /* | 29 | /* |
31 | * semaphore ops | 30 | * semaphore ops |
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index c5b2f4f078bc..fabc50adc46a 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <asm/pgalloc.h> | 21 | #include <asm/pgalloc.h> |
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | #include <asm/diag.h> | ||
23 | 24 | ||
24 | static char *sender = "VMRMSVM"; | 25 | static char *sender = "VMRMSVM"; |
25 | module_param(sender, charp, 0400); | 26 | module_param(sender, charp, 0400); |
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 9098531a2671..3a25bbf2eb0a 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
@@ -42,23 +42,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | |||
42 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); | 42 | pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); |
43 | char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); | 43 | char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); |
44 | 44 | ||
45 | void diag10(unsigned long addr) | ||
46 | { | ||
47 | if (addr >= 0x7ff00000) | ||
48 | return; | ||
49 | asm volatile( | ||
50 | #ifdef CONFIG_64BIT | ||
51 | " sam31\n" | ||
52 | " diag %0,%0,0x10\n" | ||
53 | "0: sam64\n" | ||
54 | #else | ||
55 | " diag %0,%0,0x10\n" | ||
56 | "0:\n" | ||
57 | #endif | ||
58 | EX_TABLE(0b,0b) | ||
59 | : : "a" (addr)); | ||
60 | } | ||
61 | |||
62 | void show_mem(void) | 45 | void show_mem(void) |
63 | { | 46 | { |
64 | int i, total = 0, reserved = 0; | 47 | int i, total = 0, reserved = 0; |
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index eccac1c3b71b..d32c60dbdd82 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/s390_ext.h> | 24 | #include <asm/s390_ext.h> |
25 | #include <asm/todclk.h> | 25 | #include <asm/todclk.h> |
26 | #include <asm/vtoc.h> | 26 | #include <asm/vtoc.h> |
27 | #include <asm/diag.h> | ||
27 | 28 | ||
28 | #include "dasd_int.h" | 29 | #include "dasd_int.h" |
29 | #include "dasd_diag.h" | 30 | #include "dasd_diag.h" |
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 4f2f81b16cfa..2edd5fb6d3dc 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/ccwdev.h> | 21 | #include <asm/ccwdev.h> |
22 | #include <asm/cio.h> | 22 | #include <asm/cio.h> |
23 | #include <asm/ebcdic.h> | 23 | #include <asm/ebcdic.h> |
24 | #include <asm/diag.h> | ||
24 | 25 | ||
25 | #include "raw3270.h" | 26 | #include "raw3270.h" |
26 | 27 | ||
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 04b19bdc09da..d70a6e65bf14 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <asm/cio.h> | 14 | #include <asm/cio.h> |
15 | #include <asm/ccwdev.h> | 15 | #include <asm/ccwdev.h> |
16 | #include <asm/debug.h> | 16 | #include <asm/debug.h> |
17 | #include <asm/diag.h> | ||
17 | 18 | ||
18 | #include "vmur.h" | 19 | #include "vmur.h" |
19 | 20 | ||
@@ -68,8 +69,26 @@ static struct ccw_driver ur_driver = { | |||
68 | .set_offline = ur_set_offline, | 69 | .set_offline = ur_set_offline, |
69 | }; | 70 | }; |
70 | 71 | ||
72 | static DEFINE_MUTEX(vmur_mutex); | ||
73 | |||
71 | /* | 74 | /* |
72 | * Allocation, freeing, getting and putting of urdev structures | 75 | * Allocation, freeing, getting and putting of urdev structures |
76 | * | ||
77 | * Each ur device (urd) contains a reference to its corresponding ccw device | ||
78 | * (cdev) using the urd->cdev pointer. Each ccw device has a reference to the | ||
79 | * ur device using the cdev->dev.driver_data pointer. | ||
80 | * | ||
81 | * urd references: | ||
82 | * - ur_probe gets a urd reference, ur_remove drops the reference | ||
83 | * (cdev->dev.driver_data) | ||
84 | * - ur_open gets a urd reference, ur_relase drops the reference | ||
85 | * (urf->urd) | ||
86 | * | ||
87 | * cdev references: | ||
88 | * - urdev_alloc get a cdev reference (urd->cdev) | ||
89 | * - urdev_free drops the cdev reference (urd->cdev) | ||
90 | * | ||
91 | * Setting and clearing of cdev->dev.driver_data is protected by the ccwdev lock | ||
73 | */ | 92 | */ |
74 | static struct urdev *urdev_alloc(struct ccw_device *cdev) | 93 | static struct urdev *urdev_alloc(struct ccw_device *cdev) |
75 | { | 94 | { |
@@ -78,42 +97,61 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev) | |||
78 | urd = kzalloc(sizeof(struct urdev), GFP_KERNEL); | 97 | urd = kzalloc(sizeof(struct urdev), GFP_KERNEL); |
79 | if (!urd) | 98 | if (!urd) |
80 | return NULL; | 99 | return NULL; |
81 | urd->cdev = cdev; | ||
82 | urd->reclen = cdev->id.driver_info; | 100 | urd->reclen = cdev->id.driver_info; |
83 | ccw_device_get_id(cdev, &urd->dev_id); | 101 | ccw_device_get_id(cdev, &urd->dev_id); |
84 | mutex_init(&urd->io_mutex); | 102 | mutex_init(&urd->io_mutex); |
85 | mutex_init(&urd->open_mutex); | 103 | mutex_init(&urd->open_mutex); |
104 | atomic_set(&urd->ref_count, 1); | ||
105 | urd->cdev = cdev; | ||
106 | get_device(&cdev->dev); | ||
86 | return urd; | 107 | return urd; |
87 | } | 108 | } |
88 | 109 | ||
89 | static void urdev_free(struct urdev *urd) | 110 | static void urdev_free(struct urdev *urd) |
90 | { | 111 | { |
112 | TRACE("urdev_free: %p\n", urd); | ||
113 | if (urd->cdev) | ||
114 | put_device(&urd->cdev->dev); | ||
91 | kfree(urd); | 115 | kfree(urd); |
92 | } | 116 | } |
93 | 117 | ||
94 | /* | 118 | static void urdev_get(struct urdev *urd) |
95 | * This is how the character device driver gets a reference to a | 119 | { |
96 | * ur device. When this call returns successfully, a reference has | 120 | atomic_inc(&urd->ref_count); |
97 | * been taken (by get_device) on the underlying kobject. The recipient | 121 | } |
98 | * of this urdev pointer must eventually drop it with urdev_put(urd) | 122 | |
99 | * which does the corresponding put_device(). | 123 | static struct urdev *urdev_get_from_cdev(struct ccw_device *cdev) |
100 | */ | 124 | { |
125 | struct urdev *urd; | ||
126 | unsigned long flags; | ||
127 | |||
128 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | ||
129 | urd = cdev->dev.driver_data; | ||
130 | if (urd) | ||
131 | urdev_get(urd); | ||
132 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | ||
133 | return urd; | ||
134 | } | ||
135 | |||
101 | static struct urdev *urdev_get_from_devno(u16 devno) | 136 | static struct urdev *urdev_get_from_devno(u16 devno) |
102 | { | 137 | { |
103 | char bus_id[16]; | 138 | char bus_id[16]; |
104 | struct ccw_device *cdev; | 139 | struct ccw_device *cdev; |
140 | struct urdev *urd; | ||
105 | 141 | ||
106 | sprintf(bus_id, "0.0.%04x", devno); | 142 | sprintf(bus_id, "0.0.%04x", devno); |
107 | cdev = get_ccwdev_by_busid(&ur_driver, bus_id); | 143 | cdev = get_ccwdev_by_busid(&ur_driver, bus_id); |
108 | if (!cdev) | 144 | if (!cdev) |
109 | return NULL; | 145 | return NULL; |
110 | 146 | urd = urdev_get_from_cdev(cdev); | |
111 | return cdev->dev.driver_data; | 147 | put_device(&cdev->dev); |
148 | return urd; | ||
112 | } | 149 | } |
113 | 150 | ||
114 | static void urdev_put(struct urdev *urd) | 151 | static void urdev_put(struct urdev *urd) |
115 | { | 152 | { |
116 | put_device(&urd->cdev->dev); | 153 | if (atomic_dec_and_test(&urd->ref_count)) |
154 | urdev_free(urd); | ||
117 | } | 155 | } |
118 | 156 | ||
119 | /* | 157 | /* |
@@ -245,6 +283,7 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
245 | return; | 283 | return; |
246 | } | 284 | } |
247 | urd = cdev->dev.driver_data; | 285 | urd = cdev->dev.driver_data; |
286 | BUG_ON(!urd); | ||
248 | /* On special conditions irb is an error pointer */ | 287 | /* On special conditions irb is an error pointer */ |
249 | if (IS_ERR(irb)) | 288 | if (IS_ERR(irb)) |
250 | urd->io_request_rc = PTR_ERR(irb); | 289 | urd->io_request_rc = PTR_ERR(irb); |
@@ -262,9 +301,15 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
262 | static ssize_t ur_attr_reclen_show(struct device *dev, | 301 | static ssize_t ur_attr_reclen_show(struct device *dev, |
263 | struct device_attribute *attr, char *buf) | 302 | struct device_attribute *attr, char *buf) |
264 | { | 303 | { |
265 | struct urdev *urd = dev->driver_data; | 304 | struct urdev *urd; |
305 | int rc; | ||
266 | 306 | ||
267 | return sprintf(buf, "%zu\n", urd->reclen); | 307 | urd = urdev_get_from_cdev(to_ccwdev(dev)); |
308 | if (!urd) | ||
309 | return -ENODEV; | ||
310 | rc = sprintf(buf, "%zu\n", urd->reclen); | ||
311 | urdev_put(urd); | ||
312 | return rc; | ||
268 | } | 313 | } |
269 | 314 | ||
270 | static DEVICE_ATTR(reclen, 0444, ur_attr_reclen_show, NULL); | 315 | static DEVICE_ATTR(reclen, 0444, ur_attr_reclen_show, NULL); |
@@ -379,31 +424,6 @@ static ssize_t ur_write(struct file *file, const char __user *udata, | |||
379 | return do_write(urf->urd, udata, count, urf->dev_reclen, ppos); | 424 | return do_write(urf->urd, udata, count, urf->dev_reclen, ppos); |
380 | } | 425 | } |
381 | 426 | ||
382 | static int do_diag_14(unsigned long rx, unsigned long ry1, | ||
383 | unsigned long subcode) | ||
384 | { | ||
385 | register unsigned long _ry1 asm("2") = ry1; | ||
386 | register unsigned long _ry2 asm("3") = subcode; | ||
387 | int rc = 0; | ||
388 | |||
389 | asm volatile( | ||
390 | #ifdef CONFIG_64BIT | ||
391 | " sam31\n" | ||
392 | " diag %2,2,0x14\n" | ||
393 | " sam64\n" | ||
394 | #else | ||
395 | " diag %2,2,0x14\n" | ||
396 | #endif | ||
397 | " ipm %0\n" | ||
398 | " srl %0,28\n" | ||
399 | : "=d" (rc), "+d" (_ry2) | ||
400 | : "d" (rx), "d" (_ry1) | ||
401 | : "cc"); | ||
402 | |||
403 | TRACE("diag 14: subcode=0x%lx, cc=%i\n", subcode, rc); | ||
404 | return rc; | ||
405 | } | ||
406 | |||
407 | /* | 427 | /* |
408 | * diagnose code 0x14 subcode 0x0028 - position spool file to designated | 428 | * diagnose code 0x14 subcode 0x0028 - position spool file to designated |
409 | * record | 429 | * record |
@@ -415,7 +435,7 @@ static int diag_position_to_record(int devno, int record) | |||
415 | { | 435 | { |
416 | int cc; | 436 | int cc; |
417 | 437 | ||
418 | cc = do_diag_14(record, devno, 0x28); | 438 | cc = diag14(record, devno, 0x28); |
419 | switch (cc) { | 439 | switch (cc) { |
420 | case 0: | 440 | case 0: |
421 | return 0; | 441 | return 0; |
@@ -440,7 +460,7 @@ static int diag_read_file(int devno, char *buf) | |||
440 | { | 460 | { |
441 | int cc; | 461 | int cc; |
442 | 462 | ||
443 | cc = do_diag_14((unsigned long) buf, devno, 0x00); | 463 | cc = diag14((unsigned long) buf, devno, 0x00); |
444 | switch (cc) { | 464 | switch (cc) { |
445 | case 0: | 465 | case 0: |
446 | return 0; | 466 | return 0; |
@@ -533,7 +553,7 @@ static int diag_read_next_file_info(struct file_control_block *buf, int spid) | |||
533 | { | 553 | { |
534 | int cc; | 554 | int cc; |
535 | 555 | ||
536 | cc = do_diag_14((unsigned long) buf, spid, 0xfff); | 556 | cc = diag14((unsigned long) buf, spid, 0xfff); |
537 | switch (cc) { | 557 | switch (cc) { |
538 | case 0: | 558 | case 0: |
539 | return 0; | 559 | return 0; |
@@ -750,64 +770,63 @@ static struct file_operations ur_fops = { | |||
750 | 770 | ||
751 | /* | 771 | /* |
752 | * ccw_device infrastructure: | 772 | * ccw_device infrastructure: |
753 | * ur_probe gets its own ref to the device (i.e. get_device), | 773 | * ur_probe creates the struct urdev (with refcount = 1), the device |
754 | * creates the struct urdev, the device attributes, sets up | 774 | * attributes, sets up the interrupt handler and validates the virtual |
755 | * the interrupt handler and validates the virtual unit record device. | 775 | * unit record device. |
756 | * ur_remove removes the device attributes, frees the struct urdev | 776 | * ur_remove removes the device attributes and drops the reference to |
757 | * and drops (put_device) the ref to the device we got in ur_probe. | 777 | * struct urdev. |
778 | * | ||
779 | * ur_probe, ur_remove, ur_set_online and ur_set_offline are serialized | ||
780 | * by the vmur_mutex lock. | ||
781 | * | ||
782 | * urd->char_device is used as indication that the online function has | ||
783 | * been completed successfully. | ||
758 | */ | 784 | */ |
759 | static int ur_probe(struct ccw_device *cdev) | 785 | static int ur_probe(struct ccw_device *cdev) |
760 | { | 786 | { |
761 | struct urdev *urd; | 787 | struct urdev *urd; |
762 | int rc; | 788 | int rc; |
763 | 789 | ||
764 | TRACE("ur_probe: cdev=%p state=%d\n", cdev, *(int *) cdev->private); | 790 | TRACE("ur_probe: cdev=%p\n", cdev); |
765 | |||
766 | if (!get_device(&cdev->dev)) | ||
767 | return -ENODEV; | ||
768 | 791 | ||
792 | mutex_lock(&vmur_mutex); | ||
769 | urd = urdev_alloc(cdev); | 793 | urd = urdev_alloc(cdev); |
770 | if (!urd) { | 794 | if (!urd) { |
771 | rc = -ENOMEM; | 795 | rc = -ENOMEM; |
772 | goto fail; | 796 | goto fail_unlock; |
773 | } | 797 | } |
798 | |||
774 | rc = ur_create_attributes(&cdev->dev); | 799 | rc = ur_create_attributes(&cdev->dev); |
775 | if (rc) { | 800 | if (rc) { |
776 | rc = -ENOMEM; | 801 | rc = -ENOMEM; |
777 | goto fail; | 802 | goto fail_urdev_put; |
778 | } | 803 | } |
779 | cdev->dev.driver_data = urd; | ||
780 | cdev->handler = ur_int_handler; | 804 | cdev->handler = ur_int_handler; |
781 | 805 | ||
782 | /* validate virtual unit record device */ | 806 | /* validate virtual unit record device */ |
783 | urd->class = get_urd_class(urd); | 807 | urd->class = get_urd_class(urd); |
784 | if (urd->class < 0) { | 808 | if (urd->class < 0) { |
785 | rc = urd->class; | 809 | rc = urd->class; |
786 | goto fail; | 810 | goto fail_remove_attr; |
787 | } | 811 | } |
788 | if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) { | 812 | if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) { |
789 | rc = -ENOTSUPP; | 813 | rc = -ENOTSUPP; |
790 | goto fail; | 814 | goto fail_remove_attr; |
791 | } | 815 | } |
816 | spin_lock_irq(get_ccwdev_lock(cdev)); | ||
817 | cdev->dev.driver_data = urd; | ||
818 | spin_unlock_irq(get_ccwdev_lock(cdev)); | ||
792 | 819 | ||
820 | mutex_unlock(&vmur_mutex); | ||
793 | return 0; | 821 | return 0; |
794 | 822 | ||
795 | fail: | 823 | fail_remove_attr: |
796 | urdev_free(urd); | ||
797 | put_device(&cdev->dev); | ||
798 | return rc; | ||
799 | } | ||
800 | |||
801 | static void ur_remove(struct ccw_device *cdev) | ||
802 | { | ||
803 | struct urdev *urd = cdev->dev.driver_data; | ||
804 | |||
805 | TRACE("ur_remove\n"); | ||
806 | if (cdev->online) | ||
807 | ur_set_offline(cdev); | ||
808 | ur_remove_attributes(&cdev->dev); | 824 | ur_remove_attributes(&cdev->dev); |
809 | urdev_free(urd); | 825 | fail_urdev_put: |
810 | put_device(&cdev->dev); | 826 | urdev_put(urd); |
827 | fail_unlock: | ||
828 | mutex_unlock(&vmur_mutex); | ||
829 | return rc; | ||
811 | } | 830 | } |
812 | 831 | ||
813 | static int ur_set_online(struct ccw_device *cdev) | 832 | static int ur_set_online(struct ccw_device *cdev) |
@@ -816,20 +835,29 @@ static int ur_set_online(struct ccw_device *cdev) | |||
816 | int minor, major, rc; | 835 | int minor, major, rc; |
817 | char node_id[16]; | 836 | char node_id[16]; |
818 | 837 | ||
819 | TRACE("ur_set_online: cdev=%p state=%d\n", cdev, | 838 | TRACE("ur_set_online: cdev=%p\n", cdev); |
820 | *(int *) cdev->private); | ||
821 | 839 | ||
822 | if (!try_module_get(ur_driver.owner)) | 840 | mutex_lock(&vmur_mutex); |
823 | return -EINVAL; | 841 | urd = urdev_get_from_cdev(cdev); |
842 | if (!urd) { | ||
843 | /* ur_remove already deleted our urd */ | ||
844 | rc = -ENODEV; | ||
845 | goto fail_unlock; | ||
846 | } | ||
847 | |||
848 | if (urd->char_device) { | ||
849 | /* Another ur_set_online was faster */ | ||
850 | rc = -EBUSY; | ||
851 | goto fail_urdev_put; | ||
852 | } | ||
824 | 853 | ||
825 | urd = (struct urdev *) cdev->dev.driver_data; | ||
826 | minor = urd->dev_id.devno; | 854 | minor = urd->dev_id.devno; |
827 | major = MAJOR(ur_first_dev_maj_min); | 855 | major = MAJOR(ur_first_dev_maj_min); |
828 | 856 | ||
829 | urd->char_device = cdev_alloc(); | 857 | urd->char_device = cdev_alloc(); |
830 | if (!urd->char_device) { | 858 | if (!urd->char_device) { |
831 | rc = -ENOMEM; | 859 | rc = -ENOMEM; |
832 | goto fail_module_put; | 860 | goto fail_urdev_put; |
833 | } | 861 | } |
834 | 862 | ||
835 | cdev_init(urd->char_device, &ur_fops); | 863 | cdev_init(urd->char_device, &ur_fops); |
@@ -858,29 +886,79 @@ static int ur_set_online(struct ccw_device *cdev) | |||
858 | TRACE("ur_set_online: device_create rc=%d\n", rc); | 886 | TRACE("ur_set_online: device_create rc=%d\n", rc); |
859 | goto fail_free_cdev; | 887 | goto fail_free_cdev; |
860 | } | 888 | } |
861 | 889 | urdev_put(urd); | |
890 | mutex_unlock(&vmur_mutex); | ||
862 | return 0; | 891 | return 0; |
863 | 892 | ||
864 | fail_free_cdev: | 893 | fail_free_cdev: |
865 | cdev_del(urd->char_device); | 894 | cdev_del(urd->char_device); |
866 | fail_module_put: | 895 | urd->char_device = NULL; |
867 | module_put(ur_driver.owner); | 896 | fail_urdev_put: |
868 | 897 | urdev_put(urd); | |
898 | fail_unlock: | ||
899 | mutex_unlock(&vmur_mutex); | ||
869 | return rc; | 900 | return rc; |
870 | } | 901 | } |
871 | 902 | ||
872 | static int ur_set_offline(struct ccw_device *cdev) | 903 | static int ur_set_offline_force(struct ccw_device *cdev, int force) |
873 | { | 904 | { |
874 | struct urdev *urd; | 905 | struct urdev *urd; |
906 | int rc; | ||
875 | 907 | ||
876 | TRACE("ur_set_offline: cdev=%p cdev->private=%p state=%d\n", | 908 | TRACE("ur_set_offline: cdev=%p\n", cdev); |
877 | cdev, cdev->private, *(int *) cdev->private); | 909 | urd = urdev_get_from_cdev(cdev); |
878 | urd = (struct urdev *) cdev->dev.driver_data; | 910 | if (!urd) |
911 | /* ur_remove already deleted our urd */ | ||
912 | return -ENODEV; | ||
913 | if (!urd->char_device) { | ||
914 | /* Another ur_set_offline was faster */ | ||
915 | rc = -EBUSY; | ||
916 | goto fail_urdev_put; | ||
917 | } | ||
918 | if (!force && (atomic_read(&urd->ref_count) > 2)) { | ||
919 | /* There is still a user of urd (e.g. ur_open) */ | ||
920 | TRACE("ur_set_offline: BUSY\n"); | ||
921 | rc = -EBUSY; | ||
922 | goto fail_urdev_put; | ||
923 | } | ||
879 | device_destroy(vmur_class, urd->char_device->dev); | 924 | device_destroy(vmur_class, urd->char_device->dev); |
880 | cdev_del(urd->char_device); | 925 | cdev_del(urd->char_device); |
881 | module_put(ur_driver.owner); | 926 | urd->char_device = NULL; |
927 | rc = 0; | ||
882 | 928 | ||
883 | return 0; | 929 | fail_urdev_put: |
930 | urdev_put(urd); | ||
931 | return rc; | ||
932 | } | ||
933 | |||
934 | static int ur_set_offline(struct ccw_device *cdev) | ||
935 | { | ||
936 | int rc; | ||
937 | |||
938 | mutex_lock(&vmur_mutex); | ||
939 | rc = ur_set_offline_force(cdev, 0); | ||
940 | mutex_unlock(&vmur_mutex); | ||
941 | return rc; | ||
942 | } | ||
943 | |||
944 | static void ur_remove(struct ccw_device *cdev) | ||
945 | { | ||
946 | unsigned long flags; | ||
947 | |||
948 | TRACE("ur_remove\n"); | ||
949 | |||
950 | mutex_lock(&vmur_mutex); | ||
951 | |||
952 | if (cdev->online) | ||
953 | ur_set_offline_force(cdev, 1); | ||
954 | ur_remove_attributes(&cdev->dev); | ||
955 | |||
956 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | ||
957 | urdev_put(cdev->dev.driver_data); | ||
958 | cdev->dev.driver_data = NULL; | ||
959 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | ||
960 | |||
961 | mutex_unlock(&vmur_mutex); | ||
884 | } | 962 | } |
885 | 963 | ||
886 | /* | 964 | /* |
diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h index 2b3c564e0472..fa959644735a 100644 --- a/drivers/s390/char/vmur.h +++ b/drivers/s390/char/vmur.h | |||
@@ -70,6 +70,7 @@ struct urdev { | |||
70 | size_t reclen; /* Record length for *write* CCWs */ | 70 | size_t reclen; /* Record length for *write* CCWs */ |
71 | int class; /* VM device class */ | 71 | int class; /* VM device class */ |
72 | int io_request_rc; /* return code from I/O request */ | 72 | int io_request_rc; /* return code from I/O request */ |
73 | atomic_t ref_count; /* reference counter */ | ||
73 | }; | 74 | }; |
74 | 75 | ||
75 | /* | 76 | /* |
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 02fd00b55e1b..34a796913b06 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c | |||
@@ -594,6 +594,9 @@ alloc_cmb (struct ccw_device *cdev) | |||
594 | free_pages((unsigned long)mem, get_order(size)); | 594 | free_pages((unsigned long)mem, get_order(size)); |
595 | } else if (!mem) { | 595 | } else if (!mem) { |
596 | /* no luck */ | 596 | /* no luck */ |
597 | printk(KERN_WARNING "cio: failed to allocate area " | ||
598 | "for measuring %d subchannels\n", | ||
599 | cmb_area.num_channels); | ||
597 | ret = -ENOMEM; | 600 | ret = -ENOMEM; |
598 | goto out; | 601 | goto out; |
599 | } else { | 602 | } else { |
@@ -1279,13 +1282,6 @@ init_cmf(void) | |||
1279 | case CMF_BASIC: | 1282 | case CMF_BASIC: |
1280 | format_string = "basic"; | 1283 | format_string = "basic"; |
1281 | cmbops = &cmbops_basic; | 1284 | cmbops = &cmbops_basic; |
1282 | if (cmb_area.num_channels > 4096 || cmb_area.num_channels < 1) { | ||
1283 | printk(KERN_ERR "cio: Basic channel measurement " | ||
1284 | "facility can only use 1 to 4096 devices\n" | ||
1285 | KERN_ERR "when the cmf driver is built" | ||
1286 | " as a loadable module\n"); | ||
1287 | return 1; | ||
1288 | } | ||
1289 | break; | 1285 | break; |
1290 | case CMF_EXTENDED: | 1286 | case CMF_EXTENDED: |
1291 | format_string = "extended"; | 1287 | format_string = "extended"; |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 297659fa0e26..e44d92eac8e9 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -117,7 +117,10 @@ static int ccw_uevent(struct device *dev, char **envp, int num_envp, | |||
117 | snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); | 117 | snprint_alias(modalias_buf, sizeof(modalias_buf), id, ""); |
118 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, | 118 | ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len, |
119 | "MODALIAS=%s", modalias_buf); | 119 | "MODALIAS=%s", modalias_buf); |
120 | return ret; | 120 | if (ret) |
121 | return ret; | ||
122 | envp[i] = NULL; | ||
123 | return 0; | ||
121 | } | 124 | } |
122 | 125 | ||
123 | struct bus_type ccw_bus_type; | 126 | struct bus_type ccw_bus_type; |
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c index 60b9347f7c92..f232832f2b22 100644 --- a/drivers/s390/cio/device_id.c +++ b/drivers/s390/cio/device_id.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/delay.h> | 17 | #include <asm/delay.h> |
18 | #include <asm/cio.h> | 18 | #include <asm/cio.h> |
19 | #include <asm/lowcore.h> | 19 | #include <asm/lowcore.h> |
20 | #include <asm/diag.h> | ||
20 | 21 | ||
21 | #include "cio.h" | 22 | #include "cio.h" |
22 | #include "cio_debug.h" | 23 | #include "cio_debug.h" |
@@ -25,51 +26,6 @@ | |||
25 | #include "ioasm.h" | 26 | #include "ioasm.h" |
26 | 27 | ||
27 | /* | 28 | /* |
28 | * diag210 is used under VM to get information about a virtual device | ||
29 | */ | ||
30 | int | ||
31 | diag210(struct diag210 * addr) | ||
32 | { | ||
33 | /* | ||
34 | * diag 210 needs its data below the 2GB border, so we | ||
35 | * use a static data area to be sure | ||
36 | */ | ||
37 | static struct diag210 diag210_tmp; | ||
38 | static DEFINE_SPINLOCK(diag210_lock); | ||
39 | unsigned long flags; | ||
40 | int ccode; | ||
41 | |||
42 | spin_lock_irqsave(&diag210_lock, flags); | ||
43 | diag210_tmp = *addr; | ||
44 | |||
45 | #ifdef CONFIG_64BIT | ||
46 | asm volatile( | ||
47 | " lhi %0,-1\n" | ||
48 | " sam31\n" | ||
49 | " diag %1,0,0x210\n" | ||
50 | "0: ipm %0\n" | ||
51 | " srl %0,28\n" | ||
52 | "1: sam64\n" | ||
53 | EX_TABLE(0b,1b) | ||
54 | : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); | ||
55 | #else | ||
56 | asm volatile( | ||
57 | " lhi %0,-1\n" | ||
58 | " diag %1,0,0x210\n" | ||
59 | "0: ipm %0\n" | ||
60 | " srl %0,28\n" | ||
61 | "1:\n" | ||
62 | EX_TABLE(0b,1b) | ||
63 | : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); | ||
64 | #endif | ||
65 | |||
66 | *addr = diag210_tmp; | ||
67 | spin_unlock_irqrestore(&diag210_lock, flags); | ||
68 | |||
69 | return ccode; | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * Input : | 29 | * Input : |
74 | * devno - device number | 30 | * devno - device number |
75 | * ps - pointer to sense ID data area | 31 | * ps - pointer to sense ID data area |
@@ -349,5 +305,3 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event) | |||
349 | break; | 305 | break; |
350 | } | 306 | } |
351 | } | 307 | } |
352 | |||
353 | EXPORT_SYMBOL(diag210); | ||
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 03347aed2b3e..d8d479876ec7 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -195,6 +195,8 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state, | |||
195 | again: | 195 | again: |
196 | ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt); | 196 | ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt); |
197 | rc = qdio_check_ccq(q, ccq); | 197 | rc = qdio_check_ccq(q, ccq); |
198 | if ((ccq == 96) && (tmp_cnt != *cnt)) | ||
199 | rc = 0; | ||
198 | if (rc == 1) { | 200 | if (rc == 1) { |
199 | QDIO_DBF_TEXT5(1,trace,"eqAGAIN"); | 201 | QDIO_DBF_TEXT5(1,trace,"eqAGAIN"); |
200 | goto again; | 202 | goto again; |
@@ -740,7 +742,8 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q) | |||
740 | first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used), | 742 | first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used), |
741 | (QDIO_MAX_BUFFERS_PER_Q-1)); | 743 | (QDIO_MAX_BUFFERS_PER_Q-1)); |
742 | 744 | ||
743 | if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis)) | 745 | if (((!q->is_iqdio_q) && (!q->hydra_gives_outbound_pcis)) || |
746 | (q->queue_type == QDIO_IQDIO_QFMT_ASYNCH)) | ||
744 | SYNC_MEMORY; | 747 | SYNC_MEMORY; |
745 | 748 | ||
746 | check_next: | 749 | check_next: |
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h index ea486952f778..2d184655bc5d 100644 --- a/include/asm-s390/atomic.h +++ b/include/asm-s390/atomic.h | |||
@@ -67,8 +67,17 @@ typedef struct { | |||
67 | 67 | ||
68 | #endif /* __GNUC__ */ | 68 | #endif /* __GNUC__ */ |
69 | 69 | ||
70 | #define atomic_read(v) ((v)->counter) | 70 | static inline int atomic_read(const atomic_t *v) |
71 | #define atomic_set(v,i) (((v)->counter) = (i)) | 71 | { |
72 | barrier(); | ||
73 | return v->counter; | ||
74 | } | ||
75 | |||
76 | static inline void atomic_set(atomic_t *v, int i) | ||
77 | { | ||
78 | v->counter = i; | ||
79 | barrier(); | ||
80 | } | ||
72 | 81 | ||
73 | static __inline__ int atomic_add_return(int i, atomic_t * v) | 82 | static __inline__ int atomic_add_return(int i, atomic_t * v) |
74 | { | 83 | { |
@@ -182,8 +191,17 @@ typedef struct { | |||
182 | 191 | ||
183 | #endif /* __GNUC__ */ | 192 | #endif /* __GNUC__ */ |
184 | 193 | ||
185 | #define atomic64_read(v) ((v)->counter) | 194 | static inline long long atomic64_read(const atomic64_t *v) |
186 | #define atomic64_set(v,i) (((v)->counter) = (i)) | 195 | { |
196 | barrier(); | ||
197 | return v->counter; | ||
198 | } | ||
199 | |||
200 | static inline void atomic64_set(atomic64_t *v, long long i) | ||
201 | { | ||
202 | v->counter = i; | ||
203 | barrier(); | ||
204 | } | ||
187 | 205 | ||
188 | static __inline__ long long atomic64_add_return(long long i, atomic64_t * v) | 206 | static __inline__ long long atomic64_add_return(long long i, atomic64_t * v) |
189 | { | 207 | { |
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h index f738d2827582..1982fb344164 100644 --- a/include/asm-s390/cio.h +++ b/include/asm-s390/cio.h | |||
@@ -258,19 +258,6 @@ struct ciw { | |||
258 | /* Sick revalidation of device. */ | 258 | /* Sick revalidation of device. */ |
259 | #define CIO_REVALIDATE 0x0008 | 259 | #define CIO_REVALIDATE 0x0008 |
260 | 260 | ||
261 | struct diag210 { | ||
262 | __u16 vrdcdvno : 16; /* device number (input) */ | ||
263 | __u16 vrdclen : 16; /* data block length (input) */ | ||
264 | __u32 vrdcvcla : 8; /* virtual device class (output) */ | ||
265 | __u32 vrdcvtyp : 8; /* virtual device type (output) */ | ||
266 | __u32 vrdcvsta : 8; /* virtual device status (output) */ | ||
267 | __u32 vrdcvfla : 8; /* virtual device flags (output) */ | ||
268 | __u32 vrdcrccl : 8; /* real device class (output) */ | ||
269 | __u32 vrdccrty : 8; /* real device type (output) */ | ||
270 | __u32 vrdccrmd : 8; /* real device model (output) */ | ||
271 | __u32 vrdccrft : 8; /* real device feature (output) */ | ||
272 | } __attribute__ ((packed,aligned(4))); | ||
273 | |||
274 | struct ccw_dev_id { | 261 | struct ccw_dev_id { |
275 | u8 ssid; | 262 | u8 ssid; |
276 | u16 devno; | 263 | u16 devno; |
@@ -285,8 +272,6 @@ static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1, | |||
285 | return 0; | 272 | return 0; |
286 | } | 273 | } |
287 | 274 | ||
288 | extern int diag210(struct diag210 *addr); | ||
289 | |||
290 | extern void wait_cons_dev(void); | 275 | extern void wait_cons_dev(void); |
291 | 276 | ||
292 | extern void css_schedule_reprobe(void); | 277 | extern void css_schedule_reprobe(void); |
diff --git a/include/asm-s390/diag.h b/include/asm-s390/diag.h new file mode 100644 index 000000000000..72b2e2f2d32d --- /dev/null +++ b/include/asm-s390/diag.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * s390 diagnose functions | ||
3 | * | ||
4 | * Copyright IBM Corp. 2007 | ||
5 | * Author(s): Michael Holzheu <holzheu@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #ifndef _ASM_S390_DIAG_H | ||
9 | #define _ASM_S390_DIAG_H | ||
10 | |||
11 | /* | ||
12 | * Diagnose 10: Release pages | ||
13 | */ | ||
14 | extern void diag10(unsigned long addr); | ||
15 | |||
16 | /* | ||
17 | * Diagnose 14: Input spool file manipulation | ||
18 | */ | ||
19 | extern int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode); | ||
20 | |||
21 | /* | ||
22 | * Diagnose 210: Get information about a virtual device | ||
23 | */ | ||
24 | struct diag210 { | ||
25 | u16 vrdcdvno; /* device number (input) */ | ||
26 | u16 vrdclen; /* data block length (input) */ | ||
27 | u8 vrdcvcla; /* virtual device class (output) */ | ||
28 | u8 vrdcvtyp; /* virtual device type (output) */ | ||
29 | u8 vrdcvsta; /* virtual device status (output) */ | ||
30 | u8 vrdcvfla; /* virtual device flags (output) */ | ||
31 | u8 vrdcrccl; /* real device class (output) */ | ||
32 | u8 vrdccrty; /* real device type (output) */ | ||
33 | u8 vrdccrmd; /* real device model (output) */ | ||
34 | u8 vrdccrft; /* real device feature (output) */ | ||
35 | } __attribute__((packed, aligned(4))); | ||
36 | |||
37 | extern int diag210(struct diag210 *addr); | ||
38 | |||
39 | #endif /* _ASM_S390_DIAG_H */ | ||
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h index 56c8a6c80e2e..e45d3c9a4b7e 100644 --- a/include/asm-s390/pgalloc.h +++ b/include/asm-s390/pgalloc.h | |||
@@ -19,8 +19,6 @@ | |||
19 | 19 | ||
20 | #define check_pgt_cache() do {} while (0) | 20 | #define check_pgt_cache() do {} while (0) |
21 | 21 | ||
22 | extern void diag10(unsigned long addr); | ||
23 | |||
24 | /* | 22 | /* |
25 | * Page allocation orders. | 23 | * Page allocation orders. |
26 | */ | 24 | */ |