diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-26 19:04:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-26 19:04:22 -0400 |
commit | 21cdbc1378e8aa96e1ed4a606dce1a8e7daf7fdf (patch) | |
tree | 55b6c294b912ccdc3eede15960b0ece53a69d902 /drivers/s390/cio/css.c | |
parent | 86d9c070175de65890794fa227b68297da6206d8 (diff) | |
parent | ef3500b2b2955af4fa6b0564b51c0c604e38c571 (diff) |
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (81 commits)
[S390] remove duplicated #includes
[S390] cpumask: use mm_cpumask() wrapper
[S390] cpumask: Use accessors code.
[S390] cpumask: prepare for iterators to only go to nr_cpu_ids/nr_cpumask_bits.
[S390] cpumask: remove cpu_coregroup_map
[S390] fix clock comparator save area usage
[S390] Add hwcap flag for the etf3 enhancement facility
[S390] Ensure that ipl panic notifier is called late.
[S390] fix dfp elf hwcap/facility bit detection
[S390] smp: perform initial cpu reset before starting a cpu
[S390] smp: fix memory leak on __cpu_up
[S390] ipl: Improve checking logic and remove switch defaults.
[S390] s390dbf: Remove needless check for NULL pointer.
[S390] s390dbf: Remove redundant initilizations.
[S390] use kzfree()
[S390] BUG to BUG_ON changes
[S390] zfcpdump: Prevent zcore from beeing built as a kernel module.
[S390] Use csum_partial in checksum.h
[S390] cleanup lowcore.h
[S390] eliminate ipl_device from lowcore
...
Diffstat (limited to 'drivers/s390/cio/css.c')
-rw-r--r-- | drivers/s390/cio/css.c | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 427d11d88069..0085d8901792 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -18,8 +18,8 @@ | |||
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/reboot.h> | 19 | #include <linux/reboot.h> |
20 | #include <asm/isc.h> | 20 | #include <asm/isc.h> |
21 | #include <asm/crw.h> | ||
21 | 22 | ||
22 | #include "../s390mach.h" | ||
23 | #include "css.h" | 23 | #include "css.h" |
24 | #include "cio.h" | 24 | #include "cio.h" |
25 | #include "cio_debug.h" | 25 | #include "cio_debug.h" |
@@ -83,6 +83,25 @@ static int call_fn_unknown_sch(struct subchannel_id schid, void *data) | |||
83 | return rc; | 83 | return rc; |
84 | } | 84 | } |
85 | 85 | ||
86 | static int call_fn_all_sch(struct subchannel_id schid, void *data) | ||
87 | { | ||
88 | struct cb_data *cb = data; | ||
89 | struct subchannel *sch; | ||
90 | int rc = 0; | ||
91 | |||
92 | sch = get_subchannel_by_schid(schid); | ||
93 | if (sch) { | ||
94 | if (cb->fn_known_sch) | ||
95 | rc = cb->fn_known_sch(sch, cb->data); | ||
96 | put_device(&sch->dev); | ||
97 | } else { | ||
98 | if (cb->fn_unknown_sch) | ||
99 | rc = cb->fn_unknown_sch(schid, cb->data); | ||
100 | } | ||
101 | |||
102 | return rc; | ||
103 | } | ||
104 | |||
86 | int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), | 105 | int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), |
87 | int (*fn_unknown)(struct subchannel_id, | 106 | int (*fn_unknown)(struct subchannel_id, |
88 | void *), void *data) | 107 | void *), void *data) |
@@ -90,13 +109,17 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), | |||
90 | struct cb_data cb; | 109 | struct cb_data cb; |
91 | int rc; | 110 | int rc; |
92 | 111 | ||
93 | cb.set = idset_sch_new(); | ||
94 | if (!cb.set) | ||
95 | return -ENOMEM; | ||
96 | idset_fill(cb.set); | ||
97 | cb.data = data; | 112 | cb.data = data; |
98 | cb.fn_known_sch = fn_known; | 113 | cb.fn_known_sch = fn_known; |
99 | cb.fn_unknown_sch = fn_unknown; | 114 | cb.fn_unknown_sch = fn_unknown; |
115 | |||
116 | cb.set = idset_sch_new(); | ||
117 | if (!cb.set) | ||
118 | /* fall back to brute force scanning in case of oom */ | ||
119 | return for_each_subchannel(call_fn_all_sch, &cb); | ||
120 | |||
121 | idset_fill(cb.set); | ||
122 | |||
100 | /* Process registered subchannels. */ | 123 | /* Process registered subchannels. */ |
101 | rc = bus_for_each_dev(&css_bus_type, NULL, &cb, call_fn_known_sch); | 124 | rc = bus_for_each_dev(&css_bus_type, NULL, &cb, call_fn_known_sch); |
102 | if (rc) | 125 | if (rc) |
@@ -510,6 +533,17 @@ static int reprobe_subchannel(struct subchannel_id schid, void *data) | |||
510 | return ret; | 533 | return ret; |
511 | } | 534 | } |
512 | 535 | ||
536 | static void reprobe_after_idle(struct work_struct *unused) | ||
537 | { | ||
538 | /* Make sure initial subchannel scan is done. */ | ||
539 | wait_event(ccw_device_init_wq, | ||
540 | atomic_read(&ccw_device_init_count) == 0); | ||
541 | if (need_reprobe) | ||
542 | css_schedule_reprobe(); | ||
543 | } | ||
544 | |||
545 | static DECLARE_WORK(reprobe_idle_work, reprobe_after_idle); | ||
546 | |||
513 | /* Work function used to reprobe all unregistered subchannels. */ | 547 | /* Work function used to reprobe all unregistered subchannels. */ |
514 | static void reprobe_all(struct work_struct *unused) | 548 | static void reprobe_all(struct work_struct *unused) |
515 | { | 549 | { |
@@ -517,10 +551,12 @@ static void reprobe_all(struct work_struct *unused) | |||
517 | 551 | ||
518 | CIO_MSG_EVENT(4, "reprobe start\n"); | 552 | CIO_MSG_EVENT(4, "reprobe start\n"); |
519 | 553 | ||
520 | need_reprobe = 0; | ||
521 | /* Make sure initial subchannel scan is done. */ | 554 | /* Make sure initial subchannel scan is done. */ |
522 | wait_event(ccw_device_init_wq, | 555 | if (atomic_read(&ccw_device_init_count) != 0) { |
523 | atomic_read(&ccw_device_init_count) == 0); | 556 | queue_work(ccw_device_work, &reprobe_idle_work); |
557 | return; | ||
558 | } | ||
559 | need_reprobe = 0; | ||
524 | ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL); | 560 | ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL); |
525 | 561 | ||
526 | CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, | 562 | CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, |
@@ -619,7 +655,7 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | |||
619 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; | 655 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; |
620 | } else { | 656 | } else { |
621 | #ifdef CONFIG_SMP | 657 | #ifdef CONFIG_SMP |
622 | css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id(); | 658 | css->global_pgid.pgid_high.cpu_addr = stap(); |
623 | #else | 659 | #else |
624 | css->global_pgid.pgid_high.cpu_addr = 0; | 660 | css->global_pgid.pgid_high.cpu_addr = 0; |
625 | #endif | 661 | #endif |
@@ -765,7 +801,7 @@ init_channel_subsystem (void) | |||
765 | if (ret) | 801 | if (ret) |
766 | goto out; | 802 | goto out; |
767 | 803 | ||
768 | ret = s390_register_crw_handler(CRW_RSC_SCH, css_process_crw); | 804 | ret = crw_register_handler(CRW_RSC_SCH, css_process_crw); |
769 | if (ret) | 805 | if (ret) |
770 | goto out; | 806 | goto out; |
771 | 807 | ||
@@ -845,7 +881,7 @@ out_unregister: | |||
845 | out_bus: | 881 | out_bus: |
846 | bus_unregister(&css_bus_type); | 882 | bus_unregister(&css_bus_type); |
847 | out: | 883 | out: |
848 | s390_unregister_crw_handler(CRW_RSC_CSS); | 884 | crw_unregister_handler(CRW_RSC_CSS); |
849 | chsc_free_sei_area(); | 885 | chsc_free_sei_area(); |
850 | kfree(slow_subchannel_set); | 886 | kfree(slow_subchannel_set); |
851 | pr_alert("The CSS device driver initialization failed with " | 887 | pr_alert("The CSS device driver initialization failed with " |