aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/css.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-03-26 19:04:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-03-26 19:04:22 -0400
commit21cdbc1378e8aa96e1ed4a606dce1a8e7daf7fdf (patch)
tree55b6c294b912ccdc3eede15960b0ece53a69d902 /drivers/s390/cio/css.c
parent86d9c070175de65890794fa227b68297da6206d8 (diff)
parentef3500b2b2955af4fa6b0564b51c0c604e38c571 (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.c58
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
86static 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
86int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), 105int 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
536static 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
545static 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. */
514static void reprobe_all(struct work_struct *unused) 548static 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:
845out_bus: 881out_bus:
846 bus_unregister(&css_bus_type); 882 bus_unregister(&css_bus_type);
847out: 883out:
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 "