ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / s390 / cio / css.c
1 /*
2  *  drivers/s390/cio/css.c
3  *  driver for channel subsystem
4  *   $Revision: 1.73 $
5  *
6  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
7  *                       IBM Corporation
8  *    Author(s): Arnd Bergmann (arndb@de.ibm.com)
9  *               Cornelia Huck (cohuck@de.ibm.com)
10  */
11 #include <linux/module.h>
12 #include <linux/init.h>
13 #include <linux/device.h>
14 #include <linux/slab.h>
15 #include <linux/errno.h>
16 #include <linux/list.h>
17
18 #include "css.h"
19 #include "cio.h"
20 #include "cio_debug.h"
21 #include "ioasm.h"
22
23 unsigned int highest_subchannel;
24 int need_rescan = 0;
25 int css_init_done = 0;
26
27 struct device css_bus_device = {
28         .bus_id = "css0",
29 };
30
31 static struct subchannel *
32 css_alloc_subchannel(int irq)
33 {
34         struct subchannel *sch;
35         int ret;
36
37         sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA);
38         if (sch == NULL)
39                 return ERR_PTR(-ENOMEM);
40         ret = cio_validate_subchannel (sch, irq);
41         if (ret < 0) {
42                 kfree(sch);
43                 return ERR_PTR(ret);
44         }
45         if (irq > highest_subchannel)
46                 highest_subchannel = irq;
47
48         if (sch->st != SUBCHANNEL_TYPE_IO) {
49                 /* For now we ignore all non-io subchannels. */
50                 kfree(sch);
51                 return ERR_PTR(-EINVAL);
52         }
53
54         /* 
55          * Set intparm to subchannel address.
56          * This is fine even on 64bit since the subchannel is always located
57          * under 2G.
58          */
59         sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
60         ret = cio_modify(sch);
61         if (ret) {
62                 kfree(sch);
63                 return ERR_PTR(ret);
64         }
65         return sch;
66 }
67
68 static void
69 css_free_subchannel(struct subchannel *sch)
70 {
71         if (sch) {
72                 /* Reset intparm to zeroes. */
73                 sch->schib.pmcw.intparm = 0;
74                 cio_modify(sch);
75                 kfree(sch);
76         }
77         
78 }
79
80 static void
81 css_subchannel_release(struct device *dev)
82 {
83         struct subchannel *sch;
84
85         sch = to_subchannel(dev);
86         if (!cio_is_console(sch->irq))
87                 kfree(sch);
88 }
89
90 extern int css_get_ssd_info(struct subchannel *sch);
91
92 static int
93 css_register_subchannel(struct subchannel *sch)
94 {
95         int ret;
96
97         /* Initialize the subchannel structure */
98         sch->dev.parent = &css_bus_device;
99         sch->dev.bus = &css_bus_type;
100         sch->dev.release = &css_subchannel_release;
101         
102         /* make it known to the system */
103         ret = device_register(&sch->dev);
104         if (ret)
105                 printk (KERN_WARNING "%s: could not register %s\n",
106                         __func__, sch->dev.bus_id);
107         else
108                 css_get_ssd_info(sch);
109         return ret;
110 }
111
112 int
113 css_probe_device(int irq)
114 {
115         int ret;
116         struct subchannel *sch;
117
118         sch = css_alloc_subchannel(irq);
119         if (IS_ERR(sch))
120                 return PTR_ERR(sch);
121         ret = css_register_subchannel(sch);
122         if (ret)
123                 css_free_subchannel(sch);
124         return ret;
125 }
126
127 struct subchannel *
128 get_subchannel_by_schid(int irq)
129 {
130         struct subchannel *sch;
131         struct list_head *entry;
132         struct device *dev;
133
134         if (!get_bus(&css_bus_type))
135                 return NULL;
136         down_read(&css_bus_type.subsys.rwsem);
137         sch = NULL;
138         list_for_each(entry, &css_bus_type.devices.list) {
139                 dev = get_device(container_of(entry,
140                                               struct device, bus_list));
141                 if (!dev)
142                         continue;
143                 sch = to_subchannel(dev);
144                 if (sch->irq == irq)
145                         break;
146                 put_device(dev);
147                 sch = NULL;
148         }
149         up_read(&css_bus_type.subsys.rwsem);
150         put_bus(&css_bus_type);
151
152         return sch;
153 }
154
155 static inline int
156 css_get_subchannel_status(struct subchannel *sch, int schid)
157 {
158         struct schib schib;
159         int cc;
160
161         cc = stsch(schid, &schib);
162         if (cc)
163                 return CIO_GONE;
164         if (!schib.pmcw.dnv)
165                 return CIO_GONE;
166         if (sch && sch->schib.pmcw.dnv &&
167             (schib.pmcw.dev != sch->schib.pmcw.dev))
168                 return CIO_REVALIDATE;
169         return CIO_OPER;
170 }
171         
172 static inline int
173 css_evaluate_subchannel(int irq, int slow)
174 {
175         int event, ret, disc;
176         struct subchannel *sch;
177
178         sch = get_subchannel_by_schid(irq);
179         disc = sch ? device_is_disconnected(sch) : 0;
180         if (disc && slow) {
181                 if (sch)
182                         put_device(&sch->dev);
183                 return 0; /* Already processed. */
184         }
185         if (!disc && !slow) {
186                 if (sch)
187                         put_device(&sch->dev);
188                 return -EAGAIN; /* Will be done on the slow path. */
189         }
190         event = css_get_subchannel_status(sch, irq);
191         switch (event) {
192         case CIO_GONE:
193                 if (!sch) {
194                         /* Never used this subchannel. Ignore. */
195                         ret = 0;
196                         break;
197                 }
198                 if (sch->driver && sch->driver->notify &&
199                     sch->driver->notify(&sch->dev, CIO_GONE)) {
200                         device_set_disconnected(sch);
201                         ret = 0;
202                         break;
203                 }
204                 /*
205                  * Unregister subchannel.
206                  * The device will be killed automatically.
207                  */
208                 device_unregister(&sch->dev);
209                 /* Reset intparm to zeroes. */
210                 sch->schib.pmcw.intparm = 0;
211                 cio_modify(sch);
212                 put_device(&sch->dev);
213                 ret = 0;
214                 break;
215         case CIO_REVALIDATE:
216                 /* 
217                  * Revalidation machine check. Sick.
218                  * We don't notify the driver since we have to throw the device
219                  * away in any case.
220                  */
221                 device_unregister(&sch->dev);
222                 /* Reset intparm to zeroes. */
223                 sch->schib.pmcw.intparm = 0;
224                 cio_modify(sch);
225                 put_device(&sch->dev);
226                 ret = css_probe_device(irq);
227                 break;
228         case CIO_OPER:
229                 if (disc)
230                         /* Get device operational again. */
231                         device_trigger_reprobe(sch);
232                 ret = sch ? 0 : css_probe_device(irq);
233                 break;
234         default:
235                 BUG();
236                 ret = 0;
237         }
238         return ret;
239 }
240
241 static void
242 css_rescan_devices(void)
243 {
244         int irq, ret;
245
246         for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
247                 ret = css_evaluate_subchannel(irq, 1);
248                 /* No more memory. It doesn't make sense to continue. No
249                  * panic because this can happen in midflight and just
250                  * because we can't use a new device is no reason to crash
251                  * the system. */
252                 if (ret == -ENOMEM)
253                         break;
254                 /* -ENXIO indicates that there are no more subchannels. */
255                 if (ret == -ENXIO)
256                         break;
257         }
258 }
259
260 static void
261 css_evaluate_slow_subchannel(unsigned long schid)
262 {
263         css_evaluate_subchannel(schid, 1);
264 }
265
266 void
267 css_trigger_slow_path(void)
268 {
269         if (need_rescan) {
270                 need_rescan = 0;
271                 css_rescan_devices();
272                 return;
273         }
274         css_walk_subchannel_slow_list(css_evaluate_slow_subchannel);
275 }
276
277 /*
278  * Rescan for new devices. FIXME: This is slow.
279  * This function is called when we have lost CRWs due to overflows and we have
280  * to do subchannel housekeeping.
281  */
282 void
283 css_reiterate_subchannels(void)
284 {
285         css_clear_subchannel_slow_list();
286         need_rescan = 1;
287 }
288
289 /*
290  * Called from the machine check handler for subchannel report words.
291  */
292 int
293 css_process_crw(int irq)
294 {
295         int ret;
296
297         CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq);
298
299         if (need_rescan)
300                 /* We need to iterate all subchannels anyway. */
301                 return -EAGAIN;
302         /* 
303          * Since we are always presented with IPI in the CRW, we have to
304          * use stsch() to find out if the subchannel in question has come
305          * or gone.
306          */
307         ret = css_evaluate_subchannel(irq, 0);
308         if (ret == -EAGAIN) {
309                 if (css_enqueue_subchannel_slow(irq)) {
310                         css_clear_subchannel_slow_list();
311                         need_rescan = 1;
312                 }
313         }
314         return ret;
315 }
316
317 /*
318  * some of the initialization has already been done from init_IRQ(),
319  * here we do the rest now that the driver core is running.
320  * The struct subchannel's are created during probing (except for the
321  * static console subchannel).
322  */
323 static int __init
324 init_channel_subsystem (void)
325 {
326         int ret, irq;
327
328         if ((ret = bus_register(&css_bus_type)))
329                 goto out;
330         if ((ret = device_register (&css_bus_device)))
331                 goto out_bus;
332
333         css_init_done = 1;
334
335         ctl_set_bit(6, 28);
336
337         for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
338                 struct subchannel *sch;
339
340                 if (cio_is_console(irq))
341                         sch = cio_get_console_subchannel();
342                 else {
343                         sch = css_alloc_subchannel(irq);
344                         if (IS_ERR(sch))
345                                 ret = PTR_ERR(sch);
346                         else
347                                 ret = 0;
348                         if (ret == -ENOMEM)
349                                 panic("Out of memory in "
350                                       "init_channel_subsystem\n");
351                         /* -ENXIO: no more subchannels. */
352                         if (ret == -ENXIO)
353                                 break;
354                         if (ret)
355                                 continue;
356                 }
357                 /*
358                  * We register ALL valid subchannels in ioinfo, even those
359                  * that have been present before init_channel_subsystem.
360                  * These subchannels can't have been registered yet (kmalloc
361                  * not working) so we do it now. This is true e.g. for the
362                  * console subchannel.
363                  */
364                 css_register_subchannel(sch);
365         }
366         return 0;
367
368 out_bus:
369         bus_unregister(&css_bus_type);
370 out:
371         return ret;
372 }
373
374 /*
375  * find a driver for a subchannel. They identify by the subchannel
376  * type with the exception that the console subchannel driver has its own
377  * subchannel type although the device is an i/o subchannel
378  */
379 static int
380 css_bus_match (struct device *dev, struct device_driver *drv)
381 {
382         struct subchannel *sch = container_of (dev, struct subchannel, dev);
383         struct css_driver *driver = container_of (drv, struct css_driver, drv);
384
385         if (sch->st == driver->subchannel_type)
386                 return 1;
387
388         return 0;
389 }
390
391 struct bus_type css_bus_type = {
392         .name  = "css",
393         .match = &css_bus_match,
394 };
395
396 subsys_initcall(init_channel_subsystem);
397
398 /*
399  * Register root devices for some drivers. The release function must not be
400  * in the device drivers, so we do it here.
401  */
402 static void
403 s390_root_dev_release(struct device *dev)
404 {
405         kfree(dev);
406 }
407
408 struct device *
409 s390_root_dev_register(const char *name)
410 {
411         struct device *dev;
412         int ret;
413
414         if (!strlen(name))
415                 return ERR_PTR(-EINVAL);
416         dev = kmalloc(sizeof(struct device), GFP_KERNEL);
417         if (!dev)
418                 return ERR_PTR(-ENOMEM);
419         memset(dev, 0, sizeof(struct device));
420         strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE));
421         dev->release = s390_root_dev_release;
422         ret = device_register(dev);
423         if (ret) {
424                 kfree(dev);
425                 return ERR_PTR(ret);
426         }
427         return dev;
428 }
429
430 void
431 s390_root_dev_unregister(struct device *dev)
432 {
433         if (dev)
434                 device_unregister(dev);
435 }
436
437 struct slow_subchannel {
438         struct list_head slow_list;
439         unsigned long schid;
440 };
441
442 static LIST_HEAD(slow_subchannels_head);
443 static spinlock_t slow_subchannel_lock = SPIN_LOCK_UNLOCKED;
444
445 int
446 css_enqueue_subchannel_slow(unsigned long schid)
447 {
448         struct slow_subchannel *new_slow_sch;
449         unsigned long flags;
450
451         new_slow_sch = kmalloc(sizeof(struct slow_subchannel), GFP_ATOMIC);
452         if (!new_slow_sch)
453                 return -ENOMEM;
454         new_slow_sch->schid = schid;
455         spin_lock_irqsave(&slow_subchannel_lock, flags);
456         list_add_tail(&new_slow_sch->slow_list, &slow_subchannels_head);
457         spin_unlock_irqrestore(&slow_subchannel_lock, flags);
458         return 0;
459 }
460
461 void
462 css_clear_subchannel_slow_list(void)
463 {
464         unsigned long flags;
465
466         spin_lock_irqsave(&slow_subchannel_lock, flags);
467         while (!list_empty(&slow_subchannels_head)) {
468                 struct slow_subchannel *slow_sch =
469                         list_entry(slow_subchannels_head.next,
470                                    struct slow_subchannel, slow_list);
471
472                 list_del_init(slow_subchannels_head.next);
473                 kfree(slow_sch);
474         }
475         spin_unlock_irqrestore(&slow_subchannel_lock, flags);
476 }
477
478 void
479 css_walk_subchannel_slow_list(void (*fn)(unsigned long))
480 {
481         unsigned long flags;
482
483         spin_lock_irqsave(&slow_subchannel_lock, flags);
484         while (!list_empty(&slow_subchannels_head)) {
485                 struct slow_subchannel *slow_sch =
486                         list_entry(slow_subchannels_head.next,
487                                    struct slow_subchannel, slow_list);
488
489                 list_del_init(slow_subchannels_head.next);
490                 spin_unlock_irqrestore(&slow_subchannel_lock, flags);
491                 fn(slow_sch->schid);
492                 spin_lock_irqsave(&slow_subchannel_lock, flags);
493                 kfree(slow_sch);
494         }
495         spin_unlock_irqrestore(&slow_subchannel_lock, flags);
496 }
497
498 int
499 css_slow_subchannels_exist(void)
500 {
501         return (!list_empty(&slow_subchannels_head));
502 }
503
504 MODULE_LICENSE("GPL");
505 EXPORT_SYMBOL(css_bus_type);
506 EXPORT_SYMBOL(s390_root_dev_register);
507 EXPORT_SYMBOL(s390_root_dev_unregister);