diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2008-07-14 03:58:46 -0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-07-14 04:02:06 -0400 |
commit | c11561897ab57a3c11e0a284ba17795d580589ab (patch) | |
tree | 53224c4e8062a85b1794a3cabe81a86317538dfa /drivers/s390 | |
parent | c820de39bd083222f5be2563181c87493e436f7c (diff) |
[S390] cio: Cleanup crw interface.
Eliminate the need for the machine check handler to call into
the common I/O layer directly by introducing an interface to
register handlers for crws per rsc.
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.c | 49 | ||||
-rw-r--r-- | drivers/s390/cio/chp.h | 1 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.c | 25 | ||||
-rw-r--r-- | drivers/s390/cio/chsc.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/css.c | 31 | ||||
-rw-r--r-- | drivers/s390/cio/css.h | 1 | ||||
-rw-r--r-- | drivers/s390/s390mach.c | 102 | ||||
-rw-r--r-- | drivers/s390/s390mach.h | 7 |
8 files changed, 140 insertions, 78 deletions
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 297f1653b52b..672d9731c525 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/chpid.h> | 18 | #include <asm/chpid.h> |
19 | #include <asm/sclp.h> | 19 | #include <asm/sclp.h> |
20 | 20 | ||
21 | #include "../s390mach.h" | ||
21 | #include "cio.h" | 22 | #include "cio.h" |
22 | #include "css.h" | 23 | #include "css.h" |
23 | #include "ioasm.h" | 24 | #include "ioasm.h" |
@@ -476,24 +477,52 @@ void *chp_get_chp_desc(struct chp_id chpid) | |||
476 | 477 | ||
477 | /** | 478 | /** |
478 | * chp_process_crw - process channel-path status change | 479 | * chp_process_crw - process channel-path status change |
479 | * @id: channel-path ID number | 480 | * @crw0: channel report-word to handler |
480 | * @status: non-zero if channel-path has become available, zero otherwise | 481 | * @crw1: second channel-report word (always NULL) |
482 | * @overflow: crw overflow indication | ||
481 | * | 483 | * |
482 | * Handle channel-report-words indicating that the status of a channel-path | 484 | * Handle channel-report-words indicating that the status of a channel-path |
483 | * has changed. | 485 | * has changed. |
484 | */ | 486 | */ |
485 | void chp_process_crw(int id, int status) | 487 | static void chp_process_crw(struct crw *crw0, struct crw *crw1, |
488 | int overflow) | ||
486 | { | 489 | { |
487 | struct chp_id chpid; | 490 | struct chp_id chpid; |
488 | 491 | ||
492 | if (overflow) { | ||
493 | css_schedule_eval_all(); | ||
494 | return; | ||
495 | } | ||
496 | CIO_CRW_EVENT(2, "CRW reports slct=%d, oflw=%d, " | ||
497 | "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", | ||
498 | crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc, | ||
499 | crw0->erc, crw0->rsid); | ||
500 | /* | ||
501 | * Check for solicited machine checks. These are | ||
502 | * created by reset channel path and need not be | ||
503 | * handled here. | ||
504 | */ | ||
505 | if (crw0->slct) { | ||
506 | CIO_CRW_EVENT(2, "solicited machine check for " | ||
507 | "channel path %02X\n", crw0->rsid); | ||
508 | return; | ||
509 | } | ||
489 | chp_id_init(&chpid); | 510 | chp_id_init(&chpid); |
490 | chpid.id = id; | 511 | chpid.id = crw0->rsid; |
491 | if (status) { | 512 | switch (crw0->erc) { |
513 | case CRW_ERC_IPARM: /* Path has come. */ | ||
492 | if (!chp_is_registered(chpid)) | 514 | if (!chp_is_registered(chpid)) |
493 | chp_new(chpid); | 515 | chp_new(chpid); |
494 | chsc_chp_online(chpid); | 516 | chsc_chp_online(chpid); |
495 | } else | 517 | break; |
518 | case CRW_ERC_PERRI: /* Path has gone. */ | ||
519 | case CRW_ERC_PERRN: | ||
496 | chsc_chp_offline(chpid); | 520 | chsc_chp_offline(chpid); |
521 | break; | ||
522 | default: | ||
523 | CIO_CRW_EVENT(2, "Don't know how to handle erc=%x\n", | ||
524 | crw0->erc); | ||
525 | } | ||
497 | } | 526 | } |
498 | 527 | ||
499 | 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 res_acc_data *data) |
@@ -674,10 +703,16 @@ static int cfg_wait_idle(void) | |||
674 | static int __init chp_init(void) | 703 | static int __init chp_init(void) |
675 | { | 704 | { |
676 | struct chp_id chpid; | 705 | struct chp_id chpid; |
706 | int ret; | ||
677 | 707 | ||
708 | ret = s390_register_crw_handler(CRW_RSC_CPATH, chp_process_crw); | ||
709 | if (ret) | ||
710 | return ret; | ||
678 | chp_wq = create_singlethread_workqueue("cio_chp"); | 711 | chp_wq = create_singlethread_workqueue("cio_chp"); |
679 | if (!chp_wq) | 712 | if (!chp_wq) { |
713 | s390_unregister_crw_handler(CRW_RSC_CPATH); | ||
680 | return -ENOMEM; | 714 | return -ENOMEM; |
715 | } | ||
681 | INIT_WORK(&cfg_work, cfg_func); | 716 | INIT_WORK(&cfg_work, cfg_func); |
682 | init_waitqueue_head(&cfg_wait_queue); | 717 | init_waitqueue_head(&cfg_wait_queue); |
683 | if (info_update()) | 718 | if (info_update()) |
diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h index f03b0d2cdc09..dffe2771ddac 100644 --- a/drivers/s390/cio/chp.h +++ b/drivers/s390/cio/chp.h | |||
@@ -54,7 +54,6 @@ int chp_get_status(struct chp_id chpid); | |||
54 | u8 chp_get_sch_opm(struct subchannel *sch); | 54 | u8 chp_get_sch_opm(struct subchannel *sch); |
55 | int chp_is_registered(struct chp_id chpid); | 55 | int chp_is_registered(struct chp_id chpid); |
56 | void *chp_get_chp_desc(struct chp_id chpid); | 56 | void *chp_get_chp_desc(struct chp_id chpid); |
57 | void chp_process_crw(int id, int available); | ||
58 | void chp_remove_cmg_attr(struct channel_path *chp); | 57 | void chp_remove_cmg_attr(struct channel_path *chp); |
59 | int chp_add_cmg_attr(struct channel_path *chp); | 58 | int chp_add_cmg_attr(struct channel_path *chp); |
60 | int chp_new(struct chp_id chpid); | 59 | int chp_new(struct chp_id chpid); |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 1c0f5db94c7b..cb36f7929786 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/cio.h> | 16 | #include <asm/cio.h> |
17 | #include <asm/chpid.h> | 17 | #include <asm/chpid.h> |
18 | 18 | ||
19 | #include "../s390mach.h" | ||
19 | #include "css.h" | 20 | #include "css.h" |
20 | #include "cio.h" | 21 | #include "cio.h" |
21 | #include "cio_debug.h" | 22 | #include "cio_debug.h" |
@@ -372,17 +373,25 @@ static void chsc_process_sei(struct chsc_sei_area *sei_area) | |||
372 | } | 373 | } |
373 | } | 374 | } |
374 | 375 | ||
375 | void chsc_process_crw(void) | 376 | static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow) |
376 | { | 377 | { |
377 | struct chsc_sei_area *sei_area; | 378 | struct chsc_sei_area *sei_area; |
378 | 379 | ||
380 | if (overflow) { | ||
381 | css_schedule_eval_all(); | ||
382 | return; | ||
383 | } | ||
384 | CIO_CRW_EVENT(2, "CRW reports slct=%d, oflw=%d, " | ||
385 | "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", | ||
386 | crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc, | ||
387 | crw0->erc, crw0->rsid); | ||
379 | if (!sei_page) | 388 | if (!sei_page) |
380 | return; | 389 | return; |
381 | /* Access to sei_page is serialized through machine check handler | 390 | /* Access to sei_page is serialized through machine check handler |
382 | * thread, so no need for locking. */ | 391 | * thread, so no need for locking. */ |
383 | sei_area = sei_page; | 392 | sei_area = sei_page; |
384 | 393 | ||
385 | CIO_TRACE_EVENT( 2, "prcss"); | 394 | CIO_TRACE_EVENT(2, "prcss"); |
386 | do { | 395 | do { |
387 | memset(sei_area, 0, sizeof(*sei_area)); | 396 | memset(sei_area, 0, sizeof(*sei_area)); |
388 | sei_area->request.length = 0x0010; | 397 | sei_area->request.length = 0x0010; |
@@ -751,15 +760,23 @@ out: | |||
751 | 760 | ||
752 | int __init chsc_alloc_sei_area(void) | 761 | int __init chsc_alloc_sei_area(void) |
753 | { | 762 | { |
763 | int ret; | ||
764 | |||
754 | sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 765 | sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
755 | if (!sei_page) | 766 | if (!sei_page) { |
756 | CIO_MSG_EVENT(0, "Can't allocate page for processing of " | 767 | CIO_MSG_EVENT(0, "Can't allocate page for processing of " |
757 | "chsc machine checks!\n"); | 768 | "chsc machine checks!\n"); |
758 | return (sei_page ? 0 : -ENOMEM); | 769 | return -ENOMEM; |
770 | } | ||
771 | ret = s390_register_crw_handler(CRW_RSC_CSS, chsc_process_crw); | ||
772 | if (ret) | ||
773 | kfree(sei_page); | ||
774 | return ret; | ||
759 | } | 775 | } |
760 | 776 | ||
761 | void __init chsc_free_sei_area(void) | 777 | void __init chsc_free_sei_area(void) |
762 | { | 778 | { |
779 | s390_unregister_crw_handler(CRW_RSC_CSS); | ||
763 | kfree(sei_page); | 780 | kfree(sei_page); |
764 | } | 781 | } |
765 | 782 | ||
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index d1f5db1e69b9..3b7c044d8453 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -36,8 +36,6 @@ struct channel_path_desc { | |||
36 | 36 | ||
37 | struct channel_path; | 37 | struct channel_path; |
38 | 38 | ||
39 | extern void chsc_process_crw(void); | ||
40 | |||
41 | struct css_general_char { | 39 | struct css_general_char { |
42 | u64 : 41; | 40 | u64 : 41; |
43 | u32 aif : 1; /* bit 41 */ | 41 | u32 aif : 1; /* bit 41 */ |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 020566571e07..cf9d27c6f444 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
15 | #include <linux/reboot.h> | 15 | #include <linux/reboot.h> |
16 | 16 | ||
17 | #include "../s390mach.h" | ||
17 | #include "css.h" | 18 | #include "css.h" |
18 | #include "cio.h" | 19 | #include "cio.h" |
19 | #include "cio_debug.h" | 20 | #include "cio_debug.h" |
@@ -530,18 +531,29 @@ EXPORT_SYMBOL_GPL(css_schedule_reprobe); | |||
530 | /* | 531 | /* |
531 | * Called from the machine check handler for subchannel report words. | 532 | * Called from the machine check handler for subchannel report words. |
532 | */ | 533 | */ |
533 | void css_process_crw(int rsid1, int rsid2) | 534 | static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) |
534 | { | 535 | { |
535 | struct subchannel_id mchk_schid; | 536 | struct subchannel_id mchk_schid; |
536 | 537 | ||
537 | CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n", | 538 | if (overflow) { |
538 | rsid1, rsid2); | 539 | css_schedule_eval_all(); |
540 | return; | ||
541 | } | ||
542 | CIO_CRW_EVENT(2, "CRW0 reports slct=%d, oflw=%d, " | ||
543 | "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", | ||
544 | crw0->slct, crw0->oflw, crw0->chn, crw0->rsc, crw0->anc, | ||
545 | crw0->erc, crw0->rsid); | ||
546 | if (crw1) | ||
547 | CIO_CRW_EVENT(2, "CRW1 reports slct=%d, oflw=%d, " | ||
548 | "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", | ||
549 | crw1->slct, crw1->oflw, crw1->chn, crw1->rsc, | ||
550 | crw1->anc, crw1->erc, crw1->rsid); | ||
539 | init_subchannel_id(&mchk_schid); | 551 | init_subchannel_id(&mchk_schid); |
540 | mchk_schid.sch_no = rsid1; | 552 | mchk_schid.sch_no = crw0->rsid; |
541 | if (rsid2 != 0) | 553 | if (crw1) |
542 | mchk_schid.ssid = (rsid2 >> 8) & 3; | 554 | mchk_schid.ssid = (crw1->rsid >> 8) & 3; |
543 | 555 | ||
544 | /* | 556 | /* |
545 | * Since we are always presented with IPI in the CRW, we have to | 557 | * Since we are always presented with IPI in the CRW, we have to |
546 | * use stsch() to find out if the subchannel in question has come | 558 | * use stsch() to find out if the subchannel in question has come |
547 | * or gone. | 559 | * or gone. |
@@ -740,6 +752,10 @@ init_channel_subsystem (void) | |||
740 | if (ret) | 752 | if (ret) |
741 | goto out; | 753 | goto out; |
742 | 754 | ||
755 | ret = s390_register_crw_handler(CRW_RSC_SCH, css_process_crw); | ||
756 | if (ret) | ||
757 | goto out; | ||
758 | |||
743 | if ((ret = bus_register(&css_bus_type))) | 759 | if ((ret = bus_register(&css_bus_type))) |
744 | goto out; | 760 | goto out; |
745 | 761 | ||
@@ -817,6 +833,7 @@ out_unregister: | |||
817 | out_bus: | 833 | out_bus: |
818 | bus_unregister(&css_bus_type); | 834 | bus_unregister(&css_bus_type); |
819 | out: | 835 | out: |
836 | s390_unregister_crw_handler(CRW_RSC_CSS); | ||
820 | chsc_free_sei_area(); | 837 | chsc_free_sei_area(); |
821 | kfree(slow_subchannel_set); | 838 | kfree(slow_subchannel_set); |
822 | printk(KERN_WARNING"cio: failed to initialize css driver (%d)!\n", | 839 | printk(KERN_WARNING"cio: failed to initialize css driver (%d)!\n", |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 4cdc132c86bb..3ec3dc5a1e5e 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -103,7 +103,6 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), | |||
103 | int (*fn_unknown)(struct subchannel_id, | 103 | int (*fn_unknown)(struct subchannel_id, |
104 | void *), void *data); | 104 | void *), void *data); |
105 | extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); | 105 | extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); |
106 | extern void css_process_crw(int, int); | ||
107 | extern void css_reiterate_subchannels(void); | 106 | extern void css_reiterate_subchannels(void); |
108 | void css_update_ssd_info(struct subchannel *sch); | 107 | void css_update_ssd_info(struct subchannel *sch); |
109 | 108 | ||
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 5bfbe7659830..fe75152a5084 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c | |||
@@ -2,10 +2,10 @@ | |||
2 | * drivers/s390/s390mach.c | 2 | * drivers/s390/s390mach.c |
3 | * S/390 machine check handler | 3 | * S/390 machine check handler |
4 | * | 4 | * |
5 | * S390 version | 5 | * Copyright IBM Corp. 2000,2008 |
6 | * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation | ||
7 | * Author(s): Ingo Adlung (adlung@de.ibm.com) | 6 | * Author(s): Ingo Adlung (adlung@de.ibm.com) |
8 | * Martin Schwidefsky (schwidefsky@de.ibm.com) | 7 | * Martin Schwidefsky (schwidefsky@de.ibm.com) |
8 | * Cornelia Huck <cornelia.huck@de.ibm.com> | ||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
@@ -18,10 +18,6 @@ | |||
18 | #include <asm/etr.h> | 18 | #include <asm/etr.h> |
19 | #include <asm/lowcore.h> | 19 | #include <asm/lowcore.h> |
20 | #include <asm/cio.h> | 20 | #include <asm/cio.h> |
21 | #include "cio/cio.h" | ||
22 | #include "cio/chsc.h" | ||
23 | #include "cio/css.h" | ||
24 | #include "cio/chp.h" | ||
25 | #include "s390mach.h" | 21 | #include "s390mach.h" |
26 | 22 | ||
27 | static struct semaphore m_sem; | 23 | static struct semaphore m_sem; |
@@ -36,13 +32,40 @@ s390_handle_damage(char *msg) | |||
36 | for(;;); | 32 | for(;;); |
37 | } | 33 | } |
38 | 34 | ||
35 | static crw_handler_t crw_handlers[NR_RSCS]; | ||
36 | |||
37 | /** | ||
38 | * s390_register_crw_handler() - register a channel report word handler | ||
39 | * @rsc: reporting source code to handle | ||
40 | * @handler: handler to be registered | ||
41 | * | ||
42 | * Returns %0 on success and a negative error value otherwise. | ||
43 | */ | ||
44 | int s390_register_crw_handler(int rsc, crw_handler_t handler) | ||
45 | { | ||
46 | if ((rsc < 0) || (rsc >= NR_RSCS)) | ||
47 | return -EINVAL; | ||
48 | if (!cmpxchg(&crw_handlers[rsc], NULL, handler)) | ||
49 | return 0; | ||
50 | return -EBUSY; | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * s390_unregister_crw_handler() - unregister a channel report word handler | ||
55 | * @rsc: reporting source code to handle | ||
56 | */ | ||
57 | void s390_unregister_crw_handler(int rsc) | ||
58 | { | ||
59 | if ((rsc < 0) || (rsc >= NR_RSCS)) | ||
60 | return; | ||
61 | xchg(&crw_handlers[rsc], NULL); | ||
62 | synchronize_sched(); | ||
63 | } | ||
64 | |||
39 | /* | 65 | /* |
40 | * Retrieve CRWs and call function to handle event. | 66 | * Retrieve CRWs and call function to handle event. |
41 | * | ||
42 | * Note : we currently process CRWs for io and chsc subchannels only | ||
43 | */ | 67 | */ |
44 | static int | 68 | static int s390_collect_crw_info(void *param) |
45 | s390_collect_crw_info(void *param) | ||
46 | { | 69 | { |
47 | struct crw crw[2]; | 70 | struct crw crw[2]; |
48 | int ccode; | 71 | int ccode; |
@@ -84,57 +107,24 @@ repeat: | |||
84 | crw[chain].rsid); | 107 | crw[chain].rsid); |
85 | /* Check for overflows. */ | 108 | /* Check for overflows. */ |
86 | if (crw[chain].oflw) { | 109 | if (crw[chain].oflw) { |
110 | int i; | ||
111 | |||
87 | pr_debug("%s: crw overflow detected!\n", __func__); | 112 | pr_debug("%s: crw overflow detected!\n", __func__); |
88 | css_schedule_eval_all(); | 113 | for (i = 0; i < NR_RSCS; i++) { |
114 | if (crw_handlers[i]) | ||
115 | crw_handlers[i](NULL, NULL, 1); | ||
116 | } | ||
89 | chain = 0; | 117 | chain = 0; |
90 | continue; | 118 | continue; |
91 | } | 119 | } |
92 | switch (crw[chain].rsc) { | 120 | if (crw[0].chn && !chain) { |
93 | case CRW_RSC_SCH: | 121 | chain++; |
94 | if (crw[0].chn && !chain) | 122 | continue; |
95 | break; | ||
96 | pr_debug("source is subchannel %04X\n", crw[0].rsid); | ||
97 | css_process_crw(crw[0].rsid, chain ? crw[1].rsid : 0); | ||
98 | break; | ||
99 | case CRW_RSC_MONITOR: | ||
100 | pr_debug("source is monitoring facility\n"); | ||
101 | break; | ||
102 | case CRW_RSC_CPATH: | ||
103 | pr_debug("source is channel path %02X\n", crw[0].rsid); | ||
104 | /* | ||
105 | * Check for solicited machine checks. These are | ||
106 | * created by reset channel path and need not be | ||
107 | * reported to the common I/O layer. | ||
108 | */ | ||
109 | if (crw[chain].slct) { | ||
110 | pr_debug("solicited machine check for " | ||
111 | "channel path %02X\n", crw[0].rsid); | ||
112 | break; | ||
113 | } | ||
114 | switch (crw[0].erc) { | ||
115 | case CRW_ERC_IPARM: /* Path has come. */ | ||
116 | chp_process_crw(crw[0].rsid, 1); | ||
117 | break; | ||
118 | case CRW_ERC_PERRI: /* Path has gone. */ | ||
119 | case CRW_ERC_PERRN: | ||
120 | chp_process_crw(crw[0].rsid, 0); | ||
121 | break; | ||
122 | default: | ||
123 | pr_debug("Don't know how to handle erc=%x\n", | ||
124 | crw[0].erc); | ||
125 | } | ||
126 | break; | ||
127 | case CRW_RSC_CONFIG: | ||
128 | pr_debug("source is configuration-alert facility\n"); | ||
129 | break; | ||
130 | case CRW_RSC_CSS: | ||
131 | pr_debug("source is channel subsystem\n"); | ||
132 | chsc_process_crw(); | ||
133 | break; | ||
134 | default: | ||
135 | pr_debug("unknown source\n"); | ||
136 | break; | ||
137 | } | 123 | } |
124 | if (crw_handlers[crw[chain].rsc]) | ||
125 | crw_handlers[crw[chain].rsc](&crw[0], | ||
126 | chain ? &crw[1] : NULL, | ||
127 | 0); | ||
138 | /* chain is always 0 or 1 here. */ | 128 | /* chain is always 0 or 1 here. */ |
139 | chain = crw[chain].chn ? chain + 1 : 0; | 129 | chain = crw[chain].chn ? chain + 1 : 0; |
140 | } | 130 | } |
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h index ca681f9b67fc..f11e574076d8 100644 --- a/drivers/s390/s390mach.h +++ b/drivers/s390/s390mach.h | |||
@@ -72,6 +72,13 @@ struct crw { | |||
72 | __u32 rsid : 16; /* reporting-source ID */ | 72 | __u32 rsid : 16; /* reporting-source ID */ |
73 | } __attribute__ ((packed)); | 73 | } __attribute__ ((packed)); |
74 | 74 | ||
75 | typedef void (*crw_handler_t)(struct crw *, struct crw *, int); | ||
76 | |||
77 | extern int s390_register_crw_handler(int rsc, crw_handler_t handler); | ||
78 | extern void s390_unregister_crw_handler(int rsc); | ||
79 | |||
80 | #define NR_RSCS 16 | ||
81 | |||
75 | #define CRW_RSC_MONITOR 0x2 /* monitoring facility */ | 82 | #define CRW_RSC_MONITOR 0x2 /* monitoring facility */ |
76 | #define CRW_RSC_SCH 0x3 /* subchannel */ | 83 | #define CRW_RSC_SCH 0x3 /* subchannel */ |
77 | #define CRW_RSC_CPATH 0x4 /* channel path */ | 84 | #define CRW_RSC_CPATH 0x4 /* channel path */ |