aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/Makefile2
-rw-r--r--drivers/s390/cio/chp.c6
-rw-r--r--drivers/s390/cio/chsc.c6
-rw-r--r--drivers/s390/cio/cio.c3
-rw-r--r--drivers/s390/cio/crw.c145
-rw-r--r--drivers/s390/cio/css.c6
6 files changed, 157 insertions, 11 deletions
diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile
index bd79bd165396..adb3dd301528 100644
--- a/drivers/s390/cio/Makefile
+++ b/drivers/s390/cio/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \ 5obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \
6 fcx.o itcw.o 6 fcx.o itcw.o crw.o
7ccw_device-objs += device.o device_fsm.o device_ops.o 7ccw_device-objs += device.o device_fsm.o device_ops.o
8ccw_device-objs += device_id.o device_pgid.o device_status.o 8ccw_device-objs += device_id.o device_pgid.o device_status.o
9obj-y += ccw_device.o cmf.o 9obj-y += ccw_device.o cmf.o
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 1246f61a5338..3e5f304ad88f 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -17,8 +17,8 @@
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <asm/chpid.h> 18#include <asm/chpid.h>
19#include <asm/sclp.h> 19#include <asm/sclp.h>
20#include <asm/crw.h>
20 21
21#include "../s390mach.h"
22#include "cio.h" 22#include "cio.h"
23#include "css.h" 23#include "css.h"
24#include "ioasm.h" 24#include "ioasm.h"
@@ -706,12 +706,12 @@ static int __init chp_init(void)
706 struct chp_id chpid; 706 struct chp_id chpid;
707 int ret; 707 int ret;
708 708
709 ret = s390_register_crw_handler(CRW_RSC_CPATH, chp_process_crw); 709 ret = crw_register_handler(CRW_RSC_CPATH, chp_process_crw);
710 if (ret) 710 if (ret)
711 return ret; 711 return ret;
712 chp_wq = create_singlethread_workqueue("cio_chp"); 712 chp_wq = create_singlethread_workqueue("cio_chp");
713 if (!chp_wq) { 713 if (!chp_wq) {
714 s390_unregister_crw_handler(CRW_RSC_CPATH); 714 crw_unregister_handler(CRW_RSC_CPATH);
715 return -ENOMEM; 715 return -ENOMEM;
716 } 716 }
717 INIT_WORK(&cfg_work, cfg_func); 717 INIT_WORK(&cfg_work, cfg_func);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index ebab6ea4659b..7399b07a1aeb 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -19,8 +19,8 @@
19#include <asm/cio.h> 19#include <asm/cio.h>
20#include <asm/chpid.h> 20#include <asm/chpid.h>
21#include <asm/chsc.h> 21#include <asm/chsc.h>
22#include <asm/crw.h>
22 23
23#include "../s390mach.h"
24#include "css.h" 24#include "css.h"
25#include "cio.h" 25#include "cio.h"
26#include "cio_debug.h" 26#include "cio_debug.h"
@@ -820,7 +820,7 @@ int __init chsc_alloc_sei_area(void)
820 "chsc machine checks!\n"); 820 "chsc machine checks!\n");
821 return -ENOMEM; 821 return -ENOMEM;
822 } 822 }
823 ret = s390_register_crw_handler(CRW_RSC_CSS, chsc_process_crw); 823 ret = crw_register_handler(CRW_RSC_CSS, chsc_process_crw);
824 if (ret) 824 if (ret)
825 kfree(sei_page); 825 kfree(sei_page);
826 return ret; 826 return ret;
@@ -828,7 +828,7 @@ int __init chsc_alloc_sei_area(void)
828 828
829void __init chsc_free_sei_area(void) 829void __init chsc_free_sei_area(void)
830{ 830{
831 s390_unregister_crw_handler(CRW_RSC_CSS); 831 crw_unregister_handler(CRW_RSC_CSS);
832 kfree(sei_page); 832 kfree(sei_page);
833} 833}
834 834
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 659f8a791656..73135c5e9dfb 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -30,6 +30,8 @@
30#include <asm/isc.h> 30#include <asm/isc.h>
31#include <asm/cpu.h> 31#include <asm/cpu.h>
32#include <asm/fcx.h> 32#include <asm/fcx.h>
33#include <asm/nmi.h>
34#include <asm/crw.h>
33#include "cio.h" 35#include "cio.h"
34#include "css.h" 36#include "css.h"
35#include "chsc.h" 37#include "chsc.h"
@@ -38,7 +40,6 @@
38#include "blacklist.h" 40#include "blacklist.h"
39#include "cio_debug.h" 41#include "cio_debug.h"
40#include "chp.h" 42#include "chp.h"
41#include "../s390mach.h"
42 43
43debug_info_t *cio_debug_msg_id; 44debug_info_t *cio_debug_msg_id;
44debug_info_t *cio_debug_trace_id; 45debug_info_t *cio_debug_trace_id;
diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c
new file mode 100644
index 000000000000..508f88f6420c
--- /dev/null
+++ b/drivers/s390/cio/crw.c
@@ -0,0 +1,145 @@
1/*
2 * Channel report handling code
3 *
4 * Copyright IBM Corp. 2000,2009
5 * Author(s): Ingo Adlung <adlung@de.ibm.com>,
6 * Martin Schwidefsky <schwidefsky@de.ibm.com>,
7 * Cornelia Huck <cornelia.huck@de.ibm.com>,
8 * Heiko Carstens <heiko.carstens@de.ibm.com>,
9 */
10
11#include <linux/semaphore.h>
12#include <linux/kthread.h>
13#include <linux/init.h>
14#include <asm/crw.h>
15
16static struct semaphore crw_semaphore;
17static crw_handler_t crw_handlers[NR_RSCS];
18
19/**
20 * crw_register_handler() - register a channel report word handler
21 * @rsc: reporting source code to handle
22 * @handler: handler to be registered
23 *
24 * Returns %0 on success and a negative error value otherwise.
25 */
26int crw_register_handler(int rsc, crw_handler_t handler)
27{
28 if ((rsc < 0) || (rsc >= NR_RSCS))
29 return -EINVAL;
30 if (!cmpxchg(&crw_handlers[rsc], NULL, handler))
31 return 0;
32 return -EBUSY;
33}
34
35/**
36 * crw_unregister_handler() - unregister a channel report word handler
37 * @rsc: reporting source code to handle
38 */
39void crw_unregister_handler(int rsc)
40{
41 if ((rsc < 0) || (rsc >= NR_RSCS))
42 return;
43 xchg(&crw_handlers[rsc], NULL);
44 synchronize_sched();
45}
46
47/*
48 * Retrieve CRWs and call function to handle event.
49 */
50static int crw_collect_info(void *unused)
51{
52 struct crw crw[2];
53 int ccode;
54 unsigned int chain;
55 int ignore;
56
57repeat:
58 ignore = down_interruptible(&crw_semaphore);
59 chain = 0;
60 while (1) {
61 if (unlikely(chain > 1)) {
62 struct crw tmp_crw;
63
64 printk(KERN_WARNING"%s: Code does not support more "
65 "than two chained crws; please report to "
66 "linux390@de.ibm.com!\n", __func__);
67 ccode = stcrw(&tmp_crw);
68 printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
69 "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
70 __func__, tmp_crw.slct, tmp_crw.oflw,
71 tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
72 tmp_crw.erc, tmp_crw.rsid);
73 printk(KERN_WARNING"%s: This was crw number %x in the "
74 "chain\n", __func__, chain);
75 if (ccode != 0)
76 break;
77 chain = tmp_crw.chn ? chain + 1 : 0;
78 continue;
79 }
80 ccode = stcrw(&crw[chain]);
81 if (ccode != 0)
82 break;
83 printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, "
84 "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
85 crw[chain].slct, crw[chain].oflw, crw[chain].chn,
86 crw[chain].rsc, crw[chain].anc, crw[chain].erc,
87 crw[chain].rsid);
88 /* Check for overflows. */
89 if (crw[chain].oflw) {
90 int i;
91
92 pr_debug("%s: crw overflow detected!\n", __func__);
93 for (i = 0; i < NR_RSCS; i++) {
94 if (crw_handlers[i])
95 crw_handlers[i](NULL, NULL, 1);
96 }
97 chain = 0;
98 continue;
99 }
100 if (crw[0].chn && !chain) {
101 chain++;
102 continue;
103 }
104 if (crw_handlers[crw[chain].rsc])
105 crw_handlers[crw[chain].rsc](&crw[0],
106 chain ? &crw[1] : NULL,
107 0);
108 /* chain is always 0 or 1 here. */
109 chain = crw[chain].chn ? chain + 1 : 0;
110 }
111 goto repeat;
112 return 0;
113}
114
115void crw_handle_channel_report(void)
116{
117 up(&crw_semaphore);
118}
119
120/*
121 * Separate initcall needed for semaphore initialization since
122 * crw_handle_channel_report might be called before crw_machine_check_init.
123 */
124static int __init crw_init_semaphore(void)
125{
126 init_MUTEX_LOCKED(&crw_semaphore);
127 return 0;
128}
129pure_initcall(crw_init_semaphore);
130
131/*
132 * Machine checks for the channel subsystem must be enabled
133 * after the channel subsystem is initialized
134 */
135static int __init crw_machine_check_init(void)
136{
137 struct task_struct *task;
138
139 task = kthread_run(crw_collect_info, NULL, "kmcheck");
140 if (IS_ERR(task))
141 return PTR_ERR(task);
142 ctl_set_bit(14, 28); /* enable channel report MCH */
143 return 0;
144}
145device_initcall(crw_machine_check_init);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 8019288bc6de..a5fc56371ba8 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -18,8 +18,8 @@
18#include <linux/list.h> 18#include <linux/list.h>
19#include <linux/reboot.h> 19#include <linux/reboot.h>
20#include <asm/isc.h> 20#include <asm/isc.h>
21#include <asm/crw.h>
21 22
22#include "../s390mach.h"
23#include "css.h" 23#include "css.h"
24#include "cio.h" 24#include "cio.h"
25#include "cio_debug.h" 25#include "cio_debug.h"
@@ -765,7 +765,7 @@ init_channel_subsystem (void)
765 if (ret) 765 if (ret)
766 goto out; 766 goto out;
767 767
768 ret = s390_register_crw_handler(CRW_RSC_SCH, css_process_crw); 768 ret = crw_register_handler(CRW_RSC_SCH, css_process_crw);
769 if (ret) 769 if (ret)
770 goto out; 770 goto out;
771 771
@@ -845,7 +845,7 @@ out_unregister:
845out_bus: 845out_bus:
846 bus_unregister(&css_bus_type); 846 bus_unregister(&css_bus_type);
847out: 847out:
848 s390_unregister_crw_handler(CRW_RSC_CSS); 848 crw_unregister_handler(CRW_RSC_CSS);
849 chsc_free_sei_area(); 849 chsc_free_sei_area();
850 kfree(slow_subchannel_set); 850 kfree(slow_subchannel_set);
851 pr_alert("The CSS device driver initialization failed with " 851 pr_alert("The CSS device driver initialization failed with "