X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fs390%2Fcio%2Fcss.c;h=948b3b158dd854d66eedda130fc64c83e61a08cc;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=f996528550848ed16db395b7c4369df4347bd84f;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index f99652855..948b3b158 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/css.c * driver for channel subsystem - * $Revision: 1.77 $ + * $Revision: 1.84 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -19,11 +19,15 @@ #include "cio.h" #include "cio_debug.h" #include "ioasm.h" +#include "chsc.h" unsigned int highest_subchannel; int need_rescan = 0; int css_init_done = 0; +struct pgid global_pgid; +int css_characteristics_avail = 0; + struct device css_bus_device = { .bus_id = "css0", }; @@ -184,6 +188,12 @@ css_evaluate_subchannel(int irq, int slow) put_device(&sch->dev); return 0; /* Already processed. */ } + /* + * We've got a machine check, so running I/O won't get an interrupt. + * Kill any pending timers. + */ + if (sch) + device_kill_pending_timer(sch); if (!disc && !slow) { if (sch) put_device(&sch->dev); @@ -201,6 +211,20 @@ css_evaluate_subchannel(int irq, int slow) ret = 0; break; } + if (disc && (event == CIO_NO_PATH)) { + /* + * Uargh, hack again. Because we don't get a machine + * check on configure on, our path bookkeeping can + * be out of date here (it's fine while we only do + * logical varying or get chsc machine checks). We + * need to force reprobing or we might miss devices + * coming operational again. It won't do harm in real + * no path situations. + */ + device_trigger_reprobe(sch); + ret = 0; + break; + } if (sch->driver && sch->driver->notify && sch->driver->notify(&sch->dev, event)) { cio_disable_subchannel(sch); @@ -260,7 +284,7 @@ css_rescan_devices(void) { int irq, ret; - for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) { + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { ret = css_evaluate_subchannel(irq, 1); /* No more memory. It doesn't make sense to continue. No * panic because this can happen in midflight and just @@ -280,7 +304,7 @@ struct slow_subchannel { }; static LIST_HEAD(slow_subchannels_head); -static spinlock_t slow_subchannel_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(slow_subchannel_lock); static void css_trigger_slow_path(void) @@ -352,9 +376,26 @@ css_process_crw(int irq) return ret; } +static void __init +css_generate_pgid(void) +{ + /* Let's build our path group ID here. */ + if (css_characteristics_avail && css_general_characteristics.mcss) + global_pgid.cpu_addr = 0x8000; + else { +#ifdef CONFIG_SMP + global_pgid.cpu_addr = hard_smp_processor_id(); +#else + global_pgid.cpu_addr = 0; +#endif + } + global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident; + global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine; + global_pgid.tod_high = (__u32) (get_clock() >> 32); +} + /* - * some of the initialization has already been done from init_IRQ(), - * here we do the rest now that the driver core is running. + * Now that the driver core is running, we can setup our channel subsystem. * The struct subchannel's are created during probing (except for the * static console subchannel). */ @@ -363,6 +404,11 @@ init_channel_subsystem (void) { int ret, irq; + if (chsc_determine_css_characteristics() == 0) + css_characteristics_avail = 1; + + css_generate_pgid(); + if ((ret = bus_register(&css_bus_type))) goto out; if ((ret = device_register (&css_bus_device))) @@ -481,6 +527,7 @@ css_enqueue_subchannel_slow(unsigned long schid) new_slow_sch = kmalloc(sizeof(struct slow_subchannel), GFP_ATOMIC); if (!new_slow_sch) return -ENOMEM; + memset(new_slow_sch, 0, sizeof(struct slow_subchannel)); new_slow_sch->schid = schid; spin_lock_irqsave(&slow_subchannel_lock, flags); list_add_tail(&new_slow_sch->slow_list, &slow_subchannels_head); @@ -517,3 +564,4 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(css_bus_type); EXPORT_SYMBOL(s390_root_dev_register); EXPORT_SYMBOL(s390_root_dev_unregister); +EXPORT_SYMBOL_GPL(css_characteristics_avail);