diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2013-01-15 13:02:01 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-01-16 09:57:54 -0500 |
commit | 509d97b6f91b51e180ba26ddb1e2b7f6dfa80cba (patch) | |
tree | d5381a3ba2c206c91dd3ed1ae9447f12af534479 /drivers | |
parent | ed4f20943cd4c7b55105c04daedf8d63ab6d499c (diff) |
s390/chsc: fix SEI usage
cbc0dd1 "s390/pci: CHSC PCI support for error and availability events"
introduced a new SEI notification type as part of pci support.
The way SEI was called with nt2 and nt0 consecutive broke the nt0
stuff used for channel subsystem notifications.
The reason why this was broken with the mentioned patch is that you
cannot selectively disable type 0 notifications (so even when asked
for type 2 only, type 0 could be presented).
The way to do it is to tell SEI which types of notification you can
process and -this is the important part- look at the SEI result which
notification type you actually received.
Reviewed-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
Tested-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/cio/chsc.c | 31 |
1 files changed, 12 insertions, 19 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 68e80e2734a4..10729bbceced 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -283,7 +283,7 @@ struct chsc_sei_nt2_area { | |||
283 | u8 ccdf[PAGE_SIZE - 24 - 56]; /* content-code dependent field */ | 283 | u8 ccdf[PAGE_SIZE - 24 - 56]; /* content-code dependent field */ |
284 | } __packed; | 284 | } __packed; |
285 | 285 | ||
286 | #define CHSC_SEI_NT0 0ULL | 286 | #define CHSC_SEI_NT0 (1ULL << 63) |
287 | #define CHSC_SEI_NT2 (1ULL << 61) | 287 | #define CHSC_SEI_NT2 (1ULL << 61) |
288 | 288 | ||
289 | struct chsc_sei { | 289 | struct chsc_sei { |
@@ -291,7 +291,8 @@ struct chsc_sei { | |||
291 | u32 reserved1; | 291 | u32 reserved1; |
292 | u64 ntsm; /* notification type mask */ | 292 | u64 ntsm; /* notification type mask */ |
293 | struct chsc_header response; | 293 | struct chsc_header response; |
294 | u32 reserved2; | 294 | u32 :24; |
295 | u8 nt; | ||
295 | union { | 296 | union { |
296 | struct chsc_sei_nt0_area nt0_area; | 297 | struct chsc_sei_nt0_area nt0_area; |
297 | struct chsc_sei_nt2_area nt2_area; | 298 | struct chsc_sei_nt2_area nt2_area; |
@@ -496,17 +497,17 @@ static int __chsc_process_crw(struct chsc_sei *sei, u64 ntsm) | |||
496 | css_schedule_eval_all(); | 497 | css_schedule_eval_all(); |
497 | } | 498 | } |
498 | 499 | ||
499 | switch (sei->ntsm) { | 500 | switch (sei->nt) { |
500 | case CHSC_SEI_NT0: | 501 | case 0: |
501 | chsc_process_sei_nt0(&sei->u.nt0_area); | 502 | chsc_process_sei_nt0(&sei->u.nt0_area); |
502 | return 1; | 503 | break; |
503 | case CHSC_SEI_NT2: | 504 | case 2: |
504 | chsc_process_sei_nt2(&sei->u.nt2_area); | 505 | chsc_process_sei_nt2(&sei->u.nt2_area); |
505 | return 1; | 506 | break; |
506 | default: | 507 | default: |
507 | CIO_CRW_EVENT(2, "chsc: unhandled nt (nt=%08Lx)\n", | 508 | CIO_CRW_EVENT(2, "chsc: unhandled nt=%d\n", |
508 | sei->ntsm); | 509 | sei->nt); |
509 | return 0; | 510 | break; |
510 | } | 511 | } |
511 | } else { | 512 | } else { |
512 | CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", | 513 | CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", |
@@ -537,15 +538,7 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
537 | sei = sei_page; | 538 | sei = sei_page; |
538 | 539 | ||
539 | CIO_TRACE_EVENT(2, "prcss"); | 540 | CIO_TRACE_EVENT(2, "prcss"); |
540 | 541 | __chsc_process_crw(sei, CHSC_SEI_NT0 | CHSC_SEI_NT2); | |
541 | /* | ||
542 | * The ntsm does not allow to select NT0 and NT2 together. We need to | ||
543 | * first check for NT2, than additionally for NT0... | ||
544 | */ | ||
545 | #ifdef CONFIG_PCI | ||
546 | if (!__chsc_process_crw(sei, CHSC_SEI_NT2)) | ||
547 | #endif | ||
548 | __chsc_process_crw(sei, CHSC_SEI_NT0); | ||
549 | } | 542 | } |
550 | 543 | ||
551 | void chsc_chp_online(struct chp_id chpid) | 544 | void chsc_chp_online(struct chp_id chpid) |