aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2008-07-14 03:59:02 -0400
committerHeiko Carstens <heiko.carstens@de.ibm.com>2008-07-14 04:02:11 -0400
commit99611f87176b2a908d8c66ab19a5fc550a3cd13a (patch)
tree2c9898f347d00aeab5ffcbf74c90469efb86043e /drivers/s390
parent6ef556ccc8fd256259745c4f0d0ab65aaf703824 (diff)
[S390] cio: Repair chpid event handling.
Passing the affected chpid in chp_event() worked only by chance since chpid is the first element in res_acc_data. Make it work properly by generalizing res_acc_data as chp_link and always passing around a properly filled out chp_link structure in chp_event(). Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/chp.c6
-rw-r--r--drivers/s390/cio/chp.h4
-rw-r--r--drivers/s390/cio/chsc.c55
-rw-r--r--drivers/s390/cio/css.h3
-rw-r--r--drivers/s390/cio/device.c11
5 files changed, 43 insertions, 36 deletions
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 62df43b2124c..19078d528853 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -525,7 +525,7 @@ static void chp_process_crw(struct crw *crw0, struct crw *crw1,
525 } 525 }
526} 526}
527 527
528int chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct res_acc_data *data) 528int chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct chp_link *link)
529{ 529{
530 int i; 530 int i;
531 int mask; 531 int mask;
@@ -534,10 +534,10 @@ int chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct res_acc_data *data)
534 mask = 0x80 >> i; 534 mask = 0x80 >> i;
535 if (!(ssd->path_mask & mask)) 535 if (!(ssd->path_mask & mask))
536 continue; 536 continue;
537 if (!chp_id_is_equal(&ssd->chpid[i], &data->chpid)) 537 if (!chp_id_is_equal(&ssd->chpid[i], &link->chpid))
538 continue; 538 continue;
539 if ((ssd->fla_valid_mask & mask) && 539 if ((ssd->fla_valid_mask & mask) &&
540 ((ssd->fla[i] & data->fla_mask) != data->fla)) 540 ((ssd->fla[i] & link->fla_mask) != link->fla))
541 continue; 541 continue;
542 return mask; 542 return mask;
543 } 543 }
diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h
index dffe2771ddac..26c3d2246176 100644
--- a/drivers/s390/cio/chp.h
+++ b/drivers/s390/cio/chp.h
@@ -24,7 +24,7 @@
24#define CHP_VARY_ON 2 24#define CHP_VARY_ON 2
25#define CHP_VARY_OFF 3 25#define CHP_VARY_OFF 3
26 26
27struct res_acc_data { 27struct chp_link {
28 struct chp_id chpid; 28 struct chp_id chpid;
29 u32 fla_mask; 29 u32 fla_mask;
30 u16 fla; 30 u16 fla;
@@ -60,5 +60,5 @@ int chp_new(struct chp_id chpid);
60void chp_cfg_schedule(struct chp_id chpid, int configure); 60void chp_cfg_schedule(struct chp_id chpid, int configure);
61void chp_cfg_cancel_deconfigure(struct chp_id chpid); 61void chp_cfg_cancel_deconfigure(struct chp_id chpid);
62int chp_info_get_status(struct chp_id chpid); 62int chp_info_get_status(struct chp_id chpid);
63int chp_ssd_get_mask(struct chsc_ssd_info *, struct res_acc_data *); 63int chp_ssd_get_mask(struct chsc_ssd_info *, struct chp_link *);
64#endif /* S390_CHP_H */ 64#endif /* S390_CHP_H */
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 62b0b16fe3d3..e23c3806972a 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -146,15 +146,18 @@ out_unreg:
146void chsc_chp_offline(struct chp_id chpid) 146void chsc_chp_offline(struct chp_id chpid)
147{ 147{
148 char dbf_txt[15]; 148 char dbf_txt[15];
149 struct chp_link link;
149 150
150 sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id); 151 sprintf(dbf_txt, "chpr%x.%02x", chpid.cssid, chpid.id);
151 CIO_TRACE_EVENT(2, dbf_txt); 152 CIO_TRACE_EVENT(2, dbf_txt);
152 153
153 if (chp_get_status(chpid) <= 0) 154 if (chp_get_status(chpid) <= 0)
154 return; 155 return;
156 memset(&link, 0, sizeof(struct chp_link));
157 link.chpid = chpid;
155 /* Wait until previous actions have settled. */ 158 /* Wait until previous actions have settled. */
156 css_wait_for_slow_path(); 159 css_wait_for_slow_path();
157 for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &chpid); 160 for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link);
158} 161}
159 162
160static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data) 163static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data)
@@ -187,15 +190,15 @@ static int __s390_process_res_acc(struct subchannel *sch, void *data)
187 return 0; 190 return 0;
188} 191}
189 192
190static void s390_process_res_acc (struct res_acc_data *res_data) 193static void s390_process_res_acc(struct chp_link *link)
191{ 194{
192 char dbf_txt[15]; 195 char dbf_txt[15];
193 196
194 sprintf(dbf_txt, "accpr%x.%02x", res_data->chpid.cssid, 197 sprintf(dbf_txt, "accpr%x.%02x", link->chpid.cssid,
195 res_data->chpid.id); 198 link->chpid.id);
196 CIO_TRACE_EVENT( 2, dbf_txt); 199 CIO_TRACE_EVENT( 2, dbf_txt);
197 if (res_data->fla != 0) { 200 if (link->fla != 0) {
198 sprintf(dbf_txt, "fla%x", res_data->fla); 201 sprintf(dbf_txt, "fla%x", link->fla);
199 CIO_TRACE_EVENT( 2, dbf_txt); 202 CIO_TRACE_EVENT( 2, dbf_txt);
200 } 203 }
201 /* Wait until previous actions have settled. */ 204 /* Wait until previous actions have settled. */
@@ -208,7 +211,7 @@ static void s390_process_res_acc (struct res_acc_data *res_data)
208 * will we have to do. 211 * will we have to do.
209 */ 212 */
210 for_each_subchannel_staged(__s390_process_res_acc, 213 for_each_subchannel_staged(__s390_process_res_acc,
211 s390_process_res_acc_new_sch, res_data); 214 s390_process_res_acc_new_sch, link);
212} 215}
213 216
214static int 217static int
@@ -281,7 +284,7 @@ static void chsc_process_sei_link_incident(struct chsc_sei_area *sei_area)
281 284
282static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area) 285static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
283{ 286{
284 struct res_acc_data res_data; 287 struct chp_link link;
285 struct chp_id chpid; 288 struct chp_id chpid;
286 int status; 289 int status;
287 290
@@ -297,18 +300,18 @@ static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
297 chp_new(chpid); 300 chp_new(chpid);
298 else if (!status) 301 else if (!status)
299 return; 302 return;
300 memset(&res_data, 0, sizeof(struct res_acc_data)); 303 memset(&link, 0, sizeof(struct chp_link));
301 res_data.chpid = chpid; 304 link.chpid = chpid;
302 if ((sei_area->vf & 0xc0) != 0) { 305 if ((sei_area->vf & 0xc0) != 0) {
303 res_data.fla = sei_area->fla; 306 link.fla = sei_area->fla;
304 if ((sei_area->vf & 0xc0) == 0xc0) 307 if ((sei_area->vf & 0xc0) == 0xc0)
305 /* full link address */ 308 /* full link address */
306 res_data.fla_mask = 0xffff; 309 link.fla_mask = 0xffff;
307 else 310 else
308 /* link address */ 311 /* link address */
309 res_data.fla_mask = 0xff00; 312 link.fla_mask = 0xff00;
310 } 313 }
311 s390_process_res_acc(&res_data); 314 s390_process_res_acc(&link);
312} 315}
313 316
314struct chp_config_data { 317struct chp_config_data {
@@ -413,18 +416,18 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow)
413void chsc_chp_online(struct chp_id chpid) 416void chsc_chp_online(struct chp_id chpid)
414{ 417{
415 char dbf_txt[15]; 418 char dbf_txt[15];
416 struct res_acc_data res_data; 419 struct chp_link link;
417 420
418 sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id); 421 sprintf(dbf_txt, "cadd%x.%02x", chpid.cssid, chpid.id);
419 CIO_TRACE_EVENT(2, dbf_txt); 422 CIO_TRACE_EVENT(2, dbf_txt);
420 423
421 if (chp_get_status(chpid) != 0) { 424 if (chp_get_status(chpid) != 0) {
422 memset(&res_data, 0, sizeof(struct res_acc_data)); 425 memset(&link, 0, sizeof(struct chp_link));
423 res_data.chpid = chpid; 426 link.chpid = chpid;
424 /* Wait until previous actions have settled. */ 427 /* Wait until previous actions have settled. */
425 css_wait_for_slow_path(); 428 css_wait_for_slow_path();
426 for_each_subchannel_staged(__s390_process_res_acc, NULL, 429 for_each_subchannel_staged(__s390_process_res_acc, NULL,
427 &res_data); 430 &link);
428 } 431 }
429} 432}
430 433
@@ -432,13 +435,13 @@ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
432 struct chp_id chpid, int on) 435 struct chp_id chpid, int on)
433{ 436{
434 unsigned long flags; 437 unsigned long flags;
435 struct res_acc_data res_data; 438 struct chp_link link;
436 439
437 memset(&res_data, 0, sizeof(struct res_acc_data)); 440 memset(&link, 0, sizeof(struct chp_link));
438 res_data.chpid = chpid; 441 link.chpid = chpid;
439 spin_lock_irqsave(sch->lock, flags); 442 spin_lock_irqsave(sch->lock, flags);
440 if (sch->driver && sch->driver->chp_event) 443 if (sch->driver && sch->driver->chp_event)
441 sch->driver->chp_event(sch, &res_data, 444 sch->driver->chp_event(sch, &link,
442 on ? CHP_VARY_ON : CHP_VARY_OFF); 445 on ? CHP_VARY_ON : CHP_VARY_OFF);
443 spin_unlock_irqrestore(sch->lock, flags); 446 spin_unlock_irqrestore(sch->lock, flags);
444} 447}
@@ -479,6 +482,10 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data)
479 */ 482 */
480int chsc_chp_vary(struct chp_id chpid, int on) 483int chsc_chp_vary(struct chp_id chpid, int on)
481{ 484{
485 struct chp_link link;
486
487 memset(&link, 0, sizeof(struct chp_link));
488 link.chpid = chpid;
482 /* Wait until previous actions have settled. */ 489 /* Wait until previous actions have settled. */
483 css_wait_for_slow_path(); 490 css_wait_for_slow_path();
484 /* 491 /*
@@ -487,10 +494,10 @@ int chsc_chp_vary(struct chp_id chpid, int on)
487 494
488 if (on) 495 if (on)
489 for_each_subchannel_staged(s390_subchannel_vary_chpid_on, 496 for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
490 __s390_vary_chpid_on, &chpid); 497 __s390_vary_chpid_on, &link);
491 else 498 else
492 for_each_subchannel_staged(s390_subchannel_vary_chpid_off, 499 for_each_subchannel_staged(s390_subchannel_vary_chpid_off,
493 NULL, &chpid); 500 NULL, &link);
494 501
495 return 0; 502 return 0;
496} 503}
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 3ec3dc5a1e5e..38bf9ddb8412 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -59,6 +59,7 @@ struct pgid {
59} __attribute__ ((packed)); 59} __attribute__ ((packed));
60 60
61struct subchannel; 61struct subchannel;
62struct chp_link;
62/** 63/**
63 * struct css_driver - device driver for subchannels 64 * struct css_driver - device driver for subchannels
64 * @owner: owning module 65 * @owner: owning module
@@ -77,7 +78,7 @@ struct css_driver {
77 unsigned int subchannel_type; 78 unsigned int subchannel_type;
78 struct device_driver drv; 79 struct device_driver drv;
79 void (*irq)(struct subchannel *); 80 void (*irq)(struct subchannel *);
80 int (*chp_event)(struct subchannel *, void *, int); 81 int (*chp_event)(struct subchannel *, struct chp_link *, int);
81 int (*sch_event)(struct subchannel *, int); 82 int (*sch_event)(struct subchannel *, int);
82 int (*probe)(struct subchannel *); 83 int (*probe)(struct subchannel *);
83 int (*remove)(struct subchannel *); 84 int (*remove)(struct subchannel *);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 67e7a3123954..522d47afc950 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -128,7 +128,8 @@ static int io_subchannel_probe(struct subchannel *);
128static int io_subchannel_remove(struct subchannel *); 128static int io_subchannel_remove(struct subchannel *);
129static void io_subchannel_shutdown(struct subchannel *); 129static void io_subchannel_shutdown(struct subchannel *);
130static int io_subchannel_sch_event(struct subchannel *, int); 130static int io_subchannel_sch_event(struct subchannel *, int);
131static int io_subchannel_chp_event(struct subchannel *, void *, int); 131static int io_subchannel_chp_event(struct subchannel *, struct chp_link *,
132 int);
132 133
133static struct css_driver io_subchannel_driver = { 134static struct css_driver io_subchannel_driver = {
134 .owner = THIS_MODULE, 135 .owner = THIS_MODULE,
@@ -1329,14 +1330,12 @@ static void io_subchannel_terminate_path(struct subchannel *sch, u8 mask)
1329 1330
1330} 1331}
1331 1332
1332static int io_subchannel_chp_event(struct subchannel *sch, void *data, 1333static int io_subchannel_chp_event(struct subchannel *sch,
1333 int event) 1334 struct chp_link *link, int event)
1334{ 1335{
1335 int mask; 1336 int mask;
1336 struct res_acc_data *res_data;
1337 1337
1338 res_data = data; 1338 mask = chp_ssd_get_mask(&sch->ssd_info, link);
1339 mask = chp_ssd_get_mask(&sch->ssd_info, res_data);
1340 if (!mask) 1339 if (!mask)
1341 return 0; 1340 return 0;
1342 switch (event) { 1341 switch (event) {