diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2008-07-14 03:59:02 -0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-07-14 04:02:11 -0400 |
commit | 99611f87176b2a908d8c66ab19a5fc550a3cd13a (patch) | |
tree | 2c9898f347d00aeab5ffcbf74c90469efb86043e /drivers/s390/cio | |
parent | 6ef556ccc8fd256259745c4f0d0ab65aaf703824 (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/cio')
-rw-r--r-- | drivers/s390/cio/chp.c | 6 | ||||
-rw-r--r-- | drivers/s390/cio/chp.h | 4 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.c | 55 | ||||
-rw-r--r-- | drivers/s390/cio/css.h | 3 | ||||
-rw-r--r-- | drivers/s390/cio/device.c | 11 |
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 | ||
528 | int chp_ssd_get_mask(struct chsc_ssd_info *ssd, struct res_acc_data *data) | 528 | int 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 | ||
27 | struct res_acc_data { | 27 | struct 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); | |||
60 | void chp_cfg_schedule(struct chp_id chpid, int configure); | 60 | void chp_cfg_schedule(struct chp_id chpid, int configure); |
61 | void chp_cfg_cancel_deconfigure(struct chp_id chpid); | 61 | void chp_cfg_cancel_deconfigure(struct chp_id chpid); |
62 | int chp_info_get_status(struct chp_id chpid); | 62 | int chp_info_get_status(struct chp_id chpid); |
63 | int chp_ssd_get_mask(struct chsc_ssd_info *, struct res_acc_data *); | 63 | int 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: | |||
146 | void chsc_chp_offline(struct chp_id chpid) | 146 | void 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 | ||
160 | static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data) | 163 | static 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 | ||
190 | static void s390_process_res_acc (struct res_acc_data *res_data) | 193 | static 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 | ||
214 | static int | 217 | static int |
@@ -281,7 +284,7 @@ static void chsc_process_sei_link_incident(struct chsc_sei_area *sei_area) | |||
281 | 284 | ||
282 | static void chsc_process_sei_res_acc(struct chsc_sei_area *sei_area) | 285 | static 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 | ||
314 | struct chp_config_data { | 317 | struct chp_config_data { |
@@ -413,18 +416,18 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
413 | void chsc_chp_online(struct chp_id chpid) | 416 | void 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 | */ |
480 | int chsc_chp_vary(struct chp_id chpid, int on) | 483 | int 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 | ||
61 | struct subchannel; | 61 | struct subchannel; |
62 | struct 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 *); | |||
128 | static int io_subchannel_remove(struct subchannel *); | 128 | static int io_subchannel_remove(struct subchannel *); |
129 | static void io_subchannel_shutdown(struct subchannel *); | 129 | static void io_subchannel_shutdown(struct subchannel *); |
130 | static int io_subchannel_sch_event(struct subchannel *, int); | 130 | static int io_subchannel_sch_event(struct subchannel *, int); |
131 | static int io_subchannel_chp_event(struct subchannel *, void *, int); | 131 | static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, |
132 | int); | ||
132 | 133 | ||
133 | static struct css_driver io_subchannel_driver = { | 134 | static 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 | ||
1332 | static int io_subchannel_chp_event(struct subchannel *sch, void *data, | 1333 | static 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) { |