aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/s390mach.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/s390mach.c')
-rw-r--r--drivers/s390/s390mach.c56
1 files changed, 42 insertions, 14 deletions
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 4191fd9d4d11..7dad597ff86e 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -23,7 +23,7 @@
23 23
24static struct semaphore m_sem; 24static struct semaphore m_sem;
25 25
26extern int css_process_crw(int); 26extern int css_process_crw(int, int);
27extern int chsc_process_crw(void); 27extern int chsc_process_crw(void);
28extern int chp_process_crw(int, int); 28extern int chp_process_crw(int, int);
29extern void css_reiterate_subchannels(void); 29extern void css_reiterate_subchannels(void);
@@ -49,9 +49,10 @@ s390_handle_damage(char *msg)
49static int 49static int
50s390_collect_crw_info(void *param) 50s390_collect_crw_info(void *param)
51{ 51{
52 struct crw crw; 52 struct crw crw[2];
53 int ccode, ret, slow; 53 int ccode, ret, slow;
54 struct semaphore *sem; 54 struct semaphore *sem;
55 unsigned int chain;
55 56
56 sem = (struct semaphore *)param; 57 sem = (struct semaphore *)param;
57 /* Set a nice name. */ 58 /* Set a nice name. */
@@ -59,25 +60,50 @@ s390_collect_crw_info(void *param)
59repeat: 60repeat:
60 down_interruptible(sem); 61 down_interruptible(sem);
61 slow = 0; 62 slow = 0;
63 chain = 0;
62 while (1) { 64 while (1) {
63 ccode = stcrw(&crw); 65 if (unlikely(chain > 1)) {
66 struct crw tmp_crw;
67
68 printk(KERN_WARNING"%s: Code does not support more "
69 "than two chained crws; please report to "
70 "linux390@de.ibm.com!\n", __FUNCTION__);
71 ccode = stcrw(&tmp_crw);
72 printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, "
73 "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
74 __FUNCTION__, tmp_crw.slct, tmp_crw.oflw,
75 tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc,
76 tmp_crw.erc, tmp_crw.rsid);
77 printk(KERN_WARNING"%s: This was crw number %x in the "
78 "chain\n", __FUNCTION__, chain);
79 if (ccode != 0)
80 break;
81 chain = tmp_crw.chn ? chain + 1 : 0;
82 continue;
83 }
84 ccode = stcrw(&crw[chain]);
64 if (ccode != 0) 85 if (ccode != 0)
65 break; 86 break;
66 DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " 87 DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, "
67 "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", 88 "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n",
68 crw.slct, crw.oflw, crw.chn, crw.rsc, crw.anc, 89 crw[chain].slct, crw[chain].oflw, crw[chain].chn,
69 crw.erc, crw.rsid); 90 crw[chain].rsc, crw[chain].anc, crw[chain].erc,
91 crw[chain].rsid);
70 /* Check for overflows. */ 92 /* Check for overflows. */
71 if (crw.oflw) { 93 if (crw[chain].oflw) {
72 pr_debug("%s: crw overflow detected!\n", __FUNCTION__); 94 pr_debug("%s: crw overflow detected!\n", __FUNCTION__);
73 css_reiterate_subchannels(); 95 css_reiterate_subchannels();
96 chain = 0;
74 slow = 1; 97 slow = 1;
75 continue; 98 continue;
76 } 99 }
77 switch (crw.rsc) { 100 switch (crw[chain].rsc) {
78 case CRW_RSC_SCH: 101 case CRW_RSC_SCH:
79 pr_debug("source is subchannel %04X\n", crw.rsid); 102 if (crw[0].chn && !chain)
80 ret = css_process_crw (crw.rsid); 103 break;
104 pr_debug("source is subchannel %04X\n", crw[0].rsid);
105 ret = css_process_crw (crw[0].rsid,
106 chain ? crw[1].rsid : 0);
81 if (ret == -EAGAIN) 107 if (ret == -EAGAIN)
82 slow = 1; 108 slow = 1;
83 break; 109 break;
@@ -85,18 +111,18 @@ repeat:
85 pr_debug("source is monitoring facility\n"); 111 pr_debug("source is monitoring facility\n");
86 break; 112 break;
87 case CRW_RSC_CPATH: 113 case CRW_RSC_CPATH:
88 pr_debug("source is channel path %02X\n", crw.rsid); 114 pr_debug("source is channel path %02X\n", crw[0].rsid);
89 switch (crw.erc) { 115 switch (crw[0].erc) {
90 case CRW_ERC_IPARM: /* Path has come. */ 116 case CRW_ERC_IPARM: /* Path has come. */
91 ret = chp_process_crw(crw.rsid, 1); 117 ret = chp_process_crw(crw[0].rsid, 1);
92 break; 118 break;
93 case CRW_ERC_PERRI: /* Path has gone. */ 119 case CRW_ERC_PERRI: /* Path has gone. */
94 case CRW_ERC_PERRN: 120 case CRW_ERC_PERRN:
95 ret = chp_process_crw(crw.rsid, 0); 121 ret = chp_process_crw(crw[0].rsid, 0);
96 break; 122 break;
97 default: 123 default:
98 pr_debug("Don't know how to handle erc=%x\n", 124 pr_debug("Don't know how to handle erc=%x\n",
99 crw.erc); 125 crw[0].erc);
100 ret = 0; 126 ret = 0;
101 } 127 }
102 if (ret == -EAGAIN) 128 if (ret == -EAGAIN)
@@ -115,6 +141,8 @@ repeat:
115 pr_debug("unknown source\n"); 141 pr_debug("unknown source\n");
116 break; 142 break;
117 } 143 }
144 /* chain is always 0 or 1 here. */
145 chain = crw[chain].chn ? chain + 1 : 0;
118 } 146 }
119 if (slow) 147 if (slow)
120 queue_work(slow_path_wq, &slow_path_work); 148 queue_work(slow_path_wq, &slow_path_work);