diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2009-03-26 10:24:11 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-03-26 10:24:14 -0400 |
commit | 90ac24a5aeb8d4bef001bd3589564a52846d0eee (patch) | |
tree | f57ed4032783a546507d244d147ce56f69b4c751 /drivers/s390/cio | |
parent | 87fa5af80cdd5053b27a546725948c2b74ec82b2 (diff) |
[S390] cio: device scan oom fallback.
Since some callers rely on for_each_subchannel_staged to not fail,
fall back to brute force scanning using get_subchannel_by_schid in
case of a oom situation.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r-- | drivers/s390/cio/css.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index a5fc56371ba8..1f2e424596af 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -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) |