aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/css.c
diff options
context:
space:
mode:
authorCornelia Huck <cohuck@de.ibm.com>2006-01-06 03:19:21 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:51 -0500
commita8237fc4108060402d904bea5e1062e22e731969 (patch)
treefc19e33ea8bbe664c33fba6c78b34e497f2cc478 /drivers/s390/cio/css.c
parent8129ee164267dc030b8e1d541ee3643c0b9f2fa1 (diff)
[PATCH] s390: introduce struct subchannel_id
This patch introduces a struct subchannel_id containing the subchannel number (formerly referred to as "irq") and switches code formerly relying on the subchannel number over to it. While we're touching inline assemblies anyway, make sure they have correct memory constraints. Signed-off-by: Cornelia Huck <cohuck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/s390/cio/css.c')
-rw-r--r--drivers/s390/cio/css.c69
1 files changed, 38 insertions, 31 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 7e4d57b4266f..5137dafd1e8d 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -33,7 +33,7 @@ struct device css_bus_device = {
33}; 33};
34 34
35static struct subchannel * 35static struct subchannel *
36css_alloc_subchannel(int irq) 36css_alloc_subchannel(struct subchannel_id schid)
37{ 37{
38 struct subchannel *sch; 38 struct subchannel *sch;
39 int ret; 39 int ret;
@@ -41,13 +41,11 @@ css_alloc_subchannel(int irq)
41 sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA); 41 sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA);
42 if (sch == NULL) 42 if (sch == NULL)
43 return ERR_PTR(-ENOMEM); 43 return ERR_PTR(-ENOMEM);
44 ret = cio_validate_subchannel (sch, irq); 44 ret = cio_validate_subchannel (sch, schid);
45 if (ret < 0) { 45 if (ret < 0) {
46 kfree(sch); 46 kfree(sch);
47 return ERR_PTR(ret); 47 return ERR_PTR(ret);
48 } 48 }
49 if (irq > highest_subchannel)
50 highest_subchannel = irq;
51 49
52 if (sch->st != SUBCHANNEL_TYPE_IO) { 50 if (sch->st != SUBCHANNEL_TYPE_IO) {
53 /* For now we ignore all non-io subchannels. */ 51 /* For now we ignore all non-io subchannels. */
@@ -87,7 +85,7 @@ css_subchannel_release(struct device *dev)
87 struct subchannel *sch; 85 struct subchannel *sch;
88 86
89 sch = to_subchannel(dev); 87 sch = to_subchannel(dev);
90 if (!cio_is_console(sch->irq)) 88 if (!cio_is_console(sch->schid))
91 kfree(sch); 89 kfree(sch);
92} 90}
93 91
@@ -114,12 +112,12 @@ css_register_subchannel(struct subchannel *sch)
114} 112}
115 113
116int 114int
117css_probe_device(int irq) 115css_probe_device(struct subchannel_id schid)
118{ 116{
119 int ret; 117 int ret;
120 struct subchannel *sch; 118 struct subchannel *sch;
121 119
122 sch = css_alloc_subchannel(irq); 120 sch = css_alloc_subchannel(schid);
123 if (IS_ERR(sch)) 121 if (IS_ERR(sch))
124 return PTR_ERR(sch); 122 return PTR_ERR(sch);
125 ret = css_register_subchannel(sch); 123 ret = css_register_subchannel(sch);
@@ -132,26 +130,26 @@ static int
132check_subchannel(struct device * dev, void * data) 130check_subchannel(struct device * dev, void * data)
133{ 131{
134 struct subchannel *sch; 132 struct subchannel *sch;
135 int irq = (unsigned long)data; 133 struct subchannel_id *schid = data;
136 134
137 sch = to_subchannel(dev); 135 sch = to_subchannel(dev);
138 return (sch->irq == irq); 136 return schid_equal(&sch->schid, schid);
139} 137}
140 138
141struct subchannel * 139struct subchannel *
142get_subchannel_by_schid(int irq) 140get_subchannel_by_schid(struct subchannel_id schid)
143{ 141{
144 struct device *dev; 142 struct device *dev;
145 143
146 dev = bus_find_device(&css_bus_type, NULL, 144 dev = bus_find_device(&css_bus_type, NULL,
147 (void *)(unsigned long)irq, check_subchannel); 145 (void *)&schid, check_subchannel);
148 146
149 return dev ? to_subchannel(dev) : NULL; 147 return dev ? to_subchannel(dev) : NULL;
150} 148}
151 149
152 150
153static inline int 151static inline int
154css_get_subchannel_status(struct subchannel *sch, int schid) 152css_get_subchannel_status(struct subchannel *sch, struct subchannel_id schid)
155{ 153{
156 struct schib schib; 154 struct schib schib;
157 int cc; 155 int cc;
@@ -170,13 +168,13 @@ css_get_subchannel_status(struct subchannel *sch, int schid)
170} 168}
171 169
172static int 170static int
173css_evaluate_subchannel(int irq, int slow) 171css_evaluate_subchannel(struct subchannel_id schid, int slow)
174{ 172{
175 int event, ret, disc; 173 int event, ret, disc;
176 struct subchannel *sch; 174 struct subchannel *sch;
177 unsigned long flags; 175 unsigned long flags;
178 176
179 sch = get_subchannel_by_schid(irq); 177 sch = get_subchannel_by_schid(schid);
180 disc = sch ? device_is_disconnected(sch) : 0; 178 disc = sch ? device_is_disconnected(sch) : 0;
181 if (disc && slow) { 179 if (disc && slow) {
182 if (sch) 180 if (sch)
@@ -194,9 +192,10 @@ css_evaluate_subchannel(int irq, int slow)
194 put_device(&sch->dev); 192 put_device(&sch->dev);
195 return -EAGAIN; /* Will be done on the slow path. */ 193 return -EAGAIN; /* Will be done on the slow path. */
196 } 194 }
197 event = css_get_subchannel_status(sch, irq); 195 event = css_get_subchannel_status(sch, schid);
198 CIO_MSG_EVENT(4, "Evaluating schid %04x, event %d, %s, %s path.\n", 196 CIO_MSG_EVENT(4, "Evaluating schid %04x, event %d, %s, %s path.\n",
199 irq, event, sch?(disc?"disconnected":"normal"):"unknown", 197 schid.sch_no, event,
198 sch?(disc?"disconnected":"normal"):"unknown",
200 slow?"slow":"fast"); 199 slow?"slow":"fast");
201 switch (event) { 200 switch (event) {
202 case CIO_NO_PATH: 201 case CIO_NO_PATH:
@@ -253,7 +252,7 @@ css_evaluate_subchannel(int irq, int slow)
253 sch->schib.pmcw.intparm = 0; 252 sch->schib.pmcw.intparm = 0;
254 cio_modify(sch); 253 cio_modify(sch);
255 put_device(&sch->dev); 254 put_device(&sch->dev);
256 ret = css_probe_device(irq); 255 ret = css_probe_device(schid);
257 } else { 256 } else {
258 /* 257 /*
259 * We can't immediately deregister the disconnected 258 * We can't immediately deregister the disconnected
@@ -272,7 +271,7 @@ css_evaluate_subchannel(int irq, int slow)
272 device_trigger_reprobe(sch); 271 device_trigger_reprobe(sch);
273 spin_unlock_irqrestore(&sch->lock, flags); 272 spin_unlock_irqrestore(&sch->lock, flags);
274 } 273 }
275 ret = sch ? 0 : css_probe_device(irq); 274 ret = sch ? 0 : css_probe_device(schid);
276 break; 275 break;
277 default: 276 default:
278 BUG(); 277 BUG();
@@ -284,10 +283,12 @@ css_evaluate_subchannel(int irq, int slow)
284static void 283static void
285css_rescan_devices(void) 284css_rescan_devices(void)
286{ 285{
287 int irq, ret; 286 int ret;
287 struct subchannel_id schid;
288 288
289 for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { 289 init_subchannel_id(&schid);
290 ret = css_evaluate_subchannel(irq, 1); 290 do {
291 ret = css_evaluate_subchannel(schid, 1);
291 /* No more memory. It doesn't make sense to continue. No 292 /* No more memory. It doesn't make sense to continue. No
292 * panic because this can happen in midflight and just 293 * panic because this can happen in midflight and just
293 * because we can't use a new device is no reason to crash 294 * because we can't use a new device is no reason to crash
@@ -297,12 +298,12 @@ css_rescan_devices(void)
297 /* -ENXIO indicates that there are no more subchannels. */ 298 /* -ENXIO indicates that there are no more subchannels. */
298 if (ret == -ENXIO) 299 if (ret == -ENXIO)
299 break; 300 break;
300 } 301 } while (schid.sch_no++ < __MAX_SUBCHANNEL);
301} 302}
302 303
303struct slow_subchannel { 304struct slow_subchannel {
304 struct list_head slow_list; 305 struct list_head slow_list;
305 unsigned long schid; 306 struct subchannel_id schid;
306}; 307};
307 308
308static LIST_HEAD(slow_subchannels_head); 309static LIST_HEAD(slow_subchannels_head);
@@ -357,20 +358,24 @@ int
357css_process_crw(int irq) 358css_process_crw(int irq)
358{ 359{
359 int ret; 360 int ret;
361 struct subchannel_id mchk_schid;
360 362
361 CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq); 363 CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq);
362 364
363 if (need_rescan) 365 if (need_rescan)
364 /* We need to iterate all subchannels anyway. */ 366 /* We need to iterate all subchannels anyway. */
365 return -EAGAIN; 367 return -EAGAIN;
368
369 init_subchannel_id(&mchk_schid);
370 mchk_schid.sch_no = irq;
366 /* 371 /*
367 * Since we are always presented with IPI in the CRW, we have to 372 * Since we are always presented with IPI in the CRW, we have to
368 * use stsch() to find out if the subchannel in question has come 373 * use stsch() to find out if the subchannel in question has come
369 * or gone. 374 * or gone.
370 */ 375 */
371 ret = css_evaluate_subchannel(irq, 0); 376 ret = css_evaluate_subchannel(mchk_schid, 0);
372 if (ret == -EAGAIN) { 377 if (ret == -EAGAIN) {
373 if (css_enqueue_subchannel_slow(irq)) { 378 if (css_enqueue_subchannel_slow(mchk_schid)) {
374 css_clear_subchannel_slow_list(); 379 css_clear_subchannel_slow_list();
375 need_rescan = 1; 380 need_rescan = 1;
376 } 381 }
@@ -404,7 +409,8 @@ css_generate_pgid(void)
404static int __init 409static int __init
405init_channel_subsystem (void) 410init_channel_subsystem (void)
406{ 411{
407 int ret, irq; 412 int ret;
413 struct subchannel_id schid;
408 414
409 if (chsc_determine_css_characteristics() == 0) 415 if (chsc_determine_css_characteristics() == 0)
410 css_characteristics_avail = 1; 416 css_characteristics_avail = 1;
@@ -420,13 +426,14 @@ init_channel_subsystem (void)
420 426
421 ctl_set_bit(6, 28); 427 ctl_set_bit(6, 28);
422 428
423 for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { 429 init_subchannel_id(&schid);
430 do {
424 struct subchannel *sch; 431 struct subchannel *sch;
425 432
426 if (cio_is_console(irq)) 433 if (cio_is_console(schid))
427 sch = cio_get_console_subchannel(); 434 sch = cio_get_console_subchannel();
428 else { 435 else {
429 sch = css_alloc_subchannel(irq); 436 sch = css_alloc_subchannel(schid);
430 if (IS_ERR(sch)) 437 if (IS_ERR(sch))
431 ret = PTR_ERR(sch); 438 ret = PTR_ERR(sch);
432 else 439 else
@@ -448,7 +455,7 @@ init_channel_subsystem (void)
448 * console subchannel. 455 * console subchannel.
449 */ 456 */
450 css_register_subchannel(sch); 457 css_register_subchannel(sch);
451 } 458 } while (schid.sch_no++ < __MAX_SUBCHANNEL);
452 return 0; 459 return 0;
453 460
454out_bus: 461out_bus:
@@ -482,7 +489,7 @@ struct bus_type css_bus_type = {
482subsys_initcall(init_channel_subsystem); 489subsys_initcall(init_channel_subsystem);
483 490
484int 491int
485css_enqueue_subchannel_slow(unsigned long schid) 492css_enqueue_subchannel_slow(struct subchannel_id schid)
486{ 493{
487 struct slow_subchannel *new_slow_sch; 494 struct slow_subchannel *new_slow_sch;
488 unsigned long flags; 495 unsigned long flags;