diff -Nru a/Documentation/basic_profiling.txt b/Documentation/basic_profiling.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/basic_profiling.txt Tue Mar 4 23:48:44 2003 @@ -0,0 +1,48 @@ +These instructions are deliberately very basic. If you want something clever, +go read the real docs ;-) Please don't add more stuff, but feel free to +correct my mistakes ;-) (mbligh@aracnet.com) +Thanks to John Levon, Dave Hansen, et al. for help writing this. + + is the thing you're trying to measure. +Make sure you have the correct System.map / vmlinux referenced! +IMHO it's easier to use "make install" for linux and hack /sbin/installkernel +to copy config files, system.map, vmlinux to /boot. + +Readprofile +----------- +You need a fixed readprofile command for 2.5 ... either get hold of +a current version from: +http://www.kernel.org/pub/linux/utils/util-linux/ +or get readprofile binary fixed for 2.5 / akpm's 2.5 patch from +ftp://ftp.kernel.org/pub/linux/kernel/people/mbligh/tools/readprofile/ + +Add "profile=2" to the kernel command line. + +clear readprofile -r + +dump output readprofile -m /boot/System.map > captured_profile + +Oprofile +-------- +get source (I use 0.5) from http://oprofile.sourceforge.net/ +add "idle=poll" to the kernel command line +Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel +./configure --with-kernel-support +make install + +One time setup (pick appropriate one for your CPU): +P3 opcontrol --setup --vmlinux=/boot/vmlinux \ + --ctr0-event=CPU_CLK_UNHALTED --ctr0-count=100000 +Athlon/x86-64 opcontrol --setup --vmlinux=/boot/vmlinux \ + --ctr0-event=RETIRED_INSNS --ctr0-count=100000 +P4 opcontrol --setup --vmlinux=/boot/vmlinux \ + --ctr0-event=GLOBAL_POWER_EVENTS \ + --ctr0-unit-mask=1 --ctr0-count=100000 + +start daemon opcontrol --start-daemon +clear opcontrol --reset +start opcontrol --start + +stop opcontrol --stop +dump output oprofpp -dl -i /boot/vmlinux > output_file + diff -Nru a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex --- a/Documentation/cdrom/cdrom-standard.tex Tue Feb 5 09:40:36 2002 +++ b/Documentation/cdrom/cdrom-standard.tex Sat Mar 8 14:50:21 2003 @@ -758,11 +758,8 @@ \subsection{$Struct\ file_operations\ cdrom_fops$} The contents of this structure were described in section~\ref{cdrom.c}. -As already stated, this structure should be used to register block -devices with the kernel: -$$ -register_blkdev(major, , \&cdrom_fops); -$$ +A pointer to this structure is assigned to the $fops$ field +of the $struct gendisk$. \subsection{$Int\ register_cdrom( struct\ cdrom_device_info\ * cdi)$} diff -Nru a/Documentation/cpu-freq/core.txt b/Documentation/cpu-freq/core.txt --- a/Documentation/cpu-freq/core.txt Tue Feb 4 11:04:44 2003 +++ b/Documentation/cpu-freq/core.txt Sat Mar 8 01:39:53 2003 @@ -35,6 +35,10 @@ kernel "constant" loops_per_jiffy is updated on frequency changes here. +Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu, +which make sure that the cpufreq processor driver is correctly +registered with the core, and will not be unloaded until +cpufreq_put_cpu is called. 2. CPUFreq notifiers ==================== diff -Nru a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt --- a/Documentation/cpu-freq/cpu-drivers.txt Sat Mar 1 08:56:11 2003 +++ b/Documentation/cpu-freq/cpu-drivers.txt Sat Mar 8 01:39:53 2003 @@ -63,6 +63,9 @@ cpufreq_driver.exit - A pointer to a per-CPU cleanup function. +cpufreq_driver.attr - A pointer to a NULL-terminated list of + "struct freq_attr" which allow to + export values to sysfs. 1.2 Per-CPU Initialization diff -Nru a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt --- a/Documentation/cpu-freq/user-guide.txt Sat Mar 1 08:56:11 2003 +++ b/Documentation/cpu-freq/user-guide.txt Sat Mar 8 01:39:53 2003 @@ -114,9 +114,9 @@ ------------------------------ The preferred interface is located in the sysfs filesystem. If you -mounted it at /sys, the cpufreq interface is located in the -cpu-device directory (e.g. /sys/devices/sys/cpu0/ for the first -CPU). +mounted it at /sys, the cpufreq interface is located in a subdirectory +"cpufreq" within the cpu-device directory +(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU). cpuinfo_min_freq : this file shows the minimum operating frequency the processor can run at(in kHz) @@ -125,7 +125,7 @@ scaling_driver : this file shows what cpufreq driver is used to set the frequency on this CPU -available_scaling_governors : this file shows the CPUfreq governors +scaling_available_governors : this file shows the CPUfreq governors available in this kernel. You can see the currently activated governor in diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt --- a/Documentation/crypto/api-intro.txt Tue Jan 14 03:45:05 2003 +++ b/Documentation/crypto/api-intro.txt Sat Mar 8 15:26:02 2003 @@ -38,9 +38,8 @@ Compressors. The compression algorithms especially seem to be performing very well so far. -An asynchronous scheduling interface is in planning but not yet -implemented, as we need to further analyze the requirements of all of -the possible hardware scenarios (e.g. IPsec NIC offload). +Support for hardware crypto devices via an asynchronous interface is +under development. Here's an example of how to use the API: @@ -87,8 +86,8 @@ DEVELOPER NOTES -None of this code should be called from hardirq context, only softirq and -user contexts. +Transforms may only be allocated in user context, and cryptographic +methods may only be called from softirq and user contexts. When using the API for ciphers, performance will be optimal if each scatterlist contains data which is a multiple of the cipher's block @@ -137,16 +136,11 @@ list, see: http://samba.org/~jamesm/crypto/ -Ongoing development discussion may also be found on -kerneli cryptoapi-devel, -see http://www.kerneli.org/mailman/listinfo/cryptoapi-devel - AUTHORS James Morris David S. Miller -Jean-Francois Dive (SHA1 algorithm module) CREDITS @@ -191,6 +185,10 @@ Matthew Skala (Twofish) Dag Arne Osvik (Serpent) Brian Gladman (AES) + + +SHA1 algorithm contributors: + Jean-Francois Dive DES algorithm contributors: Raimar Falke @@ -215,6 +213,8 @@ Herbert Valerio Riedel Kyle McMartin Adam J. Richter + +Generic scatterwalk code by Adam J. Richter Please send any credits updates or corrections to: James Morris diff -Nru a/Documentation/ia64/fsys.txt b/Documentation/ia64/fsys.txt --- a/Documentation/ia64/fsys.txt Mon Jan 27 10:57:50 2003 +++ b/Documentation/ia64/fsys.txt Wed Feb 12 00:11:32 2003 @@ -4,7 +4,7 @@ ----------------------------------- Started: 13-Jan-2003 - Last update: 24-Jan-2003 + Last update: 11-Feb-2003 David Mosberger-Tang @@ -42,9 +42,9 @@ can disable interrupts and avoid all other interruption-sources to avoid preemption) - - neither the memory nor the register stack can be trusted while + - neither the memory-stack nor the register-stack can be trusted while in fsys-mode (they point to the user-level stacks, which may - be invalid) + be invalid, or completely bogus addresses) In summary, fsys-mode is much more similar to running in user-mode than it is to running in kernel-mode. Of course, given that the diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Tue Feb 18 10:57:56 2003 +++ b/MAINTAINERS Thu Mar 6 09:07:03 2003 @@ -641,7 +641,7 @@ P: Rui Sousa M: rui.p.m.sousa@clix.pt L: emu10k1-devel@lists.sourceforge.net -W: http://opensource.creative.com/ +W: http://sourceforge.net/projects/emu10k1/ S: Maintained ETHEREXPRESS-16 NETWORK DRIVER diff -Nru a/Makefile b/Makefile --- a/Makefile Tue Mar 4 19:11:15 2003 +++ b/Makefile Tue Mar 11 04:26:10 2003 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 64 -EXTRAVERSION = +EXTRAVERSION = bk6 # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -107,6 +107,11 @@ # For now, leave verbose as default +ifdef V + ifeq ("$(origin V)", "command line") + KBUILD_VERBOSE = $(V) + endif +endif ifndef KBUILD_VERBOSE KBUILD_VERBOSE = 1 endif @@ -322,13 +327,14 @@ # set -e makes the rule exit immediately on error define rule_vmlinux__ - set -e; \ + set -e \ $(if $(filter .tmp_kallsyms%,$^),, \ echo ' GEN .version'; \ . $(srctree)/scripts/mkversion > .tmp_version; \ mv -f .tmp_version .version; \ $(MAKE) $(build)=init; \ ) + set -e \ $(call cmd,vmlinux__); \ echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd endef diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig --- a/arch/alpha/Kconfig Tue Feb 18 15:57:50 2003 +++ b/arch/alpha/Kconfig Sat Mar 8 14:50:37 2003 @@ -15,10 +15,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool diff -Nru a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c --- a/arch/alpha/kernel/core_marvel.c Fri Feb 14 05:51:04 2003 +++ b/arch/alpha/kernel/core_marvel.c Sat Feb 15 04:55:38 2003 @@ -1076,7 +1076,7 @@ /* * Fill it in. */ - agp->type = 0 /* FIXME: ALPHA_CORE_AGP */; + agp->type = ALPHA_CORE_AGP; agp->hose = hose; agp->private = NULL; agp->ops = &marvel_agp_ops; diff -Nru a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c --- a/arch/alpha/kernel/core_titan.c Fri Jan 17 11:59:36 2003 +++ b/arch/alpha/kernel/core_titan.c Sat Feb 15 04:55:54 2003 @@ -764,7 +764,7 @@ /* * Fill it in. */ - agp->type = 0 /* FIXME: ALPHA_CORE_AGP */; + agp->type = ALPHA_CORE_AGP; agp->hose = hose; agp->private = port; agp->ops = &titan_agp_ops; diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c --- a/arch/alpha/kernel/irq.c Tue Jan 21 05:42:33 2003 +++ b/arch/alpha/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -515,6 +515,7 @@ #endif int i; struct irqaction * action; + unsigned long flags; #ifdef CONFIG_SMP seq_puts(p, " "); @@ -525,9 +526,10 @@ #endif for (i = 0; i < ACTUAL_NR_IRQS; i++) { + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto unlock; seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); @@ -538,15 +540,18 @@ #endif seq_printf(p, " %14s", irq_desc[i].handler->typename); seq_printf(p, " %c%s", - (action->flags & SA_INTERRUPT)?'+':' ', - action->name); + (action->flags & SA_INTERRUPT)?'+':' ', + action->name); for (action=action->next; action; action = action->next) { seq_printf(p, ", %c%s", - (action->flags & SA_INTERRUPT)?'+':' ', - action->name); + (action->flags & SA_INTERRUPT)?'+':' ', + action->name); } + seq_putc(p, '\n'); +unlock: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } #if CONFIG_SMP seq_puts(p, "IPI: "); diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c --- a/arch/alpha/kernel/pci.c Wed Feb 26 17:20:09 2003 +++ b/arch/alpha/kernel/pci.c Thu Mar 6 11:08:47 2003 @@ -393,26 +393,36 @@ } static void __init +pcibios_claim_one_bus(struct pci_bus *b) +{ + struct list_head *ld; + struct pci_bus *child_bus; + + for (ld = b->devices.next; ld != &b->devices; ld = ld->next) { + struct pci_dev *dev = pci_dev_b(ld); + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *r = &dev->resource[i]; + + if (r->parent || !r->start || !r->flags) + continue; + pci_claim_resource(dev, i); + } + } + + list_for_each_entry(child_bus, &b->children, node) + pcibios_claim_one_bus(child_bus); +} + +static void __init pcibios_claim_console_setup(void) { struct list_head *lb; for(lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) { struct pci_bus *b = pci_bus_b(lb); - struct list_head *ld; - - for (ld = b->devices.next; ld != &b->devices; ld = ld->next) { - struct pci_dev *dev = pci_dev_b(ld); - int i; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *r = &dev->resource[i]; - - if (r->parent || !r->start || !r->flags) - continue; - pci_claim_resource(dev, i); - } - } + pcibios_claim_one_bus(b); } } diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c --- a/arch/alpha/kernel/sys_nautilus.c Thu Jan 23 10:59:07 2003 +++ b/arch/alpha/kernel/sys_nautilus.c Sun Mar 2 17:34:25 2003 @@ -78,6 +78,8 @@ nautilus_kill_arch(int mode) { struct pci_bus *bus = pci_isa_hose->bus; + u32 pmuport; + int off; switch (mode) { case LINUX_REBOOT_CMD_RESTART: @@ -92,14 +94,18 @@ break; case LINUX_REBOOT_CMD_POWER_OFF: - { - u32 pmuport; - pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport); - pmuport &= 0xfffe; - outl(0xffff, pmuport); /* clear pending events */ - outw(0x2000, pmuport+4); /* power off */ - /* NOTREACHED */ + /* Assume M1543C */ + off = 0x2000; /* SLP_TYPE = 0, SLP_EN = 1 */ + pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport); + if (!pmuport) { + /* M1535D/D+ */ + off = 0x3400; /* SLP_TYPE = 5, SLP_EN = 1 */ + pci_bus_read_config_dword(bus, 0x88, 0xe0, &pmuport); } + pmuport &= 0xfffe; + outw(0xffff, pmuport); /* Clear pending events. */ + outw(off, pmuport + 4); + /* NOTREACHED */ break; } } diff -Nru a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c --- a/arch/alpha/mm/fault.c Mon Jan 6 10:11:27 2003 +++ b/arch/alpha/mm/fault.c Thu Mar 6 08:19:03 2003 @@ -232,11 +232,11 @@ else { /* Synchronize this task's top level page-table with the "reference" page table from init. */ - long offset = __pgd_offset(address); + long index = pgd_index(address); pgd_t *pgd, *pgd_k; - pgd = current->active_mm->pgd + offset; - pgd_k = swapper_pg_dir + offset; + pgd = current->active_mm->pgd + index; + pgd_k = swapper_pg_dir + index; if (!pgd_present(*pgd) && pgd_present(*pgd_k)) { pgd_val(*pgd) = pgd_val(*pgd_k); return; diff -Nru a/arch/alpha/oprofile/op_model_ev4.c b/arch/alpha/oprofile/op_model_ev4.c --- a/arch/alpha/oprofile/op_model_ev4.c Tue Feb 18 19:05:36 2003 +++ b/arch/alpha/oprofile/op_model_ev4.c Fri Mar 7 20:31:28 2003 @@ -34,7 +34,7 @@ for these "disabled" counter overflows are ignored by the interrupt handler. - This is most irritating, becuase the hardware *can* enable and + This is most irritating, because the hardware *can* enable and disable the interrupts for these counters independently, but the wrperfmon interface doesn't allow it. */ diff -Nru a/arch/alpha/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S --- a/arch/alpha/vmlinux.lds.S Wed Jan 15 19:04:27 2003 +++ b/arch/alpha/vmlinux.lds.S Fri Mar 7 00:58:06 2003 @@ -63,6 +63,13 @@ .init.ramfs : { *(.init.ramfs) } __initramfs_end = .; + . = ALIGN(8); + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + . = ALIGN(64); __per_cpu_start = .; .data.percpu : { *(.data.percpu) } diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig --- a/arch/arm/Kconfig Sat Feb 15 01:34:08 2003 +++ b/arch/arm/Kconfig Sat Mar 8 14:50:37 2003 @@ -20,10 +20,6 @@ bool default y -config SWAP - bool - default y - config EISA bool ---help--- @@ -534,15 +530,63 @@ written) to implement the policy. If you don't understand what this is all about, it's safe to say 'N'. + +# CPUfreq on SA11x0 is special -- it _needs_ the userspace governor + +config CPU_FREQ_SA1100 + bool + depends on CPU_FREQ && SA1100_LART + default y + +config CPU_FREQ_SA1110 + bool + depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3) + default y + +if (CPU_FREQ_SA1100 || CPU_FREQ_SA1110) + +config CPU_FREQ_GOV_USERSPACE + bool + depends on CPU_FREQ + default y + config CPU_FREQ_24_API bool - depends on CPU_FREQ + depends on CPU_FREQ_GOV_USERSPACE && SYSCTL default y config CPU_FREQ_PROC_INTF - tristate - depends on CPU_FREQ + tristate "/proc/cpufreq interface (deprecated)" + depends on CPU_FREQ && PROC_FS + help + This enables the /proc/cpufreq interface for controlling + CPUFreq. Please note that it is recommended to use the sysfs + interface instead (which is built automatically). + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + +endif + +# CPUfreq on Integrator can use the generic cpufreq core + +config CPU_FREQ_INTEGRATOR + tristate "CPUfreq driver for ARM Integrator CPUs" + depends on ARCH_INTEGRATOR && CPU_FREQ default y + help + This enables the CPUfreq driver for ARM Integrator CPUs. + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say Y. + +if (CPU_FREQ_INTEGRATOR) + +source "drivers/cpufreq/Kconfig" + +endif source "drivers/pci/Kconfig" diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c --- a/arch/arm/common/sa1111.c Mon Feb 17 12:43:37 2003 +++ b/arch/arm/common/sa1111.c Thu Mar 6 08:08:19 2003 @@ -743,25 +743,23 @@ static int sa1111_suspend(struct device *dev, u32 state, u32 level) { struct sa1111 *sachip = dev_get_drvdata(dev); + struct sa1111_save_data *save; unsigned long flags; char *base; + if (!dev->saved_state && level == SUSPEND_NOTIFY) + dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); + if (!dev->saved_state) + return -ENOMEM; + + save = (struct sa1111_save_data *)dev->saved_state; + + spin_lock_irqsave(&sachip->lock, flags); + /* * Save state. */ - if (level == SUSPEND_SAVE_STATE || - level == SUSPEND_DISABLE || - level == SUSPEND_POWER_DOWN) { - struct sa1111_save_data *save; - - if (!dev->saved_state) - dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); - if (!dev->saved_state) - return -ENOMEM; - - save = (struct sa1111_save_data *)dev->saved_state; - - spin_lock_irqsave(&sachip->lock, flags); + if (level == SUSPEND_SAVE_STATE) { base = sachip->base; save->skcr = sa1111_readl(base + SA1111_SKCR); save->skpcr = sa1111_readl(base + SA1111_SKPCR); @@ -779,26 +777,21 @@ save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1); save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0); save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1); - spin_unlock_irqrestore(&sachip->lock, flags); } /* * Disable. */ - if (level == SUSPEND_DISABLE && state == 4) { - unsigned int val; - - spin_lock_irqsave(&sachip->lock, flags); - base = sachip->base; - - sa1111_writel(0, base + SA1111_SKPWM0); - sa1111_writel(0, base + SA1111_SKPWM1); - val = sa1111_readl(base + SA1111_SKCR); - sa1111_writel(val | SKCR_SLEEP, base + SA1111_SKCR); + if (level == SUSPEND_POWER_DOWN && state == 4) { + unsigned int val = sa1111_readl(sachip->base + SA1111_SKCR); - spin_unlock_irqrestore(&sachip->lock, flags); + sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR); + sa1111_writel(0, sachip->base + SA1111_SKPWM0); + sa1111_writel(0, sachip->base + SA1111_SKPWM1); } + spin_unlock_irqrestore(&sachip->lock, flags); + return 0; } @@ -819,17 +812,15 @@ unsigned long flags, id; char *base; - if (level != RESUME_RESTORE_STATE && level != RESUME_ENABLE) - return 0; - save = (struct sa1111_save_data *)dev->saved_state; if (!save) return 0; - dev->saved_state = NULL; + spin_lock_irqsave(&sachip->lock, flags); /* * Ensure that the SA1111 is still here. + * FIXME: shouldn't do this here. */ id = sa1111_readl(sachip->base + SA1111_SKID); if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { @@ -839,29 +830,42 @@ return 0; } - spin_lock_irqsave(&sachip->lock, flags); - sa1111_wake(sachip); + /* + * First of all, wake up the chip. + */ + if (level == RESUME_POWER_ON) { + sa1111_wake(sachip); + + sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0); + sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1); + } + + if (level == RESUME_RESTORE_STATE) { + base = sachip->base; + sa1111_writel(save->skcr, base + SA1111_SKCR); + sa1111_writel(save->skpcr, base + SA1111_SKPCR); + sa1111_writel(save->skcdr, base + SA1111_SKCDR); + sa1111_writel(save->skaud, base + SA1111_SKAUD); + sa1111_writel(save->skpwm0, base + SA1111_SKPWM0); + sa1111_writel(save->skpwm1, base + SA1111_SKPWM1); + + base = sachip->base + SA1111_INTC; + sa1111_writel(save->intpol0, base + SA1111_INTPOL0); + sa1111_writel(save->intpol1, base + SA1111_INTPOL1); + sa1111_writel(save->inten0, base + SA1111_INTEN0); + sa1111_writel(save->inten1, base + SA1111_INTEN1); + sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0); + sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1); + sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0); + sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1); + } - base = sachip->base; - sa1111_writel(save->skcr, base + SA1111_SKCR); - sa1111_writel(save->skpcr, base + SA1111_SKPCR); - sa1111_writel(save->skcdr, base + SA1111_SKCDR); - sa1111_writel(save->skaud, base + SA1111_SKAUD); - sa1111_writel(save->skpwm0, base + SA1111_SKPWM0); - sa1111_writel(save->skpwm1, base + SA1111_SKPWM1); - - base = sachip->base + SA1111_INTC; - sa1111_writel(save->intpol0, base + SA1111_INTPOL0); - sa1111_writel(save->intpol1, base + SA1111_INTPOL1); - sa1111_writel(save->inten0, base + SA1111_INTEN0); - sa1111_writel(save->inten1, base + SA1111_INTEN1); - sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0); - sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1); - sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0); - sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1); spin_unlock_irqrestore(&sachip->lock, flags); - kfree(save); + if (level == RESUME_ENABLE) { + dev->saved_state = NULL; + kfree(save); + } return 0; } diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile --- a/arch/arm/kernel/Makefile Mon Feb 3 14:19:35 2003 +++ b/arch/arm/kernel/Makefile Thu Mar 6 07:59:42 2003 @@ -16,6 +16,7 @@ obj- := obj-$(CONFIG_APM) += apm.o +obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o obj-$(CONFIG_FOOTBRIDGE) += isa.o diff -Nru a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/kernel/apm.c Thu Mar 6 07:59:42 2003 @@ -0,0 +1,573 @@ +/* + * bios-less APM driver for ARM Linux + * Jamey Hicks + * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) + * + * APM 1.2 Reference: + * Intel Corporation, Microsoft Corporation. Advanced Power Management + * (APM) BIOS Interface Specification, Revision 1.2, February 1996. + * + * [This document is available from Microsoft at: + * http://www.microsoft.com/hwdev/busbios/amp_12.htm] + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * The apm_bios device is one of the misc char devices. + * This is its minor number. + */ +#define APM_MINOR_DEV 134 + +/* + * See Documentation/Config.help for the configuration options. + * + * Various options can be changed at boot time as follows: + * (We allow underscores for compatibility with the modules code) + * apm=on/off enable/disable APM + */ + +/* + * Maximum number of events stored + */ +#define APM_MAX_EVENTS 20 + +/* + * The per-file APM data + */ +struct apm_user { + struct list_head list; + + int suser: 1; + int writer: 1; + int reader: 1; + int suspend_wait: 1; + int suspend_result; + + int suspends_pending; + int standbys_pending; + unsigned int suspends_read; + unsigned int standbys_read; + + int event_head; + int event_tail; + apm_event_t events[APM_MAX_EVENTS]; +}; + +/* + * Local variables + */ +static int suspends_pending; +static int standbys_pending; +static int apm_disabled; + +static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); +static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); + +/* + * This is a list of everyone who has opened /dev/apm_bios + */ +static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED; +static LIST_HEAD(apm_user_list); + +/* + * The kapmd info. + */ +static struct task_struct *kapmd; +static DECLARE_COMPLETION(kapmd_exit); + +static const char driver_version[] = "1.13"; /* no spaces */ + +/* + * This structure gets filled in by the machine specific 'get_power_status' + * implementation. Any fields which are not set default to a safe value. + */ +struct apm_power_info { + unsigned char ac_line_status; + unsigned char battery_status; + unsigned char battery_flag; + unsigned char battery_life; + int time; + int units; +}; + +/* + * Compatibility cruft until the IPAQ people move over to the new + * interface. + */ +static void __apm_get_power_status(struct apm_power_info *info) +{ +#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600) + extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *, + u_char *, u_short *); + + if (machine_is_h3600()) { + int dx; + h3600_apm_get_power_status(&info->ac_line_status, + &info->battery_status, &info->battery_flag, + &info->battery_life, &dx); + info->time = dx & 0x7fff; + info->units = dx & 0x8000 ? 0 : 1; + } +#endif +} + +/* + * This allows machines to provide their own "apm get power status" function. + */ +void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status; +EXPORT_SYMBOL(apm_get_power_status); + +static int queue_empty(struct apm_user *as) +{ + return as->event_head == as->event_tail; +} + +static apm_event_t get_queued_event(struct apm_user *as) +{ + as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + return as->events[as->event_tail]; +} + +static void queue_event_one_user(struct apm_user *as, apm_event_t event) +{ + as->event_head = (as->event_head + 1) % APM_MAX_EVENTS; + if (as->event_head == as->event_tail) { + static int notified; + + if (notified++ == 0) + printk(KERN_ERR "apm: an event queue overflowed\n"); + as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + } + as->events[as->event_head] = event; + + if (!as->suser || !as->writer) + return; + + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + as->suspends_pending++; + suspends_pending++; + break; + + case APM_SYS_STANDBY: + case APM_USER_STANDBY: + as->standbys_pending++; + standbys_pending++; + break; + } +} + +static void queue_event(apm_event_t event, struct apm_user *sender) +{ + struct list_head *l; + + spin_lock(&user_list_lock); + list_for_each(l, &apm_user_list) { + struct apm_user *as = list_entry(l, struct apm_user, list); + + if (as != sender && as->reader) + queue_event_one_user(as, event); + } + spin_unlock(&user_list_lock); + wake_up_interruptible(&apm_waitqueue); +} + +/* defined in pm.c */ +extern int suspend(void); + +static int apm_suspend(void) +{ + struct list_head *l; + int err = suspend(); + + /* + * Anyone on the APM queues will think we're still suspended. + * Send a message so everyone knows we're now awake again. + */ + queue_event(APM_NORMAL_RESUME, NULL); + + /* + * Finally, wake up anyone who is sleeping on the suspend. + */ + spin_lock(&user_list_lock); + list_for_each(l, &apm_user_list) { + struct apm_user *as = list_entry(l, struct apm_user, list); + + as->suspend_result = err; + as->suspend_wait = 0; + } + spin_unlock(&user_list_lock); + + wake_up_interruptible(&apm_suspend_waitqueue); + return err; +} + +static ssize_t apm_read(struct file *fp, char *buf, size_t count, loff_t *ppos) +{ + struct apm_user *as = fp->private_data; + apm_event_t event; + int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK; + + if (count < sizeof(apm_event_t)) + return -EINVAL; + + if (queue_empty(as) && nonblock) + return -EAGAIN; + + wait_event_interruptible(apm_waitqueue, !queue_empty(as)); + + while ((i >= sizeof(event)) && !queue_empty(as)) { + event = get_queued_event(as); + printk(" apm_read: event=%d\n", event); + + ret = -EFAULT; + if (copy_to_user(buf, &event, sizeof(event))) + break; + + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + as->suspends_read++; + break; + + case APM_SYS_STANDBY: + case APM_USER_STANDBY: + as->standbys_read++; + break; + } + + buf += sizeof(event); + i -= sizeof(event); + } + + if (i < count) + ret = count - i; + + return ret; +} + +static unsigned int apm_poll(struct file *fp, poll_table * wait) +{ + struct apm_user * as = fp->private_data; + + poll_wait(fp, &apm_waitqueue, wait); + return queue_empty(as) ? 0 : POLLIN | POLLRDNORM; +} + +/* + * apm_ioctl - handle APM ioctl + * + * APM_IOC_SUSPEND + * This IOCTL is overloaded, and performs two functions. It is used to: + * - initiate a suspend + * - acknowledge a suspend read from /dev/apm_bios. + * Only when everyone who has opened /dev/apm_bios with write permission + * has acknowledge does the actual suspend happen. + */ +static int +apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) +{ + struct apm_user *as = filp->private_data; + int err = -EINVAL; + + if (!as->suser || !as->writer) + return -EPERM; + + switch (cmd) { + case APM_IOC_STANDBY: + break; + + case APM_IOC_SUSPEND: + /* + * If we read a suspend command from /dev/apm_bios, + * then the corresponding APM_IOC_SUSPEND ioctl is + * interpreted as an acknowledge. + */ + if (as->suspends_read > 0) { + as->suspends_read--; + as->suspends_pending--; + suspends_pending--; + } else { + queue_event(APM_USER_SUSPEND, as); + } + + /* + * If there are outstanding suspend requests for other + * people on /dev/apm_bios, we must sleep for them. + * Last one to bed turns the lights out. + */ + if (suspends_pending > 0) { + as->suspend_wait = 1; + err = wait_event_interruptible(apm_suspend_waitqueue, + as->suspend_wait == 0); + if (err == 0) + err = as->suspend_result; + } else { + err = apm_suspend(); + } + break; + } + + return err; +} + +static int apm_release(struct inode * inode, struct file * filp) +{ + struct apm_user *as = filp->private_data; + filp->private_data = NULL; + + spin_lock(&user_list_lock); + list_del(&as->list); + spin_unlock(&user_list_lock); + + /* + * We are now unhooked from the chain. As far as new + * events are concerned, we no longer exist. However, we + * need to balance standbys_pending and suspends_pending, + * which means the possibility of sleeping. + */ + if (as->standbys_pending > 0) { + standbys_pending -= as->standbys_pending; +// if (standbys_pending <= 0) +// standby(); + } + if (as->suspends_pending > 0) { + suspends_pending -= as->suspends_pending; + if (suspends_pending <= 0) + apm_suspend(); + } + + kfree(as); + return 0; +} + +static int apm_open(struct inode * inode, struct file * filp) +{ + struct apm_user *as; + + as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); + if (as) { + memset(as, 0, sizeof(*as)); + + /* + * XXX - this is a tiny bit broken, when we consider BSD + * process accounting. If the device is opened by root, we + * instantly flag that we used superuser privs. Who knows, + * we might close the device immediately without doing a + * privileged operation -- cevans + */ + as->suser = capable(CAP_SYS_ADMIN); + as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE; + as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ; + + spin_lock(&user_list_lock); + list_add(&as->list, &apm_user_list); + spin_unlock(&user_list_lock); + + filp->private_data = as; + } + + return as ? 0 : -ENOMEM; +} + +static struct file_operations apm_bios_fops = { + owner: THIS_MODULE, + read: apm_read, + poll: apm_poll, + ioctl: apm_ioctl, + open: apm_open, + release: apm_release, +}; + +static struct miscdevice apm_device = { + minor: APM_MINOR_DEV, + name: "apm_bios", + fops: &apm_bios_fops +}; + + +#ifdef CONFIG_PROC_FS +/* + * Arguments, with symbols from linux/apm_bios.h. + * + * 0) Linux driver version (this will change if format changes) + * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. + * 2) APM flags from APM Installation Check (0x00): + * bit 0: APM_16_BIT_SUPPORT + * bit 1: APM_32_BIT_SUPPORT + * bit 2: APM_IDLE_SLOWS_CLOCK + * bit 3: APM_BIOS_DISABLED + * bit 4: APM_BIOS_DISENGAGED + * 3) AC line status + * 0x00: Off-line + * 0x01: On-line + * 0x02: On backup power (BIOS >= 1.1 only) + * 0xff: Unknown + * 4) Battery status + * 0x00: High + * 0x01: Low + * 0x02: Critical + * 0x03: Charging + * 0x04: Selected battery not present (BIOS >= 1.2 only) + * 0xff: Unknown + * 5) Battery flag + * bit 0: High + * bit 1: Low + * bit 2: Critical + * bit 3: Charging + * bit 7: No system battery + * 0xff: Unknown + * 6) Remaining battery life (percentage of charge): + * 0-100: valid + * -1: Unknown + * 7) Remaining battery life (time units): + * Number of remaining minutes or seconds + * -1: Unknown + * 8) min = minutes; sec = seconds + */ +static int apm_get_info(char *buf, char **start, off_t fpos, int length) +{ + struct apm_power_info info; + char *units; + int ret; + + info.ac_line_status = 0xff; + info.battery_status = 0xff; + info.battery_flag = 0xff; + info.battery_life = 255; + info.time = -1; + info.units = -1; + + if (apm_get_power_status) + apm_get_power_status(&info); + + switch (info.units) { + default: units = "?"; break; + case 0: units = "min"; break; + case 1: units = "sec"; break; + } + + ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", + driver_version, APM_32_BIT_SUPPORT, + info.ac_line_status, info.battery_status, + info.battery_flag, info.battery_life, + info.time, units); + + return ret; +} +#endif + +#if 0 +static int kapmd(void *startup) +{ + struct task_struct *tsk = current; + + daemonize(); + strcpy(tsk->comm, "kapmd"); + kapmd = tsk; + + spin_lock_irq(&tsk->sigmask_lock); + siginitsetinv(&tsk->blocked, sigmask(SIGQUIT)); + recalc_sigpending(tsk); + spin_unlock_irq(&tsk->sigmask_lock); + + complete((struct completion *)startup); + + do { + set_task_state(tsk, TASK_INTERRUPTIBLE); + schedule(); + } while (!signal_pending(tsk)); + + complete_and_exit(&kapmd_exit, 0); +} +#endif + +static int __init apm_init(void) +{ +// struct completion startup = COMPLETION_INITIALIZER(startup); + int ret; + + if (apm_disabled) { + printk(KERN_NOTICE "apm: disabled on user request.\n"); + return -ENODEV; + } + + if (PM_IS_ACTIVE()) { + printk(KERN_NOTICE "apm: overridden by ACPI.\n"); + return -EINVAL; + } + +// ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES); +// if (ret) +// return ret; +// wait_for_completion(&startup); + + pm_active = 1; + +#ifdef CONFIG_PROC_FS + create_proc_info_entry("apm", 0, NULL, apm_get_info); +#endif + + ret = misc_register(&apm_device); + if (ret != 0) { + pm_active = 0; + remove_proc_entry("apm", NULL); + send_sig(SIGQUIT, kapmd, 1); + wait_for_completion(&kapmd_exit); + } + + return ret; +} + +static void __exit apm_exit(void) +{ + misc_deregister(&apm_device); + remove_proc_entry("apm", NULL); + pm_active = 0; +// send_sig(SIGQUIT, kapmd, 1); +// wait_for_completion(&kapmd_exit); +} + +module_init(apm_init); +module_exit(apm_exit); + +MODULE_AUTHOR("Stephen Rothwell"); +MODULE_DESCRIPTION("Advanced Power Management"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; + +#ifndef MODULE +static int __init apm_setup(char *str) +{ + while ((str != NULL) && (*str != '\0')) { + if (strncmp(str, "off", 3) == 0) + apm_disabled = 1; + if (strncmp(str, "on", 2) == 0) + apm_disabled = 0; + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("apm=", apm_setup); +#endif diff -Nru a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c --- a/arch/arm/kernel/bios32.c Thu Jan 16 06:42:22 2003 +++ b/arch/arm/kernel/bios32.c Thu Mar 6 08:26:25 2003 @@ -18,7 +18,6 @@ #include static int debug_pci; -int have_isa_bridge; void pcibios_report_status(u_int status_mask, int warn) { @@ -363,9 +362,8 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) { struct pci_sys_data *root = bus->sysdata; - struct list_head *walk; - u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - u16 all_status = -1; + struct pci_dev *dev; + u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK; pbus_assign_bus_resources(bus, root); @@ -373,42 +371,43 @@ * Walk the devices on this bus, working out what we can * and can't support. */ - for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) { - struct pci_dev *dev = pci_dev_b(walk); + list_for_each_entry(dev, &bus->devices, bus_list) { u16 status; pdev_fixup_device_resources(root, dev); pci_read_config_word(dev, PCI_STATUS, &status); - all_status &= status; + + /* + * If any device on this bus does not support fast back + * to back transfers, then the bus as a whole is not able + * to support them. Having fast back to back transfers + * on saves us one PCI cycle per transaction. + */ + if (!(status & PCI_STATUS_FAST_BACK)) + features &= ~PCI_COMMAND_FAST_BACK; if (pdev_bad_for_parity(dev)) features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY); - /* - * If this device is an ISA bridge, set the have_isa_bridge - * flag. We will then go looking for things like keyboard, - * etc - */ - if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA || - dev->class >> 8 == PCI_CLASS_BRIDGE_EISA) - have_isa_bridge = !0; + switch (dev->class >> 8) { +#if defined(CONFIG_ISA) || defined(CONFIG_EISA) + case PCI_CLASS_BRIDGE_ISA: + case PCI_CLASS_BRIDGE_EISA: + /* + * If this device is an ISA bridge, set isa_bridge + * to point at this device. We will then go looking + * for things like keyboard, etc. + */ + isa_bridge = dev; + break; +#endif } /* - * If any device on this bus does not support fast back to back - * transfers, then the bus as a whole is not able to support them. - * Having fast back to back transfers on saves us one PCI cycle - * per transaction. - */ - if (all_status & PCI_STATUS_FAST_BACK) - features |= PCI_COMMAND_FAST_BACK; - - /* * Now walk the devices again, this time setting them up. */ - for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) { - struct pci_dev *dev = pci_dev_b(walk); + list_for_each_entry(dev, &bus->devices, bus_list) { u16 cmd; pci_read_config_word(dev, PCI_COMMAND, &cmd); @@ -416,7 +415,17 @@ pci_write_config_word(dev, PCI_COMMAND, cmd); pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - SMP_CACHE_BYTES >> 2); + L1_CACHE_BYTES >> 2); + } + + /* + * Propagate the flags to the PCI bridge. + */ + if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + if (features & PCI_COMMAND_FAST_BACK) + bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK; + if (features & PCI_COMMAND_PARITY) + bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY; } /* @@ -454,20 +463,17 @@ */ u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp) { - int pin = *pinp; + int pin = *pinp - 1; - if (pin != 0) { - pin -= 1; - while (dev->bus->self) { - pin = (pin + PCI_SLOT(dev->devfn)) & 3; - /* - * move up the chain of bridges, - * swizzling as we go. - */ - dev = dev->bus->self; - } - *pinp = pin + 1; + while (dev->bus->self) { + pin = (pin + PCI_SLOT(dev->devfn)) & 3; + /* + * move up the chain of bridges, + * swizzling as we go. + */ + dev = dev->bus->self; } + *pinp = pin + 1; return PCI_SLOT(dev->devfn); } diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c --- a/arch/arm/kernel/ecard.c Tue Feb 11 14:57:50 2003 +++ b/arch/arm/kernel/ecard.c Thu Mar 6 05:14:05 2003 @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -57,7 +56,7 @@ enum req { req_readbytes, - req_reset_all + req_reset }; struct ecard_request { @@ -131,14 +130,11 @@ #define POD_INT_ADDR(x) ((volatile unsigned char *)\ ((BUS_ADDR((x)) - IO_BASE) + IO_START)) -static inline void ecard_task_reset(void) +static inline void ecard_task_reset(struct ecard_request *req) { - ecard_t *ec; - - for (ec = cards; ec; ec = ec->next) - if (ec->loader) - ecard_loader_reset(POD_INT_ADDR(ec->podaddr), - ec->loader); + struct expansion_card *ec = req->ec; + if (ec->loader) + ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader); } static void @@ -218,8 +214,8 @@ ecard_task_readbytes(req); break; - case req_reset_all: - ecard_task_reset(); + case req_reset: + ecard_task_reset(req); break; } } @@ -355,60 +351,6 @@ /* ======================= Mid-level card control ===================== */ -/* - * This function is responsible for resetting the expansion cards to a - * sensible state immediately prior to rebooting the system. This function - * has process state (keventd), so we can sleep. - * - * Possible "val" values here: - * SYS_RESTART - restarting system - * SYS_HALT - halting system - * SYS_POWER_OFF - powering down system - * - * We ignore all calls, unless it is a SYS_RESTART call - power down/halts - * will be followed by a SYS_RESTART if ctrl-alt-del is pressed again. - */ -static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v) -{ - struct ecard_request req; - - if (val != SYS_RESTART) - return 0; - - /* - * Disable the expansion card interrupt - */ - disable_irq(IRQ_EXPANSIONCARD); - - /* - * If we have any expansion card loader code which will handle - * the reset for us, call it now. - */ - req.req = req_reset_all; - ecard_call(&req); - - /* - * Disable the expansion card interrupt again, just to be sure. - */ - disable_irq(IRQ_EXPANSIONCARD); - - /* - * Finally, reset the expansion card interrupt mask to - * all enable (RISC OS doesn't set this) - */ -#ifdef HAS_EXPMASK - have_expmask = ~0; - __raw_writeb(have_expmask, EXPMASK_ENABLE); -#endif - return 0; -} - -static struct notifier_block ecard_reboot_notifier = { - .notifier_call = ecard_reboot, -}; - - - static void ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld) { @@ -1083,11 +1025,6 @@ { int slot, irqhw; - /* - * Register our reboot notifier - */ - register_reboot_notifier(&ecard_reboot_notifier); - #ifdef CONFIG_CPU_32 init_waitqueue_head(&ecard_wait); #endif @@ -1158,11 +1095,32 @@ return 0; } +/* + * Before rebooting, we must make sure that the expansion card is in a + * sensible state, so it can be re-detected. This means that the first + * page of the ROM must be visible. We call the expansion cards reset + * handler, if any. + */ +static void ecard_drv_shutdown(struct device *dev) +{ + struct expansion_card *ec = ECARD_DEV(dev); + struct ecard_driver *drv = ECARD_DRV(dev->driver); + struct ecard_request req; + + if (drv->shutdown) + drv->shutdown(ec); + ecard_release(ec); + req.req = req_reset; + req.ec = ec; + ecard_call(&req); +} + int ecard_register_driver(struct ecard_driver *drv) { drv->drv.bus = &ecard_bus_type; drv->drv.probe = ecard_drv_probe; drv->drv.remove = ecard_drv_remove; + drv->drv.shutdown = ecard_drv_shutdown; return driver_register(&drv->drv); } diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S --- a/arch/arm/kernel/entry-armv.S Mon Feb 24 12:42:23 2003 +++ b/arch/arm/kernel/entry-armv.S Thu Mar 6 07:52:20 2003 @@ -1028,8 +1028,10 @@ @ @ now branch to the relevant MODE handling routine @ - mov r13, #PSR_I_BIT | MODE_SVC - msr spsr_c, r13 @ switch to SVC_32 mode + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #MODE_SVC + msr spsr, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] diff -Nru a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S --- a/arch/arm/kernel/entry-common.S Sat Jul 27 12:49:37 2002 +++ b/arch/arm/kernel/entry-common.S Thu Mar 6 05:18:11 2003 @@ -75,9 +75,8 @@ * This is how we return from a fork. */ ENTRY(ret_from_fork) -#ifdef CONFIG_PREEMPT + ldr r0, [r0, #TI_TASK] bl schedule_tail -#endif get_thread_info tsk ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing mov why, #1 diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c --- a/arch/arm/kernel/irq.c Tue Feb 11 15:05:29 2003 +++ b/arch/arm/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -165,17 +165,22 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < NR_IRQS ; i++) { + spin_lock_irqsave(&irq_controller_lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto unlock; + seq_printf(p, "%3d: %10u ", i, kstat_irqs(i)); seq_printf(p, " %s", action->name); - for (action = action->next; action; action = action->next) { + for (action = action->next; action; action = action->next) seq_printf(p, ", %s", action->name); - } + seq_putc(p, '\n'); +unlock: + spin_unlock_irqrestore(&irq_controller_lock, flags); } #ifdef CONFIG_ARCH_ACORN diff -Nru a/arch/arm/kernel/pm.c b/arch/arm/kernel/pm.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/kernel/pm.c Thu Mar 6 07:59:45 2003 @@ -0,0 +1,126 @@ +/* + * linux/arch/arm/kernel/suspend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License. + * + * This is the common support code for suspending an ARM machine. + * pm_do_suspend() is responsible for actually putting the CPU to + * sleep. + */ +#include +#include +#include +#include + +#include +#include + +int suspend(void) +{ + int ret; + + /* + * Suspend "legacy" devices. + */ + ret = pm_send_all(PM_SUSPEND, (void *)3); + if (ret != 0) + goto out; + + /* + * Tell LDM devices we're going to suspend. + */ + ret = device_suspend(4, SUSPEND_NOTIFY); + if (ret != 0) + goto resume_legacy; + + /* + * Disable, devices, and save state. + */ + device_suspend(4, SUSPEND_DISABLE); + device_suspend(4, SUSPEND_SAVE_STATE); + + /* + * Tell devices that they're going to be powered off. + */ + device_suspend(4, SUSPEND_POWER_DOWN); + + local_irq_disable(); + leds_event(led_stop); + + ret = pm_do_suspend(); + + leds_event(led_start); + local_irq_enable(); + + /* + * Tell devices that they now have power. + */ + device_resume(RESUME_POWER_ON); + + /* + * Restore the CPU frequency settings. + */ +#ifdef CONFIG_CPU_FREQ + cpufreq_restore(); +#endif + + /* + * Resume LDM devices. + */ + device_resume(RESUME_RESTORE_STATE); + device_resume(RESUME_ENABLE); + + resume_legacy: + /* + * Resume "legacy" devices. + */ + pm_send_all(PM_RESUME, (void *)0); + + out: + return ret; +} + +#ifdef CONFIG_SYSCTL +#include +#include + +/* + * This came from arch/arm/mach-sa1100/pm.c: + * Copyright (c) 2001 Cliff Brake + * with modifications by Nicolas Pitre and Russell King. + * + * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than + * linux/sysctl.h. + * + * This means our interface here won't survive long - it needs a new + * interface. Quick hack to get this working - use sysctl id 9999. + */ +#warning ACPI broke the kernel, this interface needs to be fixed up. +#define CTL_ACPI 9999 +#define ACPI_S1_SLP_TYP 19 + +static struct ctl_table pm_table[] = +{ + {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&suspend}, + {0} +}; + +static struct ctl_table pm_dir_table[] = +{ + {CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, + {0} +}; + +/* + * Initialize power interface + */ +static int __init pm_init(void) +{ + register_sysctl_table(pm_dir_table, 1); + return 0; +} + +fs_initcall(pm_init); + +#endif diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c --- a/arch/arm/kernel/time.c Mon Feb 24 23:13:09 2003 +++ b/arch/arm/kernel/time.c Thu Mar 6 05:40:54 2003 @@ -200,6 +200,7 @@ static struct irqaction timer_irq = { .name = "timer", + .flags = SA_INTERRUPT, }; /* diff -Nru a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile --- a/arch/arm/mach-integrator/Makefile Sat Dec 14 04:38:56 2002 +++ b/arch/arm/mach-integrator/Makefile Thu Mar 6 08:48:28 2003 @@ -4,10 +4,11 @@ # Object file lists. -obj-y := arch.o cpu.o irq.o mm.o time.o +obj-y := arch.o irq.o mm.o time.o obj-m := obj-n := obj- := obj-$(CONFIG_LEDS) += leds.o obj-$(CONFIG_PCI) += pci_v3.o pci.o +obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c --- a/arch/arm/mach-integrator/cpu.c Tue Jan 14 16:01:39 2003 +++ b/arch/arm/mach-integrator/cpu.c Thu Mar 6 11:27:03 2003 @@ -23,6 +23,8 @@ #include #include +static struct cpufreq_driver integrator_driver; + #define CM_ID (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_ID_OFFSET) #define CM_OSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_OSC_OFFSET) #define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET) @@ -43,7 +45,6 @@ return 2000 * (vco.vdw + 8) / cc_divisor[vco.od] / factor; } -#ifdef CONFIG_CPU_FREQ /* * Divisor indexes in ascending divisor order */ @@ -69,21 +70,17 @@ return vco; } + /* - * Validate the speed in khz. If it is outside our - * range, then return the lowest. + * Validate the speed policy. */ -static int integrator_verify_speed(struct cpufreq_policy *policy) +static int integrator_verify_policy(struct cpufreq_policy *policy) { struct vco vco; - if (policy->max > policy->cpuinfo.max_freq) - policy->max = policy->cpuinfo.max_freq; - - if (policy->max < 12000) - policy->max = 12000; - if (policy->max > 160000) - policy->max = 160000; + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); vco = freq_to_vco(policy->max, 1); @@ -92,12 +89,28 @@ if (vco.vdw > 152) vco.vdw = 152; - policy->min = policy->max = vco_to_freq(vco, 1); + policy->max = vco_to_freq(vco, 1); + + vco = freq_to_vco(policy->min, 1); + + if (vco.vdw < 4) + vco.vdw = 4; + if (vco.vdw > 152) + vco.vdw = 152; + + policy->min = vco_to_freq(vco, 1); + + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); return 0; } -static int integrator_set_policy(struct cpufreq_policy *policy) + +static int integrator_set_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) { unsigned long cpus_allowed; int cpu = policy->cpu; @@ -121,9 +134,18 @@ cm_osc = __raw_readl(CM_OSC); vco.od = (cm_osc >> 8) & 7; vco.vdw = cm_osc & 255; - freqs.old = vco_to_freq(vco, 1); - freqs.new = target_freq; + + /* freq_to_vco rounds down -- so we need the next larger freq in + * case of CPUFREQ_RELATION_L. + */ + if (relation == CPUFREQ_RELATION_L) + target_freq += 1999; + if (target_freq > policy->max) + target_freq = policy->max; + vco = freq_to_vco(target_freq, 1); + freqs.new = vco_to_freq(vco, 1); + freqs.cpu = policy->cpu; if (freqs.old == freqs.new) { @@ -132,7 +154,6 @@ } cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - vco = freq_to_vco(policy->max, 1); cm_osc = __raw_readl(CM_OSC); cm_osc &= 0xfffff800; @@ -152,80 +173,64 @@ return 0; } -static struct cpufreq_policy integrator_policy = { - .cpu = 0, - .policy = CPUFREQ_POLICY_POWERSAVE, - .cpuinfo = { - .max_freq = 160000, - .min_freq = 12000, - .transition_latency = CPUFREQ_ETERNAL, - }, -}; +static int integrator_cpufreq_init(struct cpufreq *policy) +{ + unsigned long cus_allowed; + unsigned int cpu = policy->cpu; + u_int cm_osc, cm_stat, mem_freq_khz; + struct vco vco; -static struct cpufreq_driver integrator_driver = { - .verify = integrator_verify_speed, - .setpolicy = integrator_set_policy, - .policy = &integrator_policy, - .name = "integrator", -}; -#endif + cpus_allowed = current->cpus_allowed; -static int __init integrator_cpu_init(void) -{ - struct cpufreq_policy *policies; - unsigned long cpus_allowed; - int cpu; + set_cpus_allowed(current, 1 << cpu); + BUG_ON(cpu != smp_processor_id()); - policies = kmalloc(sizeof(struct cpufreq_policy) * NR_CPUS, - GFP_KERNEL); - if (!policies) { - printk(KERN_ERR "CPU: unable to allocate policies structure\n"); - return -ENOMEM; - } + /* detect memory etc. */ + cm_stat = __raw_readl(CM_STAT); + cm_osc = __raw_readl(CM_OSC); + vco.od = (cm_osc >> 20) & 7; + vco.vdw = (cm_osc >> 12) & 255; + mem_freq_khz = vco_to_freq(vco, 2); + + printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255); + printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n", + cpu, mem_freq_khz / 1000, mem_freq_khz % 1000); - cpus_allowed = current->cpus_allowed; - for (cpu = 0; cpu < NR_CPUS; cpu++) { - u_int cm_osc, cm_stat, mem_freq_khz; - struct vco vco; - - if (!cpu_online(cpu)) - continue; - - set_cpus_allowed(current, 1 << cpu); - BUG_ON(cpu != smp_processor_id()); - - cm_stat = __raw_readl(CM_STAT); - cm_osc = __raw_readl(CM_OSC); - vco.od = (cm_osc >> 20) & 7; - vco.vdw = (cm_osc >> 12) & 255; - mem_freq_khz = vco_to_freq(vco, 2); - - printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255); - printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n", - cpu, mem_freq_khz / 1000, mem_freq_khz % 1000); - - vco.od = (cm_osc >> 8) & 7; - vco.vdw = cm_osc & 255; - - policies[cpu].cpu = cpu; - policies[cpu].policy = CPUFREQ_POLICY_POWERSAVE, - policies[cpu].cpuinfo.max_freq = 160000; - policies[cpu].cpuinfo.min_freq = 12000; - policies[cpu].cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policies[cpu].min = - policies[cpu].max = vco_to_freq(vco, 1); - } + vco.od = (cm_osc >> 8) & 7; + vco.vdw = cm_osc & 255; - set_cpus_allowed(current, cpus_allowed); + /* set default policy and cpuinfo */ + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->cpuinfo.max_freq = 160000; + policy->cpuinfo.min_freq = 12000; + policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */ + policy->cur = policy->min = policy->max = vco_to_freq(vco, 1); /* current freq */ -#ifdef CONFIG_CPU_FREQ - integrator_driver.policy = policies; - cpufreq_register(&integrator_driver); -#else - kfree(policies); -#endif + set_cpus_allowed(current, cpus_allowed); return 0; } -arch_initcall(integrator_cpu_init); +static struct cpufreq_driver integrator_driver = { + .verify = integrator_verify_policy, + .target = integrator_set_target, + .init = integrator_cpufreq_init, + .name = "integrator", +}; + +static int __init integrator_cpu_init(void) +{ + return cpufreq_register_driver(&integrator_driver); +} + +static void __exit integrator_cpu_exit(void) +{ + cpufreq_unregister_driver(&integrator_driver); +} + +MODULE_AUTHOR ("Russell M. King"); +MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs"); +MODULE_LICENSE ("GPL"); + +module_init(integrator_cpu_init); +module_exit(integrator_cpu_exit); diff -Nru a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig --- a/arch/arm/mach-sa1100/Kconfig Wed Nov 13 08:41:25 2002 +++ b/arch/arm/mach-sa1100/Kconfig Thu Mar 6 16:15:28 2003 @@ -326,6 +326,15 @@ # help # :: write me :: +config SA1100_SSP + tristate "Generic PIO SSP" + depends on ARCH_SA1100 + help + Say Y here to enable support for the generic PIO SSP driver. + This isn't for audio support, but for attached sensors and + other devices, eg for BadgePAD 4 sensor support, or Jornada + 720 touchscreen support. + config SA1100_USB tristate "SA1100 USB function support" depends on ARCH_SA1100 diff -Nru a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile --- a/arch/arm/mach-sa1100/Makefile Mon Feb 3 14:19:35 2003 +++ b/arch/arm/mach-sa1100/Makefile Thu Mar 6 16:15:28 2003 @@ -9,15 +9,8 @@ obj- := led-y := leds.o -# This needs to be cleaned up. We probably need to have SA1100 -# and SA1110 config symbols. -ifeq ($(CONFIG_CPU_FREQ),y) -obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o -obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o -obj-$(CONFIG_SA1100_HACKKIT) += cpu-sa1110.o -obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o -obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o -endif +obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o +obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o # Specific board support obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o @@ -99,3 +92,4 @@ # Miscelaneous functions obj-$(CONFIG_PM) += pm.o sleep.o +obj-$(CONFIG_SA1100_SSP) += ssp.o diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c --- a/arch/arm/mach-sa1100/cpu-sa1100.c Tue Jan 14 16:01:40 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1100.c Thu Mar 6 11:27:04 2003 @@ -101,7 +101,7 @@ } sa1100_dram_regs_t; - +static struct cpufreq_driver sa1100_driver; static sa1100_dram_regs_t sa1100_dram_settings[] = { @@ -176,60 +176,73 @@ } } -static int sa1100_setspeed(struct cpufreq_policy *policy) +static int sa1100_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) { unsigned int cur = sa11x0_getspeed(); + unsigned int new_ppcr; + struct cpufreq_freqs freqs; + switch(relation){ + case CPUFREQ_RELATION_L: + new_ppcr = sa11x0_freq_to_ppcr(target_freq); + if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max) + new_ppcr--; + break; + case CPUFREQ_RELATION_H: + new_ppcr = sa11x0_freq_to_ppcr(target_freq); + if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) && + (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min)) + mew_ppcr--; + break; + } freqs.old = cur; - freqs.new = policy->max; + freqs.new = sa11x0_ppcr_to_freq(new_ppcr); freqs.cpu = 0; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - if (policy->max > cur) - sa1100_update_dram_timings(cur, policy->max); + if (freqs.new > cur) + sa1100_update_dram_timings(cur, freqs.new); - PPCR = sa11x0_freq_to_ppcr(policy->max); + PPCR = new_ppcr; - if (policy->max < cur) - sa1100_update_dram_timings(cur, policy->max); + if (freqs.new < cur) + sa1100_update_dram_timings(cur, freqs.new); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return 0; } -static struct cpufreq_policy sa1100_policy = { - .cpu = 0, - .policy = CPUFREQ_POLICY_POWERSAVE, - .cpuinfo = { - .max_freq = 287000, - .min_freq = 59000, - .transition_latency = CPUFREQ_ETERNAL, - }, -}; +static int __init sa1100_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -EINVAL; + policy->cur = policy->min = policy->max = sa11x0_getspeed(); + policy->policy = CPUFREQ_POLICY_POWERSAVE; + policy->cpuinfo.min_freq = 59000; + policy->cpuinfo.max_freq = 287000; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + return 0; +} static struct cpufreq_driver sa1100_driver = { .verify = sa11x0_verify_speed, - .setpolicy = sa1100_setspeed, - .policy = &sa1100_policy, + .target = sa1100_target, + .init = sa1100_cpu_init, .name = "sa1100", }; static int __init sa1100_dram_init(void) { - int ret = -ENODEV; - - if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) { - sa1100_driver.cpu_cur_freq[0] = - sa1100_policy.min = - sa1100_policy.max = sa11x0_getspeed(); - - ret = cpufreq_register(&sa1100_driver); - } - - return ret; + cpufreq_gov_userspace_init(); + if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) + return cpufreq_register_driver(&sa1100_driver); + else + return -ENODEV; } arch_initcall(sa1100_dram_init); diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c --- a/arch/arm/mach-sa1100/cpu-sa1110.c Tue Jan 14 16:01:40 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c Thu Mar 6 11:27:04 2003 @@ -32,6 +32,8 @@ #undef DEBUG +static struct cpufreq_driver sa1110_driver; + struct sdram_params { u_char rows; /* bits */ u_char cas_latency; /* cycles */ @@ -208,11 +210,11 @@ } /* - * Ok, set the CPU frequency. Since we've done the validation - * above, we can match for an exact frequency. If we don't find - * an exact match, we will to set the lowest frequency to be safe. + * Ok, set the CPU frequency. */ -static int sa1110_setspeed(struct cpufreq_policy *policy) +static int sa1110_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) { struct sdram_params *sdram = &sdram_params; struct cpufreq_freqs freqs; @@ -220,8 +222,25 @@ unsigned long flags; unsigned int ppcr, unused; - ppcr = sa11x0_freq_to_ppcr(policy->max); - sdram_calculate_timing(&sd, policy->max, sdram); + switch(relation){ + case CPUFREQ_RELATION_L: + ppcr = sa11x0_freq_to_ppcr(target_freq); + if (sa11x0_ppcr_to_freq(ppcr) > policy->max) + ppcr--; + break; + case CPUFREQ_RELATION_H: + ppcr = sa11x0_freq_to_ppcr(target_freq); + if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) && + (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min)) + ppcr--; + break; + } + + freqs.old = sa11x0_getspeed(); + freqs.new = sa11x0_ppcr_to_freq(ppcr); + freqs.cpu = 0; + + sdram_calculate_timing(&sd, freqs.new, sdram); #if 0 /* @@ -240,10 +259,6 @@ sd.mdcas[2] = 0xaaaaaaaa; #endif - freqs.old = sa11x0_getspeed(); - freqs.new = policy->max; - freqs.cpu = 0; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); /* @@ -288,27 +303,29 @@ /* * Now, return the SDRAM refresh back to normal. */ - sdram_update_refresh(policy->max, sdram); + sdram_update_refresh(freqs.new, sdram); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return 0; } -static struct cpufreq_policy sa1110_policy = { - .cpu = 0, - .policy = CPUFREQ_POLICY_POWERSAVE, - .cpuinfo = { - .max_freq = 287000, - .min_freq = 59000, - .transition_latency = CPUFREQ_ETERNAL, - }, -}; +static int __init sa1110_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -EINVAL; + policy->cur = policy->min = policy->max = sa11x0_getspeed(); + policy->policy = CPUFREQ_POLICY_POWERSAVE; + policy->cpuinfo.min_freq = 59000; + policy->cpuinfo.max_freq = 287000; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + return 0; +} static struct cpufreq_driver sa1110_driver = { - .verify = sa11x0_verify_speed, - .setpolicy = sa1110_setspeed, - .policy = &sa1110_policy, + .verify = sa11x0_verify_speed, + .target = sa1110_target, + .init = sa1110_cpu_init, .name = "sa1110", }; @@ -331,15 +348,11 @@ sdram->tck, sdram->trcd, sdram->trp, sdram->twr, sdram->refresh, sdram->cas_latency); + cpufreq_gov_userspace_init(); + memcpy(&sdram_params, sdram, sizeof(sdram_params)); - sa1110_driver.cpu_cur_freq[0] = - sa1110_policy.min = - sa1110_policy.max = sa11x0_getspeed(); - - sa1110_setspeed(&sa1110_policy); - - return cpufreq_register(&sa1110_driver); + return cpufreq_register_driver(&sa1110_driver); } return 0; diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c --- a/arch/arm/mach-sa1100/generic.c Fri Dec 13 06:22:36 2002 +++ b/arch/arm/mach-sa1100/generic.c Thu Mar 6 12:25:44 2003 @@ -48,33 +48,48 @@ 2802 /* 280.2 MHz */ }; -#ifdef CONFIG_CPU_FREQ +#if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110) +/* rounds up(!) */ unsigned int sa11x0_freq_to_ppcr(unsigned int khz) { int i; khz /= 100; - for (i = NR_FREQS - 1; i > 0; i--) - if (cclk_frequency_100khz[i] <= khz) + for (i = 0; i < NR_FREQS; i++) + if (cclk_frequency_100khz[i] >= khz) break; return i; } -/* - * Validate the policy. We aren't able to do any fancy in-kernel - * scaling, so we force min=max, and set the policy to "performance". - * If we can't generate the precise frequency requested, round it up. +unsigned int sa11x0_ppcr_to_freq(unsigned int idx) +{ + unsigned int freq = 0; + if (idx < NR_FREQS) + freq = cclk_frequency_100khz[idx] * 100; + return freq; +} + + +/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on + * this platform, anyway. */ int sa11x0_verify_speed(struct cpufreq_policy *policy) { - if (policy->max > policy->cpuinfo.max_freq) - policy->max = policy->cpuinfo.max_freq; + unsigned int tmp; + if (policy->cpu) + return -EINVAL; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); + + /* make sure that at least one frequency is within the policy */ + tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100; + if (tmp > policy->max) + policy->max = tmp; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100; - policy->min = policy->max; - policy->policy = CPUFREQ_POLICY_POWERSAVE; return 0; } diff -Nru a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h --- a/arch/arm/mach-sa1100/generic.h Sun Nov 24 15:14:21 2002 +++ b/arch/arm/mach-sa1100/generic.h Thu Mar 6 08:48:29 2003 @@ -23,3 +23,4 @@ extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); extern int sa11x0_verify_speed(struct cpufreq_policy *policy); extern unsigned int sa11x0_getspeed(void); +extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx); diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c --- a/arch/arm/mach-sa1100/irq.c Sun Mar 2 23:32:23 2003 +++ b/arch/arm/mach-sa1100/irq.c Thu Mar 6 12:33:33 2003 @@ -211,6 +211,99 @@ .end = 0x9005ffff, }; +struct sa1100irq_state { + unsigned int saved; + unsigned int icmr; + unsigned int iclr; + unsigned int iccr; +}; + +static int sa1100irq_suspend(struct device *dev, u32 state, u32 level) +{ + struct sa1100irq_state *st; + + if (!dev->saved_state && level == SUSPEND_NOTIFY) + dev->saved_state = kmalloc(sizeof(struct sa1100irq_state), + GFP_KERNEL); + if (!dev->saved_state) + return -ENOMEM; + + if (level == SUSPEND_POWER_DOWN) { + st = (struct sa1100irq_state *)dev->saved_state; + + st->saved = 1; + st->icmr = ICMR; + st->iclr = ICLR; + st->iccr = ICCR; + + /* + * Disable all GPIO-based interrupts. + */ + ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7| + IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2| + IC_GPIO1|IC_GPIO0); + + /* + * Set the appropriate edges for wakeup. + */ + GRER = PWER & GPIO_IRQ_rising_edge; + GFER = PWER & GPIO_IRQ_falling_edge; + + /* + * Clear any pending GPIO interrupts. + */ + GEDR = GEDR; + } + return 0; +} + +static int sa1100irq_resume(struct device *dev, u32 level) +{ + struct sa1100irq_state *st; + + if (level == RESUME_POWER_ON) { + st = (struct sa1100irq_state *)dev->saved_state; + dev->saved_state = NULL; + + if (st->saved) { + ICCR = st->iccr; + ICLR = st->iclr; + + GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; + GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; + + ICMR = st->icmr; + } + + kfree(st); + } + return 0; +} + +static struct device_driver sa1100irq_driver = { + .name = "sa11x0-irq", + .bus = &system_bus_type, + .suspend = sa1100irq_suspend, + .resume = sa1100irq_resume, +}; + +static struct sys_device sa1100irq_device = { + .name = "irq", + .id = 0, + .dev = { + .name = "Intel SA11x0 [Interrupt Controller]", + .driver = &sa1100irq_driver, + }, +}; + +static int __init sa1100irq_init_devicefs(void) +{ + driver_register(&sa1100irq_driver); + return sys_device_register(&sa1100irq_device); +} + +device_initcall(sa1100irq_init_devicefs); + void __init sa1100_init_irq(void) { unsigned int irq; diff -Nru a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c --- a/arch/arm/mach-sa1100/pm.c Sun Nov 17 07:31:13 2002 +++ b/arch/arm/mach-sa1100/pm.c Thu Mar 6 08:08:20 2003 @@ -22,25 +22,12 @@ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array. * Storage is local on the stack now. */ -#include -#include -#include -#include -#include #include -#include -#include +#include #include #include #include -#include - - -/* - * Debug macros - */ -#undef DEBUG extern void sa1100_cpu_suspend(void); extern void sa1100_cpu_resume(void); @@ -58,10 +45,9 @@ SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER, SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3, - SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR, + SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR, SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR, - SLEEP_SAVE_ICMR, SLEEP_SAVE_Ser1SDCR0, SLEEP_SAVE_SIZE @@ -72,10 +58,6 @@ { unsigned long sleep_save[SLEEP_SAVE_SIZE]; - local_irq_disable(); - - leds_event(led_stop); - /* preserve current time */ RCNR = xtime.tv_sec; @@ -88,8 +70,6 @@ SAVE(OIER); SAVE(GPDR); - SAVE(GRER); - SAVE(GFER); SAVE(GAFR); SAVE(PPDR); @@ -99,13 +79,6 @@ SAVE(Ser1SDCR0); - SAVE(ICMR); - - /* ... maybe a global variable initialized by arch code to set this? */ - GRER = PWER; - GFER = 0; - GEDR = GEDR; - /* Clear previous reset status */ RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR; @@ -115,22 +88,23 @@ /* go zzz */ sa1100_cpu_suspend(); - /* ensure not to come back here if it wasn't intended */ + /* + * Ensure not to come back here if it wasn't intended + */ PSPR = 0; -#ifdef DEBUG - printk(KERN_DEBUG "*** made it back from resume\n"); -#endif + /* + * Ensure interrupt sources are disabled; we will re-init + * the interrupt subsystem via the device manager. + */ + ICLR = 0; + ICCR = 1; + ICMR = 0; /* restore registers */ RESTORE(GPDR); - RESTORE(GRER); - RESTORE(GFER); RESTORE(GAFR); - /* clear any edge detect bit */ - GEDR = GEDR; - RESTORE(PPDR); RESTORE(PPSR); RESTORE(PPAR); @@ -138,6 +112,9 @@ RESTORE(Ser1SDCR0); + /* + * Clear the peripheral sleep-hold bit. + */ PSSR = PSSR_PH; RESTORE(OSMR0); @@ -147,24 +124,9 @@ RESTORE(OSCR); RESTORE(OIER); - ICLR = 0; - ICCR = 1; - RESTORE(ICMR); - /* restore current time */ xtime.tv_sec = RCNR; - leds_event(led_start); - - local_irq_enable(); - - /* - * Restore the CPU frequency settings. - */ -#ifdef CONFIG_CPU_FREQ - cpufreq_restore(); -#endif - return 0; } @@ -172,78 +134,3 @@ { return virt_to_phys(sp); } - -#ifdef CONFIG_SYSCTL -/* - * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than - * linux/sysctl.h. - * - * This means our interface here won't survive long - it needs a new - * interface. Quick hack to get this working - use sysctl id 9999. - */ -#warning ACPI broke the kernel, this interface needs to be fixed up. -#define CTL_ACPI 9999 -#define ACPI_S1_SLP_TYP 19 - -/* - * Send us to sleep. - */ -static int sysctl_pm_do_suspend(void) -{ - int retval; - - /* - * Suspend "legacy" devices. - */ - retval = pm_send_all(PM_SUSPEND, (void *)3); - if (retval == 0) { - /* - * Suspend LDM devices. - */ - device_suspend(4, SUSPEND_NOTIFY); - device_suspend(4, SUSPEND_SAVE_STATE); - device_suspend(4, SUSPEND_DISABLE); - - retval = pm_do_suspend(); - - /* - * Resume LDM devices. - */ - device_resume(RESUME_RESTORE_STATE); - device_resume(RESUME_ENABLE); - - /* - * Resume "legacy" devices. - */ - pm_send_all(PM_RESUME, (void *)0); - } - - return retval; -} - -static struct ctl_table pm_table[] = -{ - {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend}, - {0} -}; - -static struct ctl_table pm_dir_table[] = -{ - {CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, - {0} -}; - -/* - * Initialize power interface - */ -static int __init pm_init(void) -{ - register_sysctl_table(pm_dir_table, 1); - return 0; -} - -fs_initcall(pm_init); - -#endif - -EXPORT_SYMBOL(pm_do_suspend); diff -Nru a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/mach-sa1100/ssp.c Thu Mar 6 16:15:28 2003 @@ -0,0 +1,208 @@ +/* + * linux/arch/arm/mach-sa1100/ssp.c + * + * Copyright (C) 2003 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Generic SSP driver. This provides the generic core for simple + * IO-based SSP applications. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static void ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int status = Ser4SSSR; + + if (status & SSSR_ROR) { + printk(KERN_WARNING "SSP: receiver overrun\n"); + } + + Ser4SSSR = SSSR_ROR; +} + +/** + * ssp_write_word - write a word to the SSP port + * @data: 16-bit, MSB justified data to write. + * + * Wait for a free entry in the SSP transmit FIFO, and write a data + * word to the SSP port. + * + * The caller is expected to perform the necessary locking. + * + * Returns: + * %-ETIMEDOUT timeout occurred (for future) + * 0 success + */ +int ssp_write_word(u16 data) +{ + while (!(Ser4SSSR & SSSR_TNF)) + cpu_relax(); + + Ser4SSDR = data; + + return 0; +} + +/** + * ssp_read_word - read a word from the SSP port + * + * Wait for a data word in the SSP receive FIFO, and return the + * received data. Data is LSB justified. + * + * Note: Currently, if data is not expected to be received, this + * function will wait for ever. + * + * The caller is expected to perform the necessary locking. + * + * Returns: + * %-ETIMEDOUT timeout occurred (for future) + * 16-bit data success + */ +int ssp_read_word(void) +{ + while (!(Ser4SSSR & SSSR_RNE)) + cpu_relax(); + + return Ser4SSDR; +} + +/** + * ssp_flush - flush the transmit and receive FIFOs + * + * Wait for the SSP to idle, and ensure that the receive FIFO + * is empty. + * + * The caller is expected to perform the necessary locking. + */ +void ssp_flush(void) +{ + do { + while (Ser4SSSR & SSSR_RNE) { + (void) Ser4SSDR; + } + } while (Ser4SSSR & SSSR_BSY); +} + +/** + * ssp_enable - enable the SSP port + * + * Turn on the SSP port. + */ +void ssp_enable(void) +{ + Ser4SSCR0 |= SSCR0_SSE; +} + +/** + * ssp_disable - shut down the SSP port + * + * Turn off the SSP port, optionally powering it down. + */ +void ssp_disable(void) +{ + Ser4SSCR0 &= ~SSCR0_SSE; +} + +/** + * ssp_save_state - save the SSP configuration + * @ssp: pointer to structure to save SSP configuration + * + * Save the configured SSP state for suspend. + */ +void ssp_save_state(struct ssp_state *ssp) +{ + ssp->cr0 = Ser4SSCR0; + ssp->cr1 = Ser4SSCR1; + + Ser4SSCR0 &= ~SSCR0_SSE; +} + +/** + * ssp_restore_state - restore a previously saved SSP configuration + * @ssp: pointer to configuration saved by ssp_save_state + * + * Restore the SSP configuration saved previously by ssp_save_state. + */ +void ssp_restore_state(struct ssp_state *ssp) +{ + Ser4SSSR = SSSR_ROR; + + Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE; + Ser4SSCR1 = ssp->cr1; + Ser4SSCR0 = ssp->cr0; +} + +/** + * ssp_init - setup the SSP port + * + * initialise and claim resources for the SSP port. + * + * Returns: + * %-ENODEV if the SSP port is unavailable + * %-EBUSY if the resources are already in use + * %0 on success + */ +int ssp_init(void) +{ + int ret; + + if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE)) + return -ENODEV; + + if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) { + return -EBUSY; + } + + Ser4SSSR = SSSR_ROR; + + ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL); + if (ret) + goto out_region; + + return 0; + + out_region: + release_mem_region(__PREG(Ser4SSCR0), 0x18); + return ret; +} + +/** + * ssp_exit - undo the effects of ssp_init + * + * release and free resources for the SSP port. + */ +void ssp_exit(void) +{ + Ser4SSCR0 &= ~SSCR0_SSE; + + free_irq(IRQ_Ser4SSP, NULL); + release_mem_region(__PREG(Ser4SSCR0), 0x18); +} + +MODULE_AUTHOR("Russell King"); +MODULE_DESCRIPTION("SA11x0 SSP PIO driver"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(ssp_write_word); +EXPORT_SYMBOL(ssp_read_word); +EXPORT_SYMBOL(ssp_flush); +EXPORT_SYMBOL(ssp_enable); +EXPORT_SYMBOL(ssp_disable); +EXPORT_SYMBOL(ssp_save_state); +EXPORT_SYMBOL(ssp_restore_state); +EXPORT_SYMBOL(ssp_init); +EXPORT_SYMBOL(ssp_exit); diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c --- a/arch/arm/mach-sa1100/system3.c Sun Nov 17 07:31:13 2002 +++ b/arch/arm/mach-sa1100/system3.c Thu Mar 6 08:48:29 2003 @@ -213,11 +213,17 @@ static int sdram_notifier(struct notifier_block *nb, unsigned long event, void *data) { + struct cpufreq_policy *policy = data; switch (event) { - case CPUFREQ_MINMAX: - cpufreq_updateminmax(data, 147500, 206000); + case CPUFREQ_ADJUST: + case CPUFREQ_INCOMPATIBLE: + cpufreq_verify_within_limits(policy, 147500, 206000); + break; + case CPUFREQ_NOTIFY: + if ((policy->min < 147500) || + (policy->max > 206000)) + panic("cpufreq failed to limit the speed\n"); break; - } return 0; } @@ -405,7 +411,7 @@ goto DONE; } -#if defined( CONFIG_CPU_FREQ ) +#ifdef CONFIG_CPU_FREQ ret = cpufreq_register_notifier(&system3_clkchg_block); if ( ret != 0 ) { printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" ); diff -Nru a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c --- a/arch/arm/mm/fault-common.c Sun Jan 12 09:11:08 2003 +++ b/arch/arm/mm/fault-common.c Thu Mar 6 08:19:03 2003 @@ -342,20 +342,20 @@ struct pt_regs *regs) { struct task_struct *tsk; - unsigned int offset; + unsigned int index; pgd_t *pgd, *pgd_k; pmd_t *pmd, *pmd_k; if (addr < TASK_SIZE) return do_page_fault(addr, fsr, regs); - offset = __pgd_offset(addr); + index = pgd_index(addr); /* * FIXME: CP15 C1 is write only on ARMv3 architectures. */ - pgd = cpu_get_pgd() + offset; - pgd_k = init_mm.pgd + offset; + pgd = cpu_get_pgd() + index; + pgd_k = init_mm.pgd + index; if (pgd_none(*pgd_k)) goto bad_area; diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types --- a/arch/arm/tools/mach-types Thu Jan 16 06:52:35 2003 +++ b/arch/arm/tools/mach-types Thu Mar 6 06:57:42 2003 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Mon Jan 13 22:55:16 2003 +# Last update: Wed Mar 5 22:11:59 2003 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -228,7 +228,7 @@ arnold SA1100_ARNOLD ARNOLD 217 psiboard SA1100_PSIBOARD PSIBOARD 218 jz8028 ARCH_JZ8028 JZ8028 219 -ipaq3 ARCH_IPAQ3 IPAQ3 220 +h5400 ARCH_IPAQ3 IPAQ3 220 forte SA1100_FORTE FORTE 221 acam SA1100_ACAM ACAM 222 abox SA1100_ABOX ABOX 223 @@ -259,7 +259,7 @@ stork_egg ARCH_STORK_EGG STORK_EGG 248 wismo SA1100_WISMO WISMO 249 ezlinx ARCH_EZLINX EZLINX 250 -at91rm9200 ARCH_AT91 AT91 251 +at91 ARCH_AT91 AT91 251 orion ARCH_ORION ORION 252 neptune ARCH_NEPTUNE NEPTUNE 253 hackkit SA1100_HACKKIT HACKKIT 254 @@ -281,3 +281,27 @@ siren ARCH_SIREN SIREN 270 greenlake ARCH_GREENLAKE GREENLAKE 271 argus ARCH_ARGUS ARGUS 272 +combadge SA1100_COMBADGE COMBADGE 273 +rokepxa ARCH_ROKEPXA ROKEPXA 274 +cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275 +guidea07 ARCH_GUIDEA07 GUIDEA07 276 +tat257 ARCH_TAT257 TAT257 277 +igp2425 ARCH_IGP2425 IGP2425 278 +bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279 +ipod ARCH_IPOD IPOD 280 +adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281 +trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282 +viper ARCH_VIPER VIPER 283 +adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284 +adsagc SA1100_ADSAGC ADSAGC 285 +stp7312 ARCH_STP7312 STP7312 286 +nx_phnx ARCH_PXA255 PXA255 287 +wep_ep250 ARCH_WEP_EP250 WEP_EP250 288 +inhandelf3 ARCH_INHANDELF3 INHANDELF3 289 +adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290 +iyonix ARCH_IYONIX IYONIX 291 +damicam_sa1110 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292 +meg03 ARCH_MEG03 MEG03 293 +pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294 +nwsc ARCH_NWSC NWSC 295 +nwlarm ARCH_NWLARM NWLARM 296 diff -Nru a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in --- a/arch/arm/vmlinux-armo.lds.in Wed Jan 15 09:48:42 2003 +++ b/arch/arm/vmlinux-armo.lds.in Fri Feb 14 14:36:57 2003 @@ -38,6 +38,9 @@ *(.initcall6.init) *(.initcall7.init) __initcall_end = .; + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; . = ALIGN(32768); __init_end = .; } diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in --- a/arch/arm/vmlinux-armv.lds.in Tue Feb 11 08:24:17 2003 +++ b/arch/arm/vmlinux-armv.lds.in Wed Feb 19 07:21:37 2003 @@ -45,6 +45,9 @@ *(.initcall6.init) *(.initcall7.init) __initcall_end = .; + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; . = ALIGN(32); __initramfs_start = .; usr/built-in.o(.init.ramfs) diff -Nru a/arch/cris/Kconfig b/arch/cris/Kconfig --- a/arch/cris/Kconfig Sun Feb 9 17:29:49 2003 +++ b/arch/cris/Kconfig Sat Mar 8 14:50:37 2003 @@ -9,10 +9,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c --- a/arch/cris/kernel/irq.c Thu Oct 31 07:28:36 2002 +++ b/arch/cris/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -228,11 +228,13 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0; i < NR_IRQS; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %10u %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -243,6 +245,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/cris/vmlinux.lds.S b/arch/cris/vmlinux.lds.S --- a/arch/cris/vmlinux.lds.S Wed Jan 15 09:48:42 2003 +++ b/arch/cris/vmlinux.lds.S Fri Feb 14 14:37:05 2003 @@ -69,7 +69,12 @@ *(.initcall6.init); *(.initcall7.init); __initcall_end = .; - + } + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + /* We fill to the next page, so we can discard all init pages without needing to consider what payload might be appended to the kernel image. */ diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Sun Mar 2 18:14:31 2003 +++ b/arch/i386/Kconfig Sat Mar 8 14:50:37 2003 @@ -18,15 +18,6 @@ bool default y -config SWAP - bool "Support for paging of anonymous memory" - default y - help - This option allows you to choose whether you want to have support - for socalled swap devices or swap files in your kernel that are - used to provide more virtual memory than the actual RAM present - in your computer. If unusre say Y. - config SBUS bool @@ -488,7 +479,7 @@ # Common NUMA Features config NUMA bool "Numa Memory Allocation Support" - depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))) + depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))) || X86_PC config DISCONTIGMEM bool diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile --- a/arch/i386/Makefile Fri Feb 21 19:34:09 2003 +++ b/arch/i386/Makefile Tue Mar 4 15:09:44 2003 @@ -92,7 +92,8 @@ boot := arch/i386/boot -.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install +.PHONY: zImage bzImage compressed zlilo bzlilo \ + zdisk bzdisk fdimage fdimage144 fdimage288 install all: bzImage @@ -110,8 +111,8 @@ zdisk bzdisk: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk -install: vmlinux - $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) install +install fdimage fdimage144 fdimage288: vmlinux + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ archclean: $(Q)$(MAKE) $(clean)=arch/i386/boot @@ -122,5 +123,8 @@ echo ' (your) ~/bin/installkernel or' echo ' (distribution) /sbin/installkernel or' echo ' install to $$(INSTALL_PATH) and run lilo' + echo ' bzdisk - Create a boot floppy in /dev/fd0' + echo ' fdimage - Create a boot floppy image' endef +CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf diff -Nru a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile --- a/arch/i386/boot/Makefile Mon Dec 30 23:11:35 2002 +++ b/arch/i386/boot/Makefile Fri Mar 7 14:10:59 2003 @@ -62,8 +62,36 @@ $(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \ IMAGE_OFFSET=$(IMAGE_OFFSET) $@ -zdisk: $(BOOTIMAGE) - dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0 +# Set this if you want to pass append arguments to the zdisk/fdimage kernel +FDARGS = + +$(obj)/mtools.conf: $(src)/mtools.conf.in + sed -e 's|@OBJ@|$(obj)|g' < $< > $@ + +# This requires write access to /dev/fd0 +zdisk: $(BOOTIMAGE) $(obj)/mtools.conf + MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync + syslinux /dev/fd0 ; sync + echo 'default linux $(FDARGS)' | \ + MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync + +# These require being root or having syslinux 2.02 or higher installed +fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf + dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 + MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync + syslinux $(obj)/fdimage ; sync + echo 'default linux $(FDARGS)' | \ + MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync + +fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf + dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 + MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync + syslinux $(obj)/fdimage ; sync + echo 'default linux $(FDARGS)' | \ + MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync zlilo: $(BOOTIMAGE) if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi diff -Nru a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S --- a/arch/i386/boot/bootsect.S Fri Feb 21 06:03:16 2003 +++ b/arch/i386/boot/bootsect.S Tue Mar 4 15:10:25 2003 @@ -4,29 +4,13 @@ * modified by Drew Eckhardt * modified by Bruce Evans (bde) * modified by Chris Noe (May 1999) (as86 -> gas) - * - * 360k/720k disk support: Andrzej Krzysztofowicz + * gutted by H. Peter Anvin (Jan 2003) * * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment * addresses must be multiplied by 16 to obtain their respective linear * addresses. To avoid confusion, linear addresses are written using leading * hex while segment addresses are written as segment:offset. * - * bde - should not jump blindly, there may be systems with only 512K low - * memory. Use int 0x12 to get the top of memory, etc. - * - * It then loads 'setup' directly after itself (0x90200), and the system - * at 0x10000, using BIOS interrupts. - * - * NOTE! currently system is at most (8*65536-4096) bytes long. This should - * be no problem, even in the future. I want to keep it simple. This 508 kB - * kernel size should be enough, especially as this doesn't contain the - * buffer cache as in minix (and especially now that the kernel is - * compressed :-) - * - * The loader has been made as simple as possible, and continuous - * read errors will result in a unbreakable loop. Reboot by hand. It - * loads pretty fast by getting whole tracks at a time whenever possible. */ #include @@ -59,359 +43,51 @@ .global _start _start: -# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there. + # Normalize the start address + jmpl $BOOTSEG, $start2 - movw $BOOTSEG, %ax - movw %ax, %ds # %ds = BOOTSEG - movw $INITSEG, %ax - movw %ax, %es # %ax = %es = INITSEG - movw $256, %cx - subw %si, %si - subw %di, %di - cld - rep - movsw - ljmp $INITSEG, $go - -# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We -# wouldn't have to worry about this if we checked the top of memory. Also -# my BIOS can be configured to put the wini drive tables in high memory -# instead of in the vector table. The old stack might have clobbered the -# drive table. - -go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >= - # length of bootsect + length of - # setup + room for stack; - # 12 is disk parm size. - movw %ax, %ds # %ax and %es already contain INITSEG +start2: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es movw %ax, %ss - movw %di, %sp # put stack at INITSEG:0x4000-12. + movw $0x7c00, %sp + sti + cld -# Many BIOS's default disk parameter tables will not recognize -# multi-sector reads beyond the maximum sector number specified -# in the default diskette parameter tables - this may mean 7 -# sectors in some cases. -# -# Since single sector reads are slow and out of the question, -# we must take care of this by creating new parameter tables -# (for the first disk) in RAM. We will set the maximum sector -# count to 36 - the most we will encounter on an ED 2.88. -# -# High doesn't hurt. Low does. -# -# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0, -# and %gs is unused. - - movw %cx, %fs # %fs = 0 - movw $0x78, %bx # %fs:%bx is parameter table address - pushw %ds - ldsw %fs:(%bx), %si # %ds:%si is source - movb $6, %cl # copy 12 bytes - pushw %di # %di = 0x4000-12. - rep # don't worry about cld - movsw # already done above - popw %di - popw %ds - movb $36, 0x4(%di) # patch sector count - movw %di, %fs:(%bx) - movw %es, %fs:2(%bx) - -# Get disk drive parameters, specifically number of sectors/track. - -# It seems that there is no BIOS call to get the number of sectors. -# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18 -# can be read, 15 if sector 15 can be read. Otherwise guess 9. -# Note that %cx = 0 from rep movsw above. + movw $bugger_off_msg, %si - movw $disksizes, %si # table of sizes to try -probe_loop: +msg_loop: lodsb - cbtw # extend to word - movw %ax, sectors - cmpw $disksizes+4, %si - jae got_sectors # If all else fails, try 9 - - xchgw %cx, %ax # %cx = track and sector - xorw %dx, %dx # drive 0, head 0 - movw $0x0200, %bx # address = 512, in INITSEG (%es = %cs) - movw $0x0201, %ax # service 2, 1 sector - int $0x13 - jc probe_loop # try next value - -got_sectors: - movb $0x03, %ah # read cursor pos - xorb %bh, %bh - int $0x10 - movw $9, %cx - movb $0x07, %bl # page 0, attribute 7 (normal) - # %bh is set above; int10 doesn't - # modify it - movw $msg1, %bp - movw $0x1301, %ax # write string, move cursor - int $0x10 # tell the user we're loading.. - -# Load the setup-sectors directly after the moved bootblock (at 0x90200). -# We should know the drive geometry to do it, as setup may exceed first -# cylinder (for 9-sector 360K and 720K floppies). - - movw $0x0001, %ax # set sread (sector-to-read) to 1 as - movw $sread, %si # the boot sector has already been read - movw %ax, (%si) - - call kill_motor # reset FDC - movw $0x0200, %bx # address = 512, in INITSEG -next_step: - movb setup_sects, %al - movw sectors, %cx - subw (%si), %cx # (%si) = sread - cmpb %cl, %al - jbe no_cyl_crossing - movw sectors, %ax - subw (%si), %ax # (%si) = sread -no_cyl_crossing: - call read_track - pushw %ax # save it - call set_next # set %bx properly; it uses %ax,%cx,%dx - popw %ax # restore - subb %al, setup_sects # rest - for next step - jnz next_step - - pushw $SYSSEG - popw %es # %es = SYSSEG - call read_it - call kill_motor - call print_nl - -# After that we check which root-device to use. If the device is -# defined (!= 0), nothing is done and the given device is used. -# Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8) -# depending on the number of sectors we pretend to know we have. - -# Segments are as follows: %cs = %ds = %ss = INITSEG, -# %es = SYSSEG, %fs = 0, %gs is unused. - - movw root_dev, %ax - orw %ax, %ax - jne root_defined - - movw sectors, %bx - movw $0x0208, %ax # /dev/ps0 - 1.2Mb - cmpw $15, %bx - je root_defined - - movb $0x1c, %al # /dev/PS0 - 1.44Mb - cmpw $18, %bx - je root_defined - - movb $0x20, %al # /dev/fd0H2880 - 2.88Mb - cmpw $36, %bx - je root_defined - - movb $0, %al # /dev/fd0 - autodetect -root_defined: - movw %ax, root_dev - -# After that (everything loaded), we jump to the setup-routine -# loaded directly after the bootblock: - - ljmp $SETUPSEG, $0 - -# These variables are addressed via %si register as it gives shorter code. - -sread: .word 0 # sectors read of current track -head: .word 0 # current head -track: .word 0 # current track - -# This routine loads the system at address SYSSEG, making sure -# no 64kB boundaries are crossed. We try to load it as fast as -# possible, loading whole tracks whenever we can. - -read_it: - movw %es, %ax # %es = SYSSEG when called - testw $0x0fff, %ax -die: jne die # %es must be at 64kB boundary - xorw %bx, %bx # %bx is starting address within segment -rp_read: -#ifdef __BIG_KERNEL__ # look in setup.S for bootsect_kludge - bootsect_kludge = 0x220 # 0x200 + 0x20 which is the size of the - lcall *bootsect_kludge # bootsector + bootsect_kludge offset -#else - movw %es, %ax - subw $SYSSEG, %ax - movw %bx, %cx - shr $4, %cx - add %cx, %ax # check offset -#endif - cmpw syssize, %ax # have we loaded everything yet? - jbe ok1_read - - ret - -ok1_read: - movw sectors, %ax - subw (%si), %ax # (%si) = sread - movw %ax, %cx - shlw $9, %cx - addw %bx, %cx - jnc ok2_read - - je ok2_read - - xorw %ax, %ax - subw %bx, %ax - shrw $9, %ax -ok2_read: - call read_track - call set_next - jmp rp_read - -read_track: - pusha - pusha - movw $0xe2e, %ax # loading... message 2e = . + andb %al, %al + jz die + movb $0xe, %ah movw $7, %bx - int $0x10 - popa - -# Accessing head, track, sread via %si gives shorter code. + int $0x10 + jmp msg_loop - movw 4(%si), %dx # 4(%si) = track - movw (%si), %cx # (%si) = sread - incw %cx - movb %dl, %ch - movw 2(%si), %dx # 2(%si) = head - movb %dl, %dh - andw $0x0100, %dx - movb $2, %ah - pushw %dx # save for error dump - pushw %cx - pushw %bx - pushw %ax - int $0x13 - jc bad_rt - - addw $8, %sp - popa - ret - -set_next: - movw %ax, %cx - addw (%si), %ax # (%si) = sread - cmp sectors, %ax - jne ok3_set - movw $0x0001, %ax - xorw %ax, 2(%si) # change head - jne ok4_set - incw 4(%si) # next track -ok4_set: +die: + # Allow the user to press a key, then reboot xorw %ax, %ax -ok3_set: - movw %ax, (%si) # set sread - shlw $9, %cx - addw %cx, %bx - jnc set_next_fin - movw %es, %ax - addb $0x10, %ah - movw %ax, %es - xorw %bx, %bx -set_next_fin: - ret - -bad_rt: - pushw %ax # save error code - call print_all # %ah = error, %al = read - xorb %ah, %ah - xorb %dl, %dl - int $0x13 - addw $10, %sp - popa - jmp read_track - -# print_all is for debugging purposes. -# -# it will print out all of the registers. The assumption is that this is -# called from a routine, with a stack frame like -# -# %dx -# %cx -# %bx -# %ax -# (error) -# ret <- %sp - -print_all: - movw $5, %cx # error code + 4 registers - movw %sp, %bp -print_loop: - pushw %cx # save count remaining - call print_nl # <-- for readability - cmpb $5, %cl - jae no_reg # see if register name is needed - - movw $0xe05 + 'A' - 1, %ax - subb %cl, %al - int $0x10 - movb $'X', %al - int $0x10 - movb $':', %al - int $0x10 -no_reg: - addw $2, %bp # next register - call print_hex # print it - popw %cx - loop print_loop - ret + int $0x16 + int $0x19 -print_nl: - movw $0xe0d, %ax # CR - int $0x10 - movb $0xa, %al # LF - int $0x10 - ret - -# print_hex is for debugging purposes, and prints the word -# pointed to by %ss:%bp in hexadecimal. - -print_hex: - movw $4, %cx # 4 hex digits - movw (%bp), %dx # load word into %dx -print_digit: - rolw $4, %dx # rotate to use low 4 bits - movw $0xe0f, %ax # %ah = request - andb %dl, %al # %al = mask for nybble - addb $0x90, %al # convert %al to ascii hex - daa # in only four instructions! - adc $0x40, %al - daa - int $0x10 - loop print_digit - ret + # int 0x19 should never return. In case it does anyway, + # invoke the BIOS reset code... + ljmp $0xf000,$0xfff0 -# This procedure turns off the floppy drive motor, so -# that we enter the kernel in a known state, and -# don't have to worry about it later. -# NOTE: Doesn't save %ax or %dx; do it yourself if you need to. - -kill_motor: -#if 1 - xorw %ax, %ax # reset FDC - xorb %dl, %dl - int $0x13 -#else - movw $0x3f2, %dx - xorb %al, %al - outb %al, %dx -#endif - ret -sectors: .word 0 -disksizes: .byte 36, 21, 18, 15, 9 -msg1: .byte 13, 10 - .ascii "Loading" +bugger_off_msg: + .ascii "Direct booting from floppy is no longer supported.\r\n" + .ascii "Please use a boot loader program instead.\r\n" + .ascii "\n" + .ascii "Remove disk and press any key to reboot . . .\r\n" + .byte 0 + -# XXX: This is a fairly snug fit. + # Kernel attributes; used by setup -.org 497 + .org 497 setup_sects: .byte SETUPSECTS root_flags: .word ROOT_RDONLY syssize: .word SYSSIZE diff -Nru a/arch/i386/boot/mtools.conf.in b/arch/i386/boot/mtools.conf.in --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/boot/mtools.conf.in Tue Mar 4 15:09:44 2003 @@ -0,0 +1,17 @@ +# +# mtools configuration file for "make (b)zdisk" +# + +# Actual floppy drive +drive a: + file="/dev/fd0" + +# 1.44 MB floppy disk image +drive v: + file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter + +# 2.88 MB floppy disk image (mostly for virtual uses) +drive w: + file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter + + diff -Nru a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c --- a/arch/i386/boot/tools/build.c Mon Feb 4 23:41:17 2002 +++ b/arch/i386/boot/tools/build.c Tue Mar 4 15:09:44 2003 @@ -150,13 +150,10 @@ sz = sb.st_size; fprintf (stderr, "System is %d kB\n", sz/1024); sys_size = (sz + 15) / 16; - /* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */ - if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE)) + /* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */ + if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE)) die("System is too big. Try using %smodules.", is_big_kernel ? "" : "bzImage or "); - if (sys_size > 0xefff) - fprintf(stderr,"warning: kernel is too big for standalone boot " - "from floppy\n"); while (sz > 0) { int l, n; diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c --- a/arch/i386/kernel/cpu/common.c Wed Feb 19 17:48:55 2003 +++ b/arch/i386/kernel/cpu/common.c Mon Mar 10 10:20:30 2003 @@ -480,7 +480,7 @@ */ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; - if(current->mm) + if (current->mm) BUG(); enter_lazy_tlb(&init_mm, current, cpu); @@ -508,7 +508,7 @@ /* * Force FPU initialization: */ - clear_thread_flag(TIF_USEDFPU); + current_thread_info()->status = 0; current->used_math = 0; stts(); } diff -Nru a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c --- a/arch/i386/kernel/cpu/cpufreq/acpi.c Fri Feb 28 07:59:47 2003 +++ b/arch/i386/kernel/cpu/cpufreq/acpi.c Sat Mar 8 01:37:35 2003 @@ -619,6 +619,7 @@ .init = acpi_cpufreq_cpu_init, .exit = acpi_cpufreq_cpu_exit, .name = "acpi-cpufreq", + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c Fri Feb 28 07:52:11 2003 +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c Sat Mar 8 01:37:35 2003 @@ -250,6 +250,7 @@ .target = elanfreq_target, .init = elanfreq_cpu_init, .name = "elanfreq", + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Fri Feb 28 07:52:11 2003 +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Sat Mar 8 01:37:35 2003 @@ -451,6 +451,7 @@ .target = cpufreq_gx_target, .init = cpufreq_gx_cpu_init, .name = "gx-suspmod", + .owner = THIS_MODULE, }; static int __init cpufreq_gx_init(void) diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c Fri Feb 28 08:02:11 2003 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Sat Mar 8 01:37:35 2003 @@ -649,6 +649,7 @@ .target = longhaul_target, .init = longhaul_cpu_init, .name = "longhaul", + .owner = THIS_MODULE, }; static int __init longhaul_init (void) diff -Nru a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c --- a/arch/i386/kernel/cpu/cpufreq/longrun.c Fri Feb 28 08:08:36 2003 +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c Sat Mar 8 01:37:35 2003 @@ -253,6 +253,7 @@ .setpolicy = longrun_set_policy, .init = longrun_cpu_init, .name = "longrun", + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Fri Feb 28 07:52:11 2003 +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Sat Mar 8 01:39:17 2003 @@ -214,6 +214,7 @@ else p4clockmod_table[i].frequency = (stock_freq * i)/8; } + cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); /* cpuinfo and default policy values */ policy->policy = CPUFREQ_POLICY_PERFORMANCE; @@ -226,9 +227,14 @@ static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) { + cpufreq_frequency_table_put_attr(policy->cpu); return cpufreq_p4_setdc(policy->cpu, DC_DISABLE); } +static struct freq_attr* p4clockmod_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; static struct cpufreq_driver p4clockmod_driver = { .verify = cpufreq_p4_verify, @@ -236,6 +242,8 @@ .init = cpufreq_p4_cpu_init, .exit = cpufreq_p4_cpu_exit, .name = "p4-clockmod", + .owner = THIS_MODULE, + .attr = p4clockmod_attr, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Fri Feb 28 08:03:44 2003 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Sat Mar 8 01:37:35 2003 @@ -190,6 +190,7 @@ .init = powernow_k6_cpu_init, .exit = powernow_k6_cpu_exit, .name = "powernow-k6", + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Fri Feb 28 08:03:52 2003 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Sat Mar 8 01:37:35 2003 @@ -377,6 +377,7 @@ .target = powernow_target, .init = powernow_cpu_init, .name = "powernow-k7", + .owner = THIS_MODULE, }; static int __init powernow_init (void) diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep.c b/arch/i386/kernel/cpu/cpufreq/speedstep.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep.c Fri Feb 28 08:04:04 2003 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep.c Sat Mar 8 01:46:02 2003 @@ -29,7 +29,6 @@ #include - /* speedstep_chipset: * It is necessary to know which chipset is used. As accesses to * this device occur at various places in this module, we need a @@ -40,7 +39,7 @@ #define SPEEDSTEP_CHIPSET_ICH2M 0x00000002 #define SPEEDSTEP_CHIPSET_ICH3M 0x00000003 - +#define SPEEDSTEP_CHIPSET_ICH4M 0x00000004 /* speedstep_processor */ @@ -106,6 +105,7 @@ switch (speedstep_chipset) { case SPEEDSTEP_CHIPSET_ICH2M: case SPEEDSTEP_CHIPSET_ICH3M: + case SPEEDSTEP_CHIPSET_ICH4M: /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) @@ -166,6 +166,7 @@ switch (speedstep_chipset) { case SPEEDSTEP_CHIPSET_ICH2M: case SPEEDSTEP_CHIPSET_ICH3M: + case SPEEDSTEP_CHIPSET_ICH4M: /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) @@ -245,6 +246,7 @@ switch (speedstep_chipset) { case SPEEDSTEP_CHIPSET_ICH2M: case SPEEDSTEP_CHIPSET_ICH3M: + case SPEEDSTEP_CHIPSET_ICH4M: { u16 value = 0; @@ -277,6 +279,14 @@ static unsigned int speedstep_detect_chipset (void) { speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801DB_12, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return SPEEDSTEP_CHIPSET_ICH4M; + + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, @@ -658,6 +668,7 @@ .verify = speedstep_verify, .target = speedstep_target, .init = speedstep_cpu_init, + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Tue Feb 25 11:06:46 2003 +++ b/arch/i386/kernel/entry.S Mon Mar 10 14:41:23 2003 @@ -72,6 +72,12 @@ NT_MASK = 0x00004000 VM_MASK = 0x00020000 +/* + * ESP0 is at offset 4. 0x100 is the size of the TSS, and + * also thus the top-of-stack pointer offset of SYSENTER_ESP + */ +TSS_ESP0_OFFSET = (4 - 0x100) + #ifdef CONFIG_PREEMPT #define preempt_stop cli #else @@ -229,6 +235,8 @@ # sysenter call handler stub ENTRY(sysenter_entry) + movl TSS_ESP0_OFFSET(%esp),%esp +sysenter_past_esp: sti pushl $(__USER_DS) pushl %ebp @@ -458,12 +466,36 @@ addl $4, %esp jmp ret_from_exception +/* + * Debug traps and NMI can happen at the one SYSENTER instruction + * that sets up the real kernel stack. Check here, since we can't + * allow the wrong stack to be used. + * + * "TSS_ESP0_OFFSET+12" is because the NMI/debug handler will have + * already pushed 3 words if it hits on the sysenter instruction: + * eflags, cs and eip. + * + * We just load the right stack, and push the three (known) values + * by hand onto the new stack - while updating the return eip past + * the instruction that would have done it for sysenter. + */ +#define CHECK_SYSENTER_EIP \ + cmpl $sysenter_entry,(%esp); \ + jne 1f; \ + movl TSS_ESP0_OFFSET+12(%esp),%esp; \ + pushfl; \ + pushl $__KERNEL_CS; \ + pushl $sysenter_past_esp; \ +1: + ENTRY(debug) + CHECK_SYSENTER_EIP pushl $0 pushl $do_debug jmp error_code ENTRY(nmi) + CHECK_SYSENTER_EIP pushl %eax SAVE_ALL movl %esp, %edx diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c Fri Feb 28 00:05:34 2003 +++ b/arch/i386/kernel/i386_ksyms.c Wed Mar 5 00:44:17 2003 @@ -68,6 +68,7 @@ EXPORT_SYMBOL(MCA_bus); #ifdef CONFIG_DISCONTIGMEM EXPORT_SYMBOL(node_data); +EXPORT_SYMBOL(physnode_map); #endif #ifdef CONFIG_X86_NUMAQ EXPORT_SYMBOL(xquad_portio); diff -Nru a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c --- a/arch/i386/kernel/i387.c Mon Dec 2 12:31:00 2002 +++ b/arch/i386/kernel/i387.c Mon Mar 10 10:20:30 2003 @@ -52,29 +52,13 @@ * FPU lazy state save handling. */ -static inline void __save_init_fpu( struct task_struct *tsk ) -{ - if ( cpu_has_fxsr ) { - asm volatile( "fxsave %0 ; fnclex" - : "=m" (tsk->thread.i387.fxsave) ); - } else { - asm volatile( "fnsave %0 ; fwait" - : "=m" (tsk->thread.i387.fsave) ); - } - clear_tsk_thread_flag(tsk, TIF_USEDFPU); -} - -void save_init_fpu( struct task_struct *tsk ) -{ - __save_init_fpu(tsk); - stts(); -} - void kernel_fpu_begin(void) { + struct thread_info *thread = current_thread_info(); + preempt_disable(); - if (test_thread_flag(TIF_USEDFPU)) { - __save_init_fpu(current); + if (thread->status & TS_USEDFPU) { + __save_init_fpu(thread->task); return; } clts(); diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Sun Mar 2 18:13:32 2003 +++ b/arch/i386/kernel/io_apic.c Sat Mar 8 14:50:47 2003 @@ -221,8 +221,9 @@ # define Dprintk(x...) # endif -extern unsigned long irq_affinity [NR_IRQS]; -int __cacheline_aligned pending_irq_balance_apicid [NR_IRQS]; +extern unsigned long irq_affinity[NR_IRQS]; + +static int __cacheline_aligned pending_irq_balance_apicid[NR_IRQS]; static int irqbalance_disabled = NO_BALANCE_IRQ; static int physical_balance = 0; @@ -251,8 +252,54 @@ #define BALANCED_IRQ_LESS_DELTA (HZ) long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL; - -static inline void balance_irq(int cpu, int irq); + +static unsigned long move(int curr_cpu, unsigned long allowed_mask, + unsigned long now, int direction) +{ + int search_idle = 1; + int cpu = curr_cpu; + + goto inside; + + do { + if (unlikely(cpu == curr_cpu)) + search_idle = 0; +inside: + if (direction == 1) { + cpu++; + if (cpu >= NR_CPUS) + cpu = 0; + } else { + cpu--; + if (cpu == -1) + cpu = NR_CPUS-1; + } + } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) || + (search_idle && !IDLE_ENOUGH(cpu,now))); + + return cpu; +} + +static inline void balance_irq(int cpu, int irq) +{ + unsigned long now = jiffies; + unsigned long allowed_mask; + unsigned int new_cpu; + + if (irqbalance_disabled) + return; + + allowed_mask = cpu_online_map & irq_affinity[irq]; + new_cpu = move(cpu, allowed_mask, now, 1); + if (cpu != new_cpu) { + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + pending_irq_balance_apicid[irq]=cpu_to_logical_apicid(new_cpu); + spin_unlock_irqrestore(&desc->lock, flags); + } +} static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold) { @@ -263,7 +310,8 @@ if (!irq_desc[j].action) continue; /* Is it a significant load ? */ - if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < useful_load_threshold) + if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < + useful_load_threshold) continue; balance_irq(i, j); } @@ -430,7 +478,8 @@ * We seek the least loaded sibling by making the comparison * (A+B)/2 vs B */ - if (physical_balance && (CPU_IRQ(min_loaded) >> 1) > CPU_IRQ(cpu_sibling_map[min_loaded])) + if (physical_balance && (CPU_IRQ(min_loaded) >> 1) > + CPU_IRQ(cpu_sibling_map[min_loaded])) min_loaded = cpu_sibling_map[min_loaded]; allowed_mask = cpu_online_map & irq_affinity[selected_irq]; @@ -438,11 +487,15 @@ if (target_cpu_mask & allowed_mask) { irq_desc_t *desc = irq_desc + selected_irq; - Dprintk("irq = %d moved to cpu = %d\n", selected_irq, min_loaded); + unsigned long flags; + + Dprintk("irq = %d moved to cpu = %d\n", + selected_irq, min_loaded); /* mark for change destination */ - spin_lock(&desc->lock); - pending_irq_balance_apicid[selected_irq] = cpu_to_logical_apicid(min_loaded); - spin_unlock(&desc->lock); + spin_lock_irqsave(&desc->lock, flags); + pending_irq_balance_apicid[selected_irq] = + cpu_to_logical_apicid(min_loaded); + spin_unlock_irqrestore(&desc->lock, flags); /* Since we made a change, come back sooner to * check for more variation. */ @@ -453,58 +506,16 @@ goto tryanotherirq; not_worth_the_effort: - /* if we did not find an IRQ to move, then adjust the time interval upward */ + /* + * if we did not find an IRQ to move, then adjust the time interval + * upward + */ balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL, balanced_irq_interval + BALANCED_IRQ_MORE_DELTA); Dprintk("IRQ worth rotating not found\n"); return; } -static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction) -{ - int search_idle = 1; - int cpu = curr_cpu; - - goto inside; - - do { - if (unlikely(cpu == curr_cpu)) - search_idle = 0; -inside: - if (direction == 1) { - cpu++; - if (cpu >= NR_CPUS) - cpu = 0; - } else { - cpu--; - if (cpu == -1) - cpu = NR_CPUS-1; - } - } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) || - (search_idle && !IDLE_ENOUGH(cpu,now))); - - return cpu; -} - -static inline void balance_irq (int cpu, int irq) -{ - unsigned long now = jiffies; - unsigned long allowed_mask; - unsigned int new_cpu; - - if (irqbalance_disabled) - return; - - allowed_mask = cpu_online_map & irq_affinity[irq]; - new_cpu = move(cpu, allowed_mask, now, 1); - if (cpu != new_cpu) { - irq_desc_t *desc = irq_desc + irq; - spin_lock(&desc->lock); - pending_irq_balance_apicid[irq] = cpu_to_logical_apicid(new_cpu); - spin_unlock(&desc->lock); - } -} - int balanced_irq(void *unused) { int i; @@ -516,26 +527,32 @@ /* push everything to CPU 0 to give us a starting point. */ for (i = 0 ; i < NR_IRQS ; i++) pending_irq_balance_apicid[i] = cpu_to_logical_apicid(0); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - time_remaining = schedule_timeout(time_remaining); - if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) { - Dprintk("balanced_irq: calling do_irq_balance() %lu\n", jiffies); - do_irq_balance(); - prev_balance_time = jiffies; - time_remaining = balanced_irq_interval; - } - } + +repeat: + set_current_state(TASK_INTERRUPTIBLE); + time_remaining = schedule_timeout(time_remaining); + if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) { + Dprintk("balanced_irq: calling do_irq_balance() %lu\n", + jiffies); + do_irq_balance(); + prev_balance_time = jiffies; + time_remaining = balanced_irq_interval; + } + goto repeat; } static int __init balanced_irq_init(void) { int i; struct cpuinfo_x86 *c; + c = &boot_cpu_data; if (irqbalance_disabled) return 0; - /* Enable physical balance only if more than 1 physical processor is present */ + /* + * Enable physical balance only if more than 1 physical processor + * is present + */ if (smp_num_siblings > 1 && cpu_online_map >> 2) physical_balance = 1; @@ -1150,11 +1167,8 @@ enable_8259A_irq(0); } -void __init UNEXPECTED_IO_APIC(void) +static inline void UNEXPECTED_IO_APIC(void) { - printk(KERN_WARNING "INFO: unexpected IO-APIC, please file a report at\n"); - printk(KERN_WARNING " http://bugzilla.kernel.org\n"); - printk(KERN_WARNING " if your kernel is less than 3 months old.\n"); } void __init print_IO_APIC(void) @@ -1566,7 +1580,7 @@ */ static int __init timer_irq_works(void) { - unsigned int t1 = jiffies; + unsigned long t1 = jiffies; local_irq_enable(); /* Let ten ticks pass... */ diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c Tue Feb 25 01:38:22 2003 +++ b/arch/i386/kernel/irq.c Sat Mar 8 14:50:44 2003 @@ -135,43 +135,47 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_printf(p, " "); for (j=0; jtypename); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "NMI: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) - p += seq_printf(p, "%10u ", nmi_count(j)); + seq_printf(p, "%10u ", nmi_count(j)); seq_putc(p, '\n'); #if CONFIG_X86_LOCAL_APIC seq_printf(p, "LOC: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) - p += seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs); + seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs); seq_putc(p, '\n'); #endif seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); diff -Nru a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c --- a/arch/i386/kernel/numaq.c Fri Feb 28 00:05:34 2003 +++ b/arch/i386/kernel/numaq.c Tue Mar 4 23:41:55 2003 @@ -31,8 +31,7 @@ #include /* These are needed before the pgdat's are created */ -unsigned long node_start_pfn[MAX_NUMNODES]; -unsigned long node_end_pfn[MAX_NUMNODES]; +extern long node_start_pfn[], node_end_pfn[]; #define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT)) @@ -64,26 +63,6 @@ } } } - -/* - * ----------------------------------------- - * - * functions related to physnode_map - * - * ----------------------------------------- - */ -/* - * physnode_map keeps track of the physical memory layout of the - * numaq nodes on a 256Mb break (each element of the array will - * represent 256Mb of memory and will be marked by the node id. so, - * if the first gig is on node 0, and the second gig is on node 1 - * physnode_map will contain: - * physnode_map[0-3] = 0; - * physnode_map[4-7] = 1; - * physnode_map[8- ] = -1; - */ -int physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1}; -EXPORT_SYMBOL(physnode_map); /* * for each node mark the regions diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Thu Feb 20 20:33:52 2003 +++ b/arch/i386/kernel/process.c Mon Mar 10 10:20:30 2003 @@ -275,6 +275,15 @@ release_x86_irqs(dead_task); } +/* + * This gets called before we allocate a new thread and copy + * the current task into it. + */ +void prepare_to_copy(struct task_struct *tsk) +{ + unlazy_fpu(tsk); +} + int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, unsigned long unused, struct task_struct * p, struct pt_regs * regs) @@ -297,9 +306,6 @@ savesegment(gs,p->thread.gs); tsk = current; - unlazy_fpu(tsk); - struct_cpy(&p->thread.i387, &tsk->thread.i387); - if (unlikely(NULL != tsk->thread.ts_io_bitmap)) { p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); if (!p->thread.ts_io_bitmap) diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Tue Feb 25 10:47:22 2003 +++ b/arch/i386/kernel/smpboot.c Tue Mar 4 23:41:54 2003 @@ -966,6 +966,7 @@ if (APIC_init_uniprocessor()) printk(KERN_NOTICE "Local APIC not detected." " Using dummy APIC emulation.\n"); + map_cpu_to_logical_apicid(); return; } diff -Nru a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c --- a/arch/i386/kernel/srat.c Mon Feb 24 23:13:14 2003 +++ b/arch/i386/kernel/srat.c Wed Mar 5 00:44:17 2003 @@ -57,8 +57,7 @@ static int zholes_size_init; static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES]; -unsigned long node_start_pfn[MAX_NUMNODES]; -unsigned long node_end_pfn[MAX_NUMNODES]; +extern unsigned long node_start_pfn[], node_end_pfn[]; extern void * boot_ioremap(unsigned long, unsigned long); @@ -182,30 +181,19 @@ } } -/* - * physnode_map keeps track of the physical memory layout of the - * numaq nodes on a 256Mb break (each element of the array will - * represent 256Mb of memory and will be marked by the node id. so, - * if the first gig is on node 0, and the second gig is on node 1 - * physnode_map will contain: - * physnode_map[0-3] = 0; - * physnode_map[4-7] = 1; - * physnode_map[8- ] = -1; - */ -int pfnnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1}; -EXPORT_SYMBOL(pfnnode_map); - -static void __init initialize_pfnnode_map(void) +static void __init initialize_physnode_map(void) { - unsigned long topofchunk, cur = 0; int i; - - for (i = 0; i < num_memory_chunks; i++) { - cur = node_memory_chunk[i].start_pfn; - topofchunk = node_memory_chunk[i].end_pfn; - while (cur < topofchunk) { - pfnnode_map[PFN_TO_ELEMENT(cur)] = node_memory_chunk[i].nid; - cur ++; + unsigned long pfn; + struct node_memory_chunk_s *nmcp; + + /* Run the list of memory chunks and fill in the phymap. */ + nmcp = node_memory_chunk; + for (i = num_memory_chunks; --i >= 0; nmcp++) { + for (pfn = nmcp->start_pfn; pfn <= nmcp->end_pfn; + pfn += PAGES_PER_ELEMENT) + { + physnode_map[pfn / PAGES_PER_ELEMENT] = (int)nmcp->nid; } } } @@ -272,7 +260,7 @@ for (i = 0; i < num_memory_chunks; i++) node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm]; - initialize_pfnnode_map(); + initialize_physnode_map(); printk("pxm bitmap: "); for (i = 0; i < sizeof(pxm_bitmap); i++) { diff -Nru a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c --- a/arch/i386/kernel/sysenter.c Sun Mar 2 18:13:32 2003 +++ b/arch/i386/kernel/sysenter.c Mon Mar 10 14:41:23 2003 @@ -40,8 +40,10 @@ int cpu = get_cpu(); struct tss_struct *tss = init_tss + cpu; + tss->ss1 = __KERNEL_CS; + tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss; wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); - wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp0, 0); + wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0); wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0); printk("Enabling SEP on CPU %d\n", cpu); diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Fri Feb 21 17:44:10 2003 +++ b/arch/i386/kernel/traps.c Mon Mar 10 10:20:30 2003 @@ -737,13 +737,14 @@ */ asmlinkage void math_state_restore(struct pt_regs regs) { - struct task_struct *tsk = current; - clts(); /* Allow maths ops (or we recurse) */ + struct thread_info *thread = current_thread_info(); + struct task_struct *tsk = thread->task; + clts(); /* Allow maths ops (or we recurse) */ if (!tsk->used_math) init_fpu(tsk); restore_fpu(tsk); - set_thread_flag(TIF_USEDFPU); /* So we fnsave on switch_to() */ + thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ } #ifndef CONFIG_MATH_EMULATION diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c --- a/arch/i386/kernel/vm86.c Sat Feb 15 19:30:17 2003 +++ b/arch/i386/kernel/vm86.c Sun Mar 9 18:49:37 2003 @@ -291,7 +291,7 @@ tss = init_tss + smp_processor_id(); tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; - disable_sysenter(); + disable_sysenter(tss); tsk->thread.screen_bitmap = info->screen_bitmap; if (info->flags & VM86_SCREEN_BITMAP) diff -Nru a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c --- a/arch/i386/mm/discontig.c Fri Feb 28 15:08:58 2003 +++ b/arch/i386/mm/discontig.c Tue Mar 4 23:41:55 2003 @@ -36,11 +36,36 @@ struct pglist_data *node_data[MAX_NUMNODES]; bootmem_data_t node0_bdata; +/* + * numa interface - we expect the numa architecture specfic code to have + * populated the following initialisation. + * + * 1) numnodes - the total number of nodes configured in the system + * 2) physnode_map - the mapping between a pfn and owning node + * 3) node_start_pfn - the starting page frame number for a node + * 3) node_end_pfn - the ending page fram number for a node + */ + +/* + * physnode_map keeps track of the physical memory layout of a generic + * numa node on a 256Mb break (each element of the array will + * represent 256Mb of memory and will be marked by the node id. so, + * if the first gig is on node 0, and the second gig is on node 1 + * physnode_map will contain: + * + * physnode_map[0-3] = 0; + * physnode_map[4-7] = 1; + * physnode_map[8- ] = -1; + */ +u8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1}; + +unsigned long node_start_pfn[MAX_NUMNODES]; +unsigned long node_end_pfn[MAX_NUMNODES]; + extern unsigned long find_max_low_pfn(void); extern void find_max_pfn(void); extern void one_highpage_init(struct page *, int, int); -extern unsigned long node_start_pfn[], node_end_pfn[]; extern struct e820map e820; extern char _end; extern unsigned long highend_pfn, highstart_pfn; @@ -55,6 +80,36 @@ unsigned long node_remap_offset[MAX_NUMNODES]; void *node_remap_start_vaddr[MAX_NUMNODES]; void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); + +/* + * FLAT - support for basic PC memory model with discontig enabled, essentially + * a single node with all available processors in it with a flat + * memory map. + */ +void __init get_memcfg_numa_flat(void) +{ + int pfn; + + printk("NUMA - single node, flat memory mode\n"); + + /* Run the memory configuration and find the top of memory. */ + find_max_pfn(); + node_start_pfn[0] = 0; + node_end_pfn[0] = max_pfn; + + /* Fill in the physnode_map with our simplistic memory model, + * all memory is in node 0. + */ + for (pfn = node_start_pfn[0]; pfn <= node_end_pfn[0]; + pfn += PAGES_PER_ELEMENT) + { + physnode_map[pfn / PAGES_PER_ELEMENT] = 0; + } + + /* Indicate there is one node available. */ + node_set_online(0); + numnodes = 1; +} /* * Find the highest page frame number we have available for the node diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Fri Jan 10 19:29:47 2003 +++ b/arch/i386/mm/fault.c Thu Mar 6 08:19:03 2003 @@ -394,14 +394,14 @@ * Do _not_ use "tsk" here. We might be inside * an interrupt in the middle of a task switch.. */ - int offset = __pgd_offset(address); + int index = pgd_index(address); pgd_t *pgd, *pgd_k; pmd_t *pmd, *pmd_k; pte_t *pte_k; asm("movl %%cr3,%0":"=r" (pgd)); - pgd = offset + (pgd_t *)__va(pgd); - pgd_k = init_mm.pgd + offset; + pgd = index + (pgd_t *)__va(pgd); + pgd_k = init_mm.pgd + index; if (!pgd_present(*pgd_k)) goto no_context; diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c --- a/arch/i386/mm/init.c Mon Feb 3 23:46:49 2003 +++ b/arch/i386/mm/init.c Thu Mar 6 08:19:07 2003 @@ -98,26 +98,26 @@ { pgd_t *pgd; pmd_t *pmd; - int pgd_ofs, pmd_ofs; + int pgd_idx, pmd_idx; unsigned long vaddr; vaddr = start; - pgd_ofs = __pgd_offset(vaddr); - pmd_ofs = __pmd_offset(vaddr); - pgd = pgd_base + pgd_ofs; + pgd_idx = pgd_index(vaddr); + pmd_idx = pmd_index(vaddr); + pgd = pgd_base + pgd_idx; - for ( ; (pgd_ofs < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_ofs++) { + for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) { if (pgd_none(*pgd)) one_md_table_init(pgd); pmd = pmd_offset(pgd, vaddr); - for (; (pmd_ofs < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_ofs++) { + for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) { if (pmd_none(*pmd)) one_page_table_init(pmd); vaddr += PMD_SIZE; } - pmd_ofs = 0; + pmd_idx = 0; } } @@ -132,17 +132,17 @@ pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int pgd_ofs, pmd_ofs, pte_ofs; + int pgd_idx, pmd_idx, pte_ofs; - pgd_ofs = __pgd_offset(PAGE_OFFSET); - pgd = pgd_base + pgd_ofs; + pgd_idx = pgd_index(PAGE_OFFSET); + pgd = pgd_base + pgd_idx; pfn = 0; - for (; pgd_ofs < PTRS_PER_PGD; pgd++, pgd_ofs++) { + for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) { pmd = one_md_table_init(pgd); if (pfn >= max_low_pfn) continue; - for (pmd_ofs = 0; pmd_ofs < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_ofs++) { + for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) { /* Map with big pages if possible, otherwise create normal page tables. */ if (cpu_has_pse) { set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE)); @@ -214,7 +214,7 @@ vaddr = PKMAP_BASE; page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); - pgd = swapper_pg_dir + __pgd_offset(vaddr); + pgd = swapper_pg_dir + pgd_index(vaddr); pmd = pmd_offset(pgd, vaddr); pte = pte_offset_kernel(pmd, vaddr); pkmap_page_table = pte; diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c --- a/arch/i386/mm/ioremap.c Mon Feb 24 23:13:24 2003 +++ b/arch/i386/mm/ioremap.c Thu Mar 6 06:34:47 2003 @@ -148,7 +148,7 @@ */ offset = phys_addr & ~PAGE_MASK; phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr) - phys_addr; + size = PAGE_ALIGN(last_addr+1) - phys_addr; /* * Ok, go for it.. diff -Nru a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c --- a/arch/i386/mm/pgtable.c Sun Mar 2 18:14:31 2003 +++ b/arch/i386/mm/pgtable.c Thu Mar 6 08:19:03 2003 @@ -64,7 +64,7 @@ pmd_t *pmd; pte_t *pte; - pgd = swapper_pg_dir + __pgd_offset(vaddr); + pgd = swapper_pg_dir + pgd_index(vaddr); if (pgd_none(*pgd)) { BUG(); return; @@ -104,7 +104,7 @@ printk ("set_pmd_pfn: pfn misaligned\n"); return; /* BUG(); */ } - pgd = swapper_pg_dir + __pgd_offset(vaddr); + pgd = swapper_pg_dir + pgd_index(vaddr); if (pgd_none(*pgd)) { printk ("set_pmd_pfn: pgd_none\n"); return; /* BUG(); */ diff -Nru a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c --- a/arch/i386/oprofile/nmi_int.c Sun Mar 2 18:13:32 2003 +++ b/arch/i386/oprofile/nmi_int.c Wed Mar 5 11:46:56 2003 @@ -58,7 +58,7 @@ unsigned int const nr_ctrls = model->num_controls; struct op_msr_group * counters = &msrs->counters; struct op_msr_group * controls = &msrs->controls; - int i; + unsigned int i; for (i = 0; i < nr_ctrs; ++i) { rdmsr(counters->addrs[i], @@ -108,7 +108,7 @@ unsigned int const nr_ctrls = model->num_controls; struct op_msr_group * counters = &msrs->counters; struct op_msr_group * controls = &msrs->controls; - int i; + unsigned int i; for (i = 0; i < nr_ctrls; ++i) { wrmsr(controls->addrs[i], @@ -182,7 +182,7 @@ static int nmi_create_files(struct super_block * sb, struct dentry * root) { - int i; + unsigned int i; for (i = 0; i < model->num_counters; ++i) { struct dentry * dir; diff -Nru a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c --- a/arch/i386/oprofile/op_model_athlon.c Thu Jan 23 12:24:53 2003 +++ b/arch/i386/oprofile/op_model_athlon.c Sun Mar 9 05:09:00 2003 @@ -104,10 +104,11 @@ if (CTR_OVERFLOWED(low)) { oprofile_add_sample(eip, is_kernel, i, cpu); CTR_WRITE(reset_value[i], msrs, i); - return 1; } } - return 0; + + /* See op_model_ppro.c */ + return 1; } diff -Nru a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c --- a/arch/i386/oprofile/op_model_p4.c Thu Jan 30 19:57:28 2003 +++ b/arch/i386/oprofile/op_model_p4.c Sun Mar 9 05:08:41 2003 @@ -389,7 +389,7 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs) { - int i; + unsigned int i; unsigned int addr, stag; setup_num_counters(); @@ -608,13 +608,14 @@ CTR_WRITE(reset_value[i], real); /* P4 quirk: you have to re-unmask the apic vector */ apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); - return 1; } } /* P4 quirk: you have to re-unmask the apic vector */ apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); - return 0; + + /* See op_model_ppro.c */ + return 1; } diff -Nru a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c --- a/arch/i386/oprofile/op_model_ppro.c Thu Jan 23 12:24:53 2003 +++ b/arch/i386/oprofile/op_model_ppro.c Sun Mar 9 06:15:07 2003 @@ -98,10 +98,17 @@ if (CTR_OVERFLOWED(low)) { oprofile_add_sample(eip, is_kernel, i, cpu); CTR_WRITE(reset_value[i], msrs, i); - return 1; } } - return 0; + + /* We can't work out if we really handled an interrupt. We + * might have caught a *second* counter just after overflowing + * the interrupt for this counter then arrives + * and we don't find a counter that's overflowed, so we + * would return 0 and get dazed + confused. Instead we always + * assume we found an overflow. This sucks. + */ + return 1; } diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c --- a/arch/i386/pci/irq.c Mon Oct 7 07:36:47 2002 +++ b/arch/i386/pci/irq.c Fri Mar 7 19:36:28 2003 @@ -804,6 +804,7 @@ int pirq_enable_irq(struct pci_dev *dev) { u8 pin; + extern int interrupt_line_quirk; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { char *msg; @@ -813,9 +814,17 @@ msg = ""; else msg = " Please try using pci=biosirq."; + + /* With IDE legacy devices the IRQ lookup failure is not a problem.. */ + if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5)) + return 0; + printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 'A' + pin - 1, dev->slot_name, msg); } - + /* VIA bridges use interrupt line for apic/pci steering across + the V-Link */ + else if (interrupt_line_quirk) + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); return 0; } diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S --- a/arch/i386/vmlinux.lds.S Tue Feb 18 18:58:52 2003 +++ b/arch/i386/vmlinux.lds.S Sun Feb 16 15:55:23 2003 @@ -74,6 +74,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Sun Feb 9 17:29:49 2003 +++ b/arch/ia64/Kconfig Sat Mar 8 14:50:37 2003 @@ -22,11 +22,7 @@ bool default y -config SWAP - bool - default y - -config RWSEM_GENERIC_SPINLOCK +config RWSEM_XCHGADD_ALGORITHM bool default y @@ -424,6 +420,18 @@ If you don't know what to do here, say N. +config PREEMPT + bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + + Say Y here if you are building a kernel for a desktop, embedded + or real-time system. Say N if you are unsure. + config IA32_SUPPORT bool "Support running of Linux/x86 binaries" help @@ -874,6 +882,12 @@ and certain other kinds of spinlock errors commonly made. This is best used in conjunction with the NMI watchdog so that spinlock deadlocks are also debuggable. + +config DEBUG_SPINLOCK_SLEEP + bool "Sleep-inside-spinlock checking" + help + If you say Y here, various routines which may sleep will become very + noisy if they are called with a spinlock held. config IA64_DEBUG_CMPXCHG bool "Turn on compare-and-exchange bug checking (slow!)" diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Thu Feb 6 22:47:17 2003 +++ b/arch/ia64/Makefile Mon Feb 24 05:40:16 2003 @@ -52,18 +52,19 @@ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/kernel/ \ arch/ia64/sn/io/ \ + arch/ia64/sn/io/sn2/ \ + arch/ia64/sn/io/sn2/pcibr/ \ arch/ia64/sn/kernel/sn2/ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/fakeprom/ boot := arch/ia64/boot tools := arch/ia64/tools .PHONY: boot compressed include/asm-ia64/offsets.h -all: vmlinux +all: prepare vmlinux compressed: vmlinux.gz diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c --- a/arch/ia64/hp/sim/simscsi.c Tue Feb 4 17:06:04 2003 +++ b/arch/ia64/hp/sim/simscsi.c Wed Feb 12 00:11:32 2003 @@ -156,7 +156,7 @@ if (sc->request_bufflen < req.len) return; - stat.fd = desc[sc->target]; + stat.fd = desc[sc->device->id]; if (DBG) printk("simscsi_%s @ %lx (off %lx)\n", mode == SSC_READ ? "read":"write", req.addr, offset); @@ -178,7 +178,7 @@ struct disk_stat stat; struct disk_req req; - stat.fd = desc[sc->target]; + stat.fd = desc[sc->device->id]; while (list_len) { req.addr = __pa(page_address(sl->page) + sl->offset); @@ -259,6 +259,7 @@ int simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) { + unsigned int target_id = sc->device->id; char fname[MAX_ROOT_LEN+16]; size_t disk_size; char *buf; @@ -267,21 +268,21 @@ if (DBG) printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n", - sc->target, sc->cmnd[0], sc->serial_number, sp, done); + target_id, sc->cmnd[0], sc->serial_number, sp, done); #endif sc->result = DID_BAD_TARGET << 16; sc->scsi_done = done; - if (sc->target <= 15 && sc->lun == 0) { + if (target_id <= 15 && sc->device->lun == 0) { switch (sc->cmnd[0]) { case INQUIRY: if (sc->request_bufflen < 35) { break; } - sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target); - desc[sc->target] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS, - 0, 0, SSC_OPEN); - if (desc[sc->target] < 0) { + sprintf (fname, "%s%c", simscsi_root, 'a' + target_id); + desc[target_id] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS, + 0, 0, SSC_OPEN); + if (desc[target_id] < 0) { /* disk doesn't exist... */ break; } @@ -303,37 +304,37 @@ break; case READ_6: - if (desc[sc->target] < 0 ) + if (desc[target_id] < 0 ) break; simscsi_readwrite6(sc, SSC_READ); break; case READ_10: - if (desc[sc->target] < 0 ) + if (desc[target_id] < 0 ) break; simscsi_readwrite10(sc, SSC_READ); break; case WRITE_6: - if (desc[sc->target] < 0) + if (desc[target_id] < 0) break; simscsi_readwrite6(sc, SSC_WRITE); break; case WRITE_10: - if (desc[sc->target] < 0) + if (desc[target_id] < 0) break; simscsi_readwrite10(sc, SSC_WRITE); break; case READ_CAPACITY: - if (desc[sc->target] < 0 || sc->request_bufflen < 8) { + if (desc[target_id] < 0 || sc->request_bufflen < 8) { break; } buf = sc->request_buffer; - disk_size = simscsi_get_disk_size(desc[sc->target]); + disk_size = simscsi_get_disk_size(desc[target_id]); /* pretend to be a 1GB disk (partition table contains real stuff): */ buf[0] = (disk_size >> 24) & 0xff; diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c --- a/arch/ia64/hp/sim/simserial.c Tue Feb 4 17:06:04 2003 +++ b/arch/ia64/hp/sim/simserial.c Thu Feb 13 05:43:47 2003 @@ -63,7 +63,6 @@ static char *serial_name = "SimSerial driver"; static char *serial_version = "0.6"; -static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED; /* * This has been extracted from asm/serial.h. We need one eventually but @@ -235,14 +234,14 @@ if (!tty || !info->xmit.buf) return; - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) { - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return; } info->xmit.buf[info->xmit.head] = ch; info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); } static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) @@ -250,7 +249,8 @@ int count; unsigned long flags; - spin_lock_irqsave(&serial_lock, flags); + + local_irq_save(flags); if (info->x_char) { char c = info->x_char; @@ -293,7 +293,7 @@ info->xmit.tail += count; } out: - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); } static void rs_flush_chars(struct tty_struct *tty) @@ -334,7 +334,7 @@ break; } - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); { c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); @@ -344,7 +344,7 @@ info->xmit.head = ((info->xmit.head + c) & (SERIAL_XMIT_SIZE-1)); } - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); buf += c; count -= c; @@ -352,7 +352,7 @@ } up(&tmp_buf_sem); } else { - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); while (1) { c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); if (count < c) @@ -367,7 +367,7 @@ count -= c; ret += c; } - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); } /* * Hey, we transmit directly from here in our case @@ -398,9 +398,9 @@ struct async_struct *info = (struct async_struct *)tty->driver_data; unsigned long flags; - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); info->xmit.head = info->xmit.tail = 0; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); wake_up_interruptible(&tty->write_wait); @@ -573,7 +573,7 @@ state->irq); #endif - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); { /* * First unlink the serial port from the IRQ chain... @@ -611,7 +611,7 @@ info->flags &= ~ASYNC_INITIALIZED; } - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); } /* @@ -634,13 +634,13 @@ state = info->state; - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); if (tty_hung_up_p(filp)) { #ifdef SIMSERIAL_DEBUG printk("rs_close: hung_up\n"); #endif MOD_DEC_USE_COUNT; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return; } #ifdef SIMSERIAL_DEBUG @@ -665,11 +665,11 @@ } if (state->count) { MOD_DEC_USE_COUNT; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return; } info->flags |= ASYNC_CLOSING; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); /* * Now we wait for the transmit buffer to clear; and we notify @@ -776,7 +776,7 @@ if (!page) return -ENOMEM; - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); if (info->flags & ASYNC_INITIALIZED) { free_page(page); @@ -857,11 +857,11 @@ } info->flags |= ASYNC_INITIALIZED; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return 0; errout: - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return retval; } diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S --- a/arch/ia64/ia32/ia32_entry.S Sun Jan 12 16:07:06 2003 +++ b/arch/ia64/ia32/ia32_entry.S Sat Mar 8 11:30:11 2003 @@ -300,7 +300,7 @@ data8 compat_sys_statfs data8 compat_sys_fstatfs /* 100 */ data8 sys32_ioperm - data8 sys32_socketcall + data8 compat_sys_socketcall data8 sys_syslog data8 compat_sys_setitimer data8 compat_sys_getitimer /* 105 */ @@ -424,6 +424,26 @@ data8 sys_ni_syscall /* reserved for Security */ data8 sys_gettid data8 sys_readahead /* 225 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 230 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 235 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 compat_sys_futex /* 240 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 245 */ data8 sys_ni_syscall data8 sys_ni_syscall data8 sys_ni_syscall diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c --- a/arch/ia64/ia32/ia32_ioctl.c Tue Feb 4 17:06:05 2003 +++ b/arch/ia64/ia32/ia32_ioctl.c Thu Mar 6 11:06:44 2003 @@ -97,11 +97,9 @@ int info; /* [o] auxiliary information */ } sg_io_hdr32_t; /* 64 bytes long (on IA32) */ -struct iovec32 { unsigned int iov_base; int iov_len; }; - static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32) { - struct iovec32 *uiov = (struct iovec32 *) P(uptr32); + struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32); sg_iovec_t *kiov; int i; @@ -136,7 +134,7 @@ static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32) { - struct iovec32 *uiov = (struct iovec32 *) P(uptr32); + struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32); sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; int i; diff -Nru a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c --- a/arch/ia64/ia32/ia32_support.c Fri Jan 17 14:56:29 2003 +++ b/arch/ia64/ia32/ia32_support.c Thu Jan 30 06:14:13 2003 @@ -93,7 +93,7 @@ { unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd; struct pt_regs *regs = ia64_task_regs(t); - int nr = smp_processor_id(); /* LDT and TSS depend on CPU number: */ + int nr = get_cpu(); /* LDT and TSS depend on CPU number: */ eflag = t->thread.eflag; fsr = t->thread.fsr; @@ -119,6 +119,7 @@ regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32) | (__u32) regs->r17; regs->r30 = load_desc(_LDT(nr)); /* LDTD */ + put_cpu(); } /* diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c Tue Feb 18 10:25:13 2003 +++ b/arch/ia64/ia32/sys_ia32.c Sat Mar 8 11:30:11 2003 @@ -924,12 +924,11 @@ (struct compat_timeval *) A(a.tvp)); } -struct iovec32 { unsigned int iov_base; int iov_len; }; asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long); asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long); static struct iovec * -get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type) +get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type) { int i; u32 buf, len; @@ -939,7 +938,7 @@ if (!count) return 0; - if (verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count)) return NULL; if (count > UIO_MAXIOV) return NULL; @@ -971,14 +970,14 @@ } asmlinkage long -sys32_readv (int fd, struct iovec32 *vector, u32 count) +sys32_readv (int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; long ret; mm_segment_t old_fs = get_fs(); - iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE); + iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE); if (!iov) return -EFAULT; set_fs(KERNEL_DS); @@ -990,14 +989,14 @@ } asmlinkage long -sys32_writev (int fd, struct iovec32 *vector, u32 count) +sys32_writev (int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; long ret; mm_segment_t old_fs = get_fs(); - iov = get_iovec32(vector, iovstack, count, VERIFY_READ); + iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ); if (!iov) return -EFAULT; set_fs(KERNEL_DS); @@ -1080,701 +1079,6 @@ } /* - * Declare the IA32 version of the msghdr - */ - -struct msghdr32 { - unsigned int msg_name; /* Socket name */ - int msg_namelen; /* Length of name */ - unsigned int msg_iov; /* Data blocks */ - unsigned int msg_iovlen; /* Number of blocks */ - unsigned int msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ - unsigned int msg_controllen; /* Length of cmsg list */ - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) -#define CMSG32_DATA(cmsg) \ - ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) \ - (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) -#define __CMSG32_FIRSTHDR(ctl,len) \ - ((len) >= sizeof(struct cmsghdr32) ? (struct cmsghdr32 *)(ctl) : (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -static inline struct cmsghdr32 * -__cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len) -{ - struct cmsghdr32 * ptr; - - ptr = (struct cmsghdr32 *)(((unsigned char *) cmsg) + CMSG32_ALIGN(cmsg_len)); - if ((unsigned long)((char*)(ptr+1) - (char *) ctl) > size) - return NULL; - return ptr; -} - -static inline struct cmsghdr32 * -cmsg32_nxthdr (struct msghdr *msg, struct cmsghdr32 *cmsg, int cmsg_len) -{ - return __cmsg32_nxthdr(msg->msg_control, msg->msg_controllen, cmsg, cmsg_len); -} - -static inline int -get_msghdr32 (struct msghdr *mp, struct msghdr32 *mp32) -{ - int ret; - unsigned int i; - - if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32))) - return -EFAULT; - ret = __get_user(i, &mp32->msg_name); - mp->msg_name = (void *)A(i); - ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen); - ret |= __get_user(i, &mp32->msg_iov); - mp->msg_iov = (struct iovec *)A(i); - ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen); - ret |= __get_user(i, &mp32->msg_control); - mp->msg_control = (void *)A(i); - ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen); - ret |= __get_user(mp->msg_flags, &mp32->msg_flags); - return ret ? -EFAULT : 0; -} - -/* - * There is a lot of hair here because the alignment rules (and thus placement) of cmsg - * headers and length are different for 32-bit apps. -DaveM - */ -static int -get_cmsghdr32 (struct msghdr *kmsg, unsigned char *stackbuf, struct sock *sk, size_t *bufsize) -{ - struct cmsghdr *kcmsg, *kcmsg_base; - __kernel_size_t kcmlen, tmp; - compat_size_t ucmlen; - struct cmsghdr32 *ucmsg; - long err; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while (ucmsg != NULL) { - if (get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if (CMSG32_ALIGN(ucmlen) < CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if ((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + ucmlen) - > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if (kcmlen == 0) - return -EINVAL; - - /* - * The kcmlen holds the 64-bit version of the control length. It may not be - * modified as we do not stick it into the kmsg until we have successfully copied - * over all of the data from the user. - */ - if (kcmlen > *bufsize) { - *bufsize = kcmlen; - kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL); - } - if (kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while (ucmsg != NULL) { - err = get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - err |= get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - err |= get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - err |= copy_from_user(CMSG_DATA(kcmsg), CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))); - if (err) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if (kcmsg_base != (struct cmsghdr *)stackbuf) - sock_kfree_s(sk, kcmsg_base, kcmlen); - return -EFAULT; -} - -/* - * Verify & re-shape IA32 iovec. The caller must ensure that the - * iovec is big enough to hold the re-shaped message iovec. - * - * Save time not doing verify_area. copy_*_user will make this work - * in any case. - * - * Don't need to check the total size for overflow (cf net/core/iovec.c), - * 32-bit sizes can't overflow a 64-bit count. - */ - -static inline int -verify_iovec32 (struct msghdr *m, struct iovec *iov, char *address, int mode) -{ - int size, err, ct; - struct iovec32 *iov32; - - if (m->msg_namelen) { - if (mode == VERIFY_READ) { - err = move_addr_to_kernel(m->msg_name, m->msg_namelen, address); - if (err < 0) - goto out; - } - m->msg_name = address; - } else - m->msg_name = NULL; - - err = -EFAULT; - size = m->msg_iovlen * sizeof(struct iovec32); - if (copy_from_user(iov, m->msg_iov, size)) - goto out; - m->msg_iov = iov; - - err = 0; - iov32 = (struct iovec32 *)iov; - for (ct = m->msg_iovlen; ct-- > 0; ) { - iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len; - iov[ct].iov_base = (void *) A(iov32[ct].iov_base); - err += iov[ct].iov_len; - } -out: - return err; -} - -static void -put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, - cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void -scm_detach_fds32 (struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) - / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); - i < fdmax; - i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - current->files->fd[new_fd] = fp[i]; - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* - * In these cases we (currently) can just copy to data over verbatim because all CMSGs - * created by the kernel have well defined types which have the same layout in both the - * 32-bit and 64-bit API. One must add some special cased conversions here if we start - * sending control messages with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void -cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - long err; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if (workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while (((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* - * UCMSG is the 64-bit format CMSG entry in user-space. KCMSG32 is within - * the kernel space temporary buffer we use to convert into a 32-bit style - * CMSG. - */ - err = get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - err |= get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - err |= get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - if (err) - goto fail2; - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - if (copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz)) - goto fail2; - - kmsg->msg_control = (struct cmsghdr *) (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - kfree(workbuf); - return; - - fail2: - kfree(workbuf); - fail: - /* - * If we leave the 64-bit format CMSG chunks in there, the application could get - * confused and crash. So to ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ -/* - * BSD sendmsg interface - */ - -int -sys32_sendmsg (int fd, struct msghdr32 *msg, unsigned flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, iov_size, total_len; - size_t ctl_len; - - err = -EFAULT; - if (get_msghdr32(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - if (msg_sys.msg_controllen) { - ctl_len = sizeof(ctl); - err = get_cmsghdr32(&msg_sys, ctl_buf, sock->sk, &ctl_len); - if (err) - goto out_freeiov; - ctl_buf = msg_sys.msg_control; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -/* - * BSD recvmsg interface - */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; - - err = -EFAULT; - if (get_msghdr32(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; - - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; - - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - - /* XXX This code needs massive updating... -DaveM */ - lock_kernel(); - { - struct sock_iocb *si; - struct kiocb iocb; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &msg_sys; - si->size = total_len; - si->flags = flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &msg_sys, total_len, - flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if (err < 0) - goto out_unlock_freeiov; - - len = err; - if (!msg_sys.msg_control) { - if (sock->passcred || si->scm->fp) - msg_sys.msg_flags |= MSG_CTRUNC; - if (si->scm->fp) - __scm_destroy(si->scm); - } else { - /* - * If recvmsg processing itself placed some control messages into - * user space, it's is using 64-bit CMSG processing, so we need to - * fix it up before we tack on more stuff. - */ - if ((unsigned long) msg_sys.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr); - - /* Wheee... */ - if (sock->passcred) - put_cmsg32(&msg_sys, SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if (si->scm->fp != NULL) - scm_detach_fds32(&msg_sys, si->scm); - } - } - unlock_kernel(); - - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, - &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - - out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); - out_put: - sockfd_put(sock); - out: - return err; - - out_unlock_freeiov: - goto out_freeiov; -} - -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static const unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, - int addrlen); -extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, - int *upeer_addrlen); -extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags); -extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len, - unsigned flags, u32 addr, int addr_len); -extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags); -extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size, - unsigned flags, u32 addr, u32 addr_len); -extern asmlinkage long sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - u32 optval, u32 optlen); - -extern asmlinkage long sys_socket(int family, int type, int protocol); -extern asmlinkage long sys_socketpair(int family, int type, int protocol, - int usockvec[2]); -extern asmlinkage long sys_shutdown(int fd, int how); -extern asmlinkage long sys_listen(int fd, int backlog); - -asmlinkage long -sys32_socketcall (int call, u32 *args) -{ - int ret; - u32 a[6]; - u32 a0,a1; - - if (callSYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nas[call])) - return -EFAULT; - a0=a[0]; - a1=a[1]; - - switch(call) - { - case SYS_SOCKET: - ret = sys_socket(a0, a1, a[2]); - break; - case SYS_BIND: - ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_CONNECT: - ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_LISTEN: - ret = sys_listen(a0, a1); - break; - case SYS_ACCEPT: - ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - break; - case SYS_GETSOCKNAME: - ret = sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - break; - case SYS_GETPEERNAME: - ret = sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - break; - case SYS_SOCKETPAIR: - ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3])); - break; - case SYS_SEND: - ret = sys_send(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_SENDTO: - ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_RECV: - ret = sys_recv(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_RECVFROM: - ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_SHUTDOWN: - ret = sys_shutdown(a0,a1); - break; - case SYS_SETSOCKOPT: - ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]), - a[4]); - break; - case SYS_GETSOCKOPT: - ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]); - break; - case SYS_SENDMSG: - ret = sys32_sendmsg(a0, (struct msghdr32 *) A(a1), a[2]); - break; - case SYS_RECVMSG: - ret = sys32_recvmsg(a0, (struct msghdr32 *) A(a1), a[2]); - break; - default: - ret = EINVAL; - break; - } - return ret; -} - -/* * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. * * This is really horribly ugly. @@ -3151,6 +2455,7 @@ asmlinkage long sys32_sysctl (struct sysctl32 *args) { +#ifdef CONFIG_SYSCTL struct sysctl32 a32; mm_segment_t old_fs = get_fs (); void *oldvalp, *newvalp; @@ -3188,6 +2493,9 @@ return -EFAULT; return ret; +#else + return -ENOSYS; +#endif } asmlinkage long @@ -3433,8 +2741,12 @@ u32 bufferram; u32 totalswap; u32 freeswap; - unsigned short procs; - char _f[22]; + u16 procs; + u16 pad; + u32 totalhigh; + u32 freehigh; + u32 mem_unit; + char _f[8]; }; asmlinkage long @@ -3463,6 +2775,9 @@ err |= __put_user(s.totalswap, &info->totalswap); err |= __put_user(s.freeswap, &info->freeswap); err |= __put_user(s.procs, &info->procs); + err |= __put_user (s.totalhigh, &info->totalhigh); + err |= __put_user (s.freehigh, &info->freehigh); + err |= __put_user (s.mem_unit, &info->mem_unit); if (err) return -EFAULT; return ret; diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Tue Feb 4 17:06:06 2003 +++ b/arch/ia64/kernel/acpi.c Thu Mar 6 22:21:39 2003 @@ -55,6 +55,7 @@ asm (".weak iosapic_override_isa_irq"); asm (".weak iosapic_register_platform_intr"); asm (".weak iosapic_init"); +asm (".weak iosapic_system_init"); asm (".weak iosapic_version"); void (*pm_idle) (void); @@ -182,7 +183,9 @@ #define ACPI_MAX_PLATFORM_INTERRUPTS 256 /* Array to record platform interrupt vectors for generic interrupt routing. */ -int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 }; +int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { + [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 +}; enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC; @@ -291,40 +294,6 @@ static int __init -acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address) -{ - struct acpi_table_iosapic *iosapic; - int ver; - int max_pin; - char *p; - char *end; - - if (!gsi_base || !iosapic_address) - return -ENODEV; - - p = (char *) (acpi_madt + 1); - end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt)); - - while (p < end) { - if (*p == ACPI_MADT_IOSAPIC) { - iosapic = (struct acpi_table_iosapic *) p; - - *gsi_base = iosapic->global_irq_base; - *iosapic_address = ioremap(iosapic->address, 0); - - ver = iosapic_version(*iosapic_address); - max_pin = (ver >> 16) & 0xff; - - if ((gsi - *gsi_base) <= max_pin) - return 0; /* Found it! */ - } - p += p[1]; - } - return -ENODEV; -} - - -static int __init acpi_parse_iosapic (acpi_table_entry_header *header) { struct acpi_table_iosapic *iosapic; @@ -335,16 +304,9 @@ acpi_table_print_madt_entry(header); - if (iosapic_init) { -#ifndef CONFIG_ITANIUM - /* PCAT_COMPAT flag indicates dual-8259 setup */ - iosapic_init(iosapic->address, iosapic->global_irq_base, - acpi_madt->flags.pcat_compat); -#else - /* Firmware on old Itanium systems is broken */ - iosapic_init(iosapic->address, iosapic->global_irq_base, 1); -#endif - } + if (iosapic_init) + iosapic_init(iosapic->address, iosapic->global_irq_base); + return 0; } @@ -354,8 +316,6 @@ { struct acpi_table_plat_int_src *plintsrc; int vector; - u32 gsi_base; - char *iosapic_address; plintsrc = (struct acpi_table_plat_int_src *) header; if (!plintsrc) @@ -368,11 +328,6 @@ return -ENODEV; } - if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) { - printk(KERN_WARNING PREFIX "IOSAPIC not found\n"); - return -ENODEV; - } - /* * Get vector assignment for this interrupt, set attributes, * and program the IOSAPIC routing table. @@ -382,10 +337,8 @@ plintsrc->iosapic_vector, plintsrc->eid, plintsrc->id, - (plintsrc->flags.polarity == 1) ? 1 : 0, - (plintsrc->flags.trigger == 1) ? 1 : 0, - gsi_base, - iosapic_address); + (plintsrc->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); platform_intr_list[plintsrc->type] = vector; return 0; @@ -408,8 +361,8 @@ return 0; iosapic_override_isa_irq(p->bus_irq, p->global_irq, - (p->flags.polarity == 1) ? 1 : 0, - (p->flags.trigger == 1) ? 1 : 0); + (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); return 0; } @@ -439,7 +392,13 @@ acpi_madt = (struct acpi_table_madt *) __va(phys_addr); /* remember the value for reference after free_initmem() */ +#ifdef CONFIG_ITANIUM + has_8259 = 1; /* Firmware on old Itanium systems is broken */ +#else has_8259 = acpi_madt->flags.pcat_compat; +#endif + if (iosapic_system_init) + iosapic_system_init(has_8259); /* Get base address of IPI Message Block */ @@ -571,7 +530,7 @@ } void __init -acpi_numa_arch_fixup(void) +acpi_numa_arch_fixup (void) { int i, j, node_from, node_to; @@ -618,7 +577,7 @@ if (!pxm_bit_test(j)) continue; node_to = pxm_to_nid_map[j]; - node_distance(node_from, node_to) = + node_distance(node_from, node_to) = slit_table->entry[i*slit_table->localities + j]; } } @@ -639,8 +598,7 @@ { struct acpi_table_header *fadt_header; struct fadt_descriptor_rev2 *fadt; - u32 sci_irq, gsi_base; - char *iosapic_address; + u32 sci_irq; if (!phys_addr || !size) return -EINVAL; @@ -662,8 +620,7 @@ if (has_8259 && sci_irq < 16) return 0; /* legacy, no setup required */ - if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address)) - iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address); + iosapic_register_intr(sci_irq, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); return 0; } @@ -717,8 +674,6 @@ if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) && (spcr->int_type == ACPI_SERIAL_INT_SAPIC)) { - u32 gsi_base; - char *iosapic_address; int vector; /* We have a UART in memory space with an SAPIC interrupt */ @@ -728,11 +683,7 @@ (spcr->global_int[1] << 8) | (spcr->global_int[0]) ); - /* Which iosapic does this interrupt belong to? */ - - if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address)) - vector = iosapic_register_intr(gsi, 1, 1, - gsi_base, iosapic_address); + vector = iosapic_register_intr(gsi, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); } return 0; } @@ -741,7 +692,7 @@ int __init -acpi_boot_init (char *cmdline) +acpi_boot_init (void) { /* @@ -812,20 +763,20 @@ smp_boot_data.cpu_count = total_cpus; smp_build_cpu_map(); -#ifdef CONFIG_NUMA +# ifdef CONFIG_NUMA build_cpu_to_node_map(); -#endif +# endif #endif /* Make boot-up look pretty */ printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus); return 0; } +/* + * PCI Interrupt Routing + */ -/* -------------------------------------------------------------------------- - PCI Interrupt Routing - -------------------------------------------------------------------------- */ - +#ifdef CONFIG_PCI int __init acpi_get_prt (struct pci_vector_struct **vectors, int *count) { @@ -866,6 +817,7 @@ *count = acpi_prt.count; return 0; } +#endif /* CONFIG_PCI */ /* Assume IA64 always use I/O SAPIC */ @@ -888,12 +840,10 @@ return gsi_to_vector(irq); } -int __init +int acpi_register_irq (u32 gsi, u32 polarity, u32 trigger) { int vector = 0; - u32 irq_base; - char *iosapic_address; if (acpi_madt->flags.pcat_compat && (gsi < 16)) return isa_irq_to_vector(gsi); @@ -901,12 +851,9 @@ if (!iosapic_register_intr) return 0; - /* Find the IOSAPIC */ - if (!acpi_find_iosapic(gsi, &irq_base, &iosapic_address)) { - /* Turn it on */ - vector = iosapic_register_intr (gsi, polarity, trigger, - irq_base, iosapic_address); - } + /* Turn it on */ + vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL); return vector; } diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S Tue Jan 21 18:31:31 2003 +++ b/arch/ia64/kernel/entry.S Thu Mar 6 14:56:33 2003 @@ -586,10 +586,21 @@ // work.need_resched etc. mustn't get changed by this CPU before it returns to // user- or fsys-mode: (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk +#ifdef CONFIG_PREEMPT + rsm psr.i // disable interrupts + adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; +(pKStk) ld4 r21=[r20] // preempt_count ->r21 + ;; +(pKStk) cmp4.eq p6,p0=r21,r0 // p6 <- preempt_count == 0 + ;; +#else /* CONFIG_PREEMPT */ (pUStk) rsm psr.i ;; (pUStk) adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 ;; +#endif /* CONFIG_PREEMPT */ .work_processed: (p6) ld4 r18=[r17] // load current_thread_info()->flags adds r2=PT(R8)+16,r12 @@ -701,7 +712,7 @@ * NOTE: alloc, loadrs, and cover can't be predicated. */ (pNonSys) br.cond.dpnt dont_preserve_current_frame - cover // add current frame into dirty partition + cover // add current frame into dirty partition and set cr.ifs ;; mov r19=ar.bsp // get new backing store pointer sub r16=r16,r18 // krbs = old bsp - size of dirty partition @@ -727,7 +738,7 @@ # define Nregs 14 #endif alloc loc0=ar.pfs,2,Nregs-2,2,0 - shr.u loc1=r18,9 // RNaTslots <= dirtySize / (64*8) + 1 + shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8)) sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize ;; mov ar.rsc=r19 // load ar.rsc to be used for "loadrs" @@ -774,13 +785,13 @@ ;; mov loc3=0 mov loc4=0 - mov loc9=0 mov loc5=0 mov loc6=0 + mov loc7=0 (pRecurse) br.call.sptk.many b6=rse_clear_invalid ;; - mov loc7=0 mov loc8=0 + mov loc9=0 cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret mov loc10=0 mov loc11=0 @@ -810,15 +821,27 @@ .work_pending: tbit.z p6,p0=r18,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? (p6) br.cond.sptk.few .notify +#ifdef CONFIG_PREEMPT +(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1 + ;; +(pKStk) st4 [r20]=r21 + ssm psr.i // enable interrupts +#endif + #if __GNUC__ < 3 br.call.spnt.many rp=invoke_schedule #else br.call.spnt.many rp=schedule #endif .ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 - rsm psr.i + rsm psr.i // disable interrupts ;; adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 +#if CONFIG_PREEMPT +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; +(pKStk) st4 [r20]=r0 // preempt_count() <- 0 +#endif br.cond.sptk.many .work_processed // re-check .notify: @@ -904,13 +927,14 @@ mov r9=ar.unat mov loc0=rp // save return address mov out0=0 // there is no "oldset" - adds out1=0,sp // out1=&sigscratch + adds out1=8,sp // out1=&sigscratch->ar_pfs (pSys) mov out2=1 // out2==1 => we're in a syscall ;; (pNonSys) mov out2=0 // out2==0 => not a syscall .fframe 16 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) st8 [sp]=r9,-16 // allocate space for ar.unat and save it + st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch .body br.call.sptk.many rp=do_notify_resume_user .ret15: .restore sp @@ -931,11 +955,12 @@ mov loc0=rp // save return address mov out0=in0 // mask mov out1=in1 // sigsetsize - adds out2=0,sp // out2=&sigscratch + adds out2=8,sp // out2=&sigscratch->ar_pfs ;; .fframe 16 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) st8 [sp]=r9,-16 // allocate space for ar.unat and save it + st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch .body br.call.sptk.many rp=ia64_rt_sigsuspend .ret17: .restore sp @@ -1242,7 +1267,7 @@ data8 sys_sched_setaffinity data8 sys_sched_getaffinity data8 sys_set_tid_address - data8 ia64_ni_syscall + data8 sys_fadvise64 data8 ia64_ni_syscall // 1235 data8 sys_exit_group data8 sys_lookup_dcookie @@ -1256,15 +1281,15 @@ data8 sys_epoll_wait // 1245 data8 sys_restart_syscall data8 sys_semtimedop - data8 ia64_ni_syscall - data8 ia64_ni_syscall - data8 ia64_ni_syscall // 1250 - data8 ia64_ni_syscall - data8 ia64_ni_syscall - data8 ia64_ni_syscall - data8 ia64_ni_syscall - data8 ia64_ni_syscall // 1255 - data8 ia64_ni_syscall + data8 sys_timer_create + data8 sys_timer_settime + data8 sys_timer_gettime // 1250 + data8 sys_timer_getoverrun + data8 sys_timer_delete + data8 sys_clock_settime + data8 sys_clock_gettime + data8 sys_clock_getres // 1255 + data8 sys_clock_nanosleep data8 ia64_ni_syscall data8 ia64_ni_syscall data8 ia64_ni_syscall diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S --- a/arch/ia64/kernel/fsys.S Wed Jan 29 22:16:51 2003 +++ b/arch/ia64/kernel/fsys.S Fri Feb 28 16:51:10 2003 @@ -3,11 +3,16 @@ * * Copyright (C) 2003 Hewlett-Packard Co * David Mosberger-Tang + * + * 18-Feb-03 louisk Implement fsys_gettimeofday(). + * 28-Feb-03 davidm Fixed several bugs in fsys_gettimeofday(). Tuned it some more, + * probably broke it along the way... ;-) */ #include #include #include +#include #include /* @@ -123,6 +128,183 @@ br.ret.sptk.many b6 END(fsys_set_tid_address) +/* + * Note 1: This routine uses floating-point registers, but only with registers that + * operate on integers. Because of that, we don't need to set ar.fpsr to the + * kernel default value. + * + * Note 2: For now, we will assume that all CPUs run at the same clock-frequency. + * If that wasn't the case, we would have to disable preemption (e.g., + * by disabling interrupts) between reading the ITC and reading + * local_cpu_data->nsec_per_cyc. + * + * Note 3: On platforms where the ITC-drift bit is set in the SAL feature vector, + * we ought to either skip the ITC-based interpolation or run an ntp-like + * daemon to keep the ITCs from drifting too far apart. + */ +ENTRY(fsys_gettimeofday) + add r9=TI_FLAGS+IA64_TASK_SIZE,r16 + movl r3=THIS_CPU(cpu_info) + + mov.m r31=ar.itc // put time stamp into r31 (ITC) == now (35 cyc) + movl r19=xtime // xtime is a timespec struct + ;; + +#ifdef CONFIG_SMP + movl r10=__per_cpu_offset + ;; + ld8 r10=[r10] // r10 <- __per_cpu_offset[0] + movl r21=cpu_info__per_cpu + ;; + add r10=r21, r10 // r10 <- &cpu_data(time_keeper_id) +#else + mov r10=r3 +#endif + ld4 r9=[r9] + movl r17=xtime_lock + ;; + + // r32, r33 should contain the 2 args of gettimeofday + adds r21=IA64_CPUINFO_ITM_NEXT_OFFSET, r10 + mov r2=-1 + tnat.nz p6,p7=r32 // guard against NaT args + ;; + + adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10 +(p7) tnat.nz p6,p0=r33 +(p6) br.cond.spnt.few .fail + + adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3 + movl r24=2361183241434822607 // for division hack (only for / 1000) + ;; + + ldf8 f7=[r10] // f7 now contains itm_delta + setf.sig f11=r2 + adds r10=8, r32 + + adds r20=IA64_TIMESPEC_TV_NSEC_OFFSET, r19 // r20 = &xtime->tv_nsec + movl r26=jiffies + + setf.sig f9=r24 // f9 is used for division hack + movl r27=wall_jiffies + + and r9=TIF_ALLWORK_MASK,r9 + movl r25=last_nsec_offset + ;; + + /* + * Verify that we have permission to write to struct timeval. Note: + * Another thread might unmap the mapping before we actually get + * to store the result. That's OK as long as the stores are also + * protect by EX(). + */ +EX(.fail, probe.w.fault r32, 3) // this must come _after_ NaT-check +EX(.fail, probe.w.fault r10, 3) // this must come _after_ NaT-check + nop 0 + + ldf8 f10=[r8] // f10 <- local_cpu_data->nsec_per_cyc value + cmp.ne p8, p0=0, r9 +(p8) br.spnt.many fsys_fallback_syscall + ;; +.retry: // *** seq = read_seqbegin(&xtime_lock); *** + ld4.acq r23=[r17] // since &xtime_lock == &xtime_lock->sequence + ld8 r14=[r25] // r14 (old) = last_nsec_offset + + ld8 r28=[r26] // r28 = jiffies + ld8 r29=[r27] // r29 = wall_jiffies + ;; + + ldf8 f8=[r21] // f8 now contains itm_next + sub r28=r29, r28, 1 // r28 now contains "-(lost + 1)" + tbit.nz p9, p10=r23, 0 // p9 <- is_odd(r23), p10 <- is_even(r23) + ;; + + ld8 r2=[r19] // r2 = sec = xtime.tv_sec + ld8 r29=[r20] // r29 = nsec = xtime.tv_nsec + + setf.sig f6=r28 // f6 <- -(lost + 1) (6 cyc) + ;; + + mf + xma.l f8=f6, f7, f8 // f8 (last_tick) <- -(lost + 1)*itm_delta + itm_next (5 cyc) + nop 0 + + setf.sig f12=r31 // f12 <- ITC (6 cyc) + // *** if (unlikely(read_seqretry(&xtime_lock, seq))) continue; *** + ld4 r24=[r17] // r24 = xtime_lock->sequence (re-read) + nop 0 + ;; + + mov r31=ar.itc // re-read ITC in case we .retry (35 cyc) + xma.l f8=f11, f8, f12 // f8 (elapsed_cycles) <- (-1*last_tick + now) = (now - last_tick) + nop 0 + ;; + + getf.sig r18=f8 // r18 <- (now - last_tick) + xmpy.l f8=f8, f10 // f8 <- elapsed_cycles*nsec_per_cyc (5 cyc) + add r3=r29, r14 // r3 = (nsec + old) + ;; + + cmp.lt p7, p8=r18, r0 // if now < last_tick, set p7 = 1, p8 = 0 + getf.sig r18=f8 // r18 = elapsed_cycles*nsec_per_cyc (6 cyc) + nop 0 + ;; + +(p10) cmp.ne p9, p0=r23, r24 // if xtime_lock->sequence != seq, set p9 + shr.u r18=r18, IA64_NSEC_PER_CYC_SHIFT // r18 <- offset +(p9) br.spnt.many .retry + ;; + + mov ar.ccv=r14 // ar.ccv = old (1 cyc) + cmp.leu p7, p8=r18, r14 // if (offset <= old), set p7 = 1, p8 = 0 + ;; + +(p8) cmpxchg8.rel r24=[r25], r18, ar.ccv // compare-and-exchange (atomic!) +(p8) add r3=r29, r18 // r3 = (nsec + offset) + ;; + shr.u r3=r3, 3 // initiate dividing r3 by 1000 + ;; + setf.sig f8=r3 // (6 cyc) + mov r10=1000000 // r10 = 1000000 + ;; +(p8) cmp.ne.unc p9, p0=r24, r14 + xmpy.hu f6=f8, f9 // (5 cyc) +(p9) br.spnt.many .retry + ;; + + getf.sig r3=f6 // (6 cyc) + ;; + shr.u r3=r3, 4 // end of division, r3 is divided by 1000 (=usec) + ;; + +1: cmp.geu p7, p0=r3, r10 // while (usec >= 1000000) + ;; +(p7) sub r3=r3, r10 // usec -= 1000000 +(p7) adds r2=1, r2 // ++sec +(p7) br.spnt.many 1b + + // finally: r2 = sec, r3 = usec +EX(.fail, st8 [r32]=r2) + adds r9=8, r32 + mov r8=r0 // success + ;; +EX(.fail, st8 [r9]=r3) // store them in the timeval struct + mov r10=0 + MCKINLEY_E9_WORKAROUND + br.ret.sptk.many b6 // return to caller + /* + * Note: We are NOT clearing the scratch registers here. Since the only things + * in those registers are time-related variables and some addresses (which + * can be obtained from System.map), none of this should be security-sensitive + * and we should be fine. + */ + +.fail: adds r8=EINVAL, r0 // r8 = EINVAL + adds r10=-1, r0 // r10 = -1 + MCKINLEY_E9_WORKAROUND + br.ret.spnt.many b6 // return with r8 set to EINVAL +END(fsys_gettimeofday) + .rodata .align 8 .globl fsyscall_table @@ -190,7 +372,7 @@ data8 fsys_fallback_syscall // setrlimit data8 fsys_fallback_syscall // getrlimit // 1085 data8 fsys_fallback_syscall // getrusage - data8 fsys_fallback_syscall // gettimeofday + data8 fsys_gettimeofday // gettimeofday data8 fsys_fallback_syscall // settimeofday data8 fsys_fallback_syscall // select data8 fsys_fallback_syscall // poll // 1090 diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S --- a/arch/ia64/kernel/gate.S Fri Jan 17 19:18:54 2003 +++ b/arch/ia64/kernel/gate.S Mon Feb 10 18:28:00 2003 @@ -145,11 +145,12 @@ */ #define SIGTRAMP_SAVES \ - .unwabi @svr4, 's' // mark this as a sigtramp handler (saves scratch regs) \ - .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF \ - .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF \ - .savesp pr, PR_OFF+SIGCONTEXT_OFF \ - .savesp rp, RP_OFF+SIGCONTEXT_OFF \ + .unwabi @svr4, 's'; /* mark this as a sigtramp handler (saves scratch regs) */ \ + .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF; \ + .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF; \ + .savesp pr, PR_OFF+SIGCONTEXT_OFF; \ + .savesp rp, RP_OFF+SIGCONTEXT_OFF; \ + .savesp ar.pfs, CFM_OFF+SIGCONTEXT_OFF; \ .vframesp SP_OFF+SIGCONTEXT_OFF GLOBAL_ENTRY(ia64_sigtramp) @@ -173,9 +174,7 @@ .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF (p8) br.cond.spnt setup_rbs // yup -> (clobbers r14, r15, and r16) back_from_setup_rbs: - - .spillreg ar.pfs, r8 - alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8 + alloc r8=ar.pfs,0,0,3,0 ld8 out0=[base0],16 // load arg0 (signum) adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1 ;; @@ -184,17 +183,12 @@ ;; ld8 out2=[base0] // load arg2 (sigcontextp) ld8 gp=[r17] // get signal handler's global pointer - adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp ;; .spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF - st8 [base0]=r9,(CFM_OFF-BSP_OFF) // save sc_ar_bsp - dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits - adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp - ;; - .spillsp ar.pfs, CFM_OFF+SIGCONTEXT_OFF - st8 [base0]=r8 // save CFM0 + st8 [base0]=r9 // save sc_ar_bsp adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp + adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp ;; stf.spill [base0]=f6,32 stf.spill [base1]=f7,32 @@ -217,7 +211,6 @@ ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF mov r14=ar.bsp ;; - ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0 cmp.ne p8,p0=r14,r15 // do we need to restore the rbs? (p8) br.cond.spnt restore_rbs // yup -> (clobbers r14-r18, f6 & f7) ;; diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c --- a/arch/ia64/kernel/init_task.c Tue Sep 17 23:22:09 2002 +++ b/arch/ia64/kernel/init_task.c Wed Feb 12 00:11:32 2003 @@ -17,6 +17,7 @@ static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); /* diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c Tue Feb 4 17:06:08 2003 +++ b/arch/ia64/kernel/iosapic.c Wed Feb 19 14:07:24 2003 @@ -29,6 +29,9 @@ * 02/07/29 T. Kochi Allocate interrupt vectors dynamically * 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, etc.) * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's pci_irq code. + * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC. + * Remove iosapic_address & gsi_base from external interfaces. + * Rationalize __init/__devinit attributes. */ /* * Here is what the interrupt logic between a PCI device and the kernel looks like: @@ -111,16 +114,17 @@ char *addr; /* base address of IOSAPIC */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ unsigned short num_rte; /* number of RTE in this IOSAPIC */ - unsigned char pcat_compat; /* 8259 compatibility flag */ -} iosapic_lists[256] __devinitdata; +} iosapic_lists[256]; -static int num_iosapic = 0; +static int num_iosapic; + +static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */ /* * Find an IOSAPIC associated with a GSI */ -static inline int __devinit +static inline int find_iosapic (unsigned int gsi) { int i; @@ -423,7 +427,7 @@ * if the given vector is already owned by other, * assign a new vector for the other and make the vector available */ -static void +static void __init iosapic_reassign_vector (int vector) { int new_vector; @@ -443,50 +447,36 @@ static void register_intr (unsigned int gsi, int vector, unsigned char delivery, - unsigned long polarity, unsigned long edge_triggered, - unsigned int gsi_base, char *iosapic_address) + unsigned long polarity, unsigned long trigger) { irq_desc_t *idesc; struct hw_interrupt_type *irq_type; int rte_index; + int index; + unsigned long gsi_base; + char *iosapic_address; + + index = find_iosapic(gsi); + if (index < 0) { + printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi); + return; + } + + iosapic_address = iosapic_lists[index].addr; + gsi_base = iosapic_lists[index].gsi_base; rte_index = gsi - gsi_base; iosapic_intr_info[vector].rte_index = rte_index; - iosapic_intr_info[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW; + iosapic_intr_info[vector].polarity = polarity; iosapic_intr_info[vector].dmode = delivery; + iosapic_intr_info[vector].addr = iosapic_address; + iosapic_intr_info[vector].gsi_base = gsi_base; + iosapic_intr_info[vector].trigger = trigger; - /* - * In override, it may not provide addr/gsi_base. GSI is enough to - * locate iosapic addr, gsi_base and rte_index by examining - * gsi_base and num_rte of registered iosapics (tbd) - */ -#ifndef OVERRIDE_DEBUG - if (iosapic_address) { - iosapic_intr_info[vector].addr = iosapic_address; - iosapic_intr_info[vector].gsi_base = gsi_base; - } -#else - if (iosapic_address) { - if (iosapic_intr_info[vector].addr && (iosapic_intr_info[vector].addr != iosapic_address)) - printk(KERN_WARNING "warning: register_intr: diff IOSAPIC ADDRESS for " - "GSI 0x%x, vector %d\n", gsi, vector); - iosapic_intr_info[vector].addr = iosapic_address; - if (iosapic_intr_info[vector].gsi_base && (iosapic_intr_info[vector].gsi_base != gsi_base)) { - printk(KERN_WARNING "warning: register_intr: diff GSI base 0x%x for " - "GSI 0x%x, vector %d\n", gsi_base, gsi, vector); - } - iosapic_intr_info[vector].gsi_base = gsi_base; - } else if (!iosapic_intr_info[vector].addr) - printk(KERN_WARNING "warning: register_intr: invalid override for GSI 0x%x, " - "vector %d\n", gsi, vector); -#endif - if (edge_triggered) { - iosapic_intr_info[vector].trigger = IOSAPIC_EDGE; + if (trigger == IOSAPIC_EDGE) irq_type = &irq_type_iosapic_edge; - } else { - iosapic_intr_info[vector].trigger = IOSAPIC_LEVEL; + else irq_type = &irq_type_iosapic_level; - } idesc = irq_desc(vector); if (idesc->handler != irq_type) { @@ -504,8 +494,7 @@ */ int iosapic_register_intr (unsigned int gsi, - unsigned long polarity, unsigned long edge_triggered, - unsigned int gsi_base, char *iosapic_address) + unsigned long polarity, unsigned long trigger) { int vector; unsigned int dest = (ia64_get_lid() >> 16) & 0xffff; @@ -515,11 +504,11 @@ vector = ia64_alloc_vector(); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, - polarity, edge_triggered, gsi_base, iosapic_address); + polarity, trigger); printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - gsi, (polarity ? "high" : "low"), - (edge_triggered ? "edge" : "level"), dest, vector); + gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); @@ -530,11 +519,10 @@ * ACPI calls this when it finds an entry for a platform interrupt. * Note that the irq_base and IOSAPIC address must be set in iosapic_init(). */ -int +int __init iosapic_register_platform_intr (u32 int_type, unsigned int gsi, int iosapic_vector, u16 eid, u16 id, - unsigned long polarity, unsigned long edge_triggered, - unsigned int gsi_base, char *iosapic_address) + unsigned long polarity, unsigned long trigger) { unsigned char delivery; int vector; @@ -564,11 +552,11 @@ } register_intr(gsi, vector, delivery, polarity, - edge_triggered, gsi_base, iosapic_address); + trigger); printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - int_type, gsi, (polarity ? "high" : "low"), - (edge_triggered ? "edge" : "level"), dest, vector); + int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); @@ -580,54 +568,36 @@ * ACPI calls this when it finds an entry for a legacy ISA IRQ override. * Note that the gsi_base and IOSAPIC address must be set in iosapic_init(). */ -void +void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, unsigned long polarity, - unsigned long edge_triggered) + unsigned long trigger) { - int index, vector; - unsigned int gsi_base; - char *addr; + int vector; unsigned int dest = (ia64_get_lid() >> 16) & 0xffff; - index = find_iosapic(gsi); - - if (index < 0) { - printk(KERN_ERR "ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n", - isa_irq, gsi); - return; - } - vector = isa_irq_to_vector(isa_irq); - addr = iosapic_lists[index].addr; - gsi_base = iosapic_lists[index].gsi_base; - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered, - gsi_base, addr); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n", isa_irq, gsi, - polarity ? "high" : "low", edge_triggered ? "edge" : "level", + polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); } -void __devinit -iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat) +void __init +iosapic_system_init (int system_pcat_compat) { - int num_rte, vector; - unsigned int isa_irq, ver; - char *addr; - static int first_time = 1; + int vector; - if (first_time) { - first_time = 0; - for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) - iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ - } + for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) + iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ + pcat_compat = system_pcat_compat; if (pcat_compat) { /* * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support @@ -637,6 +607,14 @@ outb(0xff, 0xA1); outb(0xff, 0x21); } +} + +void __init +iosapic_init (unsigned long phys_addr, unsigned int gsi_base) +{ + int num_rte; + unsigned int isa_irq, ver; + char *addr; addr = ioremap(phys_addr, 0); ver = iosapic_version(addr); @@ -649,7 +627,6 @@ num_rte = ((ver >> 16) & 0xff) + 1; iosapic_lists[num_iosapic].addr = addr; - iosapic_lists[num_iosapic].pcat_compat = pcat_compat; iosapic_lists[num_iosapic].gsi_base = gsi_base; iosapic_lists[num_iosapic].num_rte = num_rte; num_iosapic++; @@ -658,30 +635,18 @@ (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1); if ((gsi_base == 0) && pcat_compat) { - unsigned int dest = (ia64_get_lid() >> 16) & 0xffff; /* * Map the legacy ISA devices into the IOSAPIC data. Some of these may * get reprogrammed later on with data from the ACPI Interrupt Source * Override table. */ - for (isa_irq = 0; isa_irq < 16; ++isa_irq) { - vector = isa_irq_to_vector(isa_irq); - - register_intr(isa_irq, vector, IOSAPIC_LOWEST_PRIORITY, - /* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */ - 1, 1, gsi_base, addr); - - DBG("ISA: IRQ %u -> GSI 0x%x (high,edge) -> CPU 0x%04x vector %d\n", - isa_irq, isa_irq, dest, vector); - - /* program the IOSAPIC routing table: */ - set_rte(vector, dest); - } + for (isa_irq = 0; isa_irq < 16; ++isa_irq) + iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); } } -static void +static void __init fixup_vector (int vector, unsigned int gsi, const char *pci_id) { struct hw_interrupt_type *irq_type = &irq_type_iosapic_level; @@ -731,10 +696,9 @@ { struct acpi_prt_entry *entry; struct list_head *node; - unsigned int gsi, gsi_base; - int index, vector, pcat_compat; + unsigned int gsi; + int vector; char pci_id[16]; - char *addr; list_for_each(node, &acpi_prt.entries) { entry = list_entry(node, struct acpi_prt_entry, node); @@ -748,23 +712,13 @@ vector = gsi_to_vector(gsi); if (vector < 0) { /* allocate a vector for this interrupt line */ - index = find_iosapic(gsi); - - if (index < 0) { - printk(KERN_WARNING "IOSAPIC: GSI 0x%x has no IOSAPIC!\n", gsi); - continue; - } - addr = iosapic_lists[index].addr; - gsi_base = iosapic_lists[index].gsi_base; - pcat_compat = iosapic_lists[index].pcat_compat; - if (pcat_compat && (gsi < 16)) vector = isa_irq_to_vector(gsi); else /* new GSI; allocate a vector for it */ vector = ia64_alloc_vector(); - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, 0, 0, gsi_base, addr); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); } snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]", entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin); diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Tue Feb 25 01:38:25 2003 +++ b/arch/ia64/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -154,6 +154,7 @@ int i, j; struct irqaction * action; irq_desc_t *idesc; + unsigned long flags; seq_puts(p, " "); for (j=0; jlock, flags); action = idesc->action; if (!action) - continue; + goto skip; seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); @@ -176,10 +178,12 @@ #endif seq_printf(p, " %14s", idesc->handler->typename); seq_printf(p, " %s", action->name); - for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&idesc->lock, flags); } seq_puts(p, "NMI: "); for (j = 0; j < NR_CPUS; j++) @@ -340,12 +344,14 @@ * 0 return value means that this irq is already being * handled by some other CPU. (or is disabled) */ - int cpu = smp_processor_id(); + int cpu; irq_desc_t *desc = irq_desc(irq); struct irqaction * action; unsigned int status; irq_enter(); + cpu = smp_processor_id(); + kstat_cpu(cpu).irqs[irq]++; if (desc->status & IRQ_PER_CPU) { diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S --- a/arch/ia64/kernel/ivt.S Wed Jan 15 16:26:26 2003 +++ b/arch/ia64/kernel/ivt.S Sat Feb 15 04:39:48 2003 @@ -848,7 +848,7 @@ alloc r15=ar.pfs,0,0,6,0 // must first in an insn group ;; ld4 r8=[r14],8 // r8 == eax (syscall number) - mov r15=230 // number of entries in ia32 system call table + mov r15=250 // number of entries in ia32 system call table ;; cmp.ltu.unc p6,p7=r8,r15 ld4 out1=[r14],8 // r9 == ecx diff -Nru a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c --- a/arch/ia64/kernel/machvec.c Tue Feb 4 17:06:10 2003 +++ b/arch/ia64/kernel/machvec.c Thu Feb 20 02:35:33 2003 @@ -10,19 +10,6 @@ struct ia64_machine_vector ia64_mv; -/* - * Most platforms use this routine for mapping page frame addresses into a memory map - * index. - * - * Note: we can't use __pa() because map_nr_dense(X) MUST map to something >= max_mapnr if - * X is outside the identity mapped kernel space. - */ -unsigned long -map_nr_dense (unsigned long addr) -{ - return (addr - PAGE_OFFSET) >> PAGE_SHIFT; -} - static struct ia64_machine_vector * lookup_machvec (const char *name) { diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c Tue Feb 4 17:06:10 2003 +++ b/arch/ia64/kernel/mca.c Tue Mar 4 18:33:56 2003 @@ -825,7 +825,7 @@ plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT); proc_ptr = &plog_ptr->proc_err; - ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area); + ia64_process_min_state_save(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area); /* Clear the INIT SAL logs now that they have been saved in the OS buffer */ ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT); @@ -1620,7 +1620,7 @@ * absent. Also, current implementations only allocate space for number of * elements used. So we walk the data pointer from here on. */ - p_data = &slpi->cache_check_info[0]; + p_data = &slpi->info[0]; /* Print the cache check information if any*/ for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++) diff -Nru a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c --- a/arch/ia64/kernel/palinfo.c Tue Feb 4 17:06:11 2003 +++ b/arch/ia64/kernel/palinfo.c Thu Feb 13 05:43:47 2003 @@ -341,11 +341,11 @@ return 0; } - p += sprintf(p, "\nTLB walker : %s implemented\n" \ + p += sprintf(p, "\nTLB walker : %simplemented\n" \ "Number of DTR : %d\n" \ "Number of ITR : %d\n" \ "TLB insertable page sizes : ", - vm_info_1.pal_vm_info_1_s.vw ? "\b":"not", + vm_info_1.pal_vm_info_1_s.vw ? "" : "not ", vm_info_1.pal_vm_info_1_s.max_dtr_entry+1, vm_info_1.pal_vm_info_1_s.max_itr_entry+1); @@ -894,10 +894,12 @@ * in SMP mode, we may need to call another CPU to get correct * information. PAL, by definition, is processor specific */ - if (f->req_cpu == smp_processor_id()) + if (f->req_cpu == get_cpu()) len = (*palinfo_entries[f->func_id].proc_read)(page); else len = palinfo_handle_smp(f, page); + + put_cpu(); if (len <= off+count) *eof = 1; diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Tue Feb 25 09:44:04 2003 +++ b/arch/ia64/kernel/perfmon.c Thu Mar 6 11:40:52 2003 @@ -8,7 +8,7 @@ * Modifications by Stephane Eranian, Hewlett-Packard Co. * Modifications by David Mosberger-Tang, Hewlett-Packard Co. * - * Copyright (C) 1999-2002 Hewlett Packard Co + * Copyright (C) 1999-2003 Hewlett Packard Co * Stephane Eranian * David Mosberger-Tang */ @@ -230,9 +230,15 @@ unsigned int protected:1; /* allow access to creator of context only */ unsigned int using_dbreg:1; /* using range restrictions (debug registers) */ unsigned int excl_idle:1; /* exclude idle task in system wide session */ - unsigned int reserved:23; + unsigned int trap_reason:2; /* reason for going into pfm_block_ovfl_reset() */ + unsigned int reserved:21; } pfm_context_flags_t; +#define PFM_TRAP_REASON_NONE 0x0 /* default value */ +#define PFM_TRAP_REASON_BLOCKSIG 0x1 /* we need to block on overflow and signal user */ +#define PFM_TRAP_REASON_SIG 0x2 /* we simply need to signal user */ +#define PFM_TRAP_REASON_RESET 0x3 /* we need to reset PMDs */ + /* * perfmon context: encapsulates all the state of a monitoring session * XXX: probably need to change layout @@ -277,6 +283,7 @@ #define ctx_fl_protected ctx_flags.protected #define ctx_fl_using_dbreg ctx_flags.using_dbreg #define ctx_fl_excl_idle ctx_flags.excl_idle +#define ctx_fl_trap_reason ctx_flags.trap_reason /* * global information about all sessions @@ -1225,6 +1232,8 @@ ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0; ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0; ctx->ctx_fl_frozen = 0; + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; + /* * setting this flag to 0 here means, that the creator or the task that the * context is being attached are granted access. Given that a context can only @@ -1505,7 +1514,7 @@ unsigned long value, hw_value; unsigned int cnum; int i; - int ret = 0; + int ret = -EINVAL; /* we don't quite support this right now */ if (task != current) return -EINVAL; @@ -1514,10 +1523,10 @@ * Cannot do anything before PMU is enabled */ if (!CTX_IS_ENABLED(ctx)) return -EINVAL; + preempt_disable(); /* XXX: ctx locking may be required here */ - ret = -EINVAL; for (i = 0; i < count; i++, req++) { @@ -1591,10 +1600,12 @@ ctx->ctx_used_pmds[0], ctx->ctx_soft_pmds[cnum].reset_pmds[0])); } - + preempt_enable(); return 0; abort_mission: + preempt_enable(); + /* * for now, we have only one possibility for error */ @@ -1639,6 +1650,7 @@ DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid)); for (i = 0; i < count; i++, req++) { + int me; #if __GNUC__ < 3 foo = __get_user(cnum, &req->reg_num); if (foo) return -EFAULT; @@ -1666,13 +1678,16 @@ * PMU state is still in the local live register due to lazy ctxsw. * If true, then we read directly from the registers. */ - if (atomic_read(&ctx->ctx_last_cpu) == smp_processor_id()){ + me = get_cpu(); + if (atomic_read(&ctx->ctx_last_cpu) == me){ ia64_srlz_d(); val = ia64_get_pmd(cnum); DBprintk(("reading pmd[%u]=0x%lx from hw\n", cnum, val)); } else { val = th->pmd[cnum]; } + + if (PMD_IS_COUNTING(cnum)) { /* * XXX: need to check for overflow @@ -1694,6 +1709,8 @@ PFM_REG_RETFLAG_SET(reg_flags, ret); + put_cpu(); + DBprintk(("read pmd[%u] ret=%d value=0x%lx pmc=0x%lx\n", cnum, ret, val, ia64_get_pmc(cnum))); @@ -1831,6 +1848,7 @@ ctx->ctx_fl_frozen, ctx->ctx_ovfl_regs[0])); + preempt_disable(); pfm_reset_regs(ctx, ctx->ctx_ovfl_regs, PFM_PMD_LONG_RESET); ctx->ctx_ovfl_regs[0] = 0UL; @@ -1849,6 +1867,8 @@ /* simply unfreeze */ pfm_unfreeze_pmu(); + preempt_enable(); + return 0; } /* restart on another task */ @@ -1906,6 +1926,7 @@ ctx->ctx_fl_system, PMU_OWNER(), current)); + preempt_disable(); /* simply stop monitoring but not the PMU */ if (ctx->ctx_fl_system) { @@ -1933,6 +1954,7 @@ */ ia64_psr(regs)->up = 0; } + preempt_enable(); return 0; } @@ -1945,6 +1967,7 @@ if (!CTX_IS_ENABLED(ctx)) return -EINVAL; + preempt_disable(); /* * stop monitoring, freeze PMU, and save state in context * this call will clear IA64_THREAD_PM_VALID for per-task sessions. @@ -1965,6 +1988,7 @@ DBprintk(("enabling psr.sp for [%d]\n", current->pid)); ctx->ctx_flags.state = PFM_CTX_DISABLED; + preempt_enable(); return 0; } @@ -2314,6 +2338,7 @@ return -EINVAL; } + preempt_disable(); if (ctx->ctx_fl_system) { PFM_CPUINFO_SET(PFM_CPUINFO_DCR_PP); @@ -2331,6 +2356,7 @@ } else { if ((task->thread.flags & IA64_THREAD_PM_VALID) == 0) { + preempt_enable(); printk(KERN_DEBUG "perfmon: pfm_start task flag not set for [%d]\n", task->pid); return -EINVAL; @@ -2344,6 +2370,7 @@ ia64_srlz_i(); } + preempt_enable(); return 0; } @@ -2351,9 +2378,13 @@ pfm_enable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { + int me; + /* we don't quite support this right now */ if (task != current) return -EINVAL; + me = get_cpu(); /* make sure we're not migrated or preempted */ + if (ctx->ctx_fl_system == 0 && PMU_OWNER() && PMU_OWNER() != current) pfm_lazy_save_regs(PMU_OWNER()); @@ -2397,11 +2428,13 @@ SET_PMU_OWNER(task); ctx->ctx_flags.state = PFM_CTX_ENABLED; - atomic_set(&ctx->ctx_last_cpu, smp_processor_id()); + atomic_set(&ctx->ctx_last_cpu, me); /* simply unfreeze */ pfm_unfreeze_pmu(); + put_cpu(); + return 0; } @@ -2547,6 +2580,10 @@ task = find_task_by_pid(pid); + if (task) get_task_struct(task); + + read_unlock(&tasklist_lock); + if (!task) goto abort_call; ret = -EPERM; @@ -2584,16 +2621,116 @@ ret = (*pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func)(task, ctx, arg, count, regs); abort_call: - if (task != current) read_unlock(&tasklist_lock); + if (task && task != current) put_task_struct(task); return ret; } +/* + * send SIGPROF to register task, must be invoked when it + * is safe to send a signal, e.g., not holding any runqueue + * related locks. + */ +static int +pfm_notify_user(pfm_context_t *ctx) +{ + struct siginfo si; + int ret; + + if (ctx->ctx_notify_task == NULL) { + DBprintk(("[%d] no notifier\n", current->pid)); + return -EINVAL; + } + + si.si_errno = 0; + si.si_addr = NULL; + si.si_pid = current->pid; /* who is sending */ + si.si_signo = SIGPROF; + si.si_code = PROF_OVFL; + + si.si_pfm_ovfl[0] = ctx->ctx_ovfl_regs[0]; + + /* + * when the target of the signal is not ourself, we have to be more + * careful. The notify_task may being cleared by the target task itself + * in release_thread(). We must ensure mutual exclusion here such that + * the signal is delivered (even to a dying task) safely. + */ + + if (ctx->ctx_notify_task != current) { + /* + * grab the notification lock for this task + * This guarantees that the sequence: test + send_signal + * is atomic with regards to the ctx_notify_task field. + * + * We need a spinlock and not just an atomic variable for this. + * + */ + spin_lock(&ctx->ctx_lock); + + /* + * now notify_task cannot be modified until we're done + * if NULL, they it got modified while we were in the handler + */ + if (ctx->ctx_notify_task == NULL) { + + spin_unlock(&ctx->ctx_lock); + + /* + * If we've lost the notified task, then we will run + * to completion wbut keep the PMU frozen. Results + * will be incorrect anyway. We do not kill task + * to leave it possible to attach perfmon context + * to already running task. + */ + printk("perfmon: pfm_notify_user() lost notify_task\n"); + DBprintk_ovfl(("notification task has disappeared !\n")); + + /* we cannot afford to block now */ + ctx->ctx_fl_block = 0; + + return -EINVAL; + } + + /* + * required by send_sig_info() to make sure the target + * task does not disappear on us. + */ + read_lock(&tasklist_lock); + } + /* + * in this case, we don't stop the task, we let it go on. It will + * necessarily go to the signal handler (if any) when it goes back to + * user mode. + */ + DBprintk_ovfl(("[%d] sending notification to [%d]\n", + current->pid, ctx->ctx_notify_task->pid)); + + /* + * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock + */ + ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task); + if (ret) { + printk("perfmon: send_sig_info(process %d, SIGPROF)=%d\n", + ctx->ctx_notify_task->pid, ret); + } + + /* + * now undo the protections in order + */ + if (ctx->ctx_notify_task != current) { + read_unlock(&tasklist_lock); + spin_unlock(&ctx->ctx_lock); + } + return ret; +} + void pfm_ovfl_block_reset(void) { struct thread_struct *th = ¤t->thread; pfm_context_t *ctx = current->thread.pfm_context; + unsigned int reason; int ret; /* @@ -2609,8 +2746,31 @@ printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid); return; } + /* + * extract reason for being here and clear + */ + reason = ctx->ctx_fl_trap_reason; + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; - if (CTX_OVFL_NOBLOCK(ctx)) goto non_blocking; + DBprintk(("[%d] reason=%d\n", current->pid, reason)); + + /* + * just here for a reset (non-blocking context only) + */ + if (reason == PFM_TRAP_REASON_RESET) goto non_blocking; + + /* + * first notify user. This can fail if notify_task has disappeared. + */ + if (reason == PFM_TRAP_REASON_SIG || reason == PFM_TRAP_REASON_BLOCKSIG) { + ret = pfm_notify_user(ctx); + if (ret) return; + } + + /* + * came here just to signal (non-blocking) + */ + if (reason == PFM_TRAP_REASON_SIG) return; DBprintk(("[%d] before sleeping\n", current->pid)); @@ -2691,7 +2851,7 @@ * initialize entry header */ h->pid = current->pid; - h->cpu = smp_processor_id(); + h->cpu = get_cpu(); h->last_reset_value = ovfl_mask ? ctx->ctx_soft_pmds[ffz(~ovfl_mask)].lval : 0UL; h->ip = regs ? regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3): 0x0UL; h->regs = ovfl_mask; /* which registers overflowed */ @@ -2718,7 +2878,7 @@ DBprintk_ovfl(("e=%p pmd%d =0x%lx\n", (void *)e, j, *e)); e++; } - pfm_stats[smp_processor_id()].pfm_recorded_samples_count++; + pfm_stats[h->cpu].pfm_recorded_samples_count++; /* * make the new entry visible to user, needs to be atomic @@ -2735,9 +2895,11 @@ /* * XXX: must reset buffer in blocking mode and lost notified */ - pfm_stats[smp_processor_id()].pfm_full_smpl_buffer_count++; + pfm_stats[h->cpu].pfm_full_smpl_buffer_count++; + put_cpu(); return 1; } + put_cpu(); return 0; } @@ -2756,7 +2918,6 @@ unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL; int i; int ret = 1; - struct siginfo si; /* * It is never safe to access the task for which the overflow interrupt is destinated * using the current variable as the interrupt may occur in the middle of a context switch @@ -2770,6 +2931,8 @@ * valid one, i.e. the one that caused the interrupt. */ + preempt_disable(); + t = &task->thread; /* @@ -2779,6 +2942,7 @@ if ((t->flags & IA64_THREAD_PM_VALID) == 0 && ctx->ctx_fl_system == 0) { printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d not " "using perfmon\n", task->pid); + preempt_enable_no_resched(); return 0x1; } /* @@ -2787,6 +2951,7 @@ if ((pmc0 & 0x1) == 0) { printk(KERN_DEBUG "perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n", task->pid, pmc0); + preempt_enable_no_resched(); return 0x0; } @@ -2869,7 +3034,8 @@ if (ovfl_notify == 0UL) { if (ovfl_pmds) pfm_reset_regs(ctx, &ovfl_pmds, PFM_PMD_SHORT_RESET); - return 0x0; + preempt_enable_no_resched(); + return 0x0UL; } /* @@ -2877,142 +3043,35 @@ */ ctx->ctx_ovfl_regs[0] = ovfl_pmds; - /* - * we have come to this point because there was an overflow and that notification - * was requested. The notify_task may have disappeared, in which case notify_task - * is NULL. - */ - if (ctx->ctx_notify_task) { - - si.si_errno = 0; - si.si_addr = NULL; - si.si_pid = task->pid; /* who is sending */ - - si.si_signo = SIGPROF; - si.si_code = PROF_OVFL; /* indicates a perfmon SIGPROF signal */ - /* - * Shift the bitvector such that the user sees bit 4 for PMD4 and so on. - * We only use smpl_ovfl[0] for now. It should be fine for quite a while - * until we have more than 61 PMD available. - */ - si.si_pfm_ovfl[0] = ovfl_notify; - - /* - * when the target of the signal is not ourself, we have to be more - * careful. The notify_task may being cleared by the target task itself - * in release_thread(). We must ensure mutual exclusion here such that - * the signal is delivered (even to a dying task) safely. - */ - - if (ctx->ctx_notify_task != current) { - /* - * grab the notification lock for this task - * This guarantees that the sequence: test + send_signal - * is atomic with regards to the ctx_notify_task field. - * - * We need a spinlock and not just an atomic variable for this. - * - */ - spin_lock(&ctx->ctx_lock); - - /* - * now notify_task cannot be modified until we're done - * if NULL, they it got modified while we were in the handler - */ - if (ctx->ctx_notify_task == NULL) { - - spin_unlock(&ctx->ctx_lock); + DBprintk_ovfl(("block=%d notify [%d] current [%d]\n", + ctx->ctx_fl_block, + ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1, + current->pid )); - /* - * If we've lost the notified task, then we will run - * to completion wbut keep the PMU frozen. Results - * will be incorrect anyway. We do not kill task - * to leave it possible to attach perfmon context - * to already running task. - */ - goto lost_notify; - } - /* - * required by send_sig_info() to make sure the target - * task does not disappear on us. - */ - read_lock(&tasklist_lock); - } - /* - * in this case, we don't stop the task, we let it go on. It will - * necessarily go to the signal handler (if any) when it goes back to - * user mode. - */ - DBprintk_ovfl(("[%d] sending notification to [%d]\n", - task->pid, ctx->ctx_notify_task->pid)); - - - /* - * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock - */ - ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task); - if (ret != 0) - printk(KERN_DEBUG "send_sig_info(process %d, SIGPROF)=%d\n", - ctx->ctx_notify_task->pid, ret); - /* - * now undo the protections in order - */ - if (ctx->ctx_notify_task != current) { - read_unlock(&tasklist_lock); - spin_unlock(&ctx->ctx_lock); - } - - /* - * if we block set the pfm_must_block bit - * when in block mode, we can effectively block only when the notified - * task is not self, otherwise we would deadlock. - * in this configuration, the notification is sent, the task will not - * block on the way back to user mode, but the PMU will be kept frozen - * until PFM_RESTART. - * Note that here there is still a race condition with notify_task - * possibly being nullified behind our back, but this is fine because - * it can only be changed to NULL which by construction, can only be - * done when notify_task != current. So if it was already different - * before, changing it to NULL will still maintain this invariant. - * Of course, when it is equal to current it cannot change at this point. - */ - DBprintk_ovfl(("block=%d notify [%d] current [%d]\n", - ctx->ctx_fl_block, - ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1, - current->pid )); - - if (!CTX_OVFL_NOBLOCK(ctx) && ctx->ctx_notify_task != task) { - t->pfm_ovfl_block_reset = 1; /* will cause blocking */ - } + /* + * ctx_notify_task could already be NULL, checked in pfm_notify_user() + */ + if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) { + t->pfm_ovfl_block_reset = 1; /* will cause blocking */ + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_BLOCKSIG; } else { -lost_notify: /* XXX: more to do here, to convert to non-blocking (reset values) */ - - DBprintk_ovfl(("notification task has disappeared !\n")); - /* - * for a non-blocking context, we make sure we do not fall into the - * pfm_overflow_notify() trap. Also in the case of a blocking context with lost - * notify process, then we do not want to block either (even though it is - * interruptible). In this case, the PMU will be kept frozen and the process will - * run to completion without monitoring enabled. - * - * Of course, we cannot loose notify process when self-monitoring. - */ - t->pfm_ovfl_block_reset = 0; - + t->pfm_ovfl_block_reset = 1; /* will cause blocking */ + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG; } + /* - * If notification was successful, then we rely on the pfm_restart() - * call to unfreeze and reset (in both blocking or non-blocking mode). - * - * If notification failed, then we will keep the PMU frozen and run - * the task to completion + * keep the PMU frozen until either pfm_restart() or + * task completes (non-blocking or notify_task gone). */ ctx->ctx_fl_frozen = 1; - DBprintk_ovfl(("return pmc0=0x%x must_block=%ld\n", - ctx->ctx_fl_frozen ? 0x1 : 0x0, t->pfm_ovfl_block_reset)); + DBprintk_ovfl(("return pmc0=0x%x must_block=%ld reason=%d\n", + ctx->ctx_fl_frozen ? 0x1 : 0x0, + t->pfm_ovfl_block_reset, + ctx->ctx_fl_trap_reason)); - return ctx->ctx_fl_frozen ? 0x1 : 0x0; + preempt_enable_no_resched(); + return 0x1UL; } static void @@ -3022,13 +3081,14 @@ struct task_struct *task; pfm_context_t *ctx; - pfm_stats[smp_processor_id()].pfm_ovfl_intr_count++; + pfm_stats[get_cpu()].pfm_ovfl_intr_count++; /* * if an alternate handler is registered, just bypass the default one */ if (pfm_alternate_intr_handler) { (*pfm_alternate_intr_handler->handler)(irq, arg, regs); + put_cpu(); return; } @@ -3053,6 +3113,7 @@ if (!ctx) { printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d has " "no PFM context\n", task->pid); + put_cpu(); return; } @@ -3060,17 +3121,25 @@ * assume PMC[0].fr = 1 at this point */ pmc0 = pfm_overflow_handler(task, ctx, pmc0, regs); - /* - * We always clear the overflow status bits and either unfreeze - * or keep the PMU frozen. + * we can only update pmc0 when the overflow + * is for the current context. In UP the current + * task may not be the one owning the PMU */ - ia64_set_pmc(0, pmc0); - ia64_srlz_d(); - + if (task == current) { + /* + * We always clear the overflow status bits and either unfreeze + * or keep the PMU frozen. + */ + ia64_set_pmc(0, pmc0); + ia64_srlz_d(); + } else { + task->thread.pmc[0] = pmc0; + } } else { pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++; } + put_cpu_no_resched(); } /* for debug only */ @@ -3141,6 +3210,7 @@ unsigned long dcr; unsigned long dcr_pp; + preempt_disable(); dcr_pp = info & PFM_CPUINFO_DCR_PP ? 1 : 0; /* @@ -3151,6 +3221,7 @@ regs = (struct pt_regs *)((unsigned long) task + IA64_STK_OFFSET); regs--; ia64_psr(regs)->pp = is_ctxswin ? dcr_pp : 0; + preempt_enable(); return; } /* @@ -3166,6 +3237,7 @@ ia64_set_dcr(dcr & ~IA64_DCR_PP); pfm_clear_psr_pp(); ia64_srlz_i(); + preempt_enable(); return; } /* @@ -3179,6 +3251,7 @@ pfm_set_psr_pp(); ia64_srlz_i(); } + preempt_enable(); } void @@ -3189,6 +3262,8 @@ u64 psr; int i; + preempt_disable(); + ctx = task->thread.pfm_context; @@ -3242,6 +3317,7 @@ */ atomic_set(&ctx->ctx_last_cpu, -1); #endif + preempt_enable(); } static void @@ -3252,6 +3328,7 @@ unsigned long mask; int i; + preempt_disable(); DBprintk(("on [%d] by [%d]\n", task->pid, current->pid)); t = &task->thread; @@ -3278,6 +3355,7 @@ /* not owned by this CPU */ atomic_set(&ctx->ctx_last_cpu, -1); + preempt_enable(); } void @@ -3290,11 +3368,14 @@ u64 psr; int i; + preempt_disable(); + owner = PMU_OWNER(); ctx = task->thread.pfm_context; t = &task->thread; if (ctx == NULL) { + preempt_enable(); printk("perfmon: pfm_load_regs: null ctx for [%d]\n", task->pid); return; } @@ -3333,7 +3414,7 @@ psr = ctx->ctx_saved_psr; pfm_set_psr_l(psr); - + preempt_enable(); return; } @@ -3373,16 +3454,20 @@ if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]); } + /* + * manually invoke core interrupt handler + * if the task had a pending overflow when it was ctxsw out. + * Side effect on ctx_fl_frozen is possible. + */ if (t->pmc[0] & ~0x1) { - pfm_overflow_handler(task, ctx, t->pmc[0], NULL); + t->pmc[0] = pfm_overflow_handler(task, ctx, t->pmc[0], NULL); } /* - * fl_frozen==1 when we are in blocking mode waiting for restart + * unfreeze PMU if possible */ - if (ctx->ctx_fl_frozen == 0) { - pfm_unfreeze_pmu(); - } + if (ctx->ctx_fl_frozen == 0) pfm_unfreeze_pmu(); + atomic_set(&ctx->ctx_last_cpu, smp_processor_id()); SET_PMU_OWNER(task); @@ -3391,6 +3476,7 @@ * restore the psr we changed in pfm_save_regs() */ psr = ctx->ctx_saved_psr; + preempt_enable(); pfm_set_psr_l(psr); } @@ -3408,6 +3494,7 @@ printk("perfmon: invalid task in pfm_reset_pmu()\n"); return; } + preempt_disable(); /* Let's make sure the PMU is frozen */ pfm_freeze_pmu(); @@ -3490,6 +3577,7 @@ ctx->ctx_used_dbrs[0] = 0UL; ia64_srlz_d(); + preempt_enable(); } /* @@ -3519,6 +3607,7 @@ */ if (ctx->ctx_flags.state == PFM_CTX_DISABLED) return; + preempt_disable(); /* * stop monitoring: * This is the only way to stop monitoring without destroying overflow @@ -3646,7 +3735,7 @@ * indicates that context has been saved */ atomic_set(&ctx->ctx_last_cpu, -1); - + preempt_enable(); } @@ -3669,6 +3758,7 @@ ctx = task->thread.pfm_context; thread = &task->thread; + preempt_disable(); /* * make sure child cannot mess up the monitoring session */ @@ -3723,6 +3813,8 @@ */ ia64_psr(regs)->up = 0; + preempt_enable(); + /* copy_thread() clears IA64_THREAD_PM_VALID */ return 0; } @@ -3770,8 +3862,9 @@ } } - nctx->ctx_fl_frozen = 0; - nctx->ctx_ovfl_regs[0] = 0UL; + nctx->ctx_fl_frozen = 0; + nctx->ctx_ovfl_regs[0] = 0UL; + nctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; atomic_set(&nctx->ctx_last_cpu, -1); /* @@ -3827,6 +3920,8 @@ thread->flags |= IA64_THREAD_PM_VALID; } + preempt_enable(); + return 0; } @@ -3848,6 +3943,7 @@ /* * check sampling buffer */ + preempt_disable(); if (ctx->ctx_psb) { pfm_smpl_buffer_desc_t *psb = ctx->ctx_psb; @@ -3940,6 +4036,7 @@ } UNLOCK_CTX(ctx); + preempt_enable(); pfm_unreserve_session(task, ctx->ctx_fl_system, 1UL << ctx->ctx_cpu); @@ -4118,17 +4215,27 @@ { int ret; + /* some sanity checks */ - if (hdl == NULL || hdl->handler == NULL) return -EINVAL; + if (hdl == NULL || hdl->handler == NULL) { + return -EINVAL; + } /* do the easy test first */ - if (pfm_alternate_intr_handler) return -EBUSY; + if (pfm_alternate_intr_handler) { + return -EBUSY; + } + preempt_disable(); /* reserve our session */ ret = pfm_reserve_session(NULL, 1, cpu_online_map); - if (ret) return ret; + if (ret) { + preempt_enable(); + return ret; + } if (pfm_alternate_intr_handler) { + preempt_enable(); printk(KERN_DEBUG "perfmon: install_alternate, intr_handler not NULL " "after reserve\n"); return -EINVAL; @@ -4136,17 +4243,21 @@ pfm_alternate_intr_handler = hdl; + preempt_enable(); return 0; } int pfm_remove_alternate_syswide_subsystem(pfm_intr_handler_desc_t *hdl) { - if (hdl == NULL) return -EINVAL; + if (hdl == NULL) + return -EINVAL; /* cannot remove someone else's handler! */ - if (pfm_alternate_intr_handler != hdl) return -EINVAL; + if (pfm_alternate_intr_handler != hdl) + return -EINVAL; + preempt_disable(); pfm_alternate_intr_handler = NULL; /* @@ -4154,6 +4265,8 @@ */ pfm_unreserve_session(NULL, 1, cpu_online_map); + preempt_enable(); + return 0; } @@ -4234,8 +4347,9 @@ pfm_init_percpu(void) { int i; + int me = get_cpu(); - if (smp_processor_id() == 0) + if (me == 0) register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction); ia64_set_pmv(IA64_PERFMON_VECTOR); @@ -4259,6 +4373,7 @@ if (PMD_IS_IMPL(i) == 0) continue; ia64_set_pmd(i, 0UL); } + put_cpu(); pfm_freeze_pmu(); } diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c --- a/arch/ia64/kernel/process.c Fri Jan 24 11:56:49 2003 +++ b/arch/ia64/kernel/process.c Thu Mar 6 21:11:46 2003 @@ -746,7 +746,7 @@ memcpy(tsk, orig, sizeof(struct task_struct) + sizeof(struct thread_info)); tsk->thread_info = (struct thread_info *) ((char *) tsk + IA64_TASK_SIZE); - atomic_set(&tsk->usage, 1); + atomic_set(&tsk->usage, 2); return tsk; } diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c --- a/arch/ia64/kernel/ptrace.c Tue Jan 14 21:57:29 2003 +++ b/arch/ia64/kernel/ptrace.c Thu Mar 6 14:56:33 2003 @@ -1,7 +1,7 @@ /* * Kernel support for the ptrace() and syscall tracing interfaces. * - * Copyright (C) 1999-2002 Hewlett-Packard Co + * Copyright (C) 1999-2003 Hewlett-Packard Co * David Mosberger-Tang * * Derived from the x86 and Alpha versions. Most of the code in here @@ -1235,19 +1235,12 @@ ret = 0; goto out_tsk; - case PTRACE_GETSIGINFO: - ret = -EIO; - if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t)) || !child->thread.siginfo) - goto out_tsk; - ret = copy_siginfo_to_user((siginfo_t *) data, child->thread.siginfo); + case PTRACE_OLD_GETSIGINFO: /* for backwards-compatibility */ + ret = ptrace_request(child, PTRACE_GETSIGINFO, addr, data); goto out_tsk; - case PTRACE_SETSIGINFO: - ret = -EIO; - if (!access_ok(VERIFY_READ, data, sizeof (siginfo_t)) - || child->thread.siginfo == 0) - goto out_tsk; - ret = copy_siginfo_from_user(child->thread.siginfo, (siginfo_t *) data); + case PTRACE_OLD_SETSIGINFO: /* for backwards-compatibility */ + ret = ptrace_request(child, PTRACE_SETSIGINFO, addr, data); goto out_tsk; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ @@ -1349,15 +1342,12 @@ * The 0x80 provides a way for the tracing parent to distinguish between a syscall * stop and SIGTRAP delivery. */ - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - set_current_state(TASK_STOPPED); - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + /* - * This isn't the same as continuing with a signal, but it - * will do for normal use. strace only continues with a - * signal if the stopping signal is not SIGTRAP. -brl + * This isn't the same as continuing with a signal, but it will do for normal use. + * strace only continues with a signal if the stopping signal is not SIGTRAP. + * -brl */ if (current->exit_code) { send_sig(current->exit_code, current, 1); diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c --- a/arch/ia64/kernel/setup.c Tue Feb 4 17:06:14 2003 +++ b/arch/ia64/kernel/setup.c Wed Feb 12 00:11:32 2003 @@ -363,7 +363,7 @@ #ifdef CONFIG_ACPI_BOOT /* Initialize the ACPI boot-time table parser */ - acpi_table_init(*cmdline_p); + acpi_table_init(); # ifdef CONFIG_ACPI_NUMA acpi_numa_init(); # endif @@ -422,7 +422,7 @@ cpu_init(); /* initialize the bootstrap CPU */ #ifdef CONFIG_ACPI_BOOT - acpi_boot_init(*cmdline_p); + acpi_boot_init(); #endif #ifdef CONFIG_SERIAL_HCDP if (efi.hcdp) { diff -Nru a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h --- a/arch/ia64/kernel/sigframe.h Fri Mar 8 18:11:39 2002 +++ b/arch/ia64/kernel/sigframe.h Mon Feb 10 18:28:00 2003 @@ -1,6 +1,6 @@ struct sigscratch { unsigned long scratch_unat; /* ar.unat for the general registers saved in pt */ - unsigned long pad; + unsigned long ar_pfs; /* for syscalls, the user-level function-state */ struct pt_regs pt; }; diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c --- a/arch/ia64/kernel/signal.c Tue Feb 11 04:25:29 2003 +++ b/arch/ia64/kernel/signal.c Thu Mar 6 11:40:52 2003 @@ -315,7 +315,7 @@ static long setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr) { - unsigned long flags = 0, ifs, nat; + unsigned long flags = 0, ifs, cfm, nat; long err; ifs = scr->pt.cr_ifs; @@ -325,7 +325,9 @@ if ((ifs & (1UL << 63)) == 0) { /* if cr_ifs isn't valid, we got here through a syscall */ flags |= IA64_SC_FLAG_IN_SYSCALL; - } + cfm = scr->ar_pfs & ((1UL << 38) - 1); + } else + cfm = ifs & ((1UL << 38) - 1); ia64_flush_fph(current); if ((current->thread.flags & IA64_THREAD_FPH_VALID)) { flags |= IA64_SC_FLAG_FPH_VALID; @@ -344,6 +346,7 @@ err |= __put_user(nat, &sc->sc_nat); err |= PUT_SIGSET(mask, &sc->sc_mask); + err |= __put_user(cfm, &sc->sc_cfm); err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um); err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc); err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); @@ -422,6 +425,15 @@ scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ scr->pt.cr_iip = tramp_addr; ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */ + /* + * Force the interruption function mask to zero. This has no effect when a + * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is + * ignored), but it has the desirable effect of making it possible to deliver a + * signal with an incomplete register frame (which happens when a mandatory RSE + * load faults). Furthermore, it has no negative effect on the getting the user's + * dirty partition preserved, because that's governed by scr->pt.loadrs. + */ + scr->pt.cr_ifs = (1UL << 63); /* * Note: this affects only the NaT bits of the scratch regs (the ones saved in @@ -522,7 +534,7 @@ if (signr <= 0) break; - ka = ¤t->sig->action[signr - 1]; + ka = ¤t->sighand->action[signr - 1]; if (restart) { switch (errno) { diff -Nru a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c --- a/arch/ia64/kernel/smp.c Sun Mar 2 18:13:32 2003 +++ b/arch/ia64/kernel/smp.c Thu Mar 6 11:40:52 2003 @@ -90,7 +90,7 @@ void handle_IPI (int irq, void *dev_id, struct pt_regs *regs) { - int this_cpu = smp_processor_id(); + int this_cpu = get_cpu(); unsigned long *pending_ipis = &__get_cpu_var(ipi_operation); unsigned long ops; @@ -146,8 +146,12 @@ } while (ops); mb(); /* Order data access and bit testing. */ } + put_cpu(); } +/* + * Called with preeemption disabled + */ static inline void send_IPI_single (int dest_cpu, int op) { @@ -155,6 +159,9 @@ platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0); } +/* + * Called with preeemption disabled + */ static inline void send_IPI_allbutself (int op) { @@ -166,6 +173,9 @@ } } +/* + * Called with preeemption disabled + */ static inline void send_IPI_all (int op) { @@ -176,12 +186,18 @@ send_IPI_single(i, op); } +/* + * Called with preeemption disabled + */ static inline void send_IPI_self (int op) { send_IPI_single(smp_processor_id(), op); } +/* + * Called with preeemption disabled + */ void smp_send_reschedule (int cpu) { @@ -197,12 +213,15 @@ smp_send_reschedule_all (void) { int i; + int cpu = get_cpu(); /* disable preemption */ for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i) && i != smp_processor_id()) + if (cpu_online(i) && i != cpu) smp_send_reschedule(i); + put_cpu(); } + void smp_flush_tlb_all (void) { @@ -247,9 +266,11 @@ { struct call_data_struct data; int cpus = 1; + int me = get_cpu(); /* prevent preemption and reschedule on another processor */ - if (cpuid == smp_processor_id()) { + if (cpuid == me) { printk("%s: trying to call self\n", __FUNCTION__); + put_cpu(); return -EBUSY; } @@ -276,6 +297,7 @@ call_data = NULL; spin_unlock_bh(&call_lock); + put_cpu(); return 0; } diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c --- a/arch/ia64/kernel/sys_ia64.c Mon Jan 27 11:04:16 2003 +++ b/arch/ia64/kernel/sys_ia64.c Wed Feb 26 06:03:08 2003 @@ -33,17 +33,8 @@ return -ENOMEM; #ifdef CONFIG_HUGETLB_PAGE -#define COLOR_HALIGN(addr) ((addr + HPAGE_SIZE - 1) & ~(HPAGE_SIZE - 1)) -#define TASK_HPAGE_BASE ((REGION_HPAGE << REGION_SHIFT) | HPAGE_SIZE) - if (filp && is_file_hugepages(filp)) { - if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE -1))) - addr = TASK_HPAGE_BASE; - addr = COLOR_HALIGN(addr); - } - else { - if (REGION_NUMBER(addr) == REGION_HPAGE) - addr = 0; - } + if (REGION_NUMBER(addr) == REGION_HPAGE) + addr = 0; #endif if (!addr) addr = TASK_UNMAPPED_BASE; diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c --- a/arch/ia64/kernel/time.c Mon Feb 24 23:13:09 2003 +++ b/arch/ia64/kernel/time.c Thu Mar 6 11:40:52 2003 @@ -25,7 +25,7 @@ #include extern unsigned long wall_jiffies; -extern unsigned long last_time_offset; +extern unsigned long last_nsec_offset; u64 jiffies_64 = INITIAL_JIFFIES; @@ -74,13 +74,13 @@ - (lost + 1)*cpu_data(time_keeper_id)->itm_delta); now = ia64_get_itc(); - if ((long) (now - last_tick) < 0) { + if (unlikely((long) (now - last_tick) < 0)) { printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n", smp_processor_id(), now, last_tick); - return last_time_offset; + return last_nsec_offset; } elapsed_cycles = now - last_tick; - return (elapsed_cycles*local_cpu_data->usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT; + return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT; } void @@ -115,30 +115,55 @@ void do_gettimeofday (struct timeval *tv) { - unsigned long seq, usec, sec, old; + unsigned long seq, nsec, usec, sec, old, offset; - do { + while (1) { seq = read_seqbegin(&xtime_lock); - usec = gettimeoffset(); - + { + old = last_nsec_offset; + offset = gettimeoffset(); + sec = xtime.tv_sec; + nsec = xtime.tv_nsec; + } + if (unlikely(read_seqretry(&xtime_lock, seq))) + continue; /* - * Ensure time never goes backwards, even when ITC on - * different CPUs are not perfectly synchronized. + * Ensure that for any pair of causally ordered gettimeofday() calls, time + * never goes backwards (even when ITC on different CPUs are not perfectly + * synchronized). (A pair of concurrent calls to gettimeofday() is by + * definition non-causal and hence it makes no sense to talk about + * time-continuity for such calls.) + * + * Doing this in a lock-free and race-free manner is tricky. Here is why + * it works (most of the time): read_seqretry() just succeeded, which + * implies we calculated a consistent (valid) value for "offset". If the + * cmpxchg() below succeeds, we further know that last_nsec_offset still + * has the same value as at the beginning of the loop, so there was + * presumably no timer-tick or other updates to last_nsec_offset in the + * meantime. This isn't 100% true though: there _is_ a possibility of a + * timer-tick occurring right right after read_seqretry() and then getting + * zero or more other readers which will set last_nsec_offset to the same + * value as the one we read at the beginning of the loop. If this + * happens, we'll end up returning a slightly newer time than we ought to + * (the jump forward is at most "offset" nano-seconds). There is no + * danger of causing time to go backwards, though, so we are safe in that + * sense. We could make the probability of this unlucky case occurring + * arbitrarily small by encoding a version number in last_nsec_offset, but + * even without versioning, the probability of this unlucky case should be + * so small that we won't worry about it. */ - do { - old = last_time_offset; - if (usec <= old) { - usec = old; - break; - } - } while (cmpxchg(&last_time_offset, old, usec) != old); - - sec = xtime.tv_sec; - usec += xtime.tv_nsec / 1000; - } while (read_seqend(&xtime_lock, seq)); + if (offset <= old) { + offset = old; + break; + } else if (likely(cmpxchg(&last_nsec_offset, old, offset) == old)) + break; + + /* someone else beat us to updating last_nsec_offset; try again */ + } + usec = (nsec + offset) / 1000; - while (usec >= 1000000) { + while (unlikely(usec >= 1000000)) { usec -= 1000000; ++sec; } @@ -278,7 +303,7 @@ local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den; local_cpu_data->itc_freq = itc_freq; local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000; - local_cpu_data->usec_per_cyc = ((1000000UL<nsec_per_cyc = ((1000000000UL<> 4) & 0xf) == 2) { /* NaT page consumption */ sig = SIGSEGV; code = SEGV_ACCERR; + addr = (void *) ifa; } else { /* register NaT consumption */ sig = SIGILL; code = ILL_ILLOPN; + addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); } siginfo.si_signo = sig; siginfo.si_code = code; siginfo.si_errno = 0; - siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + siginfo.si_addr = addr; siginfo.si_imm = vector; siginfo.si_flags = __ISR_VALID; siginfo.si_isr = isr; diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c --- a/arch/ia64/kernel/unwind.c Tue Feb 4 17:06:17 2003 +++ b/arch/ia64/kernel/unwind.c Thu Mar 6 21:11:46 2003 @@ -51,18 +51,24 @@ #define UNW_LOG_HASH_SIZE (UNW_LOG_CACHE_SIZE + 1) #define UNW_HASH_SIZE (1 << UNW_LOG_HASH_SIZE) -#define UNW_DEBUG 0 #define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */ -#if UNW_DEBUG - static long unw_debug_level = 255; -# define debug(level,format...) if (unw_debug_level > level) printk(format) -# define dprintk(format...) printk(format) -# define inline -#else -# define debug(level,format...) -# define dprintk(format...) -#endif +#ifdef UNW_DEBUG + static unsigned int unw_debug_level = UNW_DEBUG; +# ifdef CONFIG_KDB +# include +# define UNW_DEBUG_ON(n) (unw_debug_level >= n && !KDB_IS_RUNNING()) +# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__) +# else /* !CONFIG_KDB */ +# define UNW_DEBUG_ON(n) unw_debug_level >= n + /* Do not code a printk level, not all debug lines end in newline */ +# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__) +# endif /* CONFIG_KDB */ +# define inline +#else /* !UNW_DEBUG */ +# define UNW_DEBUG_ON(n) 0 +# define UNW_DPRINT(n, ...) +#endif /* UNW_DEBUG */ #if UNW_STATS # define STAT(x...) x @@ -111,7 +117,7 @@ /* script cache: */ struct unw_script cache[UNW_CACHE_SIZE]; -# if UNW_DEBUG +# ifdef UNW_DEBUG const char *preg_name[UNW_NUM_REGS]; # endif # if UNW_STATS @@ -190,7 +196,7 @@ struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8, }, .hash = { [0 ... UNW_HASH_SIZE - 1] = -1 }, -#if UNW_DEBUG +#ifdef UNW_DEBUG .preg_name = { "pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp", "r4", "r5", "r6", "r7", @@ -223,10 +229,22 @@ else if (reg <= 31) off = struct_offset(struct pt_regs, r16) + 8*(reg - 16); else - dprintk("unwind: bad scratch reg r%lu\n", reg); + UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg); return off; } +static inline struct pt_regs * +get_scratch_regs (struct unw_frame_info *info) +{ + if (!info->pt) { + /* This should not happen with valid unwind info. */ + UNW_DPRINT(0, "unwind.%s: bad unwind info: resetting info->pt\n", __FUNCTION__); + info->pt = info->sp - 16; + } + UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", __FUNCTION__, info->sp, info->pt); + return (struct pt_regs *) info->pt; +} + int unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write) { @@ -235,7 +253,8 @@ struct pt_regs *pt; if ((unsigned) regnum - 1 >= 127) { - dprintk("unwind: trying to access non-existent r%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n", + __FUNCTION__, regnum); return -1; } @@ -280,8 +299,9 @@ if ((unsigned long) addr < info->regstk.limit || (unsigned long) addr >= info->regstk.top) { - dprintk("unwind: %p outside of regstk " - "[0x%lx-0x%lx)\n", (void *) addr, + UNW_DPRINT(0, "unwind.%s: %p outside of regstk " + "[0x%lx-0x%lx)\n", + __FUNCTION__, (void *) addr, info->regstk.limit, info->regstk.top); return -1; @@ -298,11 +318,13 @@ } } else { /* access a scratch register */ - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; - addr = (unsigned long *) ((long) pt + pt_regs_off(regnum)); + if (!info->pt) { + UNW_DPRINT(0, "unwind.%s: no pt-regs; cannot access r%d\n", + __FUNCTION__, regnum); + return -1; + } + pt = get_scratch_regs(info); + addr = (unsigned long *) (pt + pt_regs_off(regnum)); if (info->pri_unat_loc) nat_addr = info->pri_unat_loc; else @@ -316,7 +338,8 @@ if ((unsigned long) addr < info->regstk.limit || (unsigned long) addr >= info->regstk.top) { - dprintk("unwind: ignoring attempt to access register outside of rbs\n"); + UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside " + "of rbs\n", __FUNCTION__); return -1; } if ((unsigned long) nat_addr >= info->regstk.top) @@ -348,10 +371,7 @@ unsigned long *addr; struct pt_regs *pt; - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; + pt = get_scratch_regs(info); switch (regnum) { /* scratch: */ case 0: addr = &pt->b0; break; @@ -366,7 +386,8 @@ break; default: - dprintk("unwind: trying to access non-existent b%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n", + __FUNCTION__, regnum); return -1; } if (write) @@ -383,14 +404,12 @@ struct pt_regs *pt; if ((unsigned) (regnum - 2) >= 126) { - dprintk("unwind: trying to access non-existent f%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n", + __FUNCTION__, regnum); return -1; } - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; + pt = get_scratch_regs(info); if (regnum <= 5) { addr = *(&info->f2_loc + (regnum - 2)); @@ -428,11 +447,7 @@ unsigned long *addr; struct pt_regs *pt; - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; - + pt = get_scratch_regs(info); switch (regnum) { case UNW_AR_BSP: addr = info->bsp_loc; @@ -495,7 +510,8 @@ break; default: - dprintk("unwind: trying to access non-existent ar%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n", + __FUNCTION__, regnum); return -1; } @@ -612,7 +628,7 @@ default: break; } - dprintk("unwind: bad abreg=0x%x\n", abreg); + UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __FUNCTION__, abreg); return UNW_REG_LC; } @@ -652,7 +668,7 @@ return; } } - dprintk("unwind: excess spill!\n"); + UNW_DPRINT(0, "unwind.%s: excess spill!\n", __FUNCTION__); } static inline void @@ -720,7 +736,7 @@ desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave, struct unw_state_record *sr) { - int i; + int i, region_start; if (!(sr->in_body || sr->first_region)) finish_prologue(sr); @@ -732,19 +748,20 @@ return; } + region_start = sr->region_start + sr->region_len; + for (i = 0; i < sr->epilogue_count; ++i) pop(sr); sr->epilogue_count = 0; sr->epilogue_start = UNW_WHEN_NEVER; - if (!body) - push(sr); - - sr->region_start += sr->region_len; + sr->region_start = region_start; sr->region_len = rlen; sr->in_body = body; if (!body) { + push(sr); + for (i = 0; i < 4; ++i) { if (mask & 0x8) set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR, @@ -765,10 +782,13 @@ static inline void desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr) { - if (abi == 0 && context == 'i') + if (abi == 0 && context == 'i') { sr->flags |= UNW_FLAG_INTERRUPT_FRAME; + UNW_DPRINT(3, "unwind.%s: interrupt frame\n", __FUNCTION__); + } else - dprintk("unwind: ignoring unwabi(abi=0x%x,context=0x%x)\n", abi, context); + UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n", + __FUNCTION__, abi, context); } static inline void @@ -1136,6 +1156,9 @@ unsigned short index; unsigned long ip, pr; + if (UNW_DEBUG_ON(0)) + return 0; /* Always regenerate scripts in debug mode */ + STAT(++unw.stat.cache.lookups); ip = info->ip; @@ -1260,8 +1283,8 @@ script_emit (struct unw_script *script, struct unw_insn insn) { if (script->count >= UNW_MAX_SCRIPT_LEN) { - dprintk("unwind: script exceeds maximum size of %u instructions!\n", - UNW_MAX_SCRIPT_LEN); + UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n", + __FUNCTION__, UNW_MAX_SCRIPT_LEN); return; } script->insn[script->count++] = insn; @@ -1302,7 +1325,8 @@ break; default: - dprintk("unwind: don't know how to emit nat info for where = %u\n", r->where); + UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n", + __FUNCTION__, r->where); return; } insn.opc = opc; @@ -1339,8 +1363,9 @@ } val = unw.preg_index[UNW_REG_R4 + (rval - 4)]; } else { - opc = UNW_INSN_ADD_SP; - val = -sizeof(struct pt_regs) + pt_regs_off(rval); + /* register got spilled to a scratch register */ + opc = UNW_INSN_MOVE_SCRATCH; + val = pt_regs_off(rval); } break; @@ -1350,12 +1375,12 @@ else if (rval >= 16 && rval <= 31) val = unw.preg_index[UNW_REG_F16 + (rval - 16)]; else { - opc = UNW_INSN_ADD_SP; - val = -sizeof(struct pt_regs); + opc = UNW_INSN_MOVE_SCRATCH; if (rval <= 9) - val += struct_offset(struct pt_regs, f6) + 16*(rval - 6); + val = struct_offset(struct pt_regs, f6) + 16*(rval - 6); else - dprintk("unwind: kernel may not touch f%lu\n", rval); + UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n", + __FUNCTION__, rval); } break; @@ -1363,14 +1388,13 @@ if (rval >= 1 && rval <= 5) val = unw.preg_index[UNW_REG_B1 + (rval - 1)]; else { - opc = UNW_INSN_ADD_SP; - val = -sizeof(struct pt_regs); + opc = UNW_INSN_MOVE_SCRATCH; if (rval == 0) - val += struct_offset(struct pt_regs, b0); + val = struct_offset(struct pt_regs, b0); else if (rval == 6) - val += struct_offset(struct pt_regs, b6); + val = struct_offset(struct pt_regs, b6); else - val += struct_offset(struct pt_regs, b7); + val = struct_offset(struct pt_regs, b7); } break; @@ -1383,7 +1407,8 @@ break; default: - dprintk("unwind: register %u has unexpected `where' value of %u\n", i, r->where); + UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n", + __FUNCTION__, i, r->where); break; } insn.opc = opc; @@ -1456,9 +1481,10 @@ r->when = UNW_WHEN_NEVER; sr.pr_val = info->pr; + UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __FUNCTION__, ip); script = script_new(ip); if (!script) { - dprintk("unwind: failed to create unwind script\n"); + UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n", __FUNCTION__); STAT(unw.stat.script.build_time += ia64_get_itc() - start); return 0; } @@ -1476,8 +1502,8 @@ } if (!e) { /* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */ - dprintk("unwind: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", ip, - unw.cache[info->prev_script].ip); + UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", + __FUNCTION__, ip, unw.cache[info->prev_script].ip); sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; sr.curr.reg[UNW_REG_RP].when = -1; sr.curr.reg[UNW_REG_RP].val = 0; @@ -1525,26 +1551,32 @@ sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; sr.curr.reg[UNW_REG_RP].when = -1; sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg; + UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n", + __FUNCTION__, ip, sr.curr.reg[UNW_REG_RP].where, + sr.curr.reg[UNW_REG_RP].val); } -#if UNW_DEBUG - printk("unwind: state record for func 0x%lx, t=%u:\n", - table->segment_base + e->start_offset, sr.when_target); +#ifdef UNW_DEBUG + UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n", + __FUNCTION__, table->segment_base + e->start_offset, sr.when_target); for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) { if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) { - printk(" %s <- ", unw.preg_name[r - sr.curr.reg]); + UNW_DPRINT(1, " %s <- ", unw.preg_name[r - sr.curr.reg]); switch (r->where) { - case UNW_WHERE_GR: printk("r%lu", r->val); break; - case UNW_WHERE_FR: printk("f%lu", r->val); break; - case UNW_WHERE_BR: printk("b%lu", r->val); break; - case UNW_WHERE_SPREL: printk("[sp+0x%lx]", r->val); break; - case UNW_WHERE_PSPREL: printk("[psp+0x%lx]", r->val); break; + case UNW_WHERE_GR: UNW_DPRINT(1, "r%lu", r->val); break; + case UNW_WHERE_FR: UNW_DPRINT(1, "f%lu", r->val); break; + case UNW_WHERE_BR: UNW_DPRINT(1, "b%lu", r->val); break; + case UNW_WHERE_SPREL: UNW_DPRINT(1, "[sp+0x%lx]", r->val); break; + case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break; case UNW_WHERE_NONE: - printk("%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val); + UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val); + break; + + default: + UNW_DPRINT(1, "BADWHERE(%d)", r->where); break; - default: printk("BADWHERE(%d)", r->where); break; } - printk("\t\t%d\n", r->when); + UNW_DPRINT(1, "\t\t%d\n", r->when); } } #endif @@ -1642,6 +1674,16 @@ s[dst] = s[val]; break; + case UNW_INSN_MOVE_SCRATCH: + if (state->pt) { + s[dst] = (unsigned long) get_scratch_regs(state) + val; + } else { + s[dst] = 0; + UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n", + __FUNCTION__, dst, val); + } + break; + case UNW_INSN_MOVE_STACKED: s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp, val); @@ -1667,11 +1709,12 @@ break; case UNW_INSN_LOAD: -#if UNW_DEBUG +#ifdef UNW_DEBUG if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0 || s[val] < TASK_SIZE) { - debug(1, "unwind: rejecting bad psp=0x%lx\n", s[val]); + UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n", + __FUNCTION__, s[val]); break; } #endif @@ -1704,7 +1747,8 @@ if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) { /* don't let obviously bad addresses pollute the cache */ - debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip); + /* FIXME: should really be level 0 but it occurs too often. KAO */ + UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip); info->rp_loc = 0; return -1; } @@ -1713,8 +1757,9 @@ if (!scr) { scr = build_script(info); if (!scr) { - dprintk("unwind: failed to locate/build unwind script for ip %lx\n", - info->ip); + UNW_DPRINT(0, + "unwind.%s: failed to locate/build unwind script for ip %lx\n", + __FUNCTION__, info->ip); return -1; } have_write_lock = 1; @@ -1747,7 +1792,9 @@ /* restore the ip */ if (!info->rp_loc) { - debug(1, "unwind: failed to locate return link (ip=0x%lx)!\n", info->ip); + /* FIXME: should really be level 0 but it occurs too often. KAO */ + UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n", + __FUNCTION__, info->ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1757,14 +1804,14 @@ * We don't have unwind info for the gate page, so we consider that part * of user-space for the purpose of unwinding. */ - debug(1, "unwind: reached user-space (ip=0x%lx)\n", ip); + UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } /* restore the cfm: */ if (!info->pfs_loc) { - dprintk("unwind: failed to locate ar.pfs!\n"); + UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1774,16 +1821,18 @@ pr = info->pr; num_regs = 0; if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) { + info->pt = info->sp + 16; if ((pr & (1UL << pNonSys)) != 0) num_regs = *info->cfm_loc & 0x7f; /* size of frame */ info->pfs_loc = - (unsigned long *) (info->sp + 16 + struct_offset(struct pt_regs, ar_pfs)); + (unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs)); + UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt); } else num_regs = (*info->cfm_loc >> 7) & 0x7f; /* size of locals */ info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs); if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) { - dprintk("unwind: bsp (0x%lx) out of range [0x%lx-0x%lx]\n", - info->bsp, info->regstk.limit, info->regstk.top); + UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n", + __FUNCTION__, info->bsp, info->regstk.limit, info->regstk.top); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1791,14 +1840,15 @@ /* restore the sp: */ info->sp = info->psp; if (info->sp < info->memstk.top || info->sp > info->memstk.limit) { - dprintk("unwind: sp (0x%lx) out of range [0x%lx-0x%lx]\n", - info->sp, info->memstk.top, info->memstk.limit); + UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n", + __FUNCTION__, info->sp, info->memstk.top, info->memstk.limit); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) { - dprintk("unwind: ip, sp, bsp remain unchanged; stopping here (ip=0x%lx)\n", ip); + UNW_DPRINT(0, "unwind.%s: ip, sp, bsp unchanged; stopping here (ip=0x%lx)\n", + __FUNCTION__, ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1822,7 +1872,8 @@ while (unw_unwind(info) >= 0) { if (unw_get_rp(info, &ip) < 0) { unw_get_ip(info, &ip); - dprintk("unwind: failed to read return pointer (ip=0x%lx)\n", ip); + UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n", + __FUNCTION__, ip); return -1; } /* @@ -1833,7 +1884,7 @@ return 0; } unw_get_ip(info, &ip); - dprintk("unwind: failed to unwind to user-level (ip=0x%lx)\n", ip); + UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip); return -1; } @@ -1874,11 +1925,30 @@ info->task = t; info->sw = sw; info->sp = info->psp = (unsigned long) (sw + 1) - 16; + info->pt = 0; info->cfm_loc = &sw->ar_pfs; sol = (*info->cfm_loc >> 7) & 0x7f; info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol); info->ip = sw->b0; info->pr = sw->pr; + UNW_DPRINT(3, + "unwind.%s\n" + " rbslimit 0x%lx\n" + " rbstop 0x%lx\n" + " stklimit 0x%lx\n" + " stktop 0x%lx\n" + " task 0x%lx\n" + " sw 0x%lx\n", + __FUNCTION__, rbslimit, rbstop, stklimit, stktop, + (unsigned long)(info->task), + (unsigned long)(info->sw)); + UNW_DPRINT(3, + " sp/psp 0x%lx\n" + " sol 0x%lx\n" + " bsp 0x%lx\n" + " ip 0x%lx\n" + " pr 0x%lx\n", + info->sp, sol, info->bsp, info->ip, info->pr); find_save_locs(info); STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); @@ -1889,6 +1959,7 @@ { struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16); + UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__); unw_init_frame_info(info, t, sw); } @@ -1916,7 +1987,8 @@ unsigned long flags; if (end - start <= 0) { - dprintk("unwind: ignoring attempt to insert empty unwind table\n"); + UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n", + __FUNCTION__); return 0; } @@ -1946,13 +2018,15 @@ long index; if (!handle) { - dprintk("unwind: ignoring attempt to remove non-existent unwind table\n"); + UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n", + __FUNCTION__); return; } table = handle; if (table == &unw.kernel_table) { - dprintk("unwind: sorry, freeing the kernel's unwind table is a no-can-do!\n"); + UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a " + "no-can-do!\n", __FUNCTION__); return; } @@ -1964,7 +2038,8 @@ if (prev->next == table) break; if (!prev) { - dprintk("unwind: failed to find unwind table %p\n", (void *) table); + UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n", + __FUNCTION__, (void *) table); spin_unlock_irqrestore(&unw.lock, flags); return; } diff -Nru a/arch/ia64/kernel/unwind_i.h b/arch/ia64/kernel/unwind_i.h --- a/arch/ia64/kernel/unwind_i.h Tue Apr 2 10:57:30 2002 +++ b/arch/ia64/kernel/unwind_i.h Mon Mar 3 16:00:00 2003 @@ -137,7 +137,8 @@ UNW_INSN_SETNAT_MEMSTK, /* s[dst+1].nat.type = MEMSTK; s[dst+1].nat.off = *s.pri_unat - s[dst] */ UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */ - UNW_INSN_LOAD /* s[dst] = *s[val] */ + UNW_INSN_LOAD, /* s[dst] = *s[val] */ + UNW_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */ }; struct unw_insn { diff -Nru a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c --- a/arch/ia64/mm/fault.c Tue Feb 4 17:06:20 2003 +++ b/arch/ia64/mm/fault.c Thu Feb 13 05:43:47 2003 @@ -55,7 +55,7 @@ /* * If we're in an interrupt or have no user context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); @@ -79,7 +79,7 @@ # if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \ || (1 << VM_EXEC_BIT) != VM_EXEC) -# error File is out of sync with . Pleaes update. +# error File is out of sync with . Please update. # endif mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT) diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c --- a/arch/ia64/mm/hugetlbpage.c Mon Feb 24 23:13:11 2003 +++ b/arch/ia64/mm/hugetlbpage.c Thu Mar 6 13:34:27 2003 @@ -19,6 +19,8 @@ #include +#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT) + static long htlbpagemem; int htlbpage_max; static long htlbzone_pages; @@ -98,7 +100,6 @@ set_pte(page_table, entry); return; } - /* * This function checks for proper alignment of input addr and len parameters. */ @@ -108,6 +109,20 @@ return -EINVAL; if (addr & ~HPAGE_MASK) return -EINVAL; + if (REGION_NUMBER(addr) != REGION_HPAGE) + return -EINVAL; + + return 0; +} +/* This function checks if the address and address+len falls out of HugeTLB region. It + * return -EINVAL if any part of address range falls in HugeTLB region. + */ +int is_invalid_hugepage_range(unsigned long addr, unsigned long len) +{ + if (REGION_NUMBER(addr) == REGION_HPAGE) + return -EINVAL; + if (REGION_NUMBER(addr+len) == REGION_HPAGE) + return -EINVAL; return 0; } @@ -173,6 +188,39 @@ return i; } +struct vm_area_struct *hugepage_vma(struct mm_struct *mm, unsigned long addr) +{ + if (mm->used_hugetlb) { + if (REGION_NUMBER(addr) == REGION_HPAGE) { + struct vm_area_struct *vma = find_vma(mm, addr); + if (vma && is_vm_hugetlb_page(vma)) + return vma; + } + } + return NULL; +} + +struct page *follow_huge_addr(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, int write) +{ + struct page *page; + pte_t *ptep; + + ptep = huge_pte_offset(mm, addr); + page = pte_page(*ptep); + page += ((addr & ~HPAGE_MASK) >> PAGE_SHIFT); + get_page(page); + return page; +} +int pmd_huge(pmd_t pmd) +{ + return 0; +} +struct page * +follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write) +{ + return NULL; +} + void free_huge_page(struct page *page) { BUG_ON(page_count(page)); @@ -204,8 +252,6 @@ BUG_ON(start & (HPAGE_SIZE - 1)); BUG_ON(end & (HPAGE_SIZE - 1)); - spin_lock(&htlbpage_lock); - spin_unlock(&htlbpage_lock); for (address = start; address < end; address += HPAGE_SIZE) { pte = huge_pte_offset(mm, address); if (pte_none(*pte)) @@ -257,8 +303,12 @@ ret = -ENOMEM; goto out; } - add_to_page_cache(page, mapping, idx, GFP_ATOMIC); + ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); unlock_page(page); + if (ret) { + free_huge_page(page); + goto out; + } } set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE); } @@ -267,6 +317,29 @@ return ret; } +unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags) +{ + struct vm_area_struct *vmm; + + if (len > RGN_MAP_LIMIT) + return -ENOMEM; + if (len & ~HPAGE_MASK) + return -EINVAL; + /* This code assumes that REGION_HPAGE != 0. */ + if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1))) + addr = TASK_HPAGE_BASE; + else + addr = ALIGN(addr, HPAGE_SIZE); + for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { + /* At this point: (!vmm || addr < vmm->vm_end). */ + if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT) + return -ENOMEM; + if (!vmm || (addr + len) <= vmm->vm_start) + return addr; + addr = ALIGN(vmm->vm_end, HPAGE_SIZE); + } +} void update_and_free_page(struct page *page) { int j; @@ -302,8 +375,8 @@ break; } page = list_entry(p, struct page, list); - if ((page_zone(page))->name[0] != 'H') // Look for non-Highmem - map = page; + if (!PageHighMem(page)) + map = page; } if (map) { list_del(&map->list); @@ -317,8 +390,8 @@ int set_hugetlb_mem_size(int count) { - int j, lcount; - struct page *page, *map; + int lcount; + struct page *page ; extern long htlbzone_pages; extern struct list_head htlbpage_freelist; @@ -417,5 +490,4 @@ struct vm_operations_struct hugetlb_vm_ops = { .nopage = hugetlb_nopage, - .close = zap_hugetlb_resources, }; diff -Nru a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c --- a/arch/ia64/mm/tlb.c Wed Nov 13 17:57:34 2002 +++ b/arch/ia64/mm/tlb.c Thu Jan 30 06:14:13 2003 @@ -81,9 +81,13 @@ } read_unlock(&tasklist_lock); /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */ - for (i = 0; i < NR_CPUS; ++i) - if (i != smp_processor_id()) - per_cpu(ia64_need_tlb_flush, i) = 1; + { + int cpu = get_cpu(); /* prevent preemption/migration */ + for (i = 0; i < NR_CPUS; ++i) + if (i != cpu) + per_cpu(ia64_need_tlb_flush, i) = 1; + put_cpu(); + } local_flush_tlb_all(); } diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Tue Nov 5 07:08:17 2002 +++ b/arch/ia64/pci/pci.c Tue Mar 4 18:40:15 2003 @@ -272,3 +272,76 @@ return 0; } + +/** + * pci_cacheline_size - determine cacheline size for PCI devices + * @dev: void + * + * We want to use the line-size of the outer-most cache. We assume + * that this line-size is the same for all CPUs. + * + * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info(). + * + * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. + */ +static unsigned long +pci_cacheline_size (void) +{ + u64 levels, unique_caches; + s64 status; + pal_cache_config_info_t cci; + static u8 cacheline_size; + + if (cacheline_size) + return cacheline_size; + + status = ia64_pal_cache_summary(&levels, &unique_caches); + if (status != 0) { + printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", + __FUNCTION__, status); + return SMP_CACHE_BYTES; + } + + status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2, + &cci); + if (status != 0) { + printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n", + __FUNCTION__, status); + return SMP_CACHE_BYTES; + } + cacheline_size = 1 << cci.pcci_line_size; + return cacheline_size; +} + +/** + * pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi() + * @dev: the PCI device for which MWI is enabled + * + * For ia64, we can get the cacheline sizes from PAL. + * + * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. + */ +int +pcibios_prep_mwi (struct pci_dev *dev) +{ + unsigned long desired_linesize, current_linesize; + int rc = 0; + u8 pci_linesize; + + desired_linesize = pci_cacheline_size(); + + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize); + current_linesize = 4 * pci_linesize; + if (desired_linesize != current_linesize) { + printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,", + dev->slot_name, current_linesize); + if (current_linesize > desired_linesize) { + printk(" expected %lu bytes instead\n", desired_linesize); + rc = -EINVAL; + } else { + printk(" correcting to %lu\n", desired_linesize); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4); + } + } + return rc; +} diff -Nru a/arch/ia64/sn/io/Makefile b/arch/ia64/sn/io/Makefile --- a/arch/ia64/sn/io/Makefile Mon Feb 3 14:19:35 2003 +++ b/arch/ia64/sn/io/Makefile Mon Feb 24 04:55:04 2003 @@ -17,6 +17,6 @@ hcl.o labelcl.o invent.o sgi_io_sim.o \ klgraph_hack.o hcl_util.o cdl.o hubdev.o hubspc.o \ alenlist.o pci.o pci_dma.o ate_utils.o \ - ifconfig_net.o io.o ifconfig_bus.o + ifconfig_net.o io.o ioconfig_bus.o obj-$(CONFIG_PCIBA) += pciba.o diff -Nru a/arch/ia64/sn/io/ioconfig_bus.c b/arch/ia64/sn/io/ioconfig_bus.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/ioconfig_bus.c Mon Feb 24 04:55:13 2003 @@ -0,0 +1,402 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * ioconfig_bus - SGI's Persistent PCI Bus Numbering. + * + * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING" +#define SGI_IOCONFIG_BUS_VERSION "1.0" + +/* + * Some Global definitions. + */ +devfs_handle_t ioconfig_bus_handle = NULL; +unsigned long ioconfig_bus_debug = 0; + +#ifdef IOCONFIG_BUS_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +u64 ioconfig_file = 0; +u64 ioconfig_file_size = 0; +u64 ioconfig_activated = 0; +char ioconfig_kernopts[128]; + +/* + * For debugging purpose .. hardcode a table .. + */ +struct ascii_moduleid *ioconfig_bus_table; +u64 ioconfig_bus_table_size = 0; + + +int free_entry = 0; +int new_entry = 0; + +int next_basebus_number = 0; + +void +ioconfig_get_busnum(char *io_moduleid, int *bus_num) +{ + struct ascii_moduleid *temp; + int index; + + DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid); + + *bus_num = -1; + temp = ioconfig_bus_table; + for (index = 0; index < free_entry; temp++, index++) { + if ( (io_moduleid[0] == temp->io_moduleid[0]) && + (io_moduleid[1] == temp->io_moduleid[1]) && + (io_moduleid[2] == temp->io_moduleid[2]) && + (io_moduleid[4] == temp->io_moduleid[4]) && + (io_moduleid[5] == temp->io_moduleid[5]) ) { + *bus_num = index * 0x10; + return; + } + } + + /* + * New IO Brick encountered. + */ + if (((int)io_moduleid[0]) == 0) { + DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid); + return; + } + + io_moduleid[3] = '#'; + strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid); + *bus_num = free_entry * 0x10; + free_entry++; +} + +void +dump_ioconfig_table() +{ + + int index = 0; + struct ascii_moduleid *temp; + + temp = ioconfig_bus_table; + while (index < free_entry) { + DBG("ASSCI Module ID %s\n", temp->io_moduleid); + temp++; + index++; + } +} + +/* + * nextline + * This routine returns the nextline in the buffer. + */ +int nextline(char *buffer, char **next, char *line) +{ + + char *temp; + + if (buffer[0] == 0x0) { + return(0); + } + + temp = buffer; + while (*temp != 0) { + *line = *temp; + if (*temp != '\n'){ + *line = *temp; + temp++; line++; + } else + break; + } + + if (*temp == 0) + *next = temp; + else + *next = ++temp; + + return(1); +} + +/* + * build_pcibus_name + * This routine parses the ioconfig contents read into + * memory by ioconfig command in EFI and builds the + * persistent pci bus naming table. + */ +void +build_moduleid_table(char *file_contents, struct ascii_moduleid *table) +{ + /* + * Read the whole file into memory. + */ + int rc; + char *name; + char *temp; + char *next; + char *current; + char *line; + struct ascii_moduleid *moduleid; + + line = kmalloc(256, GFP_KERNEL); + memset(line, 0,256); + name = kmalloc(125, GFP_KERNEL); + memset(name, 0, 125); + moduleid = table; + current = file_contents; + while (nextline(current, &next, line)){ + + DBG("current 0x%lx next 0x%lx\n", current, next); + + temp = line; + /* + * Skip all leading Blank lines .. + */ + while (isspace(*temp)) + if (*temp != '\n') + temp++; + else + break; + + if (*temp == '\n') { + current = next; + memset(line, 0, 256); + continue; + } + + /* + * Skip comment lines + */ + if (*temp == '#') { + current = next; + memset(line, 0, 256); + continue; + } + + /* + * Get the next free entry in the table. + */ + rc = sscanf(temp, "%s", name); + strcpy(&moduleid->io_moduleid[0], name); + DBG("Found %s\n", name); + moduleid++; + free_entry++; + current = next; + memset(line, 0, 256); + } + + new_entry = free_entry; + kfree(line); + kfree(name); + + return; +} + +void +ioconfig_bus_init(void) +{ + + struct ia64_sal_retval ret_stuff; + u64 *temp; + int cnode; + + DBG("ioconfig_bus_init called.\n"); + + for (cnode = 0; cnode < numnodes; cnode++) { + nasid_t nasid; + /* + * Make SAL call to get the address of the bus configuration table. + */ + ret_stuff.status = (uint64_t)0; + ret_stuff.v0 = (uint64_t)0; + ret_stuff.v1 = (uint64_t)0; + ret_stuff.v2 = (uint64_t)0; + nasid = COMPACT_TO_NASID_NODEID(cnode); + SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, nasid, 0, 0, 0, 0, 0); + temp = (u64 *)TO_NODE_CAC(nasid, ret_stuff.v0); + ioconfig_file = *temp; + DBG("ioconfig_bus_init: Nasid %d ret_stuff.v0 0x%lx\n", nasid, + ret_stuff.v0); + if (ioconfig_file) { + ioconfig_file_size = ret_stuff.v1; + ioconfig_file = (ioconfig_file | CACHEABLE_MEM_SPACE); + ioconfig_activated = 1; + break; + } + } + + DBG("ioconfig_bus_init: ret_stuff.v0 %p ioconfig_file %p %d\n", + ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size); + + ioconfig_bus_table = kmalloc( 512, GFP_KERNEL ); + memset(ioconfig_bus_table, 0, 512); + + /* + * If ioconfig options are given on the bootline .. take it. + */ + if (*ioconfig_kernopts != '\0') { + /* + * ioconfig="..." kernel options given. + */ + DBG("ioconfig_bus_init: Kernel Options given.\n"); + (void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table); + (void) dump_ioconfig_table(ioconfig_bus_table); + return; + } + + if (ioconfig_activated) { + DBG("ioconfig_bus_init: ioconfig file given.\n"); + (void) build_moduleid_table((char *)ioconfig_file, ioconfig_bus_table); + (void) dump_ioconfig_table(ioconfig_bus_table); + } else { + DBG("ioconfig_bus_init: ioconfig command not executed in prom\n"); + } + +} + +void +ioconfig_bus_new_entries(void) +{ + + + int index = 0; + struct ascii_moduleid *temp; + + if ((ioconfig_activated) && (free_entry > new_entry)) { + printk("### Please add the following new IO Bricks Module ID \n"); + printk("### to your Persistent Bus Numbering Config File\n"); + } else + return; + + index = new_entry; + temp = &ioconfig_bus_table[index]; + while (index < free_entry) { + printk("%s\n", temp); + temp++; + index++; + } + printk("### End\n"); + +} +static int ioconfig_bus_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + + struct ioconfig_parm parm; + + /* + * Copy in the parameters. + */ + copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm)); + parm.number = free_entry - new_entry; + parm.ioconfig_activated = ioconfig_activated; + copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm)); + copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct ascii_moduleid) * (free_entry - new_entry)); + + return 0; +} + +/* + * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus". + */ +static int ioconfig_bus_open(struct inode * inode, struct file * filp) +{ + if (ioconfig_bus_debug) { + DBG("ioconfig_bus_open called.\n"); + } + + return(0); + +} + +/* + * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus". + */ +static int ioconfig_bus_close(struct inode * inode, struct file * filp) +{ + + if (ioconfig_bus_debug) { + DBG("ioconfig_bus_close called.\n"); + } + + return(0); +} + +struct file_operations ioconfig_bus_fops = { + ioctl:ioconfig_bus_ioctl, + open:ioconfig_bus_open, /* open */ + release:ioconfig_bus_close /* release */ +}; + + +/* + * init_ifconfig_bus() - Boot time initialization. Ensure that it is called + * after devfs has been initialized. + * + */ +int init_ioconfig_bus(void) +{ + ioconfig_bus_handle = NULL; + ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus", + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + &ioconfig_bus_fops, NULL); + + if (ioconfig_bus_handle == NULL) { + panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n"); + } + + return(0); + +} + +static int __init ioconfig_bus_setup (char *str) +{ + + char *temp; + + DBG("ioconfig_bus_setup: Kernel Options %s\n", str); + + temp = (char *)ioconfig_kernopts; + memset(temp, 0, 128); + while ( (*str != '\0') && !isspace (*str) ) { + if (*str == ',') { + *temp = '\n'; + temp++; + str++; + continue; + } + *temp = *str; + temp++; + str++; + } + + return(0); + +} +__setup("ioconfig=", ioconfig_bus_setup); diff -Nru a/arch/ia64/sn/io/sn2/Makefile b/arch/ia64/sn/io/sn2/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/Makefile Mon Feb 24 05:40:29 2003 @@ -0,0 +1,19 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. +# +# Makefile for the sn2 specific io routines. + +EXTRA_CFLAGS := -DLITTLE_ENDIAN + +obj-y += bte_error.o geo_op.o klconflib.o klgraph.o l1.o \ + l1_command.o ml_iograph.o ml_SN_init.o ml_SN_intr.o module.o \ + pci_bus_cvlink.o pciio.o pic.o sgi_io_init.o shub.o shuberror.o \ + shub_intr.o shubio.o xbow.o xtalk.o + +obj-$(CONFIG_KDB) += kdba_io.o + +obj-$(CONFIG_SHUB_1_0_SPECIFIC) += efi-rtc.o diff -Nru a/arch/ia64/sn/io/sn2/geo_op.c b/arch/ia64/sn/io/sn2/geo_op.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/geo_op.c Mon Feb 24 05:23:08 2003 @@ -0,0 +1,314 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +/* + * @doc file m:hwcfg + * DESCRIPTION: + * + * This file contains routines for manipulating and generating + * Geographic IDs. They are in a file by themself since they have + * no dependencies on other modules. + * + * ORIGIN: + * + * New for SN2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/********** Global functions and data (visible outside the module) ***********/ + +/* + * @doc gf:geo_module + * + * moduleid_t geo_module(geoid_t g) + * + * DESCRIPTION: + * + * Return the moduleid component of a geoid. + * + * INTERNALS: + * + * Return INVALID_MODULE for an invalid geoid. Otherwise extract the + * moduleid from the structure, and return it. + * + * ORIGIN: + * + * New for SN2 + */ + +moduleid_t +geo_module(geoid_t g) +{ + if (g.any.type == GEO_TYPE_INVALID) + return INVALID_MODULE; + else + return g.any.module; +} + + +/* + * @doc gf:geo_slab + * + * slabid_t geo_slab(geoid_t g) + * + * DESCRIPTION: + * + * Return the slabid component of a geoid. + * + * INTERNALS: + * + * Return INVALID_SLAB for an invalid geoid. Otherwise extract the + * slabid from the structure, and return it. + * + * ORIGIN: + * + * New for SN2 + */ + +slabid_t +geo_slab(geoid_t g) +{ + if (g.any.type == GEO_TYPE_INVALID) + return INVALID_SLAB; + else + return g.any.slab; +} + + +/* + * @doc gf:geo_type + * + * geo_type_t geo_type(geoid_t g) + * + * DESCRIPTION: + * + * Return the type component of a geoid. + * + * INTERNALS: + * + * Extract the type from the structure, and return it. + * + * ORIGIN: + * + * New for SN2 + */ + +geo_type_t +geo_type(geoid_t g) +{ + return g.any.type; +} + + +/* + * @doc gf:geo_valid + * + * int geo_valid(geoid_t g) + * + * DESCRIPTION: + * + * Return nonzero if g has a valid geoid type. + * + * INTERNALS: + * + * Test the type against GEO_TYPE_INVALID, and return the result. + * + * ORIGIN: + * + * New for SN2 + */ + +int +geo_valid(geoid_t g) +{ + return g.any.type != GEO_TYPE_INVALID; +} + + +/* + * @doc gf:geo_cmp + * + * int geo_cmp(geoid_t g0, geoid_t g1) + * + * DESCRIPTION: + * + * Compare two geoid_t values, from the coarsest field to the finest. + * The comparison should be consistent with the physical locations of + * of the hardware named by the geoids. + * + * INTERNALS: + * + * First compare the module, then the slab, type, and type-specific fields. + * + * ORIGIN: + * + * New for SN2 + */ + +int +geo_cmp(geoid_t g0, geoid_t g1) +{ + int rv; + + /* Compare the common fields */ + rv = MODULE_CMP(geo_module(g0), geo_module(g1)); + if (rv != 0) + return rv; + + rv = geo_slab(g0) - geo_slab(g1); + if (rv != 0) + return rv; + + /* Within a slab, sort by type */ + rv = geo_type(g0) - geo_type(g1); + if (rv != 0) + return rv; + + switch(geo_type(g0)) { + case GEO_TYPE_CPU: + rv = g0.cpu.slice - g1.cpu.slice; + break; + + case GEO_TYPE_IOCARD: + rv = g0.pcicard.bus - g1.pcicard.bus; + if (rv) break; + rv = SLOTNUM_GETSLOT(g0.pcicard.slot) - + SLOTNUM_GETSLOT(g1.pcicard.slot); + break; + + case GEO_TYPE_MEM: + rv = g0.mem.membus - g1.mem.membus; + if (rv) break; + rv = g0.mem.memslot - g1.mem.memslot; + break; + + default: + rv = 0; + } + + return rv; +} + + +/* + * @doc gf:geo_new + * + * geoid_t geo_new(geo_type_t type, ...) + * + * DESCRIPTION: + * + * Generate a new geoid_t value of the given type from its components. + * Expected calling sequences: + * \@itemize \@bullet + * \@item + * \@code\{geo_new(GEO_TYPE_INVALID)\} + * \@item + * \@code\{geo_new(GEO_TYPE_MODULE, moduleid_t m)\} + * \@item + * \@code\{geo_new(GEO_TYPE_NODE, moduleid_t m, slabid_t s)\} + * \@item + * \@code\{geo_new(GEO_TYPE_RTR, moduleid_t m, slabid_t s)\} + * \@item + * \@code\{geo_new(GEO_TYPE_IOCNTL, moduleid_t m, slabid_t s)\} + * \@item + * \@code\{geo_new(GEO_TYPE_IOCARD, moduleid_t m, slabid_t s, char bus, slotid_t slot)\} + * \@item + * \@code\{geo_new(GEO_TYPE_CPU, moduleid_t m, slabid_t s, char slice)\} + * \@item + * \@code\{geo_new(GEO_TYPE_MEM, moduleid_t m, slabid_t s, char membus, char slot)\} + * \@end itemize + * + * Invalid types return a GEO_TYPE_INVALID geoid_t. + * + * INTERNALS: + * + * Use the type to determine which fields to expect. Write the fields into + * a new geoid_t and return it. Note: scalars smaller than an "int" are + * promoted to "int" by the "..." operator, so we need extra casts on "char", + * "slotid_t", and "slabid_t". + * + * ORIGIN: + * + * New for SN2 + */ + +geoid_t +geo_new(geo_type_t type, ...) +{ + va_list al; + geoid_t g; + memset(&g, 0, sizeof(g)); + + va_start(al, type); + + /* Make sure the type is sane */ + if (type >= GEO_TYPE_MAX) + type = GEO_TYPE_INVALID; + + g.any.type = type; + if (type == GEO_TYPE_INVALID) + goto done; /* invalid geoids have no components at all */ + + g.any.module = va_arg(al, moduleid_t); + if (type == GEO_TYPE_MODULE) + goto done; + + g.any.slab = (slabid_t)va_arg(al, int); + + /* Some types have additional components */ + switch(type) { + case GEO_TYPE_CPU: + g.cpu.slice = (char)va_arg(al, int); + break; + + case GEO_TYPE_IOCARD: + g.pcicard.bus = (char)va_arg(al, int); + g.pcicard.slot = (slotid_t)va_arg(al, int); + break; + + case GEO_TYPE_MEM: + g.mem.membus = (char)va_arg(al, int); + g.mem.memslot = (char)va_arg(al, int); + break; + + default: + break; + } + + done: + va_end(al); + return g; +} diff -Nru a/arch/ia64/sn/io/sn2/klconflib.c b/arch/ia64/sn/io/sn2/klconflib.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/klconflib.c Mon Feb 24 05:23:53 2003 @@ -0,0 +1,933 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define printf printk +int hasmetarouter; + +#define LDEBUG 0 +#define NIC_UNKNOWN ((nic_t) -1) + +#undef DEBUG_KLGRAPH +#ifdef DEBUG_KLGRAPH +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* DEBUG_KLGRAPH */ + +static void sort_nic_names(lboard_t *) ; + +u64 klgraph_addr[MAX_COMPACT_NODES]; +int module_number = 0; + +lboard_t * +find_lboard(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (start->brd_type == brd_type) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_class(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (KLCLASS(start->brd_type) == KLCLASS(brd_type)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +klinfo_t * +find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type) +{ + int index, j; + + if (kli == (klinfo_t *)NULL) { + index = 0; + } else { + for (j = 0; j < KLCF_NUM_COMPS(brd); j++) { + if (kli == KLCF_COMP(brd, j)) + break; + } + index = j; + if (index == KLCF_NUM_COMPS(brd)) { + DBG("find_component: Bad pointer: 0x%p\n", kli); + return (klinfo_t *)NULL; + } + index++; /* next component */ + } + + for (; index < KLCF_NUM_COMPS(brd); index++) { + kli = KLCF_COMP(brd, index); + DBG("find_component: brd %p kli %p request type = 0x%x kli type 0x%x\n", brd, kli, kli->struct_type, KLCF_COMP_TYPE(kli)); + if (KLCF_COMP_TYPE(kli) == struct_type) + return kli; + } + + /* Didn't find it. */ + return (klinfo_t *)NULL; +} + +klinfo_t * +find_first_component(lboard_t *brd, unsigned char struct_type) +{ + return find_component(brd, (klinfo_t *)NULL, struct_type); +} + +lboard_t * +find_lboard_modslot(lboard_t *start, geoid_t geoid) +{ + /* Search all boards stored on this node. */ + while (start) { + if (geo_cmp(start->brd_geoid, geoid)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_module(lboard_t *start, geoid_t geoid) +{ + /* Search all boards stored on this node. */ + while (start) { + if (geo_cmp(start->brd_geoid, geoid)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_module_class(lboard_t *start, geoid_t geoid, + unsigned char brd_type) +{ + while (start) { + DBG("find_lboard_module_class: lboard 0x%p, start->brd_geoid 0x%x, mod 0x%x, start->brd_type 0x%x, brd_type 0x%x\n", start, start->brd_geoid, geoid, start->brd_type, brd_type); + + if (geo_cmp(start->brd_geoid, geoid) && + (KLCLASS(start->brd_type) == KLCLASS(brd_type))) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +/* + * Convert a NIC name to a name for use in the hardware graph. + */ +void +nic_name_convert(char *old_name, char *new_name) +{ + int i; + char c; + char *compare_ptr; + + if ((old_name[0] == '\0') || (old_name[1] == '\0')) { + strcpy(new_name, EDGE_LBL_XWIDGET); + } else { + for (i = 0; i < strlen(old_name); i++) { + c = old_name[i]; + + if (isalpha(c)) + new_name[i] = tolower(c); + else if (isdigit(c)) + new_name[i] = c; + else + new_name[i] = '_'; + } + new_name[i] = '\0'; + } + + /* XXX - + * Since a bunch of boards made it out with weird names like + * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and + * replace it with "baseio" to avoid confusion in the field. + * We also have to make sure we don't report media_io instead of + * baseio. + */ + + /* Skip underscores at the beginning of the name */ + for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++) + ; + + /* + * Check for some names we need to replace. Early boards + * had junk following the name so check only the first + * characters. + */ + if (!strncmp(new_name, "io6", 3) || + !strncmp(new_name, "mio", 3) || + !strncmp(new_name, "media_io", 8)) + strcpy(new_name, "baseio"); + else if (!strncmp(new_name, "divo", 4)) + strcpy(new_name, "divo") ; + +} + +/* + * Find the lboard structure and get the board name. + * If we can't find the structure or it's too low a revision, + * use default name. + */ +lboard_t * +get_board_name(nasid_t nasid, geoid_t geoid, slotid_t slot, char *name) +{ + lboard_t *brd; + + brd = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid), + geoid); + +#ifndef _STANDALONE + { + cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); + + if (!brd && (NODEPDA(cnode)->xbow_peer != INVALID_NASID)) + brd = find_lboard_modslot((lboard_t *) + KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer), + geoid); + } +#endif + + if (!brd || (brd->brd_sversion < 2)) { + strcpy(name, EDGE_LBL_XWIDGET); + } else { + nic_name_convert(brd->brd_name, name); + } + + /* + * PV # 540860 + * If the name is not 'baseio' + * get the lowest of all the names in the nic string. + * This is needed for boards like divo, which can have + * a bunch of daughter cards, but would like to be called + * divo. We could do this for baseio + * but it has some special case names that we would not + * like to disturb at this point. + */ + + /* gfx boards don't need any of this name scrambling */ + if (brd && (KLCLASS(brd->brd_type) == KLCLASS_GFX)) { + return(brd); + } + + if (!(!strcmp(name, "baseio") )) { + if (brd) { + sort_nic_names(brd) ; + /* Convert to small case, '-' to '_' etc */ + nic_name_convert(brd->brd_name, name) ; + } + } + + return(brd); +} + +/* + * get_actual_nasid + * + * Completely disabled brds have their klconfig on + * some other nasid as they have no memory. But their + * actual nasid is hidden in the klconfig. Use this + * routine to get it. Works for normal boards too. + */ +nasid_t +get_actual_nasid(lboard_t *brd) +{ + klhub_t *hub ; + + if (!brd) + return INVALID_NASID ; + + /* find out if we are a completely disabled brd. */ + + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + if (!hub) + return INVALID_NASID ; + if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */ + return hub->hub_info.physid ; + else + return brd->brd_nasid ; +} + +int +xbow_port_io_enabled(nasid_t nasid, int link) +{ + lboard_t *brd; + klxbow_t *xbow_p; + + /* + * look for boards that might contain an xbow or xbridge + */ + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW); + if (brd == NULL) return 0; + + if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW)) + == NULL) + return 0; + + if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link)) + return 0; + + return 1; +} + +void +board_to_path(lboard_t *brd, char *path) +{ + moduleid_t modnum; + char *board_name; + char buffer[16]; + + ASSERT(brd); + + switch (KLCLASS(brd->brd_type)) { + + case KLCLASS_NODE: + board_name = EDGE_LBL_NODE; + break; + case KLCLASS_ROUTER: + if (brd->brd_type == KLTYPE_META_ROUTER) { + board_name = EDGE_LBL_META_ROUTER; + hasmetarouter++; + } else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) { + board_name = EDGE_LBL_REPEATER_ROUTER; + hasmetarouter++; + } else + board_name = EDGE_LBL_ROUTER; + break; + case KLCLASS_MIDPLANE: + board_name = EDGE_LBL_MIDPLANE; + break; + case KLCLASS_IO: + board_name = EDGE_LBL_IO; + break; + case KLCLASS_IOBRICK: + if (brd->brd_type == KLTYPE_PBRICK) + board_name = EDGE_LBL_PBRICK; + else if (brd->brd_type == KLTYPE_IBRICK) + board_name = EDGE_LBL_IBRICK; + else if (brd->brd_type == KLTYPE_XBRICK) + board_name = EDGE_LBL_XBRICK; + else + board_name = EDGE_LBL_IOBRICK; + break; + default: + board_name = EDGE_LBL_UNKNOWN; + } + + modnum = geo_module(brd->brd_geoid); + memset(buffer, 0, 16); + format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF); + sprintf(path, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/%s", buffer, geo_slab(brd->brd_geoid), board_name); +} + +/* + * Get the module number for a NASID. + */ +moduleid_t +get_module_id(nasid_t nasid) +{ + lboard_t *brd; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + + if (!brd) + return INVALID_MODULE; + else + return geo_module(brd->brd_geoid); +} + + +#define MHZ 1000000 + + +/* Get the canonical hardware graph name for the given pci component + * on the given io board. + */ +void +device_component_canonical_name_get(lboard_t *brd, + klinfo_t *component, + char *name) +{ + slotid_t slot; + char board_name[20]; + + ASSERT(brd); + + /* Convert the [ CLASS | TYPE ] kind of slotid + * into a string + */ + slot = brd->brd_slot; + + /* Get the io board name */ + if (!brd || (brd->brd_sversion < 2)) { + strcpy(name, EDGE_LBL_XWIDGET); + } else { + nic_name_convert(brd->brd_name, board_name); + } + + /* Give out the canonical name of the pci device*/ + sprintf(name, + "/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLAB"/%d/" + EDGE_LBL_SLOT"/%s/"EDGE_LBL_PCI"/%d", + geo_module(brd->brd_geoid), geo_slab(brd->brd_geoid), + board_name, KLCF_BRIDGE_W_ID(component)); +} + +/* + * Get the serial number of the main component of a board + * Returns 0 if a valid serial number is found + * 1 otherwise. + * Assumptions: Nic manufacturing string has the following format + * *Serial:;* + */ +static int +component_serial_number_get(lboard_t *board, + klconf_off_t mfg_nic_offset, + char *serial_number, + char *key_pattern) +{ + + char *mfg_nic_string; + char *serial_string,*str; + int i; + char *serial_pattern = "Serial:"; + + /* We have an error on a null mfg nic offset */ + if (!mfg_nic_offset) + return(1); + /* Get the hub's manufacturing nic information + * which is in the form of a pre-formatted string + */ + mfg_nic_string = + (char *)NODE_OFFSET_TO_K0(NASID_GET(board), + mfg_nic_offset); + /* There is no manufacturing nic info */ + if (!mfg_nic_string) + return(1); + + str = mfg_nic_string; + /* Look for the key pattern first (if it is specified) + * and then print the serial number corresponding to that. + */ + if (strcmp(key_pattern,"") && + !(str = strstr(mfg_nic_string,key_pattern))) + return(1); + + /* There is no serial number info in the manufacturing + * nic info + */ + if (!(serial_string = strstr(str,serial_pattern))) + return(1); + + serial_string = serial_string + strlen(serial_pattern); + /* Copy the serial number information from the klconfig */ + i = 0; + while (serial_string[i] != ';') { + serial_number[i] = serial_string[i]; + i++; + } + serial_number[i] = 0; + + return(0); +} +/* + * Get the serial number of a board + * Returns 0 if a valid serial number is found + * 1 otherwise. + */ + +int +board_serial_number_get(lboard_t *board,char *serial_number) +{ + ASSERT(board && serial_number); + if (!board || !serial_number) + return(1); + + strcpy(serial_number,""); + switch(KLCLASS(board->brd_type)) { + case KLCLASS_CPU: { /* Node board */ + klhub_t *hub; + + /* Get the hub component information */ + hub = (klhub_t *)find_first_component(board, + KLSTRUCT_HUB); + /* If we don't have a hub component on an IP27 + * then we have a weird klconfig. + */ + if (!hub) + return(1); + /* Get the serial number information from + * the hub's manufacturing nic info + */ + if (component_serial_number_get(board, + hub->hub_mfg_nic, + serial_number, + "IP37")) + return(1); + break; + } + case KLCLASS_IO: { /* IO board */ + if (KLTYPE(board->brd_type) == KLTYPE_TPU) { + /* Special case for TPU boards */ + kltpu_t *tpu; + + /* Get the tpu component information */ + tpu = (kltpu_t *)find_first_component(board, + KLSTRUCT_TPU); + /* If we don't have a tpu component on a tpu board + * then we have a weird klconfig. + */ + if (!tpu) + return(1); + /* Get the serial number information from + * the tpu's manufacturing nic info + */ + if (component_serial_number_get(board, + tpu->tpu_mfg_nic, + serial_number, + "")) + return(1); + break; + } else if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) || + (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) { + /* Special case for GSN boards */ + klgsn_t *gsn; + + /* Get the gsn component information */ + gsn = (klgsn_t *)find_first_component(board, + ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ? + KLSTRUCT_GSN_A : KLSTRUCT_GSN_B)); + /* If we don't have a gsn component on a gsn board + * then we have a weird klconfig. + */ + if (!gsn) + return(1); + /* Get the serial number information from + * the gsn's manufacturing nic info + */ + if (component_serial_number_get(board, + gsn->gsn_mfg_nic, + serial_number, + "")) + return(1); + break; + } else { + klbri_t *bridge; + + /* Get the bridge component information */ + bridge = (klbri_t *)find_first_component(board, + KLSTRUCT_BRI); + /* If we don't have a bridge component on an IO board + * then we have a weird klconfig. + */ + if (!bridge) + return(1); + /* Get the serial number information from + * the bridge's manufacturing nic info + */ + if (component_serial_number_get(board, + bridge->bri_mfg_nic, + serial_number, + "")) + return(1); + break; + } + } + case KLCLASS_ROUTER: { /* Router board */ + klrou_t *router; + + /* Get the router component information */ + router = (klrou_t *)find_first_component(board, + KLSTRUCT_ROU); + /* If we don't have a router component on a router board + * then we have a weird klconfig. + */ + if (!router) + return(1); + /* Get the serial number information from + * the router's manufacturing nic info + */ + if (component_serial_number_get(board, + router->rou_mfg_nic, + serial_number, + "")) + return(1); + break; + } + case KLCLASS_GFX: { /* Gfx board */ + klgfx_t *graphics; + + /* Get the graphics component information */ + graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX); + /* If we don't have a gfx component on a gfx board + * then we have a weird klconfig. + */ + if (!graphics) + return(1); + /* Get the serial number information from + * the graphics's manufacturing nic info + */ + if (component_serial_number_get(board, + graphics->gfx_mfg_nic, + serial_number, + "")) + return(1); + break; + } + default: + strcpy(serial_number,""); + break; + } + return(0); +} + +#include "asm/sn/sn_private.h" + +xwidgetnum_t +nodevertex_widgetnum_get(devfs_handle_t node_vtx) +{ + hubinfo_t hubinfo_p; + + hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, + (arbitrary_info_t *) &hubinfo_p); + return(hubinfo_p->h_widgetid); +} + +devfs_handle_t +nodevertex_xbow_peer_get(devfs_handle_t node_vtx) +{ + hubinfo_t hubinfo_p; + nasid_t xbow_peer_nasid; + cnodeid_t xbow_peer; + + hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, + (arbitrary_info_t *) &hubinfo_p); + xbow_peer_nasid = hubinfo_p->h_nodepda->xbow_peer; + if(xbow_peer_nasid == INVALID_NASID) + return ( (devfs_handle_t)-1); + xbow_peer = NASID_TO_COMPACT_NODEID(xbow_peer_nasid); + return(NODEPDA(xbow_peer)->node_vertex); +} + +/* NIC Sorting Support */ + +#define MAX_NICS_PER_STRING 32 +#define MAX_NIC_NAME_LEN 32 + +static char * +get_nic_string(lboard_t *lb) +{ + int i; + klinfo_t *k = NULL ; + klconf_off_t mfg_off = 0 ; + char *mfg_nic = NULL ; + + for (i = 0; i < KLCF_NUM_COMPS(lb); i++) { + k = KLCF_COMP(lb, i) ; + switch(k->struct_type) { + case KLSTRUCT_BRI: + mfg_off = ((klbri_t *)k)->bri_mfg_nic ; + break ; + + case KLSTRUCT_HUB: + mfg_off = ((klhub_t *)k)->hub_mfg_nic ; + break ; + + case KLSTRUCT_ROU: + mfg_off = ((klrou_t *)k)->rou_mfg_nic ; + break ; + + case KLSTRUCT_GFX: + mfg_off = ((klgfx_t *)k)->gfx_mfg_nic ; + break ; + + case KLSTRUCT_TPU: + mfg_off = ((kltpu_t *)k)->tpu_mfg_nic ; + break ; + + case KLSTRUCT_GSN_A: + case KLSTRUCT_GSN_B: + mfg_off = ((klgsn_t *)k)->gsn_mfg_nic ; + break ; + + case KLSTRUCT_XTHD: + mfg_off = ((klxthd_t *)k)->xthd_mfg_nic ; + break; + + default: + mfg_off = 0 ; + break ; + } + if (mfg_off) + break ; + } + + if ((mfg_off) && (k)) + mfg_nic = (char *)NODE_OFFSET_TO_K0(k->nasid, mfg_off) ; + + return mfg_nic ; +} + +char * +get_first_string(char **ptrs, int n) +{ + int i ; + char *tmpptr ; + + if ((ptrs == NULL) || (n == 0)) + return NULL ; + + tmpptr = ptrs[0] ; + + if (n == 1) + return tmpptr ; + + for (i = 0 ; i < n ; i++) { + if (strcmp(tmpptr, ptrs[i]) > 0) + tmpptr = ptrs[i] ; + } + + return tmpptr ; +} + +int +get_ptrs(char *idata, char **ptrs, int n, char *label) +{ + int i = 0 ; + char *tmp = idata ; + + if ((ptrs == NULL) || (idata == NULL) || (label == NULL) || (n == 0)) + return 0 ; + + while ( (tmp = strstr(tmp, label)) ){ + tmp += strlen(label) ; + /* check for empty name field, and last NULL ptr */ + if ((i < (n-1)) && (*tmp != ';')) { + ptrs[i++] = tmp ; + } + } + + ptrs[i] = NULL ; + + return i ; +} + +/* + * sort_nic_names + * + * Does not really do sorting. Find the alphabetically lowest + * name among all the nic names found in a nic string. + * + * Return: + * Nothing + * + * Side Effects: + * + * lb->brd_name gets the new name found + */ + +static void +sort_nic_names(lboard_t *lb) +{ + char *nic_str ; + char *ptrs[MAX_NICS_PER_STRING] ; + char name[MAX_NIC_NAME_LEN] ; + char *tmp, *tmp1 ; + + *name = 0 ; + + /* Get the nic pointer from the lb */ + + if ((nic_str = get_nic_string(lb)) == NULL) + return ; + + tmp = get_first_string(ptrs, + get_ptrs(nic_str, ptrs, MAX_NICS_PER_STRING, "Name:")) ; + + if (tmp == NULL) + return ; + + if ( (tmp1 = strchr(tmp, ';')) ){ + strncpy(name, tmp, tmp1-tmp) ; + name[tmp1-tmp] = 0 ; + } else { + strncpy(name, tmp, (sizeof(name) -1)) ; + name[sizeof(name)-1] = 0 ; + } + + strcpy(lb->brd_name, name) ; +} + + + +char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#012345"; + +/* + * Format a module id for printing. + */ +void +format_module_id(char *buffer, moduleid_t m, int fmt) +{ + int rack, position; + char brickchar; + + rack = MODULE_GET_RACK(m); + ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES); + brickchar = MODULE_GET_BTCHAR(m); + position = MODULE_GET_BPOS(m); + + if (fmt == MODULE_FORMAT_BRIEF) { + /* Brief module number format, eg. 002c15 */ + + /* Decompress the rack number */ + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); + + /* Add the brick type */ + *buffer++ = brickchar; + } + else if (fmt == MODULE_FORMAT_LONG) { + /* Fuller hwgraph format, eg. rack/002/bay/15 */ + + strcpy(buffer, EDGE_LBL_RACK "/"); buffer += strlen(buffer); + + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); + + strcpy(buffer, "/" EDGE_LBL_RPOS "/"); buffer += strlen(buffer); + } + + /* Add the bay position, using at least two digits */ + if (position < 10) + *buffer++ = '0'; + sprintf(buffer, "%d", position); + +} + +/* + * Parse a module id, in either brief or long form. + * Returns < 0 on error. + * The long form does not include a brick type, so it defaults to 0 (CBrick) + */ +int +parse_module_id(char *buffer) +{ + unsigned int v, rack, bay, type, form; + moduleid_t m; + char c; + + if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) { + form = MODULE_FORMAT_LONG; + buffer += strlen(EDGE_LBL_RACK "/"); + + /* A long module ID must be exactly 5 non-template chars. */ + if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5) + return -1; + } + else { + form = MODULE_FORMAT_BRIEF; + + /* A brief module id must be exactly 6 characters */ + if (strlen(buffer) != 6) + return -2; + } + + /* The rack number must be exactly 3 digits */ + if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2]))) + return -3; + + rack = 0; + v = *buffer++ - '0'; + if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack)) + return -4; + RACK_ADD_CLASS(rack, v); + + v = *buffer++ - '0'; + if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack)) + return -5; + RACK_ADD_GROUP(rack, v); + + v = *buffer++ - '0'; + /* rack numbers are 1-based */ + if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack)) + return -6; + RACK_ADD_NUM(rack, v); + + if (form == MODULE_FORMAT_BRIEF) { + /* Next should be a module type character. Accept ucase or lcase. */ + c = *buffer++; + if (!isalpha(c)) + return -7; + + /* strchr() returns a pointer into brick_types[], or NULL */ + type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types); + if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT) + return -8; + } + else { + /* Hardcode the module type, and skip over the boilerplate */ + type = MODULE_CBRICK; + + if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer) + return -9; + + buffer += strlen("/" EDGE_LBL_RPOS "/"); + } + + /* The bay number is last. Make sure it's exactly two digits */ + + if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2])) + return -10; + + bay = 10 * (buffer[0] - '0') + (buffer[1] - '0'); + + if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT) + return -11; + + m = RBT_TO_MODULE(rack, bay, type); + + /* avoid sign extending the moduleid_t */ + return (int)(unsigned short)m; +} diff -Nru a/arch/ia64/sn/io/sn2/klgraph.c b/arch/ia64/sn/io/sn2/klgraph.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/klgraph.c Mon Feb 24 05:24:10 2003 @@ -0,0 +1,866 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +/* + * klgraph.c- + * This file specifies the interface between the kernel and the PROM's + * configuration data structures. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #define KLGRAPH_DEBUG 1 +#ifdef KLGRAPH_DEBUG +#define GRPRINTF(x) printk x +#define CE_GRPANIC CE_PANIC +#else +#define GRPRINTF(x) +#define CE_GRPANIC CE_PANIC +#endif + +#include + +extern char arg_maxnodes[]; +extern u64 klgraph_addr[]; +void mark_cpuvertex_as_cpu(devfs_handle_t vhdl, cpuid_t cpuid); + + +/* + * Support for verbose inventory via hardware graph. + * klhwg_invent_alloc allocates the necessary size of inventory information + * and fills in the generic information. + */ +invent_generic_t * +klhwg_invent_alloc(cnodeid_t cnode, int class, int size) +{ + invent_generic_t *invent; + + invent = kern_malloc(size); + if (!invent) return NULL; + + invent->ig_module = NODE_MODULEID(cnode); + invent->ig_slot = SLOTNUM_GETSLOT(NODE_SLOTID(cnode)); + invent->ig_invclass = class; + + return invent; +} + +/* + * Add detailed disabled cpu inventory info to the hardware graph. + */ +void +klhwg_disabled_cpu_invent_info(devfs_handle_t cpuv, + cnodeid_t cnode, + klcpu_t *cpu, slotid_t slot) +{ + invent_cpuinfo_t *cpu_invent; + diag_inv_t *diag_invent; + + cpu_invent = (invent_cpuinfo_t *) + klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t)); + if (!cpu_invent) + return; + + /* Diag information on this processor */ + diag_invent = (diag_inv_t *) + klhwg_invent_alloc(cnode, INV_CPUDIAGVAL, sizeof(diag_inv_t)); + + if (!diag_invent) + return; + + + /* Disabled CPU */ + cpu_invent->ic_gen.ig_flag = 0x0; + cpu_invent->ic_gen.ig_slot = slot; + cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid; + cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed; + cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed; + + cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz; + cpu_invent->ic_cpuid = cpu->cpu_info.virtid; + cpu_invent->ic_slice = cpu->cpu_info.physid; + + /* Disabled CPU label */ + hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t) cpu_invent); + hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT, + sizeof(invent_cpuinfo_t)); + + /* Diagval label - stores reason for disable +{virt,phys}id +diagval*/ + hwgraph_info_add_LBL(cpuv, INFO_LBL_DIAGVAL, + (arbitrary_info_t) diag_invent); + + hwgraph_info_export_LBL(cpuv, INFO_LBL_DIAGVAL, + sizeof(diag_inv_t)); +} + +/* + * Add detailed cpu inventory info to the hardware graph. + */ +void +klhwg_cpu_invent_info(devfs_handle_t cpuv, + cnodeid_t cnode, + klcpu_t *cpu) +{ + invent_cpuinfo_t *cpu_invent; + + cpu_invent = (invent_cpuinfo_t *) + klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t)); + if (!cpu_invent) + return; + + if (KLCONFIG_INFO_ENABLED((klinfo_t *)cpu)) + cpu_invent->ic_gen.ig_flag = INVENT_ENABLED; + else + cpu_invent->ic_gen.ig_flag = 0x0; + + cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid; + cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed; + cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed; + + cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz; + cpu_invent->ic_cpuid = cpu->cpu_info.virtid; + cpu_invent->ic_slice = cpu_physical_id_to_slice(cpu->cpu_info.virtid); + + hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t) cpu_invent); + hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT, + sizeof(invent_cpuinfo_t)); +} + +/* + * Add information about the baseio prom version number + * as a part of detailed inventory info in the hwgraph. + */ +void +klhwg_baseio_inventory_add(devfs_handle_t baseio_vhdl,cnodeid_t cnode) +{ + invent_miscinfo_t *baseio_inventory; + unsigned char version = 0,revision = 0; + + /* Allocate memory for the "detailed inventory" info + * for the baseio + */ + baseio_inventory = (invent_miscinfo_t *) + klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t)); + baseio_inventory->im_type = INV_IO6PROM; + /* Store the revision info in the inventory */ + baseio_inventory->im_version = version; + baseio_inventory->im_rev = revision; + /* Put the inventory info in the hardware graph */ + hwgraph_info_add_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t) baseio_inventory); + /* Make the information available to the user programs + * thru hwgfs. + */ + hwgraph_info_export_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT, + sizeof(invent_miscinfo_t)); +} + +char *hub_rev[] = { + "0.0", + "1.0", + "2.0", + "2.1", + "2.2", + "2.3" +}; + +/* + * Add detailed cpu inventory info to the hardware graph. + */ +void +klhwg_hub_invent_info(devfs_handle_t hubv, + cnodeid_t cnode, + klhub_t *hub) +{ + invent_miscinfo_t *hub_invent; + + hub_invent = (invent_miscinfo_t *) + klhwg_invent_alloc(cnode, INV_MISC, sizeof(invent_miscinfo_t)); + if (!hub_invent) + return; + + if (KLCONFIG_INFO_ENABLED((klinfo_t *)hub)) + hub_invent->im_gen.ig_flag = INVENT_ENABLED; + + hub_invent->im_type = INV_HUB; + hub_invent->im_rev = hub->hub_info.revision; + hub_invent->im_speed = hub->hub_speed; + hwgraph_info_add_LBL(hubv, INFO_LBL_DETAIL_INVENT, + (arbitrary_info_t) hub_invent); + hwgraph_info_export_LBL(hubv, INFO_LBL_DETAIL_INVENT, + sizeof(invent_miscinfo_t)); +} + +/* ARGSUSED */ +void +klhwg_add_hub(devfs_handle_t node_vertex, klhub_t *hub, cnodeid_t cnode) +{ + devfs_handle_t myhubv; + devfs_handle_t hub_mon; + int rc; + extern struct file_operations shub_mon_fops; + + GRPRINTF(("klhwg_add_hub: adding %s\n", EDGE_LBL_HUB)); + (void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv); + rc = device_master_set(myhubv, node_vertex); + hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON, + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + &shub_mon_fops, (void *)(long)cnode); +} + +/* ARGSUSED */ +void +klhwg_add_disabled_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot) +{ + devfs_handle_t my_cpu; + char name[120]; + cpuid_t cpu_id; + nasid_t nasid; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid); + if(cpu_id != -1){ + sprintf(name, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid); + (void) hwgraph_path_add(node_vertex, name, &my_cpu); + + mark_cpuvertex_as_cpu(my_cpu, cpu_id); + device_master_set(my_cpu, node_vertex); + + klhwg_disabled_cpu_invent_info(my_cpu, cnode, cpu, slot); + return; + } +} + +/* ARGSUSED */ +void +klhwg_add_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu) +{ + devfs_handle_t my_cpu, cpu_dir; + char name[120]; + cpuid_t cpu_id; + nasid_t nasid; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid); + + sprintf(name, "%s/%d/%c", + EDGE_LBL_CPUBUS, + 0, + 'a' + cpu->cpu_info.physid); + + GRPRINTF(("klhwg_add_cpu: adding %s to vertex 0x%p\n", name, node_vertex)); + (void) hwgraph_path_add(node_vertex, name, &my_cpu); + mark_cpuvertex_as_cpu(my_cpu, cpu_id); + device_master_set(my_cpu, node_vertex); + + /* Add an alias under the node's CPU directory */ + if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) { + sprintf(name, "%c", 'a' + cpu->cpu_info.physid); + (void) hwgraph_edge_add(cpu_dir, my_cpu, name); + } + + klhwg_cpu_invent_info(my_cpu, cnode, cpu); +} + + +void +klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid) +{ + lboard_t *brd; + klxbow_t *xbow_p; + nasid_t hub_nasid; + cnodeid_t hub_cnode; + int widgetnum; + devfs_handle_t xbow_v, hubv; + /*REFERENCED*/ + graph_error_t err; + + if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW)) == NULL) + return; + + if (KL_CONFIG_DUPLICATE_BOARD(brd)) + return; + + GRPRINTF(("klhwg_add_xbow: adding cnode %d nasid %d xbow edges\n", + cnode, nasid)); + + if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW)) + == NULL) + return; + + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { + if (!XBOW_PORT_TYPE_HUB(xbow_p, widgetnum)) + continue; + + hub_nasid = XBOW_PORT_NASID(xbow_p, widgetnum); + if (hub_nasid == INVALID_NASID) { + printk(KERN_WARNING "hub widget %d, skipping xbow graph\n", widgetnum); + continue; + } + + hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid); + + if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) { + continue; + } + + hubv = cnodeid_to_vertex(hub_cnode); + + err = hwgraph_path_add(hubv, EDGE_LBL_XTALK, &xbow_v); + if (err != GRAPH_SUCCESS) { + if (err == GRAPH_DUP) + printk(KERN_WARNING "klhwg_add_xbow: Check for " + "working routers and router links!"); + + PRINT_PANIC("klhwg_add_xbow: Failed to add " + "edge: vertex 0x%p to vertex 0x%p," + "error %d\n", + (void *)hubv, (void *)xbow_v, err); + } + xswitch_vertex_init(xbow_v); + + NODEPDA(hub_cnode)->xbow_vhdl = xbow_v; + + /* + * XXX - This won't work is we ever hook up two hubs + * by crosstown through a crossbow. + */ + if (hub_nasid != nasid) { + NODEPDA(hub_cnode)->xbow_peer = nasid; + NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer = + hub_nasid; + } + + GRPRINTF(("klhwg_add_xbow: adding port nasid %d %s to vertex 0x%p\n", + hub_nasid, EDGE_LBL_XTALK, hubv)); + } +} + + +/* ARGSUSED */ +void +klhwg_add_node(devfs_handle_t hwgraph_root, cnodeid_t cnode, gda_t *gdap) +{ + nasid_t nasid; + lboard_t *brd; + klhub_t *hub; + devfs_handle_t node_vertex = NULL; + char path_buffer[100]; + int rv; + char *s; + int board_disabled = 0; + klcpu_t *cpu; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + GRPRINTF(("klhwg_add_node: Adding cnode %d, nasid %d, brd 0x%p\n", + cnode, nasid, brd)); + ASSERT(brd); + + do { + devfs_handle_t cpu_dir; + + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + + GRPRINTF(("klhwg_add_node: adding %s to vertex 0x%p\n", + path_buffer, hwgraph_root)); + rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex); + + if (rv != GRAPH_SUCCESS) + PRINT_PANIC("Node vertex creation failed. " + "Path == %s", + path_buffer); + + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + ASSERT(hub); + if(hub->hub_info.flags & KLINFO_ENABLE) + board_disabled = 0; + else + board_disabled = 1; + + if(!board_disabled) { + mark_nodevertex_as_node(node_vertex, + cnode + board_disabled * numnodes); + + s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer)); + NODEPDA(cnode)->hwg_node_name = + kmalloc(strlen(s) + 1, + GFP_KERNEL); + ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL); + strcpy(NODEPDA(cnode)->hwg_node_name, s); + + hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo); + + /* Set up node board's slot */ + NODEPDA(cnode)->slotdesc = brd->brd_slot; + + /* Set up the module we're in */ + NODEPDA(cnode)->geoid = brd->brd_geoid; + NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid)); + } + + /* Get the first CPU structure */ + cpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); + + /* + * If there's at least 1 CPU, add a "cpu" directory to represent + * the collection of all CPUs attached to this node. + */ + if (cpu) { + graph_error_t rv; + + rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir); + if (rv != GRAPH_SUCCESS) + panic("klhwg_add_node: Cannot create CPU directory\n"); + } + + /* Add each CPU */ + while (cpu) { + cpuid_t cpu_id; + cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid); + if (cpu_enabled(cpu_id)) + klhwg_add_cpu(node_vertex, cnode, cpu); + else + klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot); + + cpu = (klcpu_t *) + find_component(brd, (klinfo_t *)cpu, KLSTRUCT_CPU); + } /* while */ + + if(!board_disabled) + klhwg_add_hub(node_vertex, hub, cnode); + + brd = KLCF_NEXT(brd); + if (brd) + brd = find_lboard(brd, KLTYPE_SNIA); + else + break; + } while(brd); +} + + +/* ARGSUSED */ +void +klhwg_add_all_routers(devfs_handle_t hwgraph_root) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd; + devfs_handle_t node_vertex; + char path_buffer[100]; + int rv; + + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + GRPRINTF(("klhwg_add_all_routers: adding router on cnode %d\n", + cnode)); + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + /* No routers stored in this node's memory */ + continue; + + do { + ASSERT(brd); + GRPRINTF(("Router board struct is %p\n", brd)); + + /* Don't add duplicate boards. */ + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + + GRPRINTF(("Router 0x%p module number is %d\n", brd, brd->brd_geoid)); + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + + GRPRINTF(("Router path is %s\n", path_buffer)); + + /* Add the router */ + GRPRINTF(("klhwg_add_all_routers: adding %s to vertex 0x%p\n", + path_buffer, hwgraph_root)); + rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex); + + if (rv != GRAPH_SUCCESS) + PRINT_PANIC("Router vertex creation " + "failed. Path == %s", + path_buffer); + + GRPRINTF(("klhwg_add_all_routers: get next board from 0x%p\n", + brd)); + /* Find the rest of the routers stored on this node. */ + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), + KLTYPE_ROUTER)) ); + + GRPRINTF(("klhwg_add_all_routers: Done.\n")); + } + +} + +/* ARGSUSED */ +void +klhwg_connect_one_router(devfs_handle_t hwgraph_root, lboard_t *brd, + cnodeid_t cnode, nasid_t nasid) +{ + klrou_t *router; + char path_buffer[50]; + char dest_path[50]; + devfs_handle_t router_hndl; + devfs_handle_t dest_hndl; + int rc; + int port; + lboard_t *dest_brd; + + GRPRINTF(("klhwg_connect_one_router: Connecting router on cnode %d\n", + cnode)); + + /* Don't add duplicate boards. */ + if (brd->brd_flags & DUPLICATE_BOARD) { + GRPRINTF(("klhwg_connect_one_router: Duplicate router 0x%p on cnode %d\n", + brd, cnode)); + return; + } + + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + + rc = hwgraph_traverse(hwgraph_root, path_buffer, &router_hndl); + + if (rc != GRAPH_SUCCESS && is_specified(arg_maxnodes)) + return; + + if (rc != GRAPH_SUCCESS) + printk(KERN_WARNING "Can't find router: %s", path_buffer); + + /* We don't know what to do with multiple router components */ + if (brd->brd_numcompts != 1) { + PRINT_PANIC("klhwg_connect_one_router: %d cmpts on router\n", + brd->brd_numcompts); + return; + } + + + /* Convert component 0 to klrou_t ptr */ + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), + brd->brd_compts[0]); + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + /* See if the port's active */ + if (router->rou_port[port].port_nasid == INVALID_NASID) { + GRPRINTF(("klhwg_connect_one_router: port %d inactive.\n", + port)); + continue; + } + if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid) + == INVALID_CNODEID) { + continue; + } + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + /* Generate a hardware graph path for this board. */ + board_to_path(dest_brd, dest_path); + + rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl); + + if (rc != GRAPH_SUCCESS) { + if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd)) + continue; + PRINT_PANIC("Can't find router: %s", dest_path); + } + GRPRINTF(("klhwg_connect_one_router: Link from %s/%d to %s\n", + path_buffer, port, dest_path)); + + sprintf(dest_path, "%d", port); + + rc = hwgraph_edge_add(router_hndl, dest_hndl, dest_path); + + if (rc == GRAPH_DUP) { + GRPRINTF(("Skipping port %d. nasid %d %s/%s\n", + port, router->rou_port[port].port_nasid, + path_buffer, dest_path)); + continue; + } + + if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes)) + PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n", + path_buffer, dest_path, (void *)dest_hndl, rc); + + } +} + + +void +klhwg_connect_routers(devfs_handle_t hwgraph_root) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd; + + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + GRPRINTF(("klhwg_connect_routers: Connecting routers on cnode %d\n", + cnode)); + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + + nasid = COMPACT_TO_NASID_NODEID(cnode); + + klhwg_connect_one_router(hwgraph_root, brd, + cnode, nasid); + + /* Find the rest of the routers stored on this node. */ + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } +} + + + +void +klhwg_connect_hubs(devfs_handle_t hwgraph_root) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd; + klhub_t *hub; + lboard_t *dest_brd; + devfs_handle_t hub_hndl; + devfs_handle_t dest_hndl; + char path_buffer[50]; + char dest_path[50]; + graph_error_t rc; + int port; + + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + GRPRINTF(("klhwg_connect_hubs: Connecting hubs on cnode %d\n", + cnode)); + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + ASSERT(brd); + + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + ASSERT(hub); + + for (port = 1; port <= MAX_NI_PORTS; port++) { + /* See if the port's active */ + if (hub->hub_port[port].port_nasid == INVALID_NASID) { + GRPRINTF(("klhwg_connect_hubs: port inactive.\n")); + continue; + } + + if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(hub->hub_port[port].port_nasid) == INVALID_CNODEID) + continue; + + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + + GRPRINTF(("klhwg_connect_hubs: Hub path is %s.\n", path_buffer)); + rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl); + + if (rc != GRAPH_SUCCESS) + printk(KERN_WARNING "Can't find hub: %s", path_buffer); + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + hub->hub_port[port].port_nasid, + hub->hub_port[port].port_offset); + + /* Generate a hardware graph path for this board. */ + board_to_path(dest_brd, dest_path); + + rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl); + + if (rc != GRAPH_SUCCESS) { + if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd)) + continue; + PRINT_PANIC("Can't find board: %s", dest_path); + } else { + char buf[1024]; + + + GRPRINTF(("klhwg_connect_hubs: Link from %s to %s.\n", + path_buffer, dest_path)); + + rc = hwgraph_path_add(hub_hndl, EDGE_LBL_INTERCONNECT, &hub_hndl); + sprintf(buf,"%s/%s",path_buffer,EDGE_LBL_INTERCONNECT); + rc = hwgraph_traverse(hwgraph_root, buf, &hub_hndl); + sprintf(buf,"%d",port); + rc = hwgraph_edge_add(hub_hndl, dest_hndl, buf); + + if (rc != GRAPH_SUCCESS) + PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n", + path_buffer, dest_path, (void *)dest_hndl, rc); + + } + } + } +} + +/* Store the pci/vme disabled board information as extended administrative + * hints which can later be used by the drivers using the device/driver + * admin interface. + */ +void +klhwg_device_disable_hints_add(void) +{ + cnodeid_t cnode; /* node we are looking at */ + nasid_t nasid; /* nasid of the node */ + lboard_t *board; /* board we are looking at */ + int comp_index; /* component index */ + klinfo_t *component; /* component in the board we are + * looking at + */ + char device_name[MAXDEVNAME]; + + for(cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + board = (lboard_t *)KL_CONFIG_INFO(nasid); + /* Check out all the board info stored on a node */ + while(board) { + /* No need to look at duplicate boards or non-io + * boards + */ + if (KL_CONFIG_DUPLICATE_BOARD(board) || + KLCLASS(board->brd_type) != KLCLASS_IO) { + board = KLCF_NEXT(board); + continue; + } + /* Check out all the components of a board */ + for (comp_index = 0; + comp_index < KLCF_NUM_COMPS(board); + comp_index++) { + component = KLCF_COMP(board,comp_index); + /* If the component is enabled move on to + * the next component + */ + if (KLCONFIG_INFO_ENABLED(component)) + continue; + /* NOTE : Since the prom only supports + * the disabling of pci devices the following + * piece of code makes sense. + * Make sure that this assumption is valid + */ + /* This component is disabled. Store this + * hint in the extended device admin table + */ + /* Get the canonical name of the pci device */ + device_component_canonical_name_get(board, + component, + device_name); +#ifdef DEBUG + printf("%s DISABLED\n",device_name); +#endif + } + /* go to the next board info stored on this + * node + */ + board = KLCF_NEXT(board); + } + } +} + +void +klhwg_add_all_modules(devfs_handle_t hwgraph_root) +{ + cmoduleid_t cm; + char name[128]; + devfs_handle_t vhdl; + devfs_handle_t module_vhdl; + int rc; + char buffer[16]; + + /* Add devices under each module */ + + for (cm = 0; cm < nummodules; cm++) { + /* Use module as module vertex fastinfo */ + + memset(buffer, 0, 16); + format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF); + sprintf(name, EDGE_LBL_MODULE "/%s", buffer); + + rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl); + ASSERT(rc == GRAPH_SUCCESS); + rc = rc; + + hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]); + + /* Add system controller */ + sprintf(name, + EDGE_LBL_MODULE "/%s/" EDGE_LBL_L1, + buffer); + + rc = hwgraph_path_add(hwgraph_root, name, &vhdl); + ASSERT_ALWAYS(rc == GRAPH_SUCCESS); + rc = rc; + + hwgraph_info_add_LBL(vhdl, + INFO_LBL_ELSC, + (arbitrary_info_t) (__psint_t) 1); + + } +} + +void +klhwg_add_all_nodes(devfs_handle_t hwgraph_root) +{ + cnodeid_t cnode; + + for (cnode = 0; cnode < numnodes; cnode++) { + klhwg_add_node(hwgraph_root, cnode, NULL); + } + + for (cnode = 0; cnode < numnodes; cnode++) { + klhwg_add_xbow(cnode, cnodeid_to_nasid(cnode)); + } + + /* + * As for router hardware inventory information, we set this + * up in router.c. + */ + + klhwg_add_all_routers(hwgraph_root); + klhwg_connect_routers(hwgraph_root); + klhwg_connect_hubs(hwgraph_root); + + /* Go through the entire system's klconfig + * to figure out which pci components have been disabled + */ + klhwg_device_disable_hints_add(); + +} diff -Nru a/arch/ia64/sn/io/sn2/l1.c b/arch/ia64/sn/io/sn2/l1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/l1.c Mon Feb 24 05:24:28 2003 @@ -0,0 +1,244 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +/* In general, this file is organized in a hierarchy from lower-level + * to higher-level layers, as follows: + * + * UART routines + * Bedrock/L1 "PPP-like" protocol implementation + * System controller "message" interface (allows multiplexing + * of various kinds of requests and responses with + * console I/O) + * Console interface: + * "l1_cons", the glue that allows the L1 to act + * as the system console for the stdio libraries + * + * Routines making use of the system controller "message"-style interface + * can be found in l1_command.c. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define UART_BAUD_RATE 57600 + +int +get_L1_baud(void) +{ + return UART_BAUD_RATE; +} + + + +/* Return the current interrupt level */ +int +l1_get_intr_value( void ) +{ + return(0); +} + +/* Disconnect the callup functions - throw away interrupts */ + +void +l1_unconnect_intr(void) +{ +} + +/* Set up uart interrupt handling for this node's uart */ + +void +l1_connect_intr(void *rx_notify, void *tx_notify) +{ +#if 0 + // Will need code here for sn2 - something like this + console_nodepda = NODEPDA(NASID_TO_COMPACT_NODEID(get_master_nasid()); + intr_connect_level(console_nodepda->node_first_cpu, + SGI_UART_VECTOR, INTPEND0_MAXMASK, + dummy_intr_func); + request_irq(SGI_UART_VECTOR | (console_nodepda->node_first_cpu << 8), + intr_func, SA_INTERRUPT | SA_SHIRQ, + "l1_protocol_driver", (void *)sc); +#endif +} + + +/* These are functions to use from serial_in/out when in protocol + * mode to send and receive uart control regs. These are external + * interfaces into the protocol driver. + */ + +void +l1_control_out(int offset, int value) +{ + /* quietly ignore unless simulator */ + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + if ( master_node_bedrock_address != (u64)0 ) { + writeb(value, (unsigned long)master_node_bedrock_address + + (offset<< 3)); + } + return; + } +} + +/* Console input exported interface. Return a register value. */ + +int +l1_control_in_polled(int offset) +{ + static int l1_control_in_local(int); + + return(l1_control_in_local(offset)); +} + +int +l1_control_in(int offset) +{ + static int l1_control_in_local(int); + + return(l1_control_in_local(offset)); +} + +static int +l1_control_in_local(int offset) +{ + int sal_call_status = 0, input; + int ret = 0; + + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + ret = readb((unsigned long)master_node_bedrock_address + + (offset<< 3)); + return(ret); + } + if ( offset == REG_LSR ) { + ret = (LSR_XHRE | LSR_XSRE); /* can send anytime */ + sal_call_status = ia64_sn_console_check(&input); + if ( !sal_call_status && input ) { + /* input pending */ + ret |= LSR_RCA; + } + } + return(ret); +} + +/* + * Console input exported interface. Return a character (if one is available) + */ + +int +l1_serial_in_polled(void) +{ + static int l1_serial_in_local(void); + + return(l1_serial_in_local()); +} + +int +l1_serial_in(void) +{ + static int l1_serial_in_local(void); + + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3))); + } + return(l1_serial_in_local()); +} + +static int +l1_serial_in_local(void) +{ + int ch; + + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3))); + } + + if ( !(ia64_sn_console_getc(&ch)) ) + return(ch); + else + return(0); +} + +/* Console output exported interface. Write message to the console. */ + +int +l1_serial_out( char *str, int len ) +{ + int counter = len; + + /* Ignore empty messages */ + if ( len == 0 ) + return(len); + +#if defined(CONFIG_IA64_EARLY_PRINTK) + /* Need to setup SAL calls so the PROM calls will work */ + { + static int inited; + void early_sn_setup(void); + if(!inited) { + inited=1; + early_sn_setup(); + } + } +#endif + + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + void early_sn_setup(void); + if (!master_node_bedrock_address) + early_sn_setup(); + if ( master_node_bedrock_address != (u64)0 ) { +#ifdef FLAG_DIRECT_CONSOLE_WRITES + /* This is an easy way to pre-pend the output to know whether the output + * was done via sal or directly */ + writeb('[', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); + writeb('+', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); + writeb(']', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); + writeb(' ', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); +#endif /* FLAG_DIRECT_CONSOLE_WRITES */ + while ( counter > 0 ) { + writeb(*str, (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); + counter--; + str++; + } + } + return(len); + } + + /* Attempt to write things out thru the sal */ + if ( ia64_sn_console_putb(str, len) ) + return(0); + + return((counter <= 0) ? 0 : (len - counter)); +} diff -Nru a/arch/ia64/sn/io/sn2/l1_command.c b/arch/ia64/sn/io/sn2/l1_command.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/l1_command.c Mon Feb 24 05:24:42 2003 @@ -0,0 +1,207 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ELSC_TIMEOUT 1000000 /* ELSC response timeout (usec) */ +#define LOCK_TIMEOUT 5000000 /* Hub lock timeout (usec) */ + +#define hub_cpu_get() 0 + +#define LBYTE(caddr) (*(char *) caddr) + +extern char *bcopy(const char * src, char * dest, int count); + +#define LDEBUG 0 + +/* + * ELSC data is in NVRAM page 7 at the following offsets. + */ + +#define NVRAM_MAGIC_AD 0x700 /* magic number used for init */ +#define NVRAM_PASS_WD 0x701 /* password (4 bytes in length) */ +#define NVRAM_DBG1 0x705 /* virtual XOR debug switches */ +#define NVRAM_DBG2 0x706 /* physical XOR debug switches */ +#define NVRAM_CFG 0x707 /* ELSC Configuration info */ +#define NVRAM_MODULE 0x708 /* system module number */ +#define NVRAM_BIST_FLG 0x709 /* BIST flags (2 bits per nodeboard) */ +#define NVRAM_PARTITION 0x70a /* module's partition id */ +#define NVRAM_DOMAIN 0x70b /* module's domain id */ +#define NVRAM_CLUSTER 0x70c /* module's cluster id */ +#define NVRAM_CELL 0x70d /* module's cellid */ + +#define NVRAM_MAGIC_NO 0x37 /* value of magic number */ +#define NVRAM_SIZE 16 /* 16 bytes in nvram */ + + +/* elsc_display_line writes up to 12 characters to either the top or bottom + * line of the L1 display. line points to a buffer containing the message + * to be displayed. The zero-based line number is specified by lnum (so + * lnum == 0 specifies the top line and lnum == 1 specifies the bottom). + * Lines longer than 12 characters, or line numbers not less than + * L1_DISPLAY_LINES, cause elsc_display_line to return an error. + */ +int elsc_display_line(nasid_t nasid, char *line, int lnum) +{ + return 0; +} + +/* + * iobrick routines + */ + +/* iobrick_rack_bay_type_get fills in the three int * arguments with the + * rack number, bay number and brick type of the L1 being addressed. Note + * that if the L1 operation fails and this function returns an error value, + * garbage may be written to brick_type. + */ + + +int iobrick_rack_bay_type_get( nasid_t nasid, uint *rack, + uint *bay, uint *brick_type ) +{ + int result = 0; + + if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) ) + return( ELSC_ERROR_CMD_SEND ); + + *rack = (result & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT; + *bay = (result & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT; + *brick_type = (result & L1_ADDR_TYPE_MASK) >> L1_ADDR_TYPE_SHFT; + *brick_type = toupper(*brick_type); + + return 0; +} + + +int iomoduleid_get(nasid_t nasid) +{ + + int result = 0; + + if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) ) + return( ELSC_ERROR_CMD_SEND ); + + return result; + +} + +int iobrick_module_get(nasid_t nasid) +{ + uint rnum, rack, bay, brick_type, t; + int ret; + + /* construct module ID from rack and slot info */ + + if ((ret = iobrick_rack_bay_type_get(nasid, &rnum, &bay, &brick_type)) < 0) + return ret; + + if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT) + return ELSC_ERROR_MODULE; + + /* Build a moduleid_t-compatible rack number */ + + rack = 0; + t = rnum / 100; /* rack class (CPU/IO) */ + if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack)) + return ELSC_ERROR_MODULE; + RACK_ADD_CLASS(rack, t); + rnum %= 100; + + t = rnum / 10; /* rack group */ + if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack)) + return ELSC_ERROR_MODULE; + RACK_ADD_GROUP(rack, t); + + t = rnum % 10; /* rack number (one-based) */ + if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack)) + return ELSC_ERROR_MODULE; + RACK_ADD_NUM(rack, t); + + switch( brick_type ) { + case 'I': + brick_type = MODULE_IBRICK; break; + case 'P': + brick_type = MODULE_PBRICK; break; + case 'X': + brick_type = MODULE_XBRICK; break; + } + + ret = RBT_TO_MODULE(rack, bay, brick_type); + + return ret; +} + +/* + * iobrick_module_get_nasid() returns a module_id which has the brick + * type encoded in bits 15-12, but this is not the true brick type... + * The module_id returned by iobrick_module_get_nasid() is modified + * to make a PEBRICKs & PXBRICKs look like a PBRICK. So this routine + * iobrick_type_get_nasid() returns the true unmodified brick type. + */ +int +iobrick_type_get_nasid(nasid_t nasid) +{ + uint rack, bay, type; + int t, ret; + extern char brick_types[]; + + if ((ret = iobrick_rack_bay_type_get(nasid, &rack, &bay, &type)) < 0) { + return ret; + } + + /* convert brick_type to lower case */ + if ((type >= 'A') && (type <= 'Z')) + type = type - 'A' + 'a'; + + /* convert to a module.h brick type */ + for( t = 0; t < MAX_BRICK_TYPES; t++ ) { + if( brick_types[t] == type ) + return t; + } + + return -1; /* unknown brick */ +} + +int iobrick_module_get_nasid(nasid_t nasid) +{ + int io_moduleid; + +#ifdef PIC_LATER + uint rack, bay; + + if (PEBRICK_NODE(nasid)) { + if (peer_iobrick_rack_bay_get(nasid, &rack, &bay)) { + printf("Could not read rack and bay location " + "of PEBrick at nasid %d\n", nasid); + } + + io_moduleid = peer_iobrick_module_get(sc, rack, bay); + } +#endif /* PIC_LATER */ + io_moduleid = iobrick_module_get(nasid); + return io_moduleid; +} diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_init.c b/arch/ia64/sn/io/sn2/ml_SN_init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/ml_SN_init.c Mon Feb 24 05:21:39 2003 @@ -0,0 +1,160 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int numcpus; +extern char arg_maxnodes[]; +extern cpuid_t master_procid; + +extern int hasmetarouter; + +int maxcpus; +cpumask_t boot_cpumask; +hubreg_t region_mask = 0; + + +extern xwidgetnum_t hub_widget_id(nasid_t); + +extern int valid_icache_reasons; /* Reasons to flush the icache */ +extern int valid_dcache_reasons; /* Reasons to flush the dcache */ +extern u_char miniroot; +extern volatile int need_utlbmiss_patch; +extern void iograph_early_init(void); + +nasid_t master_nasid = INVALID_NASID; /* This is the partition master nasid */ +nasid_t master_baseio_nasid = INVALID_NASID; /* This is the master base I/O nasid */ + + +/* + * mlreset(void) + * very early machine reset - at this point NO interrupts have been + * enabled; nor is memory, tlb, p0, etc setup. + * + * slave is zero when mlreset is called for the master processor and + * is nonzero thereafter. + */ + + +void +mlreset(int slave) +{ + /* + * We are the master cpu and node. + */ + master_nasid = get_nasid(); + set_master_bridge_base(); + + /* We're the master processor */ + master_procid = smp_processor_id(); + master_nasid = cpuid_to_nasid(master_procid); + + /* + * master_nasid we get back better be same as one from + * get_nasid() + */ + ASSERT_ALWAYS(master_nasid == get_nasid()); + + /* early initialization of iograph */ + iograph_early_init(); + + /* Initialize Hub Pseudodriver Management */ + hubdev_init(); +} + + +/* XXX - Move the meat of this to intr.c ? */ +/* + * Set up the platform-dependent fields in the nodepda. + */ +void init_platform_nodepda(nodepda_t *npda, cnodeid_t node) +{ + hubinfo_t hubinfo; + + extern void router_map_init(nodepda_t *); + extern void router_queue_init(nodepda_t *,cnodeid_t); + extern void intr_init_vecblk(nodepda_t *, cnodeid_t, int); + + /* Allocate per-node platform-dependent data */ + hubinfo = (hubinfo_t)alloc_bootmem_node(NODE_DATA(node), sizeof(struct hubinfo_s)); + + npda->pdinfo = (void *)hubinfo; + hubinfo->h_nodepda = npda; + hubinfo->h_cnodeid = node; + hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node); + + spin_lock_init(&hubinfo->h_crblock); + + hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid); + npda->xbow_peer = INVALID_NASID; + + /* + * Initialize the linked list of + * router info pointers to the dependent routers + */ + npda->npda_rip_first = NULL; + + /* + * npda_rip_last always points to the place + * where the next element is to be inserted + * into the list + */ + npda->npda_rip_last = &npda->npda_rip_first; + npda->geoid.any.type = GEO_TYPE_INVALID; + + mutex_init_locked(&npda->xbow_sema); /* init it locked? */ +} + +/* XXX - Move the interrupt stuff to intr.c ? */ +/* + * Set up the platform-dependent fields in the processor pda. + * Must be done _after_ init_platform_nodepda(). + * If we need a lock here, something else is wrong! + */ +void init_platform_pda(cpuid_t cpu) +{ +} + +void +update_node_information(cnodeid_t cnodeid) +{ + nodepda_t *npda = NODEPDA(cnodeid); + nodepda_router_info_t *npda_rip; + + /* Go through the list of router info + * structures and copy some frequently + * accessed info from the info hanging + * off the corresponding router vertices + */ + npda_rip = npda->npda_rip_first; + while(npda_rip) { + if (npda_rip->router_infop) { + npda_rip->router_portmask = + npda_rip->router_infop->ri_portmask; + npda_rip->router_slot = + npda_rip->router_infop->ri_slotnum; + } else { + /* No router, no ports. */ + npda_rip->router_portmask = 0; + } + npda_rip = npda_rip->router_next; + } +} diff -Nru a/arch/ia64/sn/io/sn2/ml_iograph.c b/arch/ia64/sn/io/sn2/ml_iograph.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/ml_iograph.c Mon Feb 24 05:24:56 2003 @@ -0,0 +1,1395 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* #define IOGRAPH_DEBUG */ +#ifdef IOGRAPH_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* IOGRAPH_DEBUG */ + +/* #define PROBE_TEST */ + +/* At most 2 hubs can be connected to an xswitch */ +#define NUM_XSWITCH_VOLUNTEER 2 + +extern unsigned char Is_pic_on_this_nasid[512]; + +/* + * Track which hubs have volunteered to manage devices hanging off of + * a Crosstalk Switch (e.g. xbow). This structure is allocated, + * initialized, and hung off the xswitch vertex early on when the + * xswitch vertex is created. + */ +typedef struct xswitch_vol_s { + mutex_t xswitch_volunteer_mutex; + int xswitch_volunteer_count; + devfs_handle_t xswitch_volunteer[NUM_XSWITCH_VOLUNTEER]; +} *xswitch_vol_t; + +void +xswitch_vertex_init(devfs_handle_t xswitch) +{ + xswitch_vol_t xvolinfo; + int rc; + extern void * snia_kmem_zalloc(size_t size, int flag); + + xvolinfo = snia_kmem_zalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL); + mutex_init(&xvolinfo->xswitch_volunteer_mutex); + rc = hwgraph_info_add_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t)xvolinfo); + ASSERT(rc == GRAPH_SUCCESS); rc = rc; +} + + +/* + * When assignment of hubs to widgets is complete, we no longer need the + * xswitch volunteer structure hanging around. Destroy it. + */ +static void +xswitch_volunteer_delete(devfs_handle_t xswitch) +{ + xswitch_vol_t xvolinfo; + int rc; + extern void snia_kmem_free(void *ptr, size_t size); + + rc = hwgraph_info_remove_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t *)&xvolinfo); + snia_kmem_free(xvolinfo, sizeof(struct xswitch_vol_s)); +} +/* + * A Crosstalk master volunteers to manage xwidgets on the specified xswitch. + */ +/* ARGSUSED */ +static void +volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master) +{ + xswitch_vol_t xvolinfo = NULL; + devfs_handle_t hubv; + hubinfo_t hubinfo; + + (void)hwgraph_info_get_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t *)&xvolinfo); + if (xvolinfo == NULL) { + if (!is_headless_node_vertex(master)) + printk(KERN_WARNING + "volunteer for widgets: vertex 0x%p has no info label", + (void *)xswitch); + return; + } + + mutex_lock(&xvolinfo->xswitch_volunteer_mutex); + ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER); + xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master; + xvolinfo->xswitch_volunteer_count++; + + /* + * if dual ported, make the lowest widgetid always be + * xswitch_volunteer[0]. + */ + if (xvolinfo->xswitch_volunteer_count == NUM_XSWITCH_VOLUNTEER) { + hubv = xvolinfo->xswitch_volunteer[0]; + hubinfo_get(hubv, &hubinfo); + if (hubinfo->h_widgetid != XBOW_HUBLINK_LOW) { + xvolinfo->xswitch_volunteer[0] = + xvolinfo->xswitch_volunteer[1]; + xvolinfo->xswitch_volunteer[1] = hubv; + } + } + mutex_unlock(&xvolinfo->xswitch_volunteer_mutex); +} + +extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum); + +/* + * Assign all the xwidgets hanging off the specified xswitch to the + * Crosstalk masters that have volunteered for xswitch duty. + */ +/* ARGSUSED */ +static void +assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv) +{ + xswitch_info_t xswitch_info; + xswitch_vol_t xvolinfo = NULL; + xwidgetnum_t widgetnum; + int num_volunteer; + nasid_t nasid; + hubinfo_t hubinfo; + extern int iobrick_type_get_nasid(nasid_t); + + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + + xswitch_info = xswitch_info_get(xswitch); + ASSERT(xswitch_info != NULL); + + (void)hwgraph_info_get_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t *)&xvolinfo); + if (xvolinfo == NULL) { + if (!is_headless_node_vertex(hubv)) + printk(KERN_WARNING + "assign_widgets_to_volunteers:vertex 0x%p has " + " no info label", + (void *)xswitch); + return; + } + + num_volunteer = xvolinfo->xswitch_volunteer_count; + ASSERT(num_volunteer > 0); + + /* Assign master hub for xswitch itself. */ + if (HUB_WIDGET_ID_MIN > 0) { + hubv = xvolinfo->xswitch_volunteer[0]; + xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv); + } + + /* + * TBD: Use administrative information to alter assignment of + * widgets to hubs. + */ + for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { + int i; + + /* + * Ignore disabled/empty ports. + */ + if (!xbow_port_io_enabled(nasid, widgetnum)) + continue; + + /* + * If this is the master IO board, assign it to the same + * hub that owned it in the prom. + */ + if (is_master_baseio_nasid_widget(nasid, widgetnum)) { + extern nasid_t get_master_baseio_nasid(void); + for (i=0; ixswitch_volunteer[i]; + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + if (nasid == get_master_baseio_nasid()) + goto do_assignment; + } + PRINT_PANIC("Nasid == %d, console nasid == %d", + nasid, get_master_baseio_nasid()); + } + + /* + * Assuming that we're dual-hosted and that PCI cards + * are naturally placed left-to-right, alternate PCI + * buses across both Cbricks. For Pbricks, and Ibricks, + * io_brick_map_widget() returns the PCI bus number + * associated with the given brick type and widget number. + * For Xbricks, it returns the XIO slot number. + */ + + i = 0; + if (num_volunteer > 1) { + int bt; + + bt = iobrick_type_get_nasid(nasid); + if (bt >= 0) { + /* + * PXBRICK has two busses per widget so this + * algorithm wouldn't work (all busses would + * be assigned to one volunteer). Change the + * bricktype to PBRICK whose mapping is setup + * suchthat 2 of the PICs will be assigned to + * one volunteer and the other one will be + * assigned to the other volunteer. + */ + if (bt == MODULE_PXBRICK) + bt = MODULE_PBRICK; + + i = io_brick_map_widget(bt, widgetnum) & 1; + } + } + + hubv = xvolinfo->xswitch_volunteer[i]; + +do_assignment: + /* + * At this point, we want to make hubv the master of widgetnum. + */ + xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv); + } + + xswitch_volunteer_delete(xswitch); +} + +/* + * Early iograph initialization. Called by master CPU in mlreset(). + * Useful for including iograph.o in kernel.o. + */ +void +iograph_early_init(void) +{ +/* + * Need new way to get this information .. + */ + cnodeid_t cnode; + nasid_t nasid; + lboard_t *board; + + /* + * Init. the board-to-hwgraph link early, so FRU analyzer + * doesn't trip on leftover values if we panic early on. + */ + for(cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + board = (lboard_t *)KL_CONFIG_INFO(nasid); + DBG("iograph_early_init: Found board 0x%p\n", board); + + /* Check out all the board info stored on a node */ + while(board) { + board->brd_graph_link = GRAPH_VERTEX_NONE; + board = KLCF_NEXT(board); + DBG("iograph_early_init: Found board 0x%p\n", board); + } + } + + hubio_init(); +} + +/* + * Let boot processor know that we're done initializing our node's IO + * and then exit. + */ +/* ARGSUSED */ +static void +io_init_done(cnodeid_t cnodeid,cpu_cookie_t c) +{ + /* Let boot processor know that we're done. */ +} + +/* + * Probe to see if this hub's xtalk link is active. If so, + * return the Crosstalk Identification of the widget that we talk to. + * This is called before any of the Crosstalk infrastructure for + * this hub is set up. It's usually called on the node that we're + * probing, but not always. + * + * TBD: Prom code should actually do this work, and pass through + * hwid for our use. + */ +static void +early_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid) +{ + hubreg_t llp_csr_reg; + nasid_t nasid; + hubinfo_t hubinfo; + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + + llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); + /* + * If link is up, read the widget's part number. + * A direct connect widget must respond to widgetnum=0. + */ + if (llp_csr_reg & IIO_LLP_CSR_IS_UP) { + /* TBD: Put hub into "indirect" mode */ + /* + * We're able to read from a widget because our hub's + * WIDGET_ID was set up earlier. + */ + widgetreg_t widget_id = *(volatile widgetreg_t *) + (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); + + DBG("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id, + (volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) ); + + hwid->part_num = XWIDGET_PART_NUM(widget_id); + hwid->rev_num = XWIDGET_REV_NUM(widget_id); + hwid->mfg_num = XWIDGET_MFG_NUM(widget_id); + + /* TBD: link reset */ + } else { + + hwid->part_num = XWIDGET_PART_NUM_NONE; + hwid->rev_num = XWIDGET_REV_NUM_NONE; + hwid->mfg_num = XWIDGET_MFG_NUM_NONE; + } +} + +/* Add inventory information to the widget vertex + * Right now (module,slot,revision) is being + * added as inventory information. + */ +static void +xwidget_inventory_add(devfs_handle_t widgetv, + lboard_t *board, + struct xwidget_hwid_s hwid) +{ + if (!board) + return; + /* Donot add inventory information for the baseio + * on a speedo with an xbox. It has already been + * taken care of in SN00_vmc. + * Speedo with xbox's baseio comes in at slot io1 (widget 9) + */ + device_inventory_add(widgetv,INV_IOBD,board->brd_type, + geo_module(board->brd_geoid), + SLOTNUM_GETSLOT(board->brd_slot), + hwid.rev_num); +} + +/* + * io_xswitch_widget_init + * + */ + +void +io_xswitch_widget_init(devfs_handle_t xswitchv, + devfs_handle_t hubv, + xwidgetnum_t widgetnum, + async_attach_t aa) +{ + xswitch_info_t xswitch_info; + xwidgetnum_t hub_widgetid; + devfs_handle_t widgetv; + cnodeid_t cnode; + widgetreg_t widget_id; + nasid_t nasid, peer_nasid; + struct xwidget_hwid_s hwid; + hubinfo_t hubinfo; + /*REFERENCED*/ + int rc; + char pathname[128]; + lboard_t *board = NULL; + char buffer[16]; + char bt; + moduleid_t io_module; + slotid_t get_widget_slotnum(int xbow, int widget); + + DBG("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum); + + /* + * Verify that xswitchv is indeed an attached xswitch. + */ + xswitch_info = xswitch_info_get(xswitchv); + ASSERT(xswitch_info != NULL); + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + cnode = NASID_TO_COMPACT_NODEID(nasid); + hub_widgetid = hubinfo->h_widgetid; + + /* + * Check that the widget is an io widget and is enabled + * on this nasid or the `peer' nasid. The peer nasid + * is the other hub/bedrock connected to the xbow. + */ + peer_nasid = NODEPDA(cnode)->xbow_peer; + if (peer_nasid == INVALID_NASID) + /* If I don't have a peer, use myself. */ + peer_nasid = nasid; + if (!xbow_port_io_enabled(nasid, widgetnum) && + !xbow_port_io_enabled(peer_nasid, widgetnum)) { + return; + } + + if (xswitch_info_link_ok(xswitch_info, widgetnum)) { + char name[4]; + lboard_t dummy; + + /* + * If the current hub is not supposed to be the master + * for this widgetnum, then skip this widget. + */ + if (xswitch_info_master_assignment_get(xswitch_info, + widgetnum) != hubv) { + return; + } + + board = find_lboard_class( + (lboard_t *)KL_CONFIG_INFO(nasid), + KLCLASS_IOBRICK); + if (!board && NODEPDA(cnode)->xbow_peer != INVALID_NASID) { + board = find_lboard_class( + (lboard_t *)KL_CONFIG_INFO( NODEPDA(cnode)->xbow_peer), + KLCLASS_IOBRICK); + } + + if (board) { + DBG("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type); + } else { + DBG("io_xswitch_widget_init: FIXME did not find IOBOARD\n"); + board = &dummy; + } + + + /* Copy over the nodes' geoid info */ + { + lboard_t *brd; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + if ( brd != (lboard_t *)0 ) { + board->brd_geoid = brd->brd_geoid; + } + } + + /* + * Make sure we really want to say xbrick, pbrick, + * etc. rather than XIO, graphics, etc. + */ + + memset(buffer, 0, 16); + format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF); + sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d" "/%cbrick" "/%s/%d", + buffer, + geo_slab(board->brd_geoid), + (board->brd_type == KLTYPE_IBRICK) ? 'I' : + (board->brd_type == KLTYPE_PBRICK) ? 'P' : + (board->brd_type == KLTYPE_XBRICK) ? 'X' : '?', + EDGE_LBL_XTALK, widgetnum); + + DBG("io_xswitch_widget_init: path= %s\n", pathname); + rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv); + + ASSERT(rc == GRAPH_SUCCESS); + + /* This is needed to let the user programs to map the + * module,slot numbers to the corresponding widget numbers + * on the crossbow. + */ + device_master_set(hwgraph_connectpt_get(widgetv), hubv); + sprintf(name, "%d", widgetnum); + DBG("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv); + rc = hwgraph_edge_add(xswitchv, widgetv, name); + + /* + * crosstalk switch code tracks which + * widget is attached to each link. + */ + xswitch_info_vhdl_set(xswitch_info, widgetnum, widgetv); + + /* + * Peek at the widget to get its crosstalk part and + * mfgr numbers, then present it to the generic xtalk + * bus provider to have its driver attach routine + * called (or not). + */ + widget_id = XWIDGET_ID_READ(nasid, widgetnum); + hwid.part_num = XWIDGET_PART_NUM(widget_id); + hwid.rev_num = XWIDGET_REV_NUM(widget_id); + hwid.mfg_num = XWIDGET_MFG_NUM(widget_id); + /* Store some inventory information about + * the xwidget in the hardware graph. + */ + xwidget_inventory_add(widgetv,board,hwid); + + (void)xwidget_register(&hwid, widgetv, widgetnum, + hubv, hub_widgetid, + aa); + + ia64_sn_sysctl_iobrick_module_get(nasid, &io_module); + + if (io_module >= 0) { + char buffer[16]; + devfs_handle_t to, from; + + memset(buffer, 0, 16); + format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF); + + bt = toupper(MODULE_GET_BTCHAR(io_module)); + /* Add a helper vertex so xbow monitoring + * can identify the brick type. It's simply + * an edge from the widget 0 vertex to the + * brick vertex. + */ + + sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/" + EDGE_LBL_SLAB "/%d/" + EDGE_LBL_NODE "/" EDGE_LBL_XTALK "/" + "0", + buffer, geo_slab(board->brd_geoid)); + from = hwgraph_path_to_vertex(pathname); + ASSERT_ALWAYS(from); + sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/" + EDGE_LBL_SLAB "/%d/" + "%cbrick", + buffer, geo_slab(board->brd_geoid), bt); + + to = hwgraph_path_to_vertex(pathname); + ASSERT_ALWAYS(to); + rc = hwgraph_edge_add(from, to, + EDGE_LBL_INTERCONNECT); + if (rc == -EEXIST) + goto link_done; + if (rc != GRAPH_SUCCESS) { + printk("%s: Unable to establish link" + " for xbmon.", pathname); + } +link_done: + } + +#ifdef SN0_USE_BTE + bte_bpush_war(cnode, (void *)board); +#endif + } +} + + +static void +io_init_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnode) +{ + xwidgetnum_t widgetnum; + async_attach_t aa; + + aa = async_attach_new(); + + DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode); + + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; + widgetnum++) { + io_xswitch_widget_init(xswitchv, + cnodeid_to_vertex(cnode), + widgetnum, aa); + } + /* + * Wait for parallel attach threads, if any, to complete. + */ + async_attach_waitall(aa); + async_attach_free(aa); +} + +/* + * For each PCI bridge connected to the xswitch, add a link from the + * board's klconfig info to the bridge's hwgraph vertex. This lets + * the FRU analyzer find the bridge without traversing the hardware + * graph and risking hangs. + */ +static void +io_link_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnodeid) +{ + xwidgetnum_t widgetnum; + char pathname[128]; + devfs_handle_t vhdl; + nasid_t nasid, peer_nasid; + lboard_t *board; + + + + /* And its connected hub's nasids */ + nasid = COMPACT_TO_NASID_NODEID(cnodeid); + peer_nasid = NODEPDA(cnodeid)->xbow_peer; + + /* + * Look for paths matching "/pci" under xswitchv. + * For every widget, init. its lboard's hwgraph link. If the + * board has a PCI bridge, point the link to it. + */ + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; + widgetnum++) { + sprintf(pathname, "%d", widgetnum); + if (hwgraph_traverse(xswitchv, pathname, &vhdl) != + GRAPH_SUCCESS) + continue; + + board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid), + NODEPDA(cnodeid)->geoid); + if (board == NULL && peer_nasid != INVALID_NASID) { + /* + * Try to find the board on our peer + */ + board = find_lboard_module( + (lboard_t *)KL_CONFIG_INFO(peer_nasid), + NODEPDA(cnodeid)->geoid); + } + if (board == NULL) { + printk(KERN_WARNING "Could not find PROM info for vertex 0x%p, " + "FRU analyzer may fail", + (void *)vhdl); + return; + } + + if ( Is_pic_on_this_nasid[nasid] ) { + /* Check both buses */ + sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum); + if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) + board->brd_graph_link = vhdl; + else { + sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum); + if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) + board->brd_graph_link = vhdl; + else + board->brd_graph_link = GRAPH_VERTEX_NONE; + } + } + else { + sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum); + if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) + board->brd_graph_link = vhdl; + else + board->brd_graph_link = GRAPH_VERTEX_NONE; + } + } +} + +/* + * Initialize all I/O on the specified node. + */ +static void +io_init_node(cnodeid_t cnodeid) +{ + /*REFERENCED*/ + devfs_handle_t hubv, switchv, widgetv; + struct xwidget_hwid_s hwid; + hubinfo_t hubinfo; + int is_xswitch; + nodepda_t *npdap; + struct semaphore *peer_sema = 0; + uint32_t widget_partnum; + nodepda_router_info_t *npda_rip; + cpu_cookie_t c = 0; + extern int hubdev_docallouts(devfs_handle_t); + + npdap = NODEPDA(cnodeid); + + /* + * Get the "top" vertex for this node's hardware + * graph; it will carry the per-hub hub-specific + * data, and act as the crosstalk provider master. + * It's canonical path is probably something of the + * form /hw/module/%M/slot/%d/node + */ + hubv = cnodeid_to_vertex(cnodeid); + DBG("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap); + + ASSERT(hubv != GRAPH_VERTEX_NONE); + + hubdev_docallouts(hubv); + + /* + * Set up the dependent routers if we have any. + */ + npda_rip = npdap->npda_rip_first; + + while(npda_rip) { + /* If the router info has not been initialized + * then we need to do the router initialization + */ + if (!npda_rip->router_infop) { + router_init(cnodeid,0,npda_rip); + } + npda_rip = npda_rip->router_next; + } + + /* + * Read mfg info on this hub + */ + + /* + * If nothing connected to this hub's xtalk port, we're done. + */ + early_probe_for_widget(hubv, &hwid); + if (hwid.part_num == XWIDGET_PART_NUM_NONE) { +#ifdef PROBE_TEST + if ((cnodeid == 1) || (cnodeid == 2)) { + int index; + + for (index = 0; index < 600; index++) + DBG("Interfering with device probing!!!\n"); + } +#endif + /* io_init_done takes cpu cookie as 2nd argument + * to do a restorenoderun for the setnoderun done + * at the start of this thread + */ + + DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv); + return; + /* NOTREACHED */ + } + + /* + * attach our hub_provider information to hubv, + * so we can use it as a crosstalk provider "master" + * vertex. + */ + xtalk_provider_register(hubv, &hub_provider); + xtalk_provider_startup(hubv); + + /* + * Create a vertex to represent the crosstalk bus + * attached to this hub, and a vertex to be used + * as the connect point for whatever is out there + * on the other side of our crosstalk connection. + * + * Crosstalk Switch drivers "climb up" from their + * connection point to try and take over the switch + * point. + * + * Of course, the edges and verticies may already + * exist, in which case our net effect is just to + * associate the "xtalk_" driver with the connection + * point for the device. + */ + + (void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv); + + DBG("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv); + + ASSERT(switchv != GRAPH_VERTEX_NONE); + + (void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO); + + DBG("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n"); + + /* + * We need to find the widget id and update the basew_id field + * accordingly. In particular, SN00 has direct connected bridge, + * and hence widget id is Not 0. + */ + + widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + WIDGET_ID))) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT; + + if (widget_partnum == BRIDGE_WIDGET_PART_NUM || + widget_partnum == XBRIDGE_WIDGET_PART_NUM){ + npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); + + DBG("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum); + + } else if ((widget_partnum == XBOW_WIDGET_PART_NUM) || + (widget_partnum == XXBOW_WIDGET_PART_NUM) || + (widget_partnum == PXBOW_WIDGET_PART_NUM) ) { + /* + * Xbow control register does not have the widget ID field. + * So, hard code the widget ID to be zero. + */ + DBG("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum); + npdap->basew_id = 0; + + } else { + npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); + + panic(" ****io_init_node: Unknown Widget Part Number 0x%x Widget ID 0x%x attached to Hubv 0x%p ****\n", widget_partnum, npdap->basew_id, (void *)hubv); + + /*NOTREACHED*/ + } + { + char widname[10]; + sprintf(widname, "%x", npdap->basew_id); + (void)hwgraph_path_add(switchv, widname, &widgetv); + DBG("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv); + ASSERT(widgetv != GRAPH_VERTEX_NONE); + } + + nodepda->basew_xc = widgetv; + + is_xswitch = xwidget_hwid_is_xswitch(&hwid); + + /* + * Try to become the master of the widget. If this is an xswitch + * with multiple hubs connected, only one will succeed. Mastership + * of an xswitch is used only when touching registers on that xswitch. + * The slave xwidgets connected to the xswitch can be owned by various + * masters. + */ + if (device_master_set(widgetv, hubv) == 0) { + + /* Only one hub (thread) per Crosstalk device or switch makes + * it to here. + */ + + /* + * Initialize whatever xwidget is hanging off our hub. + * Whatever it is, it's accessible through widgetnum 0. + */ + hubinfo_get(hubv, &hubinfo); + + (void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid, NULL); + + if (!is_xswitch) { + /* io_init_done takes cpu cookie as 2nd argument + * to do a restorenoderun for the setnoderun done + * at the start of this thread + */ + io_init_done(cnodeid,c); + /* NOTREACHED */ + } + + /* + * Special handling for Crosstalk Switches (e.g. xbow). + * We need to do things in roughly the following order: + * 1) Initialize xswitch hardware (done above) + * 2) Determine which hubs are available to be widget masters + * 3) Discover which links are active from the xswitch + * 4) Assign xwidgets hanging off the xswitch to hubs + * 5) Initialize all xwidgets on the xswitch + */ + + volunteer_for_widgets(switchv, hubv); + + /* If there's someone else on this crossbow, recognize him */ + if (npdap->xbow_peer != INVALID_NASID) { + nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer)); + peer_sema = &peer_npdap->xbow_sema; + volunteer_for_widgets(switchv, peer_npdap->node_vertex); + } + + assign_widgets_to_volunteers(switchv, hubv); + + /* Signal that we're done */ + if (peer_sema) { + mutex_unlock(peer_sema); + } + + } + else { + /* Wait 'til master is done assigning widgets. */ + mutex_lock(&npdap->xbow_sema); + } + +#ifdef PROBE_TEST + if ((cnodeid == 1) || (cnodeid == 2)) { + int index; + + for (index = 0; index < 500; index++) + DBG("Interfering with device probing!!!\n"); + } +#endif + /* Now both nodes can safely inititialize widgets */ + io_init_xswitch_widgets(switchv, cnodeid); + io_link_xswitch_widgets(switchv, cnodeid); + + /* io_init_done takes cpu cookie as 2nd argument + * to do a restorenoderun for the setnoderun done + * at the start of this thread + */ + io_init_done(cnodeid,c); + + DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid); +} + + +#define IOINIT_STKSZ (16 * 1024) + +#define __DEVSTR1 "/../.master/" +#define __DEVSTR2 "/target/" +#define __DEVSTR3 "/lun/0/disk/partition/" +#define __DEVSTR4 "/../ef" + +/* + * ioconfig starts numbering SCSI's at NUM_BASE_IO_SCSI_CTLR. + */ +#define NUM_BASE_IO_SCSI_CTLR 6 +/* + * This tells ioconfig where it can start numbering scsi controllers. + * Below this base number, platform-specific handles the numbering. + * XXX Irix legacy..controller numbering should be part of devfsd's job + */ +int num_base_io_scsi_ctlr = 2; /* used by syssgi */ +devfs_handle_t base_io_scsi_ctlr_vhdl[NUM_BASE_IO_SCSI_CTLR]; +static devfs_handle_t baseio_enet_vhdl,baseio_console_vhdl; + +/* + * Put the logical controller number information in the + * scsi controller vertices for each scsi controller that + * is in a "fixed position". + */ +static void +scsi_ctlr_nums_add(devfs_handle_t pci_vhdl) +{ + { + int i; + + num_base_io_scsi_ctlr = NUM_BASE_IO_SCSI_CTLR; + + /* Initialize base_io_scsi_ctlr_vhdl array */ + for (i=0; i +devfs_handle_t sys_critical_graph_root = GRAPH_VERTEX_NONE; + +/* Define the system critical vertices and connect them through + * a canonical parent-child relationships for easy traversal + * during io error handling. + */ +static void +sys_critical_graph_init(void) +{ + devfs_handle_t bridge_vhdl,master_node_vhdl; + devfs_handle_t xbow_vhdl = GRAPH_VERTEX_NONE; + extern devfs_handle_t hwgraph_root; + devfs_handle_t pci_slot_conn; + int slot; + devfs_handle_t baseio_console_conn; + + DBG("sys_critical_graph_init: FIXME.\n"); + baseio_console_conn = hwgraph_connectpt_get(baseio_console_vhdl); + + if (baseio_console_conn == NULL) { + return; + } + + /* Get the vertex handle for the baseio bridge */ + bridge_vhdl = device_master_get(baseio_console_conn); + + /* Get the master node of the baseio card */ + master_node_vhdl = cnodeid_to_vertex( + master_node_get(baseio_console_vhdl)); + + /* Add the "root->node" part of the system critical graph */ + + sys_critical_graph_vertex_add(hwgraph_root,master_node_vhdl); + + /* Check if we have a crossbow */ + if (hwgraph_traverse(master_node_vhdl, + EDGE_LBL_XTALK"/0", + &xbow_vhdl) == GRAPH_SUCCESS) { + /* We have a crossbow.Add "node->xbow" part of the system + * critical graph. + */ + sys_critical_graph_vertex_add(master_node_vhdl,xbow_vhdl); + + /* Add "xbow->baseio bridge" of the system critical graph */ + sys_critical_graph_vertex_add(xbow_vhdl,bridge_vhdl); + + hwgraph_vertex_unref(xbow_vhdl); + } else + /* We donot have a crossbow. Add "node->baseio_bridge" + * part of the system critical graph. + */ + sys_critical_graph_vertex_add(master_node_vhdl,bridge_vhdl); + + /* Add all the populated PCI slot vertices to the system critical + * graph with the bridge vertex as the parent. + */ + for (slot = 0 ; slot < 8; slot++) { + char slot_edge[10]; + + sprintf(slot_edge,"%d",slot); + if (hwgraph_traverse(bridge_vhdl,slot_edge, &pci_slot_conn) + != GRAPH_SUCCESS) + continue; + sys_critical_graph_vertex_add(bridge_vhdl,pci_slot_conn); + hwgraph_vertex_unref(pci_slot_conn); + } + + hwgraph_vertex_unref(bridge_vhdl); + + /* Add the "ioc3 pci connection point -> console ioc3" part + * of the system critical graph + */ + + if (hwgraph_traverse(baseio_console_vhdl,"..",&pci_slot_conn) == + GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + baseio_console_vhdl); + hwgraph_vertex_unref(pci_slot_conn); + } + + /* Add the "ethernet pci connection point -> base ethernet" part of + * the system critical graph + */ + if (hwgraph_traverse(baseio_enet_vhdl,"..",&pci_slot_conn) == + GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + baseio_enet_vhdl); + hwgraph_vertex_unref(pci_slot_conn); + } + + /* Add the "scsi controller pci connection point -> base scsi + * controller" part of the system critical graph + */ + if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[0], + "../..",&pci_slot_conn) == GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + base_io_scsi_ctlr_vhdl[0]); + hwgraph_vertex_unref(pci_slot_conn); + } + if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[1], + "../..",&pci_slot_conn) == GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + base_io_scsi_ctlr_vhdl[1]); + hwgraph_vertex_unref(pci_slot_conn); + } + hwgraph_vertex_unref(baseio_console_conn); + +} + +static void +baseio_ctlr_num_set(void) +{ + char name[MAXDEVNAME]; + devfs_handle_t console_vhdl, pci_vhdl, enet_vhdl; + devfs_handle_t ioc3_console_vhdl_get(void); + + + DBG("baseio_ctlr_num_set; FIXME\n"); + console_vhdl = ioc3_console_vhdl_get(); + if (console_vhdl == GRAPH_VERTEX_NONE) + return; + /* Useful for setting up the system critical graph */ + baseio_console_vhdl = console_vhdl; + + vertex_to_name(console_vhdl,name,MAXDEVNAME); + + strcat(name,__DEVSTR1); + pci_vhdl = hwgraph_path_to_vertex(name); + scsi_ctlr_nums_add(pci_vhdl); + /* Unref the pci_vhdl due to the reference by hwgraph_path_to_vertex + */ + hwgraph_vertex_unref(pci_vhdl); + + vertex_to_name(console_vhdl, name, MAXDEVNAME); + strcat(name, __DEVSTR4); + enet_vhdl = hwgraph_path_to_vertex(name); + + /* Useful for setting up the system critical graph */ + baseio_enet_vhdl = enet_vhdl; + + device_controller_num_set(enet_vhdl, 0); + /* Unref the enet_vhdl due to the reference by hwgraph_path_to_vertex + */ + hwgraph_vertex_unref(enet_vhdl); +} +/* #endif */ + +/* + * Initialize all I/O devices. Starting closest to nodes, probe and + * initialize outward. + */ +void +init_all_devices(void) +{ + /* Governor on init threads..bump up when safe + * (beware many devfs races) + */ + cnodeid_t cnodeid, active; + + active = 0; + for (cnodeid = 0; cnodeid < numnodes; cnodeid++) { + DBG("init_all_devices: Calling io_init_node() for cnode %d\n", cnodeid); + io_init_node(cnodeid); + + DBG("init_all_devices: Done io_init_node() for cnode %d\n", cnodeid); + } + + for (cnodeid = 0; cnodeid < numnodes; cnodeid++) + /* + * Update information generated by IO init. + */ + update_node_information(cnodeid); + + baseio_ctlr_num_set(); + /* Setup the system critical graph (which is a subgraph of the + * main hwgraph). This information is useful during io error + * handling. + */ + sys_critical_graph_init(); + +#if HWG_PRINT + hwgraph_print(); +#endif + +} + +#define toint(x) ((int)(x) - (int)('0')) + +void +devnamefromarcs(char *devnm) +{ + int val; + char tmpnm[MAXDEVNAME]; + char *tmp1, *tmp2; + + val = strncmp(devnm, "dks", 3); + if (val != 0) + return; + tmp1 = devnm + 3; + if (!isdigit(*tmp1)) + return; + + val = 0; + while (isdigit(*tmp1)) { + val = 10*val+toint(*tmp1); + tmp1++; + } + + if(*tmp1 != 'd') + return; + else + tmp1++; + + if ((val < 0) || (val >= num_base_io_scsi_ctlr)) { + int i; + int viable_found = 0; + + DBG("Only controller numbers 0..%d are supported for\n", NUM_BASE_IO_SCSI_CTLR-1); + DBG("prom \"root\" variables of the form dksXdXsX.\n"); + DBG("To use another disk you must use the full hardware graph path\n\n"); + DBG("Possible controller numbers for use in 'dksXdXsX' on this system: "); + for (i=0; i XBOW_PORT_F) + return 0; + + /* Find "brick" in the path name */ + bp = strstr(hw_path_name, "brick"); + if (bp == NULL) + return 0; + + /* Find preceding slash */ + sp = bp; + while (sp > hw_path_name) { + sp--; + if (*sp == '/') + break; + } + + /* Invalid if no preceding slash */ + if (!sp) + return 0; + + /* Bump slash pointer to "brick" prefix */ + sp++; + /* + * Verify "brick" prefix length; valid exaples: + * 'I' from "/Ibrick" + * 'P' from "/Pbrick" + * 'X' from "/Xbrick" + */ + if ((bp - sp) != 1) + return 0; + + return (io_brick_map_widget((int)*sp, widget_num)); + +} diff -Nru a/arch/ia64/sn/io/sn2/module.c b/arch/ia64/sn/io/sn2/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/module.c Mon Feb 24 05:25:25 2003 @@ -0,0 +1,280 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* #define LDEBUG 1 */ + +#ifdef LDEBUG +#define DPRINTF printk +#define printf printk +#else +#define DPRINTF(x...) +#endif + +module_t *modules[MODULE_MAX]; +int nummodules; + +#define SN00_SERIAL_FUDGE 0x3b1af409d513c2 +#define SN0_SERIAL_FUDGE 0x6e + +void +encode_int_serial(uint64_t src,uint64_t *dest) +{ + uint64_t val; + int i; + + val = src + SN00_SERIAL_FUDGE; + + + for (i = 0; i < sizeof(long long); i++) { + ((char*)dest)[i] = + ((char*)&val)[sizeof(long long)/2 + + ((i%2) ? ((i/2 * -1) - 1) : (i/2))]; + } +} + + +void +decode_int_serial(uint64_t src, uint64_t *dest) +{ + uint64_t val; + int i; + + for (i = 0; i < sizeof(long long); i++) { + ((char*)&val)[sizeof(long long)/2 + + ((i%2) ? ((i/2 * -1) - 1) : (i/2))] = + ((char*)&src)[i]; + } + + *dest = val - SN00_SERIAL_FUDGE; +} + + +void +encode_str_serial(const char *src, char *dest) +{ + int i; + + for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) { + + dest[i] = src[MAX_SERIAL_NUM_SIZE/2 + + ((i%2) ? ((i/2 * -1) - 1) : (i/2))] + + SN0_SERIAL_FUDGE; + } +} + +void +decode_str_serial(const char *src, char *dest) +{ + int i; + + for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) { + dest[MAX_SERIAL_NUM_SIZE/2 + + ((i%2) ? ((i/2 * -1) - 1) : (i/2))] = src[i] - + SN0_SERIAL_FUDGE; + } +} + + +module_t *module_lookup(moduleid_t id) +{ + int i; + + for (i = 0; i < nummodules; i++) + if (modules[i]->id == id) { + DPRINTF("module_lookup: found m=0x%p\n", modules[i]); + return modules[i]; + } + + return NULL; +} + +/* + * module_add_node + * + * The first time a new module number is seen, a module structure is + * inserted into the module list in order sorted by module number + * and the structure is initialized. + * + * The node number is added to the list of nodes in the module. + */ + +module_t *module_add_node(geoid_t geoid, cnodeid_t cnodeid) +{ + module_t *m; + int i; + char buffer[16]; + moduleid_t moduleid; + + memset(buffer, 0, 16); + moduleid = geo_module(geoid); + format_module_id(buffer, moduleid, MODULE_FORMAT_BRIEF); + DPRINTF("module_add_node: moduleid=%s node=%d\n", buffer, cnodeid); + + if ((m = module_lookup(moduleid)) == 0) { + m = kmalloc(sizeof (module_t), GFP_KERNEL); + memset(m, 0 , sizeof(module_t)); + ASSERT_ALWAYS(m); + + m->id = moduleid; + spin_lock_init(&m->lock); + + mutex_init_locked(&m->thdcnt); + + /* Insert in sorted order by module number */ + + for (i = nummodules; i > 0 && modules[i - 1]->id > moduleid; i--) + modules[i] = modules[i - 1]; + + modules[i] = m; + nummodules++; + } + + m->nodes[m->nodecnt] = cnodeid; + m->geoid[m->nodecnt] = geoid; + m->nodecnt++; + + DPRINTF("module_add_node: module %s now has %d nodes\n", buffer, m->nodecnt); + + return m; +} + +int module_probe_snum(module_t *m, nasid_t nasid) +{ + lboard_t *board; + klmod_serial_num_t *comp; + char * bcopy(const char * src, char * dest, int count); + char serial_number[16]; + + /* + * record brick serial number + */ + board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + + if (! board || KL_CONFIG_DUPLICATE_BOARD(board)) + { +#if LDEBUG + printf ("module_probe_snum: no IP35 board found!\n"); +#endif + return 0; + } + + board_serial_number_get( board, serial_number ); + if( serial_number[0] != '\0' ) { + encode_str_serial( serial_number, m->snum.snum_str ); + m->snum_valid = 1; + } +#if LDEBUG + else { + printf("module_probe_snum: brick serial number is null!\n"); + } + printf("module_probe_snum: brick serial number == %s\n", serial_number); +#endif /* DEBUG */ + + board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), + KLTYPE_IOBRICK_XBOW); + + if (! board || KL_CONFIG_DUPLICATE_BOARD(board)) + return 0; + + comp = GET_SNUM_COMP(board); + + if (comp) { +#if LDEBUG + int i; + + printf("********found module with id %x and string", m->id); + + for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) + printf(" %x ", comp->snum.snum_str[i]); + + printf("\n"); /* Fudged string is not ASCII */ +#endif + + if (comp->snum.snum_str[0] != '\0') { + bcopy(comp->snum.snum_str, + m->sys_snum, + MAX_SERIAL_NUM_SIZE); + m->sys_snum_valid = 1; + } + } + + if (m->sys_snum_valid) + return 1; + else { + DPRINTF("Invalid serial number for module %d, " + "possible missing or invalid NIC.", m->id); + return 0; + } +} + +void +io_module_init(void) +{ + cnodeid_t node; + lboard_t *board; + nasid_t nasid; + int nserial; + module_t *m; + + DPRINTF("*******module_init\n"); + + nserial = 0; + + for (node = 0; node < numnodes; node++) { + nasid = COMPACT_TO_NASID_NODEID(node); + + board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + ASSERT(board); + + m = module_add_node(board->brd_geoid, node); + + if (! m->snum_valid && module_probe_snum(m, nasid)) + nserial++; + } + + DPRINTF("********found total of %d serial numbers in the system\n", + nserial); + + if (nserial == 0) + DPRINTF(KERN_WARNING "io_module_init: No serial number found.\n"); +} + +int +get_kmod_info(cmoduleid_t cmod, module_info_t *mod_info) +{ + if (cmod < 0 || cmod >= nummodules) + return -EINVAL; + + mod_info->mod_num = modules[cmod]->id; + + ia64_sn_sys_serial_get(mod_info->serial_str); + + mod_info->serial_num = ia64_sn_partition_serial_get(); + + return 0; +} diff -Nru a/arch/ia64/sn/io/sn2/pci_bus_cvlink.c b/arch/ia64/sn/io/sn2/pci_bus_cvlink.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/pci_bus_cvlink.c Mon Feb 24 05:25:42 2003 @@ -0,0 +1,725 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int bridge_rev_b_data_check_disable; + +devfs_handle_t busnum_to_pcibr_vhdl[MAX_PCI_XWIDGET]; +nasid_t busnum_to_nid[MAX_PCI_XWIDGET]; +void * busnum_to_atedmamaps[MAX_PCI_XWIDGET]; +unsigned char num_bridges; +static int done_probing = 0; + +static int pci_bus_map_create(devfs_handle_t xtalk, char * io_moduleid); +devfs_handle_t devfn_to_vertex(unsigned char busnum, unsigned int devfn); + +extern unsigned char Is_pic_on_this_nasid[512]; + +extern void sn_init_irq_desc(void); +extern void register_pcibr_intr(int irq, pcibr_intr_t intr); + + +/* + * For the given device, initialize whether it is a PIC device. + */ +static void +set_isPIC(struct sn_device_sysdata *device_sysdata) +{ + pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + + device_sysdata->isPIC = IS_PIC_SOFT(pcibr_soft);; +} + +/* + * pci_bus_cvlink_init() - To be called once during initialization before + * SGI IO Infrastructure init is called. + */ +void +pci_bus_cvlink_init(void) +{ + + extern void ioconfig_bus_init(void); + + memset(busnum_to_pcibr_vhdl, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET); + memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET); + + memset(busnum_to_atedmamaps, 0x0, sizeof(void *) * MAX_PCI_XWIDGET); + + num_bridges = 0; + + ioconfig_bus_init(); +} + +/* + * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated + * pci bus vertex from the SGI IO Infrastructure. + */ +devfs_handle_t +pci_bus_to_vertex(unsigned char busnum) +{ + + devfs_handle_t pci_bus = NULL; + + + /* + * First get the xwidget vertex. + */ + pci_bus = busnum_to_pcibr_vhdl[busnum]; + return(pci_bus); +} + +/* + * devfn_to_vertex() - returns the vertex of the device given the bus, slot, + * and function numbers. + */ +devfs_handle_t +devfn_to_vertex(unsigned char busnum, unsigned int devfn) +{ + + int slot = 0; + int func = 0; + char name[16]; + devfs_handle_t pci_bus = NULL; + devfs_handle_t device_vertex = (devfs_handle_t)NULL; + + /* + * Go get the pci bus vertex. + */ + pci_bus = pci_bus_to_vertex(busnum); + if (!pci_bus) { + /* + * During probing, the Linux pci code invents non existant + * bus numbers and pci_dev structures and tries to access + * them to determine existance. Don't crib during probing. + */ + if (done_probing) + printk("devfn_to_vertex: Invalid bus number %d given.\n", busnum); + return(NULL); + } + + + /* + * Go get the slot&function vertex. + * Should call pciio_slot_func_to_name() when ready. + */ + slot = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + /* + * For a NON Multi-function card the name of the device looks like: + * ../pci/1, ../pci/2 .. + */ + if (func == 0) { + sprintf(name, "%d", slot); + if (hwgraph_traverse(pci_bus, name, &device_vertex) == + GRAPH_SUCCESS) { + if (device_vertex) { + return(device_vertex); + } + } + } + + /* + * This maybe a multifunction card. It's names look like: + * ../pci/1a, ../pci/1b, etc. + */ + sprintf(name, "%d%c", slot, 'a'+func); + if (hwgraph_traverse(pci_bus, name, &device_vertex) != GRAPH_SUCCESS) { + if (!device_vertex) { + return(NULL); + } + } + + return(device_vertex); +} + +/* + * For the given device, initialize the addresses for both the Device(x) Flush + * Write Buffer register and the Xbow Flush Register for the port the PCI bus + * is connected. + */ +static void +set_flush_addresses(struct pci_dev *device_dev, + struct sn_device_sysdata *device_sysdata) +{ + pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl); + pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); + bridge_t *bridge = pcibr_soft->bs_base; + nasid_t nasid; + + /* + * Get the nasid from the bridge. + */ + nasid = NASID_GET(device_sysdata->dma_buf_sync); + if (IS_PIC_DEVICE(device_dev)) { + device_sysdata->dma_buf_sync = (volatile unsigned int *) + &bridge->b_wr_req_buf[pciio_slot].reg; + device_sysdata->xbow_buf_sync = (volatile unsigned int *) + XBOW_PRIO_LINKREGS_PTR(NODE_SWIN_BASE(nasid, 0), + pcibr_soft->bs_xid); + } else { + /* + * Accessing Xbridge and Xbow register when SHUB swapoper is on!. + */ + device_sysdata->dma_buf_sync = (volatile unsigned int *) + ((uint64_t)&(bridge->b_wr_req_buf[pciio_slot].reg)^4); + device_sysdata->xbow_buf_sync = (volatile unsigned int *) + ((uint64_t)(XBOW_PRIO_LINKREGS_PTR( + NODE_SWIN_BASE(nasid, 0), pcibr_soft->bs_xid)) ^ 4); + } + +#ifdef DEBUG + printk("set_flush_addresses: dma_buf_sync %p xbow_buf_sync %p\n", + device_sysdata->dma_buf_sync, device_sysdata->xbow_buf_sync); + +printk("set_flush_addresses: dma_buf_sync\n"); + while((volatile unsigned int )*device_sysdata->dma_buf_sync); +printk("set_flush_addresses: xbow_buf_sync\n"); + while((volatile unsigned int )*device_sysdata->xbow_buf_sync); +#endif + +} + +/* + * Most drivers currently do not properly tell the arch specific pci dma + * interfaces whether they can handle A64. Here is where we privately + * keep track of this. + */ +static void __init +set_sn_pci64(struct pci_dev *dev) +{ + unsigned short vendor = dev->vendor; + unsigned short device = dev->device; + + if (vendor == PCI_VENDOR_ID_QLOGIC) { + if ((device == PCI_DEVICE_ID_QLOGIC_ISP2100) || + (device == PCI_DEVICE_ID_QLOGIC_ISP2200)) { + SET_PCIA64(dev); + return; + } + } + + if (vendor == PCI_VENDOR_ID_SGI) { + if (device == PCI_DEVICE_ID_SGI_IOC3) { + SET_PCIA64(dev); + return; + } + } + +} + +/* + * sn_pci_fixup() - This routine is called when platform_pci_fixup() is + * invoked at the end of pcibios_init() to link the Linux pci + * infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c + * + * Other platform specific fixup can also be done here. + */ +void +sn_pci_fixup(int arg) +{ + struct list_head *ln; + struct pci_bus *pci_bus = NULL; + struct pci_dev *device_dev = NULL; + struct sn_widget_sysdata *widget_sysdata; + struct sn_device_sysdata *device_sysdata; + pciio_intr_t intr_handle; + int cpuid, bit; + devfs_handle_t device_vertex; + pciio_intr_line_t lines; + extern void sn_pci_find_bios(void); + extern int numnodes; + int cnode; + extern void io_sh_swapper(int, int); + + for (cnode = 0; cnode < numnodes; cnode++) { + if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] ) + io_sh_swapper((cnodeid_to_nasid(cnode)), 0); + } + + if (arg == 0) { +#ifdef CONFIG_PROC_FS + extern void register_sn_procfs(void); +#endif + + sn_init_irq_desc(); + sn_pci_find_bios(); + for (cnode = 0; cnode < numnodes; cnode++) { + extern void intr_init_vecblk(nodepda_t *npda, cnodeid_t, int); + intr_init_vecblk(NODEPDA(cnode), cnode, 0); + } + + /* + * When we return to generic Linux, Swapper is always on .. + */ + for (cnode = 0; cnode < numnodes; cnode++) { + if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] ) + io_sh_swapper((cnodeid_to_nasid(cnode)), 1); + } +#ifdef CONFIG_PROC_FS + register_sn_procfs(); +#endif + return; + } + + + done_probing = 1; + + /* + * Initialize the pci bus vertex in the pci_bus struct. + */ + for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { + pci_bus = pci_bus_b(ln); + widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), + GFP_KERNEL); + widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number); + pci_bus->sysdata = (void *)widget_sysdata; + } + + /* + * set the root start and end so that drivers calling check_region() + * won't see a conflict + */ + ioport_resource.start = 0xc000000000000000; + ioport_resource.end = 0xcfffffffffffffff; + + /* + * Set the root start and end for Mem Resource. + */ + iomem_resource.start = 0; + iomem_resource.end = 0xffffffffffffffff; + + /* + * Initialize the device vertex in the pci_dev struct. + */ + pci_for_each_dev(device_dev) { + unsigned int irq; + int idx; + u16 cmd; + devfs_handle_t vhdl; + unsigned long size; + extern int bit_pos_to_irq(int); + + if (device_dev->vendor == PCI_VENDOR_ID_SGI && + device_dev->device == PCI_DEVICE_ID_SGI_IOC3) { + extern void pci_fixup_ioc3(struct pci_dev *d); + pci_fixup_ioc3(device_dev); + } + + /* Set the device vertex */ + + device_sysdata = kmalloc(sizeof(struct sn_device_sysdata), + GFP_KERNEL); + device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn); + device_sysdata->isa64 = 0; + /* + * Set the xbridge Device(X) Write Buffer Flush and Xbow Flush + * register addresses. + */ + (void) set_flush_addresses(device_dev, device_sysdata); + + device_dev->sysdata = (void *) device_sysdata; + set_sn_pci64(device_dev); + set_isPIC(device_sysdata); + + pci_read_config_word(device_dev, PCI_COMMAND, &cmd); + + /* + * Set the resources address correctly. The assumption here + * is that the addresses in the resource structure has been + * read from the card and it was set in the card by our + * Infrastructure .. + */ + vhdl = device_sysdata->vhdl; + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + size = 0; + size = device_dev->resource[idx].end - + device_dev->resource[idx].start; + if (size) { + device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM); + device_dev->resource[idx].start |= __IA64_UNCACHED_OFFSET; + } + else + continue; + + device_dev->resource[idx].end = + device_dev->resource[idx].start + size; + + if (device_dev->resource[idx].flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + + if (device_dev->resource[idx].flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } +#if 0 + /* + * Software WAR for a Software BUG. + * This is only temporary. + * See PV 872791 + */ + + /* + * Now handle the ROM resource .. + */ + size = device_dev->resource[PCI_ROM_RESOURCE].end - + device_dev->resource[PCI_ROM_RESOURCE].start; + + if (size) { + device_dev->resource[PCI_ROM_RESOURCE].start = + (unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0, + size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM); + device_dev->resource[PCI_ROM_RESOURCE].start |= __IA64_UNCACHED_OFFSET; + device_dev->resource[PCI_ROM_RESOURCE].end = + device_dev->resource[PCI_ROM_RESOURCE].start + size; + } +#endif + + /* + * Update the Command Word on the Card. + */ + cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */ + /* bit gets dropped .. no harm */ + pci_write_config_word(device_dev, PCI_COMMAND, cmd); + + pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines); + if (device_dev->vendor == PCI_VENDOR_ID_SGI && + device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) { + lines = 1; + } + + device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata; + device_vertex = device_sysdata->vhdl; + + intr_handle = pciio_intr_alloc(device_vertex, NULL, lines, device_vertex); + + bit = intr_handle->pi_irq; + cpuid = intr_handle->pi_cpu; + irq = bit; + irq = irq + (cpuid << 8); + pciio_intr_connect(intr_handle, (intr_func_t)0, (intr_arg_t)0); + device_dev->irq = irq; + register_pcibr_intr(irq, (pcibr_intr_t)intr_handle); +#ifdef ajmtestintr + { + int slot = PCI_SLOT(device_dev->devfn); + static int timer_set = 0; + pcibr_intr_t pcibr_intr = (pcibr_intr_t)intr_handle; + pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft; + extern void intr_test_handle_intr(int, void*, struct pt_regs *); + + if (!timer_set) { + intr_test_set_timer(); + timer_set = 1; + } + intr_test_register_irq(irq, pcibr_soft, slot); + request_irq(irq, intr_test_handle_intr,0,NULL, NULL); + } +#endif + + } + + for (cnode = 0; cnode < numnodes; cnode++) { + if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] ) + io_sh_swapper((cnodeid_to_nasid(cnode)), 1); + } +} + +/* + * linux_bus_cvlink() Creates a link between the Linux PCI Bus number + * to the actual hardware component that it represents: + * /dev/hw/linux/busnum/0 -> ../../../hw/module/001c01/slab/0/Ibrick/xtalk/15/pci + * + * The bus vertex, when called to devfs_generate_path() returns: + * hw/module/001c01/slab/0/Ibrick/xtalk/15/pci + * hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/0 + * hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/1 + */ +void +linux_bus_cvlink(void) +{ + char name[8]; + int index; + + for (index=0; index < MAX_PCI_XWIDGET; index++) { + if (!busnum_to_pcibr_vhdl[index]) + continue; + + sprintf(name, "%x", index); + (void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], + name); + } +} + +/* + * pci_bus_map_create() - Called by pci_bus_to_hcl_cvlink() to finish the job. + * + * Linux PCI Bus numbers are assigned from lowest module_id numbers + * (rack/slot etc.) starting from HUB_WIDGET_ID_MAX down to + * HUB_WIDGET_ID_MIN: + * widgetnum 15 gets lower Bus Number than widgetnum 14 etc. + * + * Given 2 modules 001c01 and 001c02 we get the following mappings: + * 001c01, widgetnum 15 = Bus number 0 + * 001c01, widgetnum 14 = Bus number 1 + * 001c02, widgetnum 15 = Bus number 3 + * 001c02, widgetnum 14 = Bus number 4 + * etc. + * + * The rational for starting Bus Number 0 with Widget number 15 is because + * the system boot disks are always connected via Widget 15 Slot 0 of the + * I-brick. Linux creates /dev/sd* devices(naming) strating from Bus Number 0 + * Therefore, /dev/sda1 will be the first disk, on Widget 15 of the lowest + * module id(Master Cnode) of the system. + * + */ +static int +pci_bus_map_create(devfs_handle_t xtalk, char * io_moduleid) +{ + + devfs_handle_t master_node_vertex = NULL; + devfs_handle_t xwidget = NULL; + devfs_handle_t pci_bus = NULL; + hubinfo_t hubinfo = NULL; + xwidgetnum_t widgetnum; + char pathname[128]; + graph_error_t rv; + int bus; + int basebus_num; + int bus_number; + + /* + * Loop throught this vertex and get the Xwidgets .. + */ + + + /* PCI devices */ + + for (widgetnum = HUB_WIDGET_ID_MAX; widgetnum >= HUB_WIDGET_ID_MIN; widgetnum--) { + sprintf(pathname, "%d", widgetnum); + xwidget = NULL; + + /* + * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget + * /hw/module/001c16/Pbrick/xtalk/8/pci/1 is device + */ + rv = hwgraph_traverse(xtalk, pathname, &xwidget); + if ( (rv != GRAPH_SUCCESS) ) { + if (!xwidget) { + continue; + } + } + + sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum); + pci_bus = NULL; + if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS) + if (!pci_bus) { + continue; +} + + /* + * Assign the correct bus number and also the nasid of this + * pci Xwidget. + * + * Should not be any race here ... + */ + num_bridges++; + busnum_to_pcibr_vhdl[num_bridges - 1] = pci_bus; + + /* + * Get the master node and from there get the NASID. + */ + master_node_vertex = device_master_get(xwidget); + if (!master_node_vertex) { + printk("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", (void *)xwidget); + } + + hubinfo_get(master_node_vertex, &hubinfo); + if (!hubinfo) { + printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", (void *)master_node_vertex); + return(1); + } else { + busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid; + } + + /* + * Pre assign DMA maps needed for 32 Bits Page Map DMA. + */ + busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc( + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL); + if (!busnum_to_atedmamaps[num_bridges - 1]) + printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget); + + memset(busnum_to_atedmamaps[num_bridges - 1], 0x0, + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS); + + } + + /* + * PCIX devices + * We number busses differently for PCI-X devices. + * We start from Lowest Widget on up .. + */ + + (void) ioconfig_get_busnum((char *)io_moduleid, &basebus_num); + + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { + + /* Do both buses */ + for ( bus = 0; bus < 2; bus++ ) { + sprintf(pathname, "%d", widgetnum); + xwidget = NULL; + + /* + * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget + * /hw/module/001c16/Pbrick/xtalk/8/pci-x/0 is the bus + * /hw/module/001c16/Pbrick/xtalk/8/pci-x/0/1 is device + */ + rv = hwgraph_traverse(xtalk, pathname, &xwidget); + if ( (rv != GRAPH_SUCCESS) ) { + if (!xwidget) { + continue; + } + } + + if ( bus == 0 ) + sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum); + else + sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum); + pci_bus = NULL; + if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS) + if (!pci_bus) { + continue; + } + + /* + * Assign the correct bus number and also the nasid of this + * pci Xwidget. + * + * Should not be any race here ... + */ + bus_number = basebus_num + bus + io_brick_map_widget(MODULE_PXBRICK, widgetnum); +#ifdef DEBUG + printk("bus_number %d basebus_num %d bus %d io %d\n", + bus_number, basebus_num, bus, + io_brick_map_widget(MODULE_PXBRICK, widgetnum)); +#endif + busnum_to_pcibr_vhdl[bus_number] = pci_bus; + + /* + * Pre assign DMA maps needed for 32 Bits Page Map DMA. + */ + busnum_to_atedmamaps[bus_number] = (void *) kmalloc( + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL); + if (!busnum_to_atedmamaps[bus_number]) + printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget); + + memset(busnum_to_atedmamaps[bus_number], 0x0, + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS); + } + } + + return(0); +} + +/* + * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure + * initialization has completed to set up the mappings between Xbridge + * and logical pci bus numbers. We also set up the NASID for each of these + * xbridges. + * + * Must be called before pci_init() is invoked. + */ +int +pci_bus_to_hcl_cvlink(void) +{ + + devfs_handle_t devfs_hdl = NULL; + devfs_handle_t xtalk = NULL; + int rv = 0; + char name[256]; + char tmp_name[256]; + int i, ii; + + /* + * Figure out which IO Brick is connected to the Compute Bricks. + */ + for (i = 0; i < nummodules; i++) { + extern int iomoduleid_get(nasid_t); + moduleid_t iobrick_id; + nasid_t nasid = -1; + int nodecnt; + int n = 0; + + nodecnt = modules[i]->nodecnt; + for ( n = 0; n < nodecnt; n++ ) { + nasid = cnodeid_to_nasid(modules[i]->nodes[n]); + iobrick_id = iomoduleid_get(nasid); + if ((int)iobrick_id > 0) { /* Valid module id */ + char name[12]; + memset(name, 0, 12); + format_module_id((char *)&(modules[i]->io[n].moduleid), iobrick_id, MODULE_FORMAT_BRIEF); + } + } + } + + devfs_hdl = hwgraph_path_to_vertex("/dev/hw/module"); + for (i = 0; i < nummodules ; i++) { + for ( ii = 0; ii < 2 ; ii++ ) { + memset(name, 0, 256); + memset(tmp_name, 0, 256); + format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF); + sprintf(tmp_name, "/slab/%d/Pbrick/xtalk", geo_slab(modules[i]->geoid[ii])); + strcat(name, tmp_name); + xtalk = NULL; + rv = hwgraph_edge_get(devfs_hdl, name, &xtalk); + pci_bus_map_create(xtalk, (char *)&(modules[i]->io[ii].moduleid)); + } + } + + /* + * Create the Linux PCI bus number vertex link. + */ + (void)linux_bus_cvlink(); + (void)ioconfig_bus_new_entries(); + + return(0); +} diff -Nru a/arch/ia64/sn/io/sn2/pcibr/Makefile b/arch/ia64/sn/io/sn2/pcibr/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/pcibr/Makefile Mon Feb 24 05:40:54 2003 @@ -0,0 +1,19 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. +# +# Makefile for the sn2 specific pci bridge routines. + +EXTRA_CFLAGS := -DLITTLE_ENDIAN + +ifdef CONFIG_IA64_SGI_SN2 +EXTRA_CFLAGS += -DSHUB_SWAP_WAR +endif + +obj-$(CONFIG_IA64_SGI_SN2) += pcibr_dvr.o pcibr_ate.o pcibr_config.o \ + pcibr_dvr.o pcibr_hints.o \ + pcibr_intr.o pcibr_rrb.o pcibr_slot.o \ + pcibr_error.o diff -Nru a/arch/ia64/sn/io/sn2/pciio.c b/arch/ia64/sn/io/sn2/pciio.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/pciio.c Mon Feb 24 05:30:35 2003 @@ -0,0 +1,1877 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#define USRPCI 0 + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Must be before iograph.h to get MAX_PORT_NUM */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __ia64 +#define rmallocmap atemapalloc +#define rmfreemap atemapfree +#define rmfree atefree +#define rmalloc atealloc +#endif + +#define DEBUG_PCIIO +#undef DEBUG_PCIIO /* turn this on for yet more console output */ + + +#define GET_NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DO_DEL(ptr) (kfree(ptr)) + +char pciio_info_fingerprint[] = "pciio_info"; + +cdl_p pciio_registry = NULL; + +int +badaddr_val(volatile void *addr, int len, volatile void *ptr) +{ + int ret = 0; + volatile void *new_addr; + + switch (len) { + case 4: + new_addr = (void *) addr; + ret = ia64_sn_probe_io_slot((long)new_addr, len, (void *)ptr); + break; + default: + printk(KERN_WARNING "badaddr_val given len %x but supports len of 4 only\n", len); + } + + if (ret < 0) + panic("badaddr_val: unexpected status (%d) in probing", ret); + return(ret); + +} + + +nasid_t +get_console_nasid(void) +{ + extern nasid_t console_nasid; + extern nasid_t master_baseio_nasid; + + if (console_nasid < 0) { + console_nasid = ia64_sn_get_console_nasid(); + if (console_nasid < 0) { +// ZZZ What do we do if we don't get a console nasid on the hardware???? + if (IS_RUNNING_ON_SIMULATOR() ) + console_nasid = master_baseio_nasid; + } + } + return console_nasid; +} + +nasid_t +get_master_baseio_nasid(void) +{ + extern nasid_t master_baseio_nasid; + extern char master_baseio_wid; + + if (master_baseio_nasid < 0) { + nasid_t tmp; + + master_baseio_nasid = ia64_sn_get_master_baseio_nasid(); + + if ( master_baseio_nasid >= 0 ) { + master_baseio_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_baseio_nasid)->memory_base); + } + } + return master_baseio_nasid; +} + +int +hub_dma_enabled(devfs_handle_t xconn_vhdl) +{ + return(0); +} + +int +hub_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code) +{ + return(0); +} + +void +ioerror_dump(char *name, int error_code, int error_mode, ioerror_t *ioerror) +{ +} + +/****** + ****** end hack defines ...... + ******/ + + + + +/* ===================================================================== + * PCI Generic Bus Provider + * Implement PCI provider operations. The pciio* layer provides a + * platform-independent interface for PCI devices. This layer + * switches among the possible implementations of a PCI adapter. + */ + +/* ===================================================================== + * Provider Function Location SHORTCUT + * + * On platforms with only one possible PCI provider, macros can be + * set up at the top that cause the table lookups and indirections to + * completely disappear. + */ + + +/* ===================================================================== + * Function Table of Contents + */ + +#if !defined(DEV_FUNC) +static pciio_provider_t *pciio_to_provider_fns(devfs_handle_t dev); +#endif + +pciio_piomap_t pciio_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned); +void pciio_piomap_free(pciio_piomap_t); +caddr_t pciio_piomap_addr(pciio_piomap_t, iopaddr_t, size_t); + +void pciio_piomap_done(pciio_piomap_t); +caddr_t pciio_piotrans_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned); +caddr_t pciio_pio_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, pciio_piomap_t *, unsigned); + +iopaddr_t pciio_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t); +void pciio_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t); + +pciio_dmamap_t pciio_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned); +void pciio_dmamap_free(pciio_dmamap_t); +iopaddr_t pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t); +alenlist_t pciio_dmamap_list(pciio_dmamap_t, alenlist_t, unsigned); +void pciio_dmamap_done(pciio_dmamap_t); +iopaddr_t pciio_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); +alenlist_t pciio_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +void pciio_dmamap_drain(pciio_dmamap_t); +void pciio_dmaaddr_drain(devfs_handle_t, paddr_t, size_t); +void pciio_dmalist_drain(devfs_handle_t, alenlist_t); +iopaddr_t pciio_dma_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, pciio_dmamap_t *, unsigned); + +pciio_intr_t pciio_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t); +void pciio_intr_free(pciio_intr_t); +int pciio_intr_connect(pciio_intr_t, intr_func_t, intr_arg_t); +void pciio_intr_disconnect(pciio_intr_t); +devfs_handle_t pciio_intr_cpu_get(pciio_intr_t); + +void pciio_slot_func_to_name(char *, pciio_slot_t, pciio_function_t); + +void pciio_provider_startup(devfs_handle_t); +void pciio_provider_shutdown(devfs_handle_t); + +pciio_endian_t pciio_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t); +pciio_priority_t pciio_priority_set(devfs_handle_t, pciio_priority_t); +devfs_handle_t pciio_intr_dev_get(pciio_intr_t); + +devfs_handle_t pciio_pio_dev_get(pciio_piomap_t); +pciio_slot_t pciio_pio_slot_get(pciio_piomap_t); +pciio_space_t pciio_pio_space_get(pciio_piomap_t); +iopaddr_t pciio_pio_pciaddr_get(pciio_piomap_t); +ulong pciio_pio_mapsz_get(pciio_piomap_t); +caddr_t pciio_pio_kvaddr_get(pciio_piomap_t); + +devfs_handle_t pciio_dma_dev_get(pciio_dmamap_t); +pciio_slot_t pciio_dma_slot_get(pciio_dmamap_t); + +pciio_info_t pciio_info_chk(devfs_handle_t); +pciio_info_t pciio_info_get(devfs_handle_t); +void pciio_info_set(devfs_handle_t, pciio_info_t); +devfs_handle_t pciio_info_dev_get(pciio_info_t); +pciio_slot_t pciio_info_slot_get(pciio_info_t); +pciio_function_t pciio_info_function_get(pciio_info_t); +pciio_vendor_id_t pciio_info_vendor_id_get(pciio_info_t); +pciio_device_id_t pciio_info_device_id_get(pciio_info_t); +devfs_handle_t pciio_info_master_get(pciio_info_t); +arbitrary_info_t pciio_info_mfast_get(pciio_info_t); +pciio_provider_t *pciio_info_pops_get(pciio_info_t); +error_handler_f *pciio_info_efunc_get(pciio_info_t); +error_handler_arg_t *pciio_info_einfo_get(pciio_info_t); +pciio_space_t pciio_info_bar_space_get(pciio_info_t, int); +iopaddr_t pciio_info_bar_base_get(pciio_info_t, int); +size_t pciio_info_bar_size_get(pciio_info_t, int); +iopaddr_t pciio_info_rom_base_get(pciio_info_t); +size_t pciio_info_rom_size_get(pciio_info_t); + +void pciio_init(void); +int pciio_attach(devfs_handle_t); + +void pciio_provider_register(devfs_handle_t, pciio_provider_t *pciio_fns); +void pciio_provider_unregister(devfs_handle_t); +pciio_provider_t *pciio_provider_fns_get(devfs_handle_t); + +int pciio_driver_register(pciio_vendor_id_t, pciio_device_id_t, char *driver_prefix, unsigned); +void pciio_driver_unregister(char *driver_prefix); + +devfs_handle_t pciio_device_register(devfs_handle_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); + +void pciio_device_unregister(devfs_handle_t); +pciio_info_t pciio_device_info_new(pciio_info_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); +void pciio_device_info_free(pciio_info_t); +devfs_handle_t pciio_device_info_register(devfs_handle_t, pciio_info_t); +void pciio_device_info_unregister(devfs_handle_t, pciio_info_t); +int pciio_device_attach(devfs_handle_t, int); +int pciio_device_detach(devfs_handle_t, int); +void pciio_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_t); + +int pciio_reset(devfs_handle_t); +int pciio_write_gather_flush(devfs_handle_t); +int pciio_slot_inuse(devfs_handle_t); + +/* ===================================================================== + * Provider Function Location + * + * If there is more than one possible provider for + * this platform, we need to examine the master + * vertex of the current vertex for a provider + * function structure, and indirect through the + * appropriately named member. + */ + +#if !defined(DEV_FUNC) + +static pciio_provider_t * +pciio_to_provider_fns(devfs_handle_t dev) +{ + pciio_info_t card_info; + pciio_provider_t *provider_fns; + + /* + * We're called with two types of vertices, one is + * the bridge vertex (ends with "pci") and the other is the + * pci slot vertex (ends with "pci/[0-8]"). For the first type + * we need to get the provider from the PFUNCS label. For + * the second we get it from fastinfo/c_pops. + */ + provider_fns = pciio_provider_fns_get(dev); + if (provider_fns == NULL) { + card_info = pciio_info_get(dev); + if (card_info != NULL) { + provider_fns = pciio_info_pops_get(card_info); + } + } + + if (provider_fns == NULL) +#if defined(SUPPORT_PRINTING_V_FORMAT) + PRINT_PANIC("%v: provider_fns == NULL", dev); +#else + PRINT_PANIC("0x%p: provider_fns == NULL", (void *)dev); +#endif + + return provider_fns; + +} + +#define DEV_FUNC(dev,func) pciio_to_provider_fns(dev)->func +#define CAST_PIOMAP(x) ((pciio_piomap_t)(x)) +#define CAST_DMAMAP(x) ((pciio_dmamap_t)(x)) +#define CAST_INTR(x) ((pciio_intr_t)(x)) +#endif + +/* + * Many functions are not passed their vertex + * information directly; rather, they must + * dive through a resource map. These macros + * are available to coordinate this detail. + */ +#define PIOMAP_FUNC(map,func) DEV_FUNC((map)->pp_dev,func) +#define DMAMAP_FUNC(map,func) DEV_FUNC((map)->pd_dev,func) +#define INTR_FUNC(intr_hdl,func) DEV_FUNC((intr_hdl)->pi_dev,func) + +/* ===================================================================== + * PIO MANAGEMENT + * + * For mapping system virtual address space to + * pciio space on a specified card + */ + +pciio_piomap_t +pciio_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ + iopaddr_t addr, /* lowest address (or offset in window) */ + size_t byte_count, /* size of region containing our mappings */ + size_t byte_count_max, /* maximum size of a mapping */ + unsigned flags) +{ /* defined in sys/pio.h */ + return (pciio_piomap_t) DEV_FUNC(dev, piomap_alloc) + (dev, dev_desc, space, addr, byte_count, byte_count_max, flags); +} + +void +pciio_piomap_free(pciio_piomap_t pciio_piomap) +{ + PIOMAP_FUNC(pciio_piomap, piomap_free) + (CAST_PIOMAP(pciio_piomap)); +} + +caddr_t +pciio_piomap_addr(pciio_piomap_t pciio_piomap, /* mapping resources */ + iopaddr_t pciio_addr, /* map for this pciio address */ + size_t byte_count) +{ /* map this many bytes */ + pciio_piomap->pp_kvaddr = PIOMAP_FUNC(pciio_piomap, piomap_addr) + (CAST_PIOMAP(pciio_piomap), pciio_addr, byte_count); + + return pciio_piomap->pp_kvaddr; +} + +void +pciio_piomap_done(pciio_piomap_t pciio_piomap) +{ + PIOMAP_FUNC(pciio_piomap, piomap_done) + (CAST_PIOMAP(pciio_piomap)); +} + +caddr_t +pciio_piotrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ + iopaddr_t addr, /* starting address (or offset in window) */ + size_t byte_count, /* map this many bytes */ + unsigned flags) +{ /* (currently unused) */ + return DEV_FUNC(dev, piotrans_addr) + (dev, dev_desc, space, addr, byte_count, flags); +} + +caddr_t +pciio_pio_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ + iopaddr_t addr, /* starting address (or offset in window) */ + size_t byte_count, /* map this many bytes */ + pciio_piomap_t *mapp, /* where to return the map pointer */ + unsigned flags) +{ /* PIO flags */ + pciio_piomap_t map = 0; + int errfree = 0; + caddr_t res; + + if (mapp) { + map = *mapp; /* possible pre-allocated map */ + *mapp = 0; /* record "no map used" */ + } + + res = pciio_piotrans_addr + (dev, dev_desc, space, addr, byte_count, flags); + if (res) + return res; /* pciio_piotrans worked */ + + if (!map) { + map = pciio_piomap_alloc + (dev, dev_desc, space, addr, byte_count, byte_count, flags); + if (!map) + return res; /* pciio_piomap_alloc failed */ + errfree = 1; + } + + res = pciio_piomap_addr + (map, addr, byte_count); + if (!res) { + if (errfree) + pciio_piomap_free(map); + return res; /* pciio_piomap_addr failed */ + } + if (mapp) + *mapp = map; /* pass back map used */ + + return res; /* pciio_piomap_addr succeeded */ +} + +iopaddr_t +pciio_piospace_alloc(devfs_handle_t dev, /* Device requiring space */ + device_desc_t dev_desc, /* Device descriptor */ + pciio_space_t space, /* MEM32/MEM64/IO */ + size_t byte_count, /* Size of mapping */ + size_t align) +{ /* Alignment needed */ + if (align < NBPP) + align = NBPP; + return DEV_FUNC(dev, piospace_alloc) + (dev, dev_desc, space, byte_count, align); +} + +void +pciio_piospace_free(devfs_handle_t dev, /* Device freeing space */ + pciio_space_t space, /* Type of space */ + iopaddr_t pciaddr, /* starting address */ + size_t byte_count) +{ /* Range of address */ + DEV_FUNC(dev, piospace_free) + (dev, space, pciaddr, byte_count); +} + +/* ===================================================================== + * DMA MANAGEMENT + * + * For mapping from pci space to system + * physical space. + */ + +pciio_dmamap_t +pciio_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */ + device_desc_t dev_desc, /* device descriptor */ + size_t byte_count_max, /* max size of a mapping */ + unsigned flags) +{ /* defined in dma.h */ + return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc) + (dev, dev_desc, byte_count_max, flags); +} + +void +pciio_dmamap_free(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_free) + (CAST_DMAMAP(pciio_dmamap)); +} + +iopaddr_t +pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap, /* use these mapping resources */ + paddr_t paddr, /* map for this address */ + size_t byte_count) +{ /* map this many bytes */ + return DMAMAP_FUNC(pciio_dmamap, dmamap_addr) + (CAST_DMAMAP(pciio_dmamap), paddr, byte_count); +} + +alenlist_t +pciio_dmamap_list(pciio_dmamap_t pciio_dmamap, /* use these mapping resources */ + alenlist_t alenlist, /* map this Address/Length List */ + unsigned flags) +{ + return DMAMAP_FUNC(pciio_dmamap, dmamap_list) + (CAST_DMAMAP(pciio_dmamap), alenlist, flags); +} + +void +pciio_dmamap_done(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_done) + (CAST_DMAMAP(pciio_dmamap)); +} + +iopaddr_t +pciio_dmatrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_addr) + (dev, dev_desc, paddr, byte_count, flags); +} + +alenlist_t +pciio_dmatrans_list(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + alenlist_t palenlist, /* system address/length list */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_list) + (dev, dev_desc, palenlist, flags); +} + +iopaddr_t +pciio_dma_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + pciio_dmamap_t *mapp, /* map to use, then map we used */ + unsigned flags) +{ /* PIO flags */ + pciio_dmamap_t map = 0; + int errfree = 0; + iopaddr_t res; + + if (mapp) { + map = *mapp; /* possible pre-allocated map */ + *mapp = 0; /* record "no map used" */ + } + + res = pciio_dmatrans_addr + (dev, dev_desc, paddr, byte_count, flags); + if (res) + return res; /* pciio_dmatrans worked */ + + if (!map) { + map = pciio_dmamap_alloc + (dev, dev_desc, byte_count, flags); + if (!map) + return res; /* pciio_dmamap_alloc failed */ + errfree = 1; + } + + res = pciio_dmamap_addr + (map, paddr, byte_count); + if (!res) { + if (errfree) + pciio_dmamap_free(map); + return res; /* pciio_dmamap_addr failed */ + } + if (mapp) + *mapp = map; /* pass back map used */ + + return res; /* pciio_dmamap_addr succeeded */ +} + +void +pciio_dmamap_drain(pciio_dmamap_t map) +{ + DMAMAP_FUNC(map, dmamap_drain) + (CAST_DMAMAP(map)); +} + +void +pciio_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size) +{ + DEV_FUNC(dev, dmaaddr_drain) + (dev, addr, size); +} + +void +pciio_dmalist_drain(devfs_handle_t dev, alenlist_t list) +{ + DEV_FUNC(dev, dmalist_drain) + (dev, list); +} + +/* ===================================================================== + * INTERRUPT MANAGEMENT + * + * Allow crosstalk devices to establish interrupts + */ + +/* + * Allocate resources required for an interrupt as specified in intr_desc. + * Return resource handle in intr_hdl. + */ +pciio_intr_t +pciio_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_intr_line_t lines, /* INTR line(s) to attach */ + devfs_handle_t owner_dev) +{ /* owner of this interrupt */ + return (pciio_intr_t) DEV_FUNC(dev, intr_alloc) + (dev, dev_desc, lines, owner_dev); +} + +/* + * Free resources consumed by intr_alloc. + */ +void +pciio_intr_free(pciio_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_free) + (CAST_INTR(intr_hdl)); +} + +/* + * Associate resources allocated with a previous pciio_intr_alloc call with the + * described handler, arg, name, etc. + * + * Returns 0 on success, returns <0 on failure. + */ +int +pciio_intr_connect(pciio_intr_t intr_hdl, + intr_func_t intr_func, intr_arg_t intr_arg) /* pciio intr resource handle */ +{ + return INTR_FUNC(intr_hdl, intr_connect) + (CAST_INTR(intr_hdl), intr_func, intr_arg); +} + +/* + * Disassociate handler with the specified interrupt. + */ +void +pciio_intr_disconnect(pciio_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_disconnect) + (CAST_INTR(intr_hdl)); +} + +/* + * Return a hwgraph vertex that represents the CPU currently + * targeted by an interrupt. + */ +devfs_handle_t +pciio_intr_cpu_get(pciio_intr_t intr_hdl) +{ + return INTR_FUNC(intr_hdl, intr_cpu_get) + (CAST_INTR(intr_hdl)); +} + +void +pciio_slot_func_to_name(char *name, + pciio_slot_t slot, + pciio_function_t func) +{ + /* + * standard connection points: + * + * PCIIO_SLOT_NONE: .../pci/direct + * PCIIO_FUNC_NONE: .../pci/ ie. .../pci/3 + * multifunction: .../pci/ ie. .../pci/3c + */ + + if (slot == PCIIO_SLOT_NONE) + sprintf(name, EDGE_LBL_DIRECT); + else if (func == PCIIO_FUNC_NONE) + sprintf(name, "%d", slot); + else + sprintf(name, "%d%c", slot, 'a'+func); +} + +/* + * pciio_cardinfo_get + * + * Get the pciio info structure corresponding to the + * specified PCI "slot" (we like it when the same index + * number is used for the PCI IDSEL, the REQ/GNT pair, + * and the interrupt line being used for INTA. We like + * it so much we call it the slot number). + */ +static pciio_info_t +pciio_cardinfo_get( + devfs_handle_t pciio_vhdl, + pciio_slot_t pci_slot) +{ + char namebuf[16]; + pciio_info_t info = 0; + devfs_handle_t conn; + + pciio_slot_func_to_name(namebuf, pci_slot, PCIIO_FUNC_NONE); + if (GRAPH_SUCCESS == + hwgraph_traverse(pciio_vhdl, namebuf, &conn)) { + info = pciio_info_chk(conn); + hwgraph_vertex_unref(conn); + } + + return info; +} + + +/* + * pciio_error_handler: + * dispatch an error to the appropriate + * pciio connection point, or process + * it as a generic pci error. + * Yes, the first parameter is the + * provider vertex at the middle of + * the bus; we get to the pciio connect + * point using the ioerror widgetdev field. + * + * This function is called by the + * specific PCI provider, after it has figured + * out where on the PCI bus (including which slot, + * if it can tell) the error came from. + */ +/*ARGSUSED */ +int +pciio_error_handler( + devfs_handle_t pciio_vhdl, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + pciio_info_t pciio_info; + devfs_handle_t pconn_vhdl; +#if USRPCI + devfs_handle_t usrpci_v; +#endif + pciio_slot_t slot; + + int retval; +#ifdef EHE_ENABLE + error_state_t e_state; +#endif /* EHE_ENABLE */ + +#if DEBUG && ERROR_DEBUG + printk("%v: pciio_error_handler\n", pciio_vhdl); +#endif + + IOERR_PRINTF(printk(KERN_NOTICE "%v: PCI Bus Error: Error code: %d Error mode: %d\n", + pciio_vhdl, error_code, mode)); + + /* If there is an error handler sitting on + * the "no-slot" connection point, give it + * first crack at the error. NOTE: it is + * quite possible that this function may + * do further refining of the ioerror. + */ + pciio_info = pciio_cardinfo_get(pciio_vhdl, PCIIO_SLOT_NONE); + if (pciio_info && pciio_info->c_efunc) { + pconn_vhdl = pciio_info_dev_get(pciio_info); + +#ifdef EHE_ENABLE + e_state = error_state_get(pciio_vhdl); + + if (e_state == ERROR_STATE_ACTION) + (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE); + + if (error_state_set(pconn_vhdl,e_state) == ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); +#endif + + retval = pciio_info->c_efunc + (pciio_info->c_einfo, error_code, mode, ioerror); + if (retval != IOERROR_UNHANDLED) + return retval; + } + + /* Is the error associated with a particular slot? + */ + if (IOERROR_FIELDVALID(ioerror, widgetdev)) { + short widgetdev; + /* + * NOTE : + * widgetdev is a 4byte value encoded as slot in the higher order + * 2 bytes and function in the lower order 2 bytes. + */ + IOERROR_GETVALUE(widgetdev, ioerror, widgetdev); + slot = pciio_widgetdev_slot_get(widgetdev); + + /* If this slot has an error handler, + * deliver the error to it. + */ + pciio_info = pciio_cardinfo_get(pciio_vhdl, slot); + if (pciio_info != NULL) { + if (pciio_info->c_efunc != NULL) { + + pconn_vhdl = pciio_info_dev_get(pciio_info); + +#ifdef EHE_ENABLE + e_state = error_state_get(pciio_vhdl); + + if (e_state == ERROR_STATE_ACTION) + (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE); + + if (error_state_set(pconn_vhdl,e_state) == + ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); +#endif /* EHE_ENABLE */ + + retval = pciio_info->c_efunc + (pciio_info->c_einfo, error_code, mode, ioerror); + if (retval != IOERROR_UNHANDLED) + return retval; + } + +#if USRPCI + /* If the USRPCI driver is available and + * knows about this connection point, + * deliver the error to it. + * + * OK to use pconn_vhdl here, even though we + * have already UNREF'd it, since we know that + * it is not going away. + */ + pconn_vhdl = pciio_info_dev_get(pciio_info); + if (GRAPH_SUCCESS == hwgraph_traverse(pconn_vhdl, EDGE_LBL_USRPCI, &usrpci_v)) { + iopaddr_t busaddr; + IOERROR_GETVALUE(busaddr, ioerror, busaddr); + retval = usrpci_error_handler (usrpci_v, error_code, busaddr); + hwgraph_vertex_unref(usrpci_v); + if (retval != IOERROR_UNHANDLED) { + /* + * This unref is not needed. If this code is called often enough, + * the system will crash, due to vertex reference count reaching 0, + * causing vertex to be unallocated. -jeremy + * hwgraph_vertex_unref(pconn_vhdl); + */ + return retval; + } + } +#endif + } + } + + return (mode == MODE_DEVPROBE) + ? IOERROR_HANDLED /* probes are OK */ + : IOERROR_UNHANDLED; /* otherwise, foo! */ +} + +/* ===================================================================== + * CONFIGURATION MANAGEMENT + */ + +/* + * Startup a crosstalk provider + */ +void +pciio_provider_startup(devfs_handle_t pciio_provider) +{ + DEV_FUNC(pciio_provider, provider_startup) + (pciio_provider); +} + +/* + * Shutdown a crosstalk provider + */ +void +pciio_provider_shutdown(devfs_handle_t pciio_provider) +{ + DEV_FUNC(pciio_provider, provider_shutdown) + (pciio_provider); +} + +/* + * Specify endianness constraints. The driver tells us what the device + * does and how it would like to see things in memory. We reply with + * how things will actually appear in memory. + */ +pciio_endian_t +pciio_endian_set(devfs_handle_t dev, + pciio_endian_t device_end, + pciio_endian_t desired_end) +{ + ASSERT((device_end == PCIDMA_ENDIAN_BIG) || (device_end == PCIDMA_ENDIAN_LITTLE)); + ASSERT((desired_end == PCIDMA_ENDIAN_BIG) || (desired_end == PCIDMA_ENDIAN_LITTLE)); + +#if DEBUG +#if defined(SUPPORT_PRINTING_V_FORMAT) + printk(KERN_ALERT "%v: pciio_endian_set is going away.\n" + "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n" + "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n", + dev); +#else + printk(KERN_ALERT "0x%x: pciio_endian_set is going away.\n" + "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n" + "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n", + dev); +#endif +#endif + + return DEV_FUNC(dev, endian_set) + (dev, device_end, desired_end); +} + +/* + * Specify PCI arbitration priority. + */ +pciio_priority_t +pciio_priority_set(devfs_handle_t dev, + pciio_priority_t device_prio) +{ + ASSERT((device_prio == PCI_PRIO_HIGH) || (device_prio == PCI_PRIO_LOW)); + + return DEV_FUNC(dev, priority_set) + (dev, device_prio); +} + +/* + * Read value of configuration register + */ +uint64_t +pciio_config_get(devfs_handle_t dev, + unsigned reg, + unsigned size) +{ + uint64_t value = 0; + unsigned shift = 0; + + /* handle accesses that cross words here, + * since that's common code between all + * possible providers. + */ + while (size > 0) { + unsigned biw = 4 - (reg&3); + if (biw > size) + biw = size; + + value |= DEV_FUNC(dev, config_get) + (dev, reg, biw) << shift; + + shift += 8*biw; + reg += biw; + size -= biw; + } + return value; +} + +/* + * Change value of configuration register + */ +void +pciio_config_set(devfs_handle_t dev, + unsigned reg, + unsigned size, + uint64_t value) +{ + /* handle accesses that cross words here, + * since that's common code between all + * possible providers. + */ + while (size > 0) { + unsigned biw = 4 - (reg&3); + if (biw > size) + biw = size; + + DEV_FUNC(dev, config_set) + (dev, reg, biw, value); + reg += biw; + size -= biw; + value >>= biw * 8; + } +} + +/* ===================================================================== + * GENERIC PCI SUPPORT FUNCTIONS + */ + +/* + * Issue a hardware reset to a card. + */ +int +pciio_reset(devfs_handle_t dev) +{ + return DEV_FUNC(dev, reset) (dev); +} + +/* + * flush write gather buffers + */ +int +pciio_write_gather_flush(devfs_handle_t dev) +{ + return DEV_FUNC(dev, write_gather_flush) (dev); +} + +devfs_handle_t +pciio_intr_dev_get(pciio_intr_t pciio_intr) +{ + return (pciio_intr->pi_dev); +} + +/****** Generic crosstalk pio interfaces ******/ +devfs_handle_t +pciio_pio_dev_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_dev); +} + +pciio_slot_t +pciio_pio_slot_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_slot); +} + +pciio_space_t +pciio_pio_space_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_space); +} + +iopaddr_t +pciio_pio_pciaddr_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_pciaddr); +} + +ulong +pciio_pio_mapsz_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_mapsz); +} + +caddr_t +pciio_pio_kvaddr_get(pciio_piomap_t pciio_piomap) +{ + return (pciio_piomap->pp_kvaddr); +} + +/****** Generic crosstalk dma interfaces ******/ +devfs_handle_t +pciio_dma_dev_get(pciio_dmamap_t pciio_dmamap) +{ + return (pciio_dmamap->pd_dev); +} + +pciio_slot_t +pciio_dma_slot_get(pciio_dmamap_t pciio_dmamap) +{ + return (pciio_dmamap->pd_slot); +} + +/****** Generic pci slot information interfaces ******/ + +pciio_info_t +pciio_info_chk(devfs_handle_t pciio) +{ + arbitrary_info_t ainfo = 0; + + hwgraph_info_get_LBL(pciio, INFO_LBL_PCIIO, &ainfo); + return (pciio_info_t) ainfo; +} + +pciio_info_t +pciio_info_get(devfs_handle_t pciio) +{ + pciio_info_t pciio_info; + + pciio_info = (pciio_info_t) hwgraph_fastinfo_get(pciio); + +#ifdef DEBUG_PCIIO + { + int pos; + char dname[256]; + pos = devfs_generate_path(pciio, dname, 256); + printk("%s : path= %s\n", __FUNCTION__, &dname[pos]); + } +#endif /* DEBUG_PCIIO */ + + if ((pciio_info != NULL) && + (pciio_info->c_fingerprint != pciio_info_fingerprint) + && (pciio_info->c_fingerprint != NULL)) { + + return((pciio_info_t)-1); /* Should panic .. */ + } + + + return pciio_info; +} + +void +pciio_info_set(devfs_handle_t pciio, pciio_info_t pciio_info) +{ + if (pciio_info != NULL) + pciio_info->c_fingerprint = pciio_info_fingerprint; + hwgraph_fastinfo_set(pciio, (arbitrary_info_t) pciio_info); + + /* Also, mark this vertex as a PCI slot + * and use the pciio_info, so pciio_info_chk + * can work (and be fairly efficient). + */ + hwgraph_info_add_LBL(pciio, INFO_LBL_PCIIO, + (arbitrary_info_t) pciio_info); +} + +devfs_handle_t +pciio_info_dev_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_vertex); +} + +pciio_slot_t +pciio_info_slot_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_slot); +} + +pciio_function_t +pciio_info_function_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_func); +} + +pciio_vendor_id_t +pciio_info_vendor_id_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_vendor); +} + +pciio_device_id_t +pciio_info_device_id_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_device); +} + +devfs_handle_t +pciio_info_master_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_master); +} + +arbitrary_info_t +pciio_info_mfast_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_mfast); +} + +pciio_provider_t * +pciio_info_pops_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_pops); +} + +error_handler_f * +pciio_info_efunc_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_efunc); +} + +error_handler_arg_t * +pciio_info_einfo_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_einfo); +} + +pciio_space_t +pciio_info_bar_space_get(pciio_info_t info, int win) +{ + return info->c_window[win].w_space; +} + +iopaddr_t +pciio_info_bar_base_get(pciio_info_t info, int win) +{ + return info->c_window[win].w_base; +} + +size_t +pciio_info_bar_size_get(pciio_info_t info, int win) +{ + return info->c_window[win].w_size; +} + +iopaddr_t +pciio_info_rom_base_get(pciio_info_t info) +{ + return info->c_rbase; +} + +size_t +pciio_info_rom_size_get(pciio_info_t info) +{ + return info->c_rsize; +} + + +/* ===================================================================== + * GENERIC PCI INITIALIZATION FUNCTIONS + */ + +/* + * pciioinit: called once during device driver + * initializtion if this driver is configured into + * the system. + */ +void +pciio_init(void) +{ + cdl_p cp; + +#if DEBUG && ATTACH_DEBUG + printf("pciio_init\n"); +#endif + /* Allocate the registry. + * We might already have one. + * If we don't, go get one. + * MPness: someone might have + * set one up for us while we + * were not looking; use an atomic + * compare-and-swap to commit to + * using the new registry if and + * only if nobody else did first. + * If someone did get there first, + * toss the one we allocated back + * into the pool. + */ + if (pciio_registry == NULL) { + cp = cdl_new(EDGE_LBL_PCI, "vendor", "device"); + if (!compare_and_swap_ptr((void **) &pciio_registry, NULL, (void *) cp)) { + cdl_del(cp); + } + } + ASSERT(pciio_registry != NULL); +} + +/* + * pciioattach: called for each vertex in the graph + * that is a PCI provider. + */ +/*ARGSUSED */ +int +pciio_attach(devfs_handle_t pciio) +{ +#if DEBUG && ATTACH_DEBUG +#if defined(SUPPORT_PRINTING_V_FORMAT) + printk("%v: pciio_attach\n", pciio); +#else + printk("0x%x: pciio_attach\n", pciio); +#endif +#endif + return 0; +} + +/* + * Associate a set of pciio_provider functions with a vertex. + */ +void +pciio_provider_register(devfs_handle_t provider, pciio_provider_t *pciio_fns) +{ + hwgraph_info_add_LBL(provider, INFO_LBL_PFUNCS, (arbitrary_info_t) pciio_fns); +} + +/* + * Disassociate a set of pciio_provider functions with a vertex. + */ +void +pciio_provider_unregister(devfs_handle_t provider) +{ + arbitrary_info_t ainfo; + + hwgraph_info_remove_LBL(provider, INFO_LBL_PFUNCS, (long *) &ainfo); +} + +/* + * Obtain a pointer to the pciio_provider functions for a specified Crosstalk + * provider. + */ +pciio_provider_t * +pciio_provider_fns_get(devfs_handle_t provider) +{ + arbitrary_info_t ainfo = 0; + + (void) hwgraph_info_get_LBL(provider, INFO_LBL_PFUNCS, &ainfo); + return (pciio_provider_t *) ainfo; +} + +/*ARGSUSED4 */ +int +pciio_driver_register( + pciio_vendor_id_t vendor_id, + pciio_device_id_t device_id, + char *driver_prefix, + unsigned flags) +{ + /* a driver's init routine might call + * pciio_driver_register before the + * system calls pciio_init; so we + * make the init call ourselves here. + */ + if (pciio_registry == NULL) + pciio_init(); + + return cdl_add_driver(pciio_registry, + vendor_id, device_id, + driver_prefix, flags, NULL); +} + +/* + * Remove an initialization function. + */ +void +pciio_driver_unregister( + char *driver_prefix) +{ + /* before a driver calls unregister, + * it must have called register; so + * we can assume we have a registry here. + */ + ASSERT(pciio_registry != NULL); + + cdl_del_driver(pciio_registry, driver_prefix, NULL); +} + +/* + * Set the slot status for a device supported by the + * driver being registered. + */ +void +pciio_driver_reg_callback( + devfs_handle_t pconn_vhdl, + int key1, + int key2, + int error) +{ +} + +/* + * Set the slot status for a device supported by the + * driver being unregistered. + */ +void +pciio_driver_unreg_callback( + devfs_handle_t pconn_vhdl, + int key1, + int key2, + int error) +{ +} + +/* + * Call some function with each vertex that + * might be one of this driver's attach points. + */ +void +pciio_iterate(char *driver_prefix, + pciio_iter_f * func) +{ + /* a driver's init routine might call + * pciio_iterate before the + * system calls pciio_init; so we + * make the init call ourselves here. + */ + if (pciio_registry == NULL) + pciio_init(); + + ASSERT(pciio_registry != NULL); + + cdl_iterate(pciio_registry, driver_prefix, (cdl_iter_f *) func); +} + +devfs_handle_t +pciio_device_register( + devfs_handle_t connectpt, /* vertex for /hw/.../pciio/%d */ + devfs_handle_t master, /* card's master ASIC (PCI provider) */ + pciio_slot_t slot, /* card's slot */ + pciio_function_t func, /* card's func */ + pciio_vendor_id_t vendor_id, + pciio_device_id_t device_id) +{ + return pciio_device_info_register + (connectpt, pciio_device_info_new (NULL, master, slot, func, + vendor_id, device_id)); +} + +void +pciio_device_unregister(devfs_handle_t pconn) +{ + DEV_FUNC(pconn,device_unregister)(pconn); +} + +pciio_info_t +pciio_device_info_new( + pciio_info_t pciio_info, + devfs_handle_t master, + pciio_slot_t slot, + pciio_function_t func, + pciio_vendor_id_t vendor_id, + pciio_device_id_t device_id) +{ + if (!pciio_info) + GET_NEW(pciio_info); + ASSERT(pciio_info != NULL); + + pciio_info->c_slot = slot; + pciio_info->c_func = func; + pciio_info->c_vendor = vendor_id; + pciio_info->c_device = device_id; + pciio_info->c_master = master; + pciio_info->c_mfast = hwgraph_fastinfo_get(master); + pciio_info->c_pops = pciio_provider_fns_get(master); + pciio_info->c_efunc = 0; + pciio_info->c_einfo = 0; + + return pciio_info; +} + +void +pciio_device_info_free(pciio_info_t pciio_info) +{ + /* NOTE : pciio_info is a structure within the pcibr_info + * and not a pointer to memory allocated on the heap !! + */ + BZERO((char *)pciio_info,sizeof(pciio_info)); +} + +devfs_handle_t +pciio_device_info_register( + devfs_handle_t connectpt, /* vertex at center of bus */ + pciio_info_t pciio_info) /* details about the connectpt */ +{ + char name[32]; + devfs_handle_t pconn; + int device_master_set(devfs_handle_t, devfs_handle_t); + + pciio_slot_func_to_name(name, + pciio_info->c_slot, + pciio_info->c_func); + + if (GRAPH_SUCCESS != + hwgraph_path_add(connectpt, name, &pconn)) + return pconn; + + pciio_info->c_vertex = pconn; + pciio_info_set(pconn, pciio_info); +#ifdef DEBUG_PCIIO + { + int pos; + char dname[256]; + pos = devfs_generate_path(pconn, dname, 256); + printk("%s : pconn path= %s \n", __FUNCTION__, &dname[pos]); + } +#endif /* DEBUG_PCIIO */ + + /* + * create link to our pci provider + */ + + device_master_set(pconn, pciio_info->c_master); + +#if USRPCI + /* + * Call into usrpci provider to let it initialize for + * the given slot. + */ + if (pciio_info->c_slot != PCIIO_SLOT_NONE) + usrpci_device_register(pconn, pciio_info->c_master, pciio_info->c_slot); +#endif + + return pconn; +} + +void +pciio_device_info_unregister(devfs_handle_t connectpt, + pciio_info_t pciio_info) +{ + char name[32]; + devfs_handle_t pconn; + + if (!pciio_info) + return; + + pciio_slot_func_to_name(name, + pciio_info->c_slot, + pciio_info->c_func); + + hwgraph_edge_remove(connectpt,name,&pconn); + pciio_info_set(pconn,0); + + /* Remove the link to our pci provider */ + hwgraph_edge_remove(pconn, EDGE_LBL_MASTER, NULL); + + + hwgraph_vertex_unref(pconn); + hwgraph_vertex_destroy(pconn); + +} +/* Add the pci card inventory information to the hwgraph + */ +static void +pciio_device_inventory_add(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + + ASSERT(pciio_info); + ASSERT(pciio_info->c_vertex == pconn_vhdl); + + /* Donot add inventory for non-existent devices */ + if ((pciio_info->c_vendor == PCIIO_VENDOR_ID_NONE) || + (pciio_info->c_device == PCIIO_DEVICE_ID_NONE)) + return; + device_inventory_add(pconn_vhdl,INV_IOBD,INV_PCIADAP, + pciio_info->c_vendor,pciio_info->c_device, + pciio_info->c_slot); +} + +/*ARGSUSED */ +int +pciio_device_attach(devfs_handle_t pconn, + int drv_flags) +{ + pciio_info_t pciio_info; + pciio_vendor_id_t vendor_id; + pciio_device_id_t device_id; + + + pciio_device_inventory_add(pconn); + pciio_info = pciio_info_get(pconn); + + vendor_id = pciio_info->c_vendor; + device_id = pciio_info->c_device; + + /* we don't start attaching things until + * all the driver init routines (including + * pciio_init) have been called; so we + * can assume here that we have a registry. + */ + ASSERT(pciio_registry != NULL); + + return(cdl_add_connpt(pciio_registry, vendor_id, device_id, pconn, drv_flags)); +} + +int +pciio_device_detach(devfs_handle_t pconn, + int drv_flags) +{ + pciio_info_t pciio_info; + pciio_vendor_id_t vendor_id; + pciio_device_id_t device_id; + + pciio_info = pciio_info_get(pconn); + + vendor_id = pciio_info->c_vendor; + device_id = pciio_info->c_device; + + /* we don't start attaching things until + * all the driver init routines (including + * pciio_init) have been called; so we + * can assume here that we have a registry. + */ + ASSERT(pciio_registry != NULL); + + return(cdl_del_connpt(pciio_registry, vendor_id, device_id, + pconn, drv_flags)); + +} + +/* SN2 */ +/* + * Allocate (if necessary) and initialize a PCI window mapping structure. + */ +pciio_win_map_t +pciio_device_win_map_new(pciio_win_map_t win_map, + size_t region_size, + size_t page_size) +{ + ASSERT((page_size & (page_size - 1)) == 0); + ASSERT((region_size & (page_size - 1)) == 0); + + if (win_map == NULL) + NEW(win_map); + + /* + * The map array tracks the free ``pages'' in the region. The worst + * case scenario is when every other page in the region is free -- + * e.i. maximum fragmentation. This leads to (max pages + 1) / 2 + 1 + * map entries. The first "+1" handles the divide by 2 rounding; the + * second handles the need for an end marker sentinel. + */ + win_map->wm_map = rmallocmap((region_size / page_size + 1) / 2 + 1); + win_map->wm_page_size = page_size; + ASSERT(win_map->wm_map != NULL); + + return win_map; +} + +/* + * Free resources associated with a PCI window mapping structure. + */ +extern void +pciio_device_win_map_free(pciio_win_map_t win_map) +{ + rmfreemap(win_map->wm_map); + bzero(win_map, sizeof *win_map); +} + +/* + * Populate window map with specified free range. + */ +void +pciio_device_win_populate(pciio_win_map_t win_map, + iopaddr_t ioaddr, + size_t size) +{ + ASSERT((size & (win_map->wm_page_size - 1)) == 0); + ASSERT((ioaddr & (win_map->wm_page_size - 1)) == 0); + + rmfree(win_map->wm_map, + size / win_map->wm_page_size, + (unsigned long)ioaddr / win_map->wm_page_size); + +} +/* + * Allocate space from the specified PCI window mapping resource. On + * success record information about the allocation in the supplied window + * allocation cookie (if non-NULL) and return the address of the allocated + * window. On failure return NULL. + * + * The "size" parameter is usually from a PCI device's Base Address Register + * (BAR) decoder. As such, the allocation must be aligned to be a multiple of + * that. The "align" parameter acts as a ``minimum alignment'' allocation + * constraint. The alignment contraint reflects system or device addressing + * restrictions such as the inability to share higher level ``windows'' + * between devices, etc. The returned PCI address allocation will be a + * multiple of the alignment constraint both in alignment and size. Thus, the + * returned PCI address block is aligned to the maximum of the requested size + * and alignment. + */ +iopaddr_t +pciio_device_win_alloc(pciio_win_map_t win_map, + pciio_win_alloc_t win_alloc, + size_t start, size_t size, size_t align) +{ + unsigned long base; + +#ifdef PIC_LATER + ASSERT((size & (size - 1)) == 0); + ASSERT((align & (align - 1)) == 0); + + /* + * Convert size and alignment to pages. If size is greated than the + * requested alignment, we bump the alignment up to size; otherwise + * convert the size into a multiple of the alignment request. + */ + size = (size + win_map->wm_page_size - 1) / win_map->wm_page_size; + align = align / win_map->wm_page_size; + if (size > align) + align = size; + else + size = (size + align - 1) & ~(align - 1); + + /* XXXX */ + base = rmalloc_align(win_map->wm_map, size, align, VM_NOSLEEP); + if (base == RMALLOC_FAIL) + return((iopaddr_t)NULL); +#else + int index_page, index_page_align; + int align_pages, size_pages; + int alloc_pages, free_pages; + int addr_align; + + /* Convert PCI bus alignment from bytes to pages */ + align_pages = align / win_map->wm_page_size; + + /* Convert PCI request from bytes to pages */ + size_pages = (size / win_map->wm_page_size) + + ((size % win_map->wm_page_size) ? 1 : 0); + + /* Align address with the larger of the size or the requested slot align */ + if (size_pages > align_pages) + align_pages = size_pages; + + /* + * Avoid wasting space by aligning - 1; this will prevent crossing + * another alignment boundary. + */ + alloc_pages = size_pages + (align_pages - 1); + + /* Allocate PCI bus space in pages */ + index_page = (int) rmalloc(win_map->wm_map, + (size_t) alloc_pages); + + /* Error if no PCI bus address space available */ + if (!index_page) + return 0; + + /* PCI bus address index starts at 0 */ + index_page--; + + /* Align the page offset as requested */ + index_page_align = (index_page + (align_pages - 1)) - + ((index_page + (align_pages - 1)) % align_pages); + + free_pages = (align_pages - 1) - (index_page_align - index_page); + + /* Free unused PCI bus pages adjusting the index to start at 1 */ + rmfree(win_map->wm_map, + free_pages, + (index_page_align + 1) + size_pages); + + /* Return aligned PCI bus space in bytes */ + addr_align = (index_page_align * win_map->wm_page_size); + base = index_page; + size = alloc_pages - free_pages; +#endif /* PIC_LATER */ + + /* + * If a window allocation cookie has been supplied, use it to keep + * track of all the allocated space assigned to this window. + */ + if (win_alloc) { + win_alloc->wa_map = win_map; + win_alloc->wa_base = base; + win_alloc->wa_pages = size; + } + + return base * win_map->wm_page_size; +} + +/* + * Free the specified window allocation back into the PCI window mapping + * resource. As noted above, we keep page addresses offset by 1 ... + */ +void +pciio_device_win_free(pciio_win_alloc_t win_alloc) +{ + if (win_alloc->wa_pages) + rmfree(win_alloc->wa_map->wm_map, + win_alloc->wa_pages, + win_alloc->wa_base); +} + +/* + * pciio_error_register: + * arrange for a function to be called with + * a specified first parameter plus other + * information when an error is encountered + * and traced to the pci slot corresponding + * to the connection point pconn. + * + * may also be called with a null function + * pointer to "unregister" the error handler. + * + * NOTE: subsequent calls silently overwrite + * previous data for this vertex. We assume that + * cooperating drivers, well, cooperate ... + */ +void +pciio_error_register(devfs_handle_t pconn, + error_handler_f *efunc, + error_handler_arg_t einfo) +{ + pciio_info_t pciio_info; + + pciio_info = pciio_info_get(pconn); + ASSERT(pciio_info != NULL); + pciio_info->c_efunc = efunc; + pciio_info->c_einfo = einfo; +} + +/* + * Check if any device has been found in this slot, and return + * true or false + * vhdl is the vertex for the slot + */ +int +pciio_slot_inuse(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + + ASSERT(pciio_info); + ASSERT(pciio_info->c_vertex == pconn_vhdl); + if (pciio_info->c_vendor) { + /* + * Non-zero value for vendor indicate + * a board being found in this slot. + */ + return 1; + } + return 0; +} + +int +pciio_dma_enabled(devfs_handle_t pconn_vhdl) +{ + return DEV_FUNC(pconn_vhdl, dma_enabled)(pconn_vhdl); +} + +int +pciio_info_type1_get(pciio_info_t pci_info) +{ + return(0); +} + + +/* + * These are complementary Linux interfaces that takes in a pci_dev * as the + * first arguement instead of devfs_handle_t. + */ +iopaddr_t snia_pciio_dmatrans_addr(struct pci_dev *, device_desc_t, paddr_t, size_t, unsigned); +pciio_dmamap_t snia_pciio_dmamap_alloc(struct pci_dev *, device_desc_t, size_t, unsigned); +void snia_pciio_dmamap_free(pciio_dmamap_t); +iopaddr_t snia_pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t); +void snia_pciio_dmamap_done(pciio_dmamap_t); +pciio_endian_t snia_pciio_endian_set(struct pci_dev *pci_dev, pciio_endian_t device_end, + pciio_endian_t desired_end); + +#include +EXPORT_SYMBOL(snia_pciio_dmatrans_addr); +EXPORT_SYMBOL(snia_pciio_dmamap_alloc); +EXPORT_SYMBOL(snia_pciio_dmamap_free); +EXPORT_SYMBOL(snia_pciio_dmamap_addr); +EXPORT_SYMBOL(snia_pciio_dmamap_done); +EXPORT_SYMBOL(snia_pciio_endian_set); + +int +snia_pcibr_rrb_alloc(struct pci_dev *pci_dev, + int *count_vchan0, + int *count_vchan1) +{ + devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + + return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1); +} +EXPORT_SYMBOL(snia_pcibr_rrb_alloc); + +pciio_endian_t +snia_pciio_endian_set(struct pci_dev *pci_dev, + pciio_endian_t device_end, + pciio_endian_t desired_end) +{ + devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + + return DEV_FUNC(dev, endian_set) + (dev, device_end, desired_end); +} + +iopaddr_t +snia_pciio_dmatrans_addr(struct pci_dev *pci_dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + unsigned flags) +{ /* defined in dma.h */ + + devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + + /* + * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be + * set. Otherwise, it must not be set. This applies to SN1 and SN2. + */ + return DEV_FUNC(dev, dmatrans_addr) + (dev, dev_desc, paddr, byte_count, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM); +} + +pciio_dmamap_t +snia_pciio_dmamap_alloc(struct pci_dev *pci_dev, /* set up mappings for this device */ + device_desc_t dev_desc, /* device descriptor */ + size_t byte_count_max, /* max size of a mapping */ + unsigned flags) +{ /* defined in dma.h */ + + devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + + /* + * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be + * set. Otherwise, it must not be set. This applies to SN1 and SN2. + */ + return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc) + (dev, dev_desc, byte_count_max, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM); +} + +void +snia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_free) + (CAST_DMAMAP(pciio_dmamap)); +} + +iopaddr_t +snia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap, /* use these mapping resources */ + paddr_t paddr, /* map for this address */ + size_t byte_count) +{ /* map this many bytes */ + return DMAMAP_FUNC(pciio_dmamap, dmamap_addr) + (CAST_DMAMAP(pciio_dmamap), paddr, byte_count); +} + +void +snia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_done) + (CAST_DMAMAP(pciio_dmamap)); +} + diff -Nru a/arch/ia64/sn/io/sn2/pic.c b/arch/ia64/sn/io/sn2/pic.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/pic.c Mon Feb 24 05:30:53 2003 @@ -0,0 +1,325 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char *bcopy(const char * src, char * dest, int count); + + +#define PCI_BUS_NO_1 1 + +int pic_devflag = D_MP; + +extern int pcibr_attach2(devfs_handle_t, bridge_t *, devfs_handle_t, int, pcibr_soft_t *); +extern void pcibr_driver_reg_callback(devfs_handle_t, int, int, int); +extern void pcibr_driver_unreg_callback(devfs_handle_t, int, int, int); + + +void +pic_init(void) +{ + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INIT, NULL, "pic_init()\n")); + + xwidget_driver_register(PIC_WIDGET_PART_NUM_BUS0, + PIC_WIDGET_MFGR_NUM, + "pic_", + 0); +} + +/* + * copy inventory_t from conn_v to peer_conn_v + */ +int +pic_bus1_inventory_dup(devfs_handle_t conn_v, devfs_handle_t peer_conn_v) +{ + inventory_t *pinv, *peer_pinv; + + if (hwgraph_info_get_LBL(conn_v, INFO_LBL_INVENT, + (arbitrary_info_t *)&pinv) == GRAPH_SUCCESS) + { + NEW(peer_pinv); + bcopy(pinv, peer_pinv, sizeof(inventory_t)); + if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_INVENT, + (arbitrary_info_t)peer_pinv) != GRAPH_SUCCESS) { + DEL(peer_pinv); + return 0; + } + return 1; + } + + printk("pic_bus1_inventory_dup: cannot get INFO_LBL_INVENT from 0x%lx\n ", + conn_v); + return 0; +} + +/* + * copy xwidget_info_t from conn_v to peer_conn_v + */ +int +pic_bus1_widget_info_dup(devfs_handle_t conn_v, devfs_handle_t peer_conn_v, + cnodeid_t xbow_peer) +{ + xwidget_info_t widget_info, peer_widget_info; + char peer_path[256]; + char *p; + devfs_handle_t peer_hubv; + hubinfo_t peer_hub_info; + + /* get the peer hub's widgetid */ + peer_hubv = NODEPDA(xbow_peer)->node_vertex; + peer_hub_info = NULL; + hubinfo_get(peer_hubv, &peer_hub_info); + if (peer_hub_info == NULL) + return 0; + + if (hwgraph_info_get_LBL(conn_v, INFO_LBL_XWIDGET, + (arbitrary_info_t *)&widget_info) == GRAPH_SUCCESS) { + NEW(peer_widget_info); + peer_widget_info->w_vertex = peer_conn_v; + peer_widget_info->w_id = widget_info->w_id; + peer_widget_info->w_master = peer_hubv; + peer_widget_info->w_masterid = peer_hub_info->h_widgetid; + /* structure copy */ + peer_widget_info->w_hwid = widget_info->w_hwid; + peer_widget_info->w_efunc = 0; + peer_widget_info->w_einfo = 0; + peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL); + strcpy(peer_widget_info->w_name, peer_path); + + if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET, + (arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) { + DEL(peer_widget_info); + return 0; + } + + xwidget_info_set(peer_conn_v, peer_widget_info); + + return 1; + } + + printk("pic_bus1_widget_info_dup: " + "cannot get INFO_LBL_XWIDGET from 0x%lx\n", conn_v); + return 0; +} + +/* + * If this PIC is attached to two Cbricks ("dual-ported") then + * attach each bus to opposite Cbricks. + * + * If successful, return a new vertex suitable for attaching the PIC bus. + * If not successful, return zero and both buses will attach to the + * vertex passed into pic_attach(). + */ +devfs_handle_t +pic_bus1_redist(nasid_t nasid, devfs_handle_t conn_v) +{ + cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); + cnodeid_t xbow_peer = -1; + char pathname[256], peer_path[256], tmpbuf[256]; + char *p; + int rc; + devfs_handle_t peer_conn_v; + int pos; + slabid_t slab; + + if (NODEPDA(cnode)->xbow_peer >= 0) { /* if dual-ported */ + /* create a path for this widget on the peer Cbrick */ + /* pcibr widget hw/module/001c11/slab/0/Pbrick/xtalk/12 */ + /* sprintf(pathname, "%v", conn_v); */ + xbow_peer = NASID_TO_COMPACT_NODEID(NODEPDA(cnode)->xbow_peer); + pos = devfs_generate_path(conn_v, tmpbuf, 256); + strcpy(pathname, &tmpbuf[pos]); + p = pathname + strlen("hw/module/001c01/slab/0/"); + + memset(tmpbuf, 0, 16); + format_module_id(tmpbuf, geo_module((NODEPDA(xbow_peer))->geoid), MODULE_FORMAT_BRIEF); + slab = geo_slab((NODEPDA(xbow_peer))->geoid); + sprintf(peer_path, "module/%s/slab/%d/%s", tmpbuf, (int)slab, p); + + /* Look for vertex for this widget on the peer Cbrick. + * Expect GRAPH_NOT_FOUND. + */ + rc = hwgraph_traverse(hwgraph_root, peer_path, &peer_conn_v); + if (GRAPH_SUCCESS == rc) + printk("pic_attach: found unexpected vertex: 0x%lx\n", + peer_conn_v); + else if (GRAPH_NOT_FOUND != rc) { + printk("pic_attach: hwgraph_traverse unexpectedly" + " returned 0x%x\n", rc); + } else { + /* try to add the widget vertex to the peer Cbrick */ + rc = hwgraph_path_add(hwgraph_root, peer_path, &peer_conn_v); + + if (GRAPH_SUCCESS != rc) + printk("pic_attach: hwgraph_path_add" + " failed with 0x%x\n", rc); + else { + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, + "pic_bus1_redist: added vertex %v\n", peer_conn_v)); + + /* Now hang appropiate stuff off of the new + * vertex. We bail out if we cannot add something. + * In that case, we don't remove the newly added + * vertex but that should be safe and we don't + * really expect the additions to fail anyway. + */ +#if 0 + if (!pic_bus1_inventory_dup(conn_v, peer_conn_v)) + return 0; + pic_bus1_device_desc_dup(conn_v, peer_conn_v); +#endif + if (!pic_bus1_widget_info_dup(conn_v, peer_conn_v, xbow_peer)) + return 0; + + return peer_conn_v; + } + } + } + return 0; +} + + +int +pic_attach(devfs_handle_t conn_v) +{ + int rc; + bridge_t *bridge0, *bridge1 = (bridge_t *)0; + devfs_handle_t pcibr_vhdl0, pcibr_vhdl1 = (devfs_handle_t)0; + pcibr_soft_t bus0_soft, bus1_soft = (pcibr_soft_t)0; + devfs_handle_t conn_v0, conn_v1, peer_conn_v; + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n")); + + bridge0 = (bridge_t *) xtalk_piotrans_addr(conn_v, NULL, + 0, sizeof(bridge_t), 0); + bridge1 = (bridge_t *)((char *)bridge0 + PIC_BUS1_OFFSET); + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, + "pic_attach: bridge0=0x%x, bridge1=0x%x\n", + bridge0, bridge1)); + + conn_v0 = conn_v1 = conn_v; + + /* If dual-ported then split the two PIC buses across both Cbricks */ + if (peer_conn_v = pic_bus1_redist(NASID_GET(bridge0), conn_v)) + conn_v1 = peer_conn_v; + + /* + * Create the vertex for the PCI buses, which week + * will also use to hold the pcibr_soft and + * which will be the "master" vertex for all the + * pciio connection points we will hang off it. + * This needs to happen before we call nic_bridge_vertex_info + * as we are some of the *_vmc functions need access to the edges. + * + * Opening this vertex will provide access to + * the Bridge registers themselves. + */ + /* FIXME: what should the hwgraph path look like ? */ + rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0); + ASSERT(rc == GRAPH_SUCCESS); + rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1); + ASSERT(rc == GRAPH_SUCCESS); + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, + "pic_attach: pcibr_vhdl0=%v, pcibr_vhdl1=%v\n", + pcibr_vhdl0, pcibr_vhdl1)); + + /* register pci provider array */ + pciio_provider_register(pcibr_vhdl0, &pci_pic_provider); + pciio_provider_register(pcibr_vhdl1, &pci_pic_provider); + + pciio_provider_startup(pcibr_vhdl0); + pciio_provider_startup(pcibr_vhdl1); + + pcibr_attach2(conn_v0, bridge0, pcibr_vhdl0, 0, &bus0_soft); + pcibr_attach2(conn_v1, bridge1, pcibr_vhdl1, 1, &bus1_soft); + + /* save a pointer to the PIC's other bus's soft struct */ + bus0_soft->bs_peers_soft = bus1_soft; + bus1_soft->bs_peers_soft = bus0_soft; + bus0_soft->bs_peers_soft = (pcibr_soft_t)0; + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, + "pic_attach: bus0_soft=0x%x, bus1_soft=0x%x\n", + bus0_soft, bus1_soft)); + + return 0; +} + +/* + * pci provider functions + * + * mostly in pcibr.c but if any are needed here then + * this might be a way to get them here. + */ +pciio_provider_t pci_pic_provider = +{ + (pciio_piomap_alloc_f *) pcibr_piomap_alloc, + (pciio_piomap_free_f *) pcibr_piomap_free, + (pciio_piomap_addr_f *) pcibr_piomap_addr, + (pciio_piomap_done_f *) pcibr_piomap_done, + (pciio_piotrans_addr_f *) pcibr_piotrans_addr, + (pciio_piospace_alloc_f *) pcibr_piospace_alloc, + (pciio_piospace_free_f *) pcibr_piospace_free, + + (pciio_dmamap_alloc_f *) pcibr_dmamap_alloc, + (pciio_dmamap_free_f *) pcibr_dmamap_free, + (pciio_dmamap_addr_f *) pcibr_dmamap_addr, + (pciio_dmamap_list_f *) pcibr_dmamap_list, + (pciio_dmamap_done_f *) pcibr_dmamap_done, + (pciio_dmatrans_addr_f *) pcibr_dmatrans_addr, + (pciio_dmatrans_list_f *) pcibr_dmatrans_list, + (pciio_dmamap_drain_f *) pcibr_dmamap_drain, + (pciio_dmaaddr_drain_f *) pcibr_dmaaddr_drain, + (pciio_dmalist_drain_f *) pcibr_dmalist_drain, + + (pciio_intr_alloc_f *) pcibr_intr_alloc, + (pciio_intr_free_f *) pcibr_intr_free, + (pciio_intr_connect_f *) pcibr_intr_connect, + (pciio_intr_disconnect_f *) pcibr_intr_disconnect, + (pciio_intr_cpu_get_f *) pcibr_intr_cpu_get, + + (pciio_provider_startup_f *) pcibr_provider_startup, + (pciio_provider_shutdown_f *) pcibr_provider_shutdown, + (pciio_reset_f *) pcibr_reset, + (pciio_write_gather_flush_f *) pcibr_write_gather_flush, + (pciio_endian_set_f *) pcibr_endian_set, + (pciio_priority_set_f *) pcibr_priority_set, + (pciio_config_get_f *) pcibr_config_get, + (pciio_config_set_f *) pcibr_config_set, + (pciio_error_devenable_f *) 0, + (pciio_error_extract_f *) 0, + (pciio_driver_reg_callback_f *) pcibr_driver_reg_callback, + (pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback, + (pciio_device_unregister_f *) pcibr_device_unregister, + (pciio_dma_enabled_f *) pcibr_dma_enabled, +}; diff -Nru a/arch/ia64/sn/io/sn2/sgi_io_init.c b/arch/ia64/sn/io/sn2/sgi_io_init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/sgi_io_init.c Mon Feb 24 05:34:00 2003 @@ -0,0 +1,226 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void mlreset(void); +extern int init_hcl(void); +extern void klgraph_hack_init(void); +extern void hubspc_init(void); +extern void pciio_init(void); +extern void pcibr_init(void); +extern void xtalk_init(void); +extern void xbow_init(void); +extern void xbmon_init(void); +extern void pciiox_init(void); +extern void pic_init(void); +extern void usrpci_init(void); +extern void ioc3_init(void); +extern void initialize_io(void); +extern void klhwg_add_all_modules(devfs_handle_t); +extern void klhwg_add_all_nodes(devfs_handle_t); + +void sn_mp_setup(void); +extern devfs_handle_t hwgraph_root; +extern void io_module_init(void); +extern void pci_bus_cvlink_init(void); +extern void temp_hack(void); + +extern int pci_bus_to_hcl_cvlink(void); + +/* #define DEBUG_IO_INIT 1 */ +#ifdef DEBUG_IO_INIT +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* DEBUG_IO_INIT */ + +/* + * per_hub_init + * + * This code is executed once for each Hub chip. + */ +static void +per_hub_init(cnodeid_t cnode) +{ + nasid_t nasid; + nodepda_t *npdap; + ii_icmr_u_t ii_icmr; + ii_ibcr_u_t ii_ibcr; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + + ASSERT(nasid != INVALID_NASID); + ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode); + + npdap = NODEPDA(cnode); + + REMOTE_HUB_S(nasid, IIO_IWEIM, 0x8000); + + /* + * Set the total number of CRBs that can be used. + */ + ii_icmr.ii_icmr_regval= 0x0; + ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf; + REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval); + + /* + * Set the number of CRBs that both of the BTEs combined + * can use minus 1. + */ + ii_ibcr.ii_ibcr_regval= 0x0; + ii_ibcr.ii_ibcr_fld_s.i_count = 0x8; + REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval); + + /* + * Set CRB timeout to be 10ms. + */ +#ifdef BRINGUP2 + REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff ); + REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); + //REMOTE_HUB_S(nasid, IIO_IWI, 0x00FF00FF00FFFFFF); +#endif + + /* Initialize error interrupts for this hub. */ + hub_error_init(cnode); +} + +/* + * This routine is responsible for the setup of all the IRIX hwgraph style + * stuff that's been pulled into linux. It's called by sn_pci_find_bios which + * is called just before the generic Linux PCI layer does its probing (by + * platform_pci_fixup aka sn_pci_fixup). + * + * It is very IMPORTANT that this call is only made by the Master CPU! + * + */ + +void +sgi_master_io_infr_init(void) +{ + int cnode; + extern void kdba_io_init(); + + /* + * Do any early init stuff .. einit_tbl[] etc. + */ + init_hcl(); /* Sets up the hwgraph compatibility layer with devfs */ + + /* + * initialize the Linux PCI to xwidget vertexes .. + */ + pci_bus_cvlink_init(); + + kdba_io_init(); + +#ifdef BRINGUP + /* + * Hack to provide statically initialzed klgraph entries. + */ + DBG("--> sgi_master_io_infr_init: calling klgraph_hack_init()\n"); + klgraph_hack_init(); +#endif /* BRINGUP */ + + /* + * This is the Master CPU. Emulate mlsetup and main.c in Irix. + */ + mlreset(); + + /* + * allowboot() is called by kern/os/main.c in main() + * Emulate allowboot() ... + * per_cpu_init() - only need per_hub_init() + * cpu_io_setup() - Nothing to do. + * + */ + sn_mp_setup(); + + for (cnode = 0; cnode < numnodes; cnode++) { + per_hub_init(cnode); + } + + /* We can do headless hub cnodes here .. */ + + /* + * io_init[] stuff. + * + * Get SGI IO Infrastructure drivers to init and register with + * each other etc. + */ + + hubspc_init(); + pciio_init(); + pcibr_init(); + pic_init(); + xtalk_init(); + xbow_init(); + xbmon_init(); + pciiox_init(); + usrpci_init(); + ioc3_init(); + + /* + * + * Our IO Infrastructure drivers are in place .. + * Initialize the whole IO Infrastructure .. xwidget/device probes. + * + */ + initialize_io(); + pci_bus_to_hcl_cvlink(); + +#ifdef CONFIG_PCIBA + DBG("--> sgi_master_io_infr_init: calling pciba_init()\n"); +#ifndef BRINGUP2 + pciba_init(); +#endif +#endif +} + +/* + * One-time setup for MP SN. + * Allocate per-node data, slurp prom klconfig information and + * convert it to hwgraph information. + */ +void +sn_mp_setup(void) +{ + cpuid_t cpu; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + /* Skip holes in CPU space */ + if (cpu_enabled(cpu)) { + init_platform_pda(cpu); + } + } + + /* + * Initialize platform-dependent vertices in the hwgraph: + * module + * node + * cpu + * memory + * slot + * hub + * router + * xbow + */ + + io_module_init(); /* Use to be called module_init() .. */ + klhwg_add_all_modules(hwgraph_root); + klhwg_add_all_nodes(hwgraph_root); +} diff -Nru a/arch/ia64/sn/io/sn2/shub.c b/arch/ia64/sn/io/sn2/shub.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/shub.c Mon Feb 24 05:34:25 2003 @@ -0,0 +1,233 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved. + */ + +#ident "$Revision: 1.167 $" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Shub WAR for Xbridge Little Endian problem: + * Xbridge has to run in BIG ENDIAN even with Shub. + */ + + +/* + * io_sh_swapper: Turn on Shub byte swapping. + * All data destined to and from Shub to XIO are byte-swapped. + */ +void +io_sh_swapper(nasid_t nasid, int onoff) +{ + ii_iwc_u_t ii_iwc; + + ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC); + + ii_iwc.ii_iwc_fld_s.i_dma_byte_swap = onoff; + REMOTE_HUB_S(nasid, IIO_IWC, ii_iwc.ii_iwc_regval); + ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC); + +} + +/* + * io_get_sh_swapper: Return current Swap mode. + * 1 = Swap on, 0 = Swap off. + */ +int +io_get_sh_swapper(nasid_t nasid) +{ + ii_iwc_u_t ii_iwc; + + ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC); + return(ii_iwc.ii_iwc_fld_s.i_dma_byte_swap); + +} + +#define SHUB_NUM_ECF_REGISTERS 8 + +static uint32_t shub_perf_counts[SHUB_NUM_ECF_REGISTERS]; + +static shubreg_t shub_perf_counts_regs[SHUB_NUM_ECF_REGISTERS] = { + SH_PERFORMANCE_COUNTER0, + SH_PERFORMANCE_COUNTER1, + SH_PERFORMANCE_COUNTER2, + SH_PERFORMANCE_COUNTER3, + SH_PERFORMANCE_COUNTER4, + SH_PERFORMANCE_COUNTER5, + SH_PERFORMANCE_COUNTER6, + SH_PERFORMANCE_COUNTER7 +}; + +static inline void +shub_mmr_write(cnodeid_t cnode, shubreg_t reg, uint64_t val) +{ + int nasid = cnodeid_to_nasid(cnode); + volatile uint64_t *addr = (uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg)); + + *addr = val; + __ia64_mf_a(); +} + +static inline void +shub_mmr_write32(cnodeid_t cnode, shubreg_t reg, uint32_t val) +{ + int nasid = cnodeid_to_nasid(cnode); + volatile uint32_t *addr = (uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg)); + + *addr = val; + __ia64_mf_a(); +} + +static inline uint64_t +shub_mmr_read(cnodeid_t cnode, shubreg_t reg) +{ + int nasid = cnodeid_to_nasid(cnode); + volatile uint64_t val; + + val = *(uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg)); + __ia64_mf_a(); + + return val; +} + +static inline uint32_t +shub_mmr_read32(cnodeid_t cnode, shubreg_t reg) +{ + int nasid = cnodeid_to_nasid(cnode); + volatile uint32_t val; + + val = *(uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg)); + __ia64_mf_a(); + + return val; +} + +static int +reset_shub_stats(cnodeid_t cnode) +{ + int i; + + for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) { + shub_perf_counts[i] = 0; + shub_mmr_write32(cnode, shub_perf_counts_regs[i], 0); + } + return 0; +} + +static int +configure_shub_stats(cnodeid_t cnode, unsigned long arg) +{ + uint64_t *p = (uint64_t *)arg; + uint64_t i; + uint64_t regcnt; + uint64_t regval[2]; + + if (copy_from_user((void *)®cnt, p, sizeof(regcnt))) + return -EFAULT; + + for (p++, i=0; i < regcnt; i++, p += 2) { + if (copy_from_user((void *)regval, (void *)p, sizeof(regval))) + return -EFAULT; + if (regval[0] & 0x7) { + printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]); + return -EINVAL; + } + shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]); + } + return 0; +} + +static int +capture_shub_stats(cnodeid_t cnode, uint32_t *counts) +{ + int i; + + for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) { + counts[i] = shub_mmr_read32(cnode, shub_perf_counts_regs[i]); + } + return 0; +} + +static int +shubstats_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + cnodeid_t cnode; + uint64_t longarg; + devfs_handle_t d; + int nasid; + + if ((d = devfs_get_handle_from_inode(inode)) == NULL) + return -ENODEV; + cnode = (cnodeid_t)hwgraph_fastinfo_get(d); + + switch (cmd) { + case SNDRV_SHUB_CONFIGURE: + return configure_shub_stats(cnode, arg); + break; + + case SNDRV_SHUB_RESETSTATS: + reset_shub_stats(cnode); + break; + + case SNDRV_SHUB_INFOSIZE: + longarg = sizeof(shub_perf_counts); + if (copy_to_user((void *)arg, &longarg, sizeof(longarg))) { + return -EFAULT; + } + break; + + case SNDRV_SHUB_GETSTATS: + capture_shub_stats(cnode, shub_perf_counts); + if (copy_to_user((void *)arg, shub_perf_counts, + sizeof(shub_perf_counts))) { + return -EFAULT; + } + break; + + case SNDRV_SHUB_GETNASID: + nasid = cnodeid_to_nasid(cnode); + if (copy_to_user((void *)arg, &nasid, + sizeof(nasid))) { + return -EFAULT; + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +struct file_operations shub_mon_fops = { + ioctl: shubstats_ioctl, +}; diff -Nru a/arch/ia64/sn/io/sn2/shubio.c b/arch/ia64/sn/io/sn2/shubio.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/shubio.c Mon Feb 24 05:34:49 2003 @@ -0,0 +1,510 @@ +/* $Id: shubio.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1992 - 1997, 2000,2002-2003 Silicon Graphics, Inc. All rights reserved. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +error_state_t error_state_get(devfs_handle_t v); +error_return_code_t error_state_set(devfs_handle_t v,error_state_t new_state); + + +/* + * Get the xtalk provider function pointer for the + * specified hub. + */ + +/*ARGSUSED*/ +int +hub_xp_error_handler( + devfs_handle_t hub_v, + nasid_t nasid, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + /*REFERENCED*/ + hubreg_t iio_imem; + devfs_handle_t xswitch; + error_state_t e_state; + cnodeid_t cnode; + + /* + * Before walking down to the next level, check if + * the I/O link is up. If it's been disabled by the + * hub ii for some reason, we can't even touch the + * widget registers. + */ + iio_imem = REMOTE_HUB_L(nasid, IIO_IMEM); + + if (!(iio_imem & (IIO_IMEM_B0ESD|IIO_IMEM_W0ESD))){ + /* + * IIO_IMEM_B0ESD getting set, indicates II shutdown + * on HUB0 parts.. Hopefully that's not true for + * Hub1 parts.. + * + * + * If either one of them is shut down, can't + * go any further. + */ + return IOERROR_XTALKLEVEL; + } + + /* Get the error state of the hub */ + e_state = error_state_get(hub_v); + + cnode = NASID_TO_COMPACT_NODEID(nasid); + + xswitch = NODEPDA(cnode)->basew_xc; + + /* Set the error state of the crosstalk device to that of + * hub. + */ + if (error_state_set(xswitch , e_state) == + ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); + + /* Clean the error state of the hub if we are in the action handling + * phase. + */ + if (e_state == ERROR_STATE_ACTION) + (void)error_state_set(hub_v, ERROR_STATE_NONE); + /* hand the error off to the switch or the directly + * connected crosstalk device. + */ + return xtalk_error_handler(xswitch, + error_code, mode, ioerror); + +} + +/* + * Check if the widget in error has been enabled for PIO accesses + */ +int +is_widget_pio_enabled(ioerror_t *ioerror) +{ + cnodeid_t src_node; + nasid_t src_nasid; + hubreg_t ii_iowa; + xwidgetnum_t widget; + iopaddr_t p; + + /* Get the node where the PIO error occurred */ + IOERROR_GETVALUE(p,ioerror, srcnode); + src_node = p; + if (src_node == CNODEID_NONE) + return(0); + + /* Get the nasid for the cnode */ + src_nasid = COMPACT_TO_NASID_NODEID(src_node); + if (src_nasid == INVALID_NASID) + return(0); + + /* Read the Outbound widget access register for this hub */ + ii_iowa = REMOTE_HUB_L(src_nasid, IIO_IOWA); + IOERROR_GETVALUE(p,ioerror, widgetnum); + widget = p; + + /* Check if the PIOs to the widget with PIO error have been + * enabled. + */ + if (ii_iowa & IIO_IOWA_WIDGET(widget)) + return(1); + + return(0); +} + +/* + * Hub IO error handling. + * + * Gets invoked for different types of errors found at the hub. + * Typically this includes situations from bus error or due to + * an error interrupt (mostly generated at the hub). + */ +int +hub_ioerror_handler( + devfs_handle_t hub_v, + int error_code, + int mode, + struct io_error_s *ioerror) +{ + hubinfo_t hinfo; /* Hub info pointer */ + nasid_t nasid; + int retval = 0; + /*REFERENCED*/ + iopaddr_t p; + + IOERROR_DUMP("hub_ioerror_handler", error_code, mode, ioerror); + + hubinfo_get(hub_v, &hinfo); + + if (!hinfo){ + /* Print an error message and return */ + goto end; + } + nasid = hinfo->h_nasid; + + switch(error_code) { + + case PIO_READ_ERROR: + /* + * Cpu got a bus error while accessing IO space. + * hubaddr field in ioerror structure should have + * the IO address that caused access error. + */ + + /* + * Identify if the physical address in hub_error_data + * corresponds to small/large window, and accordingly, + * get the xtalk address. + */ + + /* + * Evaluate the widget number and the widget address that + * caused the error. Use 'vaddr' if it's there. + * This is typically true either during probing + * or a kernel driver getting into trouble. + * Otherwise, use paddr to figure out widget details + * This is typically true for user mode bus errors while + * accessing I/O space. + */ + IOERROR_GETVALUE(p,ioerror,vaddr); + if (p){ + /* + * If neither in small window nor in large window range, + * outright reject it. + */ + IOERROR_GETVALUE(p,ioerror,vaddr); + if (NODE_SWIN_ADDR(nasid, (paddr_t)p)){ + iopaddr_t hubaddr; + xwidgetnum_t widgetnum; + iopaddr_t xtalkaddr; + + IOERROR_GETVALUE(p,ioerror,hubaddr); + hubaddr = p; + widgetnum = SWIN_WIDGETNUM(hubaddr); + xtalkaddr = SWIN_WIDGETADDR(hubaddr); + /* + * differentiate local register vs IO space access + */ + IOERROR_SETVALUE(ioerror,widgetnum,widgetnum); + IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr); + + + } else if (NODE_BWIN_ADDR(nasid, (paddr_t)p)){ + /* + * Address corresponds to large window space. + * Convert it to xtalk address. + */ + int bigwin; + hub_piomap_t bw_piomap; + xtalk_piomap_t xt_pmap = NULL; + iopaddr_t hubaddr; + xwidgetnum_t widgetnum; + iopaddr_t xtalkaddr; + + IOERROR_GETVALUE(p,ioerror,hubaddr); + hubaddr = p; + + /* + * Have to loop to find the correct xtalk_piomap + * because the're not allocated on a one-to-one + * basis to the window number. + */ + for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) { + bw_piomap = hubinfo_bwin_piomap_get(hinfo, + bigwin); + + if (bw_piomap->hpio_bigwin_num == + (BWIN_WINDOWNUM(hubaddr) - 1)) { + xt_pmap = hub_piomap_xt_piomap(bw_piomap); + break; + } + } + + ASSERT(xt_pmap); + + widgetnum = xtalk_pio_target_get(xt_pmap); + xtalkaddr = xtalk_pio_xtalk_addr_get(xt_pmap) + BWIN_WIDGETADDR(hubaddr); + + IOERROR_SETVALUE(ioerror,widgetnum,widgetnum); + IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr); + + /* + * Make sure that widgetnum doesnot map to hub + * register widget number, as we never use + * big window to access hub registers. + */ + ASSERT(widgetnum != HUB_REGISTER_WIDGET); + } + } else if (IOERROR_FIELDVALID(ioerror,hubaddr)) { + iopaddr_t hubaddr; + xwidgetnum_t widgetnum; + iopaddr_t xtalkaddr; + + IOERROR_GETVALUE(p,ioerror,hubaddr); + hubaddr = p; + if (BWIN_WINDOWNUM(hubaddr)){ + int window = BWIN_WINDOWNUM(hubaddr) - 1; + hubreg_t itte; + itte = (hubreg_t)HUB_L(IIO_ITTE_GET(nasid, window)); + widgetnum = (itte >> IIO_ITTE_WIDGET_SHIFT) & + IIO_ITTE_WIDGET_MASK; + xtalkaddr = (((itte >> IIO_ITTE_OFFSET_SHIFT) & + IIO_ITTE_OFFSET_MASK) << + BWIN_SIZE_BITS) + + BWIN_WIDGETADDR(hubaddr); + } else { + widgetnum = SWIN_WIDGETNUM(hubaddr); + xtalkaddr = SWIN_WIDGETADDR(hubaddr); + } + IOERROR_SETVALUE(ioerror,widgetnum,widgetnum); + IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr); + } else { + IOERROR_DUMP("hub_ioerror_handler", error_code, + mode, ioerror); + IOERR_PRINTF(printk( + "hub_ioerror_handler: Invalid address passed")); + + return IOERROR_INVALIDADDR; + } + + + IOERROR_GETVALUE(p,ioerror,widgetnum); + if ((p) == HUB_REGISTER_WIDGET) { + /* + * Error in accessing Hub local register + * This should happen mostly in SABLE mode.. + */ + retval = 0; + } else { + /* Make sure that the outbound widget access for this + * widget is enabled. + */ + if (!is_widget_pio_enabled(ioerror)) { + if (error_state_get(hub_v) == + ERROR_STATE_ACTION) + ioerror_dump("No outbound widget" + " access - ", + error_code, mode, ioerror); + return(IOERROR_HANDLED); + } + + + retval = hub_xp_error_handler( + hub_v, nasid, error_code, mode, ioerror); + + } + + IOERR_PRINTF(printk( + "hub_ioerror_handler:PIO_READ_ERROR return: %d", + retval)); + + break; + + case PIO_WRITE_ERROR: + /* + * This hub received an interrupt indicating a widget + * attached to this hub got a timeout. + * widgetnum field should be filled to indicate the + * widget that caused error. + * + * NOTE: This hub may have nothing to do with this error. + * We are here since the widget attached to the xbow + * gets its PIOs through this hub. + * + * There is nothing that can be done at this level. + * Just invoke the xtalk error handling mechanism. + */ + IOERROR_GETVALUE(p,ioerror,widgetnum); + if ((p) == HUB_REGISTER_WIDGET) { + } else { + /* Make sure that the outbound widget access for this + * widget is enabled. + */ + + if (!is_widget_pio_enabled(ioerror)) { + if (error_state_get(hub_v) == + ERROR_STATE_ACTION) + ioerror_dump("No outbound widget" + " access - ", + error_code, mode, ioerror); + return(IOERROR_HANDLED); + } + + retval = hub_xp_error_handler( + hub_v, nasid, error_code, mode, ioerror); + } + break; + + case DMA_READ_ERROR: + /* + * DMA Read error always ends up generating an interrupt + * at the widget level, and never at the hub level. So, + * we don't expect to come here any time + */ + ASSERT(0); + retval = IOERROR_UNHANDLED; + break; + + case DMA_WRITE_ERROR: + /* + * DMA Write error is generated when a write by an I/O + * device could not be completed. Problem is, device is + * totally unaware of this problem, and would continue + * writing to system memory. So, hub has a way to send + * an error interrupt on the first error, and bitbucket + * all further write transactions. + * Coming here indicates that hub detected one such error, + * and we need to handle it. + * + * Hub interrupt handler would have extracted physaddr, + * widgetnum, and widgetdevice from the CRB + * + * There is nothing special to do here, since gathering + * data from crb's is done elsewhere. Just pass the + * error to xtalk layer. + */ + retval = hub_xp_error_handler(hub_v, nasid, error_code, mode, + ioerror); + break; + + default: + ASSERT(0); + return IOERROR_BADERRORCODE; + + } + + /* + * If error was not handled, we may need to take certain action + * based on the error code. + * For e.g. in case of PIO_READ_ERROR, we may need to release the + * PIO Read entry table (they are sticky after errors). + * Similarly other cases. + * + * Further Action TBD + */ +end: + if (retval == IOERROR_HWGRAPH_LOOKUP) { + /* + * If we get errors very early, we can't traverse + * the path using hardware graph. + * To handle this situation, we need a functions + * which don't depend on the hardware graph vertex to + * handle errors. This break the modularity of the + * existing code. Instead we print out the reason for + * not handling error, and return. On return, all the + * info collected would be dumped. This should provide + * sufficient info to analyse the error. + */ + printk("Unable to handle IO error: hardware graph not setup\n"); + } + + return retval; +} + +#define L_BITSMINOR 18 +#define L_MAXMAJ 0x1ff +#define emajor(x) (int )(((unsigned )(x)>>L_BITSMINOR) & L_MAXMAJ) +#define dev_is_vertex(dev) (emajor((dev_t)(dev)) == 0) + +#define INFO_LBL_ERROR_STATE "error_state" + +#define v_error_state_get(v,s) \ +(hwgraph_info_get_LBL(v,INFO_LBL_ERROR_STATE, (arbitrary_info_t *)&s)) + +#define v_error_state_set(v,s,replace) \ +(replace ? \ +hwgraph_info_replace_LBL(v,INFO_LBL_ERROR_STATE,(arbitrary_info_t)s,0) :\ +hwgraph_info_add_LBL(v,INFO_LBL_ERROR_STATE, (arbitrary_info_t)s)) + + +#define v_error_state_clear(v) \ +(hwgraph_info_remove_LBL(v,INFO_LBL_ERROR_STATE,0)) + +/* + * error_state_get + * Get the state of the vertex. + * Returns ERROR_STATE_INVALID on failure + * current state otherwise + */ +error_state_t +error_state_get(devfs_handle_t v) +{ + error_state_t s; + + /* Check if we have a valid hwgraph vertex */ + if (!dev_is_vertex(v)) + return(ERROR_STATE_NONE); + + /* Get the labelled info hanging off the vertex which corresponds + * to the state. + */ + if (v_error_state_get(v, s) != GRAPH_SUCCESS) { + return(ERROR_STATE_NONE); + } + return(s); +} + + +/* + * error_state_set + * Set the state of the vertex + * Returns ERROR_RETURN_CODE_CANNOT_SET_STATE on failure + * ERROR_RETURN_CODE_SUCCESS otherwise + */ +error_return_code_t +error_state_set(devfs_handle_t v,error_state_t new_state) +{ + error_state_t old_state; + boolean_t replace = B_TRUE; + + /* Check if we have a valid hwgraph vertex */ + if (!dev_is_vertex(v)) + return(ERROR_RETURN_CODE_GENERAL_FAILURE); + + + /* This means that the error state needs to be cleaned */ + if (new_state == ERROR_STATE_NONE) { + /* Make sure that we have an error state */ + if (v_error_state_get(v,old_state) == GRAPH_SUCCESS) + v_error_state_clear(v); + return(ERROR_RETURN_CODE_SUCCESS); + } + + /* Check if the state information has been set at least once + * for this vertex. + */ + if (v_error_state_get(v,old_state) != GRAPH_SUCCESS) + replace = B_FALSE; + + if (v_error_state_set(v,new_state,replace) != GRAPH_SUCCESS) { + return(ERROR_RETURN_CODE_CANNOT_SET_STATE); + } + return(ERROR_RETURN_CODE_SUCCESS); +} diff -Nru a/arch/ia64/sn/io/sn2/xbow.c b/arch/ia64/sn/io/sn2/xbow.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/xbow.c Mon Feb 24 05:39:15 2003 @@ -0,0 +1,1681 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* #define DEBUG 1 */ +/* #define XBOW_DEBUG 1 */ +/* #define DEBUG_ERROR 1 */ + + +/* + * Files needed to get the device driver entry points + */ + +#include +#include +#include +#include + +#include +#include + + +#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DEL(ptr) (kfree(ptr)) + +int xbow_devflag = D_MP; + +/* + * This file supports the Xbow chip. Main functions: initializtion, + * error handling, and GBR. + */ + +/* + * each vertex corresponding to an xbow chip + * has a "fastinfo" pointer pointing at one + * of these things. + */ +typedef struct xbow_soft_s *xbow_soft_t; + +struct xbow_soft_s { + devfs_handle_t conn; /* our connection point */ + devfs_handle_t vhdl; /* xbow's private vertex */ + devfs_handle_t busv; /* the xswitch vertex */ + xbow_t *base; /* PIO pointer to crossbow chip */ + char *name; /* hwgraph name */ + + xbow_perf_t xbow_perfcnt[XBOW_PERF_COUNTERS]; + xbow_perf_link_t xbow_perflink[MAX_XBOW_PORTS]; + xbow_link_status_t xbow_link_status[MAX_XBOW_PORTS]; + spinlock_t xbow_perf_lock; + int link_monitor; + widget_cfg_t *wpio[MAX_XBOW_PORTS]; /* cached PIO pointer */ + + /* Bandwidth allocation state. Bandwidth values are for the + * destination port since contention happens there. + * Implicit mapping from xbow ports (8..f) -> (0..7) array indices. + */ + spinlock_t xbow_bw_alloc_lock; /* bw allocation lock */ + unsigned long long bw_hiwm[MAX_XBOW_PORTS]; /* hiwater mark values */ + unsigned long long bw_cur_used[MAX_XBOW_PORTS]; /* bw used currently */ +}; + +#define xbow_soft_set(v,i) hwgraph_fastinfo_set((v), (arbitrary_info_t)(i)) +#define xbow_soft_get(v) ((xbow_soft_t)hwgraph_fastinfo_get((v))) + +/* + * Function Table of Contents + */ + +void xbow_mlreset(xbow_t *); +void xbow_init(void); +int xbow_attach(devfs_handle_t); + +int xbow_open(devfs_handle_t *, int, int, cred_t *); +int xbow_close(devfs_handle_t, int, int, cred_t *); + +int xbow_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint); +int xbow_unmap(devfs_handle_t, vhandl_t *); +int xbow_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *); + +int xbow_widget_present(xbow_t *, int); +static int xbow_link_alive(xbow_t *, int); +devfs_handle_t xbow_widget_lookup(devfs_handle_t, int); + +void xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t); + + + +void xbow_update_perf_counters(devfs_handle_t); +xbow_perf_link_t *xbow_get_perf_counters(devfs_handle_t); +int xbow_enable_perf_counter(devfs_handle_t, int, int, int); +xbow_link_status_t *xbow_get_llp_status(devfs_handle_t); +void xbow_update_llp_status(devfs_handle_t); + +int xbow_disable_llp_monitor(devfs_handle_t); +int xbow_enable_llp_monitor(devfs_handle_t); +int xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t, + unsigned long long, unsigned long long); +static void xbow_setwidint(xtalk_intr_t); +void idbg_xbowregs(int64_t); + +xswitch_reset_link_f xbow_reset_link; + +xswitch_provider_t xbow_provider = +{ + xbow_reset_link, +}; + +/* + * This is the file operation table for the pcibr driver. + * As each of the functions are implemented, put the + * appropriate function name below. + */ +static int xbow_mmap(struct file * file, struct vm_area_struct * vma); +struct file_operations xbow_fops = { + owner: THIS_MODULE, + llseek: NULL, + read: NULL, + write: NULL, + readdir: NULL, + poll: NULL, + ioctl: NULL, + mmap: xbow_mmap, + open: xbow_open, + flush: NULL, + release: NULL, + fsync: NULL, + fasync: NULL, + lock: NULL, + readv: NULL, + writev: NULL, + sendpage: NULL, + get_unmapped_area: NULL +}; + +static int +xbow_mmap(struct file * file, struct vm_area_struct * vma) +{ + unsigned long phys_addr; + int error = 0; + + phys_addr = (unsigned long)file->private_data & ~0xc000000000000000; /* Mask out the Uncache bits */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= VM_RESERVED | VM_IO; + error = io_remap_page_range(vma, vma->vm_start, phys_addr, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + return(error); +} + + +/* + * xbow_mlreset: called at mlreset time if the + * platform specific code determines that there is + * a crossbow in a critical path that must be + * functional before the driver would normally get + * the device properly set up. + * + * what do we need to do, that the boot prom can + * not be counted on to have already done, that is + * generic across all platforms using crossbows? + */ +/*ARGSUSED */ +void +xbow_mlreset(xbow_t * xbow) +{ +} + +/* + * xbow_init: called with the rest of the device + * driver XXX_init routines. This platform *might* + * have a Crossbow chip, or even several, but it + * might have none. Register with the crosstalk + * generic provider so when we encounter the chip + * the right magic happens. + */ +void +xbow_init(void) +{ + +#if DEBUG && ATTACH_DEBUG + printk("xbow_init\n"); +#endif + + xwidget_driver_register(PXBOW_WIDGET_PART_NUM, + 0, /* XXBOW_WIDGET_MFGR_NUM, */ + "xbow_", + CDL_PRI_HI); /* attach before friends */ + + + xwidget_driver_register(XXBOW_WIDGET_PART_NUM, + 0, /* XXBOW_WIDGET_MFGR_NUM, */ + "xbow_", + CDL_PRI_HI); /* attach before friends */ + + xwidget_driver_register(XBOW_WIDGET_PART_NUM, + XBOW_WIDGET_MFGR_NUM, + "xbow_", + CDL_PRI_HI); /* attach before friends */ +} + +#ifdef XBRIDGE_REGS_SIM +/* xbow_set_simulated_regs: sets xbow regs as needed + * for powering through the boot + */ +void +xbow_set_simulated_regs(xbow_t *xbow, int port) +{ + /* + * turn on link + */ + xbow->xb_link(port).link_status = (1<<31); + /* + * and give it a live widget too + */ + xbow->xb_link(port).link_aux_status = XB_AUX_STAT_PRESENT; + /* + * zero the link control reg + */ + xbow->xb_link(port).link_control = 0x0; +} +#endif /* XBRIDGE_REGS_SIM */ + +/* + * xbow_attach: the crosstalk provider has + * determined that there is a crossbow widget + * present, and has handed us the connection + * point for that vertex. + * + * We not only add our own vertex, but add + * some "xtalk switch" data to the switch + * vertex (at the connect point's parent) if + * it does not have any. + */ + +/*ARGSUSED */ +int +xbow_attach(devfs_handle_t conn) +{ + /*REFERENCED */ + devfs_handle_t vhdl; + devfs_handle_t busv; + xbow_t *xbow; + xbow_soft_t soft; + int port; + xswitch_info_t info; + xtalk_intr_t intr_hdl; + char devnm[MAXDEVNAME], *s; + xbowreg_t id; + int rev; + int i; + int xbow_num; + static void xbow_errintr_handler(int, void *, struct pt_regs *); + + +#if DEBUG && ATTACH_DEBUG +#if defined(SUPPORT_PRINTING_V_FORMAT) + printk("%v: xbow_attach\n", conn); +#else + printk("0x%x: xbow_attach\n", conn); +#endif +#endif + + /* + * Get a PIO pointer to the base of the crossbow + * chip. + */ +#ifdef XBRIDGE_REGS_SIM + printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: allocating %ld bytes for xbow_s\n", sizeof(xbow_t)); + xbow = (xbow_t *) kmalloc(sizeof(xbow_t), GFP_KERNEL); + /* + * turn on ports e and f like in a real live ibrick + */ + xbow_set_simulated_regs(xbow, 0xe); + xbow_set_simulated_regs(xbow, 0xf); +#else + xbow = (xbow_t *) xtalk_piotrans_addr(conn, 0, 0, sizeof(xbow_t), 0); +#endif /* XBRIDGE_REGS_SIM */ + + /* + * Locate the "switch" vertex: it is the parent + * of our connection point. + */ + busv = hwgraph_connectpt_get(conn); +#if DEBUG && ATTACH_DEBUG + printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%x\n", busv, conn, xbow, *(volatile u32 *)xbow); +#endif + + ASSERT(busv != GRAPH_VERTEX_NONE); + + /* + * Create our private vertex, and connect our + * driver information to it. This makes it possible + * for diagnostic drivers to open the crossbow + * vertex for access to registers. + */ + + /* + * Register a xbow driver with devfs. + * file ops. + */ + vhdl = NULL; + vhdl = devfs_register(conn, EDGE_LBL_XBOW, + DEVFS_FL_AUTO_DEVNUM, 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, + &xbow_fops, (void *)xbow); + if (!vhdl) { + printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %p\n", + (void *)conn); + } + + /* + * Allocate the soft state structure and attach + * it to the xbow's vertex + */ + NEW(soft); + soft->conn = conn; + soft->vhdl = vhdl; + soft->busv = busv; + soft->base = xbow; + /* does the universe really need another macro? */ + /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */ + /* hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft); */ + +#define XBOW_NUM_SUFFIX_FORMAT "[xbow# %d]" + + /* Add xbow number as a suffix to the hwgraph name of the xbow. + * This is helpful while looking at the error/warning messages. + */ + xbow_num = 0; + + /* + * get the name of this xbow vertex and keep the info. + * This is needed during errors and interupts, but as + * long as we have it, we can use it elsewhere. + */ + s = dev_to_name(vhdl, devnm, MAXDEVNAME); + soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, + GFP_KERNEL); + sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num); + +#ifdef XBRIDGE_REGS_SIM + /* my o200/ibrick has id=0x2d002049, but XXBOW_WIDGET_PART_NUM is defined + * as 0xd000, so I'm using that for the partnum bitfield. + */ + printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: need xb_wid_id value!!\n"); + id = 0x2d000049; +#else + id = xbow->xb_wid_id; +#endif /* XBRIDGE_REGS_SIM */ + rev = XWIDGET_PART_REV_NUM(id); + + mutex_spinlock_init(&soft->xbow_perf_lock); + soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a; + soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b; + + /* Initialization for GBR bw allocation */ + mutex_spinlock_init(&soft->xbow_bw_alloc_lock); + +#define XBOW_8_BIT_PORT_BW_MAX (400 * 1000 * 1000) /* 400 MB/s */ +#define XBOW_16_BIT_PORT_BW_MAX (800 * 1000 * 1000) /* 800 MB/s */ + + /* Set bandwidth hiwatermark and current values */ + for (i = 0; i < MAX_XBOW_PORTS; i++) { + soft->bw_hiwm[i] = XBOW_16_BIT_PORT_BW_MAX; /* for now */ + soft->bw_cur_used[i] = 0; + } + + /* + * attach the crossbow error interrupt. + */ + intr_hdl = xtalk_intr_alloc(conn, (device_desc_t)0, vhdl); + ASSERT(intr_hdl != NULL); + + xtalk_intr_connect(intr_hdl, + (intr_func_t) xbow_errintr_handler, + (intr_arg_t) soft, + (xtalk_intr_setfunc_t) xbow_setwidint, + (void *) xbow); + + request_irq(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid, + ((hub_intr_t)intr_hdl)->i_bit), + (intr_func_t)xbow_errintr_handler, 0, "XBOW error", + (intr_arg_t) soft); + +#ifdef BUS_INT_WAR_NOT_YET + { + void sn_add_polled_interrupt(int, int); + sn_add_polled_interrupt(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid, + ((hub_intr_t)intr_hdl)->i_bit), 5000); + } +#endif + + + /* + * Enable xbow error interrupts + */ + xbow->xb_wid_control = (XB_WID_CTRL_REG_ACC_IE | XB_WID_CTRL_XTALK_IE); + + /* + * take a census of the widgets present, + * leaving notes at the switch vertex. + */ + info = xswitch_info_new(busv); + + for (port = MAX_PORT_NUM - MAX_XBOW_PORTS; + port < MAX_PORT_NUM; ++port) { + if (!xbow_link_alive(xbow, port)) { +#if DEBUG && XBOW_DEBUG + printk(KERN_INFO "0x%p link %d is not alive\n", + (void *)busv, port); +#endif + continue; + } + if (!xbow_widget_present(xbow, port)) { +#if DEBUG && XBOW_DEBUG + printk(KERN_INFO "0x%p link %d is alive but no widget is present\n", (void *)busv, port); +#endif + continue; + } +#if DEBUG && XBOW_DEBUG + printk(KERN_INFO "0x%p link %d has a widget\n", + (void *)busv, port); +#endif + + xswitch_info_link_is_ok(info, port); + /* + * Turn some error interrupts on + * and turn others off. The PROM has + * some things turned on we don't + * want to see (bandwidth allocation + * errors for instance); so if it + * is not listed here, it is not on. + */ + xbow->xb_link(port).link_control = + ( (xbow->xb_link(port).link_control + /* + * Turn off these bits; they are non-fatal, + * but we might want to save some statistics + * on the frequency of these errors. + * XXX FIXME XXX + */ + & ~XB_CTRL_RCV_CNT_OFLOW_IE + & ~XB_CTRL_XMT_CNT_OFLOW_IE + & ~XB_CTRL_BNDWDTH_ALLOC_IE + & ~XB_CTRL_RCV_IE) + /* + * These are the ones we want to turn on. + */ + | (XB_CTRL_ILLEGAL_DST_IE + | XB_CTRL_OALLOC_IBUF_IE + | XB_CTRL_XMT_MAX_RTRY_IE + | XB_CTRL_MAXREQ_TOUT_IE + | XB_CTRL_XMT_RTRY_IE + | XB_CTRL_SRC_TOUT_IE) ); + } + + xswitch_provider_register(busv, &xbow_provider); + + return 0; /* attach successful */ +} + +/*ARGSUSED */ +int +xbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp) +{ + return 0; +} + +/*ARGSUSED */ +int +xbow_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp) +{ + return 0; +} + +/*ARGSUSED */ +int +xbow_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot) +{ + devfs_handle_t vhdl = dev_to_vhdl(dev); + xbow_soft_t soft = xbow_soft_get(vhdl); + int error; + + ASSERT(soft); + len = ctob(btoc(len)); + /* XXX- this ignores the offset!!! */ + error = v_mapphys(vt, (void *) soft->base, len); + return error; +} + +/*ARGSUSED */ +int +xbow_unmap(devfs_handle_t dev, vhandl_t *vt) +{ + return 0; +} + +/* This contains special-case code for grio. There are plans to make + * this general sometime in the future, but till then this should + * be good enough. + */ +xwidgetnum_t +xbow_widget_num_get(devfs_handle_t dev) +{ + devfs_handle_t tdev; + char devname[MAXDEVNAME]; + xwidget_info_t xwidget_info; + int i; + + vertex_to_name(dev, devname, MAXDEVNAME); + + /* If this is a pci controller vertex, traverse up using + * the ".." links to get to the widget. + */ + if (strstr(devname, EDGE_LBL_PCI) && + strstr(devname, EDGE_LBL_CONTROLLER)) { + tdev = dev; + for (i=0; i< 2; i++) { + if (hwgraph_edge_get(tdev, + HWGRAPH_EDGELBL_DOTDOT, &tdev) != + GRAPH_SUCCESS) + return XWIDGET_NONE; + } + + if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) { + return (xwidget_info_id_get(xwidget_info)); + } else { + return XWIDGET_NONE; + } + } + + return XWIDGET_NONE; +} + +int +xbow_ioctl(devfs_handle_t dev, + int cmd, + void *arg, + int flag, + struct cred *cr, + int *rvalp) +{ + devfs_handle_t vhdl; + int error = 0; + +#if defined (DEBUG) + int rc; + devfs_handle_t conn; + struct xwidget_info_s *xwidget_info; + xbow_soft_t xbow_soft; +#endif + *rvalp = 0; + + vhdl = dev_to_vhdl(dev); +#if defined (DEBUG) + xbow_soft = xbow_soft_get(vhdl); + conn = xbow_soft->conn; + + xwidget_info = xwidget_info_get(conn); + ASSERT_ALWAYS(xwidget_info != NULL); + + rc = xwidget_hwid_is_xswitch(&xwidget_info->w_hwid); + ASSERT_ALWAYS(rc != 0); +#endif + switch (cmd) { + + case XBOWIOC_LLP_ERROR_ENABLE: + if ((error = xbow_enable_llp_monitor(vhdl)) != 0) + error = EINVAL; + + break; + + case XBOWIOC_LLP_ERROR_DISABLE: + + if ((error = xbow_disable_llp_monitor(vhdl)) != 0) + error = EINVAL; + + break; + + default: + break; + + } + return error; +} + +/* + * xbow_widget_present: See if a device is present + * on the specified port of this crossbow. + */ +int +xbow_widget_present(xbow_t *xbow, int port) +{ + if ( IS_RUNNING_ON_SIMULATOR() ) { + if ( (port == 14) || (port == 15) ) { + return 1; + } + else { + return 0; + } + } + else { + /* WAR: port 0xf on PIC is missing present bit */ + if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) && + IS_PIC_XBOW(xbow->xb_wid_id) && port==0xf) { + return 1; + } + return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT; + } +} + +static int +xbow_link_alive(xbow_t * xbow, int port) +{ + xbwX_stat_t xbow_linkstat; + + xbow_linkstat.linkstatus = xbow->xb_link(port).link_status; + return (xbow_linkstat.link_alive); +} + +/* + * xbow_widget_lookup + * Lookup the edges connected to the xbow specified, and + * retrieve the handle corresponding to the widgetnum + * specified. + * If not found, return 0. + */ +devfs_handle_t +xbow_widget_lookup(devfs_handle_t vhdl, + int widgetnum) +{ + xswitch_info_t xswitch_info; + devfs_handle_t conn; + + xswitch_info = xswitch_info_get(vhdl); + conn = xswitch_info_vhdl_get(xswitch_info, widgetnum); + return conn; +} + +/* + * xbow_setwidint: called when xtalk + * is establishing or migrating our + * interrupt service. + */ +static void +xbow_setwidint(xtalk_intr_t intr) +{ + xwidgetnum_t targ = xtalk_intr_target_get(intr); + iopaddr_t addr = xtalk_intr_addr_get(intr); + xtalk_intr_vector_t vect = xtalk_intr_vector_get(intr); + xbow_t *xbow = (xbow_t *) xtalk_intr_sfarg_get(intr); + + xbow_intr_preset((void *) xbow, 0, targ, addr, vect); +} + +/* + * xbow_intr_preset: called during mlreset time + * if the platform specific code needs to route + * an xbow interrupt before the xtalk infrastructure + * is available for use. + * + * Also called from xbow_setwidint, so we don't + * replicate the guts of the routine. + * + * XXX- probably should be renamed xbow_wid_intr_set or + * something to reduce confusion. + */ +/*ARGSUSED3 */ +void +xbow_intr_preset(void *which_widget, + int which_widget_intr, + xwidgetnum_t targ, + iopaddr_t addr, + xtalk_intr_vector_t vect) +{ + xbow_t *xbow = (xbow_t *) which_widget; + + xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) | + (0x000F0000 & (targ << 16)) | + XTALK_ADDR_TO_UPPER(addr)); + xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr); + +} + +#define XEM_ADD_STR(s) printk("%s", (s)) +#define XEM_ADD_NVAR(n,v) printk("\t%20s: 0x%llx\n", (n), ((unsigned long long)v)) +#define XEM_ADD_VAR(v) XEM_ADD_NVAR(#v,(v)) +#define XEM_ADD_IOEF(p,n) if (IOERROR_FIELDVALID(ioe,n)) { \ + IOERROR_GETVALUE(p,ioe,n); \ + XEM_ADD_NVAR("ioe." #n, p); \ + } + +#ifdef LATER +static void +xem_add_ioe(ioerror_t *ioe) +{ + union tmp { + ushort stmp; + unsigned long long lltmp; + cpuid_t cputmp; + cnodeid_t cntmp; + iopaddr_t iotmp; + caddr_t catmp; + paddr_t patmp; + } tmp; + + XEM_ADD_IOEF(tmp.stmp, errortype); + XEM_ADD_IOEF(tmp.stmp, widgetnum); + XEM_ADD_IOEF(tmp.stmp, widgetdev); + XEM_ADD_IOEF(tmp.cputmp, srccpu); + XEM_ADD_IOEF(tmp.cntmp, srcnode); + XEM_ADD_IOEF(tmp.cntmp, errnode); + XEM_ADD_IOEF(tmp.iotmp, sysioaddr); + XEM_ADD_IOEF(tmp.iotmp, xtalkaddr); + XEM_ADD_IOEF(tmp.iotmp, busspace); + XEM_ADD_IOEF(tmp.iotmp, busaddr); + XEM_ADD_IOEF(tmp.catmp, vaddr); + XEM_ADD_IOEF(tmp.patmp, memaddr); + XEM_ADD_IOEF(tmp.catmp, epc); + XEM_ADD_IOEF(tmp.catmp, ef); + XEM_ADD_IOEF(tmp.stmp, tnum); +} + +#define XEM_ADD_IOE() (xem_add_ioe(ioe)) +#endif /* LATER */ + +int xbow_xmit_retry_errors = 0; + +int +xbow_xmit_retry_error(xbow_soft_t soft, + int port) +{ + xswitch_info_t info; + devfs_handle_t vhdl; + widget_cfg_t *wid; + widgetreg_t id; + int part; + int mfgr; + + wid = soft->wpio[port - BASE_XBOW_PORT]; + if (wid == NULL) { + /* If we can't track down a PIO + * pointer to our widget yet, + * leave our caller knowing that + * we are interested in this + * interrupt if it occurs in + * the future. + */ + info = xswitch_info_get(soft->busv); + if (!info) + return 1; + vhdl = xswitch_info_vhdl_get(info, port); + if (vhdl == GRAPH_VERTEX_NONE) + return 1; + wid = (widget_cfg_t *) xtalk_piotrans_addr + (vhdl, 0, 0, sizeof *wid, 0); + if (!wid) + return 1; + soft->wpio[port - BASE_XBOW_PORT] = wid; + } + id = wid->w_id; + part = XWIDGET_PART_NUM(id); + mfgr = XWIDGET_MFG_NUM(id); + + /* If this thing is not a Bridge, + * do not activate the WAR, and + * tell our caller we do not need + * to be called again. + */ + if ((part != BRIDGE_WIDGET_PART_NUM) || + (mfgr != BRIDGE_WIDGET_MFGR_NUM)) { + /* FIXME: add Xbridge to the WAR. + * Shouldn't hurt anything. Later need to + * check if we can remove this. + */ + if ((part != XBRIDGE_WIDGET_PART_NUM) || + (mfgr != XBRIDGE_WIDGET_MFGR_NUM)) + return 0; + } + + /* count how many times we + * have picked up after + * LLP Transmit problems. + */ + xbow_xmit_retry_errors++; + + /* rewrite the control register + * to fix things up. + */ + wid->w_control = wid->w_control; + wid->w_control; + + return 1; +} + +/* + * xbow_errintr_handler will be called if the xbow + * sends an interrupt request to report an error. + */ +static void +xbow_errintr_handler(int irq, void *arg, struct pt_regs *ep) +{ + ioerror_t ioe[1]; + xbow_soft_t soft = (xbow_soft_t) arg; + xbow_t *xbow = soft->base; + xbowreg_t wid_control; + xbowreg_t wid_stat; + xbowreg_t wid_err_cmdword; + xbowreg_t wid_err_upper; + xbowreg_t wid_err_lower; + w_err_cmd_word_u wid_err; + unsigned long long wid_err_addr; + + int fatal = 0; + int dump_ioe = 0; + static int xbow_error_handler(void *, int, ioerror_mode_t, ioerror_t *); + + wid_control = xbow->xb_wid_control; + wid_stat = xbow->xb_wid_stat_clr; + wid_err_cmdword = xbow->xb_wid_err_cmdword; + wid_err_upper = xbow->xb_wid_err_upper; + wid_err_lower = xbow->xb_wid_err_lower; + xbow->xb_wid_err_cmdword = 0; + + wid_err_addr = wid_err_lower | (((iopaddr_t) wid_err_upper & WIDGET_ERR_UPPER_ADDR_ONLY) << 32); + + if (wid_stat & XB_WID_STAT_LINK_INTR_MASK) { + int port; + + wid_err.r = wid_err_cmdword; + + for (port = MAX_PORT_NUM - MAX_XBOW_PORTS; + port < MAX_PORT_NUM; port++) { + if (wid_stat & XB_WID_STAT_LINK_INTR(port)) { + xb_linkregs_t *link = &(xbow->xb_link(port)); + xbowreg_t link_control = link->link_control; + xbowreg_t link_status = link->link_status_clr; + xbowreg_t link_aux_status = link->link_aux_status; + xbowreg_t link_pend; + + link_pend = link_status & link_control & + (XB_STAT_ILLEGAL_DST_ERR + | XB_STAT_OALLOC_IBUF_ERR + | XB_STAT_RCV_CNT_OFLOW_ERR + | XB_STAT_XMT_CNT_OFLOW_ERR + | XB_STAT_XMT_MAX_RTRY_ERR + | XB_STAT_RCV_ERR + | XB_STAT_XMT_RTRY_ERR + | XB_STAT_MAXREQ_TOUT_ERR + | XB_STAT_SRC_TOUT_ERR + ); + + if (link_pend & XB_STAT_ILLEGAL_DST_ERR) { + if (wid_err.f.sidn == port) { + IOERROR_INIT(ioe); + IOERROR_SETVALUE(ioe, widgetnum, port); + IOERROR_SETVALUE(ioe, xtalkaddr, wid_err_addr); + if (IOERROR_HANDLED == + xbow_error_handler(soft, + IOECODE_DMA, + MODE_DEVERROR, + ioe)) { + link_pend &= ~XB_STAT_ILLEGAL_DST_ERR; + } else { + dump_ioe++; + } + } + } + /* Xbow/Bridge WAR: + * if the bridge signals an LLP Transmitter Retry, + * rewrite its control register. + * If someone else triggers this interrupt, + * ignore (and disable) the interrupt. + */ + if (link_pend & XB_STAT_XMT_RTRY_ERR) { + if (!xbow_xmit_retry_error(soft, port)) { + link_control &= ~XB_CTRL_XMT_RTRY_IE; + link->link_control = link_control; + link->link_control; /* stall until written */ + } + link_pend &= ~XB_STAT_XMT_RTRY_ERR; + } + if (link_pend) { + devfs_handle_t xwidget_vhdl; + char *xwidget_name; + + /* Get the widget name corresponding to the current + * xbow link. + */ + xwidget_vhdl = xbow_widget_lookup(soft->busv,port); + xwidget_name = xwidget_name_get(xwidget_vhdl); + + printk("%s port %X[%s] XIO Bus Error", + soft->name, port, xwidget_name); + if (link_status & XB_STAT_MULTI_ERR) + XEM_ADD_STR("\tMultiple Errors\n"); + if (link_status & XB_STAT_ILLEGAL_DST_ERR) + XEM_ADD_STR("\tInvalid Packet Destination\n"); + if (link_status & XB_STAT_OALLOC_IBUF_ERR) + XEM_ADD_STR("\tInput Overallocation Error\n"); + if (link_status & XB_STAT_RCV_CNT_OFLOW_ERR) + XEM_ADD_STR("\tLLP receive error counter overflow\n"); + if (link_status & XB_STAT_XMT_CNT_OFLOW_ERR) + XEM_ADD_STR("\tLLP transmit retry counter overflow\n"); + if (link_status & XB_STAT_XMT_MAX_RTRY_ERR) + XEM_ADD_STR("\tLLP Max Transmitter Retry\n"); + if (link_status & XB_STAT_RCV_ERR) + XEM_ADD_STR("\tLLP Receiver error\n"); + if (link_status & XB_STAT_XMT_RTRY_ERR) + XEM_ADD_STR("\tLLP Transmitter Retry\n"); + if (link_status & XB_STAT_MAXREQ_TOUT_ERR) + XEM_ADD_STR("\tMaximum Request Timeout\n"); + if (link_status & XB_STAT_SRC_TOUT_ERR) + XEM_ADD_STR("\tSource Timeout Error\n"); + + { + int other_port; + + for (other_port = 8; other_port < 16; ++other_port) { + if (link_aux_status & (1 << other_port)) { + /* XXX- need to go to "other_port" + * and clean up after the timeout? + */ + XEM_ADD_VAR(other_port); + } + } + } + +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_VAR(link_control); + XEM_ADD_VAR(link_status); + XEM_ADD_VAR(link_aux_status); + +#ifdef LATER + if (dump_ioe) { + XEM_ADD_IOE(); + dump_ioe = 0; + } +#endif +#if !DEBUG + } +#endif + fatal++; + } + } + } + } + if (wid_stat & wid_control & XB_WID_STAT_WIDGET0_INTR) { + /* we have a "widget zero" problem */ + + if (wid_stat & (XB_WID_STAT_MULTI_ERR + | XB_WID_STAT_XTALK_ERR + | XB_WID_STAT_REG_ACC_ERR)) { + + printk("%s Port 0 XIO Bus Error", + soft->name); + if (wid_stat & XB_WID_STAT_MULTI_ERR) + XEM_ADD_STR("\tMultiple Error\n"); + if (wid_stat & XB_WID_STAT_XTALK_ERR) + XEM_ADD_STR("\tXIO Error\n"); + if (wid_stat & XB_WID_STAT_REG_ACC_ERR) + XEM_ADD_STR("\tRegister Access Error\n"); + + fatal++; + } + } + if (fatal) { + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_control); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); + PRINT_PANIC("XIO Bus Error"); + } +} + +/* + * XBOW ERROR Handling routines. + * These get invoked as part of walking down the error handling path + * from hub/heart towards the I/O device that caused the error. + */ + +/* + * xbow_error_handler + * XBow error handling dispatch routine. + * This is the primary interface used by external world to invoke + * in case of an error related to a xbow. + * Only functionality in this layer is to identify the widget handle + * given the widgetnum. Otherwise, xbow does not gathers any error + * data. + */ +static int +xbow_error_handler( + void *einfo, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + int retval = IOERROR_WIDGETLEVEL; + + xbow_soft_t soft = (xbow_soft_t) einfo; + int port; + devfs_handle_t conn; + devfs_handle_t busv; + + xbow_t *xbow = soft->base; + xbowreg_t wid_stat; + xbowreg_t wid_err_cmdword; + xbowreg_t wid_err_upper; + xbowreg_t wid_err_lower; + unsigned long long wid_err_addr; + + xb_linkregs_t *link; + xbowreg_t link_control; + xbowreg_t link_status; + xbowreg_t link_aux_status; + + ASSERT(soft != 0); + busv = soft->busv; + +#if DEBUG && ERROR_DEBUG + printk("%s: xbow_error_handler\n", soft->name, busv); +#endif + + IOERROR_GETVALUE(port, ioerror, widgetnum); + + if (port == 0) { + /* error during access to xbow: + * do NOT attempt to access xbow regs. + */ + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (error_code & IOECODE_DMA) { + printk(KERN_ALERT + "DMA error blamed on Crossbow at %s\n" + "\tbut Crosbow never initiates DMA!", + soft->name); + } + if (error_code & IOECODE_PIO) { + iopaddr_t tmp; + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + printk(KERN_ALERT "PIO Error on XIO Bus %s\n" + "\tattempting to access XIO controller\n" + "\twith offset 0x%lx", + soft->name, tmp); + } + /* caller will dump contents of ioerror + * in DEBUG and kdebug kernels. + */ + + return retval; + } + /* + * error not on port zero: + * safe to read xbow registers. + */ + wid_stat = xbow->xb_wid_stat; + wid_err_cmdword = xbow->xb_wid_err_cmdword; + wid_err_upper = xbow->xb_wid_err_upper; + wid_err_lower = xbow->xb_wid_err_lower; + + wid_err_addr = + wid_err_lower + | (((iopaddr_t) wid_err_upper + & WIDGET_ERR_UPPER_ADDR_ONLY) + << 32); + + if ((port < BASE_XBOW_PORT) || + (port >= MAX_PORT_NUM)) { + + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (error_code & IOECODE_DMA) { + printk(KERN_ALERT + "DMA error blamed on XIO port at %s/%d\n" + "\tbut Crossbow does not support that port", + soft->name, port); + } + if (error_code & IOECODE_PIO) { + iopaddr_t tmp; + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + printk(KERN_ALERT + "PIO Error on XIO Bus %s\n" + "\tattempting to access XIO port %d\n" + "\t(which Crossbow does not support)" + "\twith offset 0x%lx", + soft->name, port, tmp); + } +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_STR("Raw status values for Crossbow:\n"); + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); +#if !DEBUG + } +#endif + + /* caller will dump contents of ioerror + * in DEBUG and kdebug kernels. + */ + + return retval; + } + /* access to valid port: + * ok to check port status. + */ + + link = &(xbow->xb_link(port)); + link_control = link->link_control; + link_status = link->link_status; + link_aux_status = link->link_aux_status; + + /* Check that there is something present + * in that XIO port. + */ + /* WAR: PIC widget 0xf is missing prescense bit */ + if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) && + IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xf)) + ; + else + if (!(link_aux_status & XB_AUX_STAT_PRESENT)) { + /* nobody connected. */ + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (error_code & IOECODE_DMA) { + printk(KERN_ALERT + "DMA error blamed on XIO port at %s/%d\n" + "\tbut there is no device connected there.", + soft->name, port); + } + if (error_code & IOECODE_PIO) { + iopaddr_t tmp; + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + printk(KERN_ALERT + "PIO Error on XIO Bus %s\n" + "\tattempting to access XIO port %d\n" + "\t(which has no device connected)" + "\twith offset 0x%lx", + soft->name, port, tmp); + } +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_STR("Raw status values for Crossbow:\n"); + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); + XEM_ADD_VAR(port); + XEM_ADD_VAR(link_control); + XEM_ADD_VAR(link_status); + XEM_ADD_VAR(link_aux_status); +#if !DEBUG + } +#endif + return retval; + + } + /* Check that the link is alive. + */ + if (!(link_status & XB_STAT_LINKALIVE)) { + iopaddr_t tmp; + /* nobody connected. */ + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + printk(KERN_ALERT + "%s%sError on XIO Bus %s port %d", + (error_code & IOECODE_DMA) ? "DMA " : "", + (error_code & IOECODE_PIO) ? "PIO " : "", + soft->name, port); + + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + if ((error_code & IOECODE_PIO) && + (IOERROR_FIELDVALID(ioerror, xtalkaddr))) { + printk("\tAccess attempted to offset 0x%lx\n", tmp); + } + if (link_aux_status & XB_AUX_LINKFAIL_RST_BAD) + XEM_ADD_STR("\tLink never came out of reset\n"); + else + XEM_ADD_STR("\tLink failed while transferring data\n"); + + } + /* get the connection point for the widget + * involved in this error; if it exists and + * is not our connectpoint, cycle back through + * xtalk_error_handler to deliver control to + * the proper handler (or to report a generic + * crosstalk error). + * + * If the downstream handler won't handle + * the problem, we let our upstream caller + * deal with it, after (in DEBUG and kdebug + * kernels) dumping the xbow state for this + * port. + */ + conn = xbow_widget_lookup(busv, port); + if ((conn != GRAPH_VERTEX_NONE) && + (conn != soft->conn)) { + retval = xtalk_error_handler(conn, error_code, mode, ioerror); + if (retval == IOERROR_HANDLED) + return IOERROR_HANDLED; + } + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (retval == IOERROR_UNHANDLED) { + iopaddr_t tmp; + retval = IOERROR_PANIC; + + printk(KERN_ALERT + "%s%sError on XIO Bus %s port %d", + (error_code & IOECODE_DMA) ? "DMA " : "", + (error_code & IOECODE_PIO) ? "PIO " : "", + soft->name, port); + + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + if ((error_code & IOECODE_PIO) && + (IOERROR_FIELDVALID(ioerror, xtalkaddr))) { + printk("\tAccess attempted to offset 0x%lx\n", tmp); + } + } + +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_STR("Raw status values for Crossbow:\n"); + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); + XEM_ADD_VAR(port); + XEM_ADD_VAR(link_control); + XEM_ADD_VAR(link_status); + XEM_ADD_VAR(link_aux_status); +#if !DEBUG + } +#endif + /* caller will dump raw ioerror data + * in DEBUG and kdebug kernels. + */ + + return retval; +} + +void +xbow_update_perf_counters(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_perf_t *xbow_perf = xbow_soft->xbow_perfcnt; + xbow_perf_link_t *xbow_plink = xbow_soft->xbow_perflink; + xbow_perfcount_t perf_reg; + unsigned long s; + int link, i; + + for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) { + if (xbow_perf->xp_mode == XBOW_MONITOR_NONE) + continue; + + s = mutex_spinlock(&xbow_soft->xbow_perf_lock); + + perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg; + + link = perf_reg.xb_perf.link_select; + + (xbow_plink + link)->xlp_cumulative[xbow_perf->xp_curmode] += + ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK); + xbow_perf->xp_current = perf_reg.xb_perf.count; + + mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); + } +} + +xbow_perf_link_t * +xbow_get_perf_counters(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_perf_link_t *xbow_perf_link = xbow_soft->xbow_perflink; + + return xbow_perf_link; +} + +int +xbow_enable_perf_counter(devfs_handle_t vhdl, int link, int mode, int counter) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_perf_t *xbow_perf = xbow_soft->xbow_perfcnt; + xbow_linkctrl_t xbow_link_ctrl; + xbow_t *xbow = xbow_soft->base; + xbow_perfcount_t perf_reg; + unsigned long s; + int i; + + link -= BASE_XBOW_PORT; + if ((link < 0) || (link >= MAX_XBOW_PORTS)) + return -1; + + if ((mode < XBOW_MONITOR_NONE) || (mode > XBOW_MONITOR_DEST_LINK)) + return -1; + + if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS)) + return -1; + + s = mutex_spinlock(&xbow_soft->xbow_perf_lock); + + if ((xbow_perf + counter)->xp_mode && mode) { + mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); + return -1; + } + for (i = 0; i < XBOW_PERF_COUNTERS; i++) { + if (i == counter) + continue; + if (((xbow_perf + i)->xp_link == link) && + ((xbow_perf + i)->xp_mode)) { + mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); + return -1; + } + } + xbow_perf += counter; + + xbow_perf->xp_curlink = xbow_perf->xp_link = link; + xbow_perf->xp_curmode = xbow_perf->xp_mode = mode; + + xbow_link_ctrl.xbl_ctrlword = xbow->xb_link_raw[link].link_control; + xbow_link_ctrl.xb_linkcontrol.perf_mode = mode; + xbow->xb_link_raw[link].link_control = xbow_link_ctrl.xbl_ctrlword; + + perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg; + perf_reg.xb_perf.link_select = link; + *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val; + xbow_perf->xp_current = perf_reg.xb_perf.count; + + mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); + return 0; +} + +xbow_link_status_t * +xbow_get_llp_status(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_link_status_t *xbow_llp_status = xbow_soft->xbow_link_status; + + return xbow_llp_status; +} + +void +xbow_update_llp_status(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + xbow_link_status_t *xbow_llp_status = xbow_soft->xbow_link_status; + xbow_t *xbow; + xbwX_stat_t lnk_sts; + xbow_aux_link_status_t aux_sts; + int link; + devfs_handle_t xwidget_vhdl; + char *xwidget_name; + + xbow = (xbow_t *) xbow_soft->base; + for (link = 0; link < MAX_XBOW_PORTS; link++, xbow_llp_status++) { + /* Get the widget name corresponding the current link. + * Note : 0 <= link < MAX_XBOW_PORTS(8). + * BASE_XBOW_PORT(0x8) <= xwidget number < MAX_PORT_NUM (0x10) + */ + xwidget_vhdl = xbow_widget_lookup(xbow_soft->busv,link+BASE_XBOW_PORT); + xwidget_name = xwidget_name_get(xwidget_vhdl); + aux_sts.aux_linkstatus + = xbow->xb_link_raw[link].link_aux_status; + lnk_sts.linkstatus = xbow->xb_link_raw[link].link_status_clr; + + if (lnk_sts.link_alive == 0) + continue; + + xbow_llp_status->rx_err_count += + aux_sts.xb_aux_linkstatus.rx_err_cnt; + + xbow_llp_status->tx_retry_count += + aux_sts.xb_aux_linkstatus.tx_retry_cnt; + + if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) { +#ifdef LATER + printk(KERN_WARNING "link %d[%s]: bad status 0x%x\n", + link, xwidget_name, lnk_sts.linkstatus); +#endif + } + } +} + +int +xbow_disable_llp_monitor(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + int port; + + for (port = 0; port < MAX_XBOW_PORTS; port++) { + xbow_soft->xbow_link_status[port].rx_err_count = 0; + xbow_soft->xbow_link_status[port].tx_retry_count = 0; + } + + xbow_soft->link_monitor = 0; + return 0; +} + +int +xbow_enable_llp_monitor(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + + xbow_soft->link_monitor = 1; + return 0; +} + + +int +xbow_reset_link(devfs_handle_t xconn_vhdl) +{ + xwidget_info_t widget_info; + xwidgetnum_t port; + xbow_t *xbow; + xbowreg_t ctrl; + xbwX_stat_t stat; + unsigned itick; + unsigned dtick; + static int ticks_per_ms = 0; + + if (!ticks_per_ms) { + itick = get_timestamp(); + us_delay(1000); + ticks_per_ms = get_timestamp() - itick; + } + widget_info = xwidget_info_get(xconn_vhdl); + port = xwidget_info_id_get(widget_info); + +#ifdef XBOW_K1PTR /* defined if we only have one xbow ... */ + xbow = XBOW_K1PTR; +#else + { + devfs_handle_t xbow_vhdl; + xbow_soft_t xbow_soft; + + hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl); + xbow_soft = xbow_soft_get(xbow_vhdl); + xbow = xbow_soft->base; + } +#endif + + /* + * This requires three PIOs (reset the link, check for the + * reset, restore the control register for the link) plus + * 10us to wait for the reset. We allow up to 1ms for the + * widget to come out of reset before giving up and + * returning a failure. + */ + ctrl = xbow->xb_link(port).link_control; + xbow->xb_link(port).link_reset = 0; + itick = get_timestamp(); + while (1) { + stat.linkstatus = xbow->xb_link(port).link_status; + if (stat.link_alive) + break; + dtick = get_timestamp() - itick; + if (dtick > ticks_per_ms) { + return -1; /* never came out of reset */ + } + DELAY(2); /* don't beat on link_status */ + } + xbow->xb_link(port).link_control = ctrl; + return 0; +} + +/* + * Dump xbow registers. + * input parameter is either a pointer to + * the xbow chip or the vertex handle for + * an xbow vertex. + */ +void +idbg_xbowregs(int64_t regs) +{ + xbow_t *xbow; + int i; + xb_linkregs_t *link; + + xbow = (xbow_t *) regs; + +#ifdef LATER + qprintf("Printing xbow registers starting at 0x%x\n", xbow); + qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %x\n", + xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper, + xbow->xb_wid_err_lower, xbow->xb_wid_control, + xbow->xb_wid_req_timeout); + qprintf("intr uppr %x lower %x errcmd %x llp ctrl %x arb_reload %x\n", + xbow->xb_wid_int_upper, xbow->xb_wid_int_lower, + xbow->xb_wid_err_cmdword, xbow->xb_wid_llp, + xbow->xb_wid_arb_reload); +#endif + + for (i = 8; i <= 0xf; i++) { + link = &xbow->xb_link(i); +#ifdef LATER + qprintf("Link %d registers\n", i); + qprintf("\tctrl %x stat %x arbuppr %x arblowr %x auxstat %x\n", + link->link_control, link->link_status, + link->link_arb_upper, link->link_arb_lower, + link->link_aux_status); +#endif + } +} + + +#define XBOW_ARB_RELOAD_TICKS 25 + /* granularity: 4 MB/s, max: 124 MB/s */ +#define GRANULARITY ((100 * 1000000) / XBOW_ARB_RELOAD_TICKS) + +#define XBOW_BYTES_TO_GBR(BYTES_per_s) (int) (BYTES_per_s / GRANULARITY) + +#define XBOW_GBR_TO_BYTES(cnt) (bandwidth_t) ((cnt) * GRANULARITY) + +#define CEILING_BYTES_TO_GBR(gbr, bytes_per_sec) \ + ((XBOW_GBR_TO_BYTES(gbr) < bytes_per_sec) ? gbr+1 : gbr) + +#define XBOW_ARB_GBR_MAX 31 + +#define ABS(x) ((x > 0) ? (x) : (-1 * x)) + /* absolute value */ + +int +xbow_bytes_to_gbr(bandwidth_t old_bytes_per_sec, bandwidth_t bytes_per_sec) +{ + int gbr_granted; + int new_total_gbr; + int change_gbr; + bandwidth_t new_total_bw; + +#ifdef GRIO_DEBUG + printk("xbow_bytes_to_gbr: old_bytes_per_sec %lld bytes_per_sec %lld\n", + old_bytes_per_sec, bytes_per_sec); +#endif /* GRIO_DEBUG */ + + gbr_granted = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(old_bytes_per_sec)), + old_bytes_per_sec); + new_total_bw = old_bytes_per_sec + bytes_per_sec; + new_total_gbr = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(new_total_bw)), + new_total_bw); + + change_gbr = new_total_gbr - gbr_granted; + +#ifdef GRIO_DEBUG + printk("xbow_bytes_to_gbr: gbr_granted %d new_total_gbr %d change_gbr %d\n", + gbr_granted, new_total_gbr, change_gbr); +#endif /* GRIO_DEBUG */ + + return (change_gbr); +} + +/* Conversion from GBR to bytes */ +bandwidth_t +xbow_gbr_to_bytes(int gbr) +{ + return (XBOW_GBR_TO_BYTES(gbr)); +} + +/* Given the vhdl for the desired xbow, the src and dest. widget ids + * and the req_bw value, this xbow driver entry point accesses the + * xbow registers and allocates the desired bandwidth if available. + * + * If bandwidth allocation is successful, return success else return failure. + */ +int +xbow_prio_bw_alloc(devfs_handle_t vhdl, + xwidgetnum_t src_wid, + xwidgetnum_t dest_wid, + unsigned long long old_alloc_bw, + unsigned long long req_bw) +{ + xbow_soft_t soft = xbow_soft_get(vhdl); + volatile xbowreg_t *xreg; + xbowreg_t mask; + unsigned long s; + int error = 0; + bandwidth_t old_bw_BYTES, req_bw_BYTES; + xbowreg_t old_xreg; + int old_bw_GBR, req_bw_GBR, new_bw_GBR; + +#ifdef GRIO_DEBUG + printk("xbow_prio_bw_alloc: vhdl %d src_wid %d dest_wid %d req_bw %lld\n", + (int) vhdl, (int) src_wid, (int) dest_wid, req_bw); +#endif + + ASSERT(XBOW_WIDGET_IS_VALID(src_wid)); + ASSERT(XBOW_WIDGET_IS_VALID(dest_wid)); + + s = mutex_spinlock(&soft->xbow_bw_alloc_lock); + + /* Get pointer to the correct register */ + xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid); + + /* Get mask for GBR count value */ + mask = XB_ARB_GBR_MSK << XB_ARB_GBR_SHFT(src_wid); + + req_bw_GBR = xbow_bytes_to_gbr(old_alloc_bw, req_bw); + req_bw_BYTES = (req_bw_GBR < 0) ? (-1 * xbow_gbr_to_bytes(ABS(req_bw_GBR))) + : xbow_gbr_to_bytes(req_bw_GBR); + +#ifdef GRIO_DEBUG + printk("req_bw %lld req_bw_BYTES %lld req_bw_GBR %d\n", + req_bw, req_bw_BYTES, req_bw_GBR); +#endif /* GRIO_DEBUG */ + + old_bw_BYTES = soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS]; + old_xreg = *xreg; + old_bw_GBR = (((*xreg) & mask) >> XB_ARB_GBR_SHFT(src_wid)); + +#ifdef GRIO_DEBUG + ASSERT(XBOW_BYTES_TO_GBR(old_bw_BYTES) == old_bw_GBR); + + printk("old_bw_BYTES %lld old_bw_GBR %d\n", old_bw_BYTES, old_bw_GBR); + + printk("req_bw_BYTES %lld old_bw_BYTES %lld soft->bw_hiwm %lld\n", + req_bw_BYTES, old_bw_BYTES, + soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]); + +#endif /* GRIO_DEBUG */ + + /* Accept the request only if we don't exceed the destination + * port HIWATER_MARK *AND* the max. link GBR arbitration count + */ + if (((old_bw_BYTES + req_bw_BYTES) <= + soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]) && + (req_bw_GBR + old_bw_GBR <= XBOW_ARB_GBR_MAX)) { + + new_bw_GBR = (old_bw_GBR + req_bw_GBR); + + /* Set this in the xbow link register */ + *xreg = (old_xreg & ~mask) | \ + (new_bw_GBR << XB_ARB_GBR_SHFT(src_wid) & mask); + + soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS] = + xbow_gbr_to_bytes(new_bw_GBR); + } else { + error = 1; + } + + mutex_spinunlock(&soft->xbow_bw_alloc_lock, s); + + return (error); +} diff -Nru a/arch/ia64/sn/io/sn2/xtalk.c b/arch/ia64/sn/io/sn2/xtalk.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/xtalk.c Mon Feb 24 05:35:59 2003 @@ -0,0 +1,1087 @@ +/* $Id$ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Implement crosstalk provider operations. The xtalk* layer provides a + * platform-independent interface for crosstalk devices. This layer + * switches among the possible implementations of a crosstalk adapter. + * + * On platforms with only one possible xtalk provider, macros can be + * set up at the top that cause the table lookups and indirections to + * completely disappear. + */ + +#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DEL(ptr) (kfree(ptr)) + +char widget_info_fingerprint[] = "widget_info"; + +cdl_p xtalk_registry = NULL; + +#define DEV_FUNC(dev,func) hub_##func +#define CAST_PIOMAP(x) ((hub_piomap_t)(x)) +#define CAST_DMAMAP(x) ((hub_dmamap_t)(x)) +#define CAST_INTR(x) ((hub_intr_t)(x)) + +/* ===================================================================== + * Function Table of Contents + */ +xtalk_piomap_t xtalk_piomap_alloc(devfs_handle_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned); +void xtalk_piomap_free(xtalk_piomap_t); +caddr_t xtalk_piomap_addr(xtalk_piomap_t, iopaddr_t, size_t); +void xtalk_piomap_done(xtalk_piomap_t); +caddr_t xtalk_piotrans_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, unsigned); +caddr_t xtalk_pio_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned); +void xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *); +caddr_t xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned); +static caddr_t null_xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned); +xtalk_dmamap_t xtalk_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned); +void xtalk_dmamap_free(xtalk_dmamap_t); +iopaddr_t xtalk_dmamap_addr(xtalk_dmamap_t, paddr_t, size_t); +alenlist_t xtalk_dmamap_list(xtalk_dmamap_t, alenlist_t, unsigned); +void xtalk_dmamap_done(xtalk_dmamap_t); +iopaddr_t xtalk_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); +alenlist_t xtalk_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +void xtalk_dmamap_drain(xtalk_dmamap_t); +void xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t); +void xtalk_dmalist_drain(devfs_handle_t, alenlist_t); +xtalk_intr_t xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t); +xtalk_intr_t xtalk_intr_alloc_nothd(devfs_handle_t, device_desc_t, devfs_handle_t); +void xtalk_intr_free(xtalk_intr_t); +int xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *); +void xtalk_intr_disconnect(xtalk_intr_t); +devfs_handle_t xtalk_intr_cpu_get(xtalk_intr_t); +int xtalk_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *); +int xtalk_error_devenable(devfs_handle_t, int, int); +void xtalk_provider_startup(devfs_handle_t); +void xtalk_provider_shutdown(devfs_handle_t); +devfs_handle_t xtalk_intr_dev_get(xtalk_intr_t); +xwidgetnum_t xtalk_intr_target_get(xtalk_intr_t); +xtalk_intr_vector_t xtalk_intr_vector_get(xtalk_intr_t); +iopaddr_t xtalk_intr_addr_get(struct xtalk_intr_s *); +void *xtalk_intr_sfarg_get(xtalk_intr_t); +devfs_handle_t xtalk_pio_dev_get(xtalk_piomap_t); +xwidgetnum_t xtalk_pio_target_get(xtalk_piomap_t); +iopaddr_t xtalk_pio_xtalk_addr_get(xtalk_piomap_t); +ulong xtalk_pio_mapsz_get(xtalk_piomap_t); +caddr_t xtalk_pio_kvaddr_get(xtalk_piomap_t); +devfs_handle_t xtalk_dma_dev_get(xtalk_dmamap_t); +xwidgetnum_t xtalk_dma_target_get(xtalk_dmamap_t); +xwidget_info_t xwidget_info_chk(devfs_handle_t); +xwidget_info_t xwidget_info_get(devfs_handle_t); +void xwidget_info_set(devfs_handle_t, xwidget_info_t); +devfs_handle_t xwidget_info_dev_get(xwidget_info_t); +xwidgetnum_t xwidget_info_id_get(xwidget_info_t); +devfs_handle_t xwidget_info_master_get(xwidget_info_t); +xwidgetnum_t xwidget_info_masterid_get(xwidget_info_t); +xwidget_part_num_t xwidget_info_part_num_get(xwidget_info_t); +xwidget_mfg_num_t xwidget_info_mfg_num_get(xwidget_info_t); +char *xwidget_info_name_get(xwidget_info_t); +void xtalk_init(void); +void xtalk_provider_register(devfs_handle_t, xtalk_provider_t *); +void xtalk_provider_unregister(devfs_handle_t); +xtalk_provider_t *xtalk_provider_fns_get(devfs_handle_t); +int xwidget_driver_register(xwidget_part_num_t, + xwidget_mfg_num_t, + char *, unsigned); +void xwidget_driver_unregister(char *); +int xwidget_register(xwidget_hwid_t, devfs_handle_t, + xwidgetnum_t, devfs_handle_t, + xwidgetnum_t, async_attach_t); +int xwidget_unregister(devfs_handle_t); +void xwidget_reset(devfs_handle_t); +char *xwidget_name_get(devfs_handle_t); +#if !defined(DEV_FUNC) +/* + * There is more than one possible provider + * for this platform. We need to examine the + * master vertex of the current vertex for + * a provider function structure, and indirect + * through the appropriately named member. + */ +#define DEV_FUNC(dev,func) xwidget_to_provider_fns(dev)->func +#define CAST_PIOMAP(x) ((xtalk_piomap_t)(x)) +#define CAST_DMAMAP(x) ((xtalk_dmamap_t)(x)) +#define CAST_INTR(x) ((xtalk_intr_t)(x)) + +static xtalk_provider_t * +xwidget_to_provider_fns(devfs_handle_t xconn) +{ + xwidget_info_t widget_info; + xtalk_provider_t *provider_fns; + + widget_info = xwidget_info_get(xconn); + ASSERT(widget_info != NULL); + + provider_fns = xwidget_info_pops_get(widget_info); + ASSERT(provider_fns != NULL); + + return (provider_fns); +} +#endif + +/* + * Many functions are not passed their vertex + * information directly; rather, they must + * dive through a resource map. These macros + * are available to coordinate this detail. + */ +#define PIOMAP_FUNC(map,func) DEV_FUNC(map->xp_dev,func) +#define DMAMAP_FUNC(map,func) DEV_FUNC(map->xd_dev,func) +#define INTR_FUNC(intr,func) DEV_FUNC(intr_hdl->xi_dev,func) + +/* ===================================================================== + * PIO MANAGEMENT + * + * For mapping system virtual address space to + * xtalk space on a specified widget + */ + +xtalk_piomap_t +xtalk_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t xtalk_addr, /* map for this xtalk_addr range */ + size_t byte_count, + size_t byte_count_max, /* maximum size of a mapping */ + unsigned flags) +{ /* defined in sys/pio.h */ + return (xtalk_piomap_t) DEV_FUNC(dev, piomap_alloc) + (dev, dev_desc, xtalk_addr, byte_count, byte_count_max, flags); +} + + +void +xtalk_piomap_free(xtalk_piomap_t xtalk_piomap) +{ + PIOMAP_FUNC(xtalk_piomap, piomap_free) + (CAST_PIOMAP(xtalk_piomap)); +} + + +caddr_t +xtalk_piomap_addr(xtalk_piomap_t xtalk_piomap, /* mapping resources */ + iopaddr_t xtalk_addr, /* map for this xtalk address */ + size_t byte_count) +{ /* map this many bytes */ + return PIOMAP_FUNC(xtalk_piomap, piomap_addr) + (CAST_PIOMAP(xtalk_piomap), xtalk_addr, byte_count); +} + + +void +xtalk_piomap_done(xtalk_piomap_t xtalk_piomap) +{ + PIOMAP_FUNC(xtalk_piomap, piomap_done) + (CAST_PIOMAP(xtalk_piomap)); +} + + +caddr_t +xtalk_piotrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t xtalk_addr, /* Crosstalk address */ + size_t byte_count, /* map this many bytes */ + unsigned flags) +{ /* (currently unused) */ + return DEV_FUNC(dev, piotrans_addr) + (dev, dev_desc, xtalk_addr, byte_count, flags); +} + +caddr_t +xtalk_pio_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t addr, /* starting address (or offset in window) */ + size_t byte_count, /* map this many bytes */ + xtalk_piomap_t *mapp, /* where to return the map pointer */ + unsigned flags) +{ /* PIO flags */ + xtalk_piomap_t map = 0; + caddr_t res; + + if (mapp) + *mapp = 0; /* record "no map used" */ + + res = xtalk_piotrans_addr + (dev, dev_desc, addr, byte_count, flags); + if (res) + return res; /* xtalk_piotrans worked */ + + map = xtalk_piomap_alloc + (dev, dev_desc, addr, byte_count, byte_count, flags); + if (!map) + return res; /* xtalk_piomap_alloc failed */ + + res = xtalk_piomap_addr + (map, addr, byte_count); + if (!res) { + xtalk_piomap_free(map); + return res; /* xtalk_piomap_addr failed */ + } + if (mapp) + *mapp = map; /* pass back map used */ + + return res; /* xtalk_piomap_addr succeeded */ +} + +/* ===================================================================== + * EARLY PIOTRANS SUPPORT + * + * There are places where drivers (mgras, for instance) + * need to get PIO translations before the infrastructure + * is extended to them (setting up textports, for + * instance). These drivers should call + * xtalk_early_piotrans_addr with their xtalk ID + * information, a sequence number (so we can use the second + * mgras for instance), and the usual piotrans parameters. + * + * Machine specific code should provide an implementation + * of early_piotrans_addr, and present a pointer to this + * function to xtalk_set_early_piotrans_addr so it can be + * used by clients without the clients having to know what + * platform or what xtalk provider is in use. + */ + +static xtalk_early_piotrans_addr_f null_xtalk_early_piotrans_addr; + +xtalk_early_piotrans_addr_f *impl_early_piotrans_addr = null_xtalk_early_piotrans_addr; + +/* xtalk_set_early_piotrans_addr: + * specify the early_piotrans_addr implementation function. + */ +void +xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *impl) +{ + impl_early_piotrans_addr = impl; +} + +/* xtalk_early_piotrans_addr: + * figure out a PIO address for the "nth" crosstalk widget that + * matches the specified part and mfgr number. Returns NULL if + * there is no such widget, or if the requested mapping can not + * be constructed. + * Limitations on which crosstalk slots (and busses) are + * checked, and definitions of the ordering of the search across + * the crosstalk slots, are defined by the platform. + */ +caddr_t +xtalk_early_piotrans_addr(xwidget_part_num_t part_num, + xwidget_mfg_num_t mfg_num, + int which, + iopaddr_t xtalk_addr, + size_t byte_count, + unsigned flags) +{ + return impl_early_piotrans_addr + (part_num, mfg_num, which, xtalk_addr, byte_count, flags); +} + +/* null_xtalk_early_piotrans_addr: + * used as the early_piotrans_addr implementation until and + * unless a real implementation is provided. In DEBUG kernels, + * we want to know who is calling before the implementation is + * registered; in non-DEBUG kernels, return NULL representing + * lack of mapping support. + */ +/*ARGSUSED */ +static caddr_t +null_xtalk_early_piotrans_addr(xwidget_part_num_t part_num, + xwidget_mfg_num_t mfg_num, + int which, + iopaddr_t xtalk_addr, + size_t byte_count, + unsigned flags) +{ +#if DEBUG + PRINT_PANIC("null_xtalk_early_piotrans_addr"); +#endif + return NULL; +} + +/* ===================================================================== + * DMA MANAGEMENT + * + * For mapping from crosstalk space to system + * physical space. + */ + +xtalk_dmamap_t +xtalk_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */ + device_desc_t dev_desc, /* device descriptor */ + size_t byte_count_max, /* max size of a mapping */ + unsigned flags) +{ /* defined in dma.h */ + return (xtalk_dmamap_t) DEV_FUNC(dev, dmamap_alloc) + (dev, dev_desc, byte_count_max, flags); +} + + +void +xtalk_dmamap_free(xtalk_dmamap_t xtalk_dmamap) +{ + DMAMAP_FUNC(xtalk_dmamap, dmamap_free) + (CAST_DMAMAP(xtalk_dmamap)); +} + + +iopaddr_t +xtalk_dmamap_addr(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */ + paddr_t paddr, /* map for this address */ + size_t byte_count) +{ /* map this many bytes */ + return DMAMAP_FUNC(xtalk_dmamap, dmamap_addr) + (CAST_DMAMAP(xtalk_dmamap), paddr, byte_count); +} + + +alenlist_t +xtalk_dmamap_list(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */ + alenlist_t alenlist, /* map this Address/Length List */ + unsigned flags) +{ + return DMAMAP_FUNC(xtalk_dmamap, dmamap_list) + (CAST_DMAMAP(xtalk_dmamap), alenlist, flags); +} + + +void +xtalk_dmamap_done(xtalk_dmamap_t xtalk_dmamap) +{ + DMAMAP_FUNC(xtalk_dmamap, dmamap_done) + (CAST_DMAMAP(xtalk_dmamap)); +} + + +iopaddr_t +xtalk_dmatrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_addr) + (dev, dev_desc, paddr, byte_count, flags); +} + + +alenlist_t +xtalk_dmatrans_list(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + alenlist_t palenlist, /* system address/length list */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_list) + (dev, dev_desc, palenlist, flags); +} + +void +xtalk_dmamap_drain(xtalk_dmamap_t map) +{ + DMAMAP_FUNC(map, dmamap_drain) + (CAST_DMAMAP(map)); +} + +void +xtalk_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size) +{ + DEV_FUNC(dev, dmaaddr_drain) + (dev, addr, size); +} + +void +xtalk_dmalist_drain(devfs_handle_t dev, alenlist_t list) +{ + DEV_FUNC(dev, dmalist_drain) + (dev, list); +} + +/* ===================================================================== + * INTERRUPT MANAGEMENT + * + * Allow crosstalk devices to establish interrupts + */ + +/* + * Allocate resources required for an interrupt as specified in intr_desc. + * Return resource handle in intr_hdl. + */ +xtalk_intr_t +xtalk_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */ + device_desc_t dev_desc, /* device descriptor */ + devfs_handle_t owner_dev) +{ /* owner of this interrupt */ + return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc) + (dev, dev_desc, owner_dev); +} + +/* + * Allocate resources required for an interrupt as specified in dev_desc. + * Unconditionally setup resources to be non-threaded. + * Return resource handle in intr_hdl. + */ +xtalk_intr_t +xtalk_intr_alloc_nothd(devfs_handle_t dev, /* which Crosstalk device */ + device_desc_t dev_desc, /* device descriptor */ + devfs_handle_t owner_dev) /* owner of this interrupt */ +{ + return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc_nothd) + (dev, dev_desc, owner_dev); +} + +/* + * Free resources consumed by intr_alloc. + */ +void +xtalk_intr_free(xtalk_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_free) + (CAST_INTR(intr_hdl)); +} + + +/* + * Associate resources allocated with a previous xtalk_intr_alloc call with the + * described handler, arg, name, etc. + * + * Returns 0 on success, returns <0 on failure. + */ +int +xtalk_intr_connect(xtalk_intr_t intr_hdl, /* xtalk intr resource handle */ + intr_func_t intr_func, /* xtalk intr handler */ + intr_arg_t intr_arg, /* arg to intr handler */ + xtalk_intr_setfunc_t setfunc, /* func to set intr hw */ + void *setfunc_arg) /* arg to setfunc */ +{ + return INTR_FUNC(intr_hdl, intr_connect) + (CAST_INTR(intr_hdl), intr_func, intr_arg, setfunc, setfunc_arg); +} + + +/* + * Disassociate handler with the specified interrupt. + */ +void +xtalk_intr_disconnect(xtalk_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_disconnect) + (CAST_INTR(intr_hdl)); +} + + +/* + * Return a hwgraph vertex that represents the CPU currently + * targeted by an interrupt. + */ +devfs_handle_t +xtalk_intr_cpu_get(xtalk_intr_t intr_hdl) +{ + return INTR_FUNC(intr_hdl, intr_cpu_get) + (CAST_INTR(intr_hdl)); +} + + +/* + * ===================================================================== + * ERROR MANAGEMENT + */ + +/* + * xtalk_error_handler: + * pass this error on to the handler registered + * at the specified xtalk connecdtion point, + * or complain about it here if there is no handler. + * + * This routine plays two roles during error delivery + * to most widgets: first, the external agent (heart, + * hub, or whatever) calls in with the error and the + * connect point representing the crosstalk switch, + * or whatever crosstalk device is directly connected + * to the agent. + * + * If there is a switch, it will generally look at the + * widget number stashed in the ioerror structure; and, + * if the error came from some widget other than the + * switch, it will call back into xtalk_error_handler + * with the connection point of the offending port. + */ +int +xtalk_error_handler( + devfs_handle_t xconn, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + xwidget_info_t xwidget_info; + + xwidget_info = xwidget_info_get(xconn); + /* Make sure that xwidget_info is a valid pointer before derefencing it. + * We could come in here during very early initialization. + */ + if (xwidget_info && xwidget_info->w_efunc) + return xwidget_info->w_efunc + (xwidget_info->w_einfo, + error_code, mode, ioerror); + /* + * no error handler registered for + * the offending port. it's not clear + * what needs to be done, but reporting + * it would be a good thing, unless it + * is a mode that requires nothing. + */ + if ((mode == MODE_DEVPROBE) || (mode == MODE_DEVUSERERROR) || + (mode == MODE_DEVREENABLE)) + return IOERROR_HANDLED; + +#if defined(SUPPORT_PRINTING_V_FORMAT) + printk(KERN_WARNING "Xbow at %v encountered Fatal error", xconn); +#else + printk(KERN_WARNING "Xbow at 0x%p encountered Fatal error", xconn); +#endif + ioerror_dump("xtalk", error_code, mode, ioerror); + + return IOERROR_UNHANDLED; +} + +int +xtalk_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code) +{ + return DEV_FUNC(xconn_vhdl, error_devenable) (xconn_vhdl, devnum, error_code); +} + + +/* ===================================================================== + * CONFIGURATION MANAGEMENT + */ + +/* + * Startup a crosstalk provider + */ +void +xtalk_provider_startup(devfs_handle_t xtalk_provider) +{ + DEV_FUNC(xtalk_provider, provider_startup) + (xtalk_provider); +} + + +/* + * Shutdown a crosstalk provider + */ +void +xtalk_provider_shutdown(devfs_handle_t xtalk_provider) +{ + DEV_FUNC(xtalk_provider, provider_shutdown) + (xtalk_provider); +} + +/* + * Enable a device on a xtalk widget + */ +void +xtalk_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum) +{ + DEV_FUNC(xconn_vhdl, widgetdev_enable) (xconn_vhdl, devnum); +} + +/* + * Shutdown a device on a xtalk widget + */ +void +xtalk_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum) +{ + DEV_FUNC(xconn_vhdl, widgetdev_shutdown) (xconn_vhdl, devnum); +} + +int +xtalk_dma_enabled(devfs_handle_t xconn_vhdl) +{ + return DEV_FUNC(xconn_vhdl, dma_enabled) (xconn_vhdl); +} +/* + * Generic crosstalk functions, for use with all crosstalk providers + * and all crosstalk devices. + */ + +/****** Generic crosstalk interrupt interfaces ******/ +devfs_handle_t +xtalk_intr_dev_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_dev); +} + +xwidgetnum_t +xtalk_intr_target_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_target); +} + +xtalk_intr_vector_t +xtalk_intr_vector_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_vector); +} + +iopaddr_t +xtalk_intr_addr_get(struct xtalk_intr_s *xtalk_intr) +{ + return (xtalk_intr->xi_addr); +} + +void * +xtalk_intr_sfarg_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_sfarg); +} + +/****** Generic crosstalk pio interfaces ******/ +devfs_handle_t +xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_dev); +} + +xwidgetnum_t +xtalk_pio_target_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_target); +} + +iopaddr_t +xtalk_pio_xtalk_addr_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_xtalk_addr); +} + +ulong +xtalk_pio_mapsz_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_mapsz); +} + +caddr_t +xtalk_pio_kvaddr_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_kvaddr); +} + + +/****** Generic crosstalk dma interfaces ******/ +devfs_handle_t +xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap) +{ + return (xtalk_dmamap->xd_dev); +} + +xwidgetnum_t +xtalk_dma_target_get(xtalk_dmamap_t xtalk_dmamap) +{ + return (xtalk_dmamap->xd_target); +} + + +/****** Generic crosstalk widget information interfaces ******/ + +/* xwidget_info_chk: + * check to see if this vertex is a widget; + * if so, return its widget_info (if any). + * if not, return NULL. + */ +xwidget_info_t +xwidget_info_chk(devfs_handle_t xwidget) +{ + arbitrary_info_t ainfo = 0; + + hwgraph_info_get_LBL(xwidget, INFO_LBL_XWIDGET, &ainfo); + return (xwidget_info_t) ainfo; +} + + +xwidget_info_t +xwidget_info_get(devfs_handle_t xwidget) +{ + xwidget_info_t widget_info; + + widget_info = (xwidget_info_t) + hwgraph_fastinfo_get(xwidget); + +#ifdef LATER + if ((widget_info != NULL) && + (widget_info->w_fingerprint != widget_info_fingerprint)) +#ifdef SUPPORT_PRINTING_V_FORMAT + PRINT_PANIC("%v bad xwidget_info", xwidget); +#else + PRINT_PANIC("%x bad xwidget_info", xwidget); +#endif +#endif /* LATER */ + + return (widget_info); +} + +void +xwidget_info_set(devfs_handle_t xwidget, xwidget_info_t widget_info) +{ + if (widget_info != NULL) + widget_info->w_fingerprint = widget_info_fingerprint; + + hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) widget_info); + + /* Also, mark this vertex as an xwidget, + * and use the widget_info, so xwidget_info_chk + * can work (and be fairly efficient). + */ + hwgraph_info_add_LBL(xwidget, INFO_LBL_XWIDGET, + (arbitrary_info_t) widget_info); +} + +devfs_handle_t +xwidget_info_dev_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_vertex); +} + +xwidgetnum_t +xwidget_info_id_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_id); +} + + +devfs_handle_t +xwidget_info_master_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_master); +} + +xwidgetnum_t +xwidget_info_masterid_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_masterid); +} + +xwidget_part_num_t +xwidget_info_part_num_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_hwid.part_num); +} + +xwidget_mfg_num_t +xwidget_info_mfg_num_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_hwid.mfg_num); +} +/* Extract the widget name from the widget information + * for the xtalk widget. + */ +char * +xwidget_info_name_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget info"); + return(xwidget_info->w_name); +} +/****** Generic crosstalk initialization interfaces ******/ + +/* + * One-time initialization needed for systems that support crosstalk. + */ +void +xtalk_init(void) +{ + cdl_p cp; + +#if DEBUG && ATTACH_DEBUG + printf("xtalk_init\n"); +#endif + /* Allocate the registry. + * We might already have one. + * If we don't, go get one. + * MPness: someone might have + * set one up for us while we + * were not looking; use an atomic + * compare-and-swap to commit to + * using the new registry if and + * only if nobody else did first. + * If someone did get there first, + * toss the one we allocated back + * into the pool. + */ + if (xtalk_registry == NULL) { + cp = cdl_new(EDGE_LBL_XIO, "part", "mfgr"); + if (!compare_and_swap_ptr((void **) &xtalk_registry, NULL, (void *) cp)) { + cdl_del(cp); + } + } + ASSERT(xtalk_registry != NULL); +} + +/* + * Associate a set of xtalk_provider functions with a vertex. + */ +void +xtalk_provider_register(devfs_handle_t provider, xtalk_provider_t *xtalk_fns) +{ + hwgraph_fastinfo_set(provider, (arbitrary_info_t) xtalk_fns); +} + +/* + * Disassociate a set of xtalk_provider functions with a vertex. + */ +void +xtalk_provider_unregister(devfs_handle_t provider) +{ + hwgraph_fastinfo_set(provider, (arbitrary_info_t)NULL); +} + +/* + * Obtain a pointer to the xtalk_provider functions for a specified Crosstalk + * provider. + */ +xtalk_provider_t * +xtalk_provider_fns_get(devfs_handle_t provider) +{ + return ((xtalk_provider_t *) hwgraph_fastinfo_get(provider)); +} + +/* + * Announce a driver for a particular crosstalk part. + * Returns 0 on success or -1 on failure. Failure occurs if the + * specified hardware already has a driver. + */ +/*ARGSUSED4 */ +int +xwidget_driver_register(xwidget_part_num_t part_num, + xwidget_mfg_num_t mfg_num, + char *driver_prefix, + unsigned flags) +{ + /* a driver's init routine could call + * xwidget_driver_register before the + * system calls xtalk_init; so, we + * make the call here. + */ + if (xtalk_registry == NULL) + xtalk_init(); + + return cdl_add_driver(xtalk_registry, + part_num, mfg_num, + driver_prefix, flags, NULL); +} + +/* + * Inform xtalk infrastructure that a driver is no longer available for + * handling any widgets. + */ +void +xwidget_driver_unregister(char *driver_prefix) +{ + /* before a driver calls unregister, + * it must have called registger; so we + * can assume we have a registry here. + */ + ASSERT(xtalk_registry != NULL); + + cdl_del_driver(xtalk_registry, driver_prefix, NULL); +} + +/* + * Call some function with each vertex that + * might be one of this driver's attach points. + */ +void +xtalk_iterate(char *driver_prefix, + xtalk_iter_f *func) +{ + ASSERT(xtalk_registry != NULL); + + cdl_iterate(xtalk_registry, driver_prefix, (cdl_iter_f *)func); +} + +/* + * xwidget_register: + * Register a xtalk device (xwidget) by doing the following. + * -allocate and initialize xwidget_info data + * -allocate a hwgraph vertex with name based on widget number (id) + * -look up the widget's initialization function and call it, + * or remember the vertex for later initialization. + * + */ +int +xwidget_register(xwidget_hwid_t hwid, /* widget's hardware ID */ + devfs_handle_t widget, /* widget to initialize */ + xwidgetnum_t id, /* widget's target id (0..f) */ + devfs_handle_t master, /* widget's master vertex */ + xwidgetnum_t targetid, /* master's target id (9/a) */ + async_attach_t aa) +{ + xwidget_info_t widget_info; + char *s,devnm[MAXDEVNAME]; + + /* Allocate widget_info and associate it with widget vertex */ + NEW(widget_info); + + /* Initialize widget_info */ + widget_info->w_vertex = widget; + widget_info->w_id = id; + widget_info->w_master = master; + widget_info->w_masterid = targetid; + widget_info->w_hwid = *hwid; /* structure copy */ + widget_info->w_efunc = 0; + widget_info->w_einfo = 0; + /* + * get the name of this xwidget vertex and keep the info. + * This is needed during errors and interupts, but as + * long as we have it, we can use it elsewhere. + */ + s = dev_to_name(widget,devnm,MAXDEVNAME); + widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL); + strcpy(widget_info->w_name,s); + + xwidget_info_set(widget, widget_info); + + device_master_set(widget, master); + + /* All the driver init routines (including + * xtalk_init) are called before we get into + * attaching devices, so we can assume we + * have a registry here. + */ + ASSERT(xtalk_registry != NULL); + + /* + * Add pointer to async attach info -- tear down will be done when + * the particular descendant is done with the info. + */ + if (aa) + async_attach_add_info(widget, aa); + + return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num, + widget, 0); +} + +/* + * xwidget_unregister : + * Unregister the xtalk device and detach all its hwgraph namespace. + */ +int +xwidget_unregister(devfs_handle_t widget) +{ + xwidget_info_t widget_info; + xwidget_hwid_t hwid; + + /* Make sure that we have valid widget information initialized */ + if (!(widget_info = xwidget_info_get(widget))) + return(1); + + /* Remove the inventory information associated + * with the widget. + */ + hwgraph_inventory_remove(widget, -1, -1, -1, -1, -1); + + hwid = &(widget_info->w_hwid); + + cdl_del_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num, + widget, 0); + + /* Clean out the xwidget information */ + (void)kfree(widget_info->w_name); + BZERO((void *)widget_info, sizeof(widget_info)); + DEL(widget_info); + + return(0); +} + +void +xwidget_error_register(devfs_handle_t xwidget, + error_handler_f *efunc, + error_handler_arg_t einfo) +{ + xwidget_info_t xwidget_info; + + xwidget_info = xwidget_info_get(xwidget); + ASSERT(xwidget_info != NULL); + xwidget_info->w_efunc = efunc; + xwidget_info->w_einfo = einfo; +} + +/* + * Issue a link reset to a widget. + */ +void +xwidget_reset(devfs_handle_t xwidget) +{ + xswitch_reset_link(xwidget); + +} + + +void +xwidget_gfx_reset(devfs_handle_t xwidget) +{ + xwidget_info_t info; + + xswitch_reset_link(xwidget); + info = xwidget_info_get(xwidget); +#ifdef LATER + ASSERT_ALWAYS(info != NULL); +#endif + + /* + * Enable this for other architectures once we add widget_reset to the + * xtalk provider interface. + */ + DEV_FUNC(xtalk_provider, widget_reset) + (xwidget_info_master_get(info), xwidget_info_id_get(info)); +} + +#define ANON_XWIDGET_NAME "No Name" /* Default Widget Name */ + +/* Get the canonical hwgraph name of xtalk widget */ +char * +xwidget_name_get(devfs_handle_t xwidget_vhdl) +{ + xwidget_info_t info; + + /* If we have a bogus widget handle then return + * a default anonymous widget name. + */ + if (xwidget_vhdl == GRAPH_VERTEX_NONE) + return(ANON_XWIDGET_NAME); + /* Read the widget name stored in the widget info + * for the widget setup during widget initialization. + */ + info = xwidget_info_get(xwidget_vhdl); + ASSERT(info != NULL); + return(xwidget_info_name_get(info)); +} diff -Nru a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/kernel/iomv.c Mon Feb 24 04:47:33 2003 @@ -0,0 +1,115 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include + +extern void * sn_io_addr(unsigned long port); /* defined in sn[12]/iomv.c */ + +/** + * sn_inb - read a byte from a port + * @port: port to read from + * + * Reads a byte from @port and returns it to the caller. + */ +unsigned int +sn_inb (unsigned long port) +{ + volatile unsigned char *addr = sn_io_addr(port); + unsigned char ret; + + ret = *addr; + __ia64_mf_a(); + return ret; +} + +/** + * sn_inw - read a word from a port + * @port: port to read from + * + * Reads a word from @port and returns it to the caller. + */ +unsigned int +sn_inw (unsigned long port) +{ + volatile unsigned short *addr = sn_io_addr(port); + unsigned short ret; + + ret = *addr; + __ia64_mf_a(); + return ret; +} + +/** + * sn_inl - read a word from a port + * @port: port to read from + * + * Reads a word from @port and returns it to the caller. + */ +unsigned int +sn_inl (unsigned long port) +{ + volatile unsigned int *addr = sn_io_addr(port); + unsigned int ret; + + ret = *addr; + __ia64_mf_a(); + return ret; +} + +/** + * sn_outb - write a byte to a port + * @port: port to write to + * @val: value to write + * + * Writes @val to @port. + */ +void +sn_outb (unsigned char val, unsigned long port) +{ + volatile unsigned char *addr = sn_io_addr(port); + + *addr = val; +} + +/** + * sn_outw - write a word to a port + * @port: port to write to + * @val: value to write + * + * Writes @val to @port. + */ +void +sn_outw (unsigned short val, unsigned long port) +{ + volatile unsigned short *addr = sn_io_addr(port); + + *addr = val; +} + +/** + * sn_outl - write a word to a port + * @port: port to write to + * @val: value to write + * + * Writes @val to @port. + */ +void +sn_outl (unsigned int val, unsigned long port) +{ + volatile unsigned int *addr = sn_io_addr(port); + + *addr = val; +} + +EXPORT_SYMBOL(sn_inb); +EXPORT_SYMBOL(sn_inw); +EXPORT_SYMBOL(sn_inl); +EXPORT_SYMBOL(sn_outb); +EXPORT_SYMBOL(sn_outw); +EXPORT_SYMBOL(sn_outl); diff -Nru a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c --- a/arch/ia64/sn/kernel/mca.c Tue Nov 5 06:25:20 2002 +++ b/arch/ia64/sn/kernel/mca.c Mon Feb 24 04:50:23 2003 @@ -40,7 +40,10 @@ #include #include #include +#include +#ifdef CONFIG_KDB #include +#endif #include #include @@ -53,7 +56,6 @@ #include #include -#include #include #include diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c --- a/arch/ia64/sn/kernel/setup.c Tue Feb 25 02:08:11 2003 +++ b/arch/ia64/sn/kernel/setup.c Thu Mar 6 11:40:52 2003 @@ -267,7 +267,7 @@ /* PROM has wrong value on SN1 */ sn_rtc_cycles_per_second = 990177; #endif - sn_rtc_usec_per_cyc = ((1000000UL< + +#define ZEROVAL 0x3f // "zero" value for outstanding PIO requests +#define DEADLOCKBIT SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_SHFT +#define WRITECOUNT SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_SHFT +#define ALIAS_OFFSET (SH_PIO_WRITE_STATUS_0_ALIAS-SH_PIO_WRITE_STATUS_0) + + + .global sn2_ptc_deadlock_recovery_core + .proc sn2_ptc_deadlock_recovery_core + +sn2_ptc_deadlock_recovery_core: + .regstk 5,0,0,0 + + ptc0 = in0 + data0 = in1 + ptc1 = in2 + data1 = in3 + piowc = in4 + piowcphy = r30 + psrsave = r2 + zeroval = r3 + scr1 = r16 + scr2 = r17 + + + extr.u piowcphy=piowc,0,61;; // Convert piowc to uncached physical address + dep piowcphy=-1,piowcphy,63,1 + + mov zeroval=ZEROVAL // "zero" value for PIO write count + +1: + add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register + mov scr1=7;; // Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR + st8.rel [scr2]=scr1;; + +5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete. + extr.u scr2=scr1,WRITECOUNT,7;;// PIO count + cmp.ne p6,p0=zeroval,scr2 +(p6) br.cond.sptk 5b + + + + ////////////// BEGIN PHYSICAL MODE //////////////////// + mov psrsave=psr // Disable IC (no PMIs) + rsm psr.i | psr.dt | psr.ic;; + srlz.i;; + + st8.rel [ptc0]=data0 // Write PTC0 & wait for completion. + +5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. + extr.u scr2=scr1,WRITECOUNT,7;;// PIO count + cmp.ne p6,p0=zeroval,scr2 +(p6) br.cond.sptk 5b;; + + tbit.nz p8,p7=scr1,DEADLOCKBIT;;// Test for DEADLOCK + +(p7) st8.rel [ptc1]=data1;; // Now write PTC1. + +5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. + extr.u scr2=scr1,WRITECOUNT,7;;// PIO count + cmp.ne p6,p0=zeroval,scr2 +(p6) br.cond.sptk 5b + + tbit.nz p8,p0=scr1,DEADLOCKBIT;;// Test for DEADLOCK + + mov psr.l=psrsave;; // Reenable IC + srlz.i;; + ////////////// END PHYSICAL MODE //////////////////// + +(p8) br.cond.spnt 1b;; // Repeat if DEADLOCK occurred. + + br.ret.sptk rp + .endp sn2_ptc_deadlock_recovery_core diff -Nru a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c Mon Feb 24 05:17:16 2003 @@ -0,0 +1,145 @@ +/* + * + * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan + */ +#include + +#ifdef CONFIG_PROC_FS +#include +#include + + +static int partition_id_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + + return sprintf(page, "%d\n", sn_local_partid()); +} + +struct proc_dir_entry * sgi_proc_dir = NULL; + +void +register_sn_partition_id(void) { + struct proc_dir_entry *entry; + + if (!sgi_proc_dir) { + sgi_proc_dir = proc_mkdir("sgi_sn", 0); + } + entry = create_proc_entry("partition_id", 0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = partition_id_read_proc; + entry->write_proc = NULL; + } +} + +static int +system_serial_number_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + return sprintf(page, "%s\n", sn_system_serial_number()); +} + +static int +licenseID_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + return sprintf(page, "0x%lx\n",sn_partition_serial_number_val()); +} + +void +register_sn_serial_numbers(void) { + struct proc_dir_entry *entry; + + if (!sgi_proc_dir) { + sgi_proc_dir = proc_mkdir("sgi_sn", 0); + } + entry = create_proc_entry("system_serial_number", 0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = system_serial_number_read_proc; + entry->write_proc = NULL; + } + entry = create_proc_entry("licenseID", 0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = licenseID_read_proc; + entry->write_proc = NULL; + } +} + +// Disable forced interrupts, but leave the code in, just in case. +int sn_force_interrupt_flag = 0; + +static int +sn_force_interrupt_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + if (sn_force_interrupt_flag) { + return sprintf(page, "Force interrupt is enabled\n"); + } + return sprintf(page, "Force interrupt is disabled\n"); +} + +static int +sn_force_interrupt_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + if (*buffer == '0') { + sn_force_interrupt_flag = 0; + } else { + sn_force_interrupt_flag = 1; + } + return 1; +} + +void +register_sn_force_interrupt(void) { + struct proc_dir_entry *entry; + + if (!sgi_proc_dir) { + sgi_proc_dir = proc_mkdir("sgi_sn", 0); + } + entry = create_proc_entry("sn_force_interrupt",0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = sn_force_interrupt_read_proc; + entry->write_proc = sn_force_interrupt_write_proc; + } +} +void +register_sn_procfs(void) { + register_sn_partition_id(); + register_sn_serial_numbers(); + register_sn_force_interrupt(); +} + +#endif /* CONFIG_PROC_FS */ diff -Nru a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c --- a/arch/ia64/tools/print_offsets.c Wed Jan 29 22:16:51 2003 +++ b/arch/ia64/tools/print_offsets.c Fri Feb 28 15:27:56 2003 @@ -10,7 +10,7 @@ * gets translated into an assembly file which, in turn, is processed * by awk to generate offsets.h. So if you make any changes to this * file, be sure to verify that the awk procedure still works (see - * prin_offsets.awk). + * print_offsets.awk). */ #include @@ -170,6 +170,12 @@ /* for assembly files which can't include sched.h: */ { "IA64_CLONE_VFORK", CLONE_VFORK }, { "IA64_CLONE_VM", CLONE_VM }, + /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */ + { "IA64_CPUINFO_ITM_DELTA_OFFSET", offsetof (struct cpuinfo_ia64, itm_delta) }, + { "IA64_CPUINFO_ITM_NEXT_OFFSET", offsetof (struct cpuinfo_ia64, itm_next) }, + { "IA64_CPUINFO_NSEC_PER_CYC_OFFSET", offsetof (struct cpuinfo_ia64, nsec_per_cyc) }, + { "IA64_TIMESPEC_TV_NSEC_OFFSET", offsetof (struct timespec, tv_nsec) }, + }; static const char *tabs = "\t\t\t\t\t\t\t\t\t\t"; diff -Nru a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S --- a/arch/ia64/vmlinux.lds.S Wed Jan 29 22:16:51 2003 +++ b/arch/ia64/vmlinux.lds.S Fri Feb 14 15:08:44 2003 @@ -133,6 +133,10 @@ *(.initcall7.init) __initcall_end = .; } + __con_initcall_start = .; + .con_initcall.init : AT(ADDR(.con_initcall.init) - PAGE_OFFSET) + { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(PAGE_SIZE); __init_end = .; diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig --- a/arch/m68k/Kconfig Sun Feb 9 17:29:49 2003 +++ b/arch/m68k/Kconfig Sat Mar 8 14:50:37 2003 @@ -10,10 +10,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c --- a/arch/m68k/atari/stram.c Mon Jan 13 17:54:26 2003 +++ b/arch/m68k/atari/stram.c Sat Mar 8 14:50:21 2003 @@ -1052,8 +1052,7 @@ if (!stram_disk) return -ENOMEM; - if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) { - printk(KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR); + if (register_blkdev(STRAM_MAJOR, "stram")) { put_disk(stram_disk); return -ENXIO; } diff -Nru a/arch/m68k/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds --- a/arch/m68k/vmlinux-std.lds Wed Jan 15 09:48:42 2003 +++ b/arch/m68k/vmlinux-std.lds Fri Feb 14 15:09:22 2003 @@ -60,6 +60,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(8192); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds --- a/arch/m68k/vmlinux-sun3.lds Wed Jan 15 09:48:42 2003 +++ b/arch/m68k/vmlinux-sun3.lds Fri Feb 14 15:09:22 2003 @@ -53,6 +53,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(8192); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig --- a/arch/m68knommu/Kconfig Tue Feb 18 02:27:38 2003 +++ b/arch/m68knommu/Kconfig Sat Mar 8 14:50:37 2003 @@ -9,10 +9,6 @@ bool default n -config SWAP - bool - default n - config FPU bool default n diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig --- a/arch/mips/Kconfig Sun Feb 9 17:29:49 2003 +++ b/arch/mips/Kconfig Sat Mar 8 14:50:37 2003 @@ -10,10 +10,6 @@ bool default y -config SWAP - bool - default y - config SMP bool ---help--- diff -Nru a/arch/mips/arc/arc_con.c b/arch/mips/arc/arc_con.c --- a/arch/mips/arc/arc_con.c Tue Feb 5 10:12:45 2002 +++ b/arch/mips/arc/arc_con.c Fri Feb 14 15:09:50 2003 @@ -63,7 +63,8 @@ * Register console. */ -void __init arc_console_init(void) +static void __init arc_console_init(void) { register_console(&arc_cons); } +console_initcall(arc_console_init); diff -Nru a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c --- a/arch/mips/au1000/common/serial.c Mon Feb 24 10:28:52 2003 +++ b/arch/mips/au1000/common/serial.c Thu Mar 6 09:10:40 2003 @@ -3054,10 +3054,11 @@ /* * Register console. */ -void __init au1000_serial_console_init(void) +static void __init au1000_serial_console_init(void) { register_console(&sercons); } +console_initcall(au1000_serial_console_init); #endif /* diff -Nru a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c --- a/arch/mips/baget/irq.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips/baget/irq.c Sat Mar 8 14:50:43 2003 @@ -146,11 +146,13 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < BAGET_IRQ_NR ; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -161,6 +163,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips/dec/irq.c b/arch/mips/dec/irq.c --- a/arch/mips/dec/irq.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips/dec/irq.c Sat Mar 8 14:50:43 2003 @@ -97,11 +97,13 @@ { int i; struct irqaction *action; + unsigned long flags; for (i = 0; i < 32; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -112,6 +114,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c --- a/arch/mips/ite-boards/generic/irq.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips/ite-boards/generic/irq.c Sat Mar 8 14:50:43 2003 @@ -222,6 +222,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_printf(p, " "); for (j=0; jhandler ) - continue; + goto skip; seq_printf(p, "%3d: ", i); seq_printf(p, "%10u ", kstat_irqs(i)); if ( irq_desc[i].handler ) seq_printf(p, " %s ", irq_desc[i].handler->typename ); else seq_puts(p, " None "); + seq_printf(p, " %s",action->name); for (action=action->next; action; action = action->next) { seq_printf(p, ", %s", action->name); } seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "BAD: %10lu\n", spurious_count); return 0; @@ -437,6 +443,7 @@ irq_desc[i].action = 0; irq_desc[i].depth = 1; irq_desc[i].handler = &it8172_irq_type; + spin_lock_init(&irq_desc[i].lock); } /* diff -Nru a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c --- a/arch/mips/kernel/irq.c Tue Feb 25 01:38:35 2003 +++ b/arch/mips/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -73,17 +73,19 @@ int show_interrupts(struct seq_file *p, void *v) { struct irqaction * action; + unsigned long flags; int i; - + seq_puts(p, " "); for (i=0; i < 1 /*smp_num_cpus*/; i++) seq_printf(p, "CPU%d ", i); seq_putc(p, '\n'); for (i = 0 ; i < NR_IRQS ; i++) { + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto unlock; seq_printf(p, "%3d: ",i); seq_printf(p, "%10u ", kstat_irqs(i)); seq_printf(p, " %14s", irq_desc[i].handler->typename); @@ -92,6 +94,8 @@ for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +unlock: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "ERR: %10lu\n", irq_err_count); return 0; diff -Nru a/arch/mips/kernel/old-irq.c b/arch/mips/kernel/old-irq.c --- a/arch/mips/kernel/old-irq.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips/kernel/old-irq.c Sat Mar 8 14:50:43 2003 @@ -128,11 +128,13 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < 32 ; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -143,6 +145,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c --- a/arch/mips/mips-boards/atlas/atlas_int.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips/mips-boards/atlas/atlas_int.c Sat Mar 8 14:50:43 2003 @@ -99,11 +99,13 @@ int i; int num = 0; struct irqaction *action; + unsigned long flags; for (i = 0; i < ATLASINT_END; i++, num++) { + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -114,6 +116,8 @@ action->name); } seq_printf(p, " [hw0]\n"); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } return 0; } @@ -243,6 +247,7 @@ irq_desc[i].action = 0; irq_desc[i].depth = 1; irq_desc[i].handler = &atlas_irq_type; + spin_lock_init(&irq_desc[i].lock); } #ifdef CONFIG_REMOTE_DEBUG diff -Nru a/arch/mips/philips/nino/irq.c b/arch/mips/philips/nino/irq.c --- a/arch/mips/philips/nino/irq.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips/philips/nino/irq.c Sat Mar 8 14:50:43 2003 @@ -119,11 +119,13 @@ { int i; struct irqaction *action; + unsigned long flags; for (i = 0; i < NR_IRQS; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -134,6 +136,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips/vmlinux.lds.S b/arch/mips/vmlinux.lds.S --- a/arch/mips/vmlinux.lds.S Wed Jan 15 09:48:42 2003 +++ b/arch/mips/vmlinux.lds.S Fri Feb 14 15:09:55 2003 @@ -51,6 +51,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); /* Align double page for init_task_union */ __init_end = .; diff -Nru a/arch/mips64/Kconfig b/arch/mips64/Kconfig --- a/arch/mips64/Kconfig Sun Feb 9 17:29:49 2003 +++ b/arch/mips64/Kconfig Sat Mar 8 14:50:37 2003 @@ -9,10 +9,6 @@ bool default y -config SWAP - bool - default y - source "init/Kconfig" diff -Nru a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c --- a/arch/mips64/kernel/linux32.c Tue Feb 18 10:25:13 2003 +++ b/arch/mips64/kernel/linux32.c Thu Mar 6 11:06:44 2003 @@ -729,12 +729,10 @@ return sys_llseek(fd, offset_high, offset_low, result, origin); } -struct iovec32 { unsigned int iov_base; int iov_len; }; - typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); static long -do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, +do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector, u32 count) { unsigned long tot_len; @@ -749,7 +747,7 @@ */ if (!count) return 0; - if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -835,7 +833,7 @@ } asmlinkage long -sys32_readv(int fd, struct iovec32 *vector, u32 count) +sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -855,7 +853,7 @@ } asmlinkage long -sys32_writev(int fd, struct iovec32 *vector, u32 count) +sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -1155,48 +1153,6 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) { - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - kfprog.filter = kfilter; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - kfree(kfilter); - return ret; - } - return sys_setsockopt(fd, level, optname, optval, optlen); -} - struct flock32 { short l_type; short l_whence; @@ -1873,256 +1829,3 @@ return ret; } -/* - * Declare the 32-bit version of the msghdr - */ - -struct msghdr32 { - unsigned int msg_name; /* Socket name */ - int msg_namelen; /* Length of name */ - unsigned int msg_iov; /* Data blocks */ - unsigned int msg_iovlen; /* Number of blocks */ - unsigned int msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ - unsigned int msg_controllen; /* Length of cmsg list */ - unsigned msg_flags; -}; - -static inline int -shape_msg(struct msghdr *mp, struct msghdr32 *mp32) -{ - int ret; - unsigned int i; - - if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32))) - return(-EFAULT); - ret = __get_user(i, &mp32->msg_name); - mp->msg_name = (void *)A(i); - ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen); - ret |= __get_user(i, &mp32->msg_iov); - mp->msg_iov = (struct iovec *)A(i); - ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen); - ret |= __get_user(i, &mp32->msg_control); - mp->msg_control = (void *)A(i); - ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen); - ret |= __get_user(mp->msg_flags, &mp32->msg_flags); - return(ret ? -EFAULT : 0); -} - -/* - * Verify & re-shape IA32 iovec. The caller must ensure that the - * iovec is big enough to hold the re-shaped message iovec. - * - * Save time not doing verify_area. copy_*_user will make this work - * in any case. - * - * Don't need to check the total size for overflow (cf net/core/iovec.c), - * 32-bit sizes can't overflow a 64-bit count. - */ - -static inline int -verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode) -{ - int size, err, ct; - struct iovec32 *iov32; - - if(m->msg_namelen) - { - if(mode==VERIFY_READ) - { - err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address); - if(err<0) - goto out; - } - - m->msg_name = address; - } else - m->msg_name = NULL; - - err = -EFAULT; - size = m->msg_iovlen * sizeof(struct iovec32); - if (copy_from_user(iov, m->msg_iov, size)) - goto out; - m->msg_iov=iov; - - err = 0; - iov32 = (struct iovec32 *)iov; - for (ct = m->msg_iovlen; ct-- > 0; ) { - iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len; - iov[ct].iov_base = (void *) A(iov32[ct].iov_base); - err += iov[ct].iov_len; - } -out: - return err; -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -/* - * BSD sendmsg interface - */ - -int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; - - err = -EFAULT; - if (shape_msg(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - ctl_len = msg_sys.msg_controllen; - if (ctl_len) - { - if (ctl_len > sizeof(ctl)) - { - err = -ENOBUFS; - ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); - if (ctl_buf == NULL) - goto out_freeiov; - } - err = -EFAULT; - if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len)) - goto out_freectl; - msg_sys.msg_control = ctl_buf; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - -out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -/* - * BSD recvmsg interface - */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; - - err=-EFAULT; - if (shape_msg(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; - - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; - - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - err = sock_recvmsg(sock, &msg_sys, total_len, flags); - if (err < 0) - goto out_freeiov; - len = err; - - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, - &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} diff -Nru a/arch/mips64/kernel/scall_o32.S b/arch/mips64/kernel/scall_o32.S --- a/arch/mips64/kernel/scall_o32.S Wed Dec 11 16:14:42 2002 +++ b/arch/mips64/kernel/scall_o32.S Thu Mar 6 11:06:44 2003 @@ -378,8 +378,8 @@ sys sys32_select 5 sys sys_flock 2 sys sys_msync 3 - sys sys32_readv 3 /* 4145 */ - sys sys32_writev 3 + sys compat_sys_readv 3 /* 4145 */ + sys compat_sys_writev 3 sys sys_cacheflush 3 sys sys_cachectl 3 sys sys_sysmips 4 @@ -410,11 +410,11 @@ sys sys_listen 2 sys sys_recv 4 /* 4175 */ sys sys_recvfrom 6 - sys sys32_recvmsg 3 + sys compat_sys_recvmsg 3 sys sys_send 4 - sys sys32_sendmsg 3 + sys compat_sys_sendmsg 3 sys sys_sendto 6 /* 4180 */ - sys sys32_setsockopt 5 + sys compat_sys_setsockopt 5 sys sys_shutdown 2 sys sys_socket 3 sys sys_socketpair 4 diff -Nru a/arch/mips64/mips-boards/atlas/atlas_int.c b/arch/mips64/mips-boards/atlas/atlas_int.c --- a/arch/mips64/mips-boards/atlas/atlas_int.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips64/mips-boards/atlas/atlas_int.c Sat Mar 8 14:50:43 2003 @@ -95,11 +95,13 @@ int i; int num = 0; struct irqaction *action; + unsigned long flags; for (i = 0; i < ATLASINT_END; i++, num++) { + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto unlock; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -110,6 +112,8 @@ action->name); } seq_puts(p, " [hw0]\n"); +unlock: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } return 0; } @@ -239,6 +243,7 @@ irq_desc[i].action = 0; irq_desc[i].depth = 1; irq_desc[i].handler = &atlas_irq_type; + spin_lock_init(&irq_desc[i].lock); } #ifdef CONFIG_REMOTE_DEBUG diff -Nru a/arch/mips64/mips-boards/malta/malta_int.c b/arch/mips64/mips-boards/malta/malta_int.c --- a/arch/mips64/mips-boards/malta/malta_int.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips64/mips-boards/malta/malta_int.c Sat Mar 8 14:50:43 2003 @@ -125,11 +125,13 @@ int i; int num = 0; struct irqaction *action; + unsigned long flags; for (i = 0; i < 8; i++, num++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip_1; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -140,11 +142,14 @@ action->name); } seq_puts(p, " [on-chip]\n"); +skip_1: + local_irq_restore(flags); } for (i = 0; i < MALTAINT_END; i++, num++) { + local_irq_save(flags); action = hw0_irq_action[i]; if (!action) - continue; + goto skip_2; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -155,6 +160,8 @@ action->name); } seq_puts(p, " [hw0]\n"); +skip_2: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips64/sgi-ip22/ip22-int.c b/arch/mips64/sgi-ip22/ip22-int.c --- a/arch/mips64/sgi-ip22/ip22-int.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips64/sgi-ip22/ip22-int.c Sat Mar 8 14:50:43 2003 @@ -237,11 +237,13 @@ int i; int num = 0; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < 16 ; i++, num++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip_1; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -252,11 +254,14 @@ action->name); } seq_puts(p, " [on-chip]\n"); +skip_1: + local_irq_restore(flags); } for (i = 0 ; i < 24 ; i++, num++) { + local_irq_save(flags); action = local_irq_action[i]; if (!action) - continue; + goto skip_2; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -267,6 +272,8 @@ action->name); } seq_puts(p, " [local]\n"); +skip_2: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c --- a/arch/mips64/sgi-ip27/ip27-irq.c Thu Oct 31 07:28:36 2002 +++ b/arch/mips64/sgi-ip27/ip27-irq.c Sat Mar 8 14:50:43 2003 @@ -141,11 +141,13 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < NR_IRQS ; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', action->name); @@ -156,6 +158,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips64/vmlinux.lds.S b/arch/mips64/vmlinux.lds.S --- a/arch/mips64/vmlinux.lds.S Wed Jan 15 09:48:42 2003 +++ b/arch/mips64/vmlinux.lds.S Fri Feb 14 15:10:00 2003 @@ -50,6 +50,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); /* Align double page for init_task_union */ __init_end = .; diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig --- a/arch/parisc/Kconfig Sun Feb 9 17:29:49 2003 +++ b/arch/parisc/Kconfig Sat Mar 8 14:50:37 2003 @@ -18,10 +18,6 @@ bool default y -config SWAP - bool - default y - config STACK_GROWSUP bool default y diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c --- a/arch/parisc/kernel/sys_parisc32.c Sat Feb 15 19:30:17 2003 +++ b/arch/parisc/kernel/sys_parisc32.c Thu Mar 6 11:06:44 2003 @@ -919,12 +919,10 @@ /* readv/writev stolen from mips64 */ -struct iovec32 { unsigned int iov_base; int iov_len; }; - typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); static long -do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, +do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector, u32 count) { unsigned long tot_len; @@ -939,7 +937,7 @@ */ if (!count) return 0; - if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -1025,7 +1023,7 @@ } asmlinkage long -sys32_readv(int fd, struct iovec32 *vector, u32 count) +sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -1045,7 +1043,7 @@ } asmlinkage long -sys32_writev(int fd, struct iovec32 *vector, u32 count) +sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -1062,747 +1060,6 @@ bad_file: return ret; } - -/********** Borrowed from sparc64 -- hardly reviewed, not tested *****/ -#include -#include -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -extern struct socket *sockfd_lookup(int fd, int *err); - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} - - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - - -static int do_ipv4_set_replace(int fd, int level, int optname, - char *optval, int optlen) -#if 1 -/* Fields happen to be padded such that this works. -** Don't need to change iptables.h:struct ipt_replace -*/ -{ - struct ipt_replace *repl = (struct ipt_replace *) optval; - unsigned long ptr64; - unsigned int ptr32; - int ret; - - if (copy_from_user(&ptr32, &repl->counters, sizeof(ptr32))) - return -EFAULT; - ptr64 = (unsigned long) ptr32; - if (copy_to_user(&repl->counters, &ptr64, sizeof(ptr64))) - return -EFAULT; - - ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen); - - /* Restore 32-bit ptr */ - if (copy_to_user(&repl->counters, &ptr32, sizeof(ptr32))) - return -EFAULT; - - return ret; -} -#else -/* This version tries to "do it right". ie allocate kernel buffers for -** everything and copy data in/out. Way too complicated. -** NOT TESTED for correctness! -*/ -{ - struct ipt_replace *kern_repl; - struct ipt_counters *kern_counters; - unsigned int user_counters; - mm_segment_t old_fs; - int ret = 0; - - kern_repl = (struct ipt_replace *) kmalloc(optlen+8, GFP_KERNEL); - if (!kern_repl) - return -ENOMEM; - - if (copy_from_user(kern_repl, optval, optlen)) { - ret = -EFAULT; - goto err02; - } - - /* 32-bit ptr is in the MSB's */ - user_counters = (unsigned int) (((unsigned long) kern_repl->counters) >> 32); - /* - ** We are going to set_fs() to kernel space - and thus need - ** "relocate" the counters buffer to the kernel space. - */ - kern_counters = (struct ipt_counters *) kmalloc(kern_repl->num_counters * sizeof(struct ipt_counters), GFP_KERNEL); - if (!user_counters) { - ret = -ENOMEM; - goto err02; - } - - if (copy_from_user(kern_counters, (char *) user_counters, optlen)) { - ret = -EFAULT; - goto err01; - } - - /* We can update the kernel ptr now that we have the data. */ - kern_repl->counters = kern_counters; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen); - - set_fs(old_fs); - - /* Copy counters back out to user space */ - if (copy_to_user((char *) user_counters, kern_counters, - kern_repl->num_counters * sizeof(struct ipt_counters))) - { - ret = -EFAULT; - goto err01; - } - - /* restore counters so userspace can consume it */ - kern_repl->counters = NULL; - (unsigned int) kern_repl->counters = user_counters; - - /* Copy repl back out to user space */ - if (copy_to_user(optval, kern_repl, optlen)) - { - ret = -EFAULT; - } - -err01: - kfree(kern_counters); -err02: - kfree(kern_repl); - return ret; -} -#endif - - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, optval, optlen); - - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, optval, optlen); - - /* - ** Beware: IPT_SO_SET_REPLACE == IP6T_SO_SET_REPLACE - */ - if (level == IPPROTO_IP && optname == IPT_SO_SET_REPLACE) - return do_ipv4_set_replace(fd, level, optname, optval, optlen); - - if (level == IPPROTO_IPV6 && optname == IP6T_SO_SET_REPLACE) -#if 0 - /* FIXME: I don't (yet) use IPV6. -ggg */ - return do_ipv6_set_replace(fd, level, optname, optval, optlen); -#else - { - BUG(); - return -ENXIO; - } -#endif - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - /*** copied from mips64 ***/ /* diff -Nru a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S --- a/arch/parisc/vmlinux.lds.S Wed Jan 15 09:48:42 2003 +++ b/arch/parisc/vmlinux.lds.S Fri Feb 14 15:10:04 2003 @@ -73,6 +73,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c --- a/arch/ppc/8xx_io/uart.c Mon Feb 3 05:47:46 2003 +++ b/arch/ppc/8xx_io/uart.c Mon Mar 3 11:33:06 2003 @@ -2522,12 +2522,11 @@ /* * Register console. */ -long __init console_8xx_init(long kmem_start, long kmem_end) +static void __init console_8xx_init(long kmem_start, long kmem_end) { register_console(&sercons); - return kmem_start; } - +console_initcall(console_8xx_init); #endif /* Index in baud rate table of the default console baud rate. diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig Sun Feb 9 17:29:49 2003 +++ b/arch/ppc/Kconfig Sat Mar 8 14:50:37 2003 @@ -1126,22 +1126,6 @@ config PIN_TLB bool "Pinned Kernel TLBs (860 ONLY)" depends on ADVANCED_OPTIONS && 8xx - -config SWAP - bool "Enable support for swap" - depends on ADVANCED_OPTIONS - help - This option allows you to turn off support for swapfiles in - the kernel. This can be useful if you know that your system - will never have swap. - - Say Y here unless you know what you are doing. - -config SWAP - bool - depends on !ADVANCED_OPTIONS - default y - endmenu source "drivers/mtd/Kconfig" diff -Nru a/arch/ppc/boot/simple/rw4/ppc_40x.h b/arch/ppc/boot/simple/rw4/ppc_40x.h --- a/arch/ppc/boot/simple/rw4/ppc_40x.h Fri Feb 14 15:10:29 2003 +++ b/arch/ppc/boot/simple/rw4/ppc_40x.h Wed Feb 19 07:23:15 2003 @@ -42,7 +42,7 @@ #define dccr 0x3fa /* data cache control reg. */ #define dcwr 0x3ba /* data cache write-thru reg */ #define dear 0x3d5 /* data exception address reg */ -#define esr 0x3d4 /* exception syndrome registe */ +#define esr 0x3d4 /* exception syndrome register */ #define evpr 0x3d6 /* exception vector prefix reg */ #define iccr 0x3fb /* instruction cache cntrl re */ #define icdbdr 0x3d3 /* instr cache dbug data reg */ diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c --- a/arch/ppc/kernel/irq.c Sat Feb 15 13:50:01 2003 +++ b/arch/ppc/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -346,6 +346,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_puts(p, " "); for (j=0; jhandler ) - continue; + goto skip; seq_printf(p, "%3d: ", i); #ifdef CONFIG_SMP for (j = 0; j < NR_CPUS; j++) @@ -373,8 +375,10 @@ seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); + seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } #ifdef CONFIG_TAU_INT if (tau_initialized){ diff -Nru a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S --- a/arch/ppc/vmlinux.lds.S Wed Jan 15 09:48:42 2003 +++ b/arch/ppc/vmlinux.lds.S Fri Feb 14 15:10:39 2003 @@ -107,6 +107,10 @@ } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; + __start___ftr_fixup = .; __ftr_fixup : { *(__ftr_fixup) } __stop___ftr_fixup = .; diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig Thu Feb 13 00:47:26 2003 +++ b/arch/ppc64/Kconfig Sat Mar 8 14:50:37 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Mon Dec 16 19:26:01 2002 +++ b/arch/ppc64/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -341,6 +341,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_printf(p, " "); for (j=0; jhandler) - continue; + goto skip; seq_printf(p, "%3d: ", i); #ifdef CONFIG_SMP for (j = 0; j < NR_CPUS; j++) { @@ -371,6 +373,8 @@ for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); return 0; diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Sat Feb 22 00:17:10 2003 +++ b/arch/ppc64/kernel/misc.S Thu Mar 6 11:06:44 2003 @@ -604,7 +604,7 @@ .llong .compat_sys_statfs .llong .compat_sys_fstatfs /* 100 */ .llong .sys_ioperm - .llong .sys32_socketcall + .llong .compat_sys_socketcall .llong .sys32_syslog .llong .compat_sys_setitimer .llong .compat_sys_getitimer /* 105 */ diff -Nru a/arch/ppc64/kernel/sys32.S b/arch/ppc64/kernel/sys32.S --- a/arch/ppc64/kernel/sys32.S Tue Feb 18 10:25:13 2003 +++ b/arch/ppc64/kernel/sys32.S Thu Mar 6 11:06:44 2003 @@ -25,7 +25,7 @@ extsw r4,r4 /* sign extend off_t offset parm */ b .sys_lseek -_GLOBAL(sys32_socketcall) /* r3=call, r4=args */ +_GLOBAL(compat_sys_socketcall) /* r3=call, r4=args */ cmpwi r3, 1 blt- .do_einval cmpwi r3, 17 @@ -221,14 +221,14 @@ .llong 2b,.do_efault .previous -_STATIC(do_sys_setsockopt) /* sys32_setsockopt(int, int, int, char *, int) */ +_STATIC(do_sys_setsockopt) /* compat_sys_setsockopt(int, int, int, char *, int) */ mr r10,r4 1: lwa r3,0(r10) 2: lwa r4,4(r10) 3: lwa r5,8(r10) 4: lwz r6,12(r10) 5: lwa r7,16(r10) - b .sys32_setsockopt + b .compat_sys_setsockopt .section __ex_table,"a" .align 3 .llong 1b,.do_efault @@ -238,14 +238,14 @@ .llong 5b,.do_efault .previous -_STATIC(do_sys_getsockopt) /* sys32_getsockopt(int, int, int, u32, u32) */ +_STATIC(do_sys_getsockopt) /* compat_sys_getsockopt(int, int, int, u32, u32) */ mr r10,r4 1: lwa r3,0(r10) 2: lwa r4,4(r10) 3: lwa r5,8(r10) 4: lwz r6,12(r10) 5: lwz r7,16(r10) - b .sys32_getsockopt + b .compat_sys_getsockopt .section __ex_table,"a" .align 3 .llong 1b,.do_efault @@ -255,12 +255,12 @@ .llong 5b,.do_efault .previous -_STATIC(do_sys_sendmsg) /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */ +_STATIC(do_sys_sendmsg) /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ mr r10,r4 1: lwa r3,0(r10) 2: lwz r4,4(r10) 3: lwa r5,8(r10) - b .sys32_sendmsg + b .compat_sys_sendmsg .section __ex_table,"a" .align 3 .llong 1b,.do_efault @@ -268,12 +268,12 @@ .llong 3b,.do_efault .previous -_STATIC(do_sys_recvmsg) /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */ +_STATIC(do_sys_recvmsg) /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ mr r10,r4 1: lwa r3,0(r10) 2: lwz r4,4(r10) 3: lwa r5,8(r10) - b .sys32_recvmsg + b .compat_sys_recvmsg .section __ex_table,"a" .align 3 .llong 1b,.do_efault diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Tue Feb 18 10:25:13 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Thu Mar 6 11:06:44 2003 @@ -74,13 +74,11 @@ #include #include -struct iovec32 { u32 iov_base; compat_size_t iov_len; }; - typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, - const struct iovec32 *vector, u32 count) + const struct compat_iovec *vector, u32 count) { compat_ssize_t tot_len; struct iovec iovstack[UIO_FASTIOV]; @@ -114,7 +112,7 @@ goto out; } retval = -EFAULT; - if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) goto out; /* @@ -206,7 +204,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -227,7 +225,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -2133,708 +2131,6 @@ return -EFAULT; return ret; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int err; - - if (optlen < sizeof(*up)) - return -EINVAL; - if (get_user(ktime.tv_sec, &up->tv_sec) || - __get_user(ktime.tv_usec, &up->tv_usec)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); - set_fs(old_fs); - - return err; -} - -asmlinkage long sys32_setsockopt(int fd, int level, int optname, char* optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - char *optval, int *optlen); - -static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int len, err; - - if (get_user(len, optlen)) - return -EFAULT; - if (len < sizeof(*up)) - return -EINVAL; - len = sizeof(ktime); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); - set_fs(old_fs); - - if (!err) { - if (put_user(sizeof(*up), optlen) || - put_user(ktime.tv_sec, &up->tv_sec) || - __put_user(ktime.tv_usec, &up->tv_usec)) - err = -EFAULT; - } - return err; -} - -asmlinkage int sys32_getsockopt(int fd, int level, int optname, - char *optval, int *optlen) -{ - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); -} - -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - 16 for IP, 16 for IPX, 24 for IPv6, about 80 for AX.25 */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -struct msghdr32 -{ - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 -{ - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if (kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if (kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if (kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while (ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -asmlinkage long sys32_sendmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if (kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if (copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if (copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - if (kcmsg32->cmsg_level == SOL_SOCKET && - kcmsg32->cmsg_type == SO_TIMESTAMP) { - struct timeval tv; - struct compat_timeval *tv32; - - if (clen64 != CMSG_LEN(sizeof(struct timeval))) { - kfree(workbuf); - goto fail; - } - copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv)); - tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32); - tv32->tv_sec = tv.tv_sec; - tv32->tv_usec = tv.tv_usec; - clen32 = sizeof(*tv32) + - CMSG32_ALIGN(sizeof(struct cmsghdr32)); - } else { - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - } - kcmsg32->cmsg_len = clen32; - - switch (kcmsg32->cmsg_type) { - /* - * The timestamp type's data needs to be converted - * from 64-bit time values to 32-bit time values - */ - case SO_TIMESTAMP: { - compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32); - __kernel_time_t* ptr_time = CMSG_DATA(ucmsg); - *ptr_time32 = *ptr_time; - *(ptr_time32+1) = *(ptr_time+1); - kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) - - sizeof(compat_time_t)); - } - default:; - } - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage long sys32_recvmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if (uaddr != NULL && err >= 0 && kern_msg.msg_namelen) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - - return len; } /* diff -Nru a/arch/ppc64/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S --- a/arch/ppc64/vmlinux.lds.S Wed Jan 15 09:48:42 2003 +++ b/arch/ppc64/vmlinux.lds.S Fri Feb 14 15:10:57 2003 @@ -97,6 +97,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig --- a/arch/s390/Kconfig Mon Feb 24 10:24:34 2003 +++ b/arch/s390/Kconfig Sat Mar 8 14:50:37 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/s390/vmlinux.lds.S b/arch/s390/vmlinux.lds.S --- a/arch/s390/vmlinux.lds.S Mon Feb 24 10:24:21 2003 +++ b/arch/s390/vmlinux.lds.S Mon Mar 3 11:37:38 2003 @@ -78,6 +78,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(256); __initramfs_start = .; .init.ramfs : { *(.init.initramfs) } diff -Nru a/arch/s390x/Kconfig b/arch/s390x/Kconfig --- a/arch/s390x/Kconfig Mon Feb 24 10:24:34 2003 +++ b/arch/s390x/Kconfig Sat Mar 8 14:50:37 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - config RWSEM_GENERIC_SPINLOCK bool diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S --- a/arch/s390x/kernel/entry.S Mon Feb 24 10:25:00 2003 +++ b/arch/s390x/kernel/entry.S Thu Mar 6 11:06:44 2003 @@ -499,7 +499,7 @@ .long SYSCALL(sys_statfs,compat_sys_statfs_wrapper) .long SYSCALL(sys_fstatfs,compat_sys_fstatfs_wrapper) /* 100 */ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) - .long SYSCALL(sys_socketcall,sys32_socketcall_wrapper) + .long SYSCALL(sys_socketcall,compat_sys_socketcall_wrapper) .long SYSCALL(sys_syslog,sys32_syslog_wrapper) .long SYSCALL(sys_setitimer,compat_sys_setitimer_wrapper) .long SYSCALL(sys_getitimer,compat_sys_getitimer_wrapper) /* 105 */ diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c --- a/arch/s390x/kernel/linux32.c Mon Feb 24 10:25:00 2003 +++ b/arch/s390x/kernel/linux32.c Thu Mar 6 11:06:44 2003 @@ -904,13 +904,11 @@ return sys_ftruncate(fd, (high << 32) | low); } -struct iovec32 { u32 iov_base; compat_size_t iov_len; }; - typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, - const struct iovec32 *vector, u32 count) + const struct compat_iovec *vector, u32 count) { unsigned long tot_len; struct iovec iovstack[UIO_FASTIOV]; @@ -925,7 +923,7 @@ */ if (!count) return 0; - if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -996,7 +994,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; long ret = -EBADF; @@ -1014,7 +1012,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -1867,740 +1865,6 @@ return ret; } -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - switch (kcmsg32->cmsg_type) { - /* - * The timestamp type's data needs to be converted - * from 64-bit time values to 32-bit time values - */ - case SO_TIMESTAMP: { - compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32); - __kernel_time_t* ptr_time = CMSG_DATA(ucmsg); - get_user(*ptr_time32, ptr_time); - get_user(*(ptr_time32+1), ptr_time+1); - kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) - - sizeof(compat_time_t)); - } - default:; - } - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -/* - * BSD sendmsg interface - */ - -int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; - - err = -EFAULT; - if (msghdr_from_user32_to_kern(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - ctl_len = msg_sys.msg_controllen; - if (ctl_len) - { - if (ctl_len > sizeof(ctl)) - { - ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); - if (ctl_buf == NULL) - goto out_freeiov; - } - else if (ctl_len < sizeof(struct cmsghdr)) - { - /* to get same error message as on 31 bit native */ - err = EOPNOTSUPP; - goto out_freeiov; - } - err = -EFAULT; - if (cmsghdr_from_user32_to_kern(&msg_sys, ctl_buf, ctl_len)) - goto out_freectl; -// msg_sys.msg_control = ctl_buf; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - -out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -static __inline__ void -scm_recv32(struct socket *sock, struct msghdr *msg, - struct scm_cookie *scm, int flags, unsigned long cmsg_ptr) -{ - if(!msg->msg_control) - { - if(sock->passcred || scm->fp) - msg->msg_flags |= MSG_CTRUNC; - scm_destroy(scm); - return; - } - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) msg->msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(msg, cmsg_ptr); - /* Wheee... */ - if(sock->passcred) - put_cmsg32(msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(scm->creds), &scm->creds); - if(!scm->fp) - return; - - scm_detach_fds32(msg, scm); -} - -static int -sock_recvmsg32(struct socket *sock, struct msghdr *msg, int size, int flags, - unsigned long cmsg_ptr) -{ - struct sock_iocb *si; - struct kiocb iocb; - - init_sync_kiocb(&iocb, NULL); - - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = msg; - si->size = size; - si->flags = flags; - - memset(si->scm, 0, sizeof(*si->scm)); - - size = sock->ops->recvmsg(&iocb, sock, msg, size, flags, si->scm); - if (size >= 0) - scm_recv32(sock, msg, si->scm, flags, cmsg_ptr); - - if (-EIOCBQUEUED == size) - size = wait_on_sync_kiocb(&iocb); - - return size; -} - -/* - * BSD recvmsg interface - */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; - - err=-EFAULT; - if (msghdr_from_user32_to_kern(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; - - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; - - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - err = sock_recvmsg32(sock, &msg_sys, total_len, flags, cmsg_ptr); - if (err < 0) - goto out_freeiov; - len = err; - - if (uaddr != NULL && - /* in order to get same error message as on native 31 bit */ - msg_sys.msg_namelen > 0) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((compat_size_t) ((unsigned long)msg_sys.msg_control - cmsg_ptr), &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - if (level == SOL_SOCKET && - (optname == SO_SNDTIMEO || optname == SO_RCVTIMEO)) { - long ret; - struct timeval tmp; - mm_segment_t old_fs; - - if (get_tv32(&tmp, (struct compat_timeval *)optval )) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, (char *) &tmp, sizeof(struct timeval)); - set_fs(old_fs); - return ret; - } - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - extern void check_pending(int signum); /* @@ -3663,104 +2927,6 @@ error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); out: return error; -} - -extern asmlinkage long sys_socket(int family, int type, int protocol); -extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); -extern asmlinkage long sys_listen(int fd, int backlog); -extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen); -extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage long sys_socketpair(int family, int type, int protocol, int usockvec[2]); -extern asmlinkage long sys_send(int fd, void * buff, size_t len, unsigned flags); -extern asmlinkage long sys_sendto(int fd, void * buff, size_t len, unsigned flags, - struct sockaddr *addr, int addr_len); -extern asmlinkage long sys_recv(int fd, void * ubuf, size_t size, unsigned flags); -extern asmlinkage long sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags, - struct sockaddr *addr, int *addr_len); -extern asmlinkage long sys_shutdown(int fd, int how); -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int * optlen); - -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static unsigned char nas[18] = {AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -asmlinkage long sys32_socketcall(int call, u32 *args) -{ - int ret; - u32 a[6]; - - if (call < SYS_SOCKET || call > SYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nas[call])) - return -EFAULT; - switch(call) { - case SYS_SOCKET: - ret = sys_socket(a[0], a[1], a[2]); - break; - case SYS_BIND: - ret = sys_bind(a[0], (struct sockaddr *) A(a[1]), a[2]); - break; - case SYS_CONNECT: - ret = sys_connect(a[0], (struct sockaddr *) A(a[1]), a[2]); - break; - case SYS_LISTEN: - ret = sys_listen(a[0], a[1]); - break; - case SYS_ACCEPT: - ret = sys_accept(a[0], (struct sockaddr *) A(a[1]), - (int *) A(a[2])); - break; - case SYS_GETSOCKNAME: - ret = sys_getsockname(a[0], (struct sockaddr *) A(a[1]), - (int *) A(a[2])); - break; - case SYS_GETPEERNAME: - ret = sys_getpeername(a[0], (struct sockaddr *) A(a[1]), - (int *) A(a[2])); - break; - case SYS_SOCKETPAIR: - ret = sys_socketpair(a[0], a[1], a[2], (int *) A(a[3])); - break; - case SYS_SEND: - ret = sys_send(a[0], (void *) A(a[1]), a[2], a[3]); - break; - case SYS_SENDTO: - ret = sys_sendto(a[0], (void*) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), a[5]); - break; - case SYS_RECV: - ret = sys_recv(a[0], (void *) A(a[1]), a[2], a[3]); - break; - case SYS_RECVFROM: - ret = sys_recvfrom(a[0], (void *) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), (int *) A(a[5]) ); - break; - case SYS_SHUTDOWN: - ret = sys_shutdown(a[0], a[1]); - break; - case SYS_SETSOCKOPT: - ret = sys32_setsockopt(a[0], a[1], a[2], (char *) A(a[3]), - a[4]); - break; - case SYS_GETSOCKOPT: - ret = sys_getsockopt(a[0], a[1], a[2], (char *) A(a[3]), (int *) A(a[4]) ); - break; - case SYS_SENDMSG: - ret = sys32_sendmsg(a[0], (struct msghdr32 *) A(a[1]), - a[2]); - break; - case SYS_RECVMSG: - ret = sys32_recvmsg(a[0], (struct msghdr32 *) A(a[1]), - a[2]); - break; - default: - ret = EINVAL; - break; - } - return ret; } extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len, diff -Nru a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S --- a/arch/s390x/kernel/wrapper32.S Mon Feb 24 10:25:00 2003 +++ b/arch/s390x/kernel/wrapper32.S Thu Mar 6 11:06:44 2003 @@ -452,11 +452,11 @@ llgtr %r3,%r3 # struct compat_statfs * jg compat_sys_fstatfs # branch to system call - .globl sys32_socketcall_wrapper -sys32_socketcall_wrapper: + .globl compat_sys_socketcall_wrapper +compat_sys_socketcall_wrapper: lgfr %r2,%r2 # int llgtr %r3,%r3 # u32 * - jg sys32_socketcall # branch to system call + jg compat_sys_socketcall # branch to system call .globl sys32_syslog_wrapper sys32_syslog_wrapper: diff -Nru a/arch/s390x/vmlinux.lds.S b/arch/s390x/vmlinux.lds.S --- a/arch/s390x/vmlinux.lds.S Mon Feb 24 10:24:21 2003 +++ b/arch/s390x/vmlinux.lds.S Mon Mar 3 11:44:26 2003 @@ -78,6 +78,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(256); __initramfs_start = .; .init.ramfs : { *(.init.initramfs) } diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig --- a/arch/sh/Kconfig Sun Feb 9 17:29:49 2003 +++ b/arch/sh/Kconfig Sat Mar 8 14:50:37 2003 @@ -18,10 +18,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c --- a/arch/sh/kernel/irq.c Tue Feb 25 01:38:48 2003 +++ b/arch/sh/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -90,6 +90,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_puts(p, " "); for (j=0; jtypename); @@ -108,6 +110,8 @@ for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +unlock: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } return 0; } diff -Nru a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S --- a/arch/sh/vmlinux.lds.S Wed Jan 15 09:48:42 2003 +++ b/arch/sh/vmlinux.lds.S Fri Feb 14 15:11:24 2003 @@ -68,6 +68,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; __machvec_start = .; .machvec.init : { *(.machvec.init) } __machvec_end = .; diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig --- a/arch/sparc/Kconfig Mon Mar 3 00:33:45 2003 +++ b/arch/sparc/Kconfig Sat Mar 8 14:50:37 2003 @@ -9,10 +9,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c --- a/arch/sparc/kernel/irq.c Sun Dec 8 14:33:46 2002 +++ b/arch/sparc/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -104,6 +104,7 @@ { int i; struct irqaction * action; + unsigned long flags; #ifdef CONFIG_SMP int j; #endif @@ -114,9 +115,10 @@ return show_sun4d_interrupts(p, v); } for (i = 0 ; i < NR_IRQS ; i++) { + local_irq_save(flags); action = *(i + irq_action); if (!action) - continue; + goto skip; seq_printf(p, "%3d: ", i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); @@ -136,6 +138,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c --- a/arch/sparc/kernel/sys_sunos.c Fri Feb 7 07:59:17 2003 +++ b/arch/sparc/kernel/sys_sunos.c Sat Mar 8 11:39:01 2003 @@ -1107,38 +1107,16 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage int sunos_socket(int family, int type, int protocol) -{ - int ret, one = 1; - - ret = sys_socket(family, type, protocol); - if (ret < 0) - goto out; - - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: - return ret; -} - asmlinkage int sunos_accept(int fd, struct sockaddr *sa, int *addrlen) { - int ret, one = 1; + int ret; while (1) { ret = check_nonblock(sys_accept(fd,sa,addrlen),fd); if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) break; } - if (ret < 0) - goto out; - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: return ret; } diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S --- a/arch/sparc/kernel/systbls.S Sun Dec 8 12:19:41 2002 +++ b/arch/sparc/kernel/systbls.S Sat Mar 8 11:39:01 2003 @@ -110,7 +110,7 @@ .long sys_getitimer, sys_gethostname, sys_sethostname .long sunos_getdtablesize, sys_dup2, sunos_nop .long sys_fcntl, sunos_select, sunos_nop - .long sys_fsync, sys_setpriority, sunos_socket + .long sys_fsync, sys_setpriority, sys_socket .long sys_connect, sunos_accept /*100*/ .long sys_getpriority, sunos_send, sunos_recv .long sunos_nosys, sys_bind, sunos_setsockopt diff -Nru a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S --- a/arch/sparc/vmlinux.lds.S Wed Jan 15 09:48:42 2003 +++ b/arch/sparc/vmlinux.lds.S Fri Feb 14 15:11:32 2003 @@ -55,6 +55,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Mon Mar 3 00:34:40 2003 +++ b/arch/sparc64/Kconfig Sat Mar 8 14:50:37 2003 @@ -9,10 +9,6 @@ bool default y -config SWAP - bool - default y - source "init/Kconfig" @@ -151,9 +147,14 @@ If in doubt, say N. config CPU_FREQ_TABLE - tristate + tristate "CPU frequency table helpers" + depends on CPU_FREQ default y + help + Many CPUFreq drivers use these helpers, so only say N here if + the CPUFreq driver of your choice doesn't need these helpers. + If in doubt, say Y. config US3_FREQ tristate "UltraSPARC-III CPU Frequency driver" diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig --- a/arch/sparc64/defconfig Sun Mar 2 23:23:54 2003 +++ b/arch/sparc64/defconfig Fri Mar 7 19:26:39 2003 @@ -39,9 +39,11 @@ # CONFIG_PREEMPT is not set CONFIG_NR_CPUS=4 CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_PROC_INTF=y CONFIG_CPU_FREQ_TABLE=y CONFIG_US3_FREQ=m +CONFIG_CPU_FREQ_PROC_INTF=y +CONFIG_CPU_FREQ_GOV_USERSPACE=m +# CONFIG_CPU_FREQ_24_API is not set CONFIG_SPARC64=y CONFIG_HOTPLUG=y CONFIG_HAVE_DEC_LOCK=y @@ -354,6 +356,8 @@ CONFIG_XFRM_USER=m CONFIG_IPV6=m CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m # # SCTP Configuration (EXPERIMENTAL) @@ -872,6 +876,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set CONFIG_USB_WACOM=m +CONFIG_USB_KBTAB=m # CONFIG_USB_POWERMATE is not set # CONFIG_USB_XPAD is not set @@ -928,6 +933,7 @@ # CONFIG_USB_SERIAL_EDGEPORT_TI is not set CONFIG_USB_SERIAL_KEYSPAN_PDA=m CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set # CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set # CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set # CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set @@ -938,6 +944,7 @@ # CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set # CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set CONFIG_USB_SERIAL_KLSI=m # CONFIG_USB_SERIAL_KOBIL_SCT is not set CONFIG_USB_SERIAL_MCT_U232=m diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c --- a/arch/sparc64/kernel/ioctl32.c Tue Feb 25 10:47:17 2003 +++ b/arch/sparc64/kernel/ioctl32.c Fri Mar 7 23:00:48 2003 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -4850,6 +4851,7 @@ COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) +COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) /* DEVFS */ COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) diff -Nru a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c --- a/arch/sparc64/kernel/pci_common.c Tue Feb 25 10:47:17 2003 +++ b/arch/sparc64/kernel/pci_common.c Fri Mar 7 19:08:16 2003 @@ -78,20 +78,6 @@ return 0; } -/* Remove a PCI device from the device trees, then - * free it up. Note that this must run before - * the device's resources are registered because we - * do not handle unregistering them here. - */ -static void pci_device_delete(struct pci_dev *pdev) -{ - list_del(&pdev->global_list); - list_del(&pdev->bus_list); - - /* Ok, all references are gone, free it up. */ - kfree(pdev); -} - /* Older versions of OBP on PCI systems encode 64-bit MEM * space assignments incorrectly, this fixes them up. We also * take the opportunity here to hide other kinds of bogus @@ -164,7 +150,7 @@ * second EBUS/HappyMeal pair if the external * connector for it is not present. */ - pci_device_delete(pdev); + pci_remove_bus_device(pdev); return; } diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c --- a/arch/sparc64/kernel/smp.c Sat Feb 22 00:03:07 2003 +++ b/arch/sparc64/kernel/smp.c Sat Mar 8 07:52:56 2003 @@ -1137,16 +1137,16 @@ do { sparc64_do_profile(regs); if (!--prof_counter(cpu)) { - if (cpu == boot_cpu_id) { - irq_enter(); + irq_enter(); + if (cpu == boot_cpu_id) { kstat_cpu(cpu).irqs[0]++; timer_tick_interrupt(regs); - - irq_exit(); } update_process_times(user); + + irq_exit(); prof_counter(cpu) = prof_multiplier(cpu); } diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c --- a/arch/sparc64/kernel/sparc64_ksyms.c Thu Feb 27 05:46:56 2003 +++ b/arch/sparc64/kernel/sparc64_ksyms.c Thu Mar 6 12:08:45 2003 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -243,6 +244,7 @@ /* Solaris/SunOS binary compatibility */ EXPORT_SYMBOL(_sigpause_common); +EXPORT_SYMBOL(verify_compat_iovec); /* Should really be in linux/kernel/ksyms.c */ EXPORT_SYMBOL(dump_thread); diff -Nru a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S --- a/arch/sparc64/kernel/sys32.S Tue Feb 18 10:25:13 2003 +++ b/arch/sparc64/kernel/sys32.S Thu Mar 6 11:06:44 2003 @@ -202,38 +202,38 @@ nop nop nop -do_sys_setsockopt: /* sys32_setsockopt(int, int, int, char *, int) */ +do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_setsockopt), %g1 + sethi %hi(compat_sys_setsockopt), %g1 ldswa [%o1 + 0x8] %asi, %o2 lduwa [%o1 + 0xc] %asi, %o3 ldswa [%o1 + 0x10] %asi, %o4 - jmpl %g1 + %lo(sys32_setsockopt), %g0 + jmpl %g1 + %lo(compat_sys_setsockopt), %g0 ldswa [%o1 + 0x4] %asi, %o1 nop -do_sys_getsockopt: /* sys32_getsockopt(int, int, int, u32, u32) */ +do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_getsockopt), %g1 + sethi %hi(compat_sys_getsockopt), %g1 ldswa [%o1 + 0x8] %asi, %o2 lduwa [%o1 + 0xc] %asi, %o3 lduwa [%o1 + 0x10] %asi, %o4 - jmpl %g1 + %lo(sys32_getsockopt), %g0 + jmpl %g1 + %lo(compat_sys_getsockopt), %g0 ldswa [%o1 + 0x4] %asi, %o1 nop -do_sys_sendmsg: /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */ +do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_sendmsg), %g1 + sethi %hi(compat_sys_sendmsg), %g1 lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys32_sendmsg), %g0 + jmpl %g1 + %lo(compat_sys_sendmsg), %g0 lduwa [%o1 + 0x4] %asi, %o1 nop nop nop -do_sys_recvmsg: /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */ +do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_recvmsg), %g1 + sethi %hi(compat_sys_recvmsg), %g1 lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys32_recvmsg), %g0 + jmpl %g1 + %lo(compat_sys_recvmsg), %g0 lduwa [%o1 + 0x4] %asi, %o1 nop nop diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c Tue Feb 18 10:25:13 2003 +++ b/arch/sparc64/kernel/sys_sparc32.c Thu Mar 6 11:06:44 2003 @@ -63,8 +63,6 @@ #include #include -#include - /* Use this to get at 32-bit user passed pointers. */ /* Things to consider: the low-level assembly stub does srl x, 0, x for first four arguments, so if you have @@ -860,13 +858,11 @@ return sys_ftruncate(fd, (high << 32) | low); } -struct iovec32 { u32 iov_base; compat_size_t iov_len; }; - typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, - const struct iovec32 *vector, u32 count) + const struct compat_iovec *vector, u32 count) { compat_ssize_t tot_len; struct iovec iovstack[UIO_FASTIOV]; @@ -900,7 +896,7 @@ goto out; } retval = -EFAULT; - if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) goto out; /* @@ -992,7 +988,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret; @@ -1015,7 +1011,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret; @@ -1905,773 +1901,6 @@ set_fs (old_fs); if (put_rusage (ru, &r)) return -EFAULT; return ret; -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - if (kcmsg32->cmsg_level == SOL_SOCKET && - kcmsg32->cmsg_type == SO_TIMESTAMP) { - struct timeval tv; - struct compat_timeval *tv32; - - if (clen64 != CMSG_LEN(sizeof(struct timeval))) { - kfree(workbuf); - goto fail; - } - copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv)); - tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32); - tv32->tv_sec = tv.tv_sec; - tv32->tv_usec = tv.tv_usec; - clen32 = sizeof(*tv32) + - CMSG32_ALIGN(sizeof(struct cmsghdr32)); - } else { - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - } - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_netfilter_replace(int fd, int level, int optname, - char *optval, int optlen) -{ - struct ipt_replace32 { - char name[IPT_TABLE_MAXNAMELEN]; - __u32 valid_hooks; - __u32 num_entries; - __u32 size; - __u32 hook_entry[NF_IP_NUMHOOKS]; - __u32 underflow[NF_IP_NUMHOOKS]; - __u32 num_counters; - __u32 counters; - struct ipt_entry entries[0]; - } *repl32 = (struct ipt_replace32 *)optval; - struct ipt_replace *krepl; - struct ipt_counters *counters32; - __u32 origsize; - unsigned int kreplsize, kcountersize; - mm_segment_t old_fs; - int ret; - - if (optlen < sizeof(repl32)) - return -EINVAL; - - if (copy_from_user(&origsize, - &repl32->size, - sizeof(origsize))) - return -EFAULT; - - kreplsize = sizeof(*krepl) + origsize; - kcountersize = krepl->num_counters * sizeof(struct ipt_counters); - - /* Hack: Causes ipchains to give correct error msg --RR */ - if (optlen != kreplsize) - return -ENOPROTOOPT; - - krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL); - if (krepl == NULL) - return -ENOMEM; - - if (copy_from_user(krepl, optval, kreplsize)) { - kfree(krepl); - return -EFAULT; - } - - counters32 = (struct ipt_counters *)AA( - ((struct ipt_replace32 *)krepl)->counters); - - kcountersize = krepl->num_counters * sizeof(struct ipt_counters); - krepl->counters = (struct ipt_counters *)kmalloc( - kcountersize, GFP_KERNEL); - if (krepl->counters == NULL) { - kfree(krepl); - return -ENOMEM; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)krepl, kreplsize); - set_fs(old_fs); - - if (ret == 0 && - copy_to_user(counters32, krepl->counters, kcountersize)) - ret = -EFAULT; - - kfree(krepl->counters); - kfree(krepl); - - return ret; -} - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int err; - - if (optlen < sizeof(*up)) - return -EINVAL; - if (get_user(ktime.tv_sec, &up->tv_sec) || - __get_user(ktime.tv_usec, &up->tv_usec)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); - set_fs(old_fs); - - return err; -} - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == IPT_SO_SET_REPLACE) - return do_netfilter_replace(fd, level, optname, - optval, optlen); - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - char *optval, int *optlen); - -static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int len, err; - - if (get_user(len, optlen)) - return -EFAULT; - if (len < sizeof(*up)) - return -EINVAL; - len = sizeof(ktime); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); - set_fs(old_fs); - - if (!err) { - if (put_user(sizeof(*up), optlen) || - put_user(ktime.tv_sec, &up->tv_sec) || - __put_user(ktime.tv_usec, &up->tv_usec)) - err = -EFAULT; - } - return err; -} - -asmlinkage int sys32_getsockopt(int fd, int level, int optname, - char *optval, int *optlen) -{ - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); } extern void check_pending(int signum); diff -Nru a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c --- a/arch/sparc64/kernel/sys_sunos32.c Tue Feb 18 10:25:13 2003 +++ b/arch/sparc64/kernel/sys_sunos32.c Sat Mar 8 11:39:01 2003 @@ -54,6 +54,7 @@ #include /* For SOCKET_I */ +#include #include /* Use this to get at 32-bit user passed pointers. */ @@ -1253,26 +1254,9 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage int sunos_socket(int family, int type, int protocol) -{ - int ret, one = 1; - - ret = sys_socket(family, type, protocol); - if (ret < 0) - goto out; - - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: - return ret; -} - asmlinkage int sunos_accept(int fd, u32 sa, u32 addrlen) { - int ret, one = 1; + int ret; while (1) { ret = check_nonblock(sys_accept(fd, (struct sockaddr *)A(sa), @@ -1280,12 +1264,6 @@ if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) break; } - if (ret < 0) - goto out; - - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: return ret; } @@ -1324,8 +1302,6 @@ extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen); -extern asmlinkage int sys32_getsockopt(int fd, int level, int optname, - u32 optval, u32 optlen); asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval, int optlen) @@ -1353,6 +1329,6 @@ if (tr_opt >=2 && tr_opt <= 6) tr_opt += 30; } - ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen); + ret = compat_sys_getsockopt(fd, level, tr_opt, (void*)(unsigned long)optval, (void*)(unsigned long)optlen); return ret; } diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S --- a/arch/sparc64/kernel/systbls.S Tue Feb 18 23:56:15 2003 +++ b/arch/sparc64/kernel/systbls.S Sat Mar 8 11:39:01 2003 @@ -173,13 +173,13 @@ .word compat_sys_getitimer, sys_gethostname, sys_sethostname .word sunos_getdtablesize, sys_dup2, sunos_nop .word sys32_fcntl, sunos_select, sunos_nop - .word sys_fsync, sys_setpriority32, sunos_socket + .word sys_fsync, sys_setpriority32, sys_socket .word sys_connect, sunos_accept /*100*/ .word sys_getpriority, sunos_send, sunos_recv .word sunos_nosys, sys_bind, sunos_setsockopt .word sys_listen, sunos_nosys, sunos_sigaction .word sunos_sigblock, sunos_sigsetmask, sys_sigpause - .word sys32_sigstack, sys32_recvmsg, sys32_sendmsg + .word sys32_sigstack, compat_sys_recvmsg, compat_sys_sendmsg .word sunos_nosys, sys32_gettimeofday, sys32_getrusage .word sunos_getsockopt, sunos_nosys, sunos_readv .word sunos_writev, sys32_settimeofday, sys32_fchown16 diff -Nru a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c --- a/arch/sparc64/kernel/us3_cpufreq.c Mon Mar 3 00:34:40 2003 +++ b/arch/sparc64/kernel/us3_cpufreq.c Sat Mar 8 01:37:35 2003 @@ -276,6 +276,7 @@ driver->target = us3freq_target; driver->init = us3freq_cpu_init; driver->exit = us3freq_cpu_exit; + driver->owner = THIS_MODULE, strcpy(driver->name, "UltraSPARC-III"); cpufreq_us3_driver = driver; diff -Nru a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c --- a/arch/sparc64/solaris/socket.c Wed Dec 4 11:05:21 2002 +++ b/arch/sparc64/solaris/socket.c Thu Mar 6 12:08:45 2003 @@ -267,35 +267,6 @@ unsigned char cmsg_data[0]; }; -struct iovec32 { - u32 iov_base; - u32 iov_len; -}; - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct sol_nmsghdr *umsg) { @@ -321,42 +292,6 @@ return err; } -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr *user_msg, unsigned user_flags) { struct socket *sock; @@ -371,7 +306,7 @@ return -EFAULT; if(kern_msg.msg_iovlen > UIO_MAXIOV) return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); + err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ); if (err < 0) goto out; total_len = err; @@ -439,7 +374,7 @@ uaddr = kern_msg.msg_name; uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); + err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE); if (err < 0) goto out; total_len = err; diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S --- a/arch/sparc64/vmlinux.lds.S Wed Jan 15 09:48:42 2003 +++ b/arch/sparc64/vmlinux.lds.S Fri Feb 14 15:11:44 2003 @@ -61,6 +61,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(8192); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/um/Kconfig b/arch/um/Kconfig --- a/arch/um/Kconfig Wed Feb 5 20:16:01 2003 +++ b/arch/um/Kconfig Sat Mar 8 14:50:37 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - mainmenu "Linux/Usermode Kernel Configuration" config ISA diff -Nru a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c --- a/arch/um/drivers/stdio_console.c Sat Dec 28 12:28:00 2002 +++ b/arch/um/drivers/stdio_console.c Fri Feb 14 15:11:51 2003 @@ -214,12 +214,13 @@ console_device, console_setup, CON_PRINTBUFFER); -void stdio_console_init(void) +static void __init stdio_console_init(void) { INIT_LIST_HEAD(&vts[0].chan_list); list_add(&init_console_chan.list, &vts[0].chan_list); register_console(&stdiocons); } +console_initcall(stdio_console_init); static int console_chan_setup(char *str) { diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c --- a/arch/um/drivers/ubd_kern.c Wed Feb 5 20:16:02 2003 +++ b/arch/um/drivers/ubd_kern.c Sat Mar 8 14:50:21 2003 @@ -673,7 +673,7 @@ static int ubd_mc_init(void) { mconsole_register_dev(&ubd_mc); - return(0); + return 0; } __initcall(ubd_mc_init); @@ -682,29 +682,24 @@ { int i; - ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL); - if(register_blkdev(MAJOR_NR, "ubd", &ubd_blops)){ - printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR); + ubd_dir_handle = devfs_mk_dir(NULL, "ubd", NULL); + if (register_blkdev(MAJOR_NR, "ubd")) return -1; - } blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock); elevator_init(&ubd_queue, &elevator_noop); - if(fake_major != 0){ + if (fake_major != 0) { char name[sizeof("ubd_nnn\0")]; snprintf(name, sizeof(name), "ubd_%d", fake_major); ubd_fake_dir_handle = devfs_mk_dir(NULL, name, NULL); - if(register_blkdev(fake_major, "ubd", &ubd_blops)){ - printk(KERN_ERR "ubd: unable to get major %d\n", - fake_major); + if (register_blkdev(fake_major, "ubd")) return -1; - } } - for(i = 0; i < MAX_DEV; i++) + for (i = 0; i < MAX_DEV; i++) ubd_add(i); - return(0); + return 0; } late_initcall(ubd_init); diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c --- a/arch/um/kernel/mem.c Wed Feb 5 20:16:02 2003 +++ b/arch/um/kernel/mem.c Thu Mar 6 08:19:07 2003 @@ -154,8 +154,8 @@ unsigned long vaddr; vaddr = start; - i = __pgd_offset(vaddr); - j = __pmd_offset(vaddr); + i = pgd_index(vaddr); + j = pmd_index(vaddr); pgd = pgd_base + i; for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { @@ -257,7 +257,7 @@ vaddr = PKMAP_BASE; fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir); - pgd = swapper_pg_dir + __pgd_offset(vaddr); + pgd = swapper_pg_dir + pgd_index(vaddr); pmd = pmd_offset(pgd, vaddr); pte = pte_offset_kernel(pmd, vaddr); pkmap_page_table = pte; diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig --- a/arch/v850/Kconfig Tue Feb 18 18:40:02 2003 +++ b/arch/v850/Kconfig Sat Mar 8 14:50:37 2003 @@ -10,9 +10,6 @@ config MMU bool default n -config SWAP - bool - default n config UID16 bool default n diff -Nru a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c --- a/arch/v850/kernel/irq.c Tue Feb 25 01:38:52 2003 +++ b/arch/v850/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -78,6 +78,7 @@ { int i; struct irqaction * action; + unsigned long flags; seq_puts(p, " "); for (i=0; i < 1 /*smp_num_cpus*/; i++) @@ -87,10 +88,10 @@ for (i = 0 ; i < NR_IRQS ; i++) { int j, count, num; const char *type_name = irq_desc[i].handler->typename; - + spin_lock_irqsave(&irq_desc[j].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto skip; count = 0; num = -1; @@ -108,11 +109,13 @@ seq_printf(p, " %*s%d", 14 - prec, type_name, num); } else seq_printf(p, " %14s", type_name); + seq_printf(p, " %s", action->name); - for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[j].lock, flags); } seq_printf(p, "ERR: %10lu\n", irq_err_count); return 0; diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig Wed Feb 12 05:38:20 2003 +++ b/arch/x86_64/Kconfig Sat Mar 8 14:50:37 2003 @@ -24,10 +24,6 @@ bool default y -config SWAP - bool - default y - config ISA bool diff -Nru a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile --- a/arch/x86_64/boot/Makefile Wed Jan 29 20:41:18 2003 +++ b/arch/x86_64/boot/Makefile Fri Mar 7 14:11:39 2003 @@ -62,33 +62,33 @@ # Set this if you want to pass append arguments to the zdisk/fdimage kernel FDARGS = -$(obj)/mtools.conf: $(obj)/mtools.conf.in +$(obj)/mtools.conf: $(src)/mtools.conf.in sed -e 's|@OBJ@|$(obj)|g' < $< > $@ # This requires write access to /dev/fd0 zdisk: $(BOOTIMAGE) $(obj)/mtools.conf - MTOOLSRC=$(src)/mtools.conf mformat a: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync syslinux /dev/fd0 ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync -# These require being root or having syslinux run setuid -fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf +# These require being root or having syslinux 2.02 or higher installed +fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 - MTOOLSRC=$(src)/mtools.conf mformat v: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync syslinux $(obj)/fdimage ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - v:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync -fdimage288: $(BOOTIMAGE) $(src)/mtools.conf +fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 - MTOOLSRC=$(src)/mtools.conf mformat w: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync syslinux $(obj)/fdimage ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - w:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync zlilo: $(BOOTIMAGE) if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi diff -Nru a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S --- a/arch/x86_64/boot/setup.S Fri May 10 14:10:51 2002 +++ b/arch/x86_64/boot/setup.S Wed Mar 5 01:43:54 2003 @@ -829,13 +829,6 @@ .word 0x9200 # data read/write .word 0x00CF # granularity = 4096, 386 # (+5th nibble of limit) -# this is 64bit descriptor for code - .word 0xFFFF - .word 0 - .word 0x9A00 # code read/exec - .word 0x00AF # as above, but it is long mode and with D=0 - # it does not seem to do the trick. - idt_48: .word 0 # idt limit = 0 .word 0, 0 # idt base = 0L diff -Nru a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile --- a/arch/x86_64/ia32/Makefile Mon Feb 3 14:19:36 2003 +++ b/arch/x86_64/ia32/Makefile Thu Mar 6 11:06:44 2003 @@ -4,4 +4,4 @@ obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \ ia32_signal.o \ - ia32_binfmt.o fpu32.o socket32.o ptrace32.o ipc32.o syscall32.o + ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o diff -Nru a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c --- a/arch/x86_64/ia32/ia32_signal.c Mon Feb 10 17:21:29 2003 +++ b/arch/x86_64/ia32/ia32_signal.c Sat Mar 8 18:05:09 2003 @@ -106,20 +106,24 @@ stack_t uss,uoss; int ret; mm_segment_t seg; + if (uss_ptr) { + u32 ptr; if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) || - __get_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) || - __get_user((u32)uss.ss_flags, &uss_ptr->ss_flags) || - __get_user((u32)uss.ss_size, &uss_ptr->ss_size)) + __get_user(ptr, &uss_ptr->ss_sp) || + __get_user(uss.ss_flags, &uss_ptr->ss_flags) || + __get_user(uss.ss_size, &uss_ptr->ss_size)) return -EFAULT; + uss.ss_sp = (void *)(u64)ptr; + } seg = get_fs(); set_fs(KERNEL_DS); - ret = do_sigaltstack(&uss, &uoss, regs.rsp); + ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs.rsp); set_fs(seg); if (ret >= 0 && uoss_ptr) { - if (!access_ok(VERIFY_WRITE,uss_ptr,sizeof(stack_ia32_t)) || - __put_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) || - __put_user((u32)uss.ss_flags, &uss_ptr->ss_flags) || - __put_user((u32)uss.ss_size, &uss_ptr->ss_size)) + if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) || + __put_user((u32)(u64)uss.ss_sp, &uoss_ptr->ss_sp) || + __put_user(uss.ss_flags, &uoss_ptr->ss_flags) || + __put_user(uss.ss_size, &uoss_ptr->ss_size)) ret = -EFAULT; } return ret; diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S --- a/arch/x86_64/ia32/ia32entry.S Sat Feb 15 04:39:48 2003 +++ b/arch/x86_64/ia32/ia32entry.S Sat Mar 8 15:58:09 2003 @@ -302,7 +302,7 @@ .quad compat_sys_statfs .quad compat_sys_fstatfs /* 100 */ .quad sys_ioperm - .quad sys32_socketcall + .quad compat_sys_socketcall .quad sys_syslog .quad compat_sys_setitimer .quad compat_sys_getitimer /* 105 */ @@ -443,8 +443,8 @@ .quad compat_sys_futex /* 240 */ .quad sys32_sched_setaffinity .quad sys32_sched_getaffinity - .quad sys_set_thread_area - .quad sys_get_thread_area + .quad sys32_set_thread_area + .quad sys32_get_thread_area .quad sys32_io_setup .quad sys_io_destroy .quad sys32_io_getevents diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c --- a/arch/x86_64/ia32/ptrace32.c Sat Oct 26 14:02:33 2002 +++ b/arch/x86_64/ia32/ptrace32.c Sat Mar 8 17:56:51 2003 @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include diff -Nru a/arch/x86_64/ia32/socket32.c b/arch/x86_64/ia32/socket32.c --- a/arch/x86_64/ia32/socket32.c Fri Dec 20 16:51:21 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,756 +0,0 @@ -/* - * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c. - * - * Copyright (C) 2000 VA Linux Co - * Copyright (C) 2000 Don Dugger - * Copyright (C) 1999 Arun Sharma - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 2000 Hewlett-Packard Co. - * Copyright (C) 2000 David Mosberger-Tang - * Copyright (C) 2000,2001 Andi Kleen, SuSE Labs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define A(__x) ((unsigned long)(__x)) -#define AA(__x) ((unsigned long)(__x)) - -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - void * optval, int *optlen); - - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage long sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage long sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int err; - - if (optlen < sizeof(*up)) - return -EINVAL; - if (get_user(ktime.tv_sec, &up->tv_sec) || - __get_user(ktime.tv_usec, &up->tv_usec)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); - set_fs(old_fs); - - return err; -} - -asmlinkage long sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - -static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int len, err; - - if (get_user(len, optlen)) - return -EFAULT; - if (len < sizeof(*up)) - return -EINVAL; - len = sizeof(ktime); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); - set_fs(old_fs); - - if (!err) { - if (put_user(sizeof(*up), optlen) || - put_user(ktime.tv_sec, &up->tv_sec) || - __put_user(ktime.tv_usec, &up->tv_usec)) - err = -EFAULT; - } - return err; -} - -asmlinkage long sys32_getsockopt(int fd, int level, int optname, - char *optval, int *optlen) -{ - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); -} - -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, - int addrlen); -extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, - int *upeer_addrlen); -extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags); -extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len, - unsigned flags, u32 addr, int addr_len); -extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags); -extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size, - unsigned flags, u32 addr, u32 addr_len); -extern asmlinkage long sys_socket(int family, int type, int protocol); -extern asmlinkage long sys_socketpair(int family, int type, int protocol, - int usockvec[2]); -extern asmlinkage long sys_shutdown(int fd, int how); -extern asmlinkage long sys_listen(int fd, int backlog); - -asmlinkage long sys32_socketcall(int call, u32 *args) -{ - int ret; - u32 a[6]; - u32 a0,a1; - - if (callSYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nas[call])) - return -EFAULT; - a0=a[0]; - a1=a[1]; - - switch(call) - { - case SYS_SOCKET: - ret = sys_socket(a0, a1, a[2]); - break; - case SYS_BIND: - ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_CONNECT: - ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_LISTEN: - ret = sys_listen(a0, a1); - break; - case SYS_ACCEPT: - ret = sys_accept(a0, (struct sockaddr *)A(a1), - (int *)A(a[2])); - break; - case SYS_GETSOCKNAME: - ret = sys_getsockname(a0, (struct sockaddr *)A(a1), - (int *)A(a[2])); - break; - case SYS_GETPEERNAME: - ret = sys_getpeername(a0, (struct sockaddr *)A(a1), - (int *)A(a[2])); - break; - case SYS_SOCKETPAIR: - ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3])); - break; - case SYS_SEND: - ret = sys_send(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_SENDTO: - ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_RECV: - ret = sys_recv(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_RECVFROM: - ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_SHUTDOWN: - ret = sys_shutdown(a0,a1); - break; - case SYS_SETSOCKOPT: - ret = sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]), - a[4]); - break; - case SYS_GETSOCKOPT: - ret = sys32_getsockopt(a0, a1, a[2], (char *)(u64)a[3], (int *)(u64)a[4]); - break; - case SYS_SENDMSG: - ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1), - a[2]); - break; - case SYS_RECVMSG: - ret = sys32_recvmsg(a0, (struct msghdr32 *)A(a1), - a[2]); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c --- a/arch/x86_64/ia32/sys_ia32.c Tue Feb 18 10:25:13 2003 +++ b/arch/x86_64/ia32/sys_ia32.c Sun Mar 9 07:56:11 2003 @@ -738,7 +738,7 @@ asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long); static struct iovec * -get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, int *errp) +get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type, int *errp) { int i; u32 buf, len; @@ -751,7 +751,7 @@ return 0; if (count > UIO_MAXIOV) return(struct iovec *)0; - if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count)) + if(verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count)) return(struct iovec *)0; if (count > UIO_FASTIOV) { *errp = -ENOMEM; @@ -792,14 +792,14 @@ } asmlinkage long -sys32_readv(int fd, struct iovec32 *vector, u32 count) +sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL) + if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_readv(fd, iov, count); @@ -810,14 +810,14 @@ } asmlinkage long -sys32_writev(int fd, struct iovec32 *vector, u32 count) +sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ, &ret)) == NULL) + if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_writev(fd, iov, count); @@ -1261,8 +1261,8 @@ if (s->si_signo >= SIGRTMIN) { d->si_pid = s->si_pid; d->si_uid = s->si_uid; - /* XXX: Ouch, how to find this out??? */ - d->si_int = s->si_int; + memcpy(&d->si_int, &s->si_int, + sizeof(siginfo_t) - offsetof(siginfo_t,si_int)); } else switch (s->si_signo) { /* XXX: What about POSIX1.b timers */ case SIGCHLD: @@ -1299,8 +1299,9 @@ if (s->si_signo >= SIGRTMIN) { d->si_pid = s->si_pid; d->si_uid = s->si_uid; - /* XXX: Ouch, how to find this out??? */ - d->si_int = s->si_int; + memcpy(&d->si_int, + &s->si_int, + sizeof(siginfo_t) - offsetof(siginfo_t, si_int)); } else switch (s->si_signo) { /* XXX: What about POSIX1.b timers */ case SIGCHLD: diff -Nru a/arch/x86_64/ia32/tls32.c b/arch/x86_64/ia32/tls32.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/x86_64/ia32/tls32.c Sun Mar 9 07:30:05 2003 @@ -0,0 +1,162 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * sys_alloc_thread_area: get a yet unused TLS descriptor index. + */ +static int get_free_idx(void) +{ + struct thread_struct *t = ¤t->thread; + int idx; + + for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) + if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx)) + return idx + GDT_ENTRY_TLS_MIN; + return -ESRCH; +} + +/* + * Set a given TLS descriptor: + * When you want addresses > 32bit use arch_prctl() + */ +int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info) +{ + struct user_desc info; + struct n_desc_struct *desc; + int cpu, idx; + + if (copy_from_user(&info, u_info, sizeof(info))) + return -EFAULT; + + idx = info.entry_number; + + /* + * index -1 means the kernel should try to find and + * allocate an empty descriptor: + */ + if (idx == -1) { + idx = get_free_idx(); + if (idx < 0) + return idx; + if (put_user(idx, &u_info->entry_number)) + return -EFAULT; + } + + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; + + /* + * We must not get preempted while modifying the TLS. + */ + cpu = get_cpu(); + + if (LDT_empty(&info)) { + desc->a = 0; + desc->b = 0; + } else { + desc->a = LDT_entry_a(&info); + desc->b = LDT_entry_b(&info); + } + if (t == ¤t->thread) + load_TLS(t, cpu); + + put_cpu(); + return 0; +} + +asmlinkage long sys32_set_thread_area(struct user_desc *u_info) +{ + return do_set_thread_area(¤t->thread, u_info); +} + + +/* + * Get the current Thread-Local Storage area: + */ + +#define GET_BASE(desc) ( \ + (((desc)->a >> 16) & 0x0000ffff) | \ + (((desc)->b << 16) & 0x00ff0000) | \ + ( (desc)->b & 0xff000000) ) + +#define GET_LIMIT(desc) ( \ + ((desc)->a & 0x0ffff) | \ + ((desc)->b & 0xf0000) ) + +#define GET_32BIT(desc) (((desc)->b >> 23) & 1) +#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) +#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) +#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) +#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) +#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) +#define GET_LONGMODE(desc) (((desc)->b >> 21) & 1) + +int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info) +{ + struct user_desc info; + struct n_desc_struct *desc; + int idx; + + if (get_user(idx, &u_info->entry_number)) + return -EFAULT; + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; + + memset(&info, 0, sizeof(struct user_desc)); + info.entry_number = idx; + info.base_addr = GET_BASE(desc); + info.limit = GET_LIMIT(desc); + info.seg_32bit = GET_32BIT(desc); + info.contents = GET_CONTENTS(desc); + info.read_exec_only = !GET_WRITABLE(desc); + info.limit_in_pages = GET_LIMIT_PAGES(desc); + info.seg_not_present = !GET_PRESENT(desc); + info.useable = GET_USEABLE(desc); + info.lm = GET_LONGMODE(desc); + + if (copy_to_user(u_info, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +asmlinkage long sys32_get_thread_area(struct user_desc *u_info) +{ + return do_get_thread_area(¤t->thread, u_info); +} + + +int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs) +{ + struct n_desc_struct *desc; + struct user_desc info, *cp; + int idx; + + cp = (void *)childregs->rsi; + if (copy_from_user(&info, cp, sizeof(info))) + return -EFAULT; + if (LDT_empty(&info)) + return -EINVAL; + + idx = info.entry_number; + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN; + desc->a = LDT_entry_a(&info); + desc->b = LDT_entry_b(&info); + + return 0; +} diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c --- a/arch/x86_64/kernel/apic.c Tue Feb 25 10:47:30 2003 +++ b/arch/x86_64/kernel/apic.c Sat Mar 8 18:01:10 2003 @@ -981,9 +981,6 @@ asmlinkage void smp_spurious_interrupt(void) { unsigned int v; - static unsigned long last_warning; - static unsigned long skipped; - irq_enter(); /* * Check if this really is a spurious interrupt and ACK it @@ -994,8 +991,12 @@ if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) ack_APIC_irq(); +#if 0 + static unsigned long last_warning; + static unsigned long skipped; + /* see sw-dev-man vol 3, chapter 7.4.13.5 */ - if (last_warning+30*HZ < jiffies) { + if (time_before(last_warning+30*HZ,jiffies)) { printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n", smp_processor_id(), skipped); last_warning = jiffies; @@ -1003,6 +1004,7 @@ } else { skipped++; } +#endif irq_exit(); } diff -Nru a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c --- a/arch/x86_64/kernel/head64.c Tue Feb 11 06:03:03 2003 +++ b/arch/x86_64/kernel/head64.c Sun Mar 9 08:28:23 2003 @@ -79,6 +79,9 @@ clear_bss(); pda_init(0); copy_bootdata(real_mode_data); + /* default console: */ + if (!strstr(saved_command_line, "console=")) + strcat(saved_command_line, " console=tty0"); s = strstr(saved_command_line, "earlyprintk="); if (s != NULL) setup_early_printk(s+12); diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c --- a/arch/x86_64/kernel/io_apic.c Sun Mar 2 18:13:32 2003 +++ b/arch/x86_64/kernel/io_apic.c Sat Mar 8 18:03:40 2003 @@ -1110,7 +1110,7 @@ */ static int __init timer_irq_works(void) { - unsigned int t1 = jiffies; + unsigned long t1 = jiffies; local_irq_enable(); /* Let ten ticks pass... */ @@ -1123,6 +1123,8 @@ * might have cached one ExtINT interrupt. Finally, at * least one tick may be lost due to delays. */ + + /* jiffies wrap? */ if (jiffies - t1 > 4) return 1; return 0; diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c --- a/arch/x86_64/kernel/irq.c Tue Feb 25 01:39:01 2003 +++ b/arch/x86_64/kernel/irq.c Sat Mar 8 14:50:43 2003 @@ -135,6 +135,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_printf(p, " "); for (j=0; jtypename); - seq_printf(p, " %s", action->name); + seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "NMI: "); for (j = 0; j < NR_CPUS; j++) diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c --- a/arch/x86_64/kernel/process.c Sat Feb 22 08:39:06 2003 +++ b/arch/x86_64/kernel/process.c Sun Mar 9 16:22:16 2003 @@ -19,46 +19,37 @@ #define __KERNEL_SYSCALLS__ #include -#include #include #include #include #include #include #include -#include -#include #include -#include #include -#include #include #include #include #include -#include #include -#include -#include -#include +#include +#include #include #include #include #include -#include #include #include -#include #include #include #include #include - -#include +#include +#include +#include asmlinkage extern void ret_from_fork(void); -int sys_arch_prctl(int code, unsigned long addr); unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; @@ -245,10 +236,36 @@ } } +static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr) +{ + struct user_desc ud = { + .base_addr = addr, + .limit = 0xfffff, + .seg_32bit = 1, + .limit_in_pages = 1, + .useable = 1, + }; + struct n_desc_struct *desc = (void *)t->thread.tls_array; + desc += tls; + desc->a = LDT_entry_a(&ud); + desc->b = LDT_entry_b(&ud); +} + +static inline u32 read_32bit_tls(struct task_struct *t, int tls) +{ + struct desc_struct *desc = (void *)t->thread.tls_array; + desc += tls; + return desc->base0 | + (((u32)desc->base1) << 16) | + (((u32)desc->base2) << 24); +} + + int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, unsigned long unused, struct task_struct * p, struct pt_regs * regs) { + int err; struct pt_regs * childregs; struct task_struct *me = current; @@ -265,7 +282,7 @@ p->thread.rsp = (unsigned long) childregs; p->thread.rsp0 = (unsigned long) (childregs+1); - p->thread.userrsp = current->thread.userrsp; + p->thread.userrsp = me->thread.userrsp; p->thread.rip = (unsigned long) ret_from_fork; @@ -277,8 +294,8 @@ asm("movl %%es,%0" : "=m" (p->thread.es)); asm("movl %%ds,%0" : "=m" (p->thread.ds)); - unlazy_fpu(current); - p->thread.i387 = current->thread.i387; + unlazy_fpu(me); + p->thread.i387 = me->thread.i387; if (unlikely(me->thread.io_bitmap_ptr != NULL)) { p->thread.io_bitmap_ptr = kmalloc((IO_BITMAP_SIZE+1)*4, GFP_KERNEL); @@ -292,27 +309,20 @@ * Set a new TLS for the child thread? */ if (clone_flags & CLONE_SETTLS) { - struct n_desc_struct *desc; - struct user_desc info; - int idx; - - if (copy_from_user(&info, test_thread_flag(TIF_IA32) ? - (void *)childregs->rsi : - (void *)childregs->rdx, sizeof(info))) - return -EFAULT; - if (LDT_empty(&info)) - return -EINVAL; - - idx = info.entry_number; - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN; - desc->a = LDT_entry_a(&info); - desc->b = LDT_entry_b(&info); - } - - return 0; +#ifdef CONFIG_IA32_EMULATION + if (test_thread_flag(TIF_IA32)) + err = ia32_child_tls(p, childregs); + else +#endif + err = do_arch_prctl(p, ARCH_SET_FS, childregs->r10); + if (err) + goto out; + } + err = 0; +out: + if (err && p->thread.io_bitmap_ptr) + kfree(p->thread.io_bitmap_ptr); + return err; } /* @@ -422,7 +432,7 @@ if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { if (next->io_bitmap_ptr) { /* - * 4 cachelines copy ... not good, but not that + * 2 cachelines copy ... not good, but not that * bad either. Anyone got something better? * This only affects processes which use ioperm(). */ @@ -537,19 +547,35 @@ #undef last_sched #undef first_sched -int sys_arch_prctl(int code, unsigned long addr) +long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) { int ret = 0; + int doit = task == current; + int cpu; switch (code) { case ARCH_SET_GS: if (addr >= TASK_SIZE) return -EPERM; - get_cpu(); + cpu = get_cpu(); + /* handle small bases via the GDT because that's faster to + switch. */ + if (addr <= 0xffffffff) { + set_32bit_tls(task, GS_TLS, addr); + if (doit) { + load_TLS(&task->thread, cpu); + load_gs_index(GS_TLS_SEL); + } + task->thread.gsindex = GS_TLS_SEL; + task->thread.gs = 0; + } else { + task->thread.gsindex = 0; + task->thread.gs = addr; + if (doit) { load_gs_index(0); - current->thread.gsindex = 0; - current->thread.gs = addr; ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); + } + } put_cpu(); break; case ARCH_SET_FS: @@ -557,22 +583,51 @@ with gs */ if (addr >= TASK_SIZE) return -EPERM; - get_cpu(); + cpu = get_cpu(); + /* handle small bases via the GDT because that's faster to + switch. */ + if (addr <= 0xffffffff) { + set_32bit_tls(task, FS_TLS, addr); + if (doit) { + load_TLS(&task->thread, cpu); + asm volatile("movl %0,%%fs" :: "r" (FS_TLS_SEL)); + } + task->thread.fsindex = FS_TLS_SEL; + task->thread.fs = 0; + } else { + task->thread.fsindex = 0; + task->thread.fs = addr; + if (doit) { + /* set the selector to 0 to not confuse + __switch_to */ asm volatile("movl %0,%%fs" :: "r" (0)); - current->thread.fsindex = 0; - current->thread.fs = addr; ret = checking_wrmsrl(MSR_FS_BASE, addr); + } + } put_cpu(); break; - - /* Returned value may not be correct when the user changed fs/gs */ - case ARCH_GET_FS: - ret = put_user(current->thread.fs, (unsigned long *)addr); + case ARCH_GET_FS: { + unsigned long base; + if (task->thread.fsindex == FS_TLS_SEL) + base = read_32bit_tls(task, FS_TLS); + else if (doit) { + rdmsrl(MSR_FS_BASE, base); + } else + base = task->thread.fs; + ret = put_user(base, (unsigned long *)addr); break; - - case ARCH_GET_GS: - ret = put_user(current->thread.gs, (unsigned long *)addr); + } + case ARCH_GET_GS: { + unsigned long base; + if (task->thread.gsindex == GS_TLS_SEL) + base = read_32bit_tls(task, GS_TLS); + else if (doit) { + rdmsrl(MSR_KERNEL_GS_BASE, base); + } else + base = task->thread.gs; + ret = put_user(base, (unsigned long *)addr); break; + } default: ret = -EINVAL; @@ -582,131 +637,9 @@ return ret; } -/* - * sys_alloc_thread_area: get a yet unused TLS descriptor index. - */ -static int get_free_idx(void) -{ - struct thread_struct *t = ¤t->thread; - int idx; - - for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) - if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx)) - return idx + GDT_ENTRY_TLS_MIN; - return -ESRCH; -} - -/* - * Set a given TLS descriptor: - * When you want addresses > 32bit use arch_prctl() - */ -int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info) -{ - struct user_desc info; - struct n_desc_struct *desc; - int cpu, idx; - - if (copy_from_user(&info, u_info, sizeof(info))) - return -EFAULT; - - idx = info.entry_number; - - /* - * index -1 means the kernel should try to find and - * allocate an empty descriptor: - */ - if (idx == -1) { - idx = get_free_idx(); - if (idx < 0) - return idx; - if (put_user(idx, &u_info->entry_number)) - return -EFAULT; - } - - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; - - /* - * We must not get preempted while modifying the TLS. - */ - cpu = get_cpu(); - - if (LDT_empty(&info)) { - desc->a = 0; - desc->b = 0; - } else { - desc->a = LDT_entry_a(&info); - desc->b = LDT_entry_b(&info); - } - if (t == ¤t->thread) - load_TLS(t, cpu); - - put_cpu(); - return 0; -} - -asmlinkage int sys_set_thread_area(struct user_desc *u_info) -{ - return do_set_thread_area(¤t->thread, u_info); -} - - -/* - * Get the current Thread-Local Storage area: - */ - -#define GET_BASE(desc) ( \ - (((desc)->a >> 16) & 0x0000ffff) | \ - (((desc)->b << 16) & 0x00ff0000) | \ - ( (desc)->b & 0xff000000) ) - -#define GET_LIMIT(desc) ( \ - ((desc)->a & 0x0ffff) | \ - ((desc)->b & 0xf0000) ) - -#define GET_32BIT(desc) (((desc)->b >> 23) & 1) -#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) -#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) -#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) -#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) -#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) -#define GET_LONGMODE(desc) (((desc)->b >> 21) & 1) - -int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info) -{ - struct user_desc info; - struct n_desc_struct *desc; - int idx; - - if (get_user(idx, &u_info->entry_number)) - return -EFAULT; - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; - - memset(&info, 0, sizeof(struct user_desc)); - info.entry_number = idx; - info.base_addr = GET_BASE(desc); - info.limit = GET_LIMIT(desc); - info.seg_32bit = GET_32BIT(desc); - info.contents = GET_CONTENTS(desc); - info.read_exec_only = !GET_WRITABLE(desc); - info.limit_in_pages = GET_LIMIT_PAGES(desc); - info.seg_not_present = !GET_PRESENT(desc); - info.useable = GET_USEABLE(desc); - info.lm = GET_LONGMODE(desc); - - if (copy_to_user(u_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -asmlinkage int sys_get_thread_area(struct user_desc *u_info) +long sys_arch_prctl(int code, unsigned long addr) { - return do_get_thread_area(¤t->thread, u_info); + return do_arch_prctl(current, code, addr); } /* diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c --- a/arch/x86_64/kernel/ptrace.c Sat Feb 15 01:42:03 2003 +++ b/arch/x86_64/kernel/ptrace.c Sun Mar 9 04:38:18 2003 @@ -26,6 +26,7 @@ #include #include #include +#include /* * does not yet catch signals sent when the child dies. @@ -322,6 +323,13 @@ wake_up_process(child); ret = 0; break; + } + +#ifdef CONFIG_IA32_EMULATION + /* This makes only sense with 32bit programs. Allow a + 64bit debugger to fully examine them too. Better + don't use it against 64bit processes, use + PTRACE_ARCH_PRCTL instead. */ case PTRACE_SET_THREAD_AREA: { int old; get_user(old, &((struct user_desc *)data)->entry_number); @@ -338,7 +346,13 @@ put_user(old, &((struct user_desc *)data)->entry_number); break; } - } +#endif + /* normal 64bit interface to access TLS data. + Works just like arch_prctl, except that the arguments + are reversed. */ + case PTRACE_ARCH_PRCTL: + ret = do_arch_prctl(child, data, addr); + break; /* * make the child exit. Best I can do is send it a sigkill. diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c --- a/arch/x86_64/kernel/setup64.c Fri Feb 21 08:55:38 2003 +++ b/arch/x86_64/kernel/setup64.c Wed Mar 5 01:43:54 2003 @@ -22,6 +22,7 @@ #include #include #include +#include char x86_boot_params[2048] __initdata = {0,}; @@ -29,9 +30,6 @@ struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned; -extern void system_call(void); -extern void ia32_cstar_target(void); - extern struct task_struct init_task; extern unsigned char __per_cpu_start[], __per_cpu_end[]; @@ -130,6 +128,24 @@ #define EXCEPTION_STK_ORDER 0 /* >= N_EXCEPTION_STACKS*EXCEPTION_STKSZ */ char boot_exception_stacks[N_EXCEPTION_STACKS*EXCEPTION_STKSZ]; +void syscall_init(void) +{ + /* + * LSTAR and STAR live in a bit strange symbiosis. + * They both write to the same internal register. STAR allows to set CS/DS + * but only a 32bit target. LSTAR sets the 64bit rip. + */ + wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32); + wrmsrl(MSR_LSTAR, system_call); + +#ifdef CONFIG_IA32_EMULATION + wrmsrl(MSR_CSTAR, ia32_cstar_target); +#endif + + /* Flags to clear on syscall */ + wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); +} + /* * cpu_init() initializes state that is per-CPU. Some data is already * initialized (naturally) in the bootstrap process, such as the GDT @@ -188,20 +204,7 @@ asm volatile("pushfq ; popq %%rax ; btr $14,%%rax ; pushq %%rax ; popfq" ::: "eax"); - /* - * LSTAR and STAR live in a bit strange symbiosis. - * They both write to the same internal register. STAR allows to set CS/DS - * but only a 32bit target. LSTAR sets the 64bit rip. - */ - wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32); - wrmsrl(MSR_LSTAR, system_call); - -#ifdef CONFIG_IA32_EMULATION - wrmsrl(MSR_CSTAR, ia32_cstar_target); -#endif - - /* Flags to clear on syscall */ - wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); + syscall_init(); wrmsrl(MSR_FS_BASE, 0); wrmsrl(MSR_KERNEL_GS_BASE, 0); diff -Nru a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c --- a/arch/x86_64/kernel/signal.c Tue Feb 11 02:37:45 2003 +++ b/arch/x86_64/kernel/signal.c Wed Mar 5 01:43:54 2003 @@ -96,14 +96,6 @@ #define COPY(x) err |= __get_user(regs->x, &sc->x) - { - unsigned int seg; - err |= __get_user(seg, &sc->gs); - load_gs_index(seg); - err |= __get_user(seg, &sc->fs); - loadsegment(fs,seg); - } - COPY(rdi); COPY(rsi); COPY(rbp); COPY(rsp); COPY(rbx); COPY(rdx); COPY(rcx); COPY(rip); COPY(r8); @@ -189,13 +181,10 @@ static inline int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) { - int tmp, err = 0; + int err = 0; - tmp = 0; - __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); - err |= __put_user(tmp, (unsigned int *)&sc->gs); - __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); - err |= __put_user(tmp, (unsigned int *)&sc->fs); + err |= __put_user(0, &sc->gs); + err |= __put_user(0, &sc->fs); err |= __put_user(regs->rdi, &sc->rdi); err |= __put_user(regs->rsi, &sc->rsi); diff -Nru a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c --- a/arch/x86_64/kernel/suspend.c Fri Dec 20 21:36:57 2002 +++ b/arch/x86_64/kernel/suspend.c Wed Mar 5 01:43:54 2003 @@ -26,6 +26,7 @@ #include #include #include +#include static struct saved_context saved_context; @@ -58,10 +59,9 @@ asm volatile ("movw %%gs, %0" : "=m" (saved_context.gs)); asm volatile ("movw %%ss, %0" : "=m" (saved_context.ss)); - asm volatile ("swapgs"); - rdmsrl(0xc0000100, saved_context.fs_base); - rdmsrl(0xc0000101, saved_context.gs_base); - asm volatile ("swapgs"); + rdmsrl(MSR_FS_BASE, saved_context.fs_base); + rdmsrl(MSR_GS_BASE, saved_context.gs_base); + rdmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base); /* * control registers @@ -99,10 +99,9 @@ load_gs_index(saved_context.gs); asm volatile ("movw %0, %%ss" :: "r" (saved_context.ss)); - asm volatile ("swapgs"); - wrmsrl(0xc0000100, saved_context.fs_base); - wrmsrl(0xc0000101, saved_context.gs_base); - asm volatile ("swapgs"); + wrmsrl(MSR_FS_BASE, saved_context.fs_base); + wrmsrl(MSR_GS_BASE, saved_context.gs_base); + wrmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base); /* * now restore the descriptor tables to their proper values diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c --- a/arch/x86_64/kernel/time.c Mon Feb 24 23:13:09 2003 +++ b/arch/x86_64/kernel/time.c Sun Mar 9 04:26:46 2003 @@ -30,7 +30,7 @@ #include #endif -u64 jiffies_64; +u64 jiffies_64 = INITIAL_JIFFIES; extern int using_apic_timer; @@ -47,8 +47,8 @@ struct hpet_data __hpet __section_hpet; /* address, quotient, trigger, hz */ -volatile unsigned long __jiffies __section_jiffies; -unsigned long __wall_jiffies __section_wall_jiffies; +volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; +unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES; struct timespec __xtime __section_xtime; struct timezone __sys_tz __section_sys_tz; diff -Nru a/arch/x86_64/lib/getuser.S b/arch/x86_64/lib/getuser.S --- a/arch/x86_64/lib/getuser.S Mon Feb 11 00:16:29 2002 +++ b/arch/x86_64/lib/getuser.S Sun Mar 9 16:12:06 2003 @@ -30,7 +30,7 @@ #include .text - .p2align + .p2align 4 .globl __get_user_1 __get_user_1: GET_THREAD_INFO(%rbx) @@ -40,7 +40,7 @@ xorq %rax,%rax ret - .p2align + .p2align 4 .globl __get_user_2 __get_user_2: GET_THREAD_INFO(%rbx) @@ -52,7 +52,7 @@ xorq %rax,%rax ret - .p2align + .p2align 4 .globl __get_user_4 __get_user_4: GET_THREAD_INFO(%rbx) @@ -64,7 +64,7 @@ xorq %rax,%rax ret - .p2align + .p2align 4 .globl __get_user_8 __get_user_8: GET_THREAD_INFO(%rbx) diff -Nru a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c --- a/arch/x86_64/mm/pageattr.c Sun Mar 2 18:13:32 2003 +++ b/arch/x86_64/mm/pageattr.c Wed Mar 5 03:08:42 2003 @@ -53,7 +53,7 @@ static void flush_kernel_map(void *address) { - if (address && cpu_has_clflush) { + if (0 && address && cpu_has_clflush) { /* is this worth it? */ int i; for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) diff -Nru a/arch/x86_64/pci/direct.c b/arch/x86_64/pci/direct.c --- a/arch/x86_64/pci/direct.c Fri Aug 30 06:59:56 2002 +++ b/arch/x86_64/pci/direct.c Wed Mar 5 03:01:42 2003 @@ -196,21 +196,35 @@ static int __devinit pci_sanity_check(struct pci_ops *o) { u32 x = 0; - struct pci_bus bus; /* Fake bus and device */ - struct pci_dev dev; + int retval = 0; + struct pci_bus *bus; /* Fake bus and device */ + struct pci_dev *dev; if (pci_probe & PCI_NO_CHECKS) return 1; - bus.number = 0; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn < 0x100; dev.devfn++) - if ((!o->read(&bus, dev.devfn, PCI_CLASS_DEVICE, 2, &x) && + + bus = kmalloc(sizeof(*bus), GFP_ATOMIC); + dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + if (!bus || !dev) { + printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); + goto exit; + } + + bus->number = 0; + dev->bus = bus; + for(dev->devfn=0; dev->devfn < 0x100; dev->devfn++) + if ((!o->read(bus, dev->devfn, PCI_CLASS_DEVICE, 2, &x) && (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) || - (!o->read(&bus, dev.devfn, PCI_VENDOR_ID, 2, &x) && - (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) - return 1; + (!o->read(bus, dev->devfn, PCI_VENDOR_ID, 2, &x) && + (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) { + retval = 1; + goto exit; + } DBG("PCI: Sanity check failed\n"); - return 0; +exit: + kfree(dev); + kfree(bus); + return retval; } static int __init pci_direct_init(void) @@ -218,7 +232,7 @@ unsigned int tmp; unsigned long flags; - local_save_flags(flags); local_irq_disable(); + local_irq_save(flags); /* * Check if configuration type 1 works. @@ -261,7 +275,6 @@ } local_irq_restore(flags); - pci_root_ops = NULL; return 0; } diff -Nru a/arch/x86_64/pci/irq.c b/arch/x86_64/pci/irq.c --- a/arch/x86_64/pci/irq.c Fri Nov 15 01:01:33 2002 +++ b/arch/x86_64/pci/irq.c Wed Mar 5 03:54:28 2003 @@ -109,7 +109,7 @@ */ if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL)) printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i); - pcibios_last_bus = -1; + //pcibios_last_bus = -1; } /* @@ -291,14 +291,14 @@ { irq = read_config_nybble(router, 0x56, pirq - 1); } - printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d get irq : %2d\n", + printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n", dev->vendor, dev->device, pirq, irq); return irq; } static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d SET irq : %2d\n", + printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", dev->vendor, dev->device, pirq, irq); if (pirq <= 4) { diff -Nru a/arch/x86_64/pci/legacy.c b/arch/x86_64/pci/legacy.c --- a/arch/x86_64/pci/legacy.c Wed Oct 30 02:51:28 2002 +++ b/arch/x86_64/pci/legacy.c Wed Mar 5 03:55:39 2003 @@ -1,8 +1,8 @@ /* * legacy.c - traditional, old school PCI bus probing */ -#include #include +#include #include "pci.h" /* @@ -12,28 +12,39 @@ void __devinit pcibios_fixup_peer_bridges(void) { int n; - struct pci_bus bus; - struct pci_dev dev; + struct pci_bus *bus; + struct pci_dev *dev; u16 l; - if (pcibios_last_bus <= 0 || pcibios_last_bus > 0xff) + if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) return; DBG("PCI: Peer bridge fixup\n"); + + bus = kmalloc(sizeof(*bus), GFP_ATOMIC); + dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + if (!bus || !dev) { + printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); + goto exit; + } + for (n=0; n <= pcibios_last_bus; n++) { if (pci_bus_exists(&pci_root_buses, n)) continue; - bus.number = n; - bus.ops = pci_root_ops; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn<256; dev.devfn += 8) - if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) && + bus->number = n; + bus->ops = pci_root_ops; + dev->bus = bus; + for (dev->devfn=0; dev->devfn<256; dev->devfn += 8) + if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) && l != 0x0000 && l != 0xffff) { - DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l); + DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l); printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); pci_scan_bus(n, pci_root_ops, NULL); break; } } +exit: + kfree(dev); + kfree(bus); } static int __init pci_legacy_init(void) diff -Nru a/arch/x86_64/pci/pci.h b/arch/x86_64/pci/pci.h --- a/arch/x86_64/pci/pci.h Wed Oct 30 02:47:30 2002 +++ b/arch/x86_64/pci/pci.h Wed Mar 5 03:53:36 2003 @@ -67,7 +67,6 @@ extern int pcibios_scanned; extern spinlock_t pci_config_lock; -void pcibios_fixup_irqs(void); int pirq_enable_irq(struct pci_dev *dev); extern int (*pcibios_enable_irq)(struct pci_dev *dev); diff -Nru a/arch/x86_64/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S --- a/arch/x86_64/vmlinux.lds.S Tue Feb 11 03:00:35 2003 +++ b/arch/x86_64/vmlinux.lds.S Fri Feb 14 17:50:07 2003 @@ -98,6 +98,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/crypto/api.c b/crypto/api.c --- a/crypto/api.c Mon Dec 30 13:39:58 2002 +++ b/crypto/api.c Sat Mar 8 11:46:18 2003 @@ -128,8 +128,6 @@ memset(tfm, 0, sizeof(*tfm)); - tfm->crt_ctx = (void*) &tfm[1]; - tfm->__crt_alg = alg; if (crypto_init_flags(tfm, flags)) diff -Nru a/crypto/cipher.c b/crypto/cipher.c --- a/crypto/cipher.c Sun Feb 2 23:34:59 2003 +++ b/crypto/cipher.c Sat Mar 8 11:46:18 2003 @@ -23,7 +23,8 @@ #include "internal.h" typedef void (cryptfn_t)(void *, u8 *, const u8 *); -typedef void (procfn_t)(struct crypto_tfm *, u8 *, u8*, cryptfn_t, int enc); +typedef void (procfn_t)(struct crypto_tfm *, u8 *, + u8*, cryptfn_t, int enc, void *); struct scatter_walk { struct scatterlist *sg; @@ -34,6 +35,13 @@ unsigned int offset; }; +enum km_type crypto_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + static inline void xor_64(u8 *a, const u8 *b) { ((u32 *)a)[0] ^= ((u32 *)b)[0]; @@ -159,7 +167,8 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes, cryptfn_t crfn, procfn_t prfn, int enc) + unsigned int nbytes, cryptfn_t crfn, + procfn_t prfn, int enc, void *info) { struct scatter_walk walk_in, walk_out; const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); @@ -189,7 +198,7 @@ copy_chunks(src_p, &walk_in, bsize, 0); - prfn(tfm, dst_p, src_p, crfn, enc); + prfn(tfm, dst_p, src_p, crfn, enc, info); scatter_done(&walk_in, 0, nbytes); @@ -204,35 +213,35 @@ } static void cbc_process(struct crypto_tfm *tfm, - u8 *dst, u8 *src, cryptfn_t fn, int enc) + u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info) { + u8 *iv = info; + /* Null encryption */ - if (!tfm->crt_cipher.cit_iv) + if (!iv) return; if (enc) { - tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, src); - fn(tfm->crt_ctx, dst, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, dst, - crypto_tfm_alg_blocksize(tfm)); + tfm->crt_u.cipher.cit_xor_block(iv, src); + fn(crypto_tfm_ctx(tfm), dst, iv); + memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); } else { const int need_stack = (src == dst); u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; u8 *buf = need_stack ? stack : dst; - fn(tfm->crt_ctx, buf, src); - tfm->crt_u.cipher.cit_xor_block(buf, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, src, - crypto_tfm_alg_blocksize(tfm)); + fn(crypto_tfm_ctx(tfm), buf, src); + tfm->crt_u.cipher.cit_xor_block(buf, iv); + memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); if (buf != dst) memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); } } static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, - cryptfn_t fn, int enc) + cryptfn_t fn, int enc, void *info) { - fn(tfm->crt_ctx, dst, src); + fn(crypto_tfm_ctx(tfm), dst, src); } static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) @@ -243,7 +252,7 @@ tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } else - return cia->cia_setkey(tfm->crt_ctx, key, keylen, + return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, &tfm->crt_flags); } @@ -252,7 +261,8 @@ struct scatterlist *src, unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_encrypt, ecb_process, 1); + tfm->__crt_alg->cra_cipher.cia_encrypt, + ecb_process, 1, NULL); } static int ecb_decrypt(struct crypto_tfm *tfm, @@ -261,7 +271,8 @@ unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_decrypt, ecb_process, 1); + tfm->__crt_alg->cra_cipher.cia_decrypt, + ecb_process, 1, NULL); } static int cbc_encrypt(struct crypto_tfm *tfm, @@ -270,7 +281,18 @@ unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_encrypt, cbc_process, 1); + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, tfm->crt_cipher.cit_iv); +} + +static int cbc_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, iv); } static int cbc_decrypt(struct crypto_tfm *tfm, @@ -279,7 +301,18 @@ unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_decrypt, cbc_process, 0); + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, tfm->crt_cipher.cit_iv); +} + +static int cbc_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, iv); } static int nocrypt(struct crypto_tfm *tfm, @@ -290,6 +323,14 @@ return -ENOSYS; } +static int nocrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return -ENOSYS; +} + int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) { u32 mode = flags & CRYPTO_TFM_MODE_MASK; @@ -318,16 +359,22 @@ case CRYPTO_TFM_MODE_CBC: ops->cit_encrypt = cbc_encrypt; ops->cit_decrypt = cbc_decrypt; + ops->cit_encrypt_iv = cbc_encrypt_iv; + ops->cit_decrypt_iv = cbc_decrypt_iv; break; case CRYPTO_TFM_MODE_CFB: ops->cit_encrypt = nocrypt; ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; break; case CRYPTO_TFM_MODE_CTR: ops->cit_encrypt = nocrypt; ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; break; default: diff -Nru a/crypto/digest.c b/crypto/digest.c --- a/crypto/digest.c Sun Feb 2 23:34:59 2003 +++ b/crypto/digest.c Sat Mar 8 11:46:18 2003 @@ -19,7 +19,7 @@ static void init(struct crypto_tfm *tfm) { - tfm->__crt_alg->cra_digest.dia_init(tfm->crt_ctx); + tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm)); } static void update(struct crypto_tfm *tfm, @@ -29,7 +29,7 @@ for (i = 0; i < nsg; i++) { char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; - tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), p, sg[i].length); crypto_kunmap(p, 0); crypto_yield(tfm); @@ -38,7 +38,7 @@ static void final(struct crypto_tfm *tfm, u8 *out) { - tfm->__crt_alg->cra_digest.dia_final(tfm->crt_ctx, out); + tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); } static void digest(struct crypto_tfm *tfm, @@ -50,7 +50,7 @@ for (i = 0; i < nsg; i++) { char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; - tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), p, sg[i].length); crypto_kunmap(p, 0); crypto_yield(tfm); diff -Nru a/crypto/internal.h b/crypto/internal.h --- a/crypto/internal.h Sun Feb 2 23:34:59 2003 +++ b/crypto/internal.h Sat Mar 8 11:46:18 2003 @@ -18,18 +18,12 @@ #include #include -static enum km_type km_types[] = { - KM_USER0, - KM_USER1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, -}; +extern enum km_type crypto_km_types[]; static inline enum km_type crypto_kmap_type(int out) { - return km_types[(in_softirq() ? 2 : 0) + out]; + return crypto_km_types[(in_softirq() ? 2 : 0) + out]; } - static inline void *crypto_kmap(struct page *page, int out) { @@ -50,6 +44,11 @@ static inline u32 crypto_cipher_flags(u32 flags) { return flags & (CRYPTO_TFM_MODE_MASK|CRYPTO_TFM_REQ_WEAK_KEY); +} + +static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) +{ + return (void *)&tfm[1]; } struct crypto_alg *crypto_alg_lookup(const char *name); diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Sat Feb 15 01:15:00 2003 +++ b/drivers/Makefile Mon Mar 10 22:34:21 2003 @@ -11,9 +11,13 @@ # PnP must come after ACPI since it will eventually need to check if acpi # was used and do nothing if so obj-$(CONFIG_PNP) += pnp/ + +# char/ comes before serial/ etc so that the VT console is the boot-time +# default. +obj-y += char/ obj-y += serial/ obj-$(CONFIG_PARPORT) += parport/ -obj-y += base/ char/ block/ misc/ net/ media/ +obj-y += base/ block/ misc/ net/ media/ obj-$(CONFIG_NUBUS) += nubus/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_IDE) += ide/ diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c --- a/drivers/acorn/block/fd1772.c Tue Feb 25 10:27:18 2003 +++ b/drivers/acorn/block/fd1772.c Sat Mar 8 14:50:21 2003 @@ -1539,11 +1539,9 @@ goto err_disk; } - err = register_blkdev(MAJOR_NR, "fd", &floppy_fops); - if (err) { - printk("Unable to get major %d for floppy\n", MAJOR_NR); + err = register_blkdev(MAJOR_NR, "fd"); + if (err) goto err_disk; - } err = -EBUSY; if (request_dma(FLOPPY_DMA, "fd1772")) { diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c --- a/drivers/acorn/block/mfmhd.c Tue Feb 25 10:27:22 2003 +++ b/drivers/acorn/block/mfmhd.c Sat Mar 8 14:50:21 2003 @@ -1267,11 +1267,9 @@ if (!request_region (mfm_addr, 10, "mfm")) goto out1; - ret = register_blkdev(MAJOR_NR, "mfm", &mfm_fops); - if (ret) { - printk("mfm_init: unable to get major number %d\n", MAJOR_NR); + ret = register_blkdev(MAJOR_NR, "mfm"); + if (ret) goto out2; - } /* Stuff for the assembler routines to get to */ hdc63463_baseaddress = ioaddr(mfm_addr); diff -Nru a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c --- a/drivers/acorn/net/ether1.c Sun Nov 17 13:36:31 2002 +++ b/drivers/acorn/net/ether1.c Thu Mar 6 05:00:32 2003 @@ -973,23 +973,6 @@ return &priv->stats; } -static int -ether1_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - /* - * We'll set the MAC address on the chip when we open it. - */ - - return 0; -} - /* * Set or clear the multicast filter for this adaptor. * num_addrs == -1 Promiscuous mode, receive all packets. @@ -1062,7 +1045,6 @@ dev->hard_start_xmit = ether1_sendpacket; dev->get_stats = ether1_getstats; dev->set_multicast_list = ether1_setmulticastlist; - dev->set_mac_address = ether1_set_mac_address; dev->tx_timeout = ether1_timeout; dev->watchdog_timeo = 5 * HZ / 100; diff -Nru a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c --- a/drivers/acorn/net/ether3.c Tue Feb 25 10:47:06 2003 +++ b/drivers/acorn/net/ether3.c Thu Mar 6 05:00:32 2003 @@ -461,23 +461,6 @@ return &priv->stats; } -static int -ether3_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - /* - * We'll set the MAC address on the chip when we open it. - */ - - return 0; -} - /* * Set or clear promiscuous/multicast mode filter for this adaptor. * @@ -903,7 +886,6 @@ dev->hard_start_xmit = ether3_sendpacket; dev->get_stats = ether3_getstats; dev->set_multicast_list = ether3_setmulticastlist; - dev->set_mac_address = ether3_set_mac_address; dev->tx_timeout = ether3_timeout; dev->watchdog_timeo = 5 * HZ / 100; diff -Nru a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c --- a/drivers/acorn/net/etherh.c Sun Nov 17 13:36:32 2002 +++ b/drivers/acorn/net/etherh.c Thu Mar 6 05:00:33 2003 @@ -482,23 +482,6 @@ return 0; } -static int -etherh_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - /* - * We'll set the MAC address on the chip when we open it. - */ - - return 0; -} - /* * Initialisation */ @@ -585,7 +568,6 @@ dev->open = etherh_open; dev->stop = etherh_close; - dev->set_mac_address = etherh_set_mac_address; dev->set_config = etherh_set_config; dev->irq = ec->irq; dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); diff -Nru a/drivers/atm/Makefile b/drivers/atm/Makefile --- a/drivers/atm/Makefile Mon Feb 3 14:19:36 2003 +++ b/drivers/atm/Makefile Sat Mar 8 13:46:23 2003 @@ -46,7 +46,7 @@ ifeq ($(CONFIG_ATM_FORE200E_SBA),y) fore_200e-objs += fore200e_sba_fw.o ifeq ($(CONFIG_ATM_FORE200E_SBA_DEFAULT_FW),y) - CONFIG_ATM_FORE200E_SBA_FW := sba200e_ecd.bin2 + CONFIG_ATM_FORE200E_SBA_FW := $(obj)/sba200e_ecd.bin2 endif endif diff -Nru a/drivers/atm/firestream.c b/drivers/atm/firestream.c --- a/drivers/atm/firestream.c Tue Feb 25 10:47:34 2003 +++ b/drivers/atm/firestream.c Thu Mar 6 09:14:50 2003 @@ -1792,7 +1792,7 @@ write_fs (dev, RAC, 0); /* Manual (AN9, page 6) says ASF1=0 means compare Utopia address - * too. I can't find ASF1 anywhere. Anyway, we AND with just hte + * too. I can't find ASF1 anywhere. Anyway, we AND with just the * other bits, then compare with 0, which is exactly what we * want. */ write_fs (dev, RAM, (1 << (28 - FS155_VPI_BITS - FS155_VCI_BITS)) - 1); diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c --- a/drivers/base/platform.c Tue Mar 4 08:20:34 2003 +++ b/drivers/base/platform.c Wed Mar 5 15:33:09 2003 @@ -59,12 +59,9 @@ static int platform_match(struct device * dev, struct device_driver * drv) { - char name[BUS_ID_SIZE]; + struct platform_device *pdev = container_of(dev, struct platform_device, dev); - if (sscanf(dev->bus_id,"%s",name)) - return (strcmp(name,drv->name) == 0); - - return 0; + return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); } struct bus_type platform_bus_type = { diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Mon Feb 10 19:20:39 2003 +++ b/drivers/block/DAC960.c Sat Mar 8 14:50:22 2003 @@ -13,9 +13,6 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for complete details. - The author respectfully requests that any modifications to this software be - sent directly to him for evaluation and testing. - */ @@ -2381,13 +2378,9 @@ /* Register the Block Device Major Number for this DAC960 Controller. */ - if (register_blkdev(MajorNumber, "dac960", - &DAC960_BlockDeviceOperations) < 0) - { - DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n", - Controller, MajorNumber); + if (register_blkdev(MajorNumber, "dac960") < 0) return false; - } + /* Initialize the I/O Request Queue. */ diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c --- a/drivers/block/acsi.c Thu Nov 7 15:02:52 2002 +++ b/drivers/block/acsi.c Sat Mar 8 14:50:22 2003 @@ -1613,7 +1613,6 @@ int acsi_init( void ) - { int err = 0; int i, target, lun; @@ -1623,8 +1622,7 @@ #endif if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI)) return 0; - if (register_blkdev( ACSI_MAJOR, "ad", &acsi_fops )) { - printk( KERN_ERR "Unable to get major %d for ACSI\n", ACSI_MAJOR ); + if (register_blkdev(ACSI_MAJOR, "ad")) { err = -EBUSY; goto out1; } diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c --- a/drivers/block/amiflop.c Mon Nov 18 07:04:31 2002 +++ b/drivers/block/amiflop.c Sat Mar 8 14:50:22 2003 @@ -1754,10 +1754,9 @@ if (!AMIGAHW_PRESENT(AMI_FLOPPY)) return -ENXIO; - if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) { - printk("fd: Unable to get major %d for floppy\n",FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR,"fd")) return -EBUSY; - } + /* * We request DSKPTR, DSKLEN and DSKDATA only, because the other * floppy registers are too spreaded over the custom register space diff -Nru a/drivers/block/ataflop.c b/drivers/block/ataflop.c --- a/drivers/block/ataflop.c Mon Nov 11 05:05:00 2002 +++ b/drivers/block/ataflop.c Sat Mar 8 14:50:22 2003 @@ -1929,10 +1929,8 @@ /* Hades doesn't have Atari-compatible floppy */ return -ENXIO; - if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) { - printk(KERN_ERR "Unable to get major %d for floppy\n",FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR,"fd")) return -EBUSY; - } for (i = 0; i < FD_MAX_UNITS; i++) { unit[i].disk = alloc_disk(1); diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c Thu Feb 27 17:05:57 2003 +++ b/drivers/block/cciss.c Sat Mar 8 14:50:22 2003 @@ -2064,7 +2064,7 @@ unchar cache_line_size, latency_timer; unchar irq, revision; uint addr[6]; - __u32 board_id; + __u32 board_id, scratchpad = 0; int cfg_offset; int cfg_base_addr; int cfg_base_addr_index; @@ -2156,6 +2156,20 @@ #endif /* CCISS_DEBUG */ c->vaddr = remap_pci_mem(c->paddr, 200); + /* Wait for the board to become ready. (PCI hotplug needs this.) + * We poll for up to 120 secs, once per 100ms. */ + for (i=0; i < 1200; i++) { + scratchpad = readl(c->vaddr + SA5_SCRATCHPAD_OFFSET); + if (scratchpad == CCISS_FIRMWARE_READY) + break; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 10); /* wait 100ms */ + } + if (scratchpad != CCISS_FIRMWARE_READY) { + printk(KERN_WARNING "cciss: Board not ready. Timed out.\n"); + return -1; + } + /* get the address index number */ cfg_base_addr = readl(c->vaddr + SA5_CTCFG_OFFSET); /* I am not prepared to deal with a 64 bit address value */ @@ -2437,14 +2451,12 @@ return -ENODEV; } - if( register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname, &cciss_fops)) - { - printk(KERN_ERR "cciss: Unable to get major number " - "%d for %s\n", COMPAQ_CISS_MAJOR+i, hba[i]->devname); + if (register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname)) { release_io_mem(hba[i]); free_hba(i); - return(-1); + return -1; } + /* make sure the board interrupts are off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); if( request_irq(hba[i]->intr, do_cciss_intr, diff -Nru a/drivers/block/cciss.h b/drivers/block/cciss.h --- a/drivers/block/cciss.h Thu Dec 5 08:03:43 2002 +++ b/drivers/block/cciss.h Mon Mar 3 13:52:06 2003 @@ -95,6 +95,7 @@ #define SA5_REPLY_INTR_MASK_OFFSET 0x34 #define SA5_REPLY_PORT_OFFSET 0x44 #define SA5_INTR_STATUS 0x30 +#define SA5_SCRATCHPAD_OFFSET 0xB0 #define SA5_CTCFG_OFFSET 0xB4 #define SA5_CTMEM_OFFSET 0xB8 @@ -104,6 +105,7 @@ #define SA5_INTR_PENDING 0x08 #define SA5B_INTR_PENDING 0x04 #define FIFO_EMPTY 0xffffffff +#define CCISS_FIRMWARE_READY 0xffff0000 /* value in scratchpad register */ #define CISS_ERROR_BIT 0x02 diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c --- a/drivers/block/cpqarray.c Tue Feb 25 11:05:27 2003 +++ b/drivers/block/cpqarray.c Sat Mar 8 14:50:22 2003 @@ -339,11 +339,9 @@ for(i=0; i < nr_ctlr; i++) { /* If this successful it should insure that we are the only */ /* instance of the driver */ - if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname, &ida_fops)) { - printk(KERN_ERR "cpqarray: Unable to get major number %d for ida\n", - COMPAQ_SMART2_MAJOR+i); + if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname)) continue; - } + hba[i]->access.set_intr_mask(hba[i], 0); if (request_irq(hba[i]->intr, do_ida_intr, SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) { diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c --- a/drivers/block/floppy.c Tue Feb 18 10:44:43 2003 +++ b/drivers/block/floppy.c Sat Mar 8 14:50:22 2003 @@ -4232,8 +4232,7 @@ } devfs_mk_dir (NULL, "floppy", NULL); - if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) { - printk("Unable to get major %d for floppy\n",FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR,"fd")) { err = -EBUSY; goto out; } diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c Mon Feb 24 23:13:25 2003 +++ b/drivers/block/genhd.c Mon Mar 10 11:47:07 2003 @@ -14,10 +14,16 @@ #include #include +#define MAX_PROBE_HASH 255 /* random */ static struct subsystem block_subsys; -#define MAX_PROBE_HASH 23 /* random */ +/* Can be merged with blk_probe or deleted altogether. Later. */ +static struct blk_major_name { + struct blk_major_name *next; + int major; + char name[16]; +} *major_names[MAX_PROBE_HASH]; static struct blk_probe { struct blk_probe *next; @@ -30,9 +36,125 @@ } *probes[MAX_PROBE_HASH]; /* index in the above - for now: assume no multimajor ranges */ +static inline int major_to_index(int major) +{ + return major % MAX_PROBE_HASH; +} + static inline int dev_to_index(dev_t dev) { - return MAJOR(dev) % MAX_PROBE_HASH; + return major_to_index(MAJOR(dev)); +} + +const char *__bdevname(dev_t dev) +{ + static char buffer[40]; + char *name = "unknown-block"; + unsigned int major = MAJOR(dev); + unsigned int minor = MINOR(dev); + int index = major_to_index(major); + struct blk_major_name *n; + + down_read(&block_subsys.rwsem); + for (n = major_names[index]; n; n = n->next) + if (n->major == major) + break; + if (n) + name = &(n->name[0]); + sprintf(buffer, "%s(%u,%u)", name, major, minor); + up_read(&block_subsys.rwsem); + + return buffer; +} + +/* get block device names in somewhat random order */ +int get_blkdev_list(char *p) +{ + struct blk_major_name *n; + int i, len; + + len = sprintf(p, "\nBlock devices:\n"); + + down_read(&block_subsys.rwsem); + for (i = 0; i < ARRAY_SIZE(major_names); i++) { + for (n = major_names[i]; n; n = n->next) + len += sprintf(p+len, "%3d %s\n", + n->major, n->name); + } + up_read(&block_subsys.rwsem); + + return len; +} + +int register_blkdev(unsigned int major, const char *name) +{ + struct blk_major_name **n, *p; + int index, ret = 0; + + /* temporary */ + if (major == 0) { + down_read(&block_subsys.rwsem); + for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) + if (major_names[index] == NULL) + break; + up_read(&block_subsys.rwsem); + + if (index == 0) { + printk("register_blkdev: failed to get major for %s\n", + name); + return -EBUSY; + } + ret = major = index; + } + + p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL); + if (p == NULL) + return -ENOMEM; + + p->major = major; + strncpy(p->name, name, sizeof(p->name)-1); + p->name[sizeof(p->name)-1] = 0; + p->next = 0; + index = major_to_index(major); + + down_write(&block_subsys.rwsem); + for (n = &major_names[index]; *n; n = &(*n)->next) + if ((*n)->major == major) + break; + if (!*n) + *n = p; + else + ret = -EBUSY; + up_write(&block_subsys.rwsem); + + if (ret < 0) + printk("register_blkdev: cannot get major %d for %s\n", + major, name); + + return ret; +} + +/* todo: make void - error printk here */ +int unregister_blkdev(unsigned int major, const char *name) +{ + struct blk_major_name **n, *p; + int index = major_to_index(major); + int ret = 0; + + down_write(&block_subsys.rwsem); + for (n = &major_names[index]; *n; n = &(*n)->next) + if ((*n)->major == major) + break; + if (!*n || strcmp((*n)->name, name)) + ret = -EINVAL; + else { + p = *n; + *n = p->next; + kfree(p); + } + up_write(&block_subsys.rwsem); + + return ret; } /* @@ -48,6 +170,9 @@ struct blk_probe *p = kmalloc(sizeof(struct blk_probe), GFP_KERNEL); struct blk_probe **s; + if (p == NULL) + return; + p->owner = module; p->get = probe; p->lock = lock; @@ -98,9 +223,9 @@ /** * add_gendisk - add partitioning information to kernel list - * @gp: per-device partitioning information + * @disk: per-device partitioning information * - * This function registers the partitioning information in @gp + * This function registers the partitioning information in @disk * with the kernel. */ void add_disk(struct gendisk *disk) @@ -318,7 +443,7 @@ return (jif / HZ) * 1000 + (jif % HZ) * 1000 / HZ; #endif } -static ssize_t disk_stat_read(struct gendisk * disk, char *page) +static ssize_t disk_stats_read(struct gendisk * disk, char *page) { disk_round_stats(disk); return sprintf(page, @@ -326,14 +451,16 @@ "%8u %8u %8llu %8u " "%8u %8u %8u" "\n", - disk->reads, disk->read_merges, - (unsigned long long)disk->read_sectors, - jiffies_to_msec(disk->read_ticks), - disk->writes, disk->write_merges, - (unsigned long long)disk->write_sectors, - jiffies_to_msec(disk->write_ticks), - disk->in_flight, jiffies_to_msec(disk->io_ticks), - jiffies_to_msec(disk->time_in_queue)); + disk_stat_read(disk, reads), disk_stat_read(disk, read_merges), + (unsigned long long)disk_stat_read(disk, read_sectors), + jiffies_to_msec(disk_stat_read(disk, read_ticks)), + disk_stat_read(disk, writes), + disk_stat_read(disk, write_merges), + (unsigned long long)disk_stat_read(disk, write_sectors), + jiffies_to_msec(disk_stat_read(disk, write_ticks)), + disk_stat_read(disk, in_flight), + jiffies_to_msec(disk_stat_read(disk, io_ticks)), + jiffies_to_msec(disk_stat_read(disk, time_in_queue))); } static struct disk_attribute disk_attr_dev = { .attr = {.name = "dev", .mode = S_IRUGO }, @@ -349,7 +476,7 @@ }; static struct disk_attribute disk_attr_stat = { .attr = {.name = "stat", .mode = S_IRUGO }, - .show = disk_stat_read + .show = disk_stats_read }; static struct attribute * default_attrs[] = { @@ -365,6 +492,7 @@ struct gendisk *disk = to_disk(kobj); kfree(disk->random); kfree(disk->part); + free_disk_stats(disk); kfree(disk); } @@ -384,6 +512,10 @@ struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL); if (disk) { memset(disk, 0, sizeof(struct gendisk)); + if (!init_disk_stats(disk)) { + kfree(disk); + return NULL; + } if (minors > 1) { int size = (minors - 1) * sizeof(struct hd_struct); disk->part = kmalloc(size, GFP_KERNEL); diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Tue Feb 25 10:47:06 2003 +++ b/drivers/block/ll_rw_blk.c Sat Mar 8 14:50:30 2003 @@ -1475,17 +1475,17 @@ return; if (rw == READ) { - rq->rq_disk->read_sectors += nr_sectors; + disk_stat_add(rq->rq_disk, read_sectors, nr_sectors); if (!new_io) - rq->rq_disk->read_merges++; + disk_stat_inc(rq->rq_disk, read_merges); } else if (rw == WRITE) { - rq->rq_disk->write_sectors += nr_sectors; + disk_stat_add(rq->rq_disk, write_sectors, nr_sectors); if (!new_io) - rq->rq_disk->write_merges++; + disk_stat_inc(rq->rq_disk, write_merges); } if (new_io) { disk_round_stats(rq->rq_disk); - rq->rq_disk->in_flight++; + disk_stat_inc(rq->rq_disk, in_flight); } } @@ -1525,11 +1525,12 @@ { unsigned long now = jiffies; - disk->time_in_queue += disk->in_flight * (now - disk->stamp); + disk_stat_add(disk, time_in_queue, + disk_stat_read(disk, in_flight) * (now - disk->stamp)); disk->stamp = now; - if (disk->in_flight) - disk->io_ticks += (now - disk->stamp_idle); + if (disk_stat_read(disk, in_flight)) + disk_stat_add(disk, io_ticks, (now - disk->stamp_idle)); disk->stamp_idle = now; } @@ -1647,7 +1648,7 @@ if (req->rq_disk) { disk_round_stats(req->rq_disk); - req->rq_disk->in_flight--; + disk_stat_dec(req->rq_disk, in_flight); } __blk_put_request(q, next); @@ -2199,16 +2200,16 @@ unsigned long duration = jiffies - req->start_time; switch (rq_data_dir(req)) { case WRITE: - disk->writes++; - disk->write_ticks += duration; + disk_stat_inc(disk, writes); + disk_stat_add(disk, write_ticks, duration); break; case READ: - disk->reads++; - disk->read_ticks += duration; + disk_stat_inc(disk, reads); + disk_stat_add(disk, read_ticks, duration); break; } disk_round_stats(disk); - disk->in_flight--; + disk_stat_dec(disk, in_flight); } __blk_put_request(req->q, req); } diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Sun Mar 2 18:13:25 2003 +++ b/drivers/block/loop.c Sat Mar 8 14:50:22 2003 @@ -1017,11 +1017,8 @@ max_loop = 8; } - if (register_blkdev(LOOP_MAJOR, "loop", &lo_fops)) { - printk(KERN_WARNING "Unable to get major number %d for loop" - " device\n", LOOP_MAJOR); + if (register_blkdev(LOOP_MAJOR, "loop")) return -EIO; - } devfs_mk_dir(NULL, "loop", NULL); diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c --- a/drivers/block/nbd.c Thu Feb 13 09:34:46 2003 +++ b/drivers/block/nbd.c Sat Mar 8 14:50:22 2003 @@ -564,9 +564,7 @@ nbd_dev[i].disk = disk; } - if (register_blkdev(NBD_MAJOR, "nbd", &nbd_fops)) { - printk("Unable to get major number %d for NBD\n", - NBD_MAJOR); + if (register_blkdev(NBD_MAJOR, "nbd")) { err = -EIO; goto out; } diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c --- a/drivers/block/paride/pcd.c Thu Dec 5 08:07:02 2002 +++ b/drivers/block/paride/pcd.c Sat Mar 8 14:50:22 2003 @@ -942,8 +942,7 @@ /* get the atapi capabilities page */ pcd_probe_capabilities(); - if (register_blkdev(major, name, &pcd_bdops)) { - printk("pcd: unable to get major number %d\n", major); + if (register_blkdev(major, name)) { for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) put_disk(cd->disk); return -1; diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c --- a/drivers/block/paride/pd.c Thu Dec 5 08:07:21 2002 +++ b/drivers/block/paride/pd.c Sat Mar 8 14:50:22 2003 @@ -890,10 +890,9 @@ { if (disable) return -1; - if (register_blkdev(major, name, &pd_fops)) { - printk("%s: unable to get major number %d\n", name, major); + if (register_blkdev(major, name)) return -1; - } + blk_init_queue(&pd_queue, do_pd_request, &pd_lock); blk_queue_max_sectors(&pd_queue, cluster); diff -Nru a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c --- a/drivers/block/paride/pf.c Thu Dec 5 08:06:39 2002 +++ b/drivers/block/paride/pf.c Sat Mar 8 14:50:22 2003 @@ -957,8 +957,7 @@ return -1; pf_busy = 0; - if (register_blkdev(major, name, &pf_fops)) { - printk("pf_init: unable to get major number %d\n", major); + if (register_blkdev(major, name)) { for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) put_disk(pf->disk); return -1; @@ -969,6 +968,7 @@ for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) { struct gendisk *disk = pf->disk; + if (!pf->present) continue; disk->private_data = pf; diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c --- a/drivers/block/ps2esdi.c Thu Dec 5 07:58:13 2002 +++ b/drivers/block/ps2esdi.c Sat Mar 8 14:50:22 2003 @@ -146,13 +146,10 @@ int error = 0; - /* register the device - pass the name, major number and operations - vector . */ - if (register_blkdev(PS2ESDI_MAJOR, "ed", &ps2esdi_fops)) { - printk("%s: Unable to get major number %d\n", DEVICE_NAME, - PS2ESDI_MAJOR); + /* register the device - pass the name and major number */ + if (register_blkdev(PS2ESDI_MAJOR, "ed")) return -1; - } + /* set up some global information - indicating device specific info */ blk_init_queue(&ps2esdi_queue, do_ps2esdi_request, &ps2esdi_lock); diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c Sat Dec 14 09:40:55 2002 +++ b/drivers/block/rd.c Sat Mar 8 14:50:22 2003 @@ -409,8 +409,7 @@ goto out; } - if (register_blkdev(RAMDISK_MAJOR, "ramdisk", &rd_bd_op)) { - printk("RAMDISK: Could not get major %d", RAMDISK_MAJOR); + if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) { err = -EIO; goto out; } diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c --- a/drivers/block/swim3.c Thu Dec 5 07:57:01 2002 +++ b/drivers/block/swim3.c Sat Mar 8 14:50:22 2003 @@ -1004,9 +1004,7 @@ goto out; } - if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) { - printk(KERN_ERR"Unable to get major %d for floppy\n", - FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR, "fd")) { err = -EBUSY; goto out; } diff -Nru a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c --- a/drivers/block/swim_iop.c Mon Nov 11 03:13:21 2002 +++ b/drivers/block/swim_iop.c Sat Mar 8 14:50:22 2003 @@ -137,13 +137,12 @@ current_req = NULL; floppy_count = 0; - if (!iop_ism_present) return -ENODEV; + if (!iop_ism_present) + return -ENODEV; - if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) { - printk(KERN_ERR "SWIM-IOP: Unable to get major %d for floppy\n", - FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR, "fd")) return -EBUSY; - } + blk_init_queue(&swim_queue, do_fd_request, &swim_iop_lock); printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n", DRIVER_VERSION); diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c --- a/drivers/block/umem.c Fri Jan 10 17:00:19 2003 +++ b/drivers/block/umem.c Sat Mar 8 14:50:22 2003 @@ -1145,11 +1145,9 @@ if (retval) return -ENOMEM; - err = major_nr = register_blkdev(0, "umem", &mm_fops); - if (err < 0) { - printk(KERN_ERR "MM: Could not register block device\n"); + err = major_nr = register_blkdev(0, "umem"); + if (err < 0) return -EIO; - } for (i = 0; i < num_cards; i++) { mm_gendisk[i] = alloc_disk(1 << MM_SHIFT); diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c --- a/drivers/block/xd.c Thu Dec 5 07:53:02 2002 +++ b/drivers/block/xd.c Sat Mar 8 14:50:22 2003 @@ -154,9 +154,9 @@ #ifdef MODULE for (i = 4; i > 0; i--) - if(((xd[i] = xd[i-1]) >= 0) && !count) + if (((xd[i] = xd[i-1]) >= 0) && !count) count = i; - if((xd[0] = count)) + if ((xd[0] = count)) do_xd_setup(xd); #endif @@ -170,10 +170,9 @@ } err = -EBUSY; - if (register_blkdev(XT_DISK_MAJOR,"xd",&xd_fops)) { - printk("xd: Unable to get major number %d\n",XT_DISK_MAJOR); + if (register_blkdev(XT_DISK_MAJOR, "xd")) goto out1; - } + devfs_mk_dir(NULL, "xd", NULL); blk_init_queue(&xd_queue, do_xd_request, &xd_lock); if (xd_detect(&controller,&address)) { diff -Nru a/drivers/block/z2ram.c b/drivers/block/z2ram.c --- a/drivers/block/z2ram.c Wed Nov 6 08:13:59 2002 +++ b/drivers/block/z2ram.c Sat Mar 8 14:50:22 2003 @@ -331,21 +331,18 @@ static struct request_queue z2_queue; int __init -z2_init( void ) +z2_init(void) { - if ( !MACH_IS_AMIGA ) + if (!MACH_IS_AMIGA) return -ENXIO; - if ( register_blkdev( Z2RAM_MAJOR, DEVICE_NAME, &z2_fops ) ) - { - printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n", - Z2RAM_MAJOR ); + if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME)) return -EBUSY; - } + z2ram_gendisk = alloc_disk(1); if (!z2ram_gendisk) { - unregister_blkdev( Z2RAM_MAJOR, DEVICE_NAME ); + unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME); return -ENOMEM; } z2ram_gendisk->major = Z2RAM_MAJOR; diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c --- a/drivers/cdrom/aztcd.c Tue Dec 3 09:50:14 2002 +++ b/drivers/cdrom/aztcd.c Sat Mar 8 14:50:22 2003 @@ -1910,12 +1910,12 @@ azt_disk = alloc_disk(1); if (!azt_disk) goto err_out; - if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) { - printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech" - " CD-ROM\n", MAJOR_NR); + + if (register_blkdev(MAJOR_NR, "aztcd")) { ret = -EIO; goto err_out2; } + blk_init_queue(&azt_queue, do_aztcd_request, &aztSpin); blk_queue_hardsect_size(&azt_queue, 2048); azt_disk->major = MAJOR_NR; @@ -1931,7 +1931,7 @@ azt_invalidate_buffers(); aztPresent = 1; aztCloseDoor(); - return (0); + return 0; err_out2: put_disk(azt_disk); err_out: diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c --- a/drivers/cdrom/cdu31a.c Fri Oct 18 03:55:37 2002 +++ b/drivers/cdrom/cdu31a.c Sat Mar 8 14:50:22 2003 @@ -3368,11 +3368,8 @@ if (!request_region(cdu31a_port, 4, "cdu31a")) goto errout3; - if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) { - printk("Unable to get major %d for CDU-31a\n", - MAJOR_NR); + if (register_blkdev(MAJOR_NR, "cdu31a")) goto errout2; - } disk = alloc_disk(1); if (!disk) diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c --- a/drivers/cdrom/cm206.c Mon Nov 11 05:59:04 2002 +++ b/drivers/cdrom/cm206.c Sat Mar 8 14:50:22 2003 @@ -1489,10 +1489,10 @@ goto out_probe; } printk(".\n"); - if (register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) { - printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR); + + if (register_blkdev(MAJOR_NR, "cm206")) goto out_blkdev; - } + disk = alloc_disk(1); if (!disk) goto out_disk; diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c --- a/drivers/cdrom/gscd.c Sat Dec 7 18:57:27 2002 +++ b/drivers/cdrom/gscd.c Sat Mar 8 14:50:22 2003 @@ -959,12 +959,11 @@ gscd_disk->fops = &gscd_fops; sprintf(gscd_disk->disk_name, "gscd"); - if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) { - printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar " - "CD-ROM\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, "gscd")) { ret = -EIO; goto err_out2; } + devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL); diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c --- a/drivers/cdrom/mcd.c Sun Nov 17 11:28:18 2002 +++ b/drivers/cdrom/mcd.c Sat Mar 8 14:50:22 2003 @@ -1068,8 +1068,7 @@ put_disk(disk); return -EIO; } - if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) { - printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, "mcd")) { put_disk(disk); return -EIO; } diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c --- a/drivers/cdrom/mcdx.c Mon Nov 18 06:04:22 2002 +++ b/drivers/cdrom/mcdx.c Sat Mar 8 14:50:22 2003 @@ -1193,11 +1193,9 @@ } xtrace(INIT, "init() register blkdev\n"); - if (register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) { + if (register_blkdev(MAJOR_NR, "mcdx")) { release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE); - xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n", - MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR); kfree(stuffp); put_disk(disk); return 1; diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c --- a/drivers/cdrom/optcd.c Sun Nov 17 23:09:33 2002 +++ b/drivers/cdrom/optcd.c Sat Mar 8 14:50:22 2003 @@ -2047,8 +2047,7 @@ put_disk(optcd_disk); return -EIO; } - if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) { - printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, "optcd")) { release_region(optcd_port, 4); put_disk(optcd_disk); return -EIO; diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c --- a/drivers/cdrom/sbpcd.c Mon Feb 24 12:16:14 2003 +++ b/drivers/cdrom/sbpcd.c Sat Mar 8 14:50:22 2003 @@ -5795,15 +5795,14 @@ OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ #endif /* SOUND_BASE */ - if (register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0) - { - msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, major_name)) { #ifdef MODULE return -EIO; #else goto init_done; #endif /* MODULE */ } + blk_init_queue(&sbpcd_queue, do_sbpcd_request, &sbpcd_lock); devfs_mk_dir (NULL, "sbp", NULL); diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c --- a/drivers/cdrom/sjcd.c Fri Nov 15 11:38:00 2002 +++ b/drivers/cdrom/sjcd.c Sat Mar 8 14:50:22 2003 @@ -1677,11 +1677,8 @@ printk("SJCD: sjcd=0x%x: ", sjcd_base); #endif - if (register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) { - printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n", - MAJOR_NR); - return (-EIO); - } + if (register_blkdev(MAJOR_NR, "sjcd")) + return -EIO; blk_init_queue(&sjcd_queue, do_sjcd_request, &sjcd_lock); blk_queue_hardsect_size(&sjcd_queue, 2048); diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c --- a/drivers/cdrom/sonycd535.c Mon Dec 30 20:26:12 2002 +++ b/drivers/cdrom/sonycd535.c Sat Mar 8 14:50:22 2003 @@ -1546,9 +1546,7 @@ printk("IRQ%d, ", tmp_irq); printk("using %d byte buffer\n", sony_buffer_size); - if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { - printk("Unable to get major %d for %s\n", - MAJOR_NR, CDU535_MESSAGE_NAME); + if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) { err = -EIO; goto out1; } diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c --- a/drivers/char/amiserial.c Mon Feb 3 05:47:46 2003 +++ b/drivers/char/amiserial.c Mon Mar 3 12:04:08 2003 @@ -2320,10 +2320,11 @@ /* * Register console. */ -void __init serial_console_init(void) +static void __init amiserial_console_init(void) { register_console(&sercons); } +console_initcall(amiserial_console_init); #endif MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/decserial.c b/drivers/char/decserial.c --- a/drivers/char/decserial.c Mon Feb 4 23:45:05 2002 +++ b/drivers/char/decserial.c Fri Feb 14 15:14:03 2003 @@ -75,7 +75,7 @@ /* serial_console_init handles the special case of starting * up the console on the serial port */ -void __init serial_console_init(void) +static void __init decserial_console_init(void) { #if defined(CONFIG_ZS) && defined(CONFIG_DZ) if (IOASIC) @@ -94,5 +94,6 @@ #endif } +console_initcall(decserial_console_init); #endif diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c --- a/drivers/char/hvc_console.c Tue Feb 11 14:57:50 2003 +++ b/drivers/char/hvc_console.c Fri Feb 14 15:14:16 2003 @@ -346,11 +346,12 @@ .index = -1, }; -int __init hvc_console_init(void) +static int __init hvc_console_init(void) { register_console(&hvc_con_driver); return 0; } +console_initcall(hvc_console_init); module_init(hvc_init); module_exit(hvc_exit); diff -Nru a/drivers/char/random.c b/drivers/char/random.c --- a/drivers/char/random.c Mon Feb 17 14:45:20 2003 +++ b/drivers/char/random.c Mon Mar 3 04:08:26 2003 @@ -1228,10 +1228,8 @@ * at which point we do a "catastrophic reseeding". */ static inline void xfer_secondary_pool(struct entropy_store *r, - size_t nbytes) + size_t nbytes, __u32 *tmp) { - __u32 tmp[TMP_BUF_SIZE]; - if (r->entropy_count < nbytes * 8 && r->entropy_count < r->poolinfo.POOLBITS) { int nwords = min_t(int, @@ -1284,7 +1282,7 @@ r->entropy_count = r->poolinfo.POOLBITS; if (flags & EXTRACT_ENTROPY_SECONDARY) - xfer_secondary_pool(r, nbytes); + xfer_secondary_pool(r, nbytes, tmp); DEBUG_ENT("%s has %d bits, want %d bits\n", r == sec_random_state ? "secondary" : diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c --- a/drivers/char/raw.c Tue Jan 7 14:52:26 2003 +++ b/drivers/char/raw.c Sat Mar 8 14:50:48 2003 @@ -19,14 +19,16 @@ #include +#define MAX_RAW_MINORS 256 + struct raw_device_data { struct block_device *binding; int inuse; }; -static struct raw_device_data raw_devices[256]; +static struct raw_device_data raw_devices[MAX_RAW_MINORS]; static DECLARE_MUTEX(raw_mutex); -static struct file_operations raw_ctl_fops; +static struct file_operations raw_ctl_fops; /* forward declaration */ /* * Open/close code for raw IO. @@ -85,11 +87,16 @@ { const int minor= minor(inode->i_rdev); struct block_device *bdev; - + down(&raw_mutex); bdev = raw_devices[minor].binding; raw_devices[minor].inuse--; up(&raw_mutex); + + /* Here inode->i_mapping == bdev->bd_inode->i_mapping */ + inode->i_mapping = &inode->i_data; + inode->i_mapping->backing_dev_info = &default_backing_dev_info; + bd_release(bdev); blkdev_put(bdev, BDEV_RAW); return 0; @@ -130,11 +137,13 @@ goto out; err = -EINVAL; - if (rq.raw_minor < 0 || rq.raw_minor > MINORMASK) + if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS) goto out; rawdev = &raw_devices[rq.raw_minor]; if (command == RAW_SETBIND) { + dev_t dev; + /* * This is like making block devices, so demand the * same capability @@ -151,9 +160,10 @@ */ err = -EINVAL; + dev = MKDEV(rq.block_major, rq.block_minor); if ((rq.block_major == 0 && rq.block_minor != 0) || - rq.block_major > MAX_BLKDEV || - rq.block_minor > MINORMASK) + MAJOR(dev) != rq.block_major || + MINOR(dev) != rq.block_minor) goto out; down(&raw_mutex); @@ -170,10 +180,7 @@ /* unbind */ rawdev->binding = NULL; } else { - kdev_t kdev; - - kdev = mk_kdev(rq.block_major, rq.block_minor); - rawdev->binding = bdget(kdev_t_to_nr(kdev)); + rawdev->binding = bdget(dev); MOD_INC_USE_COUNT; } up(&raw_mutex); diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c --- a/drivers/char/rio/rio_linux.c Tue Feb 25 02:08:22 2003 +++ b/drivers/char/rio/rio_linux.c Thu Mar 6 09:17:26 2003 @@ -59,7 +59,6 @@ #include #include -#include #include #if BITS_PER_LONG != 32 @@ -725,14 +724,14 @@ switch (cmd) { #if 0 case TIOCGSOFTCAR: - rc = Put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), + rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned int *) arg); break; #endif case TIOCSSOFTCAR: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(int))) == 0) { - Get_user(ival, (unsigned int *) arg); + get_user(ival, (unsigned int *) arg); tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); @@ -784,7 +783,7 @@ case TIOCMBIS: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { - Get_user(ival, (unsigned int *) arg); + get_user(ival, (unsigned int *) arg); rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), ((ival & TIOCM_RTS) ? 1 : -1)); } @@ -792,7 +791,7 @@ case TIOCMBIC: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { - Get_user(ival, (unsigned int *) arg); + get_user(ival, (unsigned int *) arg); rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), ((ival & TIOCM_RTS) ? 0 : -1)); } @@ -800,7 +799,7 @@ case TIOCMSET: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { - Get_user(ival, (unsigned int *) arg); + get_user(ival, (unsigned int *) arg); rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), ((ival & TIOCM_RTS) ? 1 : 0)); } @@ -1126,7 +1125,7 @@ t, CNTRL_REG_GOODVALUE); writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); } - my_iounmap (hwbase, rebase); + iounmap((char*) rebase); } #endif @@ -1201,7 +1200,7 @@ hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; - hp->Ivec = get_irq (pdev); + hp->Ivec = pdev->irq; if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; hp->CardP = (struct DpRam *) @@ -1234,8 +1233,7 @@ p->RIONumHosts++; found++; } else { - my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, - p->RIOHosts[p->RIONumHosts].Caddr); + iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr)); } #ifdef TWO_ZERO @@ -1272,7 +1270,7 @@ hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; - hp->Ivec = get_irq (pdev); + hp->Ivec = pdev->irq; if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; hp->Ivec |= 0x8000; /* Mark as non-sharable */ @@ -1307,8 +1305,7 @@ p->RIONumHosts++; found++; } else { - my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, - p->RIOHosts[p->RIONumHosts].Caddr); + iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr)); } #else printk (KERN_ERR "Found an older RIO PCI card, but the driver is not " @@ -1361,7 +1358,7 @@ } if (!okboard) - my_iounmap (hp->PaddrP, hp->Caddr); + iounmap ((char*) (hp->Caddr)); } } diff -Nru a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c --- a/drivers/char/rio/rioboot.c Sat Feb 15 13:50:01 2003 +++ b/drivers/char/rio/rioboot.c Sun Feb 16 16:15:30 2003 @@ -48,7 +48,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c --- a/drivers/char/rio/riocmd.c Thu Nov 21 09:58:01 2002 +++ b/drivers/char/rio/riocmd.c Sun Feb 16 16:15:30 2003 @@ -47,7 +47,6 @@ #include #include -#include #include #include "linux_compat.h" diff -Nru a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c --- a/drivers/char/rio/rioctrl.c Tue Dec 3 13:17:27 2002 +++ b/drivers/char/rio/rioctrl.c Sun Feb 16 16:15:30 2003 @@ -47,7 +47,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c --- a/drivers/char/rio/rioinit.c Tue Feb 25 09:44:30 2003 +++ b/drivers/char/rio/rioinit.c Thu Mar 6 09:17:26 2003 @@ -47,7 +47,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c --- a/drivers/char/rio/riointr.c Mon Feb 4 23:45:07 2002 +++ b/drivers/char/rio/riointr.c Sun Feb 16 16:15:30 2003 @@ -48,7 +48,6 @@ #include #include -#include #include #include diff -Nru a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c --- a/drivers/char/rio/rioparam.c Mon Feb 24 12:42:23 2003 +++ b/drivers/char/rio/rioparam.c Thu Mar 6 09:17:26 2003 @@ -48,7 +48,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c --- a/drivers/char/rio/rioroute.c Tue Feb 25 11:05:23 2003 +++ b/drivers/char/rio/rioroute.c Thu Mar 6 09:17:26 2003 @@ -46,7 +46,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c --- a/drivers/char/rio/riotable.c Tue Feb 25 11:05:23 2003 +++ b/drivers/char/rio/riotable.c Thu Mar 6 09:17:26 2003 @@ -48,7 +48,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c --- a/drivers/char/rio/riotty.c Tue Feb 25 02:17:56 2003 +++ b/drivers/char/rio/riotty.c Thu Mar 6 09:17:26 2003 @@ -51,7 +51,6 @@ #include -#include #include diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c --- a/drivers/char/rtc.c Sat Feb 15 04:17:36 2003 +++ b/drivers/char/rtc.c Thu Mar 6 08:17:53 2003 @@ -152,6 +152,9 @@ static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */ #if RTC_IRQ +/* + * rtc_task_lock nests inside rtc_lock. + */ static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED; static rtc_task_t *rtc_callback = NULL; #endif @@ -746,13 +749,15 @@ #else unsigned char tmp; - spin_lock_irq(&rtc_task_lock); + spin_lock_irq(&rtc_lock); + spin_lock(&rtc_task_lock); if (rtc_callback != task) { - spin_unlock_irq(&rtc_task_lock); + spin_unlock(&rtc_task_lock); + spin_unlock_irq(&rtc_lock); return -ENXIO; } rtc_callback = NULL; - spin_lock(&rtc_lock); + /* disable controls */ tmp = CMOS_READ(RTC_CONTROL); tmp &= ~RTC_PIE; @@ -765,8 +770,8 @@ del_timer(&rtc_irq_timer); } rtc_status &= ~RTC_IS_OPEN; - spin_unlock(&rtc_lock); - spin_unlock_irq(&rtc_task_lock); + spin_unlock(&rtc_task_lock); + spin_unlock_irq(&rtc_lock); return 0; #endif } diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c --- a/drivers/char/serial167.c Mon Nov 11 03:13:26 2002 +++ b/drivers/char/serial167.c Fri Feb 14 15:16:47 2003 @@ -2836,7 +2836,7 @@ }; -void __init serial167_console_init(void) +static void __init serial167_console_init(void) { if (vme_brdtype == VME_TYPE_MVME166 || vme_brdtype == VME_TYPE_MVME167 || @@ -2845,6 +2845,7 @@ register_console(&sercons); } } +console_initcall(serial167_console_init); #ifdef CONFIG_REMOTE_DEBUG void putDebugChar (int c) diff -Nru a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c --- a/drivers/char/serial_tx3912.c Tue Nov 5 07:39:55 2002 +++ b/drivers/char/serial_tx3912.c Fri Feb 14 15:16:47 2003 @@ -1054,9 +1054,10 @@ .index = -1 }; -void __init tx3912_console_init(void) +static void __init tx3912_console_init(void) { register_console(&sercons); } +console_initcall(tx3912_console_init); #endif diff -Nru a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c --- a/drivers/char/sh-sci.c Tue Nov 5 07:39:53 2002 +++ b/drivers/char/sh-sci.c Fri Feb 14 15:16:47 2003 @@ -1275,7 +1275,7 @@ extern void sh_console_unregister (void); #endif -void __init sci_console_init(void) +static void __init sci_console_init(void) { register_console(&sercons); #ifdef CONFIG_SH_EARLY_PRINTK @@ -1285,4 +1285,6 @@ sh_console_unregister(); #endif } +console_initcall(sci_console_init); + #endif /* CONFIG_SERIAL_CONSOLE */ diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Mon Mar 3 08:49:44 2003 +++ b/drivers/char/tty_io.c Thu Mar 6 09:17:26 2003 @@ -113,7 +113,15 @@ #define TTY_PARANOIA_CHECK 1 #define CHECK_TTY_COUNT 1 -struct termios tty_std_termios; /* for the benefit of tty drivers */ +struct termios tty_std_termios = { /* for the benefit of tty drivers */ + .c_iflag = ICRNL | IXON, + .c_oflag = OPOST | ONLCR, + .c_cflag = B38400 | CS8 | CREAD | HUPCL, + .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | + ECHOCTL | ECHOKE | IEXTEN, + .c_cc = INIT_C_CC +}; + LIST_HEAD(tty_drivers); /* linked list of tty drivers */ struct tty_ldisc ldiscs[NR_LDISCS]; /* line disc dispatch table */ @@ -141,26 +149,13 @@ unsigned int cmd, unsigned long arg); static int tty_fasync(int fd, struct file * filp, int on); extern int vme_scc_init (void); -extern long vme_scc_console_init(void); extern int serial167_init(void); -extern long serial167_console_init(void); -extern void console_8xx_init(void); extern int rs_8xx_init(void); -extern void mac_scc_console_init(void); -extern void sclp_console_init(void); -extern void sclp_tty_init(void); -extern void con3215_init(void); -extern void tub3270_con_init(void); +extern void hwc_tty_init(void); +extern void tty3215_init(void); extern void tub3270_init(void); -extern void uart_console_init(void); -extern void sgi_serial_console_init(void); -extern void sci_console_init(void); -extern void m68328_console_init(void); -extern void mcfrs_console_init(void); extern void rs_360_init(void); -extern void tx3912_console_init(void); extern void tx3912_rs_init(void); -extern void hvc_console_init(void); static struct tty_struct *alloc_tty_struct(void) { @@ -306,13 +301,9 @@ if (tty->ldisc.open) retval = (tty->ldisc.open)(tty); if (retval < 0) { - module_put(tty->ldisc.owner); - tty->ldisc = o_ldisc; tty->termios->c_line = tty->ldisc.num; if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) { - module_put(tty->ldisc.owner); - tty->ldisc = ldiscs[N_TTY]; tty->termios->c_line = N_TTY; if (tty->ldisc.open) { @@ -2206,91 +2197,28 @@ */ void __init console_init(void) { + initcall_t *call; + /* Setup the default TTY line discipline. */ - memset(ldiscs, 0, sizeof(ldiscs)); (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); /* - * Set up the standard termios. Individual tty drivers may - * deviate from this; this is used as a template. - */ - memset(&tty_std_termios, 0, sizeof(struct termios)); - memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS); - tty_std_termios.c_iflag = ICRNL | IXON; - tty_std_termios.c_oflag = OPOST | ONLCR; - tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL; - tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | - ECHOCTL | ECHOKE | IEXTEN; - - /* * set up the console device so that later boot sequences can * inform about problems etc.. */ #ifdef CONFIG_EARLY_PRINTK disable_early_printk(); #endif -#ifdef CONFIG_VT - con_init(); -#endif -#ifdef CONFIG_AU1000_SERIAL_CONSOLE - au1000_serial_console_init(); -#endif -#ifdef CONFIG_SERIAL_CONSOLE -#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) - console_8xx_init(); -#elif defined(CONFIG_MAC_SERIAL) - mac_scc_console_init(); -#elif defined(CONFIG_PARISC) - pdc_console_init(); -#elif defined(CONFIG_SERIAL) - serial_console_init(); -#endif /* CONFIG_8xx */ -#ifdef CONFIG_SGI_SERIAL - sgi_serial_console_init(); -#endif -#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC) - vme_scc_console_init(); -#endif -#if defined(CONFIG_SERIAL167) - serial167_console_init(); -#endif -#if defined(CONFIG_SH_SCI) - sci_console_init(); -#endif -#endif -#ifdef CONFIG_TN3270_CONSOLE - tub3270_con_init(); -#endif -#ifdef CONFIG_TN3215_CONSOLE - con3215_init(); -#endif -#ifdef CONFIG_SCLP_CONSOLE - sclp_console_init(); -#endif -#ifdef CONFIG_STDIO_CONSOLE - stdio_console_init(); -#endif -#ifdef CONFIG_SERIAL_CORE_CONSOLE - uart_console_init(); -#endif -#ifdef CONFIG_ARC_CONSOLE - arc_console_init(); -#endif -#ifdef CONFIG_SERIAL_68328 - m68328_console_init(); -#endif -#ifdef CONFIG_SERIAL_COLDFIRE - mcfrs_console_init(); -#endif #ifdef CONFIG_SERIAL_68360 - rs_360_init(); -#endif -#ifdef CONFIG_SERIAL_TX3912_CONSOLE - tx3912_console_init(); -#endif -#ifdef CONFIG_HVC_CONSOLE - hvc_console_init(); -#endif + /* This is not a console initcall. I know not what it's doing here. + So I haven't moved it. dwmw2 */ + rs_360_init(); +#endif + call = &__con_initcall_start; + while (call < &__con_initcall_end) { + (*call)(); + call++; + } } static struct tty_driver dev_tty_driver, dev_syscons_driver; diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c --- a/drivers/char/vme_scc.c Thu Nov 7 15:06:42 2002 +++ b/drivers/char/vme_scc.c Fri Feb 14 15:18:33 2003 @@ -1091,7 +1091,7 @@ }; -void __init vme_scc_console_init(void) +static void __init vme_scc_console_init(void) { if (vme_brdtype == VME_TYPE_MVME147 || vme_brdtype == VME_TYPE_MVME162 || @@ -1100,4 +1100,4 @@ vme_brdtype == VME_TYPE_BVME6000) register_console(&sercons); } - +console_initcall(vme_scc_console_init); diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c Tue Feb 25 09:17:44 2003 +++ b/drivers/char/vt.c Fri Mar 7 11:25:45 2003 @@ -747,8 +747,10 @@ screenbuf_size = new_screen_size; err = resize_screen(currcons, new_cols, new_rows); - if (err) + if (err) { + kfree(newscreen); return err; + } rlth = min(old_row_size, new_row_size); rrem = new_row_size - rlth; @@ -2443,7 +2445,7 @@ struct tty_driver console_driver; static int console_refcount; -void __init con_init(void) +static int __init con_init(void) { const char *display_desc = NULL; unsigned int currcons = 0; @@ -2452,7 +2454,7 @@ display_desc = conswitchp->con_startup(); if (!display_desc) { fg_console = 0; - return; + return 0; } init_timer(&console_timer); @@ -2491,7 +2493,9 @@ #ifdef CONFIG_VT_CONSOLE register_console(&vt_console_driver); #endif + return 0; } +console_initcall(con_init); int __init vty_init(void) { diff -Nru a/drivers/char/watchdog/amd7xx_tco.c b/drivers/char/watchdog/amd7xx_tco.c --- a/drivers/char/watchdog/amd7xx_tco.c Thu Feb 27 17:28:13 2003 +++ b/drivers/char/watchdog/amd7xx_tco.c Sat Mar 8 02:46:43 2003 @@ -1,6 +1,6 @@ /* * AMD 766/768 TCO Timer Driver - * (c) Copyright 2002 Zwane Mwaikambo + * (c) Copyright 2002 Zwane Mwaikambo * All Rights Reserved. * * Parts from; @@ -34,35 +34,48 @@ #include #include -#define AMDTCO_MODULE_VER "build 20020601" +#define AMDTCO_MODULE_VER "build 20021116" #define AMDTCO_MODULE_NAME "amd7xx_tco" #define PFX AMDTCO_MODULE_NAME ": " -#define MAX_TIMEOUT 38 /* max of 38 seconds */ +#define MAX_TIMEOUT 38 /* max of 38 seconds, although the system will only + * reset itself after the second timeout */ /* pmbase registers */ -#define GLOBAL_SMI_REG 0x2a -#define TCO_EN (1 << 1) /* bit 1 in global SMI register */ #define TCO_RELOAD_REG 0x40 /* bits 0-5 are current count, 6-7 are reserved */ #define TCO_INITVAL_REG 0x41 /* bits 0-5 are value to load, 6-7 are reserved */ #define TCO_TIMEOUT_MASK 0x3f +#define TCO_STATUS1_REG 0x44 #define TCO_STATUS2_REG 0x46 #define NDTO_STS2 (1 << 1) /* we're interested in the second timeout */ #define BOOT_STS (1 << 2) /* will be set if NDTO_STS2 was set before reboot */ #define TCO_CTRL1_REG 0x48 #define TCO_HALT (1 << 11) +#define NO_REBOOT (1 << 10) /* in DevB:3x48 */ -static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER; -static int timeout = 38; +static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER "\n"; +static int timeout = MAX_TIMEOUT; static u32 pmbase; /* PMxx I/O base */ static struct pci_dev *dev; static struct semaphore open_sem; -spinlock_t amdtco_lock; /* only for device access */ +static spinlock_t amdtco_lock; /* only for device access */ static int expect_close = 0; MODULE_PARM(timeout, "i"); MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38"); +static inline u8 seconds_to_ticks(int seconds) +{ + /* the internal timer is stored as ticks which decrement + * every 0.6 seconds */ + return (seconds * 10) / 6; +} + +static inline int ticks_to_seconds(u8 ticks) +{ + return (ticks * 6) / 10; +} + static inline int amdtco_status(void) { u16 reg; @@ -81,28 +94,19 @@ static inline void amdtco_ping(void) { - u8 reg; - - spin_lock(&amdtco_lock); - reg = inb(pmbase+TCO_RELOAD_REG); - outb(1 | reg, pmbase+TCO_RELOAD_REG); - spin_unlock(&amdtco_lock); + outb(1, pmbase+TCO_RELOAD_REG); } static inline int amdtco_gettimeout(void) { - return inb(TCO_RELOAD_REG) & TCO_TIMEOUT_MASK; + u8 reg = inb(pmbase+TCO_RELOAD_REG) & TCO_TIMEOUT_MASK; + return ticks_to_seconds(reg); } static inline void amdtco_settimeout(unsigned int timeout) { - u8 reg; - - spin_lock(&amdtco_lock); - reg = inb(pmbase+TCO_INITVAL_REG); - reg |= timeout & TCO_TIMEOUT_MASK; + u8 reg = seconds_to_ticks(timeout) & TCO_TIMEOUT_MASK; outb(reg, pmbase+TCO_INITVAL_REG); - spin_unlock(&amdtco_lock); } static inline void amdtco_global_enable(void) @@ -110,9 +114,12 @@ u16 reg; spin_lock(&amdtco_lock); - reg = inw(pmbase+GLOBAL_SMI_REG); - reg |= TCO_EN; - outw(reg, pmbase+GLOBAL_SMI_REG); + + /* clear NO_REBOOT on DevB:3x48 p97 */ + pci_read_config_word(dev, 0x48, ®); + reg &= ~NO_REBOOT; + pci_write_config_word(dev, 0x48, reg); + spin_unlock(&amdtco_lock); } @@ -146,10 +153,12 @@ if (timeout > MAX_TIMEOUT) timeout = MAX_TIMEOUT; + amdtco_disable(); amdtco_settimeout(timeout); amdtco_global_enable(); + amdtco_enable(); amdtco_ping(); - printk(KERN_INFO PFX "Watchdog enabled, timeout = %d/%d seconds", + printk(KERN_INFO PFX "Watchdog enabled, timeout = %ds of %ds\n", amdtco_gettimeout(), timeout); return 0; @@ -198,7 +207,7 @@ case WDIOC_GETTIMEOUT: return put_user(amdtco_gettimeout(), (int *)arg); - + case WDIOC_SETOPTIONS: if (copy_from_user(&tmp, (int *)arg, sizeof tmp)) return -EFAULT; @@ -221,7 +230,7 @@ printk(KERN_INFO PFX "Watchdog disabled\n"); } else { amdtco_ping(); - printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds)\n", timeout); + printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds\n", timeout); } up(&open_sem); @@ -249,10 +258,9 @@ } #endif amdtco_ping(); - return len; } - return 0; + return len; } @@ -357,6 +365,9 @@ if (ints[0] > 0) timeout = ints[1]; + if (!timeout || timeout > MAX_TIMEOUT) + timeout = MAX_TIMEOUT; + return 1; } @@ -366,8 +377,7 @@ module_init(amdtco_init); module_exit(amdtco_exit); -MODULE_AUTHOR("Zwane Mwaikambo "); +MODULE_AUTHOR("Zwane Mwaikambo "); MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver"); MODULE_LICENSE("GPL"); -EXPORT_NO_SYMBOLS; diff -Nru a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c --- a/drivers/cpufreq/freq_table.c Sat Feb 15 01:16:27 2003 +++ b/drivers/cpufreq/freq_table.c Sat Mar 8 01:39:17 2003 @@ -77,56 +77,6 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); -int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table, - unsigned int *index) -{ - struct cpufreq_frequency_table optimal = { .index = ~0, }; - unsigned int i; - - switch (policy->policy) { - case CPUFREQ_POLICY_PERFORMANCE: - optimal.frequency = 0; - break; - case CPUFREQ_POLICY_POWERSAVE: - optimal.frequency = ~0; - break; - } - - if (!cpu_online(policy->cpu)) - return -EINVAL; - - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { - unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - if ((freq < policy->min) || (freq > policy->max)) - continue; - switch(policy->policy) { - case CPUFREQ_POLICY_PERFORMANCE: - if (optimal.frequency <= freq) { - optimal.frequency = freq; - optimal.index = i; - } - break; - case CPUFREQ_POLICY_POWERSAVE: - if (optimal.frequency >= freq) { - optimal.frequency = freq; - optimal.index = i; - } - break; - } - } - if (optimal.index > i) - return -EINVAL; - - *index = optimal.index; - - return 0; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy); - - int cpufreq_frequency_table_target(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table, unsigned int target_freq, @@ -196,6 +146,56 @@ return 0; } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); + +static struct cpufreq_frequency_table *show_table[NR_CPUS]; +/** + * show_scaling_governor - show the current policy for the specified CPU + */ +static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) +{ + unsigned int i = 0; + unsigned int cpu = policy->cpu; + ssize_t count = 0; + struct cpufreq_frequency_table *table; + + if (!show_table[cpu]) + return -ENODEV; + + table = show_table[cpu]; + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + if (table[i].frequency == CPUFREQ_ENTRY_INVALID) + continue; + count += sprintf(&buf[count], "%d ", table[i].frequency); + } + count += sprintf(&buf[count], "\n"); + + return count; + +} + +struct freq_attr cpufreq_freq_attr_scaling_available_freqs = { + .attr = { .name = "scaling_available_frequencies", .mode = 0444 }, + .show = show_available_freqs, +}; +EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); + +/* + * if you use these, you must assure that the frequency table is valid + * all the time between get_attr and put_attr! + */ +void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, + unsigned int cpu) +{ + show_table[cpu] = table; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr); + +void cpufreq_frequency_table_put_attr(unsigned int cpu) +{ + show_table[cpu] = NULL; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr); MODULE_AUTHOR ("Dominik Brodowski "); diff -Nru a/drivers/cpufreq/userspace.c b/drivers/cpufreq/userspace.c --- a/drivers/cpufreq/userspace.c Sun Feb 16 05:23:39 2003 +++ b/drivers/cpufreq/userspace.c Sat Mar 8 01:37:35 2003 @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -112,7 +113,7 @@ if (freq > cpu_max_freq[cpu]) freq = cpu_max_freq[cpu]; - ret = cpufreq_driver_target_l(¤t_policy[cpu], freq, + ret = cpufreq_driver_target(¤t_policy[cpu], freq, CPUFREQ_RELATION_L); err: @@ -465,23 +466,14 @@ /************************** sysfs interface ************************/ -static inline int to_cpu_nr (struct device *dev) +static ssize_t show_speed (struct cpufreq_policy *policy, char *buf) { - struct sys_device * cpu_sys_dev = container_of(dev, struct sys_device, dev); - return (cpu_sys_dev->id); -} - -static ssize_t show_speed (struct device *dev, char *buf) -{ - unsigned int cpu = to_cpu_nr(dev); - - return sprintf (buf, "%u\n", cpu_cur_freq[cpu]); + return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]); } static ssize_t -store_speed (struct device *dev, const char *buf, size_t count) +store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) { - unsigned int cpu = to_cpu_nr(dev); unsigned int freq = 0; unsigned int ret; @@ -489,13 +481,16 @@ if (ret != 1) return -EINVAL; - cpufreq_set(freq, cpu); + cpufreq_set(freq, policy->cpu); return count; } -static DEVICE_ATTR(scaling_setspeed, (S_IRUGO | S_IWUSR), show_speed, store_speed); - +static struct freq_attr freq_attr_scaling_setspeed = { + .attr = { .name = "scaling_setspeed", .mode = 0644 }, + .show = show_speed, + .store = store_speed, +}; static int cpufreq_governor_userspace(struct cpufreq_policy *policy, unsigned int event) @@ -511,7 +506,7 @@ cpu_min_freq[cpu] = policy->min; cpu_max_freq[cpu] = policy->max; cpu_cur_freq[cpu] = policy->cur; - device_create_file (policy->intf.dev, &dev_attr_scaling_setspeed); + sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); up(&userspace_sem); break; @@ -520,7 +515,7 @@ cpu_is_managed[cpu] = 0; cpu_min_freq[cpu] = 0; cpu_max_freq[cpu] = 0; - device_remove_file (policy->intf.dev, &dev_attr_scaling_setspeed); + sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); up(&userspace_sem); module_put(THIS_MODULE); break; diff -Nru a/drivers/hotplug/acpiphp_glue.c b/drivers/hotplug/acpiphp_glue.c --- a/drivers/hotplug/acpiphp_glue.c Thu Feb 27 16:27:27 2003 +++ b/drivers/hotplug/acpiphp_glue.c Mon Feb 24 03:28:46 2003 @@ -801,7 +801,7 @@ static int enable_device (struct acpiphp_slot *slot) { u8 bus; - struct pci_dev dev0, *dev; + struct pci_dev *dev; struct pci_bus *child; struct list_head *l; struct acpiphp_func *func; @@ -824,16 +824,8 @@ if (retval) goto err_exit; - memset(&dev0, 0, sizeof (struct pci_dev)); - - dev0.bus = slot->bridge->pci_bus; - dev0.devfn = PCI_DEVFN(slot->device, 0); - dev0.sysdata = dev0.bus->sysdata; - dev0.dev.parent = dev0.bus->dev; - dev0.dev.bus = &pci_bus_type; - /* returned `dev' is the *first function* only! */ - dev = pci_scan_slot (&dev0); + dev = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0)); if (!dev) { err("No new device found\n"); diff -Nru a/drivers/hotplug/cpci_hotplug_pci.c b/drivers/hotplug/cpci_hotplug_pci.c --- a/drivers/hotplug/cpci_hotplug_pci.c Mon Feb 24 08:17:14 2003 +++ b/drivers/hotplug/cpci_hotplug_pci.c Mon Feb 24 03:29:36 2003 @@ -574,19 +574,13 @@ /* Still NULL? Well then scan for it! */ if(slot->dev == NULL) { - struct pci_dev dev0; - dbg("pci_dev still null"); - memset(&dev0, 0, sizeof (struct pci_dev)); - dev0.bus = slot->bus; - dev0.devfn = slot->devfn; - dev0.sysdata = slot->bus->self->sysdata; /* * This will generate pci_dev structures for all functions, but * we will only call this case when lookup fails. */ - slot->dev = pci_scan_slot(&dev0); + slot->dev = pci_scan_slot(slot->bus, slot->devfn); if(slot->dev == NULL) { err("Could not find PCI device for slot %02x", slot->number); return 0; diff -Nru a/drivers/hotplug/cpqphp_pci.c b/drivers/hotplug/cpqphp_pci.c --- a/drivers/hotplug/cpqphp_pci.c Mon Feb 24 08:17:34 2003 +++ b/drivers/hotplug/cpqphp_pci.c Mon Feb 24 03:31:07 2003 @@ -84,24 +84,19 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) { unsigned char bus; - struct pci_dev dev0; struct pci_bus *child; int rc = 0; - memset(&dev0, 0, sizeof(struct pci_dev)); - if (func->pci_dev == NULL) func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7)); //Still NULL ? Well then scan for it ! if (func->pci_dev == NULL) { dbg("INFO: pci_dev still null\n"); - dev0.bus = ctrl->pci_dev->bus; - dev0.devfn = (func->device << 3) + (func->function & 0x7); - dev0.sysdata = ctrl->pci_dev->sysdata; //this will generate pci_dev structures for all functions, but we will only call this case when lookup fails - func->pci_dev = pci_scan_slot(&dev0); + func->pci_dev = pci_scan_slot(ctrl->pci_dev->bus, + (func->device << 3) + (func->function & 0x7)); if (func->pci_dev == NULL) { dbg("ERROR: pci_dev still null\n"); return 0; diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c --- a/drivers/hotplug/ibmphp_core.c Thu Feb 27 13:49:39 2003 +++ b/drivers/hotplug/ibmphp_core.c Mon Feb 24 03:32:11 2003 @@ -845,26 +845,22 @@ static int ibm_configure_device (struct pci_func *func) { unsigned char bus; - struct pci_dev dev0; struct pci_bus *child; int rc = 0; int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ - memset (&dev0, 0, sizeof (struct pci_dev)); - if (!(bus_structure_fixup (func->busno))) flag = 1; if (func->dev == NULL) func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7)); if (func->dev == NULL) { - dev0.bus = ibmphp_find_bus (func->busno); - if (!dev0.bus) + struct pci_bus *bus = ibmphp_find_bus (func->busno); + if (!bus) return 0; - dev0.devfn = ((func->device << 3) + (func->function & 0x7)); - dev0.sysdata = dev0.bus->sysdata; - func->dev = pci_scan_slot (&dev0); + func->dev = pci_scan_slot(bus, + (func->device << 3) + (func->function & 0x7)); if (func->dev == NULL) { err ("ERROR... : pci_dev still NULL \n"); diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c --- a/drivers/i2c/i2c-core.c Thu Feb 20 11:58:55 2003 +++ b/drivers/i2c/i2c-core.c Sat Mar 1 06:39:04 2003 @@ -68,22 +68,12 @@ /**** debug level */ static int i2c_debug; -/* --------------------------------------------------- - * /proc entry declarations - *---------------------------------------------------- - */ - #ifdef CONFIG_PROC_FS -static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, - loff_t *ppos); -static int read_bus_i2c(char *buf, char **start, off_t offset, int len, - int *eof , void *private); - -/* To implement the dynamic /proc/bus/i2c-? files, we need our own - implementation of the read hook */ -static struct file_operations i2cproc_operations = { - .read = i2cproc_bus_read, -}; +static int i2cproc_register(struct i2c_adapter *adap, int bus); +static void i2cproc_remove(int bus); +#else +# define i2cproc_register(adap, bus) 0 +# define i2cproc_remove(bus) do { } while (0) #endif /* CONFIG_PROC_FS */ @@ -109,8 +99,7 @@ printk(KERN_WARNING " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n", adap->name); - res = -ENOMEM; - goto ERROR0; + goto fail; } adapters[i] = adap; @@ -119,26 +108,9 @@ /* init data types */ init_MUTEX(&adap->lock); -#ifdef CONFIG_PROC_FS - { - char name[8]; - struct proc_dir_entry *proc_entry; - - sprintf(name,"i2c-%d", i); - - proc_entry = create_proc_entry(name,0,proc_bus); - if (! proc_entry) { - printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", - name); - res = -ENOENT; - goto ERROR1; - } - - proc_entry->proc_fops = &i2cproc_operations; - proc_entry->owner = THIS_MODULE; - adap->inode = proc_entry->low_ino; - } -#endif /* def CONFIG_PROC_FS */ + res = i2cproc_register(adap, i); + if (res) + return res; /* inform drivers of new adapters */ DRV_LOCK(); @@ -154,13 +126,9 @@ return 0; - -ERROR1: - ADAP_LOCK(); - adapters[i] = NULL; -ERROR0: + fail: ADAP_UNLOCK(); - return res; + return -ENOMEM; } @@ -214,13 +182,8 @@ goto ERROR0; } } -#ifdef CONFIG_PROC_FS - { - char name[8]; - sprintf(name,"i2c-%d", i); - remove_proc_entry(name, proc_bus); - } -#endif /* def CONFIG_PROC_FS */ + + i2cproc_remove(i); adapters[i] = NULL; @@ -501,10 +464,9 @@ */ #ifdef CONFIG_PROC_FS - /* This function generates the output for /proc/bus/i2c */ -int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof, - void *private) +static int read_bus_i2c(char *buf, char **start, off_t offset, + int len, int *eof, void *private) { int i; int nr = 0; @@ -529,10 +491,10 @@ } /* This function generates the output for /proc/bus/i2c-? */ -ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, - loff_t *ppos) +static ssize_t i2cproc_bus_read(struct file *file, char *buf, + size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; char *kbuf; struct i2c_client *client; int i,j,k,order_nr,len=0; @@ -593,6 +555,38 @@ return -ENOENT; } +static struct file_operations i2cproc_operations = { + .read = i2cproc_bus_read, +}; + +static int i2cproc_register(struct i2c_adapter *adap, int bus) +{ + struct proc_dir_entry *proc_entry; + char name[8]; + + sprintf(name, "i2c-%d", bus); + + proc_entry = create_proc_entry(name, 0, proc_bus); + if (!proc_entry) + goto fail; + + proc_entry->proc_fops = &i2cproc_operations; + proc_entry->owner = THIS_MODULE; + adap->inode = proc_entry->low_ino; + return 0; + fail: + printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", name); + return -ENOENT; +} + +static void i2cproc_remove(int bus) +{ + char name[8]; + + sprintf(name,"i2c-%d", bus); + remove_proc_entry(name, proc_bus); +} + static int i2cproc_init(void) { @@ -611,7 +605,6 @@ static void __exit i2cproc_cleanup(void) { - remove_proc_entry("i2c",proc_bus); } diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile --- a/drivers/ide/Makefile Wed Feb 19 09:48:49 2003 +++ b/drivers/ide/Makefile Mon Mar 3 12:06:45 2003 @@ -28,3 +28,4 @@ endif obj-$(CONFIG_BLK_DEV_IDE) += legacy/ ppc/ arm/ +obj-$(CONFIG_BLK_DEV_HD) += legacy/ diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Wed Nov 13 14:49:14 2002 +++ b/drivers/ide/ide-disk.c Tue Feb 18 10:06:17 2003 @@ -38,9 +38,11 @@ * Version 1.15 convert all calls to ide_raw_taskfile * since args will return register content. * Version 1.16 added suspend-resume-checkpower + * Version 1.17 do flush on standy, do flush on ATA < ATA6 + * fix wcache setup. */ -#define IDEDISK_VERSION "1.16" +#define IDEDISK_VERSION "1.17" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -140,7 +142,7 @@ static ide_startstop_t read_intr (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - int i = 0, nsect = 0, msect = drive->mult_count; + u32 i = 0, nsect = 0, msect = drive->mult_count; struct request *rq; unsigned long flags; u8 stat; @@ -157,7 +159,7 @@ ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } - + read_next: rq = HWGROUP(drive)->rq; if (msect) { @@ -203,7 +205,7 @@ ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); struct request *rq = hwgroup->rq; - int i = 0; + u32 i = 0; u8 stat; if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), @@ -506,14 +508,10 @@ if (drive->using_dma && !hwif->ide_dma_read(drive)) return ide_started; - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - command = ((drive->mult_count) ? ((lba48) ? WIN_MULTREAD_EXT : WIN_MULTREAD) : ((lba48) ? WIN_READ_EXT : WIN_READ)); - hwif->OUTB(command, IDE_COMMAND_REG); + ide_execute_command(drive, command, &read_intr, WAIT_CMD, NULL); return ide_started; } else if (rq_data_dir(rq) == WRITE) { ide_startstop_t startstop; @@ -628,11 +626,7 @@ static task_ioreg_t get_command (ide_drive_t *drive, int cmd) { - int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0; - -#if 1 - lba48bit = (drive->addressing == 1) ? 1 : 0; -#endif + int lba48bit = (drive->addressing == 1) ? 1 : 0; if ((cmd == READ) && drive->using_tcq) return lba48bit ? WIN_READDMA_QUEUED_EXT : WIN_READDMA_QUEUED; @@ -1412,32 +1406,6 @@ return call_idedisk_standby(drive, 0); } -#if 0 -static int call_idedisk_checkpower (ide_drive_t *drive, int arg) -{ - ide_task_t args; - u8 ckpw = (arg) ? WIN_CHECKPOWERMODE2 : WIN_CHECKPOWERMODE1; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_COMMAND_OFFSET] = ckpw; - args.command_type = ide_cmd_type_parser(&args); - ide_raw_taskfile(drive, &args, NULL); -#if 0 -if (errno != EIO || args[0] != 0 || args[1] != 0) - state = "unknown"; -else - state = "sleeping"; -} else { - state = (args[2] == 255) ? "active/idle" : "standby"; -#endif - return 0; -} - -static int do_idedisk_checkpower (ide_drive_t *drive) -{ - return call_idedisk_checkpower(drive, 0); -} -#endif - static int do_idedisk_flushcache (ide_drive_t *drive) { ide_task_t args; @@ -1596,13 +1564,8 @@ drive->doorlocking = 1; } } -#if 1 + (void) probe_lba_addressing(drive, 1); -#else - /* if using 48-bit addressing bump the request size up */ - if (probe_lba_addressing(drive, 1)) - blk_queue_max_sectors(&drive->queue, 2048); -#endif /* Extract geometry if we did not already have one for the drive */ if (!drive->cyl || !drive->head || !drive->sect) { @@ -1675,13 +1638,9 @@ static int idedisk_cleanup (ide_drive_t *drive) { + static int ide_cacheflush_p(ide_drive_t *drive); struct gendisk *g = drive->disk; - - do_idedisk_standby(drive); - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (do_idedisk_flushcache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); + ide_cacheflush_p(drive); if (ide_unregister_subdriver(drive)) return 1; del_gendisk(g); @@ -1725,6 +1684,7 @@ drive->usage++; if (drive->removable && drive->usage == 1) { ide_task_t args; + u8 cf; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK; args.command_type = ide_cmd_type_parser(&args); @@ -1736,6 +1696,32 @@ */ if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; + drive->wcache = 0; + /* Cache enabled ? */ + if (drive->id->csfo & 1) + drive->wcache = 1; + /* Cache command set available ? */ + if (drive->id->cfs_enable_1 & (1<<5)) + drive->wcache = 1; + /* ATA6 cache extended commands */ + cf = drive->id->command_set_2 >> 24; + if((cf & 0xC0) == 0x40 && (cf & 0x30) != 0) + drive->wcache = 1; + } + return 0; +} + +static int ide_cacheflush_p(ide_drive_t *drive) +{ + if(drive->wcache) + { + if (do_idedisk_flushcache(drive)) + { + printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", + drive->name); + return -EIO; + } + return 1; } return 0; } @@ -1752,10 +1738,7 @@ if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (do_idedisk_flushcache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); + ide_cacheflush_p(drive); drive->usage--; return 0; } diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c --- a/drivers/ide/ide-dma.c Tue Feb 25 02:43:50 2003 +++ b/drivers/ide/ide-dma.c Thu Mar 6 09:21:37 2003 @@ -664,11 +664,6 @@ if (drive->media != ide_disk) return 0; - /* paranoia check */ - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; if (drive->vdma) @@ -680,8 +675,7 @@ } /* issue cmd to drive */ - hwif->OUTB(command, IDE_COMMAND_REG); - + ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); return HWIF(drive)->ide_dma_count(drive); } @@ -702,11 +696,6 @@ if (drive->media != ide_disk) return 0; - /* paranoia check */ - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; if (drive->vdma) command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE; @@ -717,7 +706,7 @@ } /* issue cmd to drive */ - hwif->OUTB(command, IDE_COMMAND_REG); + ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); return HWIF(drive)->ide_dma_count(drive); } diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Tue Feb 18 10:06:17 2003 +++ b/drivers/ide/ide-floppy.c Tue Feb 18 10:06:17 2003 @@ -1077,14 +1077,11 @@ } if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, + /* Issue the packet command */ + ide_execute_command(drive, WIN_PACKETCMD, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); - /* Issue the packet command */ - HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); return ide_started; } else { /* Issue the packet command */ diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c Mon Feb 24 10:30:38 2003 +++ b/drivers/ide/ide-io.c Thu Mar 6 09:21:48 2003 @@ -358,18 +358,15 @@ * Issue a simple drive command with interrupts. * The drive must be selected beforehand. */ - + void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler) { ide_hwif_t *hwif = HWIF(drive); - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, handler, WAIT_CMD, NULL); if (IDE_CONTROL_REG) hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ SELECT_MASK(drive,0); hwif->OUTB(nsect,IDE_NSECTOR_REG); - hwif->OUTB(cmd,IDE_COMMAND_REG); + ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL); } EXPORT_SYMBOL(ide_cmd); @@ -841,14 +838,14 @@ * happens anyway when any interrupt comes in, IDE or otherwise * -- the kernel masks the IRQ while it is being handled. */ - if (masked_irq && hwif->irq != masked_irq) + if (hwif->irq != masked_irq) disable_irq_nosync(hwif->irq); spin_unlock(&ide_lock); local_irq_enable(); /* allow other IRQs while we start this request */ startstop = start_request(drive, rq); spin_lock_irq(&ide_lock); - if (masked_irq && hwif->irq != masked_irq) + if (hwif->irq != masked_irq) enable_irq(hwif->irq); if (startstop == ide_released) goto queue_next; @@ -864,7 +861,7 @@ */ void do_ide_request(request_queue_t *q) { - ide_do_request(q->queuedata, 0); + ide_do_request(q->queuedata, IDE_NO_IRQ); } /* @@ -1012,7 +1009,7 @@ hwgroup->busy = 0; } } - ide_do_request(hwgroup, 0); + ide_do_request(hwgroup, IDE_NO_IRQ); spin_unlock_irqrestore(&ide_lock, flags); } @@ -1302,7 +1299,7 @@ insert_end = 0; } __elv_add_request(&drive->queue, rq, insert_end, 0); - ide_do_request(hwgroup, 0); + ide_do_request(hwgroup, IDE_NO_IRQ); spin_unlock_irqrestore(&ide_lock, flags); err = 0; diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c --- a/drivers/ide/ide-iops.c Tue Feb 18 10:06:17 2003 +++ b/drivers/ide/ide-iops.c Thu Feb 20 08:50:44 2003 @@ -59,11 +59,11 @@ { } -static void ide_unplugged_outb (u8 addr, unsigned long port) +static void ide_unplugged_outb (u8 val, unsigned long port) { } -static void ide_unplugged_outw (u16 addr, unsigned long port) +static void ide_unplugged_outw (u16 val, unsigned long port) { } @@ -71,7 +71,7 @@ { } -static void ide_unplugged_outl (u32 addr, unsigned long port) +static void ide_unplugged_outl (u32 val, unsigned long port) { } @@ -125,14 +125,14 @@ insl(port, addr, count); } -static void ide_outb (u8 addr, unsigned long port) +static void ide_outb (u8 val, unsigned long port) { - outb(addr, port); + outb(val, port); } -static void ide_outw (u16 addr, unsigned long port) +static void ide_outw (u16 val, unsigned long port) { - outw(addr, port); + outw(val, port); } static void ide_outsw (unsigned long port, void *addr, u32 count) @@ -140,9 +140,9 @@ outsw(port, addr, count); } -static void ide_outl (u32 addr, unsigned long port) +static void ide_outl (u32 val, unsigned long port) { - outl(addr, port); + outl(val, port); } static void ide_outsl (unsigned long port, void *addr, u32 count) diff -Nru a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c --- a/drivers/ide/ide-lib.c Thu Nov 14 09:12:22 2002 +++ b/drivers/ide/ide-lib.c Tue Feb 18 10:06:17 2003 @@ -171,7 +171,7 @@ BUG(); return min(speed, speed_max[mode]); #else /* !CONFIG_BLK_DEV_IDEDMA */ - return min(speed, (u8)XFER_PIO_4); + return min(speed, XFER_PIO_4); #endif /* CONFIG_BLK_DEV_IDEDMA */ } diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c Tue Feb 18 10:06:17 2003 +++ b/drivers/ide/ide-probe.c Sat Mar 8 14:50:22 2003 @@ -1292,11 +1292,8 @@ /* we set it back to 1 if all is ok below */ hwif->present = 0; - if (register_blkdev (hwif->major, hwif->name, ide_fops)) { - printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", - hwif->name, hwif->major); + if (register_blkdev(hwif->major, hwif->name)) return 0; - } if (alloc_disks(hwif) < 0) goto out; diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Wed Nov 13 07:06:17 2002 +++ b/drivers/ide/ide-taskfile.c Tue Feb 18 10:06:17 2003 @@ -177,8 +177,7 @@ hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); if (task->handler != NULL) { - ide_set_handler(drive, task->handler, WAIT_WORSTCASE, NULL); - hwif->OUTB(taskfile->command, IDE_COMMAND_REG); + ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); if (task->prehandler != NULL) return task->prehandler(drive, task->rq); return ide_started; @@ -1880,9 +1879,8 @@ if (task->handler == NULL) return ide_stopped; - ide_set_handler(drive, task->handler, WAIT_WORSTCASE, NULL); /* Issue the command */ - hwif->OUTB(taskfile->command, IDE_COMMAND_REG); + ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); if (task->prehandler != NULL) return task->prehandler(drive, HWGROUP(drive)->rq); } diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c --- a/drivers/ide/legacy/hd.c Wed Nov 20 17:00:00 2002 +++ b/drivers/ide/legacy/hd.c Sat Mar 8 14:50:22 2003 @@ -708,10 +708,10 @@ static int __init hd_init(void) { int drive; - if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { - printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); + + if (register_blkdev(MAJOR_NR,"hd")) return -1; - } + blk_init_queue(&hd_queue, do_hd_request, &hd_lock); blk_queue_max_sectors(&hd_queue, 255); init_timer(&device_timer); diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c --- a/drivers/ide/pci/amd74xx.c Wed Feb 19 12:15:57 2003 +++ b/drivers/ide/pci/amd74xx.c Mon Mar 3 12:09:31 2003 @@ -82,7 +82,7 @@ #include #include -static long amd_base; +static unsigned long amd_base; static struct pci_dev *bmide_dev; extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ @@ -102,7 +102,7 @@ amd_print("----------AMD BusMastering IDE Configuration----------------"); - amd_print("Driver Version: 2.8"); + amd_print("Driver Version: 2.9"); amd_print("South Bridge: %s", bmide_dev->dev.name); pci_read_config_byte(dev, PCI_REVISION_ID, &t); @@ -284,7 +284,7 @@ * and initialize its drive independent registers. */ -unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name) +static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name) { unsigned char t; unsigned int u; @@ -378,12 +378,12 @@ return 0; } -unsigned int __init ata66_amd74xx(ide_hwif_t *hwif) +static unsigned int __init ata66_amd74xx(ide_hwif_t *hwif) { return ((amd_enabled & amd_80w) >> hwif->channel) & 1; } -void __init init_hwif_amd74xx(ide_hwif_t *hwif) +static void __init init_hwif_amd74xx(ide_hwif_t *hwif) { int i; diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c --- a/drivers/ide/pci/via82cxxx.c Wed Feb 19 12:13:48 2003 +++ b/drivers/ide/pci/via82cxxx.c Mon Mar 3 12:11:59 2003 @@ -1,16 +1,6 @@ /* - * $Id: via82cxxx.c,v 3.35-ac2 2002/09/111 Alan Exp $ * - * Copyright (c) 2000-2001 Vojtech Pavlik - * - * Based on the work of: - * Michel Aubry - * Jeff Garzik - * Andre Hedrick - */ - -/* - * Version 3.35 + * Version 3.36 * * VIA IDE driver for Linux. Supported southbridges: * @@ -24,6 +14,10 @@ * Michel Aubry * Jeff Garzik * Andre Hedrick + * + * Documentation: + * Obsolete device documentation publically available from via.com.tw + * Current device documentation available under NDA only */ /* @@ -67,6 +61,7 @@ #define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */ #define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */ #define VIA_BAD_ID 0x100 /* Has wrong vendor ID (0x1107) */ +#define VIA_BAD_AST 0x200 /* Don't touch Address Setup Timing */ /* * VIA SouthBridge chips. @@ -82,8 +77,8 @@ #ifdef FUTURE_BRIDGES { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 }, #endif - { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 }, - { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 }, + { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, @@ -152,7 +147,7 @@ via_print("----------VIA BusMastering IDE Configuration" "----------------"); - via_print("Driver Version: 3.35-ac"); + via_print("Driver Version: 3.36"); via_print("South Bridge: VIA %s", via_config->name); @@ -292,9 +287,11 @@ { u8 t; - pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); - t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); - pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); + if (~via_config->flags & VIA_BAD_AST) { + pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); + t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); + pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); + } pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)), ((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1)); diff -Nru a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c --- a/drivers/isdn/hardware/avm/b1pci.c Thu Aug 15 15:01:13 2002 +++ b/drivers/isdn/hardware/avm/b1pci.c Sat Feb 22 09:42:22 2003 @@ -343,12 +343,16 @@ static void __devexit b1pci_pci_remove(struct pci_dev *pdev) { +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 avmcard *card = pci_get_drvdata(pdev); if (card->dma) b1pciv4_remove(pdev); else b1pci_remove(pdev); +#else + b1pci_remove(pdev); +#endif } static struct pci_driver b1pci_pci_driver = { diff -Nru a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c --- a/drivers/isdn/hisax/amd7930.c Sun Jan 12 16:05:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,717 +0,0 @@ -/* $Id: amd7930.c,v 1.5.6.4 2001/09/23 22:24:46 kai Exp $ - * - * HiSax ISDN driver - chip specific routines for AMD 7930 - * - * Author Brent Baccala - * Copyright by Brent Baccala - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * - Existing ISDN HiSax driver provides all the smarts - * - it compiles, runs, talks to an isolated phone switch, connects - * to a Cisco, pings go through - * - AMD 7930 support only (no DBRI yet) - * - no US NI-1 support (may not work on US phone system - untested) - * - periodic packet loss, apparently due to lost interrupts - * - ISDN sometimes freezes, requiring reboot before it will work again - * - * The code is unreliable enough to be consider alpha - * - * This file is (c) under GNU General Public License - * - * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the - * SparcStation 1+. The chip provides microphone and speaker interfaces - * which provide mono-channel audio at 8K samples per second via either - * 8-bit A-law or 8-bit mu-law encoding. Also, the chip features an - * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface, - * which performs basic D channel LAPD processing and provides raw - * B channel data. The digital audio channel, the two ISDN B channels, - * and two 64 Kbps channels to the microprocessor are all interconnected - * via a multiplexer. - * - * This driver interfaces to the Linux HiSax ISDN driver, which performs - * all high-level Q.921 and Q.931 ISDN functions. The file is not - * itself a hardware driver; rather it uses functions exported by - * the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio), - * allowing the chip to be simultaneously used for both audio and ISDN data. - * The hardware driver does _no_ buffering, but provides several callbacks - * which are called during interrupt service and should therefore run quickly. - * - * D channel transmission is performed by passing the hardware driver the - * address and size of an skb's data area, then waiting for a callback - * to signal successful transmission of the packet. A task is then - * queued to notify the HiSax driver that another packet may be transmitted. - * - * D channel reception is quite simple, mainly because of: - * 1) the slow speed of the D channel - 16 kbps, and - * 2) the presence of an 8- or 32-byte (depending on chip version) FIFO - * to buffer the D channel data on the chip - * Worst case scenario of back-to-back packets with the 8 byte buffer - * at 16 kbps yields an service time of 4 ms - long enough to preclude - * the need for fancy buffering. We queue a background task that copies - * data out of the receive buffer into an skb, and the hardware driver - * simply does nothing until we're done with the receive buffer and - * reset it for a new packet. - * - * B channel processing is more complex, because of: - * 1) the faster speed - 64 kbps, - * 2) the lack of any on-chip buffering (it interrupts for every byte), and - * 3) the lack of any chip support for HDLC encapsulation - * - * The HiSax driver can put each B channel into one of three modes - - * L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay), - * and L1_MODE_HDLC (HDLC encapsulation by low-level driver). - * L1_MODE_HDLC is the most common, used for almost all "pure" digital - * data sessions. L1_MODE_TRANS is used for ISDN audio. - * - * HDLC B channel transmission is performed via a large buffer into - * which the skb is copied while performing HDLC bit-stuffing. A CRC - * is computed and attached to the end of the buffer, which is then - * passed to the low-level routines for raw transmission. Once - * transmission is complete, the hardware driver is set to enter HDLC - * idle by successive transmission of mark (all 1) bytes, waiting for - * the ISDN driver to prepare another packet for transmission and - * deliver it. - * - * HDLC B channel reception is performed via an X-byte ring buffer - * divided into N sections of X/N bytes each. Defaults: X=256 bytes, N=4. - * As the hardware driver notifies us that each section is full, we - * hand it the next section and schedule a background task to peruse - * the received section, bit-by-bit, with an HDLC decoder. As - * packets are detected, they are copied into a large buffer while - * decoding HDLC bit-stuffing. The ending CRC is verified, and if - * it is correct, we alloc a new skb of the correct length (which we - * now know), copy the packet into it, and hand it to the upper layers. - * Optimization: for large packets, we hand the buffer (which also - * happens to be an skb) directly to the upper layer after an skb_trim, - * and alloc a new large buffer for future packets, thus avoiding a copy. - * Then we return to HDLC processing; state is saved between calls. - * - */ - -#include "hisax.h" -#include "../../sbus/audio/amd7930.h" -#include "isac.h" -#include "isdnl1.h" -#include "rawhdlc.h" -#include - -static const char *amd7930_revision = "$Revision: 1.5.6.4 $"; - -#define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */ -#define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into - * (must divide RCV_BUFSIZE) */ - -static void Bchan_fill_fifo(struct BCState *, struct sk_buff *); - -static void -Bchan_xmt_bh(void *data) -{ - struct BCState *bcs = data; - struct sk_buff *skb; - - if (bcs->hw.amd7930.tx_skb != NULL) { - dev_kfree_skb(bcs->hw.amd7930.tx_skb); - bcs->hw.amd7930.tx_skb = NULL; - } - xmit_ready_b(bcs); -} - -static void -Bchan_xmit_callback(struct BCState *bcs) -{ - schedule_work(&bcs->hw.amd7930.xmt_work); -} - -/* B channel transmission: two modes (three, if you count L1_MODE_NULL) - * - * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting - * the packet (i.e. make_raw_hdlc_data). Since this can be a - * time-consuming operation, our completion callback just schedules - * a bottom half to do encapsulation for the next packet. In between, - * the link will just idle - * - * L1_MODE_TRANS - Data goes through, well, transparent. No HDLC encap, - * and we can't just let the link idle, so the "bottom half" actually - * gets called during the top half (it's our callback routine in this case), - * but it's a lot faster now since we don't call make_raw_hdlc_data - */ - -static void -Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb) -{ - struct IsdnCardState *cs = bcs->cs; - int len; - - if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) { - char tmp[1024]; - char *t = tmp; - - t += sprintf(t, "amd7930_fill_fifo %c cnt %d", - bcs->channel ? 'B' : 'A', skb->len); - if (cs->debug & L1_DEB_HSCX_FIFO) - QuickHex(t, skb->data, skb->len); - debugl1(cs, tmp); - } - - if (bcs->mode == L1_MODE_HDLC) { - len = make_raw_hdlc_data(skb->data, skb->len, - bcs->hw.amd7930.tx_buff, RAW_BUFMAX); - if (len > 0) - amd7930_bxmit(0, bcs->channel, - bcs->hw.amd7930.tx_buff, len, - (void *) &Bchan_xmit_callback, - (void *) bcs); - dev_kfree_skb(skb); - } else if (bcs->mode == L1_MODE_TRANS) { - amd7930_bxmit(0, bcs->channel, - bcs->hw.amd7930.tx_buff, skb->len, - (void *) &Bchan_xmt_bh, - (void *) bcs); - bcs->hw.amd7930.tx_skb = skb; - } else { - dev_kfree_skb(skb); - } -} - -static void -Bchan_mode(struct BCState *bcs, int mode, int bc) -{ - struct IsdnCardState *cs = bcs->cs; - - if (cs->debug & L1_DEB_HSCX) { - char tmp[40]; - sprintf(tmp, "AMD 7930 mode %d bchan %d/%d", - mode, bc, bcs->channel); - debugl1(cs, tmp); - } - bcs->mode = mode; -} - -/* Bchan_l2l1 is the entry point for upper layer routines that want to - * transmit on the B channel. PH_DATA_REQ is a normal packet that - * we either start transmitting (if idle) or queue (if busy). - * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF) - * once the link is idle. After a "pull" callback, the upper layer - * routines can use PH_PULL_IND to send data. - */ - -static void -Bchan_l2l1(struct PStack *st, int pr, void *arg) -{ - struct sk_buff *skb = arg; - - switch (pr) { - case (PH_DATA_REQ): - if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - } else { - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - Bchan_fill_fifo(st->l1.bcs, skb); - } - break; - case (PH_PULL_IND): - if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) { - printk(KERN_WARNING "amd7930: this shouldn't happen\n"); - break; - } - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - Bchan_fill_fifo(st->l1.bcs, skb); - break; - case (PH_PULL_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) { - clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); - } else - set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - break; - } -} - -/* Receiver callback and bottom half - decodes HDLC at leisure (if - * L1_MODE_HDLC) and passes newly received skb on via bcs->rqueue. If - * a large packet is received, stick rv_skb (the buffer that the - * packet has been decoded into) on the receive queue and alloc a new - * (large) skb to act as buffer for future receives. If a small - * packet is received, leave rv_skb alone, alloc a new skb of the - * correct size, and copy the packet into it - */ - -static void -Bchan_recv_callback(struct BCState *bcs) -{ - struct amd7930_hw *hw = &bcs->hw.amd7930; - - hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS; - hw->rv_buff_in %= RCV_BUFSIZE; - - if (hw->rv_buff_in != hw->rv_buff_out) { - amd7930_brecv(0, bcs->channel, - hw->rv_buff + hw->rv_buff_in, - RCV_BUFSIZE/RCV_BUFBLKS, - (void *) &Bchan_recv_callback, (void *) bcs); - } - - schedule_work(&hw->rcv_work); -} - -static void -Bchan_rcv_bh(void *data) -{ - struct BCState *bcs = data; - struct IsdnCardState *cs = bcs->cs; - struct amd7930_hw *hw = &bcs->hw.amd7930; - struct sk_buff *skb; - int len; - - if (cs->debug & L1_DEB_HSCX) { - char tmp[1024]; - - sprintf(tmp, "amd7930_Bchan_rcv (%d/%d)", - hw->rv_buff_in, hw->rv_buff_out); - debugl1(cs, tmp); - QuickHex(tmp, hw->rv_buff + hw->rv_buff_out, - RCV_BUFSIZE/RCV_BUFBLKS); - debugl1(cs, tmp); - } - - do { - if (bcs->mode == L1_MODE_HDLC) { - while ((len = read_raw_hdlc_data(hw->hdlc_state, - hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS, - hw->rv_skb->tail, HSCX_BUFMAX))) { - if (len > 0 && (cs->debug & L1_DEB_HSCX_FIFO)) { - char tmp[1024]; - char *t = tmp; - - t += sprintf(t, "amd7930_Bchan_rcv %c cnt %d", bcs->channel ? 'B' : 'A', len); - QuickHex(t, hw->rv_skb->tail, len); - debugl1(cs, tmp); - } - - if (len > HSCX_BUFMAX/2) { - /* Large packet received */ - - if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) { - printk(KERN_WARNING "amd7930: receive out of memory"); - } else { - skb_put(hw->rv_skb, len); - skb_queue_tail(&bcs->rqueue, hw->rv_skb); - hw->rv_skb = skb; - bcs->event |= 1 << B_RCVBUFREADY; - schedule_work(&bcs->work); - } - } else if (len > 0) { - /* Small packet received */ - - if (!(skb = dev_alloc_skb(len))) { - printk(KERN_WARNING "amd7930: receive out of memory\n"); - } else { - memcpy(skb_put(skb, len), hw->rv_skb->tail, len); - skb_queue_tail(&bcs->rqueue, skb); - bcs->event |= 1 << B_RCVBUFREADY; - schedule_work(&bcs->work); - } - } else { - /* Reception Error */ - /* printk("amd7930: B channel receive error\n"); */ - } - } - } else if (bcs->mode == L1_MODE_TRANS) { - if (!(skb = dev_alloc_skb(RCV_BUFSIZE/RCV_BUFBLKS))) { - printk(KERN_WARNING "amd7930: receive out of memory\n"); - } else { - memcpy(skb_put(skb, RCV_BUFSIZE/RCV_BUFBLKS), - hw->rv_buff + hw->rv_buff_out, - RCV_BUFSIZE/RCV_BUFBLKS); - skb_queue_tail(&bcs->rqueue, skb); - bcs->event |= 1 << B_RCVBUFREADY; - schedule_work(&bcs->work); - } - } - - if (hw->rv_buff_in == hw->rv_buff_out) { - /* Buffer was filled up - need to restart receiver */ - amd7930_brecv(0, bcs->channel, - hw->rv_buff + hw->rv_buff_in, - RCV_BUFSIZE/RCV_BUFBLKS, - (void *) &Bchan_recv_callback, - (void *) bcs); - } - - hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS; - hw->rv_buff_out %= RCV_BUFSIZE; - - } while (hw->rv_buff_in != hw->rv_buff_out); -} - -static void -Bchan_close(struct BCState *bcs) -{ - struct sk_buff *skb; - - Bchan_mode(bcs, 0, 0); - amd7930_bclose(0, bcs->channel); - - if (test_bit(BC_FLG_INIT, &bcs->Flag)) { - skb_queue_purge(&bcs->rqueue); - skb_queue_purge(&bcs->squeue); - } - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); -} - -static int -Bchan_open(struct BCState *bcs) -{ - struct amd7930_hw *hw = &bcs->hw.amd7930; - - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - } - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - - amd7930_bopen(0, bcs->channel, 0xff); - hw->rv_buff_in = 0; - hw->rv_buff_out = 0; - hw->tx_skb = NULL; - init_hdlc_state(hw->hdlc_state, 0); - amd7930_brecv(0, bcs->channel, - hw->rv_buff + hw->rv_buff_in, RCV_BUFSIZE/RCV_BUFBLKS, - (void *) &Bchan_recv_callback, (void *) bcs); - - bcs->event = 0; - bcs->tx_cnt = 0; - return (0); -} - -static void -Bchan_init(struct BCState *bcs) -{ - if (!(bcs->hw.amd7930.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for amd7930.tx_buff\n"); - return; - } - if (!(bcs->hw.amd7930.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for amd7930.rv_buff\n"); - return; - } - if (!(bcs->hw.amd7930.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) { - printk(KERN_WARNING - "HiSax: No memory for amd7930.rv_skb\n"); - return; - } - if (!(bcs->hw.amd7930.hdlc_state = kmalloc(sizeof(struct hdlc_state), - GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for amd7930.hdlc_state\n"); - return; - } - - INIT_WORK(&bcs->hw.amd7930.rcv_work, &Bchan_rcv_bh, bcs); - INIT_WORK(&bcs->hw.amd7930.xmt_work, &Bchan_xmt_bh, bcs); -} - -static void -Bchan_manl1(struct PStack *st, int pr, - void *arg) -{ - switch (pr) { - case (PH_ACTIVATE_REQ): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc); - st->l1.l1man(st, PH_ACTIVATE_CNF, NULL); - break; - case (PH_DEACTIVATE_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) - Bchan_mode(st->l1.bcs, 0, 0); - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - break; - } -} - -int -setstack_amd7930(struct PStack *st, struct BCState *bcs) -{ - if (Bchan_open(bcs)) - return (-1); - st->l1.bcs = bcs; - st->l2.l2l1 = Bchan_l2l1; - st->ma.manl1 = Bchan_manl1; - setstack_manager(st); - bcs->st = st; - return (0); -} - - -static void -amd7930_drecv_callback(void *arg, int error, unsigned int count) -{ - struct IsdnCardState *cs = (struct IsdnCardState *) arg; - static struct work_struct task; - struct sk_buff *skb; - - /* NOTE: This function is called directly from an interrupt handler */ - - if (1) { - if (!(skb = alloc_skb(count, GFP_ATOMIC))) - printk(KERN_WARNING "HiSax: D receive out of memory\n"); - else { - memcpy(skb_put(skb, count), cs->rcvbuf, count); - skb_queue_tail(&cs->rq, skb); - } - - INIT_WORK(&task, (void *) DChannel_proc_rcv, (void *) cs); - schedule_work(&task); - } - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char tmp[128]; - char *t = tmp; - - t += sprintf(t, "amd7930 Drecv cnt %d", count); - if (error) t += sprintf(t, " ERR %x", error); - QuickHex(t, cs->rcvbuf, count); - debugl1(cs, tmp); - } - - amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN, - &amd7930_drecv_callback, cs); -} - -static void -amd7930_dxmit_callback(void *arg, int error) -{ - struct IsdnCardState *cs = (struct IsdnCardState *) arg; - static struct work_struct task; - - /* NOTE: This function is called directly from an interrupt handler */ - - /* may wish to do retransmission here, if error indicates collision */ - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char tmp[128]; - char *t = tmp; - - t += sprintf(t, "amd7930 Dxmit cnt %d", cs->tx_skb->len); - if (error) t += sprintf(t, " ERR %x", error); - QuickHex(t, cs->tx_skb->data, cs->tx_skb->len); - debugl1(cs, tmp); - } - - cs->tx_skb = NULL; - - INIT_WORK(&task, (void *) DChannel_proc_xmt, (void *) cs); - schedule_work(&task); -} - -static void -amd7930_Dchan_l2l1(struct PStack *st, int pr, void *arg) -{ - struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; - struct sk_buff *skb = arg; - char str[64]; - - switch (pr) { - case (PH_DATA_REQ): - if (cs->tx_skb) { - skb_queue_tail(&cs->sq, skb); -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA Queued", 0); -#endif - } else { - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { - /* I-FRAME */ - LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data+4, skb->len-4, - str); - } - cs->tx_skb = skb; - cs->tx_cnt = 0; -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA", 0); -#endif - amd7930_dxmit(0, skb->data, skb->len, - &amd7930_dxmit_callback, cs); - } - break; - case (PH_PULL_IND): - if (cs->tx_skb) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); - skb_queue_tail(&cs->sq, skb); - break; - } - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */ - LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data + 4, skb->len - 4, - str); - } - cs->tx_skb = skb; - cs->tx_cnt = 0; -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); -#endif - amd7930_dxmit(0, cs->tx_skb->data, cs->tx_skb->len, - &amd7930_dxmit_callback, cs); - break; - case (PH_PULL_REQ): -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - debugl1(cs, "-> PH_REQUEST_PULL"); -#endif - if (!cs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - break; - } -} - -int -setDstack_amd7930(struct PStack *st, struct IsdnCardState *cs) -{ - st->l2.l2l1 = amd7930_Dchan_l2l1; - if (! cs->rcvbuf) { - printk("setDstack_amd7930: No cs->rcvbuf!\n"); - } else { - amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN, - &amd7930_drecv_callback, cs); - } - return (0); -} - -static void -manl1_msg(struct IsdnCardState *cs, int msg, void *arg) { - struct PStack *st; - - st = cs->stlist; - while (st) { - st->ma.manl1(st, msg, arg); - st = st->next; - } -} - -static void -amd7930_new_ph(struct IsdnCardState *cs) -{ - switch (amd7930_get_liu_state(0)) { - case 3: - manl1_msg(cs, PH_POWERUP_CNF, NULL); - break; - - case 7: - manl1_msg(cs, PH_I4_P8_IND, NULL); - break; - - case 8: - manl1_msg(cs, PH_RSYNC_IND, NULL); - break; - } -} - -/* amd7930 LIU state change callback */ - -static void -amd7930_liu_callback(struct IsdnCardState *cs) -{ - static struct work_struct task; - - if (!cs) - return; - - if (cs->debug & L1_DEB_ISAC) { - char tmp[32]; - sprintf(tmp, "amd7930_liu state %d", amd7930_get_liu_state(0)); - debugl1(cs, tmp); - } - - INIT_WORK(&task, (void *) &amd7930_new_ph, (void *) cs); - schedule_work(&task); -} - -void -amd7930_l1cmd(struct IsdnCardState *cs, int msg, void *arg) -{ - u8 val; - char tmp[32]; - - if (cs->debug & L1_DEB_ISAC) { - char tmp[32]; - sprintf(tmp, "amd7930_l1cmd msg %x", msg); - debugl1(cs, tmp); - } - - switch(msg) { - case PH_RESET_REQ: - if (amd7930_get_liu_state(0) <= 3) - amd7930_liu_activate(0,0); - else - amd7930_liu_deactivate(0); - break; - case PH_ENABLE_REQ: - break; - case PH_INFO3_REQ: - amd7930_liu_activate(0,0); - break; - case PH_TESTLOOP_REQ: - break; - default: - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "amd7930_l1cmd unknown %4x", msg); - debugl1(cs, tmp); - } - break; - } -} - -static void init_amd7930(struct IsdnCardState *cs) -{ - Bchan_init(&cs->bcs[0]); - Bchan_init(&cs->bcs[1]); - cs->bcs[0].BC_SetStack = setstack_amd7930; - cs->bcs[1].BC_SetStack = setstack_amd7930; - cs->bcs[0].BC_Close = Bchan_close; - cs->bcs[1].BC_Close = Bchan_close; - Bchan_mode(cs->bcs, 0, 0); - Bchan_mode(cs->bcs + 1, 0, 0); -} - -static int -amd7930_init(struct IsdnCardState *cs) -{ - cs->l1cmd = amd7930_l1cmd; - amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs); - init_amd7930(cs); - return 0; -} - -static struct card_ops amd7930_ops = { - .init = amd7930_init, -}; - -int __init -setup_amd7930(struct IsdnCard *card) -{ - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, amd7930_revision); - printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp)); - - cs->irq = amd7930_get_irqnum(0); - if (cs->irq == 0) - return 0; - - cs->card_ops = &amd7930_ops; - return 1; -} diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c --- a/drivers/isdn/hisax/asuscom.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/asuscom.c Thu Mar 6 22:52:04 2003 @@ -231,6 +231,51 @@ .irq_func = ipac_irq, }; +static int __init +asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int rc; + u8 val; + + printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n", + card->para[1], card->para[0]); + + cs->hw.asus.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + + rc = -EBUSY; + if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn")) + goto err; + + rc = -ENODEV; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; + val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); + if ((val == 1) || (val == 2)) { + cs->subtyp = ASUS_IPAC; + cs->card_ops = &asuscom_ipac_ops; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + } else { + cs->subtyp = ASUS_ISACHSCX; + cs->card_ops = &asuscom_ops; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; + cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; + cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; + cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + } + printk(KERN_INFO "ISDNLink: resetting card\n"); + cs->card_ops->reset(cs); + return 0; + + err: + hisax_release_resources(cs); + return rc; +} + #ifdef __ISAPNP__ static struct isapnp_device_id asus_ids[] __initdata = { { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688), @@ -255,9 +300,6 @@ int __init setup_asuscom(struct IsdnCard *card) { - int bytecnt; - struct IsdnCardState *cs = card->cs; - u8 val; char tmp[64]; strcpy(tmp, Asuscom_revision); @@ -310,36 +352,7 @@ } } #endif - bytecnt = 8; - cs->hw.asus.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn")) - goto err; - printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n", - cs->hw.asus.cfg_reg, cs->irq); - cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; - val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); - if ((val == 1) || (val == 2)) { - cs->subtyp = ASUS_IPAC; - cs->card_ops = &asuscom_ipac_ops; - cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else { - cs->subtyp = ASUS_ISACHSCX; - cs->card_ops = &asuscom_ops; - cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; - cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; - cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; - cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; - cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - } - printk(KERN_INFO "ISDNLink: resetting card\n"); - cs->card_ops->reset(cs); + if (asuscom_probe(card->cs, card) < 0) + return 0; return 1; - err: - hisax_release_resources(cs); - return 0; } diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c --- a/drivers/isdn/hisax/avm_a1.c Sun Jan 12 16:12:36 2003 +++ b/drivers/isdn/hisax/avm_a1.c Thu Mar 6 22:52:04 2003 @@ -160,16 +160,16 @@ .irq_func = avm_a1_interrupt, }; -int __init -setup_avm_a1(struct IsdnCard *card) +static int __init +avm_a1_probe(struct IsdnCardState *cs, struct IsdnCard *card) { + int rc; u8 val; - struct IsdnCardState *cs = card->cs; - char tmp[64]; - strcpy(tmp, avm_revision); - printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); + printk(KERN_INFO "AVM A1: defined at %#lx IRQ %lu\n", + card->para[1], card->para[0]); + rc = -EBUSY; cs->hw.avm.cfg_reg = request_io(&cs->rs, card->para[1] + 0x1800, 8, "avm cfg"); if (!cs->hw.avm.cfg_reg) goto err; cs->hw.avm.isac = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac"); @@ -216,23 +216,24 @@ printk(KERN_INFO "AVM A1: Byte at %x is %x\n", cs->hw.avm.cfg_reg, val); - printk(KERN_INFO - "HiSax: %s config irq:%d cfg:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.avm.cfg_reg); - printk(KERN_INFO - "HiSax: isac:0x%X/0x%X\n", - cs->hw.avm.isac + 32, cs->hw.avm.isacfifo); - printk(KERN_INFO - "HiSax: hscx A:0x%X/0x%X hscx B:0x%X/0x%X\n", - cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0], - cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]); - cs->card_ops = &avm_a1_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); - return 0; + return rc; +} + +int __init +setup_avm_a1(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, avm_revision); + printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); + + if (avm_a1_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c --- a/drivers/isdn/hisax/avm_a1p.c Sun Jan 12 16:12:36 2003 +++ b/drivers/isdn/hisax/avm_a1p.c Thu Mar 6 22:52:04 2003 @@ -215,20 +215,13 @@ .irq_func = avm_a1p_interrupt, }; -int __devinit -setup_avm_a1_pcmcia(struct IsdnCard *card) +static int __init +avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card) { u8 model, vers; - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, avm_revision); - printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", - HiSax_getrev(tmp)); - cs->hw.avm.cfg_reg = card->para[1]; cs->irq = card->para[0]; - + cs->hw.avm.cfg_reg = card->para[1]; outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0); @@ -244,11 +237,26 @@ vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET); printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n", - cs->hw.avm.cfg_reg, cs->irq, model, vers); + cs->hw.avm.cfg_reg, cs->irq, model, vers); cs->card_ops = &avm_a1p_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return 0; + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +int __devinit +setup_avm_a1_pcmcia(struct IsdnCard *card) +{ + char tmp[64]; + strcpy(tmp, avm_revision); + printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", + HiSax_getrev(tmp)); + if (avm_a1p_probe(card->cs, card)) + return 0; return 1; } diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c --- a/drivers/isdn/hisax/avm_pci.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/avm_pci.c Thu Mar 6 22:52:04 2003 @@ -497,7 +497,7 @@ .close = close_hdlcstate, }; -void __init +static void __init inithdlc(struct IsdnCardState *cs) { u_int val; @@ -596,6 +596,82 @@ .irq_func = avm_pcipnp_interrupt, }; +static int __init +avm_pcipnp_hw_init(struct IsdnCardState *cs) +{ + cs->bc_hw_ops = &hdlc_hw_ops; + cs->bc_l1_ops = &hdlc_l1_ops; + cs->card_ops = &avm_pci_ops; + avm_pcipnp_reset(cs); + return isac_setup(cs, &isac_ops); +} + +static int __init +avm_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + int rc; + u32 val; + + printk(KERN_INFO "AVM PCI: defined at %#lx IRQ %u\n", + pci_resource_start(pdev, 1), pdev->irq); + + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = AVM_FRITZ_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1); + cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; + if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PCI")) + goto err; + + val = inl(cs->hw.avm.cfg_reg); + printk(KERN_INFO "AVM PCI: stat %#x\n", val); + printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", + val & 0xff, (val>>8) & 0xff); + + if (avm_pcipnp_hw_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return rc; +} + +static int __init +avm_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int rc; + u8 val, ver; + + printk(KERN_INFO "AVM PnP: defined at %#lx IRQ %lu\n", + card->para[1], card->para[0]); + + cs->subtyp = AVM_FRITZ_PNP; + cs->irq = card->para[0]; + cs->hw.avm.cfg_reg = card->para[1]; + cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; + + rc = -EBUSY; + if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PnP")) + goto err; + + val = inb(cs->hw.avm.cfg_reg); + ver = inb(cs->hw.avm.cfg_reg + 1); + printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); + + if (avm_pcipnp_hw_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return rc; +} + static struct pci_dev *dev_avm __initdata = NULL; #ifdef __ISAPNP__ static struct pnp_card *card_avm __initdata = NULL; @@ -605,17 +681,15 @@ int __init setup_avm_pcipnp(struct IsdnCard *card) { - u_int val, ver; - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, avm_pci_rev); printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (card->para[1]) { /* old manual method */ - cs->hw.avm.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - cs->subtyp = AVM_FRITZ_PNP; + if (avm_pnp_probe(card->cs, card)) + return 0; + return 1; } else { #ifdef __ISAPNP__ if (isapnp_present()) { @@ -647,69 +721,24 @@ pnp_device_detach(pnp_avm); return(0); } - cs->hw.avm.cfg_reg = pnp_port_start(pnp_avm, 0); - cs->irq = pnp_irq(pnp_avm, 0); - cs->subtyp = AVM_FRITZ_PNP; - goto ready; + card->para[1] = pnp_port_start(pnp_avm, 0); + card->para[0] = pnp_irq(pnp_avm, 0); + if (avm_pnp_probe(card->cs, card)) + return 0; + return 1; } } - } else { - printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); } #endif #if CONFIG_PCI if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, dev_avm))) { - cs->irq = dev_avm->irq; - if (!cs->irq) { - printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); - return(0); - } - if (pci_enable_device(dev_avm)) - return(0); - cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); - if (!cs->hw.avm.cfg_reg) { - printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); - return(0); - } - cs->subtyp = AVM_FRITZ_PCI; - } else { - printk(KERN_WARNING "FritzPCI: No PCI card found\n"); - return(0); + if (avm_pci_probe(card->cs, dev_avm)) + return 0; + return 1; } - cs->irq_flags |= SA_SHIRQ; #endif /* CONFIG_PCI */ } -ready: - cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; - if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, - cs->subtyp == AVM_FRITZ_PCI ? "avm PCI" : "avm PnP")) - goto err; - - switch (cs->subtyp) { - case AVM_FRITZ_PCI: - val = inl(cs->hw.avm.cfg_reg); - printk(KERN_INFO "AVM PCI: stat %#x\n", val); - printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", - val & 0xff, (val>>8) & 0xff); - break; - case AVM_FRITZ_PNP: - val = inb(cs->hw.avm.cfg_reg); - ver = inb(cs->hw.avm.cfg_reg + 1); - printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); - avm_pcipnp_reset(cs); - break; - } - printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n", - (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP", - cs->irq, cs->hw.avm.cfg_reg); - - cs->bc_hw_ops = &hdlc_hw_ops; - cs->bc_l1_ops = &hdlc_l1_ops; - cs->card_ops = &avm_pci_ops; - isac_setup(cs, &isac_ops); - return 1; - err: - hisax_release_resources(cs); + printk(KERN_WARNING "FritzPCI: No card found\n"); return 0; } diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c --- a/drivers/isdn/hisax/bkm_a4t.c Sun Jan 12 16:12:36 2003 +++ b/drivers/isdn/hisax/bkm_a4t.c Thu Mar 6 22:52:04 2003 @@ -21,11 +21,11 @@ #include "bkm_ax.h" extern const char *CardType[]; +// FIXME needs per card lock static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED; const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $"; - static inline u8 readreg(unsigned int ale, unsigned long adr, u8 off) { @@ -249,15 +249,57 @@ .irq_func = bkm_interrupt, }; +static int __init +bkm_a4t_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + I20_REGISTER_FILE *pI20_Regs; + int rc; + + printk(KERN_INFO "BKM A4T: defined at %#lx IRQ %u\n", + pci_resource_start(pdev, 0), pdev->irq); + + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1); + + cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "Telekom A4T"); + if (!cs->hw.ax.base) + goto err; + + /* Check suspicious address */ + // FIXME needs to use read[bl] + pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { + printk(KERN_WARNING "HiSax: address %lx suspicious\n", + cs->hw.ax.base); + goto err; + } + cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.isac_ale = GCS_1; + cs->hw.ax.jade_ale = GCS_3; + + reset_bkm(cs); + cs->card_ops = &bkm_a4t_ops; + isac_setup(cs, &isac_ops); + jade_setup(cs, &jade_ops); + return 0; + + err: + hisax_release_resources(cs); + return rc; +} + static struct pci_dev *dev_a4t __initdata = NULL; int __init setup_bkm_a4t(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; - u_int pci_memaddr = 0, found = 0; - I20_REGISTER_FILE *pI20_Regs; strcpy(tmp, bkm_a4t_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); @@ -268,49 +310,13 @@ sub_vendor = dev_a4t->subsystem_vendor; sub_sys = dev_a4t->subsystem_device; - if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) { - if (pci_enable_device(dev_a4t)) - return(0); - found = 1; - pci_memaddr = pci_resource_start(dev_a4t, 0); - cs->irq = dev_a4t->irq; - break; + if (sub_sys == PCI_DEVICE_ID_BERKOM_A4T && + sub_vendor == PCI_VENDOR_ID_BERKOM) { + if (bkm_a4t_probe(card->cs, dev_a4t)) + return 0; + return 1; } } - if (!found) { - printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); - return (0); - } - if (!cs->irq) { /* IRQ range check ?? */ - printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]); - return (0); - } - cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs,pci_memaddr, 4096, "Telekom A4T"); - if (!cs->hw.ax.base) { - printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]); - return (0); - } - - /* Check suspecious address */ - pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { - printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n", - CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096); - hisax_release_resources(cs); - return (0); - } - cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; - cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; - cs->hw.ax.isac_ale = GCS_1; - cs->hw.ax.jade_ale = GCS_3; - - printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n", - CardType[card->typ], cs->hw.ax.base, cs->irq); - - reset_bkm(cs); - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &bkm_a4t_ops; - isac_setup(cs, &isac_ops); - jade_setup(cs, &jade_ops); - return 1; + printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); + return 0; } diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c --- a/drivers/isdn/hisax/config.c Wed Jan 15 08:20:56 2003 +++ b/drivers/isdn/hisax/config.c Thu Mar 6 23:20:18 2003 @@ -490,125 +490,36 @@ __setup("hisax=", HiSax_setup); #endif /* MODULES */ -#if CARD_TELES0 extern int setup_teles0(struct IsdnCard *card); -#endif - -#if CARD_TELES3 extern int setup_teles3(struct IsdnCard *card); -#endif - -#if CARD_S0BOX extern int setup_s0box(struct IsdnCard *card); -#endif - -#if CARD_TELESPCI extern int setup_telespci(struct IsdnCard *card); -#endif - -#if CARD_AVM_A1 extern int setup_avm_a1(struct IsdnCard *card); -#endif - -#if CARD_AVM_A1_PCMCIA extern int setup_avm_a1_pcmcia(struct IsdnCard *card); -#endif - -#if CARD_FRITZPCI extern int setup_avm_pcipnp(struct IsdnCard *card); -#endif - -#if CARD_ELSA extern int setup_elsa(struct IsdnCard *card); -#endif - -#if CARD_IX1MICROR2 extern int setup_ix1micro(struct IsdnCard *card); -#endif - -#if CARD_DIEHLDIVA extern int setup_diva(struct IsdnCard *card); -#endif - -#if CARD_ASUSCOM extern int setup_asuscom(struct IsdnCard *card); -#endif - -#if CARD_TELEINT extern int setup_TeleInt(struct IsdnCard *card); -#endif - -#if CARD_SEDLBAUER extern int setup_sedlbauer(struct IsdnCard *card); -#endif - -#if CARD_SPORTSTER extern int setup_sportster(struct IsdnCard *card); -#endif - -#if CARD_MIC extern int setup_mic(struct IsdnCard *card); -#endif - -#if CARD_NETJET_S extern int setup_netjet_s(struct IsdnCard *card); -#endif - -#if CARD_HFCS extern int setup_hfcs(struct IsdnCard *card); -#endif - -#if CARD_HFC_PCI extern int setup_hfcpci(struct IsdnCard *card); -#endif - -#if CARD_HFC_SX extern int setup_hfcsx(struct IsdnCard *card); -#endif - -#if CARD_AMD7930 extern int setup_amd7930(struct IsdnCard *card); -#endif - -#if CARD_NICCY extern int setup_niccy(struct IsdnCard *card); -#endif - -#if CARD_ISURF extern int setup_isurf(struct IsdnCard *card); -#endif - -#if CARD_HSTSAPHIR extern int setup_saphir(struct IsdnCard *card); -#endif - -#if CARD_TESTEMU extern int setup_testemu(struct IsdnCard *card); -#endif - -#if CARD_BKM_A4T extern int setup_bkm_a4t(struct IsdnCard *card); -#endif - -#if CARD_SCT_QUADRO extern int setup_sct_quadro(struct IsdnCard *card); -#endif - -#if CARD_GAZEL extern int setup_gazel(struct IsdnCard *card); -#endif - -#if CARD_W6692 extern int setup_w6692(struct IsdnCard *card); -#endif - -#if CARD_NETJET_U extern int setup_netjet_u(struct IsdnCard *card); -#endif - -#if CARD_FN_ENTERNOW_PCI extern int setup_enternow_pci(struct IsdnCard *card); -#endif /* * Find card with given driverId @@ -703,16 +614,16 @@ return 8; } -static u8 tmpbuf[HISAX_STATUS_BUFSIZE]; +static char tmpbuf[HISAX_STATUS_BUFSIZE]; -void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, +void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args) { /* if head == NULL the fmt contains the full info */ unsigned long flags; int count, i; - u8 *p; + char *p; isdn_ctrl ic; int len; @@ -727,7 +638,7 @@ len = p - tmpbuf; p = tmpbuf; } else { - p = fmt; + p = (char *) fmt; len = strlen(fmt); } if (!cs) { @@ -814,12 +725,6 @@ ic.command = ISDN_STAT_UNLOAD; ic.driver = cs->myid; cs->iif.statcallb(&ic); - if (cs->status_buf) - kfree(cs->status_buf); - cs->status_read = NULL; - cs->status_write = NULL; - cs->status_end = NULL; - kfree(cs->dlog); } static void closecard(int cardnr) @@ -893,59 +798,97 @@ return 3; } +static struct IsdnCardState * +alloc_IsdnCardState(void) +{ + struct IsdnCardState *cs; + + cs = kmalloc(sizeof(*cs), GFP_ATOMIC); // FIXME + if (!cs) + goto err; + + memset(cs, 0, sizeof(*cs)); + + cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC); + if (!cs->dlog) + goto err_cs; + + cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC); + if (!cs->status_buf) + goto err_dlog; + + cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC); + if (!cs->rcvbuf) + goto err_status_buf; + + cs->chanlimit = 2; /* maximum B-channel number */ + cs->debug = L1_DEB_WARN; + cs->irq_flags = I4L_IRQ_FLAG; + cs->stlist = NULL; + cs->status_read = cs->status_buf; + cs->status_write = cs->status_buf; + cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; + cs->rcvidx = 0; + cs->tx_skb = NULL; + cs->tx_cnt = 0; + cs->event = 0; + + skb_queue_head_init(&cs->rq); + skb_queue_head_init(&cs->sq); + + spin_lock_init(&cs->lock); + resources_init(&cs->rs); + return cs; + + err_status_buf: + kfree(cs->status_buf); + err_dlog: + kfree(cs->dlog); + err_cs: + kfree(cs); + err: + return NULL; +} + +static void +free_IsdnCardState(struct IsdnCardState *cs) +{ + kfree(cs->rcvbuf); + kfree(cs->status_buf); + kfree(cs->dlog); + kfree(cs); +} + static int __devinit checkcard(int cardnr, char *id, int *busy_flag) { int ret = 0; struct IsdnCard *card = cards + cardnr; struct IsdnCardState *cs; - cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC); + cs = alloc_IsdnCardState(); if (!cs) { printk(KERN_WARNING "HiSax: No memory for IsdnCardState(card %d)\n", cardnr + 1); goto out; } - memset(cs, 0, sizeof(struct IsdnCardState)); card->cs = cs; - cs->chanlimit = 2; /* maximum B-channel number */ - cs->logecho = 0; /* No echo logging */ - cs->cardnr = cardnr; - cs->debug = L1_DEB_WARN; - cs->HW_Flags = 0; - cs->busy_flag = busy_flag; - cs->irq_flags = I4L_IRQ_FLAG; #if TEI_PER_CARD if (card->protocol == ISDN_PTYPE_NI1) test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); #else test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); #endif + cs->cardnr = cardnr; cs->protocol = card->protocol; + cs->typ = card->typ; + cs->busy_flag = busy_flag; if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) { printk(KERN_WARNING "HiSax: Card Type %d out of range\n", card->typ); goto outf_cs; } - if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for dlog(card %d)\n", cardnr + 1); - goto outf_cs; - } - if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for status_buf(card %d)\n", - cardnr + 1); - goto outf_dlog; - } - cs->stlist = NULL; - cs->status_read = cs->status_buf; - cs->status_write = cs->status_buf; - cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; - cs->typ = card->typ; - spin_lock_init(&cs->lock); - resources_init(&cs->rs); SET_MODULE_OWNER(&cs->iif); strcpy(cs->iif.id, id); cs->iif.channels = 2; @@ -982,13 +925,13 @@ (card->protocol == ISDN_PTYPE_NI1) ? "NI1" : "NONE", cs->iif.id, cs->myid); switch (card->typ) { -#if CARD_TELES0 +#ifdef CONFIG_HISAX_16_0 case ISDN_CTYPE_16_0: case ISDN_CTYPE_8_0: ret = setup_teles0(card); break; #endif -#if CARD_TELES3 +#ifdef CONFIG_HISAX_16_3 case ISDN_CTYPE_16_3: case ISDN_CTYPE_PNP: case ISDN_CTYPE_TELESPCMCIA: @@ -996,32 +939,32 @@ ret = setup_teles3(card); break; #endif -#if CARD_S0BOX +#ifdef CONFIG_HISAX_S0BOX case ISDN_CTYPE_S0BOX: ret = setup_s0box(card); break; #endif -#if CARD_TELESPCI +#ifdef CONFIG_HISAX_TELESPCI case ISDN_CTYPE_TELESPCI: ret = setup_telespci(card); break; #endif -#if CARD_AVM_A1 +#ifdef CONFIG_HISAX_AVM_A1 case ISDN_CTYPE_A1: ret = setup_avm_a1(card); break; #endif -#if CARD_AVM_A1_PCMCIA +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA case ISDN_CTYPE_A1_PCMCIA: ret = setup_avm_a1_pcmcia(card); break; #endif -#if CARD_FRITZPCI +#ifdef CONFIG_HISAX_FRITZPCI case ISDN_CTYPE_FRITZPCI: ret = setup_avm_pcipnp(card); break; #endif -#if CARD_ELSA +#ifdef CONFIG_HISAX_ELSA case ISDN_CTYPE_ELSA: case ISDN_CTYPE_ELSA_PNP: case ISDN_CTYPE_ELSA_PCMCIA: @@ -1029,115 +972,115 @@ ret = setup_elsa(card); break; #endif -#if CARD_IX1MICROR2 +#ifdef CONFIG_HISAX_IX1MICROR2 case ISDN_CTYPE_IX1MICROR2: ret = setup_ix1micro(card); break; #endif -#if CARD_DIEHLDIVA +#ifdef CONFIG_HISAX_DIEHLDIVA case ISDN_CTYPE_DIEHLDIVA: ret = setup_diva(card); break; #endif -#if CARD_ASUSCOM +#ifdef CONFIG_HISAX_ASUSCOM case ISDN_CTYPE_ASUSCOM: ret = setup_asuscom(card); break; #endif -#if CARD_TELEINT +#ifdef CONFIG_HISAX_TELEINT case ISDN_CTYPE_TELEINT: ret = setup_TeleInt(card); break; #endif -#if CARD_SEDLBAUER +#ifdef CONFIG_HISAX_SEDLBAUER case ISDN_CTYPE_SEDLBAUER: case ISDN_CTYPE_SEDLBAUER_PCMCIA: case ISDN_CTYPE_SEDLBAUER_FAX: ret = setup_sedlbauer(card); break; #endif -#if CARD_SPORTSTER +#ifdef CONFIG_HISAX_SPORTSTER case ISDN_CTYPE_SPORTSTER: ret = setup_sportster(card); break; #endif -#if CARD_MIC +#ifdef CONFIG_HISAX_MIC case ISDN_CTYPE_MIC: ret = setup_mic(card); break; #endif -#if CARD_NETJET_S +#ifdef CONFIG_HISAX_NETJET case ISDN_CTYPE_NETJET_S: ret = setup_netjet_s(card); break; #endif -#if CARD_HFCS +#ifdef CONFIG_HISAX_HFCS case ISDN_CTYPE_TELES3C: case ISDN_CTYPE_ACERP10: ret = setup_hfcs(card); break; #endif -#if CARD_HFC_PCI +#ifdef CONFIG_HISAX_HFC_PCI case ISDN_CTYPE_HFC_PCI: ret = setup_hfcpci(card); break; #endif -#if CARD_HFC_SX +#ifdef CONFIG_HISAX_HFC_SX case ISDN_CTYPE_HFC_SX: ret = setup_hfcsx(card); break; #endif -#if CARD_NICCY +#ifdef CONFIG_HISAX_NICCY case ISDN_CTYPE_NICCY: ret = setup_niccy(card); break; #endif -#if CARD_AMD7930 +#ifdef CONFIG_HISAX_AMD7930 case ISDN_CTYPE_AMD7930: ret = setup_amd7930(card); break; #endif -#if CARD_ISURF +#ifdef CONFIG_HISAX_ISURF case ISDN_CTYPE_ISURF: ret = setup_isurf(card); break; #endif -#if CARD_HSTSAPHIR +#ifdef CONFIG_HISAX_HSTSAPHIR case ISDN_CTYPE_HSTSAPHIR: ret = setup_saphir(card); break; #endif -#if CARD_TESTEMU +#ifdef CONFIG_HISAX_TESTEMU case ISDN_CTYPE_TESTEMU: ret = setup_testemu(card); break; #endif -#if CARD_BKM_A4T +#ifdef CONFIG_HISAX_BKM_A4T case ISDN_CTYPE_BKM_A4T: ret = setup_bkm_a4t(card); break; #endif -#if CARD_SCT_QUADRO +#ifdef CONFIG_HISAX_SCT_QUADRO case ISDN_CTYPE_SCT_QUADRO: ret = setup_sct_quadro(card); break; #endif -#if CARD_GAZEL +#ifdef CONFIG_HISAX_GAZEL case ISDN_CTYPE_GAZEL: ret = setup_gazel(card); break; #endif -#if CARD_W6692 +#ifdef CONFIG_HISAX_W6692 case ISDN_CTYPE_W6692: ret = setup_w6692(card); break; #endif -#if CARD_NETJET_U +#ifdef CONFIG_HISAX_NETJET_U case ISDN_CTYPE_NETJET_U: ret = setup_netjet_u(card); break; #endif -#if CARD_FN_ENTERNOW_PCI +#ifdef CONFIG_HISAX_ENTERNOW_PCI case ISDN_CTYPE_ENTERNOW: ret = setup_enternow_pci(card); break; @@ -1156,19 +1099,6 @@ ll_unload(cs); goto outf_cs; } - if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) { - printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n"); - ll_unload(cs); - goto outf_cs; - } - cs->rcvidx = 0; - cs->tx_skb = NULL; - cs->tx_cnt = 0; - cs->event = 0; - - skb_queue_head_init(&cs->rq); - skb_queue_head_init(&cs->sq); - init_bcstate(cs, 0); init_bcstate(cs, 1); @@ -1201,10 +1131,8 @@ ret = 1; goto out; - outf_dlog: - kfree(cs->dlog); outf_cs: - kfree(cs); + free_IsdnCardState(cs); card->cs = NULL; out: return ret; @@ -1253,8 +1181,8 @@ i++; } else { printk(KERN_WARNING - "HiSax: Card %s not installed !\n", - CardType[cards[i].typ]); + "HiSax: Card type %d not installed !\n", + cards[i].typ); HiSax_shiftcards(i); nrcards--; } diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c --- a/drivers/isdn/hisax/diva.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/diva.c Thu Mar 6 22:52:04 2003 @@ -362,7 +362,7 @@ static void diva_release(struct IsdnCardState *cs) { - del_timer(&cs->hw.diva.tl); + del_timer_sync(&cs->hw.diva.tl); if (cs->hw.diva.cfg_reg) byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ @@ -515,6 +515,162 @@ .irq_func = diva_ipacx_pci_irq, }; +static int __init +diva_ipac_probe(struct IsdnCardState *cs) +{ + u8 val; + + // request_io + val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, + cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + return (val == 1 || val == 2); +} + +static int __init +diva_ipac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = DIVA_IPAC_ISA; + cs->irq = card->para[0]; + cs->hw.diva.cfg_reg = card->para[1]; + cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "IPAC ISA", cs->hw.diva.cfg_reg, cs->irq); + if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) + goto err; + diva_ipac_isa_reset(cs); + cs->card_ops = &diva_ipac_isa_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +diva_isac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = DIVA_ISA; + cs->irq = card->para[0]; + cs->hw.diva.cfg_reg = card->para[1]; + cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; + cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; + cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; + cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "ISA", cs->hw.diva.cfg_reg, cs->irq); + if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) + goto err; + diva_reset(cs); + init_timer(&cs->hw.diva.tl); + cs->hw.diva.tl.function = (void *) diva_led_handler; + cs->hw.diva.tl.data = (long) cs; + cs->card_ops = &diva_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +diva_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int is_ipac; + cs->hw.diva.cfg_reg = card->para[1]; + if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) + return -EBUSY; + + is_ipac = diva_ipac_probe(cs); + hisax_release_resources(cs); + + if (is_ipac) + return diva_ipac_isa_probe(cs, card); + else + return diva_isac_isa_probe(cs, card); +} + +static int __init +diva_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = DIVA_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.diva.cfg_reg = pci_resource_start(pdev, 2); + cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; + cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; + cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; + cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "PCI", cs->hw.diva.cfg_reg, cs->irq); + printk(KERN_INFO "Diva: %s space at %#lx\n", + "PCI", cs->hw.diva.pci_cfg); + if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 32, "diva isdn")) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +diva_ipac_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = DIVA_IPAC_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.diva.pci_cfg = (unsigned long)request_mmio( + &cs->rs, pci_resource_start(pdev, 0), 4096, "diva"); + cs->hw.diva.cfg_reg = (unsigned long)request_mmio( + &cs->rs, pci_resource_start(pdev, 1), 4096, "diva"); + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "IPAC PCI", cs->hw.diva.cfg_reg, cs->irq); + printk(KERN_INFO "Diva: %s space at %#lx\n", + "IPAC PCI", cs->hw.diva.pci_cfg); + diva_ipac_pci_reset(cs); + cs->card_ops = &diva_ipac_pci_ops; + if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +diva_ipacx_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = DIVA_IPACX_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "IPACX PCI", cs->hw.diva.cfg_reg, cs->irq); + printk(KERN_INFO "Diva: %s space at %#lx\n", + "IPACX PCI", cs->hw.diva.pci_cfg); + diva_ipacx_pci_reset(cs); + cs->card_ops = &diva_ipacx_pci_ops; + if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_diva __initdata = NULL; static struct pci_dev *dev_diva_u __initdata = NULL; static struct pci_dev *dev_diva201 __initdata = NULL; @@ -545,101 +701,60 @@ static struct pnp_card *pnp_c __devinitdata = NULL; #endif - int __init setup_diva(struct IsdnCard *card) { - int bytecnt = 8; - u8 val; - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, Diva_revision); printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp)); if (card->para[1]) { - cs->hw.diva.ctrl_reg = 0; - cs->hw.diva.cfg_reg = card->para[1]; - val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, - cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); - printk(KERN_INFO "Diva: IPAC version %x\n", val); - if ((val == 1) || (val==2)) { - cs->subtyp = DIVA_IPAC_ISA; - cs->hw.diva.ctrl = 0; - cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; - cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; - } else { - cs->subtyp = DIVA_ISA; - cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; - cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; - cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; - cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; - } - cs->irq = card->para[0]; - } else { + if (diva_isa_probe(card->cs, card) < 0) + return 0; + return 1; + + } #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { - printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Diva PnP: attach failed\n"); + if (isapnp_present()) { + struct pnp_card *pb; + struct pnp_dev *pd; + + while(pdev->card_vendor) { + if ((pb = pnp_find_card(pdev->card_vendor, + pdev->card_device, pnp_c))) { + pnp_c = pb; + pd = NULL; + if ((pd = pnp_find_dev(pnp_c, + pdev->vendor, + pdev->function, + pd))) { + printk(KERN_INFO "HiSax: %s detected\n", + (char *)pdev->driver_data); + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "Diva PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd) < 0) { + printk(KERN_ERR "Diva PnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); + return(0); + } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); + if (pdev->function == ISAPNP_FUNCTION(0xA1)) { + if (diva_ipac_isa_probe(cs->card, cs)) return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "Diva PnP: activate failed\n"); - pnp_device_detach(pd); + return 1; + } else { + if (diva_isac_isa_probe(cs->card, cs)) return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { - printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); - return(0); - } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - cs->hw.diva.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (pdev->function == ISAPNP_FUNCTION(0xA1)) { - cs->subtyp = DIVA_IPAC_ISA; - cs->hw.diva.ctrl = 0; - cs->hw.diva.isac = - card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.hscx = - card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.isac_adr = - card->para[1] + DIVA_IPAC_ADR; - cs->hw.diva.hscx_adr = - card->para[1] + DIVA_IPAC_ADR; - } else { - cs->subtyp = DIVA_ISA; - cs->hw.diva.ctrl = - card->para[1] + DIVA_ISA_CTRL; - cs->hw.diva.isac = - card->para[1] + DIVA_ISA_ISAC_DATA; - cs->hw.diva.hscx = - card->para[1] + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = - card->para[1] + DIVA_ISA_ISAC_ADR; - cs->hw.diva.hscx_adr = - card->para[1] + DIVA_HSCX_ADR; - } - goto ready; + return 1; } else { printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); return(0); @@ -652,111 +767,29 @@ printk(KERN_INFO "Diva PnP: no ISAPnP card found\n"); } } + } #endif #if CONFIG_PCI - cs->subtyp = 0; - if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { - if (pci_enable_device(dev_diva)) - return(0); - cs->subtyp = DIVA_PCI; - cs->irq = dev_diva->irq; - cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); - } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { - if (pci_enable_device(dev_diva_u)) - return(0); - cs->subtyp = DIVA_PCI; - cs->irq = dev_diva_u->irq; - cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); - } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { - if (pci_enable_device(dev_diva201)) - return(0); - cs->subtyp = DIVA_IPAC_PCI; - cs->irq = dev_diva201->irq; - cs->hw.diva.pci_cfg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 0), 4096, "diva"); - cs->hw.diva.cfg_reg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 1), 4096, "diva"); - } else { - printk(KERN_WARNING "Diva: No PCI card found\n"); - return(0); - } - - if (!cs->irq) { - printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); - goto err; - } - - if (!cs->hw.diva.cfg_reg) { - printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); - goto err; - } - cs->irq_flags |= SA_SHIRQ; -#endif /* CONFIG_PCI */ - if ((cs->subtyp == DIVA_IPAC_PCI) || - (cs->subtyp == DIVA_IPACX_PCI) ) { - cs->hw.diva.ctrl = 0; - cs->hw.diva.isac = 0; - cs->hw.diva.hscx = 0; - cs->hw.diva.isac_adr = 0; - cs->hw.diva.hscx_adr = 0; - bytecnt = 0; - } else { - cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; - cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; - cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; - cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; - bytecnt = 32; - } - } -ready: - printk(KERN_INFO - "Diva: %s card configured at %#lx IRQ %d\n", - (cs->subtyp == DIVA_PCI) ? "PCI" : - (cs->subtyp == DIVA_ISA) ? "ISA" : - (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : - (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", - cs->hw.diva.cfg_reg, cs->irq); - if ((cs->subtyp == DIVA_IPAC_PCI) || - (cs->subtyp == DIVA_IPACX_PCI) || - (cs->subtyp == DIVA_PCI) ) - printk(KERN_INFO "Diva: %s space at %#lx\n", - (cs->subtyp == DIVA_PCI) ? "PCI" : - (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", - cs->hw.diva.pci_cfg); - if ((cs->subtyp != DIVA_IPAC_PCI) && - (cs->subtyp != DIVA_IPACX_PCI) ) { - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) + if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA20, + dev_diva))) { + if (diva_pci_probe(card->cs, dev_diva)) return 0; + return 1; + } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA20_U, + dev_diva_u))) { + if (diva_pci_probe(card->cs, dev_diva_u)) + return 0; + return 1; + } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA201, + dev_diva201))) { + if (diva_ipac_pci_probe(card->cs, dev_diva201)) + return 0; + return 1; } - if (cs->subtyp == DIVA_IPAC_ISA) { - diva_ipac_isa_reset(cs); - cs->card_ops = &diva_ipac_isa_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else if (cs->subtyp == DIVA_IPAC_PCI) { - diva_ipac_pci_reset(cs); - cs->card_ops = &diva_ipac_pci_ops; - if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops)) - goto err; - } else if (cs->subtyp == DIVA_IPACX_PCI) { - diva_ipacx_pci_reset(cs); - cs->card_ops = &diva_ipacx_pci_ops; - if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops)) - goto err; - } else { /* DIVA 2.0 */ - diva_reset(cs); - cs->hw.diva.tl.function = (void *) diva_led_handler; - cs->hw.diva.tl.data = (long) cs; - init_timer(&cs->hw.diva.tl); - cs->card_ops = &diva_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - } - return 1; - err: - diva_release(cs); + printk(KERN_WARNING "Diva: No PCI card found\n"); +#endif /* CONFIG_PCI */ return 0; - } diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c --- a/drivers/isdn/hisax/elsa.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/elsa.c Thu Mar 6 22:52:04 2003 @@ -690,7 +690,47 @@ .irq_func = elsa_interrupt_ipac, }; -static unsigned char +static void __init +elsa_arcofi_init(struct IsdnCardState *cs) +{ +#if ARCOFI_USE + init_arcofi(cs); +#endif +} + +static void __init +elsa_timer_init(struct IsdnCardState *cs) +{ + cs->hw.elsa.tl.function = (void *) elsa_led_handler; + cs->hw.elsa.tl.data = (long) cs; + init_timer(&cs->hw.elsa.tl); +} + +static int __init +elsa_timer_test(struct IsdnCardState *cs) +{ + /* test timer */ + byteout(cs->hw.elsa.trig, 0xff); + byteout(cs->hw.elsa.timer, 0); + if (!TimerRun(cs)) { + byteout(cs->hw.elsa.timer, 0); /* second attempt */ + if (!TimerRun(cs)) { + printk(KERN_WARNING "Elsa: timer does not start\n"); + goto err; + } + } + HZDELAY(10 * HZ / 1000); /* wait >=10 ms */ + if (TimerRun(cs)) { + printk(KERN_WARNING "Elsa: timer does not run\n"); + goto err; + } + printk(KERN_INFO "Elsa: timer OK; resetting card\n"); + return 0; + err: + return -EBUSY; +} + +static unsigned char __init probe_elsa_adr(unsigned int adr, int typ) { int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0, @@ -699,15 +739,13 @@ /* In case of the elsa pcmcia card, this region is in use, reserved for us by the card manager. So we do not check it here, it would fail. */ - if (typ != ISDN_CTYPE_ELSA_PCMCIA && check_region(adr, 8)) { - printk(KERN_WARNING - "Elsa: Probing Port 0x%x: already in use\n", - adr); - return (0); + if (typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(adr, 8, "elsa")) { + printk(KERN_WARNING "Elsa: probing port 0x%x: in use\n", adr); + return 0; } for (i = 0; i < 16; i++) { - in1 = inb(adr + ELSA_CONFIG); /* 'toggelt' bei */ - in2 = inb(adr + ELSA_CONFIG); /* jedem Zugriff */ + in1 = inb(adr + ELSA_CONFIG); /* 'toggels' at */ + in2 = inb(adr + ELSA_CONFIG); /* each access */ p16_1 += 0x04 & in1; p16_2 += 0x04 & in2; p8_1 += 0x02 & in1; @@ -717,6 +755,7 @@ pfp_1 += 0x40 & in1; pfp_2 += 0x40 & in2; } + release_region(adr, 8); printk(KERN_INFO "Elsa: Probing IO 0x%x", adr); if (65 == ++p16_1 * ++p16_2) { printk(" PCC-16/PCF found\n"); @@ -736,18 +775,227 @@ } } -static unsigned int -probe_elsa(struct IsdnCardState *cs) +static int __init +elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - int i; - unsigned int CARD_portlist[] = - {0x160, 0x170, 0x260, 0x360, 0}; - - for (i = 0; CARD_portlist[i]; i++) { - if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ))) + u8 val; + int i, bytecnt = 8; + unsigned int CARD_portlist[] = {0x160, 0x170, 0x260, 0x360, 0}; + + cs->hw.elsa.base = card->para[0]; + printk(KERN_INFO "Elsa: Microlink IO probing\n"); + if (cs->hw.elsa.base) { + cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, cs->typ); + if (!cs->subtyp) { + printk(KERN_WARNING "Elsa: no Microlink at %#lx\n", + cs->hw.elsa.base); + goto err; + } + } else { + for (i = 0; CARD_portlist[i]; i++) { + cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ); + if (cs->subtyp) + cs->hw.elsa.base = CARD_portlist[i]; break; + } + } + if (!cs->hw.elsa.base) + goto err; + + cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; + cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; + cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; + cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; + val = bytein(cs->hw.elsa.cfg); + if (cs->subtyp == ELSA_PC) { + const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; + } else if (cs->subtyp == ELSA_PCC8) { + const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; + } else { + const u8 CARD_IrqTab[8] = {15, 10, 15, 3, 11, 5, 11, 9}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; } - return (CARD_portlist[i]); + val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; + if (val < 3) + val |= 8; + val += 'A' - 3; + if (val == 'B' || val == 'C') + val ^= 1; + if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) + val = 'C'; + printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", + Elsa_Types[cs->subtyp], cs->hw.elsa.base, val, cs->irq); + val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; + if (val) { + printk(KERN_WARNING "Elsa: Microlink S0 bus power bad\n"); + cs->hw.elsa.status |= ELSA_BAD_PWR; + } + switch (cs->subtyp) { + case ELSA_PCFPRO: bytecnt = 16; break; + } + if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) + goto err; + elsa_arcofi_init(cs); + elsa_timer_init(cs); + if (elsa_timer_test(cs)) + goto err; + elsa_reset(cs); + cs->card_ops = &elsa_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + if (cs->subtyp == ELSA_PC) { + val = readitac(cs, ITAC_SYS); + printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]); + writeitac(cs, ITAC_ISEN, 0); + writeitac(cs, ITAC_RFIE, 0); + writeitac(cs, ITAC_XFIE, 0); + writeitac(cs, ITAC_SCIE, 0); + writeitac(cs, ITAC_STIE, 0); + } + return 0; + err: + elsa_release(cs); + return -EBUSY; +} + +static int __init +elsa_qs_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int bytecnt = 8; + + cs->irq = card->para[0]; + cs->hw.elsa.base = card->para[1]; + cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; + cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; + cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; + printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n", + Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq); + switch (cs->subtyp) { + case ELSA_QS3000: bytecnt = 16; break; + } + if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) + goto err; + elsa_arcofi_init(cs); + elsa_timer_init(cs); + if (elsa_timer_test(cs)) + goto err; + elsa_reset(cs); + cs->card_ops = &elsa_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 0; + err: + elsa_release(cs); + return -EBUSY; +} + +static int __init +elsa_qs1000_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = ELSA_QS1000; + return elsa_qs_probe(cs, card); +} + +static int __init +elsa_qs3000_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = ELSA_QS3000; + return elsa_qs_probe(cs, card); +} + +static int __init +elsa_pcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + u8 val; + + cs->irq = card->para[0]; + cs->hw.elsa.base = card->para[1]; + cs->hw.elsa.ale = cs->hw.elsa.base + 0; + val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID); + if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ + cs->subtyp = ELSA_PCMCIA_IPAC; + cs->hw.elsa.isac = cs->hw.elsa.base + 2; + } else { + cs->subtyp = ELSA_PCMCIA; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + } + cs->hw.elsa.timer = 0; + cs->hw.elsa.trig = 0; + cs->hw.elsa.ctrl = 0; + printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n", + Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq); + elsa_arcofi_init(cs); + elsa_reset(cs); + if (cs->subtyp == ELSA_PCMCIA_IPAC) { + cs->card_ops = &elsa_ipac_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + } else { + cs->card_ops = &elsa_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + } + return 0; + err: + elsa_release(cs); + return -EBUSY; +} + +static int __init +elsa_qs_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, + int subtyp) +{ + int bytecnt = 2; + u8 pci_rev; + + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = subtyp; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.elsa.cfg = pci_resource_start(pdev, 1); + cs->hw.elsa.base = pci_resource_start(pdev, 3); + pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); + if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) { + printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n"); + __set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); + } + cs->hw.elsa.ale = cs->hw.elsa.base; + cs->hw.elsa.isac = cs->hw.elsa.base +1; + cs->hw.elsa.hscx = cs->hw.elsa.base +1; + printk(KERN_INFO "Elsa: %s defined at %#lx/%#x IRQ %d\n", + Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->hw.elsa.cfg, + cs->irq); + switch (cs->subtyp) { + case ELSA_QS3000PCI: bytecnt = 16; break; + } + if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) + goto err; + if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) + goto err; + elsa_arcofi_init(cs); + elsa_timer_init(cs); + elsa_reset(cs); + cs->card_ops = &elsa_ipac_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + return 0; + err: + elsa_release(cs); + return -EBUSY; } static struct pci_dev *dev_qs1000 __devinitdata = NULL; @@ -771,83 +1019,21 @@ int __devinit setup_elsa(struct IsdnCard *card) { - int bytecnt; - u8 val, pci_rev; - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, Elsa_revision); printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp)); - cs->hw.elsa.ctrl_reg = 0; - cs->hw.elsa.status = 0; - cs->hw.elsa.MFlag = 0; - cs->subtyp = 0; - if (cs->typ == ISDN_CTYPE_ELSA) { - cs->hw.elsa.base = card->para[0]; - printk(KERN_INFO "Elsa: Microlink IO probing\n"); - if (cs->hw.elsa.base) { - if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, - cs->typ))) { - printk(KERN_WARNING - "Elsa: no Elsa Microlink at %#lx\n", - cs->hw.elsa.base); - return (0); - } - } else - cs->hw.elsa.base = probe_elsa(cs); - if (cs->hw.elsa.base) { - cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; - cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; - cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; - cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; - val = bytein(cs->hw.elsa.cfg); - if (cs->subtyp == ELSA_PC) { - const u8 CARD_IrqTab[8] = - {7, 3, 5, 9, 0, 0, 0, 0}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; - } else if (cs->subtyp == ELSA_PCC8) { - const u8 CARD_IrqTab[8] = - {7, 3, 5, 9, 0, 0, 0, 0}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; - } else { - const u8 CARD_IrqTab[8] = - {15, 10, 15, 3, 11, 5, 11, 9}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; - } - val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; - if (val < 3) - val |= 8; - val += 'A' - 3; - if (val == 'B' || val == 'C') - val ^= 1; - if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) - val = 'C'; - printk(KERN_INFO - "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base, - val, cs->irq); - val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; - if (val) { - printk(KERN_WARNING - "Elsa: Microlink S0 bus power bad\n"); - cs->hw.elsa.status |= ELSA_BAD_PWR; - } - } else { - printk(KERN_WARNING - "No Elsa Microlink found\n"); - return (0); - } - } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) { + + if (card->typ == ISDN_CTYPE_ELSA) { + if (elsa_probe(card->cs, card)) + return 0; + return 1; + } else if (card->typ == ISDN_CTYPE_ELSA_PNP) { #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { struct pnp_card *pb; struct pnp_dev *pd; - + while(pdev->card_vendor) { if ((pb = pnp_find_card(pdev->card_vendor, pdev->card_device, @@ -878,10 +1064,15 @@ } card->para[1] = pnp_port_start(pd, 0); card->para[0] = pnp_irq(pd, 0); - if (pdev->function == ISAPNP_FUNCTION(0x133)) - cs->subtyp = ELSA_QS1000; - else - cs->subtyp = ELSA_QS3000; + if (pdev->function == ISAPNP_FUNCTION(0x133)) { + if (elsa_qs1000_probe(card->cs, card)) + return 0; + return 1; + } else { + if (elsa_qs3000_probe(card->cs, card)) + return 0; + return 1; + } break; } else { printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n"); @@ -897,184 +1088,33 @@ } } #endif - if (card->para[1] && card->para[0]) { - cs->hw.elsa.base = card->para[1]; - cs->irq = card->para[0]; - if (!cs->subtyp) - cs->subtyp = ELSA_QS1000; - } else { - printk(KERN_ERR "Elsa PnP: no parameter\n"); - } - cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; - cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; - cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; - printk(KERN_INFO - "Elsa: %s defined at %#lx IRQ %d\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base, - cs->irq); - } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) { - cs->hw.elsa.base = card->para[1]; - cs->irq = card->para[0]; - cs->hw.elsa.ale = cs->hw.elsa.base + 0; - val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID); - if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ - cs->subtyp = ELSA_PCMCIA_IPAC; - cs->hw.elsa.isac = cs->hw.elsa.base + 2; - cs->hw.elsa.hscx = cs->hw.elsa.base + 2; - } else { - cs->subtyp = ELSA_PCMCIA; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - } - cs->hw.elsa.timer = 0; - cs->hw.elsa.trig = 0; - cs->hw.elsa.ctrl = 0; - printk(KERN_INFO - "Elsa: %s defined at %#lx IRQ %d\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base, - cs->irq); - } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { + if (elsa_qs1000_probe(card->cs, card)) + return 0; + return 1; + + } else if (card->typ == ISDN_CTYPE_ELSA_PCMCIA) { + if (elsa_pcmcia_probe(card->cs, card)) + return 0; + return 1; + } else if (card->typ == ISDN_CTYPE_ELSA_PCI) { #if CONFIG_PCI - cs->subtyp = 0; if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { - if (pci_enable_device(dev_qs1000)) - return(0); - cs->subtyp = ELSA_QS1000PCI; - cs->irq = dev_qs1000->irq; - cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); - cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); - pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev); + if (elsa_qs_pci_probe(card->cs, dev_qs1000, + ELSA_QS1000PCI)) + return 0; + return 1; } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { - if (pci_enable_device(dev_qs3000)) - return(0); - cs->subtyp = ELSA_QS3000PCI; - cs->irq = dev_qs3000->irq; - cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1); - cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3); - pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev); + if (elsa_qs_pci_probe(card->cs, dev_qs3000, + ELSA_QS3000PCI)) + return 0; + return 1; } else { printk(KERN_WARNING "Elsa: No PCI card found\n"); - return(0); + return 0; } - if (!cs->irq) { - printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); - return(0); - } - - if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) { - printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); - return(0); - } - if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) { - printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n"); - set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); - } - cs->hw.elsa.ale = cs->hw.elsa.base; - cs->hw.elsa.isac = cs->hw.elsa.base +1; - cs->hw.elsa.hscx = cs->hw.elsa.base +1; - cs->hw.elsa.timer = 0; - cs->hw.elsa.trig = 0; - cs->irq_flags |= SA_SHIRQ; - printk(KERN_INFO - "Elsa: %s defined at %#lx/0x%x IRQ %d\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base, - cs->hw.elsa.cfg, - cs->irq); #endif /* CONFIG_PCI */ - } else - return (0); - - switch (cs->subtyp) { - case ELSA_PC: - case ELSA_PCC8: - case ELSA_PCC16: - case ELSA_QS1000: - case ELSA_PCMCIA: - case ELSA_PCMCIA_IPAC: - bytecnt = 8; - break; - case ELSA_PCFPRO: - case ELSA_PCF: - case ELSA_QS3000: - case ELSA_QS3000PCI: - bytecnt = 16; - break; - case ELSA_QS1000PCI: - bytecnt = 2; - break; - default: - printk(KERN_WARNING - "Unknown ELSA subtype %d\n", cs->subtyp); - return (0); - } - /* In case of the elsa pcmcia card, this region is in use, - reserved for us by the card manager. So we do not check it - here, it would fail. */ - if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA) - if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) - goto err; - - if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) - if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) - goto err; - -#if ARCOFI_USE - init_arcofi(cs); -#endif - - cs->hw.elsa.tl.function = (void *) elsa_led_handler; - cs->hw.elsa.tl.data = (long) cs; - init_timer(&cs->hw.elsa.tl); - /* Teste Timer */ - if (cs->hw.elsa.timer) { - byteout(cs->hw.elsa.trig, 0xff); - byteout(cs->hw.elsa.timer, 0); - if (!TimerRun(cs)) { - byteout(cs->hw.elsa.timer, 0); /* 2. Versuch */ - if (!TimerRun(cs)) { - printk(KERN_WARNING - "Elsa: timer do not start\n"); - goto err; - } - } - HZDELAY(1); /* wait >=10 ms */ - if (TimerRun(cs)) { - printk(KERN_WARNING "Elsa: timer do not run down\n"); - goto err; - } - printk(KERN_INFO "Elsa: timer OK; resetting card\n"); - } - elsa_reset(cs); - if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { - cs->card_ops = &elsa_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else { - cs->card_ops = &elsa_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; } - if (cs->subtyp == ELSA_PC) { - val = readitac(cs, ITAC_SYS); - printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]); - writeitac(cs, ITAC_ISEN, 0); - writeitac(cs, ITAC_RFIE, 0); - writeitac(cs, ITAC_XFIE, 0); - writeitac(cs, ITAC_SCIE, 0); - writeitac(cs, ITAC_STIE, 0); - } - return 1; - err: - elsa_release(cs); return 0; } diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c --- a/drivers/isdn/hisax/enternow_pci.c Mon Feb 24 10:29:08 2003 +++ b/drivers/isdn/hisax/enternow_pci.c Thu Mar 6 22:52:04 2003 @@ -263,13 +263,65 @@ .irq_func = enpci_interrupt, }; +static int __init +enpci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.njet.base = pci_resource_start(pdev, 0); + if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN")) + goto err; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD + + /* Reset an */ + cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff + OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + /* 50 ms Pause */ + schedule_timeout((50*HZ)/1000); + + cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ + OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.auxd = 0x00; // war 0xc0 + cs->hw.njet.dmactrl = 0; + + OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); + OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ); + OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); + + printk(KERN_INFO + "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + reset_enpci(cs); + cs->hw.njet.last_is0 = 0; + cs->hw.njet.bc_activate = enpci_bc_activate; + cs->hw.njet.bc_deactivate = enpci_bc_deactivate; + amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask); + + cs->card_ops = &enpci_ops; + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_netjet __initdata = NULL; /* called by config.c */ int __init setup_enternow_pci(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN @@ -278,72 +330,22 @@ strcpy(tmp, enternow_pci_rev); printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp)); - for ( ;; ) { - if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { - if (pci_enable_device(dev_netjet)) - return(0); - cs->irq = dev_netjet->irq; - if (!cs->irq) { - printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n"); - return(0); - } - cs->hw.njet.base = pci_resource_start(dev_netjet, 0); - if (!cs->hw.njet.base) { - printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n"); - return(0); - } - /* checks Sub-Vendor ID because system crashes with Traverse-Card */ - if ((dev_netjet->subsystem_vendor != 0x55) || - (dev_netjet->subsystem_device != 0x02)) { - printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n"); - printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n"); - return(0); - } - } else { - printk(KERN_WARNING "enter:now PCI: No PCI card found\n"); - return(0); + dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet); + if (dev_netjet) { + if (dev_netjet->subsystem_vendor != 0x55 || + dev_netjet->subsystem_device != 0x02) { + printk(KERN_WARNING "enter:now: You tried to load " + "this driver with an incompatible " + "TigerJet-card\n"); + printk(KERN_WARNING "Use type=20 for Traverse " + "NetJet PCI Card.\n"); + return 0; } - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD - - /* Reset an */ - cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff - OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - /* 50 ms Pause */ - schedule_timeout((50*HZ)/1000); - - cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ - OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0x00; // war 0xc0 - cs->hw.njet.dmactrl = 0; - - OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); - OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ); - OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); - - break; - } - printk(KERN_INFO - "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN")) + if (enpci_probe(card->cs, dev_netjet)) + return 1; return 0; - reset_enpci(cs); - cs->hw.njet.last_is0 = 0; - cs->hw.njet.bc_activate = enpci_bc_activate; - cs->hw.njet.bc_deactivate = enpci_bc_deactivate; - amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask); - - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &enpci_ops; - - return 1; + } + printk(KERN_WARNING "enter:now PCI: No PCI card found\n"); + return 0; } diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c --- a/drivers/isdn/hisax/gazel.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/gazel.c Thu Mar 6 22:52:04 2003 @@ -294,60 +294,6 @@ inithscxisac(cs); } -static int -r647_reserve_regions(struct IsdnCardState *cs) -{ - int i, base = cs->hw.gazel.hscx[0]; - - for (i = 0; i < 0xc000; i += 0x1000) { - if (!request_io(&cs->rs, i + base, 16, "gazel")) - goto err; - } - if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int -r685_reserve_regions(struct IsdnCardState *cs) -{ - if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel")) - goto err; - if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int -r742_reserve_regions(struct IsdnCardState *cs) -{ - if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int -r753_reserve_regions(struct IsdnCardState *cs) -{ - if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) - goto err; - if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - static struct card_ops r647_ops = { .init = gazel_init, .reset = r647_reset, @@ -377,194 +323,213 @@ }; static int __init -setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) +gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n"); - // we got an irq parameter, assume it is an ISA card - // R742 decodes address even in not started... - // R647 returns FF if not present or not started - // eventually needs improvment - cs->hw.gazel.ipac = card->para[1]; - if (ipac_read(cs, IPAC_ID) == 1) - cs->subtyp = R742; - else - cs->subtyp = R647; + int i, base; + cs->subtyp = R647; + cs->irq = card->para[0]; cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; + + printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + cs->hw.gazel.isac = card->para[1] + 0x8000; cs->hw.gazel.hscx[0] = card->para[1]; cs->hw.gazel.hscx[1] = card->para[1] + 0x4000; - cs->irq = card->para[0]; cs->hw.gazel.isacfifo = cs->hw.gazel.isac; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; - switch (cs->subtyp) { - case R647: - printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); - cs->dc.isac.adf2 = 0x87; - printk(KERN_INFO - "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO - "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - - return r647_reserve_regions(cs); - case R742: - printk(KERN_INFO "Gazel: Card ISA R742 found\n"); - printk(KERN_INFO - "Gazel: config irq:%d ipac:0x%X\n", - cs->irq, cs->hw.gazel.ipac); - return r742_reserve_regions(cs); + base = cs->hw.gazel.hscx[0]; + for (i = 0; i < 0xc000; i += 0x1000) { + if (!request_io(&cs->rs, base + i, 16, "gazel")) + goto err; } + if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel")) + goto err; + + cs->card_ops = &r647_ops; + if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops)) + goto err; + + cs->card_ops->reset(cs); return 0; + err: + hisax_release_resources(cs); + return -EBUSY; } -static struct pci_dev *dev_tel __initdata = NULL; - static int __init -setup_gazelpci(struct IsdnCardState *cs) +gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; - u8 pci_irq = 0, found; - u_int nbseek, seekcard; - u8 pci_rev; + cs->subtyp = R742; + cs->irq = card->para[0]; + cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; - printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); + printk(KERN_INFO "Gazel: Card ISA R742 found\n"); + printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n", + cs->irq, cs->hw.gazel.ipac); - found = 0; - if (!pci_present()) { - printk(KERN_WARNING "Gazel: No PCI bus present\n"); - return 1; - } - seekcard = PCI_DEVICE_ID_PLX_R685; - for (nbseek = 0; nbseek < 3; nbseek++) { - if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) { - if (pci_enable_device(dev_tel)) - return 1; - pci_irq = dev_tel->irq; - pci_ioaddr0 = pci_resource_start(dev_tel, 1); - pci_ioaddr1 = pci_resource_start(dev_tel, 2); - found = 1; - } - if (found) - break; - else { - switch (seekcard) { - case PCI_DEVICE_ID_PLX_R685: - seekcard = PCI_DEVICE_ID_PLX_R753; - break; - case PCI_DEVICE_ID_PLX_R753: - seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO; - break; - } - } - } - if (!found) { - printk(KERN_WARNING "Gazel: No PCI card found\n"); - return -ENODEV; - } - if (!pci_irq) { - printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n"); - return -ENODEV; - } - cs->hw.gazel.pciaddr[0] = pci_ioaddr0; - cs->hw.gazel.pciaddr[1] = pci_ioaddr1; + if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) + goto err; - pci_ioaddr1 &= 0xfffe; - cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe; - cs->hw.gazel.ipac = pci_ioaddr1; - cs->hw.gazel.isac = pci_ioaddr1 + 0x80; - cs->hw.gazel.hscx[0] = pci_ioaddr1; - cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40; - cs->hw.gazel.isacfifo = cs->hw.gazel.isac; + cs->card_ops = &r742_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + + cs->card_ops->reset(cs); + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = R685; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1); + cs->hw.gazel.isac = pci_resource_start(pdev, 2) + 0x80; + cs->hw.gazel.hscx[0] = pci_resource_start(pdev, 2); + cs->hw.gazel.hscx[1] = pci_resource_start(pdev, 2) + 0x40; + cs->hw.gazel.isacfifo = cs->hw.gazel.isac; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; - cs->irq = pci_irq; - cs->irq_flags |= SA_SHIRQ; + cs->dc.isac.adf2 = 0x87; - switch (seekcard) { - case PCI_DEVICE_ID_PLX_R685: - printk(KERN_INFO "Gazel: Card PCI R685 found\n"); - cs->subtyp = R685; - cs->dc.isac.adf2 = 0x87; - printk(KERN_INFO - "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO - "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - return r685_reserve_regions(cs); - case PCI_DEVICE_ID_PLX_R753: - case PCI_DEVICE_ID_PLX_DJINN_ITOO: - printk(KERN_INFO "Gazel: Card PCI R753 found\n"); - cs->subtyp = R753; - printk(KERN_INFO - "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); - /* - * Erratum for PLX9050, revision 1: - * If bit 7 of BAR 0/1 is set, local config registers - * can not be read (write is okay) - */ - if (cs->hw.gazel.cfg_reg & 0x80) { - pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev); - if (pci_rev == 1) { - printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n"); - set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); - } + if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel")) + goto err; + if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) + goto err; + + printk(KERN_INFO "Gazel: Card PCI R685 found\n"); + printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + + cs->card_ops = &r685_ops; + if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops)) + goto err; + + cs->card_ops->reset(cs); + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + u8 pci_rev; + + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = R753; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1); + cs->hw.gazel.ipac = pci_resource_start(pdev, 2); + + if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) + goto err; + if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) + goto err; + + printk(KERN_INFO "Gazel: Card PCI R753 found\n"); + printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); + /* + * Erratum for PLX9050, revision 1: + * If bit 7 of BAR 0/1 is set, local config registers + * can not be read (write is okay) + */ + if (cs->hw.gazel.cfg_reg & 0x80) { + pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); + if (pci_rev == 1) { + printk(KERN_INFO "Gazel: PLX9050 rev1 workaround " + "activated\n"); + __set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); } - return r753_reserve_regions(cs); } + cs->card_ops = &r753_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + + cs->card_ops->reset(cs); return 0; + err: + hisax_release_resources(cs); + return -EBUSY; } +static struct pci_dev *dev_tel __initdata = NULL; +static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685; + int __init setup_gazel(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, gazel_revision); printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp)); if (card->para[0]) { - if (setup_gazelisa(card, cs)) - return (0); - } else { - if (setup_gazelpci(cs)) - return (0); + printk(KERN_INFO "Gazel: ISA card automatic recognition\n"); + // we got an irq parameter, assume it is an ISA card + // R742 decodes address even in not started... + // R647 returns FF if not present or not started + // eventually needs improvment + card->cs->hw.gazel.ipac = card->para[1]; + if (ipac_read(card->cs, IPAC_ID) == 1) { + if (gazel742_probe(card->cs, card)) + return 0; + } else { + if (gazel647_probe(card->cs, card)) + return 0; + } + return 1; } - switch (cs->subtyp) { - case R647: - case R685: - if (cs->subtyp == R647) { - cs->card_ops = &r647_ops; - if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops)) - goto err; - } else { - cs->card_ops = &r685_ops; - if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops)) - goto err; + for (;;) { + dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel); + if (dev_tel) { + switch (dev_id) { + case PCI_DEVICE_ID_PLX_R685: + if (gazel685_probe(card->cs, dev_tel)) + return 0; + return 1; + case PCI_DEVICE_ID_PLX_R753: + case PCI_DEVICE_ID_PLX_DJINN_ITOO: + if (gazel753_probe(card->cs, dev_tel)) + return 0; + return 1; + } } - cs->card_ops->reset(cs); - break; - case R742: - case R753: - if (cs->subtyp == R742) { - cs->card_ops = &r742_ops; - } else { - cs->card_ops = &r753_ops; + switch (dev_id) { + case PCI_DEVICE_ID_PLX_R685: + dev_id = PCI_DEVICE_ID_PLX_R753; + case PCI_DEVICE_ID_PLX_R753: + dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO; + default: + break; } - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - cs->card_ops->reset(cs); - break; } - return 1; - err: - hisax_release_resources(cs); + printk(KERN_WARNING "Gazel: No PCI card found\n"); return 0; } + + diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c --- a/drivers/isdn/hisax/hfc_pci.c Sun Jan 12 16:05:35 2003 +++ b/drivers/isdn/hisax/hfc_pci.c Thu Mar 6 22:52:04 2003 @@ -1382,72 +1382,41 @@ }; -/* this variable is used as card index when more than one cards are present */ -static struct pci_dev *dev_hfcpci __initdata = NULL; - -int __init -setup_hfcpci(struct IsdnCard *card) +static int __init +niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, int i) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - int i; - struct pci_dev *tmp_hfcpci = NULL; + int rc; - strcpy(tmp, hfcpci_revision); - printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); - cs->hw.hfcpci.int_s1 = 0; - cs->dc.hfcpci.ph_state = 0; - cs->hw.hfcpci.fifo = 255; + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; - i = 0; - while (id_list[i].vendor_id) { - tmp_hfcpci = pci_find_device(id_list[i].vendor_id, - id_list[i].device_id, - dev_hfcpci); - i++; - if (tmp_hfcpci) { - if (pci_enable_device(tmp_hfcpci)) - continue; - pci_set_master(tmp_hfcpci); - if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) - continue; - else - break; - } - } + pci_set_master(pdev); + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.hfcpci.pdev = pdev; + + cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, + pci_resource_start(pdev, 1), 128, + "hfc_pci"); + if (!cs->hw.hfcpci.pci_io) + goto err; - if (tmp_hfcpci) { - i--; - dev_hfcpci = tmp_hfcpci; /* old device */ - cs->irq = dev_hfcpci->irq; - cs->hw.hfcpci.pdev = tmp_hfcpci; - if (!cs->irq) { - printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); - return (0); - } - printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name); - } else { - printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); - return (0); - } /* Allocate memory for FIFOS */ - cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma); - if (!cs->hw.hfcpci.fifos) { - printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); - return 0; - } + rc = -ENOMEM; + cs->hw.hfcpci.fifos = pci_alloc_consistent(pdev, 32768, + &cs->hw.hfcpci.fifos_dma); + if (!cs->hw.hfcpci.fifos) + goto err; + pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80, (u_int)cs->hw.hfcpci.fifos_dma); - cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, dev_hfcpci->resource[ 1].start, 256, "hfc_pci"); - if (!cs->hw.hfcpci.pci_io) - goto err; - - printk(KERN_INFO - "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", - (u_int) cs->hw.hfcpci.pci_io, - (u_int) cs->hw.hfcpci.fifos, - (u_int) cs->hw.hfcpci.fifos_dma, - cs->irq, HZ); + printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s name: %s\n", + id_list[i].vendor_name, id_list[i].card_name); + printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d\n", + (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos, + (u_int) cs->hw.hfcpci.fifos_dma, cs->irq); printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID)); cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ cs->hw.hfcpci.int_m1 = 0; @@ -1456,17 +1425,46 @@ /* At this point the needed PCI config is done */ /* fifos are still not enabled */ - cs->irq_flags |= SA_SHIRQ; - + init_timer(&cs->hw.hfcpci.timer); cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; cs->hw.hfcpci.timer.data = (long) cs; - init_timer(&cs->hw.hfcpci.timer); hfcpci_reset(cs); cs->auxcmd = &hfcpci_auxcmd; cs->card_ops = &hfcpci_ops; - return 1; + return 0; err: hisax_release_resources(cs); + return -EBUSY; +} + +/* this variable is used as card index when more than one cards are present */ +static struct pci_dev *dev_hfcpci __initdata = NULL; + +int __init +setup_hfcpci(struct IsdnCard *card) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + int i; + struct pci_dev *tmp_hfcpci = NULL; + + strcpy(tmp, hfcpci_revision); + printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); + cs->hw.hfcpci.int_s1 = 0; + cs->dc.hfcpci.ph_state = 0; + cs->hw.hfcpci.fifo = 255; + + for (i = 0; id_list[i].vendor_id; i++) { + tmp_hfcpci = pci_find_device(id_list[i].vendor_id, + id_list[i].device_id, + dev_hfcpci); + if (!tmp_hfcpci) + continue; + + if (niccy_pci_probe(card->cs, tmp_hfcpci, i) < 0) + return 0; + return 1; + } return 0; } diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c --- a/drivers/isdn/hisax/hfc_sx.c Tue Feb 25 11:05:23 2003 +++ b/drivers/isdn/hisax/hfc_sx.c Thu Mar 6 22:52:04 2003 @@ -1159,6 +1159,74 @@ .irq_func = hfcsx_interrupt, }; +static int __init +hfcsx_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int rc; + char c; + + cs->irq = card->para[0]; + cs->hw.hfcsx.base = card->para[1] & 0xfffe; + + cs->hw.hfcsx.fifo = 255; + cs->hw.hfcsx.int_s1 = 0; + cs->dc.hfcsx.ph_state = 0; + + rc = -EBUSY; + if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn")) + goto err; + + rc = -ENODEV; + byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); + byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); + udelay(10); + cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); + switch (cs->hw.hfcsx.chip >> 4) { + case 1: + c ='+'; + break; + case 9: + c ='P'; + break; + default: + printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n", + cs->hw.hfcsx.chip >> 4); + goto err; + } + if (!ccd_sp_irqtab[cs->irq & 0xF]) { + printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n", + cs->irq & 0xF); + goto err; + } + rc = -ENOMEM; + cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC); + if (!cs->hw.hfcsx.extra) { + printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); + goto err; + } + printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d\n", + c, (u_int) cs->hw.hfcsx.base, cs->irq); + + cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcsx.int_m1 = 0; + Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); + + init_timer(&cs->hw.hfcsx.timer); + cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; + cs->hw.hfcsx.timer.data = (long) cs; + cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ + cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not eval. */ + + hfcsx_reset(cs); + cs->auxcmd = &hfcsx_auxcmd; + cs->card_ops = &hfcsx_ops; + return 0; + err: + hisax_release_resources(cs); + return rc; +} + #ifdef __ISAPNP__ static struct isapnp_device_id hfc_ids[] __initdata = { { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620), @@ -1174,7 +1242,6 @@ int __devinit setup_hfcsx(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, hfcsx_revision); @@ -1227,62 +1294,7 @@ } } #endif - cs->hw.hfcsx.base = card->para[1] & 0xfffe; - cs->irq = card->para[0]; - cs->hw.hfcsx.int_s1 = 0; - cs->dc.hfcsx.ph_state = 0; - cs->hw.hfcsx.fifo = 255; - - if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn")) - return 0; - byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); - byteout(cs->hw.hfcsx.base + 1, - ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); - udelay(10); - cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); - switch (cs->hw.hfcsx.chip >> 4) { - case 1: - tmp[0] ='+'; - break; - case 9: - tmp[0] ='P'; - break; - default: - printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n", - cs->hw.hfcsx.chip >> 4); - hisax_release_resources(cs); + if (hfcsx_probe(card->cs, card) < 0) return 0; - } - if (!ccd_sp_irqtab[cs->irq & 0xF]) { - printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n", - cs->irq & 0xF); - hisax_release_resources(cs); - return 0; - } - cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), - GFP_ATOMIC); - if (!cs->hw.hfcsx.extra) { - hisax_release_resources(cs); - printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); - return 0; - } - - printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n", - tmp[0], (u_int) cs->hw.hfcsx.base, - cs->irq, HZ); - cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ - cs->hw.hfcsx.int_m1 = 0; - Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); - - cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; - cs->hw.hfcsx.timer.data = (long) cs; - cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ - cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */ - init_timer(&cs->hw.hfcsx.timer); - - hfcsx_reset(cs); - cs->auxcmd = &hfcsx_auxcmd; - cs->card_ops = &hfcsx_ops; return 1; } diff -Nru a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c --- a/drivers/isdn/hisax/hfcscard.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/hfcscard.c Thu Mar 6 22:52:04 2003 @@ -133,6 +133,50 @@ .irq_func = hfcs_interrupt, }; +static int __init +hfcs_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->irq = card->para[0]; + cs->hw.hfcD.addr = card->para[1]; + + if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn")) + goto err; + + printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n", + cs->hw.hfcD.addr, cs->irq); + + cs->hw.hfcD.cip = 0; + cs->hw.hfcD.int_s1 = 0; + cs->hw.hfcD.send = NULL; + cs->bcs[0].hw.hfc.send = NULL; + cs->bcs[1].hw.hfc.send = NULL; + cs->hw.hfcD.dfifosize = 512; + cs->dc.hfcd.ph_state = 0; + cs->hw.hfcD.fifo = 255; + + if (cs->typ == ISDN_CTYPE_TELES3C) { + cs->hw.hfcD.bfifosize = 1024 + 512; + /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x56, cs->hw.hfcD.addr | 1); + } else if (cs->typ == ISDN_CTYPE_ACERP10) { + cs->hw.hfcD.bfifosize = 7*1024 + 512; + /* Acer P10 IO ADR is 0x300 */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x57, cs->hw.hfcD.addr | 1); + } + set_cs_func(cs); + init_timer(&cs->hw.hfcD.timer); + cs->hw.hfcD.timer.function = (void *) hfcs_Timer; + cs->hw.hfcD.timer.data = (long) cs; + hfcs_reset(cs); + cs->card_ops = &hfcs_ops; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + #ifdef __ISAPNP__ static struct isapnp_device_id hfc_ids[] __initdata = { { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114), @@ -166,7 +210,6 @@ int __init setup_hfcs(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, hfcs_revision); @@ -220,42 +263,8 @@ } } #endif - cs->hw.hfcD.addr = card->para[1] & 0xfffe; - cs->irq = card->para[0]; - cs->hw.hfcD.cip = 0; - cs->hw.hfcD.int_s1 = 0; - cs->hw.hfcD.send = NULL; - cs->bcs[0].hw.hfc.send = NULL; - cs->bcs[1].hw.hfc.send = NULL; - cs->hw.hfcD.dfifosize = 512; - cs->dc.hfcd.ph_state = 0; - cs->hw.hfcD.fifo = 255; - if (cs->typ == ISDN_CTYPE_TELES3C) { - cs->hw.hfcD.bfifosize = 1024 + 512; - } else if (cs->typ == ISDN_CTYPE_ACERP10) { - cs->hw.hfcD.bfifosize = 7*1024 + 512; - } else - return (0); - if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn")) + if (hfcs_probe(card->cs, card) < 0) return 0; - printk(KERN_INFO - "HFCS: defined at 0x%x IRQ %d HZ %d\n", - cs->hw.hfcD.addr, - cs->irq, HZ); - if (cs->typ == ISDN_CTYPE_TELES3C) { - /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ - outb(0x00, cs->hw.hfcD.addr); - outb(0x56, cs->hw.hfcD.addr | 1); - } else if (cs->typ == ISDN_CTYPE_ACERP10) { - /* Acer P10 IO ADR is 0x300 */ - outb(0x00, cs->hw.hfcD.addr); - outb(0x57, cs->hw.hfcD.addr | 1); - } - set_cs_func(cs); - cs->hw.hfcD.timer.function = (void *) hfcs_Timer; - cs->hw.hfcD.timer.data = (long) cs; - init_timer(&cs->hw.hfcD.timer); - hfcs_reset(cs); - cs->card_ops = &hfcs_ops; - return (1); + return 1; + } diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h --- a/drivers/isdn/hisax/hisax.h Sun Jan 12 16:03:30 2003 +++ b/drivers/isdn/hisax/hisax.h Thu Mar 6 23:20:18 2003 @@ -782,7 +782,6 @@ struct gazel_hw { unsigned int cfg_reg; - unsigned int pciaddr[2]; signed int ipac; signed int isac; signed int hscx[2]; @@ -1073,264 +1072,17 @@ #define ISDN_CTYPE_COUNT 41 -#ifdef ISDN_CHIP_ISAC -#undef ISDN_CHIP_ISAC -#endif - -#ifdef CONFIG_HISAX_16_0 -#define CARD_TELES0 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_TELES0 0 -#endif - -#ifdef CONFIG_HISAX_16_3 -#define CARD_TELES3 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_TELES3 0 -#endif - -#ifdef CONFIG_HISAX_TELESPCI -#define CARD_TELESPCI 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_TELESPCI 0 -#endif - -#ifdef CONFIG_HISAX_AVM_A1 -#define CARD_AVM_A1 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_AVM_A1 0 -#endif - -#ifdef CONFIG_HISAX_AVM_A1_PCMCIA -#define CARD_AVM_A1_PCMCIA 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_AVM_A1_PCMCIA 0 -#endif - -#ifdef CONFIG_HISAX_FRITZPCI -#define CARD_FRITZPCI 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_FRITZPCI 0 -#endif - -#ifdef CONFIG_HISAX_ELSA -#define CARD_ELSA 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_ELSA 0 -#endif - -#ifdef CONFIG_HISAX_IX1MICROR2 -#define CARD_IX1MICROR2 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_IX1MICROR2 0 -#endif - -#ifdef CONFIG_HISAX_DIEHLDIVA -#define CARD_DIEHLDIVA 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_DIEHLDIVA 0 -#endif - -#ifdef CONFIG_HISAX_ASUSCOM -#define CARD_ASUSCOM 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_ASUSCOM 0 -#endif - -#ifdef CONFIG_HISAX_TELEINT -#define CARD_TELEINT 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_TELEINT 0 -#endif - -#ifdef CONFIG_HISAX_SEDLBAUER -#define CARD_SEDLBAUER 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_SEDLBAUER 0 -#endif - -#ifdef CONFIG_HISAX_SPORTSTER -#define CARD_SPORTSTER 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_SPORTSTER 0 -#endif - -#ifdef CONFIG_HISAX_MIC -#define CARD_MIC 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_MIC 0 -#endif - -#ifdef CONFIG_HISAX_NETJET -#define CARD_NETJET_S 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_NETJET_S 0 -#endif - -#ifdef CONFIG_HISAX_HFCS -#define CARD_HFCS 1 -#else -#define CARD_HFCS 0 -#endif - -#ifdef CONFIG_HISAX_HFC_PCI -#define CARD_HFC_PCI 1 -#else -#define CARD_HFC_PCI 0 -#endif - -#ifdef CONFIG_HISAX_HFC_SX -#define CARD_HFC_SX 1 -#else -#define CARD_HFC_SX 0 -#endif - -#ifdef CONFIG_HISAX_AMD7930 -#define CARD_AMD7930 1 -#else -#define CARD_AMD7930 0 -#endif - -#ifdef CONFIG_HISAX_NICCY -#define CARD_NICCY 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_NICCY 0 -#endif - -#ifdef CONFIG_HISAX_ISURF -#define CARD_ISURF 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_ISURF 0 -#endif - -#ifdef CONFIG_HISAX_S0BOX -#define CARD_S0BOX 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_S0BOX 0 -#endif - -#ifdef CONFIG_HISAX_HSTSAPHIR -#define CARD_HSTSAPHIR 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_HSTSAPHIR 0 -#endif - #ifdef CONFIG_HISAX_TESTEMU -#define CARD_TESTEMU 1 #define ISDN_CTYPE_TESTEMU 99 #undef ISDN_CTYPE_COUNT #define ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU -#else -#define CARD_TESTEMU 0 -#endif - -#ifdef CONFIG_HISAX_BKM_A4T -#define CARD_BKM_A4T 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_BKM_A4T 0 -#endif - -#ifdef CONFIG_HISAX_SCT_QUADRO -#define CARD_SCT_QUADRO 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_SCT_QUADRO 0 -#endif - -#ifdef CONFIG_HISAX_GAZEL -#define CARD_GAZEL 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_GAZEL 0 -#endif - -#ifdef CONFIG_HISAX_W6692 -#define CARD_W6692 1 -#ifndef ISDN_CHIP_W6692 -#define ISDN_CHIP_W6692 1 -#endif -#else -#define CARD_W6692 0 #endif #ifdef CONFIG_HISAX_NETJET_U -#define CARD_NETJET_U 1 -#ifndef ISDN_CHIP_ICC -#define ISDN_CHIP_ICC 1 -#endif #ifndef HISAX_UINTERFACE #define HISAX_UINTERFACE 1 #endif #else -#define CARD_NETJET_U 0 -#endif - -#ifdef CONFIG_HISAX_ENTERNOW_PCI -#define CARD_FN_ENTERNOW_PCI 1 #endif #define TEI_PER_CARD 1 @@ -1402,7 +1154,7 @@ int HiSax_command(isdn_ctrl * ic); int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb); void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...); -void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args); +void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args); void HiSax_reportcard(int cardnr, int sel); int QuickHex(char *txt, u8 * p, int cnt); void LogFrame(struct IsdnCardState *cs, u8 * p, int size); diff -Nru a/drivers/isdn/hisax/hisax_fcclassic.c b/drivers/isdn/hisax/hisax_fcclassic.c --- a/drivers/isdn/hisax/hisax_fcclassic.c Sat Jan 4 07:35:38 2003 +++ b/drivers/isdn/hisax/hisax_fcclassic.c Sat Feb 22 08:50:25 2003 @@ -231,7 +231,7 @@ adapter->isac.write_isac = &fcclassic_write_isac; adapter->isac.read_isac_fifo = &fcclassic_read_isac_fifo; adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo; - isac_setup(&adapter->isac); + hisax_isac_setup(&adapter->isac); for (i = 0; i < 2; i++) { hscx_init(&adapter->hscx[i]); adapter->hscx[i].priv = adapter; diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c --- a/drivers/isdn/hisax/hisax_fcpcipnp.c Wed Jan 15 08:22:25 2003 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c Sat Feb 22 10:05:19 2003 @@ -46,24 +46,22 @@ MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver"); -// FIXME temporary hack until I sort out the new PnP stuff -#define __ISAPNP__ - static struct pci_device_id fcpci_ids[] __devinitdata = { - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1 , PCI_ANY_ID, PCI_ANY_ID, - 0, 0, (unsigned long) "Fritz!Card PCI" }, - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, (unsigned long) "Fritz!Card PCI v2" }, - { } + { .vendor = PCI_VENDOR_ID_AVM, + .device = PCI_DEVICE_ID_AVM_A1, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) "Fritz!Card PCI", + }, + { .vendor = PCI_VENDOR_ID_AVM, + .device = PCI_DEVICE_ID_AVM_A1_V2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) "Fritz!Card PCI v2" }, + {} }; -MODULE_DEVICE_TABLE(pci, fcpci_ids); -static struct pnp_card_device_id fcpnp_ids[] __devinitdata = { - { .id = "AVM0900", - .driver_data = (unsigned long) "Fritz!Card PnP", - .devs = { { "AVM0900" } } } -}; -MODULE_DEVICE_TABLE(pnp_card, fcpnp_ids); +MODULE_DEVICE_TABLE(pci, fcpci_ids); static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); @@ -782,7 +780,7 @@ case AVM_FRITZ_PCI: case AVM_FRITZ_PNP: fcpci_init(adapter); - isac_setup(&adapter->isac); + hisax_isac_setup(&adapter->isac); break; } val = adapter->read_hdlc_status(adapter, 0); @@ -908,10 +906,10 @@ .id_table = fcpci_ids, }; -#ifdef __ISAPNP__ +#ifdef CONFIG_PNP_CARD static int __devinit fcpnp_probe(struct pnp_card *card, - const struct pnp_card_device_id *card_id) + const struct pnp_card_id *card_id) { struct fritz_adapter *adapter; struct pnp_dev *pnp_dev; @@ -957,6 +955,14 @@ delete_adapter(adapter); } +static struct pnp_card_id fcpnp_ids[] __devinitdata = { + { .id = "AVM0900", + .driver_data = (unsigned long) "Fritz!Card PnP", + .devs = { { "AVM0900" } }, + }, + {} +}; + static struct pnpc_driver fcpnp_driver = { .name = "fcpnp", .probe = fcpnp_probe, @@ -968,7 +974,7 @@ static int __init hisax_fcpcipnp_init(void) { - int retval, pci_nr_found; + int retval = 0, pci_nr_found; printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n"); @@ -977,10 +983,8 @@ goto out; pci_nr_found = retval; -#ifdef __ISAPNP__ +#ifdef CONFIG_PNP_CARD retval = pnpc_register_driver(&fcpnp_driver); -#else - retval = 0; #endif if (retval < 0) goto out_unregister_pci; @@ -988,14 +992,14 @@ #if !defined(CONFIG_HOTPLUG) || defined(MODULE) if (pci_nr_found + retval == 0) { retval = -ENODEV; - goto out_unregister_isapnp; + goto out_unregister_pnp; } #endif return 0; #if !defined(CONFIG_HOTPLUG) || defined(MODULE) - out_unregister_isapnp: -#ifdef __ISAPNP__ + out_unregister_pnp: +#ifdef CONFIG_PNP_CARD pnpc_unregister_driver(&fcpnp_driver); #endif #endif @@ -1007,7 +1011,7 @@ static void __exit hisax_fcpcipnp_exit(void) { -#ifdef __ISAPNP__ +#ifdef CONFIG_PNP_CARD pnpc_unregister_driver(&fcpnp_driver); #endif pci_unregister_driver(&fcpci_driver); diff -Nru a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c --- a/drivers/isdn/hisax/hisax_isac.c Sat Jan 4 07:35:38 2003 +++ b/drivers/isdn/hisax/hisax_isac.c Sat Feb 22 08:50:25 2003 @@ -770,7 +770,7 @@ FsmInitTimer(&isac->l1m, &isac->timer); } -void isac_setup(struct isac *isac) +void hisax_isac_setup(struct isac *isac) { int val, eval; @@ -890,7 +890,7 @@ EXPORT_SYMBOL(isacsx_setup); EXPORT_SYMBOL(isacsx_irq); -EXPORT_SYMBOL(isac_setup); +EXPORT_SYMBOL(hisax_isac_setup); EXPORT_SYMBOL(isac_irq); module_init(hisax_isac_init); diff -Nru a/drivers/isdn/hisax/hisax_isac.h b/drivers/isdn/hisax/hisax_isac.h --- a/drivers/isdn/hisax/hisax_isac.h Sat Jan 4 07:35:38 2003 +++ b/drivers/isdn/hisax/hisax_isac.h Sat Feb 22 08:50:25 2003 @@ -36,7 +36,7 @@ void isac_init(struct isac *isac); void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg); -void isac_setup(struct isac *isac); +void hisax_isac_setup(struct isac *isac); void isac_irq(struct isac *isac); void isacsx_setup(struct isac *isac); diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c --- a/drivers/isdn/hisax/isdnl1.c Sat Jan 11 11:24:09 2003 +++ b/drivers/isdn/hisax/isdnl1.c Sat Feb 22 09:10:42 2003 @@ -126,7 +126,7 @@ }; void -debugl1(struct IsdnCardState *cs, char *fmt, ...) +debugl1(struct IsdnCardState *cs, const char *fmt, ...) { va_list args; char tmp[8]; diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h --- a/drivers/isdn/hisax/isdnl1.h Sat Jan 11 11:24:09 2003 +++ b/drivers/isdn/hisax/isdnl1.h Sat Feb 22 09:10:42 2003 @@ -28,7 +28,7 @@ #define B_LL_CONNECT 9 #define B_LL_OK 10 -extern void debugl1(struct IsdnCardState *cs, char *fmt, ...); +extern void debugl1(struct IsdnCardState *cs, const char *fmt, ...); extern void DChannel_proc_xmt(struct IsdnCardState *cs); extern void DChannel_proc_rcv(struct IsdnCardState *cs); extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg); diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c --- a/drivers/isdn/hisax/isurf.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/isurf.c Thu Mar 6 22:52:04 2003 @@ -187,95 +187,92 @@ static struct pnp_card *pnp_surf __devinitdata = NULL; #endif -int __init -setup_isurf(struct IsdnCard *card) +static int __init +isurf_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; unsigned long phymem; - char tmp[64]; - strcpy(tmp, ISurf_revision); - printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp)); - - if (card->para[1] && card->para[2]) { - cs->hw.isurf.reset = card->para[1]; - phymem = card->para[2]; - cs->irq = card->para[0]; - } else { -#ifdef __ISAPNP__ - struct pnp_card *pb; - struct pnp_dev *pd; + phymem = card->para[2]; + cs->hw.isurf.reset = card->para[1]; + cs->irq = card->para[0]; - if (isapnp_present()) { - cs->subtyp = 0; - if ((pb = pnp_find_card( - ISAPNP_VENDOR('S', 'I', 'E'), - ISAPNP_FUNCTION(0x0010), pnp_surf))) { - pnp_surf = pb; - pd = NULL; - if (!(pd = pnp_find_dev(pnp_surf, - ISAPNP_VENDOR('S', 'I', 'E'), - ISAPNP_FUNCTION(0x0010), pd))) { - printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n"); - return (0); - } - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "ISurfPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "ISurfPnP: activate failed\n"); - pnp_device_detach(pd); - return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { - printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); - pnp_device_detach(pd); - return(0); - } - cs->hw.isurf.reset = pnp_port_start(pd, 0); - phymem = pnp_port_start(pd, 1); - cs->irq = pnp_irq(pd, 0); - } else { - printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n"); - return(0); - } - } else { - printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n"); - return(0); - } -#else - printk(KERN_WARNING "HiSax: %s port/mem not set\n", - CardType[card->typ]); - return (0); -#endif - } if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn")) goto err; - cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, "isurf iomem"); + + cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, + "isurf iomem"); if (!cs->hw.isurf.isar) goto err; cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET; - printk(KERN_INFO - "ISurf: defined at 0x%x 0x%lx IRQ %d\n", - cs->hw.isurf.reset, - card->para[2], - cs->irq); + printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n", + cs->hw.isurf.reset, phymem, cs->irq); cs->auxcmd = &isurf_auxcmd; cs->card_ops = &isurf_ops; cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r; cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r; reset_isurf(cs, ISURF_RESET); - test_and_set_bit(HW_ISAR, &cs->HW_Flags); + __set_bit(HW_ISAR, &cs->HW_Flags); isac_setup(cs, &isac_ops); if (isar_setup(cs, &isar_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); - return 0; + return -EBUSY; +} +int __init +setup_isurf(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, ISurf_revision); + printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp)); + +#ifdef __ISAPNP__ + if (!card->para[1] || !card->para[2]) { + struct pnp_card *pb; + struct pnp_dev *pd; + + cs->subtyp = 0; + if ((pb = pnp_find_card( + ISAPNP_VENDOR('S', 'I', 'E'), + ISAPNP_FUNCTION(0x0010), pnp_surf))) { + pnp_surf = pb; + pd = NULL; + if (!(pd = pnp_find_dev(pnp_surf, + ISAPNP_VENDOR('S', 'I', 'E'), + ISAPNP_FUNCTION(0x0010), pd))) { + printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n"); + return (0); + } + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "ISurfPnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd) < 0) { + printk(KERN_ERR "ISurfPnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { + printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n", + pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); + pnp_device_detach(pd); + return(0); + } + card->para[1] = pnp_port_start(pd, 0); + card->para[2] = pnp_port_start(pd, 1); + card->para[0] = pnp_irq(pd, 0); + } else { + printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n"); + return 0; + } + } +#endif + if (isurf_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c --- a/drivers/isdn/hisax/ix1_micro.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/ix1_micro.c Thu Mar 6 22:52:04 2003 @@ -162,6 +162,29 @@ .irq_func = hscxisac_irq, }; +static int __init +ix1_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->irq = card->para[0]; + cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET; + cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET; + cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET; + cs->hw.ix1.cfg_reg = card->para[1]; + if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) + goto err; + + printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", + CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg); + ix1_reset(cs); + cs->card_ops = &ix1_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + #ifdef __ISAPNP__ static struct isapnp_device_id itk_ids[] __initdata = { { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25), @@ -181,14 +204,18 @@ int __init setup_ix1micro(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, ix1_revision); printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp)); + if (card->para[1]) { + if (ix1_probe(card->cs, card)) + return 0; + return 1; + } #ifdef __ISAPNP__ - if (!card->para[1] && isapnp_present()) { + if (isapnp_present()) { struct pnp_card *pb; struct pnp_dev *pd; @@ -221,7 +248,9 @@ } card->para[1] = pnp_port_start(pd, 0); card->para[0] = pnp_irq(pd, 0); - break; + if (ix1_probe(card->cs, card)) + return 0; + return 1; } else { printk(KERN_ERR "ITK PnP: PnP error card found, no device\n"); } @@ -231,27 +260,8 @@ } if (!idev->card_vendor) { printk(KERN_INFO "ITK PnP: no ISAPnP card found\n"); - return(0); } } #endif - /* IO-Ports */ - cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET; - cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET; - cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET; - cs->hw.ix1.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) - goto err; - - printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", - CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg); - ix1_reset(cs); - cs->card_ops = &ix1_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 1; - err: - hisax_release_resources(cs); return 0; } diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c --- a/drivers/isdn/hisax/mic.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/mic.c Thu Mar 6 22:52:04 2003 @@ -138,17 +138,11 @@ .irq_func = hscxisac_irq, }; -int __init -setup_mic(struct IsdnCard *card) +static int __init +mic_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, mic_revision); - printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp)); - - cs->hw.mic.cfg_reg = card->para[1]; cs->irq = card->para[0]; + cs->hw.mic.cfg_reg = card->para[1]; cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR; cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC; cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX; @@ -158,11 +152,25 @@ printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n", cs->hw.mic.cfg_reg, cs->irq); + cs->card_ops = &mic_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); - return 0; + return -EBUSY; +} + +int __init +setup_mic(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, mic_revision); + printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp)); + + if (mic_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c --- a/drivers/isdn/hisax/niccy.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/niccy.c Thu Mar 6 22:52:04 2003 @@ -199,6 +199,70 @@ .irq_func = niccy_interrupt, }; +static int __init +niccy_probe(struct IsdnCardState *cs) +{ + printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", + CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", + cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); + cs->card_ops = &niccy_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + return -EBUSY; + return 0; +} + +static int __init +niccy_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = NICCY_PNP; + cs->irq = card->para[0]; + cs->hw.niccy.isac = card->para[1] + ISAC_PNP; + cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; + cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP; + cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP; + cs->hw.niccy.cfg_reg = 0; + + if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data")) + goto err; + if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr")) + goto err; + if (niccy_probe(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + u32 pci_ioaddr; + + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = NICCY_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.niccy.cfg_reg = pci_resource_start(pdev, 0); + pci_ioaddr = pci_resource_start(pdev, 1); + cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; + cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; + cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; + cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; + if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy")) + goto err; + if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) + goto err; + if (niccy_probe(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *niccy_dev __initdata = NULL; #ifdef __ISAPNP__ static struct pnp_card *pnp_c __devinitdata = NULL; @@ -207,7 +271,6 @@ int __init setup_niccy(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, niccy_revision); @@ -252,66 +315,18 @@ } #endif if (card->para[1]) { - cs->hw.niccy.isac = card->para[1] + ISAC_PNP; - cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; - cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP; - cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP; - cs->hw.niccy.cfg_reg = 0; - cs->subtyp = NICCY_PNP; - cs->irq = card->para[0]; - if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data")) - goto err; - if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr")) - goto err; + if (niccy_pnp_probe(card->cs, card) < 0) + return 0; + return 1; } else { #if CONFIG_PCI - u_int pci_ioaddr; - cs->subtyp = 0; if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) { - if (pci_enable_device(niccy_dev)) - return(0); - /* get IRQ */ - if (!niccy_dev->irq) { - printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n"); - return(0); - } - cs->irq = niccy_dev->irq; - cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0); - if (!cs->hw.niccy.cfg_reg) { - printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); - return(0); - } - pci_ioaddr = pci_resource_start(niccy_dev, 1); - if (!pci_ioaddr) { - printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); - return(0); - } - cs->subtyp = NICCY_PCI; - } else { - printk(KERN_WARNING "Niccy: No PCI card found\n"); - return(0); + if (niccy_pci_probe(card->cs, niccy_dev) < 0) + return 0; + return 1; } - cs->irq_flags |= SA_SHIRQ; - cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; - cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; - cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; - cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; - - if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy")) - goto err; - if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) - goto err; #endif /* CONFIG_PCI */ } - printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", - CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", - cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); - cs->card_ops = &niccy_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 1; - err: - niccy_release(cs); return 0; } diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c --- a/drivers/isdn/hisax/nj_s.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/nj_s.c Thu Mar 6 22:52:04 2003 @@ -106,96 +106,99 @@ .irq_func = nj_s_interrupt, }; +static int __init +nj_s_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + pci_set_master(pdev); + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.njet.pdev = pdev; + cs->hw.njet.base = pci_resource_start(pdev, 0); + if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) + return 0; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; + + cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.auxd = 0xC0; + cs->hw.njet.dmactrl = 0; + + byteout(cs->hw.njet.auxa, 0); + byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); + byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + + switch ((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3) { + case 0 : + break; + case 3 : + printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); + goto err; + default : + printk(KERN_WARNING "NETjet-S: No PCI card found\n" ); + goto err; + } + printk(KERN_INFO + "NETjet-S: PCI card configured at %#lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + + nj_s_reset(cs); + cs->irq_flags |= SA_SHIRQ; + cs->card_ops = &nj_s_ops; + isac_setup(cs, &netjet_dc_ops); + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_netjet __initdata = NULL; int __init setup_netjet_s(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, NETjet_S_revision); - printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", + HiSax_getrev(tmp)); - for ( ;; ) { - if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { - if (pci_enable_device(dev_netjet)) - return(0); - pci_set_master(dev_netjet); - cs->irq = dev_netjet->irq; - if (!cs->irq) { - printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n"); - return(0); - } - cs->hw.njet.base = pci_resource_start(dev_netjet, 0); - if (!cs->hw.njet.base) { - printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n"); - return(0); - } - /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */ - if ((dev_netjet->subsystem_vendor == 0x55) && - (dev_netjet->subsystem_device == 0x02)) { - printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n"); - printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n"); - return(0); - } - /* end new code */ - cs->hw.njet.pdev = dev_netjet; - } else { - printk(KERN_WARNING "NETjet-S: No PCI card found\n"); - return(0); + dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet); + if (dev_netjet) { + /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */ + if (dev_netjet->subsystem_vendor == 0x55 && + dev_netjet->subsystem_device == 0x02) { + printk(KERN_WARNING "Netjet: You tried to load this " + "driver with an incompatible TigerJet-card\n"); + printk(KERN_WARNING "Use type=41 for Formula-n " + "enter:now ISDN PCI and compatible\n"); + return 0; } - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0xC0; - cs->hw.njet.dmactrl = 0; - - byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); - byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - - switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) ) - { - case 0 : - break; - - case 3 : - printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); - continue; - - default : - printk( KERN_WARNING "NETjet-S: No PCI card found\n" ); - return 0; - } - break; - } - printk(KERN_INFO - "NETjet-S: PCI card configured at %#lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) + if (nj_s_probe(card->cs, dev_netjet)) + return 1; return 0; - - nj_s_reset(cs); - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &nj_s_ops; - isac_setup(cs, &netjet_dc_ops); - return 1; + } + printk(KERN_WARNING "NETjet-S: No PCI card found\n"); + return 0; } + diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c --- a/drivers/isdn/hisax/nj_u.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/nj_u.c Thu Mar 6 22:52:05 2003 @@ -110,88 +110,85 @@ .irq_func = nj_u_interrupt, }; +static int __init +nj_u_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + pci_set_master(pdev); + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.njet.pdev = pdev; + cs->hw.njet.base = pci_resource_start(pdev, 0); + if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netspider-u isdn")) + goto err; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; + + cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.auxd = 0xC0; + cs->hw.njet.dmactrl = 0; + + byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); + byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + + switch ((NETjet_ReadIC(cs, ICC_RBCH) >> 5) & 3) { + case 3: + break; + case 0: + printk(KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" ); + goto err; + default: + printk(KERN_WARNING "NETspider-U: No PCI card found\n" ); + goto err; + } + printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + + nj_u_reset(cs); + cs->card_ops = &nj_u_ops; + icc_setup(cs, &netjet_dc_ops); + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_netjet __initdata = NULL; int __init setup_netjet_u(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, NETjet_U_revision); - printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp)); - - for ( ;; ) { - if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { - if (pci_enable_device(dev_netjet)) - return(0); - pci_set_master(dev_netjet); - cs->irq = dev_netjet->irq; - if (!cs->irq) { - printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n"); - return(0); - } - cs->hw.njet.base = pci_resource_start(dev_netjet, 0); - if (!cs->hw.njet.base) { - printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n"); - return(0); - } - cs->hw.njet.pdev = dev_netjet; - } else { - printk(KERN_WARNING "NETspider-U: No PCI card found\n"); - return(0); - } - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0xC0; - cs->hw.njet.dmactrl = 0; - - byteout(cs->hw.njet.auxa, 0); - byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); - byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - - switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) ) - { - case 3 : - break; - - case 0 : - printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" ); - continue; - - default : - printk( KERN_WARNING "NETspider-U: No PCI card found\n" ); - return 0; - } - break; - } - printk(KERN_INFO - "NETspider-U: PCI card configured at %#lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) - return 0; + printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", + HiSax_getrev(tmp)); - nj_u_reset(cs); - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &nj_u_ops; - icc_setup(cs, &netjet_dc_ops); - return 1; + dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet); + if (dev_netjet) { + if (nj_u_probe(card->cs, dev_netjet)) + return 1; + return 0; + } + printk(KERN_WARNING "NETspider-U: No PCI card found\n"); + return 0; } diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c --- a/drivers/isdn/hisax/s0box.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/s0box.c Thu Mar 6 22:52:05 2003 @@ -172,14 +172,9 @@ .irq_func = hscxisac_irq, }; -int __init -setup_s0box(struct IsdnCard *card) +static int __init +s0box_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, s0box_revision); - printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); cs->hw.teles3.cfg_reg = card->para[1]; cs->hw.teles3.hscx[0] = -0x20; cs->hw.teles3.hscx[1] = 0x0; @@ -200,8 +195,20 @@ cs->card_ops = &s0box_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); - return 0; + return -EBUSY; +} + +int __init +setup_s0box(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, s0box_revision); + printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); + if (s0box_probe(card->cs, card)) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c --- a/drivers/isdn/hisax/saphir.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/saphir.c Thu Mar 6 22:52:05 2003 @@ -201,36 +201,21 @@ .irq_func = saphir_interrupt, }; -int __init -setup_saphir(struct IsdnCard *card) +static int __init +saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, saphir_rev); - printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_HSTSAPHIR) - return (0); - - init_timer(&cs->hw.saphir.timer); - /* IO-Ports */ cs->hw.saphir.cfg_reg = card->para[1]; cs->hw.saphir.isac = card->para[1] + ISAC_DATA; cs->hw.saphir.hscx = card->para[1] + HSCX_DATA; cs->hw.saphir.ale = card->para[1] + ADDRESS_REG; cs->irq = card->para[0]; + if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir")) goto err; - printk(KERN_INFO - "HiSax: %s config irq:%d io:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.saphir.cfg_reg); + printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", + CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg); - cs->hw.saphir.timer.function = (void *) SaphirWatchDog; - cs->hw.saphir.timer.data = (long) cs; - cs->hw.saphir.timer.expires = jiffies + 4*HZ; - add_timer(&cs->hw.saphir.timer); if (saphir_reset(cs)) goto err; @@ -238,8 +223,27 @@ if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; - err: - saphir_release(cs); + init_timer(&cs->hw.saphir.timer); + cs->hw.saphir.timer.function = (void *) SaphirWatchDog; + cs->hw.saphir.timer.data = (long) cs; + cs->hw.saphir.timer.expires = jiffies + 4*HZ; + add_timer(&cs->hw.saphir.timer); return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +int __init +setup_saphir(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, saphir_rev); + printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", + HiSax_getrev(tmp)); + + if (saphir_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c --- a/drivers/isdn/hisax/sedlbauer.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/sedlbauer.c Thu Mar 6 22:52:05 2003 @@ -73,7 +73,6 @@ #define SEDL_SPEEDFAX_PYRAMID 7 #define SEDL_SPEEDFAX_PCI 8 -#define SEDL_CHIP_TEST 0 #define SEDL_CHIP_ISAC_HSCX 1 #define SEDL_CHIP_ISAC_ISAR 2 #define SEDL_CHIP_IPAC 3 @@ -452,6 +451,241 @@ .irq_func = sedlbauer_isar_interrupt, }; +static int __init +sedl_ipac_probe(struct IsdnCardState *cs) +{ + u8 val; + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; + val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID); + printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val); + return (val == 1 || val == 2); +} + +static int __init +sedl_ipac_init(struct IsdnCardState *cs) +{ + cs->card_ops = &sedlbauer_ipac_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + return -ENODEV; + sedlbauer_reset(cs); + return 0; +} + +static int __init +sedl_isac_isar_init(struct IsdnCardState *cs) +{ + cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; + cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; + __set_bit(HW_ISAR, &cs->HW_Flags); + cs->card_ops = &sedlbauer_isar_ops; + cs->auxcmd = &isar_auxcmd; + isac_setup(cs, &isac_ops); + return isar_setup(cs, &isar_ops); +} + +static int __init +sedl_isac_hscx_init(struct IsdnCardState *cs) +{ + cs->card_ops = &sedlbauer_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + return -ENODEV; + sedlbauer_reset(cs); + return 0; +} + +static int __init +sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->irq = card->para[0]; + cs->hw.sedl.cfg_reg = card->para[1]; + cs->hw.sedl.bus = SEDL_BUS_ISA; + if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn")) + goto err; + + if (sedl_ipac_probe(cs)) { + cs->subtyp = SEDL_SPEED_WIN2_PC104; + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + if (sedl_ipac_init(cs)) + goto err; + } else { + cs->subtyp = SEDL_SPEED_CARD_WIN; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; + if (sedl_isac_hscx_init(cs)) + goto err; + } + printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", + Sedlbauer_Types[cs->subtyp], + cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq); + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.sedl.bus = SEDL_BUS_PCMCIA; + if (sedl_ipac_probe(cs)) { + cs->subtyp = SEDL_SPEED_STAR2; + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + if (sedl_ipac_init(cs)) + goto err; + } else { + cs->subtyp = SEDL_SPEED_STAR; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + if (sedl_isac_hscx_init(cs)) + goto err; + } + printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", + Sedlbauer_Types[cs->subtyp], + cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq); + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = SEDL_SPEED_FAX; + cs->hw.sedl.bus = SEDL_BUS_ISA; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn")) + goto err; + + printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", + Sedlbauer_Types[cs->subtyp], + cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq); + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF; + if (sedl_isac_isar_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0); + cs->hw.sedl.bus = SEDL_BUS_PCI; + + if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn")) + return -EBUSY; + + printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", + Sedlbauer_Types[cs->subtyp], + cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq); + + cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; + cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; + byteout(cs->hw.sedl.cfg_reg, 0xff); + byteout(cs->hw.sedl.cfg_reg, 0x00); + byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); + byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + return 0; +} + +static int __init +sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = SEDL_SPEEDFAX_PYRAMID; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + if (sedl_pci_init(cs, pdev)) + goto err; + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR; + if (sedl_isac_isar_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = SEDL_SPEEDFAX_PCI; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + + if (sedl_pci_init(cs, pdev)) + goto err; + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR; + if (sedl_isac_isar_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = SEDL_SPEED_PCI; + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + if (sedl_pci_init(cs, pdev)) + goto err; + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; + if (sedl_ipac_init(cs)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_sedl __devinitdata = NULL; #ifdef __ISAPNP__ @@ -472,265 +706,117 @@ int __devinit setup_sedlbauer(struct IsdnCard *card) { - int bytecnt, val; struct IsdnCardState *cs = card->cs; char tmp[64]; u16 sub_vendor_id, sub_id; strcpy(tmp, Sedlbauer_revision); - printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", + HiSax_getrev(tmp)); - if (cs->typ == ISDN_CTYPE_SEDLBAUER) { - cs->subtyp = SEDL_SPEED_CARD_WIN; - cs->hw.sedl.bus = SEDL_BUS_ISA; - cs->hw.sedl.chip = SEDL_CHIP_TEST; - } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { - cs->subtyp = SEDL_SPEED_STAR; - cs->hw.sedl.bus = SEDL_BUS_PCMCIA; - cs->hw.sedl.chip = SEDL_CHIP_TEST; - } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { - cs->subtyp = SEDL_SPEED_FAX; - cs->hw.sedl.bus = SEDL_BUS_ISA; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - } else - return (0); - - bytecnt = 8; if (card->para[1]) { - cs->hw.sedl.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { - bytecnt = 16; + if (cs->typ == ISDN_CTYPE_SEDLBAUER) { + if (sedl_card_win_probe(card->cs, card) < 0) + return 0; + return 1; + } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { + if (sedl_star_probe(card->cs, card) < 0) + return 0; + return 1; + } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { + if (sedl_fax_probe(card->cs, card) < 0) + return 0; + return 1; } - } else { + } #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { - printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Sedlbauer PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "Sedlbauer PnP: activate failed\n"); - pnp_device_detach(pd); + if (isapnp_present()) { + struct pnp_card *pb; + struct pnp_dev *pd; + + while(pdev->card_vendor) { + if ((pb = pnp_find_card(pdev->card_vendor, + pdev->card_device, + pnp_c))) { + pnp_c = pb; + pd = NULL; + if ((pd = pnp_find_dev(pnp_c, + pdev->vendor, + pdev->function, + pd))) { + printk(KERN_INFO "HiSax: %s detected\n", + (char *)pdev->driver_data); + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "Sedlbauer PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd) < 0) { + printk(KERN_ERR "Sedlbauer PnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); + goto err; + } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); + cs->hw.sedl.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (pdev->function == ISAPNP_FUNCTION(0x2)) { + if (sedl_fax_probe(card->cs, card)) return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { - printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); - goto err; - } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - cs->hw.sedl.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (pdev->function == ISAPNP_FUNCTION(0x2)) { - cs->subtyp = SEDL_SPEED_FAX; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - bytecnt = 16; - } else { - cs->subtyp = SEDL_SPEED_CARD_WIN; - cs->hw.sedl.chip = SEDL_CHIP_TEST; - } - goto ready; + return 1; } else { - printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); - goto err; + if (sedl_card_win_probe(card->cs, card)) + return 0; + return 1; } + } else { + printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); + goto err; } - pdev++; - pnp_c=NULL; - } - if (!pdev->card_vendor) { - printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); } + pdev++; + pnp_c=NULL; + } + if (!pdev->card_vendor) { + printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); } + } #endif /* Probe for Sedlbauer speed pci */ #if CONFIG_PCI - if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { - if (pci_enable_device(dev_sedl)) - goto err; - cs->irq = dev_sedl->irq; - if (!cs->irq) { - printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); - goto err; - } - cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0); - } else { - printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); - goto err; - } - cs->irq_flags |= SA_SHIRQ; - cs->hw.sedl.bus = SEDL_BUS_PCI; + dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_100, dev_sedl); + if (dev_sedl) { sub_vendor_id = dev_sedl->subsystem_vendor; sub_id = dev_sedl->subsystem_device; printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n", - sub_vendor_id, sub_id); - printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n", - cs->hw.sedl.cfg_reg); + sub_vendor_id, sub_id); if (sub_id != PCI_SUB_ID_SEDLBAUER) { printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id); - goto err; + return 0; } if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) { - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - cs->subtyp = SEDL_SPEEDFAX_PYRAMID; + if (sedl_fax_pyramid_probe(cs, dev_sedl)) + return 0; + return 1; } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) { - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - cs->subtyp = SEDL_SPEEDFAX_PCI; + if (sedl_fax_pci_probe(cs, dev_sedl)) + return 0; + return 1; } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) { - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - cs->subtyp = SEDL_SPEED_PCI; - } else { - printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", - sub_vendor_id); - goto err; - } - bytecnt = 256; - cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; - cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; - byteout(cs->hw.sedl.cfg_reg, 0xff); - byteout(cs->hw.sedl.cfg_reg, 0x00); - byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); - byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); -#endif /* CONFIG_PCI */ - } -ready: - /* In case of the sedlbauer pcmcia card, this region is in use, - * reserved for us by the card manager. So we do not check it - * here, it would fail. - */ - if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA) { - if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) - goto err; - } - - printk(KERN_INFO - "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n", - cs->hw.sedl.cfg_reg, - cs->hw.sedl.cfg_reg + bytecnt, - cs->irq); - -/* - * testing ISA and PCMCIA Cards for IPAC, default is ISAC - * do not test for PCI card, because ports are different - * and PCI card uses only IPAC (for the moment) - */ - if (cs->hw.sedl.bus != SEDL_BUS_PCI) { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, - IPAC_ID); - printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val); - if ((val == 1) || (val == 2)) { - /* IPAC */ - cs->subtyp = SEDL_SPEED_WIN2_PC104; - if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { - cs->subtyp = SEDL_SPEED_STAR2; - } - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - } else { - /* ISAC_HSCX oder ISAC_ISAR */ - if (cs->hw.sedl.chip == SEDL_CHIP_TEST) { - cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; - } - } - } - -/* - * hw.sedl.chip is now properly set - */ - printk(KERN_INFO "Sedlbauer: %s detected\n", - Sedlbauer_Types[cs->subtyp]); - - - if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { - if (cs->hw.sedl.bus == SEDL_BUS_PCI) { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; - } else { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; - } - cs->card_ops = &sedlbauer_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - sedlbauer_reset(cs); - } else { - /* ISAC_HSCX oder ISAC_ISAR */ - if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { - if (cs->hw.sedl.bus == SEDL_BUS_PCI) { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + - SEDL_ISAR_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + - SEDL_ISAR_PCI_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + - SEDL_ISAR_PCI_ISAR; - } else { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ISAR; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ISAR_RESET_ON; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ISAR_RESET_OFF; - } - cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; - cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; - test_and_set_bit(HW_ISAR, &cs->HW_Flags); - cs->card_ops = &sedlbauer_isar_ops; - cs->auxcmd = &isar_auxcmd; - isac_setup(cs, &isac_ops); - if (isar_setup(cs, &isar_ops)) - goto err; - } else { - if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; - } else { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; - } - cs->card_ops = &sedlbauer_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - - sedlbauer_reset(cs); + if (sedl_pci_probe(cs, dev_sedl)) + return 0; + return 1; } + printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", + sub_vendor_id); + return 0; } - return 1; - err: - hisax_release_resources(cs); +#endif /* CONFIG_PCI */ return 0; } diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c --- a/drivers/isdn/hisax/sportster.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/sportster.c Thu Mar 6 22:52:05 2003 @@ -189,42 +189,29 @@ } return 0; } - -int __init -setup_sportster(struct IsdnCard *card) -{ - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, sportster_revision); - printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp)); - cs->hw.spt.cfg_reg = card->para[1]; +static int __init +sportster_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ cs->irq = card->para[0]; + cs->hw.spt.cfg_reg = card->para[1]; if (!get_io_range(cs)) - return (0); + return -EBUSY; cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC; cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA; cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB; switch(cs->irq) { - case 5: cs->hw.spt.res_irq = 1; - break; - case 7: cs->hw.spt.res_irq = 2; - break; - case 10:cs->hw.spt.res_irq = 3; - break; - case 11:cs->hw.spt.res_irq = 4; - break; - case 12:cs->hw.spt.res_irq = 5; - break; - case 14:cs->hw.spt.res_irq = 6; - break; - case 15:cs->hw.spt.res_irq = 7; - break; - default:sportster_release(cs); - printk(KERN_WARNING "Sportster: wrong IRQ\n"); - return(0); + case 5: cs->hw.spt.res_irq = 1; break; + case 7: cs->hw.spt.res_irq = 2; break; + case 10:cs->hw.spt.res_irq = 3; break; + case 11:cs->hw.spt.res_irq = 4; break; + case 12:cs->hw.spt.res_irq = 5; break; + case 14:cs->hw.spt.res_irq = 6; break; + case 15:cs->hw.spt.res_irq = 7; break; + default: + printk(KERN_WARNING "Sportster: wrong IRQ\n"); + goto err; } sportster_reset(cs); printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n", @@ -234,8 +221,22 @@ cs->card_ops = &sportster_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; - err: - hisax_release_resources(cs); return 0; + err: + sportster_release(cs); + return -EBUSY; +} + +int __init +setup_sportster(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, sportster_revision); + printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", + HiSax_getrev(tmp)); + + if (sportster_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c --- a/drivers/isdn/hisax/teleint.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/teleint.c Thu Mar 6 22:52:05 2003 @@ -256,15 +256,9 @@ .irq_func = teleint_interrupt, }; -int __init -setup_TeleInt(struct IsdnCard *card) +static int __init +teleint_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, TeleInt_revision); - printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp)); - cs->hw.hfc.addr = card->para[1] & 0x3fe; cs->irq = card->para[0]; cs->hw.hfc.cirm = HFC_CIRM; @@ -284,42 +278,54 @@ byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff); byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54); switch (cs->irq) { - case 3: - cs->hw.hfc.cirm |= HFC_INTA; - break; - case 4: - cs->hw.hfc.cirm |= HFC_INTB; - break; - case 5: - cs->hw.hfc.cirm |= HFC_INTC; - break; - case 7: - cs->hw.hfc.cirm |= HFC_INTD; - break; - case 10: - cs->hw.hfc.cirm |= HFC_INTE; - break; - case 11: - cs->hw.hfc.cirm |= HFC_INTF; - break; - default: - printk(KERN_WARNING "TeleInt: wrong IRQ\n"); - goto err; + case 3: + cs->hw.hfc.cirm |= HFC_INTA; + break; + case 4: + cs->hw.hfc.cirm |= HFC_INTB; + break; + case 5: + cs->hw.hfc.cirm |= HFC_INTC; + break; + case 7: + cs->hw.hfc.cirm |= HFC_INTD; + break; + case 10: + cs->hw.hfc.cirm |= HFC_INTE; + break; + case 11: + cs->hw.hfc.cirm |= HFC_INTF; + break; + default: + printk(KERN_WARNING "TeleInt: wrong IRQ\n"); + goto err; } byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt); - printk(KERN_INFO - "TeleInt: defined at 0x%x IRQ %d\n", - cs->hw.hfc.addr, - cs->irq); + printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n", + cs->hw.hfc.addr, cs->irq); cs->card_ops = &teleint_ops; teleint_reset(cs); isac_setup(cs, &isac_ops); hfc_setup(cs, &hfc_ops); - return 1; - err: - teleint_release(cs); return 0; + + err: + hisax_release_resources(cs); + return -EBUSY; +} + +int __init +setup_TeleInt(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, TeleInt_revision); + printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp)); + + if (teleint_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c --- a/drivers/isdn/hisax/teles0.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/teles0.c Thu Mar 6 22:52:05 2003 @@ -165,72 +165,95 @@ .irq_func = hscxisac_irq, }; -int __init -setup_teles0(struct IsdnCard *card) +static int __init +teles0_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - u8 val; - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, teles0_revision); - printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ == ISDN_CTYPE_16_0) - cs->hw.teles0.cfg_reg = card->para[2]; - else /* 8.0 */ - cs->hw.teles0.cfg_reg = 0; - - if (card->para[1] < 0x10000) { - card->para[1] <<= 4; - printk(KERN_INFO - "Teles0: membase configured DOSish, assuming 0x%lx\n", - (unsigned long) card->para[1]); - } cs->irq = card->para[0]; - if (cs->hw.teles0.cfg_reg) { - if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg")) - goto err; - - if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 0, val); - goto err; - } - if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 1, val); - goto err; - } - val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB - * 0x1f=with AB - * 0x1c 16.3 ??? - */ - if (val != 0x1e && val != 0x1f) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 2, val); - goto err; - } - } /* 16.0 and 8.0 designed for IOM1 */ test_and_set_bit(HW_IOM1, &cs->HW_Flags); cs->hw.teles0.phymem = card->para[1]; - cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem"); + cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, + TELES_IOMEM_SIZE, "teles iomem"); if (!cs->hw.teles0.membase) - goto err; + return -EBUSY; - printk(KERN_INFO - "HiSax: %s config irq:%d mem:0x%p cfg:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.teles0.membase, cs->hw.teles0.cfg_reg); if (teles0_reset(cs)) { printk(KERN_WARNING "Teles0: wrong IRQ\n"); - goto err; + return -EBUSY; } cs->card_ops = &teles0_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 1; + return -EBUSY; + return 0; +} + +static int __init +teles16_0_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + u8 val; + + cs->hw.teles0.cfg_reg = card->para[2]; + if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg")) + goto err; + + if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 0, val); + goto err; + } + if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 1, val); + goto err; + } + val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB + * 0x1f=with AB + * 0x1c 16.3 ??? + */ + if (val != 0x1e && val != 0x1f) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 2, val); + goto err; + } + if (teles0_probe(cs, card) < 0) + goto err; + + return 0; err: hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +teles8_0_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.teles0.cfg_reg = 0; + + if (teles0_probe(cs, card) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +int __init +setup_teles0(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, teles0_revision); + printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", + HiSax_getrev(tmp)); + + if (card->cs->typ == ISDN_CTYPE_16_0) { + if (teles16_0_probe(card->cs, card) < 0) + return 0; + } else { + if (teles8_0_probe(card->cs, card) < 0) + return 0; + } + return 1; } diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c --- a/drivers/isdn/hisax/teles3.c Tue Feb 25 11:50:51 2003 +++ b/drivers/isdn/hisax/teles3.c Thu Mar 6 22:52:05 2003 @@ -176,6 +176,152 @@ .irq_func = hscxisac_irq, }; +static int +teles_hw_init(struct IsdnCardState *cs) +{ + + printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n", + CardType[cs->typ], cs->irq, + cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg); + printk(KERN_INFO "HiSax: hscx A:0x%X hscx B:0x%X\n", + cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32); + + if (teles3_reset(cs)) { + printk(KERN_WARNING "Teles3: wrong IRQ\n"); + return -EBUSY; + } + cs->card_ops = &teles3_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + return -EBUSY; + return 0; +} + +static void __init +teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->irq = card->para[0]; + cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e; + cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; + cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; +} + +static int __init +telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.teles3.cfg_reg = 0; + cs->hw.teles3.hscx[0] = card->para[1] - 0x20; + cs->hw.teles3.hscx[1] = card->para[1]; + cs->hw.teles3.isac = card->para[1] + 0x20; + teles_setup_io(cs, card); + if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, + "HiSax Teles PCMCIA")) + goto err; + if (teles_hw_init(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +teles_request_io(struct IsdnCardState *cs) +{ + if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac")) + return -EBUSY; + if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A")) + return -EBUSY; + if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B")) + return -EBUSY; + return 0; +} + +static int __init +teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + u8 val; + + cs->hw.teles3.cfg_reg = card->para[1]; + switch (cs->hw.teles3.cfg_reg) { + case 0x180: + case 0x280: + case 0x380: + cs->hw.teles3.cfg_reg |= 0xc00; + break; + } + cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420; + cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20; + cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820; + teles_setup_io(cs, card); + if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) + goto err; + if (teles_request_io(cs) < 0) + goto err; + if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 0, val); + goto err; + } + if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 1, val); + goto err; + } + /* 0x1e without AB, 0x1f with AB, 0x1c 16.3 ???, + * 0x39 16.3 1.1, 0x38 16.3 1.3, 0x46 16.3 with AB + Video */ + val = bytein(cs->hw.teles3.cfg_reg + 2); + if (val != 0x46 && val != 0x39 && val != 0x38 && + val != 0x1c && val != 0x1e && val != 0x1f) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 2, val); + goto err; + } + if (teles_hw_init(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.teles3.cfg_reg = card->para[3]; + cs->hw.teles3.isac = card->para[2] - 32; + cs->hw.teles3.hscx[0] = card->para[1] - 32; + cs->hw.teles3.hscx[1] = card->para[1]; + teles_setup_io(cs, card); + if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) + goto err; + if (teles_request_io(cs) < 0) + goto err; + if (teles_hw_init(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.teles3.cfg_reg = 0; + cs->hw.teles3.isac = card->para[1] - 32; + cs->hw.teles3.hscx[0] = card->para[2] - 32; + cs->hw.teles3.hscx[1] = card->para[2]; + teles_setup_io(cs, card); + if (teles_request_io(cs) < 0) + goto err; + if (teles_hw_init(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + #ifdef __ISAPNP__ static struct isapnp_device_id teles_ids[] __initdata = { { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110), @@ -197,16 +343,10 @@ int __devinit setup_teles3(struct IsdnCard *card) { - u8 val; - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, teles3_revision); printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp)); - if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP) - && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) - return (0); - #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { struct pnp_card *pnp_card; @@ -258,100 +398,18 @@ } } #endif - if (cs->typ == ISDN_CTYPE_16_3) { - cs->hw.teles3.cfg_reg = card->para[1]; - switch (cs->hw.teles3.cfg_reg) { - case 0x180: - case 0x280: - case 0x380: - cs->hw.teles3.cfg_reg |= 0xc00; - break; - } - cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420; - cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20; - cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820; - } else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { - cs->hw.teles3.cfg_reg = 0; - cs->hw.teles3.hscx[0] = card->para[1] - 0x20; - cs->hw.teles3.hscx[1] = card->para[1]; - cs->hw.teles3.isac = card->para[1] + 0x20; - } else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - cs->hw.teles3.cfg_reg = card->para[3]; - cs->hw.teles3.isac = card->para[2] - 32; - cs->hw.teles3.hscx[0] = card->para[1] - 32; - cs->hw.teles3.hscx[1] = card->para[1]; + if (card->cs->typ == ISDN_CTYPE_16_3) { + if (teles16_3_probe(card->cs, card) < 0) + return 0; + } else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) { + if (telespcmcia_probe(card->cs, card) < 0) + return 0; + } else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + if (compaq_probe(card->cs, card) < 0) + return 0; } else { /* PNP */ - cs->hw.teles3.cfg_reg = 0; - cs->hw.teles3.isac = card->para[1] - 32; - cs->hw.teles3.hscx[0] = card->para[2] - 32; - cs->hw.teles3.hscx[1] = card->para[2]; - } - cs->irq = card->para[0]; - cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e; - cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; - cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; - if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { - if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) - goto err; - } else { - if (cs->hw.teles3.cfg_reg) { - if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) - goto err; - } else { - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) - goto err; - } - } - if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac")) - goto err; - if (!request_io(&cs->rs, cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) - goto err; - if (!request_io(&cs->rs, cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) - goto err; - } - if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) { - if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 0, val); - goto err; - } - if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 1, val); - goto err; - } - val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB - * 0x1f=with AB - * 0x1c 16.3 ??? - * 0x39 16.3 1.1 - * 0x38 16.3 1.3 - * 0x46 16.3 with AB + Video (Teles-Vision) - */ - if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 2, val); - goto err; - } - } - printk(KERN_INFO - "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg); - printk(KERN_INFO - "HiSax: hscx A:0x%X hscx B:0x%X\n", - cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32); - - if (teles3_reset(cs)) { - printk(KERN_WARNING "Teles3: wrong IRQ\n"); - goto err; + if (telespnp_probe(card->cs, card) < 0) + return 0; } - cs->card_ops = &teles3_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; return 1; - err: - hisax_release_resources(cs); - return 0; - } diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c --- a/drivers/isdn/hisax/telespci.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/telespci.c Thu Mar 6 22:52:05 2003 @@ -231,36 +231,23 @@ .irq_func = telespci_interrupt, }; -static struct pci_dev *dev_tel __initdata = NULL; - -int __init -setup_telespci(struct IsdnCard *card) +static int __init +telespci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; + int rc; -#ifdef __BIG_ENDIAN -#error "not running on big endian machines now" -#endif - strcpy(tmp, telespci_revision); - printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); - if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { - if (pci_enable_device(dev_tel)) - return(0); - cs->irq = dev_tel->irq; - if (!cs->irq) { - printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); - return(0); - } - cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(dev_tel, 0), 4096, "telespci"); - if (!cs->hw.teles0.membase) - goto err; - printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n", - pci_resource_start(dev_tel, 0), dev_tel->irq); - } else { - printk(KERN_WARNING "TelesPCI: No PCI card found\n"); - return(0); - } + printk(KERN_INFO "TelesPCI: defined at %#lx IRQ %d\n", + pci_resource_start(pdev, 0), pdev->irq); + + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "telespci"); + if (!cs->hw.teles0.membase) + goto err; /* Initialize Zoran PCI controller */ writel(0x00000000, cs->hw.teles0.membase + 0x28); @@ -270,17 +257,36 @@ writel(0x70000000, cs->hw.teles0.membase + 0x3C); writel(0x61000000, cs->hw.teles0.membase + 0x40); /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ - printk(KERN_INFO - "HiSax: %s config irq:%d mem:%p\n", - CardType[cs->typ], cs->irq, - cs->hw.teles0.membase); - cs->irq_flags |= SA_SHIRQ; cs->card_ops = &telespci_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); + return rc; +} + +static struct pci_dev *dev_tel __initdata = NULL; + +int __init +setup_telespci(struct IsdnCard *card) +{ + char tmp[64]; + +#ifdef __BIG_ENDIAN +#error "not running on big endian machines now" +#endif + strcpy(tmp, telespci_revision); + printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", + HiSax_getrev(tmp)); + dev_tel = pci_find_device(PCI_VENDOR_ID_ZORAN, + PCI_DEVICE_ID_ZORAN_36120, dev_tel); + if (dev_tel) { + if (telespci_probe(card->cs, dev_tel) < 0) + return 0; + return 1; + } + printk(KERN_WARNING "TelesPCI: No PCI card found\n"); return 0; } diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c --- a/drivers/isdn/hisax/w6692.c Sun Jan 12 16:12:37 2003 +++ b/drivers/isdn/hisax/w6692.c Thu Mar 6 22:52:05 2003 @@ -669,11 +669,11 @@ static struct pci_dev *dev_w6692 __initdata = NULL; static int -w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops, - struct bc_hw_ops *bc_ops) +w6692_hw_init(struct IsdnCardState *cs) { - cs->dc_hw_ops = dc_ops; - cs->bc_hw_ops = bc_ops; + cs->card_ops = &w6692_ops; + cs->dc_hw_ops = &w6692_dc_hw_ops, + cs->bc_hw_ops = &w6692_bc_hw_ops; dc_l1_init(cs, &w6692_dc_l1_ops); cs->bc_l1_ops = &w6692_bc_l1_ops; W6692Version(cs, "W6692:"); @@ -685,14 +685,45 @@ return 0; } +static int __init +w6692_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + int rc; + + printk(KERN_INFO "W6692: %s %s at %#lx IRQ %d\n", + id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, + pci_resource_start(pdev, 1), pdev->irq); + + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; + + /* USR ISDN PCI card TA need some special handling */ + if (cs->subtyp == W6692_WINBOND) { + if (pdev->subsystem_vendor == W6692_SV_USR && + pdev->subsystem_device == W6692_SD_USR) { + cs->subtyp = W6692_USR; + } + } + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.w6692.iobase = pci_resource_start(pdev, 1); + + if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, + id_list[cs->subtyp].card_name)) + goto err; + + w6692_hw_init(cs); + return 0; + err: + hisax_release_resources(cs); + return rc; +} + int __init setup_w6692(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; - u8 found = 0; - u8 pci_irq = 0; - u_int pci_ioaddr = 0; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" @@ -704,54 +735,13 @@ id_list[id_idx].device_id, dev_w6692); if (dev_w6692) { - if (pci_enable_device(dev_w6692)) - continue; - cs->subtyp = id_idx; - break; + card->cs->subtyp = id_idx; + if (w6692_probe(card->cs, dev_w6692) < 0) + return 0; + return 1; } id_idx++; } - if (dev_w6692) { - found = 1; - pci_irq = dev_w6692->irq; - /* I think address 0 is allways the configuration area */ - /* and address 1 is the real IO space KKe 03.09.99 */ - pci_ioaddr = pci_resource_start(dev_w6692, 1); - /* USR ISDN PCI card TA need some special handling */ - if (cs->subtyp == W6692_WINBOND) { - if ((W6692_SV_USR == dev_w6692->subsystem_vendor) && - (W6692_SD_USR == dev_w6692->subsystem_device)) { - cs->subtyp = W6692_USR; - } - } - } - if (!found) { - printk(KERN_WARNING "W6692: No PCI card found\n"); - return (0); - } - cs->irq = pci_irq; - if (!cs->irq) { - printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); - return (0); - } - if (!pci_ioaddr) { - printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); - return (0); - } - cs->hw.w6692.iobase = pci_ioaddr; - printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", - id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, - pci_ioaddr, pci_irq); - if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, id_list[cs->subtyp].card_name)) - return 0; - - printk(KERN_INFO - "HiSax: %s config irq:%d I/O:%x\n", - id_list[cs->subtyp].card_name, cs->irq, - cs->hw.w6692.iobase); - - cs->card_ops = &w6692_ops; - w6692_setup(cs, &w6692_dc_hw_ops, &w6692_bc_hw_ops); - cs->irq_flags |= SA_SHIRQ; - return (1); + printk(KERN_WARNING "W6692: No PCI card found\n"); + return 0; } diff -Nru a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig --- a/drivers/isdn/i4l/Kconfig Tue Nov 12 12:48:13 2002 +++ b/drivers/isdn/i4l/Kconfig Sat Feb 22 09:17:33 2003 @@ -85,7 +85,7 @@ config ISDN_X25 bool "X.25 PLP on top of ISDN" - depends on X25 + depends on X25 && BROKEN help This feature provides the X.25 protocol over ISDN connections. See for more information diff -Nru a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c --- a/drivers/isdn/i4l/isdn_net_lib.c Tue Nov 12 13:33:35 2002 +++ b/drivers/isdn/i4l/isdn_net_lib.c Sat Feb 22 09:17:33 2003 @@ -58,6 +58,7 @@ #include "isdn_net.h" #include "isdn_ppp.h" #include "isdn_ciscohdlck.h" +#include "isdn_concap.h" #define ISDN_NET_TX_TIMEOUT (20*HZ) diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c --- a/drivers/isdn/i4l/isdn_ppp.c Tue Nov 12 13:34:48 2002 +++ b/drivers/isdn/i4l/isdn_ppp.c Sat Mar 1 13:01:59 2003 @@ -867,7 +867,7 @@ skb_pull(skb, 1); } else { if (skb->len < 2) - return -1; + return -EINVAL; get_u16(skb->data, proto); skb_pull(skb, 2); } @@ -1037,7 +1037,7 @@ isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1); ippp_push_proto(ind_ppp, skb, proto); - ippp_mp_xmit(idev, skb, proto); + ippp_mp_xmit(idev, skb); return 0; drop: diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.c b/drivers/isdn/i4l/isdn_ppp_mp.c --- a/drivers/isdn/i4l/isdn_ppp_mp.c Tue Oct 29 18:41:43 2002 +++ b/drivers/isdn/i4l/isdn_ppp_mp.c Sat Feb 22 10:03:46 2003 @@ -91,12 +91,13 @@ } void -ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) +ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb) { struct ind_ppp *ind_ppp = idev->ind_priv; struct inl_ppp *inl_ppp = idev->mlp->inl_priv; unsigned char *p; - long txseq; + u32 txseq; + u16 proto; if (!(inl_ppp->mp_cfg & SC_MP_PROT)) { return ippp_xmit(idev, skb); diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.h b/drivers/isdn/i4l/isdn_ppp_mp.h --- a/drivers/isdn/i4l/isdn_ppp_mp.h Tue Oct 29 18:28:25 2002 +++ b/drivers/isdn/i4l/isdn_ppp_mp.h Sat Feb 22 10:03:46 2003 @@ -19,7 +19,7 @@ int ippp_mp_bind(isdn_net_dev *idev); void ippp_mp_disconnected(isdn_net_dev *idev); int ippp_mp_bundle(isdn_net_dev *idev, int val); -void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto); +void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb); void ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto); #else @@ -42,9 +42,9 @@ } static inline void -ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) +ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb) { - ippp_xmit(idev, skb, proto); + ippp_xmit(idev, skb); } static inline void diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c --- a/drivers/macintosh/macserial.c Mon Nov 11 05:18:24 2002 +++ b/drivers/macintosh/macserial.c Fri Feb 14 15:20:31 2003 @@ -3043,10 +3043,12 @@ /* * Register console. */ -void __init mac_scc_console_init(void) +static void __init mac_scc_console_init(void) { register_console(&sercons); } +console_initcall(mac_scc_console_init); + #endif /* ifdef CONFIG_SERIAL_CONSOLE */ #ifdef CONFIG_KGDB diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c --- a/drivers/md/dm.c Thu Jan 2 03:27:23 2003 +++ b/drivers/md/dm.c Sat Mar 8 14:50:22 2003 @@ -79,9 +79,8 @@ return -ENOMEM; _major = major; - r = register_blkdev(_major, _name, &dm_blk_dops); + r = register_blkdev(_major, _name); if (r < 0) { - DMERR("register_blkdev failed"); kmem_cache_destroy(_io_cache); return r; } diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Tue Feb 25 02:44:05 2003 +++ b/drivers/md/md.c Sat Mar 8 14:50:30 2003 @@ -2803,7 +2803,9 @@ idle = 1; ITERATE_RDEV(mddev,rdev,tmp) { struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; - curr_events = disk->read_sectors + disk->write_sectors - disk->sync_io; + curr_events = disk_stat_read(disk, read_sectors) + + disk_stat_read(disk, write_sectors) - + disk->sync_io; if ((curr_events - rdev->last_events) > 32) { rdev->last_events = curr_events; idle = 0; @@ -3214,11 +3216,10 @@ MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); - if (register_blkdev (MAJOR_NR, "md", &md_fops)) { - printk(KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR); - return (-1); - } - devfs_mk_dir (NULL, "md", NULL); + if (register_blkdev(MAJOR_NR, "md")) + return -1; + + devfs_mk_dir(NULL, "md", NULL); blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE, md_probe, NULL, NULL); for (minor=0; minor < MAX_MD_DEVS; ++minor) { diff -Nru a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c --- a/drivers/media/video/bw-qcam.c Fri Nov 29 08:30:40 2002 +++ b/drivers/media/video/bw-qcam.c Sun Feb 16 16:16:53 2003 @@ -83,11 +83,9 @@ static unsigned int yieldlines=4; /* Yield after this many during capture */ static int video_nr = -1; -#if LINUX_VERSION_CODE >= 0x020117 MODULE_PARM(maxpoll,"i"); MODULE_PARM(yieldlines,"i"); MODULE_PARM(video_nr,"i"); -#endif static inline int read_lpstatus(struct qcam_device *q) { diff -Nru a/drivers/media/video/planb.c b/drivers/media/video/planb.c --- a/drivers/media/video/planb.c Fri Nov 29 08:30:40 2002 +++ b/drivers/media/video/planb.c Sun Feb 16 16:16:53 2003 @@ -181,12 +181,7 @@ /* Let's wait 30msec for this one */ current->state = TASK_INTERRUPTIBLE; -#if LINUX_VERSION_CODE >= 0x02017F schedule_timeout(30 * HZ / 1000); -#else - current->timeout = jiffies + 30 * HZ / 1000; /* 30 ms */; - schedule(); -#endif return (unsigned char)in_8 (&planb_regs->saa_status); } diff -Nru a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c --- a/drivers/media/video/video-buf.c Wed Jan 8 01:59:58 2003 +++ b/drivers/media/video/video-buf.c Thu Mar 6 07:10:08 2003 @@ -83,6 +83,8 @@ return NULL; memset(sglist, 0, sizeof(*sglist) * nr_pages); + if (NULL == pages[0]) + goto nopage; if (PageHighMem(pages[0])) /* DMA to highmem pages might not work */ goto highmem; @@ -118,7 +120,7 @@ for (i = 0; i < nr_pages; i++) if (TryLockPage(pages[i])) goto err; - dprintk(2,"lock ok\n"); + dprintk(2,"lock ok [%d pages]\n",nr_pages); return 0; err: @@ -136,7 +138,7 @@ dprintk(2,"unlock start ...\n"); for (i = 0; i < nr_pages; i++) unlock_page(pages[i]); - dprintk(2,"unlock ok\n"); + dprintk(2,"unlock ok [%d pages]\n",nr_pages); return 0; } @@ -270,7 +272,7 @@ /* --------------------------------------------------------------------- */ -void* videobuf_alloc(int size) +void* videobuf_alloc(unsigned int size) { struct videobuf_buffer *vb; @@ -340,7 +342,7 @@ spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, - int msize) + unsigned int msize) { memset(q,0,sizeof(*q)); @@ -417,11 +419,11 @@ if (V4L2_FIELD_ALTERNATE == field) { if (V4L2_FIELD_TOP == q->last) { - field = V4L2_FIELD_TOP; - q->last = V4L2_FIELD_TOP; - } else { field = V4L2_FIELD_BOTTOM; q->last = V4L2_FIELD_BOTTOM; + } else { + field = V4L2_FIELD_TOP; + q->last = V4L2_FIELD_TOP; } } return field; @@ -463,7 +465,8 @@ videobuf_reqbufs(struct file *file, struct videobuf_queue *q, struct v4l2_requestbuffers *req) { - int size,count,retval; + unsigned int size,count; + int retval; if (req->type != q->type) return -EINVAL; @@ -477,6 +480,8 @@ size = 0; q->ops->buf_setup(file,&count,&size); size = PAGE_ALIGN(size); + dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n", + count, size, (count*size)>>PAGE_SHIFT); retval = videobuf_mmap_setup(file,q,count,size); if (retval < 0) @@ -660,7 +665,10 @@ retval = videobuf_waiton(q->read_buf,0,0); if (0 == retval) { videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); - retval = q->read_buf->size; + if (STATE_ERROR == q->read_buf->state) + retval = -EIO; + else + retval = q->read_buf->size; } done: @@ -676,7 +684,8 @@ { enum v4l2_field field; unsigned long flags; - int retval, bytes, size, nbufs; + unsigned size, nbufs, bytes; + int retval; down(&q->lock); @@ -686,7 +695,7 @@ count >= size && !(file->f_flags & O_NONBLOCK)) { retval = videobuf_read_zerocopy(file,q,data,count,ppos); - if (retval >= 0) + if (retval >= 0 || retval == -EIO) /* ok, all done */ goto done; /* fallback to kernel bounce buffer on failures */ @@ -714,6 +723,15 @@ goto done; videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); + if (STATE_ERROR == q->read_buf->state) { + /* catch I/O errors */ + q->ops->buf_release(file,q->read_buf); + kfree(q->read_buf); + q->read_buf = NULL; + retval = -EIO; + goto done; + } + /* copy to userspace */ bytes = count; if (bytes > q->read_buf->size - q->read_off) @@ -788,8 +806,8 @@ char *data, size_t count, loff_t *ppos, int vbihack) { - unsigned int *fc; - int err, bytes, retval; + unsigned int *fc, bytes; + int err, retval; unsigned long flags; down(&q->lock); @@ -968,9 +986,10 @@ }; int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, - int bcount, int bsize) + unsigned int bcount, unsigned int bsize) { - int i,err; + unsigned int i; + int err; err = videobuf_mmap_free(file,q); if (0 != err) @@ -1008,7 +1027,8 @@ struct videobuf_queue *q) { struct videobuf_mapping *map; - int first,last,size,i,retval; + unsigned int first,last,size,i; + int retval; down(&q->lock); retval = -EINVAL; @@ -1025,7 +1045,7 @@ for (first = 0; first < VIDEO_MAX_FRAME; first++) { if (NULL == q->bufs[first]) continue; - if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) + if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) break; } if (VIDEO_MAX_FRAME == first) { diff -Nru a/drivers/media/video/video-buf.h b/drivers/media/video/video-buf.h --- a/drivers/media/video/video-buf.h Wed Jan 8 01:59:58 2003 +++ b/drivers/media/video/video-buf.h Thu Mar 6 06:29:59 2003 @@ -110,7 +110,7 @@ struct videobuf_queue; struct videobuf_mapping { - int count; + unsigned int count; int highmem_ok; unsigned long start; unsigned long end; @@ -128,19 +128,19 @@ }; struct videobuf_buffer { - int i; + unsigned int i; /* info about the buffer */ - int width; - int height; - long size; + unsigned int width; + unsigned int height; + unsigned long size; enum v4l2_field field; enum videobuf_state state; struct videobuf_dmabuf dma; struct list_head stream; /* QBUF/DQBUF list */ /* for mmap'ed buffers */ - off_t boff; /* buffer offset (mmap) */ + size_t boff; /* buffer offset (mmap) */ size_t bsize; /* buffer size */ unsigned long baddr; /* buffer addr (userland ptr!) */ struct videobuf_mapping *map; @@ -148,12 +148,13 @@ /* touched by irq handler */ struct list_head queue; wait_queue_head_t done; - int field_count; + unsigned int field_count; struct timeval ts; }; struct videobuf_queue_ops { - int (*buf_setup)(struct file *file, int *count, int *size); + int (*buf_setup)(struct file *file, + unsigned int *count, unsigned int *size); int (*buf_prepare)(struct file *file,struct videobuf_buffer *vb, enum v4l2_field field); void (*buf_queue)(struct file *file,struct videobuf_buffer *vb); @@ -166,23 +167,23 @@ struct pci_dev *pci; enum v4l2_buf_type type; - int msize; + unsigned int msize; enum v4l2_field field; enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ struct videobuf_buffer *bufs[VIDEO_MAX_FRAME]; struct videobuf_queue_ops *ops; /* capture via mmap() + ioctl(QBUF/DQBUF) */ - int streaming; + unsigned int streaming; struct list_head stream; /* capture via read() */ - int reading; - int read_off; + unsigned int reading; + unsigned int read_off; struct videobuf_buffer *read_buf; }; -void* videobuf_alloc(int size); +void* videobuf_alloc(unsigned int size); int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb); @@ -190,7 +191,8 @@ struct videobuf_queue_ops *ops, struct pci_dev *pci, spinlock_t *irqlock, enum v4l2_buf_type type, - enum v4l2_field field, int msize); + enum v4l2_field field, + unsigned int msize); int videobuf_queue_is_busy(struct videobuf_queue *q); void videobuf_queue_cancel(struct file *file, struct videobuf_queue *q); @@ -218,7 +220,7 @@ poll_table *wait); int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, - int bcount, int bsize); + unsigned int bcount, unsigned int bsize); int videobuf_mmap_free(struct file *file, struct videobuf_queue *q); int videobuf_mmap_mapper(struct vm_area_struct *vma, struct videobuf_queue *q); diff -Nru a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h --- a/drivers/media/video/zoran.h Tue Feb 5 11:10:31 2002 +++ b/drivers/media/video/zoran.h Sun Feb 16 16:16:53 2003 @@ -32,10 +32,6 @@ #include -#if LINUX_VERSION_CODE < 0x20212 -typedef struct wait_queue *wait_queue_head_t; -#endif - /* The Buz only supports a maximum width of 720, but some V4L applications (e.g. xawtv are more happy with 768). If XAWTV_HACK is defined, we try to fake a device with bigger width */ diff -Nru a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c --- a/drivers/media/video/zr36120.c Thu Feb 6 07:33:47 2003 +++ b/drivers/media/video/zr36120.c Sun Feb 16 16:16:53 2003 @@ -943,7 +943,6 @@ return -EINVAL; } -#if LINUX_VERSION_CODE >= 0x020100 static unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait) { @@ -964,7 +963,6 @@ return mask; } -#endif /* append a new clipregion to the vector of video_clips */ static @@ -1745,7 +1743,6 @@ return count; } -#if LINUX_VERSION_CODE >= 0x020100 static unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait) { @@ -1766,7 +1763,6 @@ return mask; } -#endif static int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) diff -Nru a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h --- a/drivers/message/fusion/lsi/mpi_raid.h Fri Feb 21 06:26:38 2003 +++ b/drivers/message/fusion/lsi/mpi_raid.h Thu Feb 20 08:33:15 2003 @@ -184,7 +184,7 @@ /****************************************************************************/ -/* Mailbox reqeust structure */ +/* Mailbox request structure */ /****************************************************************************/ typedef struct _MSG_MAILBOX_REQUEST diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c --- a/drivers/message/i2o/i2o_block.c Tue Feb 25 11:05:27 2003 +++ b/drivers/message/i2o/i2o_block.c Sat Mar 8 14:50:22 2003 @@ -1608,12 +1608,8 @@ /* * Register the block device interfaces */ - - if (register_blkdev(MAJOR_NR, "i2o_block", &i2ob_fops)) { - printk(KERN_ERR "Unable to get major number %d for i2o_block\n", - MAJOR_NR); + if (register_blkdev(MAJOR_NR, "i2o_block")) return -EIO; - } for (i = 0; i < MAX_I2OB; i++) { struct gendisk *disk = alloc_disk(16); diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c --- a/drivers/mtd/ftl.c Wed Feb 26 05:35:35 2003 +++ b/drivers/mtd/ftl.c Sat Mar 8 14:50:22 2003 @@ -1281,11 +1281,9 @@ static spinlock_t lock = SPIN_LOCK_UNLOCKED; DEBUG(0, "$Id: ftl.c,v 1.39 2001/10/02 15:05:11 dwmw2 Exp $\n"); - if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) { - printk(KERN_NOTICE "ftl_cs: unable to grab major " - "device number!\n"); + if (register_blkdev(FTL_MAJOR, "ftl")) return -EAGAIN; - } + blk_init_queue(&ftl_queue, &do_ftl_request, &lock); register_mtd_user(&ftl_notifier); return 0; diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c --- a/drivers/mtd/mtdblock.c Tue Feb 11 14:57:51 2003 +++ b/drivers/mtd/mtdblock.c Sat Mar 8 14:50:22 2003 @@ -570,11 +570,10 @@ int __init init_mtdblock(void) { spin_lock_init(&mtdblks_lock); - if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_BLOCK_MAJOR); + + if (register_blkdev(MAJOR_NR, DEVICE_NAME)) return -EAGAIN; - } + #ifdef CONFIG_DEVFS_FS devfs_mk_dir(NULL, DEVICE_NAME, NULL); #endif diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c --- a/drivers/mtd/mtdblock_ro.c Mon Oct 28 11:57:56 2002 +++ b/drivers/mtd/mtdblock_ro.c Sat Mar 8 14:50:22 2003 @@ -240,20 +240,13 @@ int __init init_mtdblock(void) { - int err; - - if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_BLOCK_MAJOR); - err = -EAGAIN; - goto out; - } + if (register_blkdev(MAJOR_NR, DEVICE_NAME)) + return -EAGAIN; blk_init_queue(&mtdro_queue, &mtdblock_request, &mtdro_lock); register_mtd_user(¬ifier); - err = 0; - out: - return err; + + return 0; } static void __exit cleanup_mtdblock(void) diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c --- a/drivers/mtd/nftlcore.c Wed Feb 26 05:35:01 2003 +++ b/drivers/mtd/nftlcore.c Sat Mar 8 14:50:22 2003 @@ -928,10 +928,8 @@ printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.82 $, nftlmount.c %s\n", nftlmountrev); #endif - if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)) { - printk("unable to register NFTL block device on major %d\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, "nftl")) return -EBUSY; - } blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE, nftl_probe, NULL, NULL); diff -Nru a/drivers/net/bonding.c b/drivers/net/bonding.c --- a/drivers/net/bonding.c Tue Feb 18 10:50:38 2003 +++ b/drivers/net/bonding.c Sat Mar 8 14:50:38 2003 @@ -2574,6 +2574,13 @@ return 0; } + if (bond->slave_cnt == 0) { + /* no slaves in the bond, frame not sent */ + dev_kfree_skb(skb); + read_unlock_irqrestore(&bond->lock, flags); + return 0; + } + slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt; while ( (slave_no > 0) && (slave != (slave_t *)bond) ) { diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c --- a/drivers/net/dgrs.c Tue Feb 25 11:05:27 2003 +++ b/drivers/net/dgrs.c Tue Mar 4 22:44:07 2003 @@ -981,7 +981,7 @@ { DGRS_PRIV *priv0 = (DGRS_PRIV *) dev0->priv; int is; - int i; + unsigned long i; static int iv2is[16] = { 0, 0, 0, ES4H_IS_INT3, @@ -1140,7 +1140,7 @@ dgrs_probe1(struct net_device *dev) { DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv; - int i; + unsigned long i; int rc; printk("%s: Digi RightSwitch io=%lx mem=%lx irq=%d plx=%lx dma=%lx\n", diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c --- a/drivers/net/eepro100.c Mon Feb 24 10:34:28 2003 +++ b/drivers/net/eepro100.c Sat Mar 8 18:51:49 2003 @@ -529,8 +529,6 @@ static int eepro100_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static void eepro100_remove_one (struct pci_dev *pdev); - static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len); static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); @@ -843,6 +841,7 @@ sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE); sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE); init_timer(&sp->timer); /* used in ioctl() */ + spin_lock_init(&sp->lock); sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0; if (card_idx >= 0) { @@ -994,7 +993,6 @@ sp->dirty_tx = 0; sp->last_cmd = 0; sp->tx_full = 0; - spin_lock_init(&sp->lock); sp->in_interrupt = 0; /* .. we can safely take handler calls during init. */ diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c --- a/drivers/net/eth16i.c Tue Feb 25 02:08:43 2003 +++ b/drivers/net/eth16i.c Thu Mar 6 09:23:56 2003 @@ -1404,7 +1404,6 @@ static char* mediatype[MAX_ETH16I_CARDS]; static int debug = -1; -#if (LINUX_VERSION_CODE >= 0x20115) MODULE_AUTHOR("Mika Kuoppala "); MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver"); MODULE_LICENSE("GPL"); @@ -1423,7 +1422,6 @@ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "eth16i debug level (0-6)"); -#endif int init_module(void) { diff -Nru a/drivers/net/mac8390.c b/drivers/net/mac8390.c --- a/drivers/net/mac8390.c Sun Feb 9 17:29:54 2003 +++ b/drivers/net/mac8390.c Sun Feb 16 16:17:32 2003 @@ -376,11 +376,9 @@ } #ifdef MODULE -#if LINUX_VERSION_CODE > 0x20118 MODULE_AUTHOR("David Huggins-Daines and others"); MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver"); MODUEL_LICENSE("GPL"); -#endif int init_module(void) { diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c --- a/drivers/net/pppoe.c Tue Feb 25 09:17:47 2003 +++ b/drivers/net/pppoe.c Thu Mar 6 11:06:44 2003 @@ -538,7 +538,7 @@ if (!sk) return 0; - if (sk->dead != 0) + if (test_bit(SOCK_DEAD, &sk->flags)) return -EBADF; pppox_unbind_sock(sk); @@ -777,7 +777,7 @@ int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int total_len, struct scm_cookie *scm) + int total_len) { struct sk_buff *skb = NULL; struct sock *sk = sock->sk; @@ -788,7 +788,7 @@ struct net_device *dev; char *start; - if (sk->dead || !(sk->state & PPPOX_CONNECTED)) { + if (test_bit(SOCK_DEAD, &sk->flags) || !(sk->state & PPPOX_CONNECTED)) { error = -ENOTCONN; goto end; } @@ -864,7 +864,7 @@ int data_len = skb->len; struct sk_buff *skb2; - if (sk->dead || !(sk->state & PPPOX_CONNECTED)) + if (test_bit(SOCK_DEAD, &sk->flags) || !(sk->state & PPPOX_CONNECTED)) goto abort; hdr.ver = 1; @@ -937,7 +937,8 @@ struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL }; -int pppoe_rcvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len, int flags, struct scm_cookie *scm) +int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, int total_len, int flags) { struct sock *sk = sock->sk; struct sk_buff *skb = NULL; @@ -1089,7 +1090,7 @@ .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = pppoe_sendmsg, - .recvmsg = pppoe_rcvmsg, + .recvmsg = pppoe_recvmsg, .mmap = sock_no_mmap }; diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c --- a/drivers/net/shaper.c Sat Feb 15 11:32:47 2003 +++ b/drivers/net/shaper.c Tue Mar 4 22:44:07 2003 @@ -88,10 +88,10 @@ #include struct shaper_cb { + unsigned long shapeclock; /* Time it should go out */ + unsigned long shapestamp; /* Stamp for shaper */ __u32 shapelatency; /* Latency on frame */ - __u32 shapeclock; /* Time it should go out */ __u32 shapelen; /* Frame length in clocks */ - __u32 shapestamp; /* Stamp for shaper */ __u16 shapepend; /* Pending */ }; #define SHAPERCB(skb) ((struct shaper_cb *) ((skb)->cb)) @@ -335,7 +335,7 @@ */ if(sh_debug) - printk("Clock = %d, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies); + printk("Clock = %ld, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies); if(time_before_eq(SHAPERCB(skb)->shapeclock - jiffies, SHAPER_BURST)) { /* diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c --- a/drivers/net/sis900.c Tue Feb 25 02:45:05 2003 +++ b/drivers/net/sis900.c Tue Mar 4 22:44:07 2003 @@ -509,7 +509,7 @@ { struct sis900_private * sis_priv = net_dev->priv; u16 poll_bit = MII_STAT_LINK, status = 0; - unsigned int timeout = jiffies + 5 * HZ; + unsigned long timeout = jiffies + 5 * HZ; int phy_addr; u8 revision; diff -Nru a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h --- a/drivers/net/sk98lin/h/skgepnm2.h Mon Feb 4 23:42:03 2002 +++ b/drivers/net/sk98lin/h/skgepnm2.h Thu Mar 6 08:18:07 2003 @@ -341,7 +341,7 @@ #if SK_TICKS_PER_SEC == 100 #define SK_PNMI_HUNDREDS_SEC(t) (t) #else -#define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC)) +#define SK_PNMI_HUNDREDS_SEC(t) ((((long)t) * 100) / (SK_TICKS_PER_SEC)) #endif /* diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c --- a/drivers/net/sk_mca.c Mon Feb 24 12:16:14 2003 +++ b/drivers/net/sk_mca.c Thu Mar 6 09:24:43 2003 @@ -649,9 +649,7 @@ skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_NONE; priv->stat.rx_packets++; -#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */ priv->stat.rx_bytes += descr.Len; -#endif netif_rx(skb); dev->last_rx = jiffies; } @@ -709,9 +707,7 @@ /* update statistics */ if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0) { priv->stat.tx_packets++; -#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */ priv->stat.tx_bytes++; -#endif } else { priv->stat.tx_errors++; if ((descr.Status & TXDSCR_STATUS_UFLO) != 0) { @@ -1001,13 +997,8 @@ tx_done: - /* When did that change exactly ? */ - -#if LINUX_VERSION_CODE >= 0x020200 dev_kfree_skb(skb); -#else - dev_kfree_skb(skb, FREE_WRITE); -#endif + return retval; } @@ -1146,9 +1137,7 @@ mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter"); mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev); -#if LINUX_VERSION_CODE >= 0x020200 mca_mark_as_used(slot); -#endif /* announce success */ printk("%s: SKNet %s adapter found in slot %d\n", dev->name, @@ -1283,9 +1272,7 @@ free_irq(dev->irq, dev); dev->irq = 0; unregister_netdev(dev); -#if LINUX_VERSION_CODE >= 0x020200 mca_mark_as_unused(priv->slot); -#endif mca_set_adapter_procfn(priv->slot, NULL, NULL); kfree(dev->priv); dev->priv = NULL; diff -Nru a/drivers/net/wan/comx-hw-munich.c b/drivers/net/wan/comx-hw-munich.c --- a/drivers/net/wan/comx-hw-munich.c Tue Feb 25 02:45:14 2003 +++ b/drivers/net/wan/comx-hw-munich.c Thu Mar 6 09:25:13 2003 @@ -812,13 +812,8 @@ printk("munich_probe: munich chip found, IRQ %d\n", pci->irq); -#if (LINUX_VERSION_CODE < 0x02030d) - bar1 = ioremap_nocache(pci->base_address[0], 0x100); - lbi = ioremap_nocache(pci->base_address[1], 0x100); -#else bar1 = ioremap_nocache(pci->resource[0].start, 0x100); lbi = ioremap_nocache(pci->resource[1].start, 0x100); -#endif if (bar1 && lbi) { diff -Nru a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c --- a/drivers/net/wan/pc300_tty.c Thu Nov 21 14:06:12 2002 +++ b/drivers/net/wan/pc300_tty.c Sun Feb 16 16:22:42 2003 @@ -198,12 +198,6 @@ int port, aux; st_cpc_tty_area * cpc_tty; - if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) { - printk("%s-tty: Error: TTY driver is supported on 2.4.X kernel!\n", - ((struct net_device*)(pc300dev->hdlc))->name); - return; - } - /* hdlcX - X=interface number */ port = ((struct net_device*)(pc300dev->hdlc))->name[4] - '0'; if (port >= CPC_TTY_NPORTS) { diff -Nru a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c --- a/drivers/net/wan/sdla_chdlc.c Tue Feb 25 02:45:24 2003 +++ b/drivers/net/wan/sdla_chdlc.c Thu Mar 6 09:25:13 2003 @@ -60,14 +60,9 @@ #include /* ARPHRD_* defines */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include - #include - #include -#else - #include - #include /* Adding new route entries : 2.0.X kernels */ -#endif +#include +#include +#include #include /* sockaddr_in */ #include @@ -153,13 +148,11 @@ unsigned short timer_int_enabled; char update_comms_stats; /* updating comms stats */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) bh_data_t *bh_head; /* Circular buffer for chdlc_bh */ unsigned long tq_working; volatile int bh_write; volatile int bh_read; atomic_t bh_buff_used; -#endif unsigned char interface_down; @@ -204,15 +197,8 @@ static int if_header (struct sk_buff* skb, netdevice_t* dev, unsigned short type, void* daddr, void* saddr, unsigned len); -#if defined(LINUX_2_1) || defined(LINUX_2_4) - static int if_rebuild_hdr (struct sk_buff *skb); - static struct net_device_stats* if_stats (netdevice_t* dev); - -#else - static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb); - static struct enet_statistics* if_stats (netdevice_t* dev); -#endif +static int if_rebuild_hdr (struct sk_buff *skb); +static struct net_device_stats* if_stats (netdevice_t* dev); static int if_send (struct sk_buff* skb, netdevice_t* dev); @@ -228,9 +214,7 @@ static int chdlc_disable_comm_shutdown (sdla_t *card); -#ifdef LINUX_2_4 - static void if_tx_timeout (netdevice_t *dev); -#endif +static void if_tx_timeout (netdevice_t *dev); /* Miscellaneous CHDLC Functions */ static int set_chdlc_config (sdla_t* card); @@ -260,12 +244,10 @@ static void rx_intr (sdla_t* card); static void timer_intr(sdla_t *); -#if defined(LINUX_2_1) || defined(LINUX_2_4) - /* Bottom half handlers */ - static void chdlc_work (netdevice_t *); - static int chdlc_work_cleanup (netdevice_t *); - static int bh_enqueue (netdevice_t *, struct sk_buff *); -#endif +/* Bottom half handlers */ +static void chdlc_work (netdevice_t *); +static int chdlc_work_cleanup (netdevice_t *); +static int bh_enqueue (netdevice_t *, struct sk_buff *); /* Miscellaneous functions */ static int chk_bcast_mcast_addr(sdla_t* card, netdevice_t* dev, @@ -287,8 +269,6 @@ /* TTY Global Definitions */ -#if defined(LINUX_2_4) || defined(LINUX_2_1) - #define NR_PORTS 4 #define WAN_TTY_MAJOR 226 #define WAN_TTY_MINOR 0 @@ -321,8 +301,6 @@ static void* tty_card_map[NR_PORTS] = {NULL,NULL,NULL,NULL}; -#endif - /****** Public Functions ****************************************************/ @@ -569,7 +547,6 @@ } if ((card->tty_opt=conf->tty) == WANOPT_YES){ -#if defined(LINUX_2_4) || defined(LINUX_2_1) int err; card->tty_minor = conf->tty_minor; @@ -582,11 +559,6 @@ if (err){ return err; } -#else - printk(KERN_INFO "%s: Error: TTY driver is not supported on 2.0.X kernels!\n", - card->devname); - return -EINVAL; -#endif }else{ @@ -851,18 +823,6 @@ min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) : DEFAULT_SLARP_REQ_TIMER; -#ifdef LINUX_2_0 - if (card->u.c.slarp_timer){ - printk(KERN_INFO - "%s: Error: Dynamic IP support not available for 2.0.X kernels\n", - card->devname); - printk(KERN_INFO "%s: Defaulting to Static IP addressing\n", - card->devname); - } - card->u.c.slarp_timer=0; -#endif - - if (conf->hdlc_streaming == WANOPT_YES) { printk(KERN_INFO "%s: Enabling HDLC STREAMING Mode\n", wandev->name); @@ -892,40 +852,24 @@ } } else if( strcmp(conf->usedby, "API") == 0) { -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->u.c.usedby = API; printk(KERN_INFO "%s: Running in API mode !\n", wandev->name); -#else - printk(KERN_INFO "%s: API Mode is not supported for kernels lower than 2.2.X!\n", - wandev->name); - printk(KERN_INFO "%s: Please upgrade to a 2.2.X kernel fro the API support\n", - wandev->name); - kfree(chdlc_priv_area); - return -EINVAL; -#endif } } -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Tells us that if this interface is a * gateway or not */ if ((chdlc_priv_area->gateway = conf->gateway) == WANOPT_YES){ printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", card->devname,card->u.c.if_name); } -#endif /* Get Multicast Information */ chdlc_priv_area->mc = conf->mc; /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,card->u.c.if_name); -#else - dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); - sprintf(dev->name, "%s", card->u.c.if_name); -#endif dev->init = &if_init; dev->priv = chdlc_priv_area; @@ -958,9 +902,6 @@ chdlc_private_area_t* chdlc_priv_area = dev->priv; sdla_t* card = chdlc_priv_area->card; wan_device_t* wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* Initialize device driver entry points */ dev->open = &if_open; @@ -969,10 +910,8 @@ dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif /* Initialize media-specific parameters */ @@ -984,16 +923,8 @@ dev->flags |= IFF_MULTICAST; } -#ifdef LINUX_2_0 - dev->family = AF_INET; -#endif - if (chdlc_priv_area->true_if_encoding){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) dev->type = ARPHRD_HDLC; /* This breaks the tcpdump */ -#else - dev->type = ARPHRD_PPP; -#endif }else{ dev->type = ARPHRD_PPP; } @@ -1019,11 +950,6 @@ */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ -#if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); -#endif return 0; } @@ -1043,10 +969,9 @@ /* Only one open per interface is allowed */ - if (is_dev_running(dev)) + if (netif_running(dev)) return -EBUSY; -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Initialize the work queue entry */ chdlc_priv_area->tq_working=0; @@ -1058,18 +983,11 @@ chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC); memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1))); atomic_set(&chdlc_priv_area->bh_buff_used, 0); -#endif do_gettimeofday(&tv); chdlc_priv_area->router_start_time = tv.tv_sec; -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif wanpipe_open(card); @@ -1100,8 +1018,6 @@ chdlc_private_area_t* chdlc_priv_area = dev->priv; sdla_t* card = chdlc_priv_area->card; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - if (chdlc_priv_area->bh_head){ int i; struct sk_buff *skb; @@ -1109,18 +1025,14 @@ for (i=0; i<(MAX_BH_BUFF+1); i++){ skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb; if (skb != NULL){ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } } kfree(chdlc_priv_area->bh_head); chdlc_priv_area->bh_head=NULL; } -#endif - stop_net_queue(dev); -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); wanpipe_close(card); del_timer(&chdlc_priv_area->poll_delay_timer); return 0; @@ -1136,7 +1048,6 @@ flags->interrupt_info_struct.interrupt_permission = 0; } -#if defined(LINUX_2_4) || defined(LINUX_2_1) if (!tty_init_cnt) return; @@ -1160,7 +1071,6 @@ state = &rs_table[card->tty_minor]; memset(state,0,sizeof(state)); } -#endif return; } @@ -1183,7 +1093,6 @@ } -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -1203,7 +1112,6 @@ printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); netif_wake_queue (dev); } -#endif @@ -1213,18 +1121,11 @@ * Return: 1 physical address resolved. * 0 physical address not resolved */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr (struct sk_buff *skb) { return 1; } -#else -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb) -{ - return 1; -} -#endif + /*============================================================================ * Send a packet on a network interface. @@ -1253,9 +1154,7 @@ unsigned long smp_flags; int err=0; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif if (skb == NULL){ /* If we get here, some higher layer thinks we've missed an @@ -1264,31 +1163,10 @@ printk(KERN_INFO "%s: interface %s got kicked!\n", card->devname, dev->name); - wake_net_dev(dev); + netif_wake_queue(dev); return 0; } -#ifndef LINUX_2_4 - if (dev->tbusy){ - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - ++card->wandev.stats.collisions; - if((jiffies - chdlc_priv_area->tick_counter) < (5 * HZ)) { - return 1; - } - - printk (KERN_INFO "%s: Transmit timeout !\n", - card->devname); - - /* unbusy the interface */ - clear_bit(0,&dev->tbusy); - } -#endif - if (ntohs(skb->protocol) != htons(PVC_PROT)){ /* check the udp packet type */ @@ -1301,7 +1179,7 @@ chdlc_int->interrupt_permission |= APP_INT_ON_TIMER; } - start_net_queue(dev); + netif_start_queue(dev); return 0; } @@ -1309,8 +1187,8 @@ /* multicast IP address */ if(chk_bcast_mcast_addr(card, dev, skb)){ ++card->wandev.stats.tx_dropped; - wan_dev_kfree_skb(skb,FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } } @@ -1325,17 +1203,17 @@ printk(KERN_INFO "%s: Critical in if_send: %lx\n", card->wandev.name,card->wandev.critical); ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_exit_crit; } if(card->u.c.state != WAN_CONNECTED){ ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); }else if(!skb->protocol){ ++card->wandev.stats.tx_errors; - start_net_queue(dev); + netif_start_queue(dev); }else { void* data = skb->data; @@ -1355,7 +1233,7 @@ (len <= sizeof(api_tx_hdr_t))) { ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_exit_crit; } @@ -1366,25 +1244,21 @@ } if(chdlc_send(card, data, len)) { - stop_net_queue(dev); + netif_stop_queue(dev); }else{ ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += len; -#endif - start_net_queue(dev); + netif_start_queue(dev); -#ifdef LINUX_2_4 dev->trans_start = jiffies; -#endif } } if_send_exit_crit: - if (!(err=is_queue_stopped(dev))) { - wan_dev_kfree_skb(skb, FREE_WRITE); + if (!(err=netif_queue_stopped(dev))) { + dev_kfree_skb_any(skb); }else{ chdlc_priv_area->tick_counter = jiffies; chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; @@ -1409,14 +1283,12 @@ { u32 src_ip_addr; u32 broadcast_ip_addr = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev; -#endif + /* read the IP source address from the outgoing packet */ src_ip_addr = *(u32 *)(skb->data + 12); /* read the IP broadcast address for the device */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) in_dev = dev->ip_ptr; if(in_dev != NULL) { struct in_ifaddr *ifa= in_dev->ifa_list; @@ -1425,9 +1297,6 @@ else return 0; } -#else - broadcast_ip_addr = dev->pa_brdaddr; -#endif /* check if the IP Source Address is a Broadcast address */ if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { @@ -1552,7 +1421,6 @@ * Get ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats* if_stats (netdevice_t* dev) { sdla_t *my_card; @@ -1564,19 +1432,7 @@ my_card = chdlc_priv_area->card; return &my_card->wandev.stats; } -#else -static struct enet_statistics* if_stats (netdevice_t* dev) -{ - sdla_t *my_card; - chdlc_private_area_t* chdlc_priv_area = dev->priv; - if ((chdlc_priv_area=dev->priv) == NULL) - return NULL; - - my_card = chdlc_priv_area->card; - return &my_card->wandev.stats; -} -#endif /****** Cisco HDLC Firmware Interface Functions *******************************/ @@ -1846,7 +1702,7 @@ return 0; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) + /********** Bottom Half Handlers ********************************************/ /* NOTE: There is no API, BH support for Kernels lower than 2.2.X. @@ -1873,7 +1729,7 @@ if (chan->common.sk == NULL || chan->common.func == NULL){ ++card->wandev.stats.rx_dropped; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); chdlc_work_cleanup(dev); continue; } @@ -1921,7 +1777,7 @@ if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){ ++card->wandev.stats.rx_dropped; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return 1; } @@ -1940,7 +1796,6 @@ /* END OF API BH Support */ -#endif /****** Interrupt Handlers **************************************************/ @@ -2017,24 +1872,19 @@ flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_TX_FRAME; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - if (card->tty_opt){ wanpipe_tty_trigger_poll(card); break; } - if (dev && is_queue_stopped(dev)){ + if (dev && netif_queue_stopped(dev)){ if (card->u.c.usedby == API){ - start_net_queue(dev); + netif_start_queue(dev); wakeup_sk_bh(dev); }else{ - wake_net_dev(dev); + netif_wake_queue(dev); } } -#else - wake_net_dev(dev); -#endif break; case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */ @@ -2120,7 +1970,6 @@ len = rxbuf->frame_length; -#if defined(LINUX_2_4) || defined(LINUX_2_1) if (card->tty_opt){ if (rxbuf->error_flag){ @@ -2138,7 +1987,6 @@ wanpipe_tty_receive(card,addr,len); goto rx_exit; } -#endif dev = card->wandev.dev; @@ -2146,7 +1994,7 @@ goto rx_exit; } - if (!is_dev_running(dev)) + if (!netif_running(dev)) goto rx_exit; chdlc_priv_area = dev->priv; @@ -2177,9 +2025,7 @@ skb->protocol = htons(ETH_P_IP); card->wandev.stats.rx_packets ++; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.rx_bytes += skb->len; -#endif udp_type = udp_pkt_type( skb, card ); if(udp_type == UDP_CPIPE_TYPE) { @@ -2189,7 +2035,6 @@ interrupt_permission |= APP_INT_ON_TIMER; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) } else if(card->u.c.usedby == API) { api_rx_hdr_t* api_rx_hdr; @@ -2207,7 +2052,6 @@ if (!test_and_set_bit(0,&chdlc_priv_area->tq_working)) wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work); -#endif }else{ /* FIXME: we should check to see if the received packet is a multicast packet so that we can increment the multicast @@ -2331,7 +2175,6 @@ netdevice_t * dev = card->wandev.dev; chdlc_private_area_t *chdlc_priv_area = dev->priv; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev = dev->ip_ptr; if(in_dev != NULL) { @@ -2344,12 +2187,6 @@ chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask); } } -#else - cfg.IP_address = ntohl(dev->pa_addr); - cfg.IP_netmask = ntohl(dev->pa_mask); - chdlc_priv_area->IP_address = ntohl(dev->pa_addr); - chdlc_priv_area->IP_netmask = ntohl(dev->pa_mask); -#endif /* FIXME: We must re-think this message in next release if((cfg.IP_address & 0x000000FF) > 2) { @@ -2647,15 +2484,10 @@ u32 remote_IP_addr = 0; u32 IP_netmask, IP_addr; int err = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev; mm_segment_t fs; struct ifreq if_info; struct sockaddr_in *if_data1, *if_data2; -#else - unsigned long fs = 0; - struct rtentry route; -#endif chdlc_priv_area = dev->priv; port_num = card->u.c.comm_port; @@ -2705,7 +2537,6 @@ return; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) in_dev = dev->ip_ptr; if(in_dev != NULL) { @@ -2715,11 +2546,6 @@ IP_netmask = ifa->ifa_mask; } } -#else - local_IP_addr = dev->pa_addr; - remote_IP_addr = dev->pa_dstaddr; - IP_netmask = dev->pa_mask; -#endif }else{ /* According to Cisco HDLC, if the point-to-point address is A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa. @@ -2749,44 +2575,20 @@ fs = get_fs(); /* Save file system */ set_fs(get_ds()); /* Get user space block */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Setup a structure for adding/removing routes */ memset(&if_info, 0, sizeof(if_info)); strcpy(if_info.ifr_name, dev->name); -#else - /* Setup a structure for adding/removing routes */ - dev->pa_mask = IP_netmask; - dev->pa_dstaddr = remote_IP_addr; - dev->pa_addr = local_IP_addr; - - memset(&route, 0, sizeof(route)); - route.rt_dev = dev->name; - route.rt_flags = 0; - ((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr = - dev->pa_dstaddr; - ((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr = - 0xFFFFFFFF; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_family = - AF_INET; -#endif - switch (chdlc_priv_area->route_status) { case ADD_ROUTE: if(!card->u.c.slarp_timer) { -#if defined(LINUX_2_1) || defined(LINUX_2_4) if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; if_data2->sin_addr.s_addr = remote_IP_addr; if_data2->sin_family = AF_INET; err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); -#else - err = ip_rt_new(&route); -#endif } else { -#if defined(LINUX_2_1) || defined(LINUX_2_4) if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; if_data1->sin_addr.s_addr = local_IP_addr; if_data1->sin_family = AF_INET; @@ -2796,9 +2598,6 @@ if_data2->sin_family = AF_INET; err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); } -#else - err = ip_rt_new(&route); -#endif } if(err) { @@ -2819,7 +2618,6 @@ case REMOVE_ROUTE: -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Change the local ip address of the interface to 0. * This will also delete the destination route. */ @@ -2835,11 +2633,6 @@ err = devinet_ioctl(SIOCSIFADDR,&if_info); } -#else - /* set the point-to-point IP address to 0.0.0.0 */ - dev->pa_dstaddr = 0; - err = ip_rt_kill(&route); -#endif if(err) { printk(KERN_INFO "%s: Remove route %u.%u.%u.%u failed, (err %d)\n", @@ -2880,9 +2673,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK){ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } return(udp_pkt_stored); @@ -3256,9 +3049,7 @@ if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) { ++ card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += len; -#endif } } } else { @@ -3808,30 +3599,21 @@ void s508_lock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock_irqsave(&card->wandev.lock, *smp_flags); if (card->next){ spin_lock(&card->next->wandev.lock); } -#else - disable_irq(card->hw.irq); -#endif } void s508_unlock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) if (card->next){ spin_unlock(&card->next->wandev.lock); } spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -#else - enable_irq(card->hw.irq); -#endif } //*********** TTY SECTION **************** -#if defined(LINUX_2_4) || defined(LINUX_2_1) static void wanpipe_tty_trigger_tx_irq(sdla_t *card) { @@ -3858,8 +3640,7 @@ (tty->ldisc.write_wakeup)(tty); } wake_up_interruptible(&tty->write_wait); -#if defined(SERIAL_HAVE_POLL_WAIT) || \ - (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)) +#if defined(SERIAL_HAVE_POLL_WAIT) wake_up_interruptible(&tty->poll_wait); #endif return; @@ -4479,8 +4260,7 @@ return; wake_up_interruptible(&tty->write_wait); -#if defined(SERIAL_HAVE_POLL_WAIT) || \ - (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)) +#if defined(SERIAL_HAVE_POLL_WAIT) wake_up_interruptible(&tty->poll_wait); #endif if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && @@ -4721,8 +4501,6 @@ INIT_WORK(&card->tty_work, tty_poll_work, (void*)card); return 0; } - -#endif MODULE_LICENSE("GPL"); diff -Nru a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c --- a/drivers/net/wan/sdla_fr.c Tue Feb 25 11:05:23 2003 +++ b/drivers/net/wan/sdla_fr.c Thu Mar 6 09:25:30 2003 @@ -229,11 +229,7 @@ int inarp_interval; /* Time between InArp Requests */ unsigned long inarp_tick; /* InArp jiffies tick counter */ long interface_down; /* Bring interface down on disconnect */ - #if defined(LINUX_2_1) || defined(LINUX_2_4) struct net_device_stats ifstats; /* interface statistics */ - #else - struct enet_statistics ifstats; - #endif if_send_stat_t drvstats_if_send; rx_intr_stat_t drvstats_rx_intr; pipe_mgmt_stat_t drvstats_gen; @@ -242,14 +238,11 @@ unsigned short transmit_length; struct sk_buff *delay_skb; - - #if defined(LINUX_2_1) || defined(LINUX_2_4) bh_data_t *bh_head; /* Circular buffer for chdlc_bh */ unsigned long tq_working; volatile int bh_write; volatile int bh_read; atomic_t bh_buff_used; - #endif /* Polling task queue. Each interface * has its own task queue, which is used @@ -343,26 +336,14 @@ static int if_open(netdevice_t *dev); static int if_close(netdevice_t *dev); - -#ifdef LINUX_2_4 static void if_tx_timeout (netdevice_t *dev); -#endif -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr (struct sk_buff *skb); -#else -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb); -#endif static int if_send(struct sk_buff *skb, netdevice_t *dev); static int chk_bcast_mcast_addr(sdla_t *card, netdevice_t* dev, struct sk_buff *skb); -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats *if_stats(netdevice_t *dev); -#else -static struct enet_statistics* if_stats (netdevice_t* dev); -#endif /* Interrupt handlers */ static void fr_isr(sdla_t *card); @@ -417,13 +398,11 @@ netdevice_t * move_dev_to_next (sdla_t *, netdevice_t *); static int check_tx_status(sdla_t *, netdevice_t *); -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Frame Relay Socket API */ static void trigger_fr_bh (fr_channel_t *); static void fr_bh (netdevice_t *); static int fr_bh_cleanup (netdevice_t *); static int bh_enqueue (netdevice_t *, struct sk_buff *); -#endif static void trigger_fr_poll (netdevice_t *); static void fr_poll (netdevice_t *); @@ -886,26 +865,14 @@ chan->common.usedby = BRIDGE; -#if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n", card->devname); -#else - printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n", - card->devname); - err = -EPROTONOSUPPORT; -#endif }else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){ chan->common.usedby = BRIDGE_NODE; -#if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n", card->devname); -#else - printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n", - card->devname); - err = -EPROTONOSUPPORT; -#endif } if (!err){ @@ -922,18 +889,9 @@ } else if(strcmp(conf->usedby, "API") == 0){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->common.usedby = API; printk(KERN_INFO "%s: Running in API mode.\n", wandev->name); -#else - printk(KERN_INFO "%s: The API Mode is not supported for" - "kernels lower than 2.2.X !\n", - wandev->name); - printk(KERN_INFO "%s: Please upgrade to a 2.2.X kernel for the API support\n", - wandev->name); - err = -EINVAL; -#endif } if (err) { @@ -980,16 +938,9 @@ chan->mc = conf->mc; if (conf->inarp == WANOPT_YES){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname); chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE; chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10; -#else - printk(KERN_INFO "%s: Warning, Inverse ARP Support not available for 2.0.X kernels!\n", - card->devname); - chan->inarp = INARP_NONE; - chan->inarp_interval = 10; -#endif }else{ printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname); chan->inarp = INARP_NONE; @@ -1023,17 +974,7 @@ chan->transmit_length = 0; /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,chan->name); -#else - dev->name = (char *)kmalloc(strlen(chan->name) + 2, GFP_KERNEL); - if(dev->name == NULL) - { - kfree(chan); - return -ENOMEM; - } - sprintf(dev->name, "%s", chan->name); -#endif dev->init = &if_init; dev->priv = chan; @@ -1042,9 +983,6 @@ * We need a poll routine for each network * interface. */ -#ifndef LINUX_2_4 - chan->fr_poll_task.next = NULL; -#endif chan->fr_poll_task.sync = 0; chan->fr_poll_task.routine = (void *)(void *)fr_poll; chan->fr_poll_task.data = dev; @@ -1138,8 +1076,6 @@ int err, len; fr_cmd_t cmd; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd))) return -EFAULT; @@ -1169,44 +1105,6 @@ if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len)) return -EFAULT; return 0; - -#else - if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(fr_cmd_t))) - return -EFAULT; - - memcpy_fromfs((void*)&cmd, u_cmd, sizeof(cmd)); - - if (cmd.length) { - - if (!u_data || verify_area(VERIFY_READ, u_data, cmd.length)) - return -EFAULT; - } - - /* execute command */ - do - { - memcpy(&mbox->cmd, &cmd, sizeof(cmd)); - - if (cmd.length) - memcpy_fromfs((void*)&mbox->data, u_data, cmd.length); - - if (sdla_exec(mbox)) - err = mbox->cmd.result; - - else return -EIO; - } while (err && retry-- && fr_event(card, err, mbox)); - - /* return result */ - memcpy_tofs(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t)); - len = mbox->cmd.length; - - if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len)) - memcpy_tofs(u_data, (void*)&mbox->data, len); - - return 0; - -#endif - } /****** Network Device Interface ********************************************/ @@ -1223,9 +1121,6 @@ fr_channel_t* chan = dev->priv; sdla_t* card = chan->card; wan_device_t* wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* Initialize device driver entry points */ dev->open = &if_open; @@ -1234,15 +1129,11 @@ dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif if (chan->common.usedby == WANPIPE || chan->common.usedby == API){ -#ifdef LINUX_2_0 - dev->family = AF_INET; -#endif + /* Initialize media-specific parameters */ if (chan->true_if_encoding){ dev->type = ARPHRD_DLCI; /* This breaks tcpdump */ @@ -1274,11 +1165,6 @@ /* Set transmit buffer queue length */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ -#if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); -#endif }else{ /* Setup the interface for Bridging */ @@ -1315,16 +1201,12 @@ int err = 0; struct timeval tv; - if (is_dev_running(dev)) + if (netif_running(dev)) return -EBUSY; -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Initialize the task queue */ chan->tq_working=0; -#ifndef LINUX_2_4 - chan->common.wanpipe_task.next = NULL; -#endif chan->common.wanpipe_task.sync = 0; chan->common.wanpipe_task.routine = (void *)(void *)fr_bh; chan->common.wanpipe_task.data = dev; @@ -1333,15 +1215,8 @@ chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC); memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF)); atomic_set(&chan->bh_buff_used, 0); -#endif -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif wanpipe_open(card); do_gettimeofday( &tv ); @@ -1370,10 +1245,7 @@ chan->inarp = INARP_REQUEST; } - stop_net_queue(dev); -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); wanpipe_close(card); return 0; @@ -1385,18 +1257,10 @@ * Return: 1 physical address resolved. * 0 physical address not resolved */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr (struct sk_buff* skb) { -#else -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb) -{ -#endif -#if defined(LINUX_2_1) || defined(LINUX_2_4) netdevice_t *dev = skb->dev; -#endif fr_channel_t* chan = dev->priv; sdla_t* card = chan->card; @@ -1405,7 +1269,6 @@ return 1; } -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -1429,7 +1292,7 @@ netif_wake_queue (dev); } -#endif + /*============================================================================ * Send a packet on a network interface. @@ -1448,7 +1311,7 @@ * 1. This routine is called either by the protocol stack or by the "net * bottom half" (with interrupts enabled). * - * 2. Using the start_net_queue() and stop_net_queue() MACROS + * 2. Using netif_start_queue() and netif_stop_queue() * will inhibit further transmit requests from the protocol stack * and can be used for flow control with protocol layer. */ @@ -1466,9 +1329,7 @@ chan->drvstats_if_send.if_send_entry++; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif if (skb == NULL) { /* if we get here, some higher layer thinks we've missed an @@ -1478,7 +1339,7 @@ card->devname, dev->name); chan->drvstats_if_send.if_send_skb_null ++; - wake_net_dev(dev); + netif_wake_queue(dev); return 0; } @@ -1488,8 +1349,8 @@ printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n", card->devname); - wan_dev_kfree_skb(skb,FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } @@ -1500,37 +1361,13 @@ */ set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); if(chan->transmit_length) { - stop_net_queue(dev); + netif_stop_queue(dev); chan->tick_counter = jiffies; clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); return 1; } clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); -#ifndef LINUX_2_4 - if (dev->tbusy) { - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - - chan->drvstats_if_send.if_send_tbusy++; - ++chan->ifstats.collisions; - - if ((jiffies - chan->tick_counter) < (5 * HZ)) { - return 1; - } - - printk(KERN_INFO "%s: Transmit timed out on %s\n", - card->devname, chan->name); - chan->drvstats_if_send.if_send_tbusy_timeout ++; - dev->tbusy = 0; - } -#endif - - /* Move the if_header() code to here. By inserting frame * relay header in if_header() we would break the * tcpdump and other packet sniffers */ @@ -1539,8 +1376,8 @@ ++chan->ifstats.tx_dropped; ++card->wandev.stats.tx_dropped; - wan_dev_kfree_skb(skb,FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } @@ -1557,7 +1394,7 @@ if_send_PIPE_request ++; } } - start_net_queue(dev); + netif_start_queue(dev); return 0; } @@ -1569,8 +1406,8 @@ if(chk_bcast_mcast_addr(card, dev, skb)){ ++chan->ifstats.tx_dropped; ++card->wandev.stats.tx_dropped; - wan_dev_kfree_skb(skb, FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } } @@ -1691,26 +1528,22 @@ ++chan->ifstats.tx_packets; ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += skb->len; card->wandev.stats.tx_bytes += skb->len; -#endif -#ifdef LINUX_2_4 dev->trans_start = jiffies; -#endif } } } if_send_start_and_exit: - start_net_queue(dev); + netif_start_queue(dev); /* If we queued the packet for transmission, we must not * deallocate it. The packet is unlinked from the IP stack * not copied. Therefore, we must keep the original packet */ if (!test_bit(1,&delay_tx_queued)) { - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ adptr_flags->imask |= FR_INTR_TXRDY; card->u.f.tx_interrupts_pending ++; @@ -1786,16 +1619,13 @@ { u32 src_ip_addr; u32 broadcast_ip_addr = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev; -#endif fr_channel_t* chan = dev->priv; /* read the IP source address from the outgoing packet */ src_ip_addr = *(u32 *)(skb->data + 14); /* read the IP broadcast address for the device */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) in_dev = dev->ip_ptr; if(in_dev != NULL) { struct in_ifaddr *ifa= in_dev->ifa_list; @@ -1804,9 +1634,6 @@ else return 0; } -#else - broadcast_ip_addr = dev->pa_brdaddr; -#endif /* check if the IP Source Address is a Broadcast address */ if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { @@ -1999,11 +1826,7 @@ * Get ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats *if_stats(netdevice_t *dev) -#else -static struct enet_statistics* if_stats (netdevice_t* dev) -#endif { fr_channel_t* chan = dev->priv; @@ -2193,7 +2016,7 @@ skb = dev_alloc_skb(len); - if (!is_dev_running(dev) || (skb == NULL)){ + if (!netif_running(dev) || (skb == NULL)){ ++chan->ifstats.rx_dropped; @@ -2206,11 +2029,11 @@ chan->drvstats_rx_intr.rx_intr_no_socket ++; } - if (!is_dev_running(dev)){ + if (!netif_running(dev)){ chan->drvstats_rx_intr. rx_intr_dev_not_started ++; if (skb){ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } } goto rx_done; @@ -2252,7 +2075,6 @@ } } -#if defined(LINUX_2_1) || defined(LINUX_2_4) }else if (chan->common.usedby == API) { /* We are in API mode. @@ -2281,7 +2103,6 @@ bh_enqueue(dev, skb); trigger_fr_bh(chan); - #endif }else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){ @@ -2289,7 +2110,7 @@ //if (chan->enable_IPX) { // fr_send(card, dlci, 0, skb->len,skb->data); //} - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } else if (is_arp(skb->data)) { @@ -2304,7 +2125,7 @@ card->devname); } } - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } else if (skb->data[0] != 0x03) { @@ -2312,7 +2133,7 @@ printk(KERN_INFO "%s: Non IETF packet discarded.\n", card->devname); } - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } else { @@ -2341,7 +2162,7 @@ if (!wanrouter_type_trans(skb, dev)) { /* can't decapsulate packet */ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack; ++chan->ifstats.rx_errors; @@ -2359,10 +2180,8 @@ ++chan->ifstats.rx_packets; ++card->wandev.stats.rx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.rx_bytes += len_incl_hdr; card->wandev.stats.rx_bytes += len_incl_hdr; -#endif } rx_done: @@ -2454,36 +2273,28 @@ ++chan->ifstats.tx_packets; ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += chan->transmit_length; card->wandev.stats.tx_bytes += chan->transmit_length; -#endif /* We must free an sk buffer, which we used * for delayed transmission; Otherwise, the sock * will run out of memory */ - wan_dev_kfree_skb(chan->delay_skb, FREE_WRITE); + dev_kfree_skb_any(chan->delay_skb); chan->delay_skb = NULL; chan->transmit_length = 0; -#ifdef LINUX_2_4 dev->trans_start = jiffies; -#endif -#ifdef LINUX_2_0 - wake_net_dev(dev); -#else - if (is_queue_stopped(dev)){ + if (netif_queue_stopped(dev)){ /* If using API, than wakeup socket BH handler */ if (chan->common.usedby == API){ - start_net_queue(dev); + netif_start_queue(dev); wakeup_sk_bh(dev); }else{ - wake_net_dev(dev); + netif_wake_queue(dev); } } -#endif } end_of_tx_intr: @@ -2778,8 +2589,6 @@ fr_channel_t *chan = dev->priv; sdla_t *card = chan->card; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - struct ifreq if_info; struct sockaddr_in *if_data; mm_segment_t fs = get_fs(); @@ -2851,66 +2660,6 @@ } /* Case Statement */ -#else - /* Dynamic Route adding/removing */ - struct rtentry route; - int err = 0; - unsigned long fs = get_fs(); - - memset(&route, 0, sizeof(route)); - route.rt_dev = dev->name; - route.rt_flags = 0; - - ((struct sockaddr_in *) &(route.rt_dst)) -> - sin_addr.s_addr=dev->pa_dstaddr; - ((struct sockaddr_in *) &(route.rt_dst)) -> - sin_family = AF_INET; - ((struct sockaddr_in *) &(route.rt_genmask)) -> - sin_addr.s_addr = 0xFFFFFFFF; - ((struct sockaddr_in *) &(route.rt_genmask)) -> - sin_family = AF_INET; - switch(chan->route_flag) { - - case ADD_ROUTE: - - set_fs(get_ds()); /* get user space block */ - err = ip_rt_new(&route); - set_fs(fs); /* restore old block */ - - if (err) { - printk(KERN_INFO "%s: Adding of route failed. Error: %d\n", - card->devname,err); - printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n", - chan->name, NIPQUAD(dev->pa_dstaddr) ); - } - else { - chan->route_flag = ROUTE_ADDED; - } - break; - - case REMOVE_ROUTE: - - set_fs(get_ds()); /* get user space block */ - err = ip_rt_kill(&route); - set_fs(fs); /* restore old block */ - - if (err) { - printk(KERN_INFO "%s: Deleting of route failed. Error: %d\n", - card->devname,err); - printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n", - dev->name,NIPQUAD(dev->pa_dstaddr) ); - } else { - - printk(KERN_INFO "%s: Removed route.\n", - ((fr_channel_t*)dev->priv)->name); - chan->route_flag = NO_ROUTE; - - } - break; - } - -#endif - } @@ -3468,7 +3217,7 @@ "%s: DLCI %u is inactive!\n", card->devname, dlci); - if (dev && is_dev_running(dev)) + if (dev && netif_running(dev)) set_chan_state(dev, WAN_DISCONNECTED); } @@ -3478,7 +3227,7 @@ "%s: DLCI %u has been deleted!\n", card->devname, dlci); - if (dev && is_dev_running(dev)){ + if (dev && netif_running(dev)){ fr_channel_t *chan = dev->priv; @@ -3743,9 +3492,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK){ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } return(udp_pkt_stored); @@ -4173,8 +3922,6 @@ { int err=0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - arphdr_1490_t *ArpPacket; arphdr_fr_t *arphdr; fr_channel_t *chan = dev->priv; @@ -4225,47 +3972,6 @@ return 1; } -#else - arphdr_1490_t *ArpPacket; - arphdr_fr_t *arphdr; - fr_channel_t *chan = dev->priv; - - ArpPacket = kmalloc(sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), GFP_ATOMIC); - /* SNAP Header indicating ARP */ - ArpPacket->control = 0x03; - ArpPacket->pad = 0x00; - ArpPacket->NLPID = 0x80; - ArpPacket->OUI[0] = 0; - ArpPacket->OUI[1] = 0; - ArpPacket->OUI[2] = 0; - ArpPacket->PID = 0x0608; - - arphdr = (arphdr_fr_t *)(ArpPacket + 1); // Go to ARP Packet - /* InARP request */ - arphdr->ar_hrd = 0x0F00; /* Frame Relay HW type */ - arphdr->ar_pro = 0x0008; /* IP Protocol */ - arphdr->ar_hln = 2; /* HW addr length */ - arphdr->ar_pln = 4; /* IP addr length */ - arphdr->ar_op = htons(0x08); /* InARP Request */ - arphdr->ar_sha = 0; /* src HW DLCI - Doesn't matter */ - arphdr->ar_sip = dev->pa_addr; /* Local Address */ - arphdr->ar_tha = 0; /* dst HW DLCI - Doesn't matter */ - arphdr->ar_tip = 0; /* Remote Address -- what we want */ - - printk(KERN_INFO "%s: Sending InARP request on DLCI %d.\n", card->devname, chan->dlci); - err = fr_send(card, chan->dlci, 0, - sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), - (void *)ArpPacket); - - if (!err){ - printk(KERN_INFO "\n%s: Sending InARP request on DLCI %d.\n", - card->devname, chan->dlci); - clear_bit(ARP_CRIT,&card->wandev.critical); - } - - kfree(ArpPacket); -#endif - return 0; } @@ -4293,15 +3999,10 @@ { -#if defined(LINUX_2_1) || defined(LINUX_2_4) arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */ fr_rx_buf_ctl_t* frbuf = card->rxmb; struct in_device *in_dev; fr_channel_t *chan = dev->priv; -#else - arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */ - fr_rx_buf_ctl_t* frbuf = card->rxmb; -#endif /* Before we transmit ARP packet, we must check * to see that we are not currently transmitting a @@ -4316,8 +4017,6 @@ return 0; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) - in_dev = dev->ip_ptr; /* Check that IP addresses exist for our network address */ @@ -4434,87 +4133,6 @@ } return 0; -#else - - switch (ntohs(arphdr->ar_op)) { - - case 0x08: // Inverse ARP request -- Send Reply, add route. - - /* Check for valid Address */ - printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Req\n", - ((fr_channel_t *)dev->priv)->name, NIPQUAD(arphdr->ar_sip)); - - - if (dev->pa_mask != 0xFFFFFFFF){ - - if ((dev->pa_mask & arphdr->ar_sip) != (dev->pa_mask & dev->pa_addr)) { - printk(KERN_INFO "%s: Invalid PtP address. InARP ignored.\n", - card->devname); - return -1; - } - } - - if (dev->pa_addr == arphdr->ar_sip) { - printk(KERN_INFO "%s: Local addr = PtP addr. InARP ignored.\n", - card->devname); - return -1; - } - - arphdr->ar_op = htons(0x09); /* InARP Reply */ - - /* Set addresses */ - arphdr->ar_tip = arphdr->ar_sip; - arphdr->ar_sip = dev->pa_addr; - - fr_send(card, frbuf->dlci, 0, frbuf->length, (void *)ArpPacket); - - clear_bit(ARP_CRIT,&card->wandev.critical); - - /* Modify Point-to-Point Address */ - dev->pa_dstaddr = arphdr->ar_tip; - - /* Add Route Flag */ - /* The route will be added in the polling routine so - that it is not interrupt context. */ - ((fr_channel_t *) dev->priv)->route_flag = ADD_ROUTE; - trigger_fr_poll(dev); - - break; - case 0x09: // Inverse ARP reply - - /* Check for valid Address */ - printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Reply\n", - ((fr_channel_t *)dev->priv)->name, NIPQUAD(arphdr->ar_sip)); - - if ((dev->pa_mask & arphdr->ar_sip) != (dev->pa_mask & dev->pa_addr)) { - printk(KERN_INFO "%s: Invalid PtP address. InARP ignored.\n", - card->devname); - return -1; - } - - if (dev->pa_addr == arphdr->ar_sip) { - printk(KERN_INFO "%s: Local addr = PtP addr. InARP ignored.\n", - card->devname); - return -1; - } - - /* Modify Point-to-Point Address */ - dev->pa_dstaddr = arphdr->ar_sip; - /* Add Route Flag */ - /* The route will be added in the polling routine so - that it is not interrupt context. */ - - ((fr_channel_t *) dev->priv)->route_flag = ADD_ROUTE; - ((fr_channel_t *) dev->priv)->inarp = INARP_CONFIGURED; - trigger_fr_poll(dev); - - break; - default: // ARP's and RARP's -- Shouldn't happen. - } - - return 0; - -#endif } @@ -4706,15 +4324,9 @@ { if (card->hw.type != SDLA_S514){ -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock_irqsave(&card->wandev.lock, *smp_flags); -#else - disable_irq(card->hw.irq); -#endif }else{ -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock(&card->u.f.if_send_lock); -#endif } return; } @@ -4724,23 +4336,15 @@ { if (card->hw.type != SDLA_S514){ -#if defined(__SMP__) || defined(LINUX_2_4) spin_unlock_irqrestore (&card->wandev.lock, *smp_flags); -#else - enable_irq(card->hw.irq); -#endif }else{ -#if defined(__SMP__) || defined(LINUX_2_4) spin_unlock(&card->u.f.if_send_lock); -#endif } return; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) - /*---------------------------------------------------------------------- RECEIVE INTERRUPT: BOTTOM HALF HANDLERS ----------------------------------------------------------------------*/ @@ -4770,7 +4374,7 @@ if (atomic_read(&chan->bh_buff_used) == MAX_BH_BUFF){ ++card->wandev.stats.rx_dropped; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return 1; } @@ -4859,7 +4463,7 @@ if (chan->common.sk == NULL || chan->common.func == NULL){ ++card->wandev.stats.rx_dropped; ++chan->ifstats.rx_dropped; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); fr_bh_cleanup(dev); continue; } @@ -4896,7 +4500,6 @@ atomic_dec(&chan->bh_buff_used); return 0; } -#endif /*---------------------------------------------------------------------- @@ -4919,11 +4522,7 @@ static void trigger_fr_poll (netdevice_t *dev) { fr_channel_t* chan = dev->priv; -#ifdef LINUX_2_4 schedule_task(&chan->fr_poll_task); -#else - queue_task(&chan->fr_poll_task, &tq_scheduler); -#endif return; } @@ -5047,7 +4646,7 @@ } } - if (is_queue_stopped(dev) || (card->u.f.tx_interrupts_pending)) + if (netif_queue_stopped(dev) || (card->u.f.tx_interrupts_pending)) return 1; return 0; @@ -5295,7 +4894,6 @@ * an Ethernet header */ if (op_mode == BRIDGE || op_mode == BRIDGE_NODE){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Encapsulate the packet as a bridged Ethernet frame. */ #ifdef DEBUG @@ -5316,12 +4914,6 @@ skb->protocol = ETH_P_802_3; return 8; -#else - - /* BRIDGING is not supported in 2.0.X */ - return -EINVAL; - -#endif } return 0; diff -Nru a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c --- a/drivers/net/wan/sdla_ft1.c Mon Aug 26 11:35:50 2002 +++ b/drivers/net/wan/sdla_ft1.c Sun Feb 16 16:22:42 2003 @@ -252,8 +252,6 @@ CHDLC_MAILBOX_STRUCT* mbox = card->mbox; int len; - -#if defined(LINUX_2_1) || defined(LINUX_2_4) if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){ return -EFAULT; } @@ -281,36 +279,6 @@ if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){ return -EFAULT; } - -#else - - if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(ft1_exec_cmd_t))){ - return -EFAULT; - } - - memcpy_fromfs((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t)); - - len = mbox->buffer_length; - - if (len) { - if (!u_data || verify_area(VERIFY_READ, u_data, len)) - return -EFAULT; - memcpy_fromfs((void*)&mbox->data, u_data, len); - } - - /* execute command */ - if (!sdla_exec(mbox)) - return -EIO; - - /* return result */ - memcpy_tofs(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t)); - len = mbox->buffer_length; - - if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len)){ - memcpy_tofs(u_data, (void*)&mbox->data, len); - } - -#endif return 0; diff -Nru a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c --- a/drivers/net/wan/sdla_ppp.c Tue Feb 25 11:05:23 2003 +++ b/drivers/net/wan/sdla_ppp.c Thu Mar 6 09:25:30 2003 @@ -104,15 +104,9 @@ #include /* sockaddr_in */ -/* ---- 2.4.X KERNEL SUPPORT -----------------------*/ -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include - #include - #include -#else - #include - #include /* Adding new route entries : 2.0.X kernels */ -#endif +#include +#include +#include #include #include /* PPP firmware API definitions */ @@ -163,10 +157,6 @@ #define NUM_AUTH_REQ_WITHOUT_REPLY 10 #define END_OFFSET 0x1F0 -#if LINUX_VERSION_CODE < 0x020125 -#define test_and_set_bit set_bit -#define net_ratelimit() 1 -#endif /******Data Structures*****************************************************/ @@ -255,18 +245,10 @@ static int if_header(struct sk_buff *skb, netdevice_t *dev, unsigned short type, void *daddr, void *saddr, unsigned len); -#ifdef LINUX_2_4 static void if_tx_timeout (netdevice_t *dev); -#endif -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr(struct sk_buff *skb); static struct net_device_stats *if_stats(netdevice_t *dev); -#else -static struct enet_statistics *if_stats(netdevice_t *dev); -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb); -#endif static int if_send(struct sk_buff *skb, netdevice_t *dev); @@ -615,17 +597,7 @@ } /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,card->u.p.if_name); -#else - dev->name = (char *)kmalloc(strlen(card->u.p.if_name) + 2, GFP_KERNEL); - if(dev->name == NULL) - { - kfree(ppp_priv_area); - return -ENOMEM; - } - sprintf(dev->name, "%s", card->u.p.if_name); -#endif dev->init = &if_init; dev->priv = ppp_priv_area; @@ -673,7 +645,6 @@ ppp_mbox_t *mbox = card->mbox; int len; -#if defined(LINUX_2_1) || defined(LINUX_2_4) if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t))) return -EFAULT; @@ -698,35 +669,6 @@ if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)) return -EFAULT; -#else - - if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(ppp_cmd_t))) - return -EFAULT; - - memcpy_fromfs((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t)); - - len = mbox->cmd.length; - - if (len) { - - if (!u_data || verify_area(VERIFY_READ, u_data, len)) - return -EFAULT; - } - - /* execute command */ - if (!sdla_exec(mbox)) - return -EIO; - - /* return result */ - memcpy_tofs(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t)); - len = mbox->cmd.length; - - if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len)) - memcpy_tofs(u_data, (void*)&mbox->data, len); - - -#endif - return 0; } @@ -744,9 +686,6 @@ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; wan_device_t *wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* Initialize device driver entry points */ dev->open = &if_open; @@ -755,10 +694,8 @@ dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif /* Initialize media-specific parameters */ dev->type = ARPHRD_PPP; /* ARP h/w type */ @@ -770,9 +707,6 @@ dev->flags |= IFF_MULTICAST; } -#ifdef LINUX_2_0 - dev->family = AF_INET; -#endif dev->mtu = wandev->mtu; dev->hard_header_len = PPP_HDR_LEN; /* media header length */ @@ -786,12 +720,6 @@ /* Set transmit buffer queue length */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ - #if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); - #endif - return 0; } @@ -809,18 +737,12 @@ struct timeval tv; //unsigned long smp_flags; - if (is_dev_running(dev)) + if (netif_running(dev)) return -EBUSY; wanpipe_open(card); -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif do_gettimeofday( &tv ); ppp_priv_area->router_start_time = tv.tv_sec; @@ -852,10 +774,7 @@ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; - stop_net_queue(dev); -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); wanpipe_close(card); del_timer (&ppp_priv_area->poll_delay_timer); @@ -894,7 +813,6 @@ * Return: 1 physical address resolved. * 0 physical address not resolved */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr (struct sk_buff *skb) { netdevice_t *dev = skb->dev; @@ -906,16 +824,6 @@ return 1; } -#else -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb) -{ - return 1; - -} -#endif - -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -937,7 +845,6 @@ ++chan->if_send_stat.if_send_tbusy_timeout; netif_wake_queue (dev); } -#endif @@ -970,9 +877,7 @@ ++ppp_priv_area->if_send_stat.if_send_entry; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif if (skb == NULL) { @@ -984,36 +889,10 @@ ++ppp_priv_area->if_send_stat.if_send_skb_null; - wake_net_dev(dev); + netif_wake_queue(dev); return 0; } -#ifndef LINUX_2_4 - if (dev->tbusy) { - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - - ++ppp_priv_area->if_send_stat.if_send_tbusy; - ++card->wandev.stats.collisions; - - if ((jiffies - ppp_priv_area->tick_counter) < (5*HZ)) { - return 1; - } - - printk (KERN_INFO "%s: Transmit times out on %s\n",card->devname,dev->name); - - ++ppp_priv_area->if_send_stat.if_send_tbusy_timeout; - ++card->wandev.stats.collisions; - - /* unbusy the card (because only one interface per card)*/ - dev->tbusy = 0; - } -#endif - sendpacket = skb->data; udp_type = udp_pkt_type( skb, card ); @@ -1025,7 +904,7 @@ flags->imask |= PPP_INTR_TIMER; } ++ppp_priv_area->if_send_stat.if_send_PIPE_request; - start_net_queue(dev); + netif_start_queue(dev); return 0; } @@ -1034,8 +913,8 @@ */ if(chk_bcast_mcast_addr(card, dev, skb)){ ++card->wandev.stats.tx_dropped; - wan_dev_kfree_skb(skb,FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } @@ -1051,7 +930,7 @@ ++card->wandev.stats.tx_dropped; ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_exit_crit; } @@ -1059,12 +938,12 @@ ++ppp_priv_area->if_send_stat.if_send_wan_disconnected; ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); } else if (!skb->protocol) { ++ppp_priv_area->if_send_stat.if_send_protocol_error; ++card->wandev.stats.tx_errors; - start_net_queue(dev); + netif_start_queue(dev); } else { @@ -1075,32 +954,28 @@ ppp_priv_area->network_number, 0); } else { ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_exit_crit; } } if (ppp_send(card, skb->data, skb->len, skb->protocol)) { - stop_net_queue(dev); + netif_stop_queue(dev); ++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full; ++ppp_priv_area->if_send_stat.if_send_tx_int_enabled; } else { ++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr; ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += skb->len; -#endif - start_net_queue(dev); -#ifdef LINUX_2_4 + netif_start_queue(dev); dev->trans_start = jiffies; -#endif } } if_send_exit_crit: - if (!(err=is_queue_stopped(dev))){ - wan_dev_kfree_skb(skb, FREE_WRITE); + if (!(err=netif_queue_stopped(dev))){ + dev_kfree_skb_any(skb); }else{ ppp_priv_area->tick_counter = jiffies; flags->imask |= PPP_INTR_TXRDY; /* unmask Tx interrupts */ @@ -1134,13 +1009,8 @@ udp_pkt_stored = 1; }else{ if (skb->len > MAX_LGTH_UDP_MGNT_PKT){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n", card->devname, skb->len); -#else - printk(KERN_INFO "%s: PIPEMON UDP request too long : %li\n", - card->devname, skb->len); -#endif }else{ printk(KERN_INFO "%s: PIPEMON UPD request already pending\n", card->devname); @@ -1149,9 +1019,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK){ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } return(udp_pkt_stored); @@ -1319,11 +1189,7 @@ * Get ethernet-style interface statistics. * Return a pointer to struct net_device_stats. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats *if_stats(netdevice_t *dev) -#else -static struct enet_statistics *if_stats(netdevice_t *dev) -#endif { ppp_private_area_t *ppp_priv_area = dev->priv; @@ -1743,7 +1609,7 @@ case PPP_INTR_TXRDY: /* transmit interrupt 0x02 (bit 1)*/ ++card->statistics.isr_tx; flags->imask &= ~PPP_INTR_TXRDY; - wake_net_dev(dev); + netif_wake_queue(dev); break; case PPP_INTR_CMD: /* interface command completed */ @@ -1821,7 +1687,7 @@ return; } - if (dev && is_dev_running(dev) && dev->priv){ + if (dev && netif_running(dev) && dev->priv){ len = rxbuf->length; ppp_priv_area = dev->priv; @@ -1881,7 +1747,7 @@ if (!test_bit(SEND_CRIT, &card->wandev.critical)){ ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX)); } - wan_dev_kfree_skb(skb,FREE_READ); + dev_kfree_skb_any(skb); } else { ++card->wandev.stats.rx_dropped; @@ -1892,9 +1758,7 @@ skb->mac.raw = skb->data; ++card->wandev.stats.rx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.rx_bytes += skb->len; -#endif ++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack; netif_rx(skb); dev->last_rx = jiffies; @@ -2244,8 +2108,6 @@ netdevice_t *dev = card->wandev.dev; ppp_private_area_t *ppp_priv_area = dev->priv; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && (flags->ip_state == 0x09)){ @@ -2276,29 +2138,6 @@ } } } -#else - - if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && - (flags->ip_state == 0x09)){ - - if (ppp_priv_area->ip_local == 0) - return; - - printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname); - if (read_info( card )) { - printk(KERN_INFO - "%s: An error occurred in IP assignment.\n", - card->devname); - } else { - printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n", - card->devname, NIPQUAD(dev->pa_addr)); - printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%U\n", - card->devname, NIPQUAD(dev->pa_dstaddr)); - } - } - -#endif - } /*============================================================================ @@ -2328,9 +2167,7 @@ static int config508(netdevice_t *dev, sdla_t *card) { ppp508_conf_t cfg; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev = dev->ip_ptr; -#endif ppp_private_area_t *ppp_priv_area = dev->priv; /* Prepare PPP configuration structure */ @@ -2393,14 +2230,8 @@ printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname); cfg.ip_options = L_AND_R_IP_NO_ASSIG | ENABLE_IP; -#if defined(LINUX_2_1) || defined(LINUX_2_4) cfg.ip_local = in_dev->ifa_list->ifa_local; cfg.ip_remote = in_dev->ifa_list->ifa_address; -#else - cfg.ip_local = dev->pa_addr; - cfg.ip_remote = dev->pa_dstaddr; -#endif - /* Debugging code used to check that IP addresses * obtained from the kernel are correct */ @@ -2414,14 +2245,8 @@ cfg.ip_options = L_IP_LOCAL_ASSIG | R_IP_LOCAL_ASSIG | ENABLE_IP; -#if defined(LINUX_2_1) || defined(LINUX_2_4) cfg.ip_local = in_dev->ifa_list->ifa_local; cfg.ip_remote = in_dev->ifa_list->ifa_address; -#else - cfg.ip_local = dev->pa_addr; - cfg.ip_remote = dev->pa_dstaddr; -#endif - /* Debugging code used to check that IP addresses * obtained from the kernel are correct */ NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n", @@ -2431,8 +2256,6 @@ case WANOPT_PPP_PEER: -#if defined(LINUX_2_1) || defined(LINUX_2_4) - printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname); cfg.ip_options = L_IP_REMOTE_ASSIG | R_IP_REMOTE_ASSIG | @@ -2441,16 +2264,6 @@ cfg.ip_remote = 0x00; break; -#else - - /* No PEER support for 2.0.X kernels, drop down to default - * condition */ - - printk(KERN_INFO "%s: ERROR, PEER mode is not supported in 2.0.X kernels\n", - card->devname); - -#endif - default: printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n", card->devname); @@ -3038,19 +2851,9 @@ ppp_private_area_t *ppp_priv_area = dev->priv; int err; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct ifreq if_info; struct sockaddr_in *if_data1, *if_data2; mm_segment_t fs; -#else -#ifdef _DYNAMIC_ROUTE_20X_SUPPORT_ - struct rtentry route; -#endif -#endif - - - -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Set Local and remote addresses */ memset(&if_info, 0, sizeof(if_info)); @@ -3074,39 +2877,6 @@ set_fs(fs); /* restore old block */ -#else - /* FIXME: Dynamic Routing in 2.0.X kernels is not - * supported. Sorry ! I'll come back to it when I get - * a chance. */ - - printk(KERN_INFO "%s: ERROR, Dynamic routing is not supported in 2.0.X kernels\n", - card->devname); - printk(KERN_INFO "%s: Please use the STATIC IP mode!\n", - card->devname); - - err = 0; - -#ifdef _DYNAMIC_ROUTE_20X_SUPPORT_ - dev->pa_dstaddr = ppp_priv_area->ip_remote; - dev->pa_addr = ppp_priv_area->ip_local; - - memset(&route, 0, sizeof(route)); - route.rt_dev = dev->name; - route.rt_flags = 0; - ((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr = - dev->pa_dstaddr; - ((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr = - 0xFFFFFFFF; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_family = - AF_INET; - - err = ip_rt_new(&route); - -#endif - -#endif - if (err) { printk (KERN_INFO "%s: Adding of route failed: %i\n", card->devname,err); @@ -3130,32 +2900,21 @@ long ip_addr; int err; -#if defined(LINUX_2_1) || defined(LINUX_2_4) mm_segment_t fs; struct ifreq if_info; struct sockaddr_in *if_data1; struct in_device *in_dev = dev->ip_ptr; struct in_ifaddr *ifa = in_dev->ifa_list; -#else - unsigned long fs = 0; - struct rtentry route; -#endif - -#if defined(LINUX_2_1) || defined(LINUX_2_4) ip_addr = ifa->ifa_local; /* Set Local and remote addresses */ memset(&if_info, 0, sizeof(if_info)); strcpy(if_info.ifr_name, dev->name); -#endif - fs = get_fs(); set_fs(get_ds()); /* get user space block */ - -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Change the local ip address of the interface to 0. * This will also delete the destination route. */ @@ -3163,26 +2922,6 @@ if_data1->sin_addr.s_addr = 0; if_data1->sin_family = AF_INET; err = devinet_ioctl( SIOCSIFADDR, &if_info ); -#else - - ip_addr = dev->pa_addr; - dev->pa_dstaddr = 0; - - memset(&route, 0, sizeof(route)); - route.rt_dev = dev->name; - route.rt_flags = 0; - ((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr = - dev->pa_dstaddr; - ((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr = - 0xFFFFFFFF; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_family = - AF_INET; - - - err = ip_rt_kill(&route); - -#endif set_fs(fs); /* restore old block */ @@ -3288,14 +3027,12 @@ { u32 src_ip_addr; u32 broadcast_ip_addr = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev; -#endif + /* read the IP source address from the outgoing packet */ src_ip_addr = *(u32 *)(skb->data + 12); /* read the IP broadcast address for the device */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) in_dev = dev->ip_ptr; if(in_dev != NULL) { struct in_ifaddr *ifa= in_dev->ifa_list; @@ -3304,9 +3041,6 @@ else return 0; } -#else - broadcast_ip_addr = dev->pa_brdaddr; -#endif /* check if the IP Source Address is a Broadcast address */ if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { @@ -3328,20 +3062,12 @@ void s508_lock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock_irqsave(&card->wandev.lock, *smp_flags); -#else - disable_irq(card->hw.irq); -#endif } void s508_unlock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -#else - enable_irq(card->hw.irq); -#endif } static int read_connection_info (sdla_t *card) diff -Nru a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c --- a/drivers/net/wan/sdla_x25.c Tue Feb 25 11:05:23 2003 +++ b/drivers/net/wan/sdla_x25.c Thu Mar 6 09:25:30 2003 @@ -95,12 +95,7 @@ #include #include /* Experimental delay */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include -#else - #include - #include -#endif +#include #include #include @@ -281,11 +276,7 @@ int ch_idx; unsigned char enable_IPX; unsigned long network_number; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct net_device_stats ifstats; /* interface statistics */ -#else - struct enet_statistics ifstats; -#endif unsigned short transmit_length; unsigned short tx_offset; char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)]; @@ -369,9 +360,7 @@ static int if_send (struct sk_buff* skb, netdevice_t* dev); static struct net_device_stats *if_stats (netdevice_t* dev); -#ifdef LINUX_2_4 static void if_tx_timeout (netdevice_t *dev); -#endif /*================================================= * Interrupt handlers @@ -792,9 +781,6 @@ init_global_statistics(card); -#ifndef LINUX_2_4 - card->u.x.x25_poll_task.next = NULL; -#endif card->u.x.x25_poll_task.sync=0; card->u.x.x25_poll_task.routine = (void*)(void*)wpx_poll; card->u.x.x25_poll_task.data = card; @@ -1011,18 +997,8 @@ chan->network_number = 0xDEADBEEF; /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,chan->name); -#else - dev->name = (char *)kmalloc(strlen(chan->name) + 2, GFP_KERNEL); - if(dev->name == NULL) - { - kfree(chan); - dev->priv = NULL; - return -ENOMEM; - } - sprintf(dev->name, "%s", chan->name); -#endif + dev->init = &if_init; init_x25_channel_struct(chan); @@ -1124,9 +1100,6 @@ x25_channel_t* chan = dev->priv; sdla_t* card = chan->card; wan_device_t* wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* Initialize device driver entry points */ dev->open = &if_open; @@ -1135,19 +1108,11 @@ dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; - -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif /* Initialize media-specific parameters */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) dev->type = ARPHRD_PPP; /* ARP h/w type */ -#else - dev->family = AF_INET; /* address family */ - dev->type = ARPHRD_PPP; /* no x25 type */ -#endif dev->flags |= IFF_POINTOPOINT; dev->flags |= IFF_NOARP; @@ -1174,11 +1139,6 @@ /* Set transmit buffer queue length */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ -#if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); -#endif /* FIXME Why are we doing this */ set_chan_state(dev, WAN_DISCONNECTED); return 0; @@ -1214,15 +1174,12 @@ struct timeval tv; unsigned long smp_flags; - if (is_dev_running(dev)) + if (netif_running(dev)) return -EBUSY; chan->tq_working = 0; /* Initialize the task queue */ -#ifndef LINUX_2_4 - chan->common.wanpipe_task.next = NULL; -#endif chan->common.wanpipe_task.sync = 0; chan->common.wanpipe_task.routine = (void *)(void *)x25api_bh; chan->common.wanpipe_task.data = dev; @@ -1276,13 +1233,8 @@ do_gettimeofday( &tv ); chan->router_start_time = tv.tv_sec; -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif + return 0; } @@ -1314,10 +1266,7 @@ sdla_t* card = chan->card; unsigned long smp_flags; - stop_net_queue(dev); -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); if ((chan->common.state == WAN_CONNECTED) || (chan->common.state == WAN_CONNECTING)){ @@ -1336,7 +1285,7 @@ for (i=0; i<(MAX_BH_BUFF+1); i++){ skb = ((bh_data_t *)&chan->bh_head[i])->skb; if (skb != NULL){ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } } kfree(chan->bh_head); @@ -1405,7 +1354,6 @@ } -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -1425,7 +1373,6 @@ card->devname, dev->name); netif_wake_queue (dev); } -#endif /*========================================================================= @@ -1457,33 +1404,11 @@ ++chan->if_send_stat.if_send_entry; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif /* No need to check frame length, since socket code * will perform the check for us */ -#ifndef LINUX_2_4 - if (dev->tbusy){ - netdevice_t *dev2; - - ++chan->if_send_stat.if_send_tbusy; - if ((jiffies - chan->tick_counter) < (5*HZ)){ - return 1; - } - printk(KERN_INFO "%s: Transmit time out %s!\n", - card->devname, dev->name); - - for( dev2 = card->wandev.dev; dev2; - dev2 = *((netdevice_t**)dev2->priv)){ - - dev2->tbusy = 0; - } - ++chan->if_send_stat.if_send_tbusy_timeout; - } -#endif - chan->tick_counter = jiffies; /* Critical region starts here */ @@ -1506,7 +1431,7 @@ chan->if_send_stat.if_send_PIPE_request++; } } - start_net_queue(dev); + netif_start_queue(dev); clear_bit(SEND_CRIT,(void*)&card->wandev.critical); S508_S514_unlock(card, &smp_flags); return 0; @@ -1518,7 +1443,7 @@ chan->transmit_length=0; atomic_set(&chan->common.driver_busy,0); }else{ - stop_net_queue(dev); + netif_stop_queue(dev); ++card->u.x.tx_interrupts_pending; status->imask |= INTR_ON_TX_FRAME; clear_bit(SEND_CRIT,(void*)&card->wandev.critical); @@ -1589,9 +1514,9 @@ if_send_crit_exit: - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); - start_net_queue(dev); + netif_start_queue(dev); clear_bit(SEND_CRIT,(void*)&card->wandev.critical); S508_S514_unlock(card, &smp_flags); return 0; @@ -1787,14 +1712,12 @@ ++chan->ifstats.rx_dropped; ++card->wandev.stats.rx_dropped; ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return; } ++chan->ifstats.rx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.rx_bytes += skb->len; -#endif chan->rx_skb = NULL; @@ -1814,7 +1737,7 @@ /* Decapsulate packet, if necessary */ if (!skb->protocol && !wanrouter_type_trans(skb, dev)){ /* can't decapsulate packet */ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); ++chan->ifstats.rx_errors; ++chan->ifstats.rx_dropped; ++card->wandev.stats.rx_dropped; @@ -1829,7 +1752,7 @@ if(chan_send(dev, skb->data, skb->len,0)){ chan->tx_skb = skb; }else{ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; } }else{ @@ -1839,9 +1762,7 @@ } }else{ skb->mac.raw = skb->data; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.rx_bytes += skb->len; -#endif ++chan->ifstats.rx_packets; ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack; netif_rx(skb); @@ -1898,7 +1819,7 @@ if (skb_tailroom(new_skb) < len){ /* No room for the packet. Call off the whole thing! */ - wan_dev_kfree_skb(new_skb, FREE_READ); + dev_kfree_skb_any(new_skb); if (chan->common.usedby == WANPIPE){ chan->rx_skb = NULL; if (qdm & 0x01){ @@ -1985,12 +1906,12 @@ chan->transmit_length = 0; atomic_set(&chan->common.driver_busy,0); chan->tx_offset=0; - if (is_queue_stopped(dev)){ + if (netif_queue_stopped(dev)){ if (chan->common.usedby == API){ - start_net_queue(dev); + netif_start_queue(dev); wakeup_sk_bh(dev); }else{ - wake_net_dev(dev); + netif_wake_queue(dev); } } dev = move_dev_to_next(card,dev); @@ -2092,12 +2013,12 @@ /* If we are in API mode, wakeup the * sock BH handler, not the NET_BH */ - if (is_queue_stopped(dev)){ + if (netif_queue_stopped(dev)){ if (chan->common.usedby == API){ - start_net_queue(dev); + netif_start_queue(dev); wakeup_sk_bh(dev); }else{ - wake_net_dev(dev); + netif_wake_queue(dev); } } return 0; @@ -2342,11 +2263,7 @@ static void trigger_x25_poll(sdla_t *card) { -#ifdef LINUX_2_4 schedule_task(&card->u.x.x25_poll_task); -#else - queue_task(&card->u.x.x25_poll_task, &tq_scheduler); -#endif } /*==================================================================== @@ -3658,8 +3575,8 @@ chan->transmit_length=0; atomic_set(&chan->common.driver_busy,0); chan->tx_offset=0; - if (is_queue_stopped(dev)){ - wake_net_dev(dev); + if (netif_queue_stopped(dev)){ + netif_wake_queue(dev); } } atomic_set(&chan->common.command,0); @@ -3766,9 +3683,7 @@ case 0x00: /* success */ chan->i_timeout_sofar = jiffies; -#ifdef LINUX_2_4 dev->trans_start=jiffies; -#endif if ((qdm & M_BIT) && !card->u.x.LAPB_hdlc){ if (!tx_intr){ @@ -3780,9 +3695,7 @@ chan->tx_offset += len; ++chan->ifstats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += len; -#endif if (chan->tx_offset < orig_len){ setup_for_delayed_transmit (dev, buff, data_len); @@ -3795,9 +3708,7 @@ * be X number of times larger than max data size. */ ++chan->ifstats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += len; -#endif ++chan->if_send_stat.if_send_bfr_passed_to_adptr; chan->tx_offset += len; @@ -3817,9 +3728,7 @@ } }else{ ++chan->ifstats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += len; -#endif ++chan->if_send_stat.if_send_bfr_passed_to_adptr; res=0; } @@ -4288,7 +4197,7 @@ if (chan->common.sk == NULL || chan->common.func == NULL){ printk(KERN_INFO "%s: BH: Socket disconnected, dropping\n", card->devname); - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); x25api_bh_cleanup(dev); ++chan->ifstats.rx_dropped; ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; @@ -4745,7 +4654,7 @@ if (card->func(skb,card->sk) < 0){ printk(KERN_INFO "%s: MAJOR ERROR: Failed to send up place call \n",card->devname); - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return 1; } @@ -4912,7 +4821,7 @@ if (chan->common.func(skb,dev,chan->common.sk) < 0){ if (bh_enqueue(dev,skb)){ printk(KERN_INFO "%s: Dropping OOB MSG\n",card->devname); - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } } @@ -4940,7 +4849,7 @@ if (skb_tailroom(new_skb) < len){ /* No room for the packet. Call off the whole thing! */ - wan_dev_kfree_skb(new_skb, FREE_READ); + dev_kfree_skb_any(new_skb); printk(KERN_INFO "%s: Listen: unexpectedly long packet sequence\n" ,card->devname); *skb = NULL; @@ -5448,9 +5357,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK){ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } return(udp_pkt_stored); diff -Nru a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c --- a/drivers/net/wan/sdladrv.c Wed May 22 11:16:37 2002 +++ b/drivers/net/wan/sdladrv.c Sun Feb 16 16:22:42 2003 @@ -108,16 +108,8 @@ #define _OUTB(port, byte) (outb((byte),(port))) #define SYSTEM_TICK jiffies +#include -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include -#else - #include /* BIOS32, PCI BIOS functions and definitions */ - #define ioremap vremap - #define iounmap vfree - extern void * vremap (unsigned long offset, unsigned long size); - extern void vfree (void *addr); -#endif #elif defined(_SCO_UNIX_) /****** SCO Unix ****************************/ @@ -381,9 +373,7 @@ * < 0 error */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_setup); -#endif int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len) { @@ -528,9 +518,7 @@ * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_down); -#endif int sdla_down (sdlahw_t* hw) { @@ -572,7 +560,6 @@ *(char *)hw->vector = S514_CPU_HALT; CPU_no = hw->S514_cpu_no[0]; -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* disable the PCI IRQ and disable memory access */ pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config); int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A : ~PCI_DISABLE_IRQ_CPU_B; @@ -585,22 +572,6 @@ else pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD, PCI_CPU_B_MEM_DISABLE); -#else - /* disable the PCI IRQ and disable memory access */ - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, - PCI_INT_CONFIG, &int_config); - int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A : ~PCI_DISABLE_IRQ_CPU_B; - pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, - PCI_INT_CONFIG, int_config); - read_S514_int_stat(hw, &int_status); - S514_intack(hw, int_status); - // disable PCI memory access - if(CPU_no == S514_CPU_A) - pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func, - PCI_MAP0_DWORD, PCI_CPU_A_MEM_DISABLE); - else - pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func, PCI_MAP1_DWORD, PCI_CPU_B_MEM_DISABLE); -#endif /* free up the allocated virtual memory */ iounmap((void *)hw->dpmbase); @@ -618,9 +589,7 @@ * Map shared memory window into SDLA address space. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_mapmem); -#endif int sdla_mapmem (sdlahw_t* hw, unsigned long addr) { @@ -681,9 +650,7 @@ * Enable interrupt generation. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_inten); -#endif int sdla_inten (sdlahw_t* hw) { @@ -739,9 +706,7 @@ * Disable interrupt generation. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_intde); -#endif int sdla_intde (sdlahw_t* hw) { @@ -796,9 +761,7 @@ * Acknowledge SDLA hardware interrupt. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_intack); -#endif int sdla_intack (sdlahw_t* hw) { @@ -848,18 +811,11 @@ * Acknowledge S514 hardware interrupt. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(S514_intack); -#endif void S514_intack (sdlahw_t* hw, u32 int_status) { -#if defined(LINUX_2_1) || defined(LINUX_2_4) pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status); -#else - pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, - PCI_INT_STATUS, int_status); -#endif } @@ -867,18 +823,11 @@ * Read the S514 hardware interrupt status. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(read_S514_int_stat); -#endif void read_S514_int_stat (sdlahw_t* hw, u32* int_status) { -#if defined(LINUX_2_1) || defined(LINUX_2_4) pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status); -#else - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_STATUS, - int_status); -#endif } @@ -886,9 +835,7 @@ * Generate an interrupt to adapter's CPU. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_intr); -#endif int sdla_intr (sdlahw_t* hw) { @@ -932,9 +879,7 @@ * o Return number of loops made, or 0 if command timed out. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_exec); -#endif int sdla_exec (void* opflag) { @@ -970,9 +915,7 @@ * interrupt routines are accessing adapter shared memory. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_peek); -#endif int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) { @@ -1054,9 +997,7 @@ * interrupt routines are accessing adapter shared memory. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_poke); -#endif int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) { @@ -1961,20 +1902,11 @@ int number_S514_cards = 0; u32 S514_mem_base_addr = 0; u32 ut_u32; - -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct pci_dev *pci_dev; -#else - u8 ut_u8; -#endif #ifdef CONFIG_PCI -#if defined(LINUX_2_1) || defined(LINUX_2_4) if(!pci_present()) -#else - if(!pcibios_present()) -#endif { printk(KERN_INFO "%s: PCI BIOS not present!\n", modname); return 0; @@ -2029,26 +1961,12 @@ } } - #if defined(LINUX_2_4) pci_dev = hw->pci_dev; /* read the physical memory base address */ S514_mem_base_addr = (CPU_no == S514_CPU_A) ? (pci_dev->resource[1].start) : (pci_dev->resource[2].start); - #elif defined (LINUX_2_1) - pci_dev = hw->pci_dev; - /* read the physical memory base address */ - S514_mem_base_addr = (CPU_no == S514_CPU_A) ? - (pci_dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK) : - (pci_dev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK); - - #else - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, - (CPU_no == S514_CPU_A) ? PCI_MEM_BASE0_DWORD : - PCI_MEM_BASE1_DWORD, &S514_mem_base_addr); - #endif - printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n", modname, S514_mem_base_addr); if(!S514_mem_base_addr) { @@ -2060,24 +1978,14 @@ } /* enable the PCI memory */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) pci_read_config_dword(pci_dev, (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, &ut_u32); pci_write_config_dword(pci_dev, (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, (ut_u32 | PCI_MEMORY_ENABLE)); -#else - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, - (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, - &ut_u32); - pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, - (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, - (ut_u32 | PCI_MEMORY_ENABLE)); -#endif /* check the IRQ allocated and enable IRQ usage */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) if(!(hw->irq = pci_dev->irq)) { printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n", modname); @@ -2099,29 +2007,6 @@ ut_u32 |= (CPU_no == S514_CPU_A) ? PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B; pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32); -#else - /* the INTPIN must not be 0 - if it is, then the S514 adapter is not */ - /* configured for IRQ usage */ - pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func, - PCI_INT_PIN_BYTE, &ut_u8); - if(!ut_u8) { - printk(KERN_INFO "%s: invalid setting for INTPIN on S514 card\n", modname); - printk(KERN_INFO "Please contact your Sangoma representative\n"); - return 0; - } - pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func, - PCI_INT_LINE_BYTE, (unsigned char *)&hw->irq); - if(hw->irq == PCI_IRQ_NOT_ALLOCATED) { - printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n", - modname); - return 0; - } - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_CONFIG, &ut_u32); - ut_u32 |= (CPU_no == S514_CPU_A) ? - PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B; - pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, - PCI_INT_CONFIG, ut_u32); -#endif printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n", modname, hw->irq); @@ -2157,15 +2042,10 @@ char S514_found_in_slot = 0; u16 PCI_subsys_vendor; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct pci_dev *pci_dev = NULL; -#else - int pci_index; -#endif slot_no = hw->S514_slot_no; -#if defined(LINUX_2_1) || defined(LINUX_2_4) while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev)) != NULL) { @@ -2197,40 +2077,6 @@ } } -#else - //LINUX VERSION 2.0.X - for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) { - if (pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index, - &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) { - break; - } - - pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func, - PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor); - - if (PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR) - continue; - - if (find_first_S514_card) - return(1); - - number_S514_cards ++; - - printk(KERN_INFO "%s: S514 card found, bus #%d, slot #%d\n", - modname, hw->pci_bus, - ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK)); - - if (hw->auto_pci_cfg){ - hw->S514_slot_no = ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK) - slot_no = hw->S514_slot_no; - - }else if (((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK) == slot_no) { - S514_found_in_slot = 1; - break; - } - } -#endif - /* if no S514 adapter has been found, then exit */ if (!number_S514_cards) { printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname); @@ -2408,17 +2254,11 @@ u16 PCI_subsys_vendor; u16 PCI_card_type; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct pci_dev *pci_dev = NULL; struct pci_bus *bus = NULL; -#else - int pci_index; - u8 irq; -#endif slot_no = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev)) != NULL) { @@ -2453,52 +2293,13 @@ } } -#else - for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) { - - if(pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index, - &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) { - break; - } - pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func, - PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor); - if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR) - continue; - - pcibios_read_config_word(hw->pci_bus,hw->pci_dev_func,PCI_CARD_TYPE, - &PCI_card_type); - - pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func, - PCI_INT_LINE_BYTE, &irq); - - /* A dual cpu card can support up to 4 physical connections, - * where a single cpu card can support up to 2 physical - * connections. The FT1 card can only support a single - * connection, however we cannot distinguish between a Single - * CPU card and an FT1 card. */ - if (PCI_card_type == S514_DUAL_CPU){ - number_S514_cards += 4; - printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n", - modname, hw->pci_bus, - ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq); - }else{ - printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n", - modname, hw->pci_bus, - ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq); - number_S514_cards += 2; - } - } -#endif - return number_S514_cards; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(wanpipe_hw_probe); -#endif unsigned wanpipe_hw_probe(void) { diff -Nru a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c --- a/drivers/net/wan/sdlamain.c Tue Feb 25 11:05:23 2003 +++ b/drivers/net/wan/sdlamain.c Thu Mar 6 09:25:30 2003 @@ -64,26 +64,10 @@ #include #include -#if defined(LINUX_2_4) +#define netdevice_t struct net_device - #include /* kernel <-> user copy */ - #include - #define netdevice_t struct net_device - -#elif defined(LINUX_2_1) - - #include /* kernel <-> user copy */ - #include - #define netdevice_t struct device - -#else - - #include - #define devinet_ioctl(x,y) dev_ioctl(x,y) - #define netdevice_t struct device - #define test_and_set_bit set_bit - typedef unsigned long mm_segment_t; -#endif +#include /* kernel <-> user copy */ +#include #include #include @@ -240,23 +224,12 @@ * function, which will execute all pending, * tasks in wanpipe_tq_custom queue */ -#ifdef LINUX_2_4 DECLARE_TASK_QUEUE(wanpipe_tq_custom); static struct tq_struct wanpipe_tq_task = { .routine = (void (*)(void *)) run_wanpipe_tq, .data = &wanpipe_tq_custom }; -#else -static struct tq_struct *wanpipe_tq_custom = NULL; -static struct tq_struct wanpipe_tq_task = -{ - NULL, - 0, - (void *)(void *) run_wanpipe_tq, - &wanpipe_tq_custom -}; -#endif static int wanpipe_bh_critical=0; @@ -511,9 +484,7 @@ if (!card->configured){ /* Initialize the Spin lock */ -#if defined(__SMP__) || defined(LINUX_2_4) printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name); -#endif /* Piggyback spin lock has already been initialized, * in check_s514/s508_conflicts() */ @@ -974,26 +945,13 @@ unsigned long smp_flags; int err = 0; - #if defined(LINUX_2_1) || defined(LINUX_2_4) if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t))) return -EFAULT; - #else - if ((u_dump == NULL) || - verify_area(VERIFY_READ, u_dump, sizeof(sdla_dump_t))) - return -EFAULT; - memcpy_fromfs((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t)); - #endif if ((dump.magic != WANPIPE_MAGIC) || (dump.offset + dump.length > card->hw.memory)) return -EINVAL; - #ifdef LINUX_2_0 - if ((dump.ptr == NULL) || - verify_area(VERIFY_WRITE, dump.ptr, dump.length)) - return -EFAULT; - #endif - winsize = card->hw.dpmsize; if(card->hw.type != SDLA_S514) { @@ -1014,17 +972,13 @@ break; } - #if defined(LINUX_2_1) || defined(LINUX_2_4) if(copy_to_user((void *)dump.ptr, (u8 *)card->hw.dpmbase + pos, len)){ unlock_adapter_irq(&card->wandev.lock, &smp_flags); return -EFAULT; } - #else - memcpy_tofs((void*)(dump.ptr), - (void*)(card->hw.dpmbase + pos), len); - #endif + dump.length -= len; dump.offset += len; (char*)dump.ptr += len; @@ -1035,15 +989,10 @@ }else { - #if defined(LINUX_2_1) || defined(LINUX_2_4) if(copy_to_user((void *)dump.ptr, (u8 *)card->hw.dpmbase + dump.offset, dump.length)){ return -EFAULT; } - #else - memcpy_tofs((void*)(dump.ptr), - (void*)(card->hw.dpmbase + dump.offset), dump.length); - #endif } return err; @@ -1064,15 +1013,8 @@ return -ENODEV; } - #if defined(LINUX_2_1) || defined(LINUX_2_4) if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t))) return -EFAULT; - #else - if ((u_exec == NULL) || - verify_area(VERIFY_READ, u_exec, sizeof(sdla_exec_t))) - return -EFAULT; - memcpy_fromfs((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t)); - #endif if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL)) return -EINVAL; @@ -1345,60 +1287,33 @@ unsigned long get_ip_address (netdevice_t *dev, int option) { - #ifdef LINUX_2_4 struct in_ifaddr *ifaddr; struct in_device *in_dev; if ((in_dev = __in_dev_get(dev)) == NULL){ return 0; } - #elif defined(LINUX_2_1) - struct in_ifaddr *ifaddr; - struct in_device *in_dev; - - if ((in_dev = dev->ip_ptr) == NULL){ - return 0; - } - #endif - #if defined(LINUX_2_1) || defined(LINUX_2_4) if ((ifaddr = in_dev->ifa_list)== NULL ){ return 0; } - #endif switch (option){ case WAN_LOCAL_IP: - #ifdef LINUX_2_0 - return dev->pa_addr; - #else return ifaddr->ifa_local; - #endif break; case WAN_POINTOPOINT_IP: - #ifdef LINUX_2_0 - return dev->pa_dstaddr; - #else return ifaddr->ifa_address; - #endif break; case WAN_NETMASK_IP: - #ifdef LINUX_2_0 - return dev->pa_mask; - #else return ifaddr->ifa_mask; - #endif break; case WAN_BROADCAST_IP: - #ifdef LINUX_2_0 - return dev->pa_brdaddr; - #else return ifaddr->ifa_broadcast; - #endif break; default: return 0; @@ -1431,11 +1346,7 @@ oldfs = get_fs(); set_fs(get_ds()); - #if defined(LINUX_2_1) || defined(LINUX_2_4) res = ip_rt_ioctl(SIOCADDRT,&route); - #else - res = ip_rt_new(&route); - #endif set_fs(oldfs); if (res == 0){ diff -Nru a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c --- a/drivers/net/wan/wanpipe_multppp.c Mon Feb 24 09:56:18 2003 +++ b/drivers/net/wan/wanpipe_multppp.c Thu Mar 6 09:25:30 2003 @@ -42,19 +42,11 @@ #include -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include - #include +#include +#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) - #include -#else - #include "syncppp.h" -#endif +#include -#else - #include /* Adding new route entries */ -#endif /****** Defines & Macros ****************************************************/ @@ -148,15 +140,9 @@ static int if_open (netdevice_t* dev); static int if_close (netdevice_t* dev); static int if_send (struct sk_buff* skb, netdevice_t* dev); -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats* if_stats (netdevice_t* dev); -#else -static struct enet_statistics* if_stats (netdevice_t* dev); -#endif -#ifdef LINUX_2_4 static void if_tx_timeout (netdevice_t *dev); -#endif /* CHDLC Firmware interface functions */ static int chdlc_configure (sdla_t* card, void* data); @@ -601,18 +587,8 @@ /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,card->u.c.if_name); -#else - dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); - if(dev->name == NULL) - { - kfree(chdlc_priv_area); - return -ENOMEM; - } - sprintf(dev->name, "%s", card->u.c.if_name); -#endif - + /* Attach PPP protocol layer to pppdev * The sppp_attach() will initilize the dev structure * and setup ppp layer protocols. @@ -620,11 +596,7 @@ * if_open(), if_close(), if_send() and get_stats() functions. */ sppp_attach(pppdev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16) dev = pppdev->dev; -#else - dev = &pppdev->dev; -#endif sp = &pppdev->sppp; /* Enable PPP Debugging */ @@ -684,9 +656,6 @@ chdlc_private_area_t* chdlc_priv_area = dev->priv; sdla_t* card = chdlc_priv_area->card; wan_device_t* wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* NOTE: Most of the dev initialization was * done in sppp_attach(), called by new_if() @@ -699,16 +668,10 @@ dev->stop = &if_close; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif -#ifdef LINUX_2_0 - dev->family = AF_INET; -#endif - /* Initialize hardware parameters */ dev->irq = wandev->irq; dev->dma = wandev->dma; @@ -724,17 +687,10 @@ */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ -#if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); -#endif - return 0; } -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -754,8 +710,6 @@ printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); netif_wake_queue (dev); } -#endif - /*============================================================================ @@ -773,14 +727,8 @@ SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; /* Only one open per interface is allowed */ - -#ifdef LINUX_2_4 if (netif_running(dev)) return -EBUSY; -#else - if (dev->start) - return -EBUSY; /* only one open is allowed */ -#endif /* Start PPP Layer */ if (sppp_open(dev)){ @@ -790,13 +738,7 @@ do_gettimeofday(&tv); chdlc_priv_area->router_start_time = tv.tv_sec; -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif wanpipe_open(card); @@ -817,11 +759,7 @@ /* Stop the PPP Layer */ sppp_close(dev); - stop_net_queue(dev); - -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); wanpipe_close(card); @@ -855,9 +793,7 @@ unsigned long smp_flags; int err=0; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif if (skb == NULL){ @@ -867,32 +803,10 @@ printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n", card->devname, dev->name); - wake_net_dev(dev); + netif_wake_queue(dev); return 0; } -#ifndef LINUX_2_4 - if (dev->tbusy){ - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - ++card->wandev.stats.collisions; - - if((jiffies - chdlc_priv_area->tick_counter) < (5 * HZ)) { - return 1; - } - - printk (KERN_INFO "%s: Transmit (tbusy) timeout !\n", - card->devname); - - /* unbusy the interface */ - dev->tbusy = 0; - } -#endif - if (ntohs(skb->protocol) != htons(PVC_PROT)){ /* check the udp packet type */ @@ -903,7 +817,7 @@ chdlc_int->interrupt_permission |= APP_INT_ON_TIMER; } - start_net_queue(dev); + netif_start_queue(dev); return 0; } } @@ -918,33 +832,29 @@ printk(KERN_INFO "%s: Critical in if_send: %lx\n", card->wandev.name,card->wandev.critical); ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_crit_exit; } if (card->wandev.state != WAN_CONNECTED){ ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_crit_exit; } if (chdlc_send(card, skb->data, skb->len)){ - stop_net_queue(dev); + netif_stop_queue(dev); }else{ ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += skb->len; -#endif -#ifdef LINUX_2_4 dev->trans_start = jiffies; -#endif - start_net_queue(dev); + netif_start_queue(dev); } if_send_crit_exit: - if (!(err=is_queue_stopped(dev))){ - wan_dev_kfree_skb(skb, FREE_WRITE); + if (!(err=netif_queue_stopped(dev))){ + dev_kfree_skb_any(skb); }else{ chdlc_priv_area->tick_counter = jiffies; chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; @@ -1063,7 +973,6 @@ * Get ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats* if_stats (netdevice_t* dev) { sdla_t *my_card; @@ -1079,23 +988,7 @@ my_card = chdlc_priv_area->card; return &my_card->wandev.stats; } -#else -static struct enet_statistics* if_stats (netdevice_t* dev) -{ - sdla_t *my_card; - chdlc_private_area_t* chdlc_priv_area = dev->priv; - /* Shutdown bug fix. In del_if() we kill - * dev->priv pointer. This function, gets - * called after del_if(), thus check - * if pointer has been deleted */ - if ((chdlc_priv_area=dev->priv) == NULL) - return NULL; - - my_card = chdlc_priv_area->card; - return &my_card->wandev.stats; -} -#endif /****** Cisco HDLC Firmware Interface Functions *******************************/ @@ -1417,7 +1310,7 @@ flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_TX_FRAME; - wake_net_dev(dev); + netif_wake_queue(dev); break; case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */ @@ -1505,15 +1398,9 @@ goto rx_exit; } -#ifdef LINUX_2_4 if (!netif_running(dev)){ goto rx_exit; } -#else - if (!dev->start){ - goto rx_exit; - } -#endif chdlc_priv_area = dev->priv; @@ -1555,9 +1442,7 @@ skb->protocol = htons(ETH_P_WAN_PPP); card->wandev.stats.rx_packets ++; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.rx_bytes += skb->len; -#endif udp_type = udp_pkt_type( skb, card ); if(udp_type == UDP_CPIPE_TYPE) { @@ -1795,9 +1680,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK) - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); else - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return(udp_pkt_stored); } @@ -2156,9 +2041,7 @@ if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) { ++ card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += len; -#endif } } else { @@ -2360,28 +2243,20 @@ void s508_lock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock_irqsave(&card->wandev.lock, *smp_flags); if (card->next){ /* It is ok to use spin_lock here, since we * already turned off interrupts */ spin_lock(&card->next->wandev.lock); } -#else - disable_irq(card->hw.irq); -#endif } void s508_unlock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) if (card->next){ spin_unlock(&card->next->wandev.lock); } spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -#else - enable_irq(card->hw.irq); -#endif } diff -Nru a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c --- a/drivers/oprofile/buffer_sync.c Thu Feb 20 10:06:22 2003 +++ b/drivers/oprofile/buffer_sync.c Sun Mar 2 22:46:44 2003 @@ -277,10 +277,7 @@ */ static struct mm_struct * take_task_mm(struct task_struct * task) { - struct mm_struct * mm; - task_lock(task); - mm = task->mm; - task_unlock(task); + struct mm_struct * mm = task->mm; /* if task->mm !NULL, mm_count must be at least 1. It cannot * drop to 0 without the task exiting, which will have to sleep @@ -310,6 +307,32 @@ } +/* compute number of filled slots in cpu_buffer queue */ +static unsigned long nr_filled_slots(struct oprofile_cpu_buffer * b) +{ + unsigned long head = b->head_pos; + unsigned long tail = b->tail_pos; + + if (head >= tail) + return head - tail; + + return head + (b->buffer_size - tail); +} + + +static void increment_tail(struct oprofile_cpu_buffer * b) +{ + unsigned long new_tail = b->tail_pos + 1; + + rmb(); + + if (new_tail < (b->buffer_size)) + b->tail_pos = new_tail; + else + b->tail_pos = 0; +} + + /* Sync one of the CPU's buffers into the global event buffer. * Here we need to go through each batch of samples punctuated * by context switch notes, taking the task's mmap_sem and doing @@ -322,10 +345,14 @@ struct task_struct * new; unsigned long cookie; int in_kernel = 1; - int i; + unsigned int i; - for (i=0; i < cpu_buf->pos; ++i) { - struct op_sample * s = &cpu_buf->buffer[i]; + /* Remember, only we can modify tail_pos */ + + unsigned long const available_elements = nr_filled_slots(cpu_buf); + + for (i=0; i < available_elements; ++i) { + struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; if (is_ctx_switch(s->eip)) { if (s->event <= 1) { @@ -345,6 +372,8 @@ } else { add_sample(mm, s, in_kernel); } + + increment_tail(cpu_buf); } release_mm(mm); @@ -369,17 +398,8 @@ cpu_buf = &cpu_buffer[i]; - /* We take a spin lock even though we might - * sleep. It's OK because other users are try - * lockers only, and this region is already - * protected by buffer_sem. It's raw to prevent - * the preempt bogometer firing. Fruity, huh ? */ - if (cpu_buf->pos > 0) { - _raw_spin_lock(&cpu_buf->int_lock); - add_cpu_switch(i); - sync_buffer(cpu_buf); - _raw_spin_unlock(&cpu_buf->int_lock); - } + add_cpu_switch(i); + sync_buffer(cpu_buf); } up(&buffer_sem); diff -Nru a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c --- a/drivers/oprofile/cpu_buffer.c Thu Jan 23 12:24:53 2003 +++ b/drivers/oprofile/cpu_buffer.c Thu Mar 6 08:24:34 2003 @@ -26,8 +26,6 @@ struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned; -static unsigned long buffer_size; - static void __free_cpu_buffers(int num) { int i; @@ -47,7 +45,7 @@ { int i; - buffer_size = fs_cpu_buffer_size; + unsigned long buffer_size = fs_cpu_buffer_size; for (i=0; i < NR_CPUS; ++i) { struct oprofile_cpu_buffer * b = &cpu_buffer[i]; @@ -59,12 +57,12 @@ if (!b->buffer) goto fail; - spin_lock_init(&b->int_lock); - b->pos = 0; b->last_task = 0; b->last_is_kernel = -1; + b->buffer_size = buffer_size; + b->tail_pos = 0; + b->head_pos = 0; b->sample_received = 0; - b->sample_lost_locked = 0; b->sample_lost_overflow = 0; b->sample_lost_task_exit = 0; } @@ -80,11 +78,38 @@ __free_cpu_buffers(NR_CPUS); } - -/* Note we can't use a semaphore here as this is supposed to - * be safe from any context. Instead we trylock the CPU's int_lock. - * int_lock is taken by the processing code in sync_cpu_buffers() - * so we avoid disturbing that. + +/* compute number of available slots in cpu_buffer queue */ +static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b) +{ + unsigned long head = b->head_pos; + unsigned long tail = b->tail_pos; + + if (tail > head) + return tail - head; + + return tail + (b->buffer_size - head); +} + + +static void increment_head(struct oprofile_cpu_buffer * b) +{ + unsigned long new_head = b->head_pos + 1; + + /* Ensure anything written to the slot before we + * increment is visible */ + wmb(); + + if (new_head < (b->buffer_size)) + b->head_pos = new_head; + else + b->head_pos = 0; +} + + +/* This must be safe from any context. It's safe writing here + * because of the head/tail separation of the writer and reader + * of the CPU buffer. * * is_kernel is needed because on some architectures you cannot * tell if you are in kernel or user space simply by looking at @@ -101,14 +126,10 @@ cpu_buf->sample_received++; - if (!spin_trylock(&cpu_buf->int_lock)) { - cpu_buf->sample_lost_locked++; - return; - } - if (cpu_buf->pos > buffer_size - 2) { + if (nr_available_slots(cpu_buf) < 3) { cpu_buf->sample_lost_overflow++; - goto out; + return; } task = current; @@ -116,18 +137,18 @@ /* notice a switch from user->kernel or vice versa */ if (cpu_buf->last_is_kernel != is_kernel) { cpu_buf->last_is_kernel = is_kernel; - cpu_buf->buffer[cpu_buf->pos].eip = ~0UL; - cpu_buf->buffer[cpu_buf->pos].event = is_kernel; - cpu_buf->pos++; + cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL; + cpu_buf->buffer[cpu_buf->head_pos].event = is_kernel; + increment_head(cpu_buf); } /* notice a task switch */ if (cpu_buf->last_task != task) { cpu_buf->last_task = task; if (!(task->flags & PF_EXITING)) { - cpu_buf->buffer[cpu_buf->pos].eip = ~0UL; - cpu_buf->buffer[cpu_buf->pos].event = (unsigned long)task; - cpu_buf->pos++; + cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL; + cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task; + increment_head(cpu_buf); } } @@ -138,23 +159,20 @@ */ if (task->flags & PF_EXITING) { cpu_buf->sample_lost_task_exit++; - goto out; + return; } - cpu_buf->buffer[cpu_buf->pos].eip = eip; - cpu_buf->buffer[cpu_buf->pos].event = event; - cpu_buf->pos++; -out: - spin_unlock(&cpu_buf->int_lock); + cpu_buf->buffer[cpu_buf->head_pos].eip = eip; + cpu_buf->buffer[cpu_buf->head_pos].event = event; + increment_head(cpu_buf); } + /* resets the cpu buffer to a sane state - should be called with * cpu_buf->int_lock held */ void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf) { - cpu_buf->pos = 0; - /* reset these to invalid values; the next sample * collected will populate the buffer with proper * values to initialize the buffer @@ -162,4 +180,3 @@ cpu_buf->last_is_kernel = -1; cpu_buf->last_task = 0; } - diff -Nru a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h --- a/drivers/oprofile/cpu_buffer.h Thu Jan 23 12:24:53 2003 +++ b/drivers/oprofile/cpu_buffer.h Wed Mar 5 13:56:22 2003 @@ -30,14 +30,13 @@ }; struct oprofile_cpu_buffer { - spinlock_t int_lock; - /* protected by int_lock */ - unsigned long pos; + volatile unsigned long head_pos; + volatile unsigned long tail_pos; + unsigned long buffer_size; struct task_struct * last_task; int last_is_kernel; struct op_sample * buffer; unsigned long sample_received; - unsigned long sample_lost_locked; unsigned long sample_lost_overflow; unsigned long sample_lost_task_exit; } ____cacheline_aligned; diff -Nru a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c --- a/drivers/oprofile/oprofile_stats.c Sun Dec 22 04:53:01 2002 +++ b/drivers/oprofile/oprofile_stats.c Tue Feb 25 05:56:06 2003 @@ -27,7 +27,6 @@ cpu_buf = &cpu_buffer[i]; cpu_buf->sample_received = 0; - cpu_buf->sample_lost_locked = 0; cpu_buf->sample_lost_overflow = 0; cpu_buf->sample_lost_task_exit = 0; } @@ -63,8 +62,6 @@ */ oprofilefs_create_ro_ulong(sb, cpudir, "sample_received", &cpu_buf->sample_received); - oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_locked", - &cpu_buf->sample_lost_locked); oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_overflow", &cpu_buf->sample_lost_overflow); oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_task_exit", diff -Nru a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c --- a/drivers/parport/ieee1284.c Mon Nov 18 14:18:05 2002 +++ b/drivers/parport/ieee1284.c Wed Mar 5 21:39:37 2003 @@ -170,7 +170,7 @@ { int ret; int usec; - long deadline; + unsigned long deadline; unsigned char status; usec = port->physport->spintime; /* usecs of fast polling */ diff -Nru a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c --- a/drivers/parport/ieee1284_ops.c Sat Nov 23 06:29:46 2002 +++ b/drivers/parport/ieee1284_ops.c Wed Mar 5 21:39:37 2003 @@ -58,7 +58,7 @@ parport_write_control (port, ctl); parport_data_forward (port); while (count < len) { - long expire = jiffies + dev->timeout; + unsigned long expire = jiffies + dev->timeout; long wait = (HZ + 99) / 100; unsigned char mask = (PARPORT_STATUS_ERROR | PARPORT_STATUS_BUSY); @@ -431,7 +431,7 @@ | PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT); for (written = 0; written < len; written++, buf++) { - long expire = jiffies + port->cad->timeout; + unsigned long expire = jiffies + port->cad->timeout; unsigned char byte; byte = *buf; @@ -520,7 +520,7 @@ parport_write_control (port, ctl | PARPORT_CONTROL_AUTOFD); while (count < len) { - long expire = jiffies + dev->timeout; + unsigned long expire = jiffies + dev->timeout; unsigned char byte; int command; @@ -668,7 +668,7 @@ PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT); for (written = 0; written < len; written++, buf++) { - long expire = jiffies + port->cad->timeout; + unsigned long expire = jiffies + port->cad->timeout; unsigned char byte; byte = *buf; diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile Tue Feb 18 18:58:56 2003 +++ b/drivers/pci/Makefile Sat Mar 1 07:41:20 2003 @@ -2,7 +2,7 @@ # Makefile for the PCI bus specific drivers. # -obj-y += access.o probe.o pci.o pool.o quirks.o \ +obj-y += access.o bus.o probe.o pci.o pool.o quirks.o \ names.o pci-driver.o search.o hotplug.o \ pci-sysfs.o obj-$(CONFIG_PM) += power.o diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/bus.c Mon Mar 3 13:26:41 2003 @@ -0,0 +1,127 @@ +/* + * drivers/pci/bus.c + * + * From setup-res.c, by: + * Dave Rusling (david.rusling@reo.mts.dec.com) + * David Mosberger (davidm@cs.arizona.edu) + * David Miller (davem@redhat.com) + * Ivan Kokshaysky (ink@jurassic.park.msu.ru) + */ +#include +#include +#include +#include +#include +#include +#include + +#include "pci.h" + +/** + * pci_bus_alloc_resource - allocate a resource from a parent bus + * @bus: PCI bus + * @res: resource to allocate + * @size: size of resource to allocate + * @align: alignment of resource to allocate + * @min: minimum /proc/iomem address to allocate + * @type_mask: IORESOURCE_* type flags + * @alignf: resource alignment function + * @alignf_data: data argument for resource alignment function + * + * Given the PCI bus a device resides on, the size, minimum address, + * alignment and type, try to find an acceptable resource allocation + * for a specific device resource. + */ +int +pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, + unsigned long size, unsigned long align, unsigned long min, + unsigned int type_mask, + void (*alignf)(void *, struct resource *, + unsigned long, unsigned long), + void *alignf_data) +{ + int i, ret = -ENOMEM; + + type_mask |= IORESOURCE_IO | IORESOURCE_MEM; + + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + struct resource *r = bus->resource[i]; + if (!r) + continue; + + /* type_mask must match */ + if ((res->flags ^ r->flags) & type_mask) + continue; + + /* We cannot allocate a non-prefetching resource + from a pre-fetching area */ + if ((r->flags & IORESOURCE_PREFETCH) && + !(res->flags & IORESOURCE_PREFETCH)) + continue; + + /* Ok, try it out.. */ + ret = allocate_resource(r, res, size, min, -1, align, + alignf, alignf_data); + if (ret == 0) + break; + } + return ret; +} + +/** + * pci_bus_add_devices - insert newly discovered PCI devices + * @bus: bus to check for new devices + * + * Add newly discovered PCI devices (which are on the bus->devices + * list) to the global PCI device list, add the sysfs and procfs + * entries. Where a bridge is found, add the discovered bus to + * the parents list of child buses, and recurse. + * + * Call hotplug for each new devices. + */ +void __devinit pci_bus_add_devices(struct pci_bus *bus) +{ + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + /* + * Skip already-present devices (which are on the + * global device list.) + */ + if (!list_empty(&dev->global_list)) + continue; + + device_register(&dev->dev); + list_add_tail(&dev->global_list, &pci_devices); +#ifdef CONFIG_PROC_FS + pci_proc_attach_device(dev); +#endif + pci_create_sysfs_dev_files(dev); + + /* + * If there is an unattached subordinate bus, attach + * it and then scan for unattached PCI devices. + */ + if (dev->subordinate && list_empty(&dev->subordinate->node)) { + list_add_tail(&dev->subordinate->node, &dev->bus->children); + pci_bus_add_devices(dev->subordinate); + } + } +} + +void pci_enable_bridges(struct pci_bus *bus) +{ + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + if (dev->subordinate) { + pci_enable_device(dev); + pci_set_master(dev); + pci_enable_bridges(dev->subordinate); + } + } +} + +EXPORT_SYMBOL(pci_bus_alloc_resource); +EXPORT_SYMBOL(pci_bus_add_devices); +EXPORT_SYMBOL(pci_enable_bridges); diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c --- a/drivers/pci/probe.c Mon Feb 24 08:17:19 2003 +++ b/drivers/pci/probe.c Tue Feb 25 15:47:51 2003 @@ -221,47 +221,64 @@ b = kmalloc(sizeof(*b), GFP_KERNEL); if (b) { memset(b, 0, sizeof(*b)); + INIT_LIST_HEAD(&b->node); INIT_LIST_HEAD(&b->children); INIT_LIST_HEAD(&b->devices); } return b; } -struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) +static struct pci_bus * __devinit +pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) { struct pci_bus *child; - int i; /* * Allocate a new bus, and inherit stuff from the parent.. */ child = pci_alloc_bus(); - list_add_tail(&child->node, &parent->children); - child->self = dev; - dev->subordinate = child; - child->parent = parent; - child->ops = parent->ops; - child->sysdata = parent->sysdata; - child->dev = &dev->dev; + if (child) { + int i; - /* - * Set up the primary, secondary and subordinate - * bus numbers. - */ - child->number = child->secondary = busnr; - child->primary = parent->secondary; - child->subordinate = 0xff; - - /* Set up default resource pointers and names.. */ - for (i = 0; i < 4; i++) { - child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; - child->resource[i]->name = child->name; + child->self = bridge; + child->parent = parent; + child->ops = parent->ops; + child->sysdata = parent->sysdata; + child->dev = &bridge->dev; + + /* + * Set up the primary, secondary and subordinate + * bus numbers. + */ + child->number = child->secondary = busnr; + child->primary = parent->secondary; + child->subordinate = 0xff; + + /* Set up default resource pointers and names.. */ + for (i = 0; i < 4; i++) { + child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; + child->resource[i]->name = child->name; + } + + bridge->subordinate = child; } return child; } +struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) +{ + struct pci_bus *child; + + child = pci_alloc_child_bus(parent, dev, busnr); + if (child) + list_add_tail(&child->node, &parent->children); + return child; +} + +static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); + /* * If it's a bridge, configure it and scan the bus behind it. * For CardBus bridges, we don't scan behind as the devices will @@ -288,12 +305,12 @@ */ if (pass) return max; - child = pci_add_new_bus(bus, dev, 0); + child = pci_alloc_child_bus(bus, dev, 0); child->primary = buses & 0xFF; child->secondary = (buses >> 8) & 0xFF; child->subordinate = (buses >> 16) & 0xFF; child->number = child->secondary; - cmax = pci_do_scan_bus(child); + cmax = pci_scan_child_bus(child); if (cmax > max) max = cmax; } else { /* @@ -306,18 +323,27 @@ /* Clear errors */ pci_write_config_word(dev, PCI_STATUS, 0xffff); - child = pci_add_new_bus(bus, dev, ++max); + child = pci_alloc_child_bus(bus, dev, ++max); buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) | ((unsigned int)(child->secondary) << 8) | ((unsigned int)(child->subordinate) << 16); + + /* + * yenta.c forces a secondary latency timer of 176. + * Copy that behaviour here. + */ + if (is_cardbus) + buses = (buses & 0x00ffffff) | (176 << 24); + /* * We need to blast all three values with a single write. */ pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); + if (!is_cardbus) { /* Now we can scan all subordinate buses... */ - max = pci_do_scan_bus(child); + max = pci_scan_child_bus(child); } else { /* * For CardBus bridges, we leave 4 bus numbers @@ -374,7 +400,8 @@ dev->class = class; class >>= 8; - DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, dev->vendor, dev->device, class, dev->hdr_type); + DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, + dev->vendor, dev->device, class, dev->hdr_type); /* "Unknown power state" */ dev->current_state = 4; @@ -427,23 +454,35 @@ * Read the config data for a PCI device, sanity-check it * and fill in the dev structure... */ -struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp) +static struct pci_dev * __devinit +pci_scan_device(struct pci_bus *bus, int devfn) { struct pci_dev *dev; u32 l; + u8 hdr_type; + + if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type)) + return NULL; - if (pci_read_config_dword(temp, PCI_VENDOR_ID, &l)) + if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l)) return NULL; /* some broken boards return 0 or ~0 if a slot is empty: */ if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) return NULL; - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return NULL; - memcpy(dev, temp, sizeof(*dev)); + memset(dev, 0, sizeof(struct pci_dev)); + dev->bus = bus; + dev->sysdata = bus->sysdata; + dev->dev.parent = bus->dev; + dev->dev.bus = &pci_bus_type; + dev->devfn = devfn; + dev->hdr_type = hdr_type & 0x7f; + dev->multifunction = !!(hdr_type & 0x80); dev->vendor = l & 0xffff; dev->device = (l >> 16) & 0xffff; @@ -461,74 +500,63 @@ strcpy(dev->dev.bus_id,dev->slot_name); dev->dev.dma_mask = &dev->dma_mask; - device_register(&dev->dev); return dev; } -struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp) +/** + * pci_scan_slot - scan a PCI slot on a bus for devices. + * @bus: PCI bus to scan + * @devfn: slot number to scan (must have zero function.) + * + * Scan a PCI slot on the specified PCI bus for devices, adding + * discovered devices to the @bus->devices list. New devices + * will have an empty dev->global_list head. + */ +int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) { - struct pci_bus *bus = temp->bus; - struct pci_dev *dev; - struct pci_dev *first_dev = NULL; - int func = 0; - int is_multi = 0; - u8 hdr_type; + int func, nr = 0; - for (func = 0; func < 8; func++, temp->devfn++) { - if (func && !is_multi) /* not a multi-function device */ - continue; - if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) - continue; - temp->hdr_type = hdr_type & 0x7f; + for (func = 0; func < 8; func++, devfn++) { + struct pci_dev *dev; - dev = pci_scan_device(temp); + dev = pci_scan_device(bus, devfn); if (!dev) continue; - if (!func) { - is_multi = hdr_type & 0x80; - first_dev = dev; - } - /* - * Link the device to both the global PCI device chain and - * the per-bus list of devices and add the /proc entry. - */ - pci_insert_device (dev, bus); + if (func != 0) + dev->multifunction = 1; /* Fix up broken headers */ pci_fixup_device(PCI_FIXUP_HEADER, dev); + + /* + * Add the device to our list of discovered devices + * and the bus list for fixup functions, etc. + */ + INIT_LIST_HEAD(&dev->global_list); + list_add_tail(&dev->bus_list, &bus->devices); + nr++; + + /* + * If this is a single function device, + * don't scan past the first function. + */ + if (!dev->multifunction) + break; } - return first_dev; + return nr; } -unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) +static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) { - unsigned int devfn, max, pass; - struct list_head *ln; + unsigned int devfn, pass, max = bus->secondary; struct pci_dev *dev; - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); - return 0; - } - DBG("Scanning bus %02x\n", bus->number); - max = bus->secondary; - - /* Create a device template */ - memset(dev, 0, sizeof(*dev)); - dev->bus = bus; - dev->sysdata = bus->sysdata; - dev->dev.parent = bus->dev; - dev->dev.bus = &pci_bus_type; /* Go find them, Rover! */ - for (devfn = 0; devfn < 0x100; devfn += 8) { - dev->devfn = devfn; - pci_scan_slot(dev); - } - kfree(dev); + for (devfn = 0; devfn < 0x100; devfn += 8) + pci_scan_slot(bus, devfn); /* * After performing arch-dependent fixup of the bus, look behind @@ -537,9 +565,9 @@ DBG("Fixups for bus %02x\n", bus->number); pcibios_fixup_bus(bus); for (pass=0; pass < 2; pass++) - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - dev = pci_dev_b(ln); - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) + list_for_each_entry(dev, &bus->devices, bus_list) { + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) max = pci_scan_bridge(bus, dev, max, pass); } @@ -551,6 +579,20 @@ * Return how far we've got finding sub-buses. */ DBG("Bus scan for %02x returning with max=%02x\n", bus->number, max); + return max; +} + +unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) +{ + unsigned int max; + + max = pci_scan_child_bus(bus); + + /* + * Make the discovered devices available. + */ + pci_bus_add_devices(bus); + return max; } diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c --- a/drivers/pci/quirks.c Sat Feb 15 04:56:07 2003 +++ b/drivers/pci/quirks.c Thu Feb 20 08:59:29 2003 @@ -167,6 +167,22 @@ } } +/* + * Ali Magik requires workarounds to be used by the drivers + * that DMA to AGP space. Latency must be set to 0xA and triton + * workaround applied too + * [Info kindly provided by ALi] + */ + +static void __init quirk_alimagik(struct pci_dev *dev) +{ + if((pci_pci_problems&PCIPCI_ALIMAGIK)==0) + { + printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n"); + pci_pci_problems|=PCIPCI_ALIMAGIK|PCIPCI_TRITON; + } +} + /* * Natoma has some interesting boundary conditions with Zoran stuff @@ -219,7 +235,7 @@ static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev) { printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n"); - /* Mae rhaid in i beidio a edrych ar y lleoliad I/O hyn */ + /* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */ request_region(0x3b0, 0x0C, "RadeonIGP"); request_region(0x3d3, 0x01, "RadeonIGP"); } @@ -535,6 +551,92 @@ } } +/* + * As per PCI spec, ignore base address registers 0-3 of the IDE controllers + * running in Compatible mode (bits 0 and 2 in the ProgIf for primary and + * secondary channels respectively). If the device reports Compatible mode + * but does use BAR0-3 for address decoding, we assume that firmware has + * programmed these BARs with standard values (0x1f0,0x3f4 and 0x170,0x374). + * Exceptions (if they exist) must be handled in chip/architecture specific + * fixups. + * + * Note: for non x86 people. You may need an arch specific quirk to handle + * moving IDE devices to native mode as well. Some plug in card devices power + * up in compatible mode and assume the BIOS will adjust them. + * + * Q: should we load the 0x1f0,0x3f4 into the registers or zap them as + * we do now ? We don't want is pci_enable_device to come along + * and assign new resources. Both approaches work for that. + */ + +static void __devinit quirk_ide_bases(struct pci_dev *dev) +{ + struct resource *res; + int first_bar = 2, last_bar = 0; + + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + + res = &dev->resource[0]; + + /* primary channel: ProgIf bit 0, BAR0, BAR1 */ + if (!(dev->class & 1) && (res[0].flags || res[1].flags)) { + res[0].start = res[0].end = res[0].flags = 0; + res[1].start = res[1].end = res[1].flags = 0; + first_bar = 0; + last_bar = 1; + } + + /* secondary channel: ProgIf bit 2, BAR2, BAR3 */ + if (!(dev->class & 4) && (res[2].flags || res[3].flags)) { + res[2].start = res[2].end = res[2].flags = 0; + res[3].start = res[3].end = res[3].flags = 0; + last_bar = 3; + } + + if (!last_bar) + return; + + printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n", + first_bar, last_bar, dev->slot_name); +} + +/* + * Ensure C0 rev restreaming is off. This is normally done by + * the BIOS but in the odd case it is not the results are corruption + * hence the presence of a Linux check + */ + +static void __init quirk_disable_pxb(struct pci_dev *pdev) +{ + u16 config; + u8 rev; + + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); + if(rev != 0x04) /* Only C0 requires this */ + return; + pci_read_config_word(pdev, 0x40, &config); + if(config & (1<<6)) + { + config &= ~(1<<6); + pci_write_config_word(pdev, 0x40, config); + printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n"); + } +} + +/* + * VIA northbridges care about PCI_INTERRUPT_LINE + */ + +int interrupt_line_quirk; + +static void __init quirk_via_bridge(struct pci_dev *pdev) +{ + if(pdev->devfn == 0) + interrupt_line_quirk = 1; +} + + /* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. */ @@ -559,7 +661,10 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton }, @@ -574,6 +679,8 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency }, @@ -586,6 +693,8 @@ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3_usb }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, quirk_piix3_usb }, + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, quirk_ide_bases }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge }, { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy }, #ifdef CONFIG_X86_IO_APIC diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c --- a/drivers/pci/setup-bus.c Tue Feb 18 03:27:06 2003 +++ b/drivers/pci/setup-bus.c Tue Feb 25 03:17:33 2003 @@ -350,6 +350,7 @@ { struct pci_bus *b; int found_vga = pbus_assign_resources_sorted(bus); + struct pci_dev *dev; if (found_vga) { /* Propagate presence of the VGA to upstream bridges */ @@ -357,9 +358,12 @@ b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA; } } - list_for_each_entry(b, &bus->children, node) { - pci_bus_assign_resources(b); - pci_setup_bridge(b); + list_for_each_entry(dev, &bus->devices, bus_list) { + b = dev->subordinate; + if (b) { + pci_bus_assign_resources(b); + pci_setup_bridge(b); + } } } EXPORT_SYMBOL(pci_bus_assign_resources); diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c --- a/drivers/pci/setup-res.c Tue Dec 10 01:15:16 2002 +++ b/drivers/pci/setup-res.c Sat Mar 1 02:11:51 2003 @@ -55,84 +55,47 @@ return err; } -/* - * Given the PCI bus a device resides on, try to - * find an acceptable resource allocation for a - * specific device resource.. - */ -static int pci_assign_bus_resource(const struct pci_bus *bus, - struct pci_dev *dev, - struct resource *res, - unsigned long size, - unsigned long min, - unsigned int type_mask, - int resno) +int pci_assign_resource(struct pci_dev *dev, int resno) { - unsigned long align; - int i; - - type_mask |= IORESOURCE_IO | IORESOURCE_MEM; - for (i = 0 ; i < PCI_BUS_NUM_RESOURCES; i++) { - struct resource *r = bus->resource[i]; - if (!r) - continue; - - /* type_mask must match */ - if ((res->flags ^ r->flags) & type_mask) - continue; - - /* We cannot allocate a non-prefetching resource - from a pre-fetching area */ - if ((r->flags & IORESOURCE_PREFETCH) && - !(res->flags & IORESOURCE_PREFETCH)) - continue; - - /* The bridge resources are special, as their - size != alignment. Sizing routines return - required alignment in the "start" field. */ - align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start; - - /* Ok, try it out.. */ - if (allocate_resource(r, res, size, min, -1, align, - pcibios_align_resource, dev) < 0) - continue; - - /* Update PCI config space. */ - pcibios_update_resource(dev, r, res, resno); - return 0; - } - return -EBUSY; -} - -int -pci_assign_resource(struct pci_dev *dev, int i) -{ - const struct pci_bus *bus = dev->bus; - struct resource *res = dev->resource + i; - unsigned long size, min; + struct pci_bus *bus = dev->bus; + struct resource *res = dev->resource + resno; + unsigned long size, min, align; + int ret; size = res->end - res->start + 1; min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; + /* The bridge resources are special, as their + size != alignment. Sizing routines return + required alignment in the "start" field. */ + align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start; /* First, try exact prefetching match.. */ - if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH, i) < 0) { + ret = pci_bus_alloc_resource(bus, res, size, align, min, + IORESOURCE_PREFETCH, + pcibios_align_resource, dev); + + if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) { /* * That failed. * * But a prefetching area can handle a non-prefetching * window (it will just not perform as well). */ - if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) { - printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n", - i, res->start, res->end, dev->slot_name); - return -EBUSY; - } + ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, + pcibios_align_resource, dev); } - DBGC((KERN_ERR " got res[%lx:%lx] for resource %d of %s\n", res->start, - res->end, i, dev->dev.name)); + if (ret) { + printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n", + resno, res->start, res->end, dev->slot_name); + } else { + DBGC((KERN_ERR " got res[%lx:%lx] for resource %d of %s\n", + res->start, res->end, i, dev->dev.name)); + /* Update PCI config space. */ + pcibios_update_resource(dev, res->parent, res, resno); + } - return 0; + return ret; } /* Sort resources by alignment */ diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c --- a/drivers/pcmcia/hd64465_ss.c Fri Feb 21 13:05:18 2003 +++ b/drivers/pcmcia/hd64465_ss.c Tue Mar 4 22:35:34 2003 @@ -1070,8 +1070,8 @@ } /* hd64465_io_debug = 0; */ - platform_device_register(&hd64465_device); hd64465_device.dev.class_data = &hd64465_data; + platform_device_register(&hd64465_device); return 0; } diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c --- a/drivers/pcmcia/i82365.c Tue Feb 25 11:50:51 2003 +++ b/drivers/pcmcia/i82365.c Tue Mar 4 22:35:34 2003 @@ -1628,11 +1628,11 @@ request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt); #endif - platform_device_register(&i82365_device); - i82365_data.nsock = sockets; i82365_device.dev.class_data = &i82365_data; + platform_device_register(&i82365_device); + /* Finally, schedule a polling interrupt */ if (poll_interval != 0) { poll_timer.function = pcic_interrupt_wrapper; diff -Nru a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c --- a/drivers/pcmcia/sa1100_generic.c Sun Mar 2 12:59:19 2003 +++ b/drivers/pcmcia/sa1100_generic.c Thu Mar 6 08:48:29 2003 @@ -47,7 +47,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c Fri Feb 21 13:05:24 2003 +++ b/drivers/pcmcia/tcic.c Tue Mar 4 22:35:34 2003 @@ -452,8 +452,6 @@ sockets++; } - platform_device_register(&tcic_device); - switch (socket_table[0].id) { case TCIC_ID_DB86082: printk("DB86082"); break; @@ -526,6 +524,8 @@ tcic_data.nsock = sockets; tcic_device.dev.class_data = &tcic_data; + + platform_device_register(&tcic_device); return 0; diff -Nru a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig --- a/drivers/pnp/Kconfig Sun Feb 9 17:29:49 2003 +++ b/drivers/pnp/Kconfig Sun Mar 9 15:37:55 2003 @@ -30,15 +30,6 @@ If unsure, say Y. -config PNP_CARD - bool "Plug and Play card services" - depends on PNP - help - Select Y if you want the PnP Layer to manage cards. Cards are groups - of PnP devices. Some drivers, especially PnP sound card drivers, use - these cards. If you want to use the protocol ISAPNP you will need to - say Y here. - config PNP_DEBUG bool "PnP Debug Messages" depends on PNP @@ -51,7 +42,7 @@ config ISAPNP bool "ISA Plug and Play support (EXPERIMENTAL)" - depends on PNP && EXPERIMENTAL && PNP_CARD + depends on PNP && EXPERIMENTAL help Say Y here if you would like support for ISA Plug and Play devices. Some information is in . diff -Nru a/drivers/pnp/Makefile b/drivers/pnp/Makefile --- a/drivers/pnp/Makefile Wed Feb 19 08:45:42 2003 +++ b/drivers/pnp/Makefile Sun Mar 9 15:37:55 2003 @@ -2,9 +2,7 @@ # Makefile for the Linux Plug-and-Play Support. # -pnp-card-$(CONFIG_PNP_CARD) = card.o - -obj-y := core.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o $(pnp-card-y) +obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o obj-$(CONFIG_PNPBIOS) += pnpbios/ obj-$(CONFIG_ISAPNP) += isapnp/ diff -Nru a/drivers/pnp/card.c b/drivers/pnp/card.c --- a/drivers/pnp/card.c Wed Feb 19 09:51:16 2003 +++ b/drivers/pnp/card.c Sun Mar 9 15:44:14 2003 @@ -16,15 +16,14 @@ #endif #include -#include #include "base.h" - LIST_HEAD(pnp_cards); -static const struct pnp_card_id * match_card(struct pnpc_driver *drv, struct pnp_card *card) + +static const struct pnp_card_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card) { - const struct pnp_card_id *drv_id = drv->id_table; + const struct pnp_card_id * drv_id = drv->id_table; while (*drv_id->id){ if (compare_pnp_id(card->id,drv_id->id)) return drv_id; @@ -33,31 +32,33 @@ return NULL; } -static int card_bus_match(struct device *dev, struct device_driver *drv) +static void generic_card_remove(struct pnp_dev * dev) { - struct pnp_card * card = to_pnp_card(dev); - struct pnpc_driver * pnp_drv = to_pnpc_driver(drv); - if (match_card(pnp_drv, card) == NULL) - return 0; - return 1; + dev->card_link = NULL; } -struct bus_type pnpc_bus_type = { - .name = "pnp_card", - .match = card_bus_match, -}; - +static void generic_card_remove_first(struct pnp_dev * dev) +{ + struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver); + if (!dev->card || !drv) + return; + if (drv->remove) + drv->remove(dev->card_link); + drv->link.remove = &generic_card_remove; + kfree(dev->card_link); + generic_card_remove(dev); +} /** - * pnpc_add_id - adds an EISA id to the specified card + * pnp_add_card_id - adds an EISA id to the specified card * @id: pointer to a pnp_id structure * @card: pointer to the desired card * */ -int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) +int pnp_add_card_id(struct pnp_id *id, struct pnp_card * card) { - struct pnp_id *ptr; + struct pnp_id * ptr; if (!id) return -EINVAL; if (!card) @@ -73,7 +74,7 @@ return 0; } -static void pnpc_free_ids(struct pnp_card *card) +static void pnp_free_card_ids(struct pnp_card * card) { struct pnp_id * id; struct pnp_id *next; @@ -90,47 +91,51 @@ static void pnp_release_card(struct device *dmdev) { struct pnp_card * card = to_pnp_card(dmdev); - pnpc_free_ids(card); + pnp_free_card_ids(card); kfree(card); } /** - * pnpc_add_card - adds a PnP card to the PnP Layer + * pnp_add_card - adds a PnP card to the PnP Layer * @card: pointer to the card to add */ -int pnpc_add_card(struct pnp_card *card) +int pnp_add_card(struct pnp_card * card) { - int error = 0; + int error; + struct list_head * pos; if (!card || !card->protocol) return -EINVAL; + sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, card->number); - INIT_LIST_HEAD(&card->rdevs); card->dev.parent = &card->protocol->dev; - card->dev.bus = &pnpc_bus_type; + card->dev.bus = NULL; card->dev.release = &pnp_release_card; - card->status = PNP_READY; error = device_register(&card->dev); - if (error == 0){ - struct list_head *pos; + if (error == 0) { spin_lock(&pnp_lock); list_add_tail(&card->global_list, &pnp_cards); list_add_tail(&card->protocol_list, &card->protocol->cards); spin_unlock(&pnp_lock); + + /* we wait until now to add devices in order to ensure the drivers + * will be able to use all of the related devices on the card + * without waiting any unresonable length of time */ list_for_each(pos,&card->devices){ struct pnp_dev *dev = card_to_pnp_dev(pos); __pnp_add_device(dev); } - } + } else + pnp_err("sysfs failure, card '%s' will be unavailable", card->dev.bus_id); return error; } /** - * pnpc_remove_card - removes a PnP card from the PnP Layer + * pnp_remove_card - removes a PnP card from the PnP Layer * @card: pointer to the card to remove */ -void pnpc_remove_card(struct pnp_card *card) +void pnp_remove_card(struct pnp_card * card) { struct list_head *pos, *temp; if (!card) @@ -142,22 +147,24 @@ spin_unlock(&pnp_lock); list_for_each_safe(pos,temp,&card->devices){ struct pnp_dev *dev = card_to_pnp_dev(pos); - pnpc_remove_device(dev); + pnp_remove_card_device(dev); } } /** - * pnpc_add_device - adds a device to the specified card + * pnp_add_card_device - adds a device to the specified card * @card: pointer to the card to add to * @dev: pointer to the device to add */ -int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) +int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev) { - if (!dev || !dev->protocol || !card) + if (!card || !dev || !dev->protocol) return -EINVAL; dev->dev.parent = &card->dev; - sprintf(dev->dev.bus_id, "%02x:%02x.%02x", dev->protocol->number, card->number,dev->number); + dev->card_link = NULL; + snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x", dev->protocol->number, + card->number,dev->number); spin_lock(&pnp_lock); dev->card = card; list_add_tail(&dev->card_list, &card->devices); @@ -166,12 +173,12 @@ } /** - * pnpc_remove_device- removes a device from the specified card + * pnp_remove_card_device- removes a device from the specified card * @card: pointer to the card to remove from * @dev: pointer to the device to remove */ -void pnpc_remove_device(struct pnp_dev *dev) +void pnp_remove_card_device(struct pnp_dev * dev) { spin_lock(&pnp_lock); dev->card = NULL; @@ -182,20 +189,21 @@ /** * pnp_request_card_device - Searches for a PnP device under the specified card - * @card: pointer to the card to search under, cannot be NULL + * @lcard: pointer to the card link, cannot be NULL * @id: pointer to a PnP ID structure that explains the rules for finding the device * @from: Starting place to search from. If NULL it will start from the begining. - * - * Will activate the device */ -struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from) +struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from) { - struct list_head *pos; - struct pnp_dev *dev; - struct pnpc_driver *cdrv; - if (!card || !id) + struct list_head * pos; + struct pnp_dev * dev; + struct pnp_card_driver * drv; + struct pnp_card * card; + if (!clink || !id) goto done; + card = clink->card; + drv = clink->driver; if (!from) { pos = card->devices.next; } else { @@ -205,7 +213,7 @@ } while (pos != &card->devices) { dev = card_to_pnp_dev(pos); - if (compare_pnp_id(dev->id,id)) + if ((!dev->card_link) && compare_pnp_id(dev->id,id)) goto found; pos = pos->next; } @@ -214,168 +222,93 @@ return NULL; found: - if (pnp_device_attach(dev) < 0) - return NULL; - cdrv = to_pnpc_driver(card->dev.driver); - if (dev->active == 0) { - if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) { - if(pnp_activate_dev(dev)<0) { - pnp_device_detach(dev); - return NULL; - } + down_write(&dev->dev.bus->subsys.rwsem); + dev->card_link = clink; + dev->dev.driver = &drv->link.driver; + if (drv->link.driver.probe) { + if (drv->link.driver.probe(&dev->dev)) { + dev->dev.driver = NULL; + return NULL; } - } else { - if ((cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) - pnp_disable_dev(dev); } - spin_lock(&pnp_lock); - list_add_tail(&dev->rdev_list, &card->rdevs); - spin_unlock(&pnp_lock); + device_bind_driver(&dev->dev); + up_write(&dev->dev.bus->subsys.rwsem); + return dev; } /** * pnp_release_card_device - call this when the driver no longer needs the device * @dev: pointer to the PnP device stucture - * - * Will disable the device */ -void pnp_release_card_device(struct pnp_dev *dev) -{ - spin_lock(&pnp_lock); - list_del(&dev->rdev_list); - spin_unlock(&pnp_lock); - pnp_device_detach(dev); -} - -static void pnpc_recover_devices(struct pnp_card *card) -{ - struct list_head *pos, *temp; - list_for_each_safe(pos,temp,&card->rdevs){ - struct pnp_dev *dev = list_entry(pos, struct pnp_dev, rdev_list); - pnp_release_card_device(dev); - } -} - -int pnpc_attach(struct pnp_card *pnp_card) -{ - spin_lock(&pnp_lock); - if(pnp_card->status != PNP_READY){ - spin_unlock(&pnp_lock); - return -EBUSY; - } - pnp_card->status = PNP_ATTACHED; - spin_unlock(&pnp_lock); - return 0; -} - -void pnpc_detach(struct pnp_card *pnp_card) -{ - spin_lock(&pnp_lock); - if (pnp_card->status == PNP_ATTACHED) - pnp_card->status = PNP_READY; - spin_unlock(&pnp_lock); - pnpc_recover_devices(pnp_card); -} - -static int pnpc_card_probe(struct device *dev) -{ - int error = 0; - struct pnpc_driver *drv = to_pnpc_driver(dev->driver); - struct pnp_card *card = to_pnp_card(dev); - const struct pnp_card_id *card_id = NULL; - - pnp_dbg("pnp: match found with the PnP card '%s' and the driver '%s'", dev->bus_id,drv->name); - - error = pnpc_attach(card); - if (error < 0) - return error; - if (drv->probe) { - card_id = match_card(drv, card); - if (card_id != NULL) - error = drv->probe(card, card_id); - if (error >= 0){ - card->driver = drv; - error = 0; - } else - pnpc_detach(card); - } - return error; -} - -static int pnpc_card_remove(struct device *dev) +void pnp_release_card_device(struct pnp_dev * dev) { - struct pnp_card * card = to_pnp_card(dev); - struct pnpc_driver * drv = card->driver; - - if (drv) { - if (drv->remove) - drv->remove(card); - card->driver = NULL; - } - pnpc_detach(card); - return 0; + struct pnp_card_driver * drv = dev->card_link->driver; + if (!drv) + return; + down_write(&dev->dev.bus->subsys.rwsem); + drv->link.remove = &generic_card_remove; + device_release_driver(&dev->dev); + drv->link.remove = &generic_card_remove_first; + up_write(&dev->dev.bus->subsys.rwsem); } /** - * pnpc_register_driver - registers a PnP card driver with the PnP Layer - * @cdrv: pointer to the driver to register + * pnp_register_card_driver - registers a PnP card driver with the PnP Layer + * @drv: pointer to the driver to register */ -int pnpc_register_driver(struct pnpc_driver * drv) +int pnp_register_card_driver(struct pnp_card_driver * drv) { - int count; - struct list_head *pos; - - drv->driver.name = drv->name; - drv->driver.bus = &pnpc_bus_type; - drv->driver.probe = pnpc_card_probe; - drv->driver.remove = pnpc_card_remove; - - pnp_dbg("the card driver '%s' has been registered", drv->name); - - count = driver_register(&drv->driver); + int count = 0; + struct list_head *pos, *temp; - /* get the number of initial matches */ - if (count >= 0){ - count = 0; - list_for_each(pos,&drv->driver.devices){ - count++; + drv->link.name = drv->name; + drv->link.id_table = NULL; /* this will disable auto matching */ + drv->link.flags = drv->flags; + drv->link.probe = NULL; + drv->link.remove = &generic_card_remove_first; + + pnp_register_driver(&drv->link); + + list_for_each_safe(pos,temp,&pnp_cards){ + struct pnp_card *card = list_entry(pos, struct pnp_card, global_list); + const struct pnp_card_id *id = match_card(drv,card); + if (id) { + struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link)); + if (!clink) + continue; + clink->card = card; + clink->driver = drv; + if (drv->probe) { + if (drv->probe(clink, id)>=0) + count++; + } else + count++; } } return count; } /** - * pnpc_unregister_driver - unregisters a PnP card driver from the PnP Layer - * @cdrv: pointer to the driver to unregister - * - * Automatically disables requested devices + * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer + * @drv: pointer to the driver to unregister */ -void pnpc_unregister_driver(struct pnpc_driver *drv) +void pnp_unregister_card_driver(struct pnp_card_driver * drv) { - driver_unregister(&drv->driver); - pnp_dbg("the card driver '%s' has been unregistered", drv->name); -} + pnp_unregister_driver(&drv->link); -static int __init pnp_card_init(void) -{ - printk(KERN_INFO "pnp: Enabling Plug and Play Card Services.\n"); - return bus_register(&pnpc_bus_type); + pnp_dbg("the card driver '%s' has been unregistered", drv->name); } -subsys_initcall(pnp_card_init); - -EXPORT_SYMBOL(pnpc_add_card); -EXPORT_SYMBOL(pnpc_remove_card); -EXPORT_SYMBOL(pnpc_add_device); -EXPORT_SYMBOL(pnpc_remove_device); +EXPORT_SYMBOL(pnp_add_card); +EXPORT_SYMBOL(pnp_remove_card); +EXPORT_SYMBOL(pnp_add_card_device); +EXPORT_SYMBOL(pnp_remove_card_device); +EXPORT_SYMBOL(pnp_add_card_id); EXPORT_SYMBOL(pnp_request_card_device); EXPORT_SYMBOL(pnp_release_card_device); -EXPORT_SYMBOL(pnpc_register_driver); -EXPORT_SYMBOL(pnpc_unregister_driver); -EXPORT_SYMBOL(pnpc_add_id); -EXPORT_SYMBOL(pnpc_attach); -EXPORT_SYMBOL(pnpc_detach); +EXPORT_SYMBOL(pnp_register_card_driver); +EXPORT_SYMBOL(pnp_unregister_card_driver); diff -Nru a/drivers/pnp/driver.c b/drivers/pnp/driver.c --- a/drivers/pnp/driver.c Wed Feb 19 09:54:46 2003 +++ b/drivers/pnp/driver.c Sun Mar 9 15:44:14 2003 @@ -53,12 +53,11 @@ static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct pnp_dev *dev) { const struct pnp_device_id *drv_id = drv->id_table; - if (!drv) + if (!drv_id) return NULL; - if (!dev) - return NULL; - while (*drv_id->id){ - if (compare_pnp_id(dev->id,drv_id->id)) + + while (*drv_id->id) { + if (compare_pnp_id(dev->id, drv_id->id)) return drv_id; drv_id++; } @@ -102,14 +101,19 @@ return error; if (pnp_dev->active == 0) { - if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) { + if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { error = pnp_activate_dev(pnp_dev); if (error < 0) return error; } + } else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE) + == PNP_DRIVER_RES_DISABLE) { + error = pnp_disable_dev(pnp_dev); + if (error < 0) + return error; } error = 0; - if (pnp_drv->probe && pnp_dev->active) { + if (pnp_drv->probe) { dev_id = match_device(pnp_drv, pnp_dev); if (dev_id != NULL) error = pnp_drv->probe(pnp_dev, dev_id); @@ -117,9 +121,8 @@ if (error >= 0){ pnp_dev->driver = pnp_drv; error = 0; - } - else - goto fail; + } else + goto fail; return error; fail: diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c --- a/drivers/pnp/interface.c Tue Mar 4 09:12:57 2003 +++ b/drivers/pnp/interface.c Sun Mar 9 15:17:52 2003 @@ -332,11 +332,18 @@ buffer->buffer = buf; buffer->curr = buffer->buffer; + pnp_printf(buffer,"mode = "); + if (dev->config_mode & PNP_CONFIG_MANUAL) + pnp_printf(buffer,"manual\n"); + else + pnp_printf(buffer,"auto\n"); + pnp_printf(buffer,"state = "); if (dev->active) pnp_printf(buffer,"active\n"); else pnp_printf(buffer,"disabled\n"); + for (i = 0; i < PNP_MAX_PORT; i++) { if (pnp_port_valid(dev, i)) { pnp_printf(buffer,"io"); @@ -402,13 +409,13 @@ retval = pnp_activate_dev(dev); goto done; } - if (!strnicmp(buf,"auto-config",11)) { + if (!strnicmp(buf,"auto",4)) { if (dev->active) goto done; retval = pnp_auto_config_dev(dev); goto done; } - if (!strnicmp(buf,"clear-config",12)) { + if (!strnicmp(buf,"clear",5)) { if (dev->active) goto done; spin_lock(&pnp_lock); diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c --- a/drivers/pnp/isapnp/core.c Wed Feb 19 09:54:46 2003 +++ b/drivers/pnp/isapnp/core.c Sun Mar 9 15:37:55 2003 @@ -626,7 +626,7 @@ isapnp_peek(name, size1); name[size1] = '\0'; *size -= size1; - + /* clean whitespace from end of string */ while (size1 > 0 && name[--size1] == ' ') name[size1] = '\0'; @@ -647,7 +647,7 @@ return 1; if (pnp_build_resource(dev, 0) == NULL) return 1; - pnpc_add_device(card,dev); + pnp_add_card_device(card,dev); while (1) { if (isapnp_read_tag(&type, &size)<0) return 1; @@ -659,7 +659,7 @@ if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; pnp_build_resource(dev,0); - pnpc_add_device(card,dev); + pnp_add_card_device(card,dev); size = 0; skip = 0; } else { @@ -852,7 +852,7 @@ device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); - pnpc_add_id(id,card); + pnp_add_card_id(id,card); } @@ -962,7 +962,7 @@ isapnp_parse_current_resources(dev, &dev->res); } - pnpc_add_card(card); + pnp_add_card(card); } isapnp_wait(); return 0; diff -Nru a/drivers/pnp/manager.c b/drivers/pnp/manager.c --- a/drivers/pnp/manager.c Sat Feb 22 13:40:31 2003 +++ b/drivers/pnp/manager.c Thu Mar 6 13:50:22 2003 @@ -532,6 +532,39 @@ return error; } +static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struct pnp_resource_table * ntab) +{ + int idx; + for (idx = 0; idx < PNP_MAX_IRQ; idx++) { + if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->irq_resource[idx].start = ntab->irq_resource[idx].start; + ctab->irq_resource[idx].end = ntab->irq_resource[idx].end; + ctab->irq_resource[idx].flags = ntab->irq_resource[idx].flags; + } + for (idx = 0; idx < PNP_MAX_DMA; idx++) { + if (ntab->dma_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->dma_resource[idx].start = ntab->dma_resource[idx].start; + ctab->dma_resource[idx].end = ntab->dma_resource[idx].end; + ctab->dma_resource[idx].flags = ntab->dma_resource[idx].flags; + } + for (idx = 0; idx < PNP_MAX_PORT; idx++) { + if (ntab->port_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->port_resource[idx].start = ntab->port_resource[idx].start; + ctab->port_resource[idx].end = ntab->port_resource[idx].end; + ctab->port_resource[idx].flags = ntab->port_resource[idx].flags; + } + for (idx = 0; idx < PNP_MAX_MEM; idx++) { + if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->irq_resource[idx].start = ntab->mem_resource[idx].start; + ctab->irq_resource[idx].end = ntab->mem_resource[idx].end; + ctab->irq_resource[idx].flags = ntab->mem_resource[idx].flags; + } +} + /** * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table * @dev: pointer to the desired device @@ -554,7 +587,7 @@ *bak = dev->res; spin_lock(&pnp_lock); - dev->res = *res; + pnp_process_manual_resources(&dev->res, res); if (!(mode & PNP_CONFIG_FORCE)) { for (i = 0; i < PNP_MAX_PORT; i++) { if(pnp_check_port(dev,i)) @@ -681,7 +714,7 @@ return -1; } dev->active = 0; /* just in case the protocol doesn't do this */ - pnp_dbg("the device '%s' has been disabled.", dev->dev.bus_id); + pnp_dbg("res: the device '%s' has been disabled.", dev->dev.bus_id); return 0; } diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c --- a/drivers/pnp/resource.c Sat Feb 22 13:40:31 2003 +++ b/drivers/pnp/resource.c Thu Mar 6 13:50:22 2003 @@ -558,25 +558,25 @@ table->irq_resource[idx].name = NULL; table->irq_resource[idx].start = -1; table->irq_resource[idx].end = -1; - table->irq_resource[idx].flags = 0; + table->irq_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_DMA; idx++) { table->dma_resource[idx].name = NULL; table->dma_resource[idx].start = -1; table->dma_resource[idx].end = -1; - table->dma_resource[idx].flags = 0; + table->dma_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_PORT; idx++) { table->port_resource[idx].name = NULL; table->port_resource[idx].start = 0; table->port_resource[idx].end = 0; - table->port_resource[idx].flags = 0; + table->port_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_MEM; idx++) { table->mem_resource[idx].name = NULL; table->mem_resource[idx].start = 0; table->mem_resource[idx].end = 0; - table->mem_resource[idx].flags = 0; + table->mem_resource[idx].flags = IORESOURCE_AUTO; } } diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c --- a/drivers/pnp/system.c Wed Feb 19 09:54:46 2003 +++ b/drivers/pnp/system.c Sun Mar 9 15:44:14 2003 @@ -93,8 +93,8 @@ static struct pnp_driver system_pnp_driver = { .name = "system", - .flags = PNP_DRIVER_DO_NOT_ACTIVATE, .id_table = pnp_dev_table, + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, .probe = system_pnp_probe, .remove = NULL, }; diff -Nru a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c --- a/drivers/s390/block/dasd_3990_erp.c Mon Feb 24 10:29:29 2003 +++ b/drivers/s390/block/dasd_3990_erp.c Thu Mar 6 09:25:58 2003 @@ -2445,7 +2445,7 @@ * - exit with permanent error * * PARAMETER - * erp ERP which is in progress wiht no retry left + * erp ERP which is in progress with no retry left * * RETURN VALUES * erp modified/additional ERP diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c --- a/drivers/s390/block/dasd_genhd.c Fri Dec 6 11:37:54 2002 +++ b/drivers/s390/block/dasd_genhd.c Sat Mar 8 14:50:22 2003 @@ -60,11 +60,8 @@ } /* Register block device. */ - new_major = register_blkdev(major, "dasd", &dasd_device_operations); + new_major = register_blkdev(major, "dasd"); if (new_major < 0) { - MESSAGE(KERN_WARNING, - "Cannot register to major no %d, rc = %d", - major, new_major); kfree(mi); return new_major; } diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Tue Dec 3 09:21:05 2002 +++ b/drivers/s390/block/xpram.c Sat Mar 8 14:50:22 2003 @@ -430,13 +430,11 @@ /* * Register xpram major. */ - rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME, &xpram_devops); - if (rc < 0) { - PRINT_ERR("Can't get xpram major %d\n", XPRAM_MAJOR); + rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME); + if (rc < 0) goto out; - } - devfs_mk_dir (NULL, "slram", NULL); + devfs_mk_dir(NULL, "slram", NULL); /* * Assign the other needed values: make request function, sizes and @@ -452,6 +450,7 @@ for (i = 0; i < xpram_devs; i++) { struct gendisk *disk = xpram_disks[i]; char name[16]; + xpram_devices[i].size = xpram_sizes[i] / 4; xpram_devices[i].offset = offset; offset += xpram_devices[i].size; diff -Nru a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c --- a/drivers/s390/char/con3215.c Tue Feb 25 10:27:52 2003 +++ b/drivers/s390/char/con3215.c Thu Mar 6 09:25:58 2003 @@ -862,7 +862,7 @@ spin_unlock_irqrestore(raw->lock, flags); } -static int __init +static int __init con3215_consetup(struct console *co, char *options) { return 0; @@ -884,7 +884,7 @@ * 3215 console initialization code called from console_init(). * NOTE: This is called before kmalloc is available. */ -void __init +static void __init con3215_init(void) { struct ccw_device *cdev; @@ -1122,6 +1122,7 @@ spin_unlock_irqrestore(raw->lock, flags); } } +console_initcall(con3215_init); /* * Disable writing to a 3215 tty diff -Nru a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c --- a/drivers/s390/char/sclp_con.c Thu Dec 12 10:03:31 2002 +++ b/drivers/s390/char/sclp_con.c Fri Feb 14 15:23:21 2003 @@ -237,3 +237,5 @@ /* enable printk-access to this driver */ register_console(&sclp_console); } + +console_initcall(sclp_console_init); diff -Nru a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c --- a/drivers/s390/char/sclp_tty.c Thu Feb 6 07:33:47 2003 +++ b/drivers/s390/char/sclp_tty.c Fri Feb 14 15:23:21 2003 @@ -797,3 +797,6 @@ if (tty_register_driver(&sclp_tty_driver)) panic("Couldn't register sclp_tty driver\n"); } + +console_initcall(sclp_tty_init); + diff -Nru a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c --- a/drivers/s390/char/tape_block.c Fri Dec 6 16:20:07 2002 +++ b/drivers/s390/char/tape_block.c Sat Mar 8 14:50:22 2003 @@ -333,12 +333,10 @@ int rc; /* Register the tape major number to the kernel */ - rc = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops); - if (rc < 0) { - PRINT_ERR("can't get major %d for block device\n", - tapeblock_major); + rc = register_blkdev(tapeblock_major, "tBLK"); + if (rc < 0) return rc; - } + if (tapeblock_major == 0) tapeblock_major = rc; PRINT_INFO("tape gets major %d for block device\n", tapeblock_major); diff -Nru a/drivers/s390/char/tuball.c b/drivers/s390/char/tuball.c --- a/drivers/s390/char/tuball.c Wed Oct 9 07:01:46 2002 +++ b/drivers/s390/char/tuball.c Fri Feb 14 15:24:00 2003 @@ -131,7 +131,7 @@ #else #define tub3270_con_devno console_device -void __init tub3270_con_init(void) +static void __init tub3270_con_init(void) { tub3270_con_bcb.bc_len = 65536; if (!CONSOLE_IS_3270) @@ -140,6 +140,8 @@ tub3270_con_bcb.bc_len); register_console(&tub3270_con); } +console_initcall(tub3270_con_init); + #endif static kdev_t diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c --- a/drivers/sbus/char/jsflash.c Mon Oct 28 11:57:56 2002 +++ b/drivers/sbus/char/jsflash.c Sat Mar 8 14:50:22 2003 @@ -570,9 +570,7 @@ jsfd_disk[i] = disk; } - if (register_blkdev(JSFD_MAJOR, "jsfd", &jsfd_fops)) { - printk("jsfd_init: unable to get major number %d\n", - JSFD_MAJOR); + if (register_blkdev(JSFD_MAJOR, "jsfd")) { err = -EIO; goto out; } diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig Tue Feb 18 01:04:49 2003 +++ b/drivers/scsi/Kconfig Wed Mar 5 23:02:07 2003 @@ -946,16 +946,6 @@ Please read for more information. -config SCSI_ZALON - tristate "Zalon SCSI support" - depends on GSC && SCSI - help - The Zalon is a GSC/HSC bus interface chip that sits between the - PA-RISC processor and the NCR 53c720 SCSI controller on C100, - C110, J200, J210 and some D, K & R-class machines. It's also - used on the add-in Bluefish, Barracuda & Shrike SCSI cards. - Say Y here if you have one of these machines or cards. - config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE int "DMA addressing mode" depends on SCSI_SYM53C8XX_2 @@ -1010,9 +1000,19 @@ If you say Y here, the driver will preferently use normal IO rather than memory mapped IO. +config SCSI_ZALON + tristate "Zalon SCSI support" + depends on GSC && SCSI + help + The Zalon is a GSC/HSC bus interface chip that sits between the + PA-RISC processor and the NCR 53c720 SCSI controller on C100, + C110, J200, J210 and some D, K & R-class machines. It's also + used on the add-in Bluefish, Barracuda & Shrike SCSI cards. + Say Y here if you have one of these machines or cards. + config SCSI_NCR53C8XX tristate "NCR53C8XX SCSI support" - depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI + depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI_ZALON!=y && SCSI ---help--- This is the BSD ncr driver adapted to Linux for the NCR53C8XX family of PCI-SCSI controllers. This driver supports parity checking, diff -Nru a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile --- a/drivers/scsi/aic7xxx/aicasm/Makefile Tue Dec 10 11:02:52 2002 +++ b/drivers/scsi/aic7xxx/aicasm/Makefile Thu Feb 20 08:39:57 2003 @@ -10,9 +10,10 @@ GENSRCS= $(YSRCS:.y=.c) $(LSRCS:.l=.c) SRCS= ${CSRCS} ${GENSRCS} +LIBS= -ldb CLEANFILES= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) # Override default kernel CFLAGS. This is a userland app. -AICASM_CFLAGS:= -I/usr/include -I. -ldb +AICASM_CFLAGS:= -I/usr/include -I. YFLAGS= -d NOMAN= noman @@ -30,7 +31,7 @@ endif $(PROG): ${GENHDRS} $(SRCS) - $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) + $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS) aicdb.h: @if [ -e "/usr/include/db3/db_185.h" ]; then \ @@ -45,8 +46,9 @@ echo "*** Install db development libraries"; \ fi +clean-files := $(CLEANFILES) $(PROG) clean: - rm -f $(CLEANFILES) $(PROG) + rm -f $(clean-files) aicasm_gram.c aicasm_gram.h: aicasm_gram.y $(YACC) $(YFLAGS) -b $(<:.y=) $< diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c --- a/drivers/scsi/fdomain.c Thu Feb 20 04:16:32 2003 +++ b/drivers/scsi/fdomain.c Thu Feb 27 09:39:04 2003 @@ -271,13 +271,8 @@ **************************************************************************/ +#include #include - -#ifdef PCMCIA -#undef MODULE -#endif - -#include /* for CONFIG_PCI */ #include #include #include @@ -295,9 +290,13 @@ #include "scsi.h" #include "hosts.h" -#include "fdomain.h" + +MODULE_AUTHOR("Rickard E. Faith"); +MODULE_DESCRIPTION("Future domain SCSI driver"); +MODULE_LICENSE("GPL"); + -#define VERSION "$Revision: 5.50 $" +#define VERSION "$Revision: 5.51 $" /* START OF USER DEFINABLE OPTIONS */ @@ -421,15 +420,12 @@ static void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs ); +int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt); -#ifdef MODULE - /* Allow insmod parameters to be like LILO - parameters. For example: - insmod fdomain fdomain=0x140,11 - */ +/* Allow insmod parameters to be like LILO parameters. For example: + insmod fdomain fdomain=0x140,11 */ static char * fdomain = NULL; MODULE_PARM(fdomain, "s"); -#endif static unsigned long addresses[] = { 0xc8000, @@ -561,7 +557,7 @@ printk( "\n" ); } -static int __init fdomain_setup(char *str) +int __init fdomain_setup(char *str) { int ints[4]; @@ -862,7 +858,7 @@ } #endif -static int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) +struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt ) { int retcode; struct Scsi_Host *shpnt; @@ -879,13 +875,6 @@ unsigned char buf[buflen]; #endif - tpnt->proc_name = "fdomain"; - -#ifdef MODULE - if (fdomain) - fdomain_setup(fdomain); -#endif - if (setup_called) { #if DEBUG_DETECT printk( "scsi: No BIOS, using port_base = 0x%x, irq = %d\n", @@ -895,7 +884,7 @@ printk( "scsi: Cannot locate chip at port base 0x%x\n", port_base ); printk( "scsi: Bad LILO/INSMOD parameters?\n" ); - return 0; + return NULL; } } else { int flag = 0; @@ -910,7 +899,7 @@ if (!flag) { printk( "scsi: Detection failed (no card)\n" ); - return 0; + return NULL; } } } @@ -936,7 +925,7 @@ if (setup_called) { printk(KERN_ERR "scsi: Bad LILO/INSMOD parameters?\n"); } - return 0; + return NULL; } if (this_id) { @@ -957,7 +946,7 @@ shpnt = scsi_register( tpnt, 0 ); if(shpnt == NULL) - return 0; + return NULL; shpnt->irq = interrupt_level; shpnt->io_port = port_base; scsi_set_device(shpnt, &pdev->dev); @@ -967,7 +956,7 @@ /* Log IRQ with kernel */ if (!interrupt_level) { printk(KERN_ERR "scsi: Card Detected, but driver not loaded (no IRQ)\n" ); - return 0; + return NULL; } else { /* Register the IRQ with the kernel */ @@ -988,7 +977,7 @@ printk(KERN_ERR " Send mail to faith@acm.org\n" ); } printk(KERN_ERR "scsi: Detected, but driver not loaded (IRQ)\n" ); - return 0; + return NULL; } } @@ -1048,7 +1037,14 @@ } #endif - return 1; /* Maximum of one adapter will be detected. */ + return shpnt; +} + +static int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) +{ + if (fdomain) + fdomain_setup(fdomain); + return (__fdomain_16x0_detect(tpnt) != NULL); } static const char *fdomain_16x0_info( struct Scsi_Host *ignore ) @@ -1150,8 +1146,9 @@ { int status; unsigned long timeout; +#if ERRORS_ONLY static int flag = 0; - +#endif outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port ); @@ -1574,6 +1571,7 @@ /* End of code derived from Tommy Thorn's work. */ +#if DEBUG_ABORT static void print_info(Scsi_Cmnd *SCpnt) { unsigned int imr; @@ -1643,6 +1641,7 @@ printk( "Configuration 2 = 0x%02x\n", inb( port_base + Configuration2 ) ); } +#endif static int fdomain_16x0_abort( Scsi_Cmnd *SCpnt) { @@ -1670,7 +1669,7 @@ return SUCCESS; } -static int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt) +int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt) { outb( 1, SCSI_Cntl_port ); do_pause( 2 ); @@ -1866,9 +1865,29 @@ return 0; } -MODULE_LICENSE("GPL"); - -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = FDOMAIN_16X0; +Scsi_Host_Template fdomain_driver_template = { + .module = THIS_MODULE, + .name = "fdomain", + .proc_name = "fdomain", + .proc_info = fdomain_16x0_proc_info, + .detect = fdomain_16x0_detect, + .info = fdomain_16x0_info, + .command = fdomain_16x0_command, + .queuecommand = fdomain_16x0_queue, + .eh_abort_handler = fdomain_16x0_abort, + .eh_bus_reset_handler = fdomain_16x0_bus_reset, + .eh_device_reset_handler = fdomain_16x0_device_reset, + .eh_host_reset_handler = fdomain_16x0_host_reset, + .bios_param = fdomain_16x0_biosparam, + .release = fdomain_16x0_release, + .can_queue = 1, + .this_id = 6, + .sg_tablesize = 64, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; +#ifndef PCMCIA +#define driver_template fdomain_driver_template #include "scsi_module.c" +#endif diff -Nru a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h --- a/drivers/scsi/fdomain.h Tue Dec 10 12:28:33 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,59 +0,0 @@ -/* fdomain.h -- Header for Future Domain TMC-16x0 driver - * Created: Sun May 3 18:47:33 1992 by faith@cs.unc.edu - * Revised: Thu Oct 12 13:21:35 1995 by faith@acm.org - * Author: Rickard E. Faith, faith@cs.unc.edu - * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith - * - * $Id: fdomain.h,v 5.12 1995/10/12 19:01:09 root Exp $ - - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - - */ - -#ifndef _FDOMAIN_H -#define _FDOMAIN_H - -static int fdomain_16x0_detect( Scsi_Host_Template *); -static int fdomain_16x0_command( Scsi_Cmnd *); -static int fdomain_16x0_abort(Scsi_Cmnd *); -static const char *fdomain_16x0_info(struct Scsi_Host *); -static int fdomain_16x0_bus_reset(Scsi_Cmnd *); -static int fdomain_16x0_host_reset(Scsi_Cmnd *); -static int fdomain_16x0_device_reset(Scsi_Cmnd *); -static int fdomain_16x0_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -static int fdomain_16x0_biosparam(struct scsi_device *, - struct block_device *, sector_t, int * ); -static int fdomain_16x0_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout ); -static int fdomain_16x0_release(struct Scsi_Host *shpnt); - -#define FDOMAIN_16X0 { .proc_info = fdomain_16x0_proc_info, \ - .detect = fdomain_16x0_detect, \ - .info = fdomain_16x0_info, \ - .command = fdomain_16x0_command, \ - .queuecommand = fdomain_16x0_queue, \ - .eh_abort_handler = fdomain_16x0_abort, \ - .eh_bus_reset_handler = fdomain_16x0_bus_reset, \ - .eh_device_reset_handler = fdomain_16x0_device_reset, \ - .eh_host_reset_handler = fdomain_16x0_host_reset, \ - .bios_param = fdomain_16x0_biosparam, \ - .release = fdomain_16x0_release, \ - .can_queue = 1, \ - .this_id = 6, \ - .sg_tablesize = 64, \ - .cmd_per_lun = 1, \ - .use_clustering = DISABLE_CLUSTERING \ -} -#endif diff -Nru a/drivers/scsi/i91uscsi.h b/drivers/scsi/i91uscsi.h --- a/drivers/scsi/i91uscsi.h Mon Feb 4 23:52:37 2002 +++ b/drivers/scsi/i91uscsi.h Sun Feb 16 16:20:08 2003 @@ -70,12 +70,6 @@ #ifndef NULL #define NULL 0 /* zero */ #endif -#ifndef TRUE -#define TRUE (1) /* boolean true */ -#endif -#ifndef FALSE -#define FALSE (0) /* boolean false */ -#endif #ifndef FAILURE #define FAILURE (-1) #endif @@ -597,11 +591,9 @@ TCS HCS_Tcs[MAX_TARGETS]; /* 78 */ ULONG pSRB_head; /* SRB save queue header */ ULONG pSRB_tail; /* SRB save queue tail */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spinlock_t HCS_AvailLock; spinlock_t HCS_SemaphLock; spinlock_t pSRB_lock; /* SRB queue lock */ -#endif } HCS; /* Bit Definition for HCB_Config */ diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c --- a/drivers/scsi/imm.c Mon Feb 17 17:02:24 2003 +++ b/drivers/scsi/imm.c Thu Mar 6 15:50:31 2003 @@ -174,6 +174,7 @@ parport_unregister_device(imm_hosts[i].dev); continue; } + /* now the glue ... */ switch (imm_hosts[i].mode) { case IMM_NIBBLE: @@ -218,7 +219,7 @@ /* This is to give the imm driver a way to modify the timings (and other * parameters) by writing to the /proc/scsi/imm/0 file. - * Very simple method really... (To simple, no error checking :( ) + * Very simple method really... (Too simple, no error checking :( ) * Reason: Kernel hackers HATE having to unload and reload modules for * testing... * Also gives a method to use a script to obtain optimum timings (TODO) @@ -948,7 +949,7 @@ unsigned char l = 0, h = 0; int retv, x; - /* First check for any errors that may of occurred + /* First check for any errors that may have occurred * Here we check for internal errors */ if (tmp->failed) diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c --- a/drivers/scsi/inia100.c Fri Jan 3 10:58:49 2003 +++ b/drivers/scsi/inia100.c Sun Feb 16 16:18:17 2003 @@ -67,12 +67,6 @@ * - Fix allocation of scsi host structs and private data **************************************************************************/ -#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S) - -#ifndef LINUX_VERSION_CODE -#include -#endif - #include #include diff -Nru a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h --- a/drivers/scsi/inia100.h Tue Dec 10 12:28:32 2002 +++ b/drivers/scsi/inia100.h Sun Feb 16 16:18:17 2003 @@ -63,14 +63,6 @@ * merged them into a single header used by both .c files. ****************************************************************************/ -#ifndef CVT_LINUX_VERSION -#define CVT_LINUX_VERSION(V,P,S) (((V) * 65536) + ((P) * 256) + (S)) -#endif - -#ifndef LINUX_VERSION_CODE -#include -#endif - #include #include #include @@ -116,12 +108,6 @@ #ifndef NULL #define NULL 0 /* zero */ -#endif -#ifndef TRUE -#define TRUE (1) /* boolean true */ -#endif -#ifndef FALSE -#define FALSE (0) /* boolean false */ #endif #ifndef FAILURE #define FAILURE (-1) diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c --- a/drivers/scsi/ncr53c8xx.c Tue Feb 25 02:46:22 2003 +++ b/drivers/scsi/ncr53c8xx.c Wed Mar 5 23:02:17 2003 @@ -5024,7 +5024,6 @@ **========================================================== */ -#ifdef MODULE static int ncr_detach(ncb_p np) { ccb_p cp; @@ -5160,7 +5159,6 @@ return 1; } -#endif /*========================================================== ** @@ -8935,7 +8933,6 @@ } -#ifdef MODULE int ncr53c8xx_release(struct Scsi_Host *host) { #ifdef DEBUG_NCR53C8XX @@ -8945,7 +8942,6 @@ return 1; } -#endif /* diff -Nru a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h --- a/drivers/scsi/ncr53c8xx.h Tue Dec 10 12:28:33 2002 +++ b/drivers/scsi/ncr53c8xx.h Mon Feb 17 12:02:10 2003 @@ -60,17 +60,12 @@ int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int); int ncr53c8xx_slave_configure(Scsi_Device *); - -#ifdef MODULE int ncr53c8xx_release(struct Scsi_Host *); -#else -#define ncr53c8xx_release NULL -#endif #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75) -#define NCR53C8XX { .name = "", \ +#define NCR53C8XX { .name = "ncr53c8xx", \ .detect = ncr53c8xx_detect, \ .release = ncr53c8xx_release, \ .info = ncr53c8xx_info, \ diff -Nru a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig --- a/drivers/scsi/pcmcia/Kconfig Sun Feb 9 17:29:49 2003 +++ b/drivers/scsi/pcmcia/Kconfig Thu Feb 27 08:33:17 2003 @@ -3,22 +3,11 @@ # menu "PCMCIA SCSI adapter support" - depends on SCSI!=n && HOTPLUG && PCMCIA!=n - -config SCSI_PCMCIA - bool "PCMCIA SCSI adapter support" - help - Say Y here if you intend to attach a PCMCIA or CardBus card to your - computer which acts as a SCSI host adapter. These are credit card - size devices often used with laptops. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions PCMCIA SCSI host adapters. + depends on SCSI!=n && PCMCIA!=n config PCMCIA_AHA152X tristate "Adaptec AHA152X PCMCIA support" - depends on SCSI_PCMCIA && m + depends on m help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -30,7 +19,7 @@ config PCMCIA_FDOMAIN tristate "Future Domain PCMCIA support" - depends on SCSI_PCMCIA && m + depends on m help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -42,7 +31,7 @@ config PCMCIA_NINJA_SCSI tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support" - depends on SCSI_PCMCIA && m + depends on m help If you intend to attach this type of PCMCIA SCSI host adapter to your computer, say Y here and read @@ -55,7 +44,7 @@ config PCMCIA_QLOGIC tristate "Qlogic PCMCIA support" - depends on SCSI_PCMCIA && m + depends on m help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -65,10 +54,4 @@ whenever you want). If you want to compile it as a module, say M here and read . -config PCMCIA_SCSICARD - bool - depends on PCMCIA_QLOGIC=y || PCMCIA_AHA152X=y || PCMCIA_FDOMAIN=y || PCMCIA_NINJA_SCSI=y - default y - endmenu - diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c --- a/drivers/scsi/pcmcia/fdomain_stub.c Tue Feb 4 12:12:27 2003 +++ b/drivers/scsi/pcmcia/fdomain_stub.c Thu Feb 27 09:35:58 2003 @@ -61,15 +61,15 @@ MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver"); MODULE_LICENSE("Dual MPL/GPL"); -#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") - /* Bit map of interrupts to choose from */ -INT_MODULE_PARM(irq_mask, 0xdeb8); +static int irq_mask = 0xdeb8; +MODULE_PARM(irq_mask, "i"); static int irq_list[4] = { -1 }; MODULE_PARM(irq_list, "1-4i"); #ifdef PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = "fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)"; @@ -81,11 +81,15 @@ typedef struct scsi_info_t { dev_link_t link; + struct Scsi_Host *host; int ndev; dev_node_t node[8]; } scsi_info_t; +extern Scsi_Host_Template fdomain_driver_template; extern void fdomain_setup(char *str, int *ints); +extern struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt ); +extern int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt); static void fdomain_release(u_long arg); static int fdomain_event(event_t event, int priority, @@ -94,8 +98,6 @@ static dev_link_t *fdomain_attach(void); static void fdomain_detach(dev_link_t *); -#define driver_template fdomain_driver_template -extern Scsi_Host_Template fdomain_driver_template; static dev_link_t *dev_list = NULL; @@ -231,7 +233,6 @@ link->conf.ConfigBase = parse.config.base; /* Configure card */ - driver_template.module = &__this_module; link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; @@ -260,14 +261,18 @@ sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ); fdomain_setup(str, ints); - scsi_register_host(&driver_template); + host = __fdomain_16x0_detect(&fdomain_driver_template); + if (!host) { + printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); + goto cs_failed; + } + + scsi_add_host(host, NULL); tail = &link->dev; info->ndev = 0; - for (host = scsi_host_get_next(NULL); host; - host = scsi_host_get_next(host)) - if (host->hostt == &driver_template) - list_for_each_entry (dev, &host->my_devices, siblings) { + + list_for_each_entry (dev, &host->my_devices, siblings) { u_long arg[2], id; kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + @@ -296,10 +301,11 @@ } *tail = node; tail = &node->next; info->ndev++; - } + + } + *tail = NULL; - if (info->ndev == 0) - printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); + info->host = host; link->state &= ~DEV_CONFIG_PENDING; return; @@ -316,30 +322,22 @@ static void fdomain_release(u_long arg) { dev_link_t *link = (dev_link_t *)arg; + scsi_info_t *info = link->priv; DEBUG(0, "fdomain_release(0x%p)\n", link); -#warning This does not protect you. You need some real fix for your races. -#if 0 - if (GET_USE_COUNT(&__this_module) != 0) { - DEBUG(1, "fdomain_cs: release postponed, " - "device still open\n"); - link->state |= DEV_STALE_CONFIG; - return; - } -#endif - - scsi_unregister_host(&driver_template); + scsi_remove_host(info->host); link->dev = NULL; CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); - + + scsi_unregister(info->host); + link->state &= ~DEV_CONFIG; if (link->state & DEV_STALE_LINK) fdomain_detach(link); - } /* fdomain_release */ /*====================================================================*/ @@ -374,7 +372,7 @@ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) { CardServices(RequestConfiguration, link->handle, &link->conf); - fdomain_16x0_reset(NULL, 0); + fdomain_16x0_bus_reset(NULL); } break; } diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c --- a/drivers/scsi/pcmcia/qlogic_stub.c Mon Feb 3 23:47:00 2003 +++ b/drivers/scsi/pcmcia/qlogic_stub.c Thu Feb 27 09:12:48 2003 @@ -55,7 +55,11 @@ #include #include + +extern Scsi_Host_Template qlogicfas_driver_template; extern void qlogicfas_preset(int port, int irq); +extern struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *); +extern int qlogicfas_bus_reset(Scsi_Cmnd *); #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; @@ -81,6 +85,7 @@ typedef struct scsi_info_t { dev_link_t link; + struct Scsi_Host *host; unsigned short manf_id; int ndev; dev_node_t node[8]; @@ -92,9 +97,6 @@ static dev_link_t *qlogic_attach(void); static void qlogic_detach(dev_link_t *); -/* Import our driver template */ -extern Scsi_Host_Template qlogicfas_driver_template; -#define driver_template qlogicfas_driver_template static dev_link_t *dev_list = NULL; @@ -233,7 +235,6 @@ info->manf_id = le16_to_cpu(tuple.TupleData[0]); /* Configure card */ - driver_template.module = &__this_module; link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; @@ -272,46 +273,52 @@ else qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ); - scsi_register_host(&driver_template); - tail = &link->dev; info->ndev = 0; - for (host = scsi_host_get_next(NULL); host; host = scsi_host_get_next(host)) - if (host->hostt == &driver_template) - list_for_each_entry (dev, &host->my_devices, siblings) { - u_long arg[2], id; - kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); - id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000); - node = &info->node[info->ndev]; - node->minor = 0; - switch (dev->type) { - case TYPE_TAPE: - node->major = SCSI_TAPE_MAJOR; - sprintf(node->dev_name, "st#%04lx", id); - break; - case TYPE_DISK: - case TYPE_MOD: - node->major = SCSI_DISK0_MAJOR; - sprintf(node->dev_name, "sd#%04lx", id); - break; - case TYPE_ROM: - case TYPE_WORM: - node->major = SCSI_CDROM_MAJOR; - sprintf(node->dev_name, "sr#%04lx", id); - break; - default: - node->major = SCSI_GENERIC_MAJOR; - sprintf(node->dev_name, "sg#%04lx", id); - break; - } - *tail = node; - tail = &node->next; - info->ndev++; - } - *tail = NULL; - if (info->ndev == 0) + + host = __qlogicfas_detect(&qlogicfas_driver_template); + if (!host) { printk(KERN_INFO "qlogic_cs: no SCSI devices found\n"); + goto out; + } + + scsi_add_host(host, NULL); + + list_for_each_entry(dev, &host->my_devices, siblings) { + u_long arg[2], id; + kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); + id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000); + node = &info->node[info->ndev]; + node->minor = 0; + switch (dev->type) { + case TYPE_TAPE: + node->major = SCSI_TAPE_MAJOR; + sprintf(node->dev_name, "st#%04lx", id); + break; + case TYPE_DISK: + case TYPE_MOD: + node->major = SCSI_DISK0_MAJOR; + sprintf(node->dev_name, "sd#%04lx", id); + break; + case TYPE_ROM: + case TYPE_WORM: + node->major = SCSI_CDROM_MAJOR; + sprintf(node->dev_name, "sr#%04lx", id); + break; + default: + node->major = SCSI_GENERIC_MAJOR; + sprintf(node->dev_name, "sg#%04lx", id); + break; + } + *tail = node; + tail = &node->next; + info->ndev++; + } + *tail = NULL; + info->host = host; + +out: link->state &= ~DEV_CONFIG_PENDING; return; @@ -327,29 +334,22 @@ static void qlogic_release(u_long arg) { dev_link_t *link = (dev_link_t *) arg; + scsi_info_t *info = link->priv; DEBUG(0, "qlogic_release(0x%p)\n", link); -#warning This does not protect you. You need some real fix for your races. -#if 0 - if (GET_USE_COUNT(&__this_module) != 0) { - DEBUG(0, "qlogic_cs: release postponed, device still open\n"); - link->state |= DEV_STALE_CONFIG; - return; - } -#endif - - scsi_unregister_host(&driver_template); + scsi_remove_host(info->host); link->dev = NULL; CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); + scsi_unregister(info->host); + link->state &= ~DEV_CONFIG; if (link->state & DEV_STALE_LINK) qlogic_detach(link); - } /* qlogic_release */ /*====================================================================*/ @@ -390,7 +390,7 @@ outb(0x04, link->io.BasePort1 + 0xd); } /* Ugggglllyyyy!!! */ - driver_template.eh_bus_reset_handler(NULL); + qlogicfas_bus_reset(NULL); } break; } diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c --- a/drivers/scsi/qlogicfas.c Tue Feb 4 01:41:00 2003 +++ b/drivers/scsi/qlogicfas.c Thu Feb 27 09:13:04 2003 @@ -127,11 +127,6 @@ #endif #include - -#ifdef PCMCIA -#undef MODULE -#endif - #include /* to get disk capacity */ #include #include @@ -148,7 +143,6 @@ #include "scsi.h" #include "hosts.h" -#include "qlogicfas.h" /*----------------------------------------------------------------*/ /* driver state info, local to driver */ @@ -166,6 +160,8 @@ static int qlcfg9 = ((XTALFREQ + 4) / 5); static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4); +int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); + /*----------------------------------------------------------------*/ /* The qlogic card uses two register maps - These macros select which one */ #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) @@ -631,14 +627,12 @@ * Look for qlogic card and init if found */ -int __devinit qlogicfas_detect(Scsi_Host_Template * host) +struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *host) { int i, j; /* these are only used by IRQ detect */ int qltyp; /* type of chip */ struct Scsi_Host *hreg; /* registered host structure */ - host->proc_name = "qlogicfas"; - /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself * decodes the address - I check 230 first since MIDI cards are * typically at 0x330 @@ -659,7 +653,7 @@ release_region(qbase, 0x10); } if (qbase == 0x430) - return 0; + return NULL;; } else printk(KERN_INFO "Ql: Using preset base address of %03x\n", qbase); @@ -726,16 +720,21 @@ qltyp, qbase, qlirq, QL_TURBO_PDMA); host->name = qinfo; - return 1; + return hreg; err_release_mem: release_region(qbase, 0x10); if (host->can_queue) free_irq(qlirq, do_ql_ihandl); - return 0; + return NULL;; } +int __devinit qlogicfas_detect(Scsi_Host_Template *sht) +{ + return (__qlogicfas_detect(sht) != NULL); +} + /* * Return bios parameters */ @@ -777,7 +776,7 @@ * the PCMCIA qlogic_stub code. This wants fixing */ -static int qlogicfas_bus_reset(Scsi_Cmnd * cmd) +int qlogicfas_bus_reset(Scsi_Cmnd * cmd) { qabort = 2; ql_zap(); @@ -818,9 +817,27 @@ /* * The driver template is also needed for PCMCIA */ - -Scsi_Host_Template qlogicfas_driver_template = QLOGICFAS; -#define driver_template qlogicfas_driver_template +Scsi_Host_Template qlogicfas_driver_template = { + .module = THIS_MODULE, + .name = "qlogicfas", + .proc_name = "qlogicfas", + .detect = qlogicfas_detect, + .info = qlogicfas_info, + .command = qlogicfas_command, + .queuecommand = qlogicfas_queuecommand, + .eh_abort_handler = qlogicfas_abort, + .eh_bus_reset_handler = qlogicfas_bus_reset, + .eh_device_reset_handler= qlogicfas_device_reset, + .eh_host_reset_handler = qlogicfas_host_reset, + .bios_param = qlogicfas_biosparam, + .can_queue = 0, + .this_id = -1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; +#ifndef PCMCIA +#define driver_template qlogicfas_driver_template #include "scsi_module.c" - +#endif diff -Nru a/drivers/scsi/qlogicfas.h b/drivers/scsi/qlogicfas.h --- a/drivers/scsi/qlogicfas.h Tue Dec 10 12:28:33 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,34 +0,0 @@ -#ifndef _QLOGICFAS_H -#define _QLOGICFAS_H - -static int qlogicfas_detect(Scsi_Host_Template * ); -static const char * qlogicfas_info(struct Scsi_Host *); -static int qlogicfas_command(Scsi_Cmnd *); -static int qlogicfas_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); -static int qlogicfas_abort(Scsi_Cmnd *); -static int qlogicfas_bus_reset(Scsi_Cmnd *); -static int qlogicfas_device_reset(Scsi_Cmnd *); -static int qlogicfas_host_reset(Scsi_Cmnd *); -static int qlogicfas_biosparam(struct scsi_device *, struct block_device *, - sector_t, int[]); - -#define QLOGICFAS { \ - .detect = qlogicfas_detect, \ - .info = qlogicfas_info, \ - .command = qlogicfas_command, \ - .queuecommand = qlogicfas_queuecommand, \ - .eh_abort_handler = qlogicfas_abort, \ - .eh_bus_reset_handler = qlogicfas_bus_reset, \ - .eh_device_reset_handler = qlogicfas_device_reset, \ - .eh_host_reset_handler = qlogicfas_host_reset, \ - .bios_param = qlogicfas_biosparam, \ - .can_queue = 0, \ - .this_id = -1, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 1, \ - .use_clustering = DISABLE_CLUSTERING \ -} -#endif /* _QLOGICFAS_H */ - - - diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c --- a/drivers/scsi/qlogicfc.c Tue Feb 25 02:46:27 2003 +++ b/drivers/scsi/qlogicfc.c Tue Mar 4 22:44:07 2003 @@ -694,7 +694,7 @@ int isp2x00_detect(Scsi_Host_Template * tmpt) { int hosts = 0; - int wait_time; + unsigned long wait_time; struct Scsi_Host *host = NULL; struct isp2x00_hostdata *hostdata; struct pci_dev *pdev; diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Sun Feb 23 10:34:55 2003 +++ b/drivers/scsi/scsi.h Thu Mar 6 15:50:31 2003 @@ -280,26 +280,7 @@ #define SCSI_SET_IOCTL_LOGGING(LEVEL) \ SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL); -/* - * the return of the status word will be in the following format : - * The low byte is the status returned by the SCSI command, - * with vendor specific bits masked. - * - * The next byte is the message which followed the SCSI status. - * This allows a stos to be used, since the Intel is a little - * endian machine. - * - * The final byte is a host return code, which is one of the following. - * - * IE - * lsb msb - * status msg host code - * - * Our errors returned by OUR driver, NOT SCSI message. Or'd with - * SCSI message passed back to driver . - */ - - +/* host byte codes */ #define DID_OK 0x00 /* NO error */ #define DID_NO_CONNECT 0x01 /* Couldn't connect before timeout period */ #define DID_BUS_BUSY 0x02 /* BUS stayed busy through time out period */ diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Sat Feb 22 08:17:01 2003 +++ b/drivers/scsi/scsi_error.c Sat Mar 8 07:03:27 2003 @@ -92,10 +92,8 @@ * * Notes: * This should be turned into an inline function. Each scsi command - * has it's own timer, and as it is added to the queue, we set up the - * timer. When the command completes, we cancel the timer. Pretty - * simple, really, especially compared to the old way of handling this - * crap. + * has its own timer, and as it is added to the queue, we set up the + * timer. When the command completes, we cancel the timer. **/ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, void (*complete)(struct scsi_cmnd *)) @@ -249,6 +247,7 @@ { if (!SCSI_SENSE_VALID(scmd)) return FAILED; + if (scmd->sense_buffer[2] & 0xe0) return SUCCESS; @@ -515,7 +514,7 @@ * actually did complete normally. */ if (rtn == SUCCESS) { - int rtn = scsi_eh_completed_normally(scmd); + rtn = scsi_eh_completed_normally(scmd); SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scsi_eh_completed_normally %x\n", __FUNCTION__, rtn)); @@ -545,20 +544,20 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) { static unsigned char generic_sense[6] = - {REQUEST_SENSE, 0, 0, 0, 255, 0}; - unsigned char scsi_result0[256], *scsi_result = &scsi_result0[0]; + {REQUEST_SENSE, 0, 0, 0, 254, 0}; + unsigned char *scsi_result; int saved_result; int rtn; memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense)); - if (scmd->device->host->hostt->unchecked_isa_dma) { - scsi_result = kmalloc(512, GFP_ATOMIC | __GFP_DMA); - if (unlikely(!scsi_result)) { - printk(KERN_ERR "%s: cannot allocate scsi_result.\n", - __FUNCTION__); - return FAILED; - } + scsi_result = kmalloc(254, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0); + + + if (unlikely(!scsi_result)) { + printk(KERN_ERR "%s: cannot allocate scsi_result.\n", + __FUNCTION__); + return FAILED; } /* @@ -568,11 +567,11 @@ * address (db). 0 is not a valid sense code. */ memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer)); - memset(scsi_result, 0, 256); + memset(scsi_result, 0, 254); saved_result = scmd->result; scmd->request_buffer = scsi_result; - scmd->request_bufflen = 256; + scmd->request_bufflen = 254; scmd->use_sg = 0; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); scmd->sc_data_direction = SCSI_DATA_READ; @@ -581,13 +580,12 @@ rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT); /* last chance to have valid sense data */ - if (!SCSI_SENSE_VALID(scmd)) { + if(!SCSI_SENSE_VALID(scmd)) { memcpy(scmd->sense_buffer, scmd->request_buffer, - sizeof(scmd->sense_buffer)); + sizeof(scmd->sense_buffer)); } - if (scsi_result != &scsi_result0[0]) - kfree(scsi_result); + kfree(scsi_result); /* * when we eventually call scsi_finish, we really wish to complete @@ -703,25 +701,14 @@ * upper level. */ if (rtn == SUCCESS) - scsi_eh_finish_cmd(scmd, done_q); - if (rtn != NEEDS_RETRY) - continue; - - /* - * we only come in here if we want to retry a - * command. the test to see whether the command - * should be retried should be keeping track of the - * number of tries, so we don't end up looping, of - * course. - */ - scmd->state = NEEDS_RETRY; - rtn = scsi_eh_retry_cmd(scmd); - if (rtn != SUCCESS) + /* we don't want this command reissued, just + * finished with the sense data, so set + * retries to the max allowed to ensure it + * won't get reissued */ + scmd->retries = scmd->allowed; + else if (rtn != NEEDS_RETRY) continue; - /* - * we eventually hand this one back to the top level. - */ scsi_eh_finish_cmd(scmd, done_q); } @@ -1193,12 +1180,12 @@ * Notes: * This is *only* called when we are examining the status after sending * out the actual data command. any commands that are queued for error - * recovery (i.e. test_unit_ready) do *not* come through here. + * recovery (e.g. test_unit_ready) do *not* come through here. * * When this routine returns failed, it means the error handler thread - * is woken. in cases where the error code indicates an error that + * is woken. In cases where the error code indicates an error that * doesn't require the error handler read (i.e. we don't need to - * abort/reset), then this function should return SUCCESS. + * abort/reset), this function should return SUCCESS. **/ int scsi_decide_disposition(struct scsi_cmnd *scmd) { @@ -1214,11 +1201,11 @@ __FUNCTION__)); return SUCCESS; } + /* * first check the host byte, to see if there is anything in there * that would indicate what we need to do. */ - switch (host_byte(scmd->result)) { case DID_PASSTHROUGH: /* @@ -1296,11 +1283,11 @@ /* * next, check the message byte. */ - if (msg_byte(scmd->result) != COMMAND_COMPLETE) { + if (msg_byte(scmd->result) != COMMAND_COMPLETE) return FAILED; - } + /* - * now, check the status byte to see if this indicates anything special. + * check the status byte to see if this indicates anything special. */ switch (status_byte(scmd->result)) { case QUEUE_FULL: @@ -1321,9 +1308,12 @@ return SUCCESS; case CHECK_CONDITION: rtn = scsi_check_sense(scmd); - if (rtn == NEEDS_RETRY) { + if (rtn == NEEDS_RETRY) goto maybe_retry; - } + /* if rtn == FAILED, we have no sense information; + * returning FAILED will wake the error handler thread + * to collect the sense and redo the decide + * disposition */ return rtn; case CONDITION_GOOD: case INTERMEDIATE_GOOD: @@ -1490,9 +1480,9 @@ struct list_head *work_q, struct list_head *done_q) { - if (scsi_eh_bus_device_reset(shost, work_q, done_q)) - if (scsi_eh_bus_reset(shost, work_q, done_q)) - if (scsi_eh_host_reset(work_q, done_q)) + if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) + if (!scsi_eh_bus_reset(shost, work_q, done_q)) + if (!scsi_eh_host_reset(work_q, done_q)) scsi_eh_offline_sdevs(work_q, done_q); } diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Sat Feb 22 12:35:33 2003 +++ b/drivers/scsi/scsi_lib.c Sat Mar 8 07:03:27 2003 @@ -265,7 +265,6 @@ cmd->serial_number = 0; cmd->serial_number_at_timeout = 0; cmd->flags = 0; - cmd->retries = 0; cmd->abort_reason = 0; memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer); diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Fri Feb 28 12:45:00 2003 +++ b/drivers/scsi/scsi_scan.c Thu Mar 6 16:02:09 2003 @@ -960,7 +960,6 @@ SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: host %d channel %d" " id %d lun %d name/id: '%s'\n", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun, sdev->sdev_driverfs_dev.name)); - return; } /** diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Mon Feb 24 10:18:07 2003 +++ b/drivers/scsi/sd.c Sun Mar 9 06:48:19 2003 @@ -1197,7 +1197,7 @@ return; } - buffer = kmalloc(512, GFP_DMA); + buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) { printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation " "failure.\n"); @@ -1389,14 +1389,9 @@ SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); - for (i = 0; i < SD_MAJORS; i++) { - if (register_blkdev(sd_major(i), "sd", &sd_fops)) - printk(KERN_NOTICE - "Unable to get major %d for SCSI disk\n", - sd_major(i)); - else + for (i = 0; i < SD_MAJORS; i++) + if (register_blkdev(sd_major(i), "sd") == 0) majors++; - } if (!majors) return -ENODEV; @@ -1409,7 +1404,7 @@ } /** - * exit_sd - exit point for this driver (when it is a module). + * exit_sd - exit point for this driver (when it is a module). * * Note: this function unregisters this driver from the scsi mid-level. **/ diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Mon Feb 24 12:16:14 2003 +++ b/drivers/scsi/sr.c Sun Mar 9 06:48:19 2003 @@ -604,7 +604,7 @@ struct scsi_request *SRpnt = NULL; request_queue_t *queue; - buffer = kmalloc(512, GFP_DMA); + buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) goto Enomem; SRpnt = scsi_allocate_request(cd->device); @@ -698,7 +698,7 @@ goto out; } -void get_capabilities(struct scsi_cd *cd) +static void get_capabilities(struct scsi_cd *cd) { struct cdrom_generic_command cgc; unsigned char *buffer; @@ -716,9 +716,8 @@ "" }; - buffer = kmalloc(512, GFP_DMA); - if (!buffer) - { + buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); + if (!buffer) { printk(KERN_ERR "sr: out of memory.\n"); return; } @@ -835,7 +834,7 @@ { int rc; - rc = register_blkdev(SCSI_CDROM_MAJOR, "sr", &sr_bdops); + rc = register_blkdev(SCSI_CDROM_MAJOR, "sr"); if (rc) return rc; return scsi_register_device(&sr_template); diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c --- a/drivers/scsi/sym53c8xx.c Wed Feb 26 19:03:06 2003 +++ b/drivers/scsi/sym53c8xx.c Wed Mar 5 23:02:24 2003 @@ -112,8 +112,8 @@ #include #endif #include +#include #include -#include #include #include #include @@ -7214,7 +7214,6 @@ **========================================================== */ -#ifdef MODULE static int ncr_detach(ncb_p np) { int i; @@ -7260,7 +7259,6 @@ return 1; } -#endif /*========================================================== ** @@ -12958,6 +12956,7 @@ } if (i != count) /* Ignore this device if we already have it */ continue; + pci_set_master(pcidev); devp = &devtbl[count]; devp->host_id = driver_setup.host_id; devp->attach_done = 0; @@ -13798,7 +13797,6 @@ } -#ifdef MODULE int sym53c8xx_release(struct Scsi_Host *host) { #ifdef DEBUG_SYM53C8XX @@ -13808,7 +13806,6 @@ return 1; } -#endif /* diff -Nru a/drivers/scsi/sym53c8xx.h b/drivers/scsi/sym53c8xx.h --- a/drivers/scsi/sym53c8xx.h Tue Dec 10 12:28:33 2002 +++ b/drivers/scsi/sym53c8xx.h Mon Feb 17 12:02:12 2003 @@ -75,17 +75,11 @@ int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int sym53c8xx_reset(Scsi_Cmnd *, unsigned int); int sym53c8xx_slave_configure(Scsi_Device *); - -#ifdef MODULE int sym53c8xx_release(struct Scsi_Host *); -#else -#define sym53c8xx_release NULL -#endif - #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75) -#define SYM53C8XX { .name = "", \ +#define SYM53C8XX { .name = "sym53c8xx", \ .detect = sym53c8xx_detect, \ .release = sym53c8xx_release, \ .info = sym53c8xx_info, \ diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c Mon Feb 24 07:25:23 2003 +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c Sat Mar 8 14:50:22 2003 @@ -221,7 +221,7 @@ */ static void sym_soft_reset (hcb_p np) { - u_char istat; + u_char istat = 0; int i; if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SCRUN)) diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c --- a/drivers/scsi/zalon.c Sat Jan 4 12:04:10 2003 +++ b/drivers/scsi/zalon.c Mon Feb 17 12:02:12 2003 @@ -151,7 +151,6 @@ return (hosts_used != 0); } -#ifdef MODULE extern int ncr53c8xx_release(struct Scsi_Host *host); int zalon7xx_release(struct Scsi_Host *host) @@ -160,4 +159,3 @@ unregister_parisc_driver(&zalon_driver); return 1; } -#endif diff -Nru a/drivers/scsi/zalon.h b/drivers/scsi/zalon.h --- a/drivers/scsi/zalon.h Sat Jan 4 12:04:11 2003 +++ b/drivers/scsi/zalon.h Mon Feb 17 12:02:12 2003 @@ -15,12 +15,7 @@ int zalon7xx_detect(Scsi_Host_Template *tpnt); const char *ncr53c8xx_info(struct Scsi_Host *host); int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - -#ifdef MODULE int zalon7xx_release(struct Scsi_Host *); -#else -#define zalon7xx_release NULL -#endif #define GSC_SCSI_ZALON_OFFSET 0x800 diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c --- a/drivers/serial/21285.c Sat Feb 22 09:59:10 2003 +++ b/drivers/serial/21285.c Thu Mar 6 09:27:42 2003 @@ -501,11 +501,12 @@ .index = -1, }; -void __init rs285_console_init(void) +static void __init rs285_console_init(void) { serial21285_setup_ports(); register_console(&serial21285_console); } +console_initcall(rs285_console_init); #define SERIAL_21285_CONSOLE &serial21285_console #else diff -Nru a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c --- a/drivers/serial/68328serial.c Sun Nov 17 23:09:28 2002 +++ b/drivers/serial/68328serial.c Fri Feb 14 15:26:21 2003 @@ -1691,8 +1691,9 @@ }; -void m68328_console_init(void) +static void __init m68328_console_init(void) { register_console(&m68328_driver); } +console_initcall(m68328_console_init); diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c --- a/drivers/serial/8250.c Tue Feb 25 18:39:37 2003 +++ b/drivers/serial/8250.c Sat Mar 8 16:01:37 2003 @@ -1982,11 +1982,13 @@ .index = -1, }; -void __init serial8250_console_init(void) +static int __init serial8250_console_init(void) { serial8250_isa_init_ports(); register_console(&serial8250_console); + return 0; } +console_initcall(serial8250_console_init); #define SERIAL8250_CONSOLE &serial8250_console #else diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c --- a/drivers/serial/amba.c Sat Feb 22 09:59:10 2003 +++ b/drivers/serial/amba.c Thu Mar 6 09:28:07 2003 @@ -705,10 +705,11 @@ .index = -1, }; -void __init ambauart_console_init(void) +static void __init ambauart_console_init(void) { register_console(&amba_console); } +console_initcall(ambauart_console_init); #define AMBA_CONSOLE &amba_console #else diff -Nru a/drivers/serial/anakin.c b/drivers/serial/anakin.c --- a/drivers/serial/anakin.c Sat Feb 22 09:59:10 2003 +++ b/drivers/serial/anakin.c Thu Mar 6 09:28:07 2003 @@ -502,11 +502,12 @@ .index = -1, }; -void __init +static void __init anakin_console_init(void) { register_console(&anakin_console); } +console_initcall(anakin_console_init); #define ANAKIN_CONSOLE &anakin_console #else diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c --- a/drivers/serial/clps711x.c Sat Feb 22 09:59:10 2003 +++ b/drivers/serial/clps711x.c Thu Mar 6 09:28:07 2003 @@ -567,10 +567,11 @@ .index = -1, }; -void __init clps711xuart_console_init(void) +static void __init clps711xuart_console_init(void) { register_console(&clps711x_console); } +console_initcall(clps711xuart_console_init); #define CLPS711X_CONSOLE &clps711x_console #else diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c --- a/drivers/serial/core.c Mon Feb 24 15:32:22 2003 +++ b/drivers/serial/core.c Thu Mar 6 09:28:07 2003 @@ -1890,42 +1890,6 @@ return 0; } - -extern void ambauart_console_init(void); -extern void anakin_console_init(void); -extern void clps711xuart_console_init(void); -extern void rs285_console_init(void); -extern void sa1100_rs_console_init(void); -extern void serial8250_console_init(void); -extern void uart00_console_init(void); - -/* - * Central "initialise all serial consoles" container. Needs to be killed. - */ -void __init uart_console_init(void) -{ -#ifdef CONFIG_SERIAL_AMBA_CONSOLE - ambauart_console_init(); -#endif -#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE - anakin_console_init(); -#endif -#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE - clps711xuart_console_init(); -#endif -#ifdef CONFIG_SERIAL_21285_CONSOLE - rs285_console_init(); -#endif -#ifdef CONFIG_SERIAL_SA1100_CONSOLE - sa1100_rs_console_init(); -#endif -#ifdef CONFIG_SERIAL_8250_CONSOLE - serial8250_console_init(); -#endif -#ifdef CONFIG_SERIAL_UART00_CONSOLE - uart00_console_init(); -#endif -} #endif /* CONFIG_SERIAL_CORE_CONSOLE */ #ifdef CONFIG_PM diff -Nru a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c --- a/drivers/serial/mcfserial.c Tue Feb 18 02:28:34 2003 +++ b/drivers/serial/mcfserial.c Mon Mar 3 12:25:14 2003 @@ -1853,9 +1853,11 @@ .index = -1, }; -void __init mcfrs_console_init(void) +static void __init mcfrs_console_init(void) { register_console(&mcfrs_console); } + +console_initcall(mcfrs_console_init); /****************************************************************************/ diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c --- a/drivers/serial/sa1100.c Tue Feb 25 18:39:37 2003 +++ b/drivers/serial/sa1100.c Thu Mar 6 09:28:07 2003 @@ -835,11 +835,12 @@ .index = -1, }; -void __init sa1100_rs_console_init(void) +static void __init sa1100_rs_console_init(void) { sa1100_init_ports(); register_console(&sa1100_console); } +console_initcall(sa1100_rs_console_init); #define SA1100_CONSOLE &sa1100_console #else diff -Nru a/drivers/serial/uart00.c b/drivers/serial/uart00.c --- a/drivers/serial/uart00.c Sun Feb 16 11:33:25 2003 +++ b/drivers/serial/uart00.c Thu Mar 6 09:30:07 2003 @@ -645,10 +645,11 @@ .index = 0, }; -void __init uart00_console_init(void) +static void __init uart00_console_init(void) { register_console(&uart00_console); } +console_initcall(uart00_console_init); #define UART00_CONSOLE &uart00_console #else diff -Nru a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c --- a/drivers/sgi/char/sgiserial.c Sun Nov 17 23:09:37 2002 +++ b/drivers/sgi/char/sgiserial.c Fri Feb 14 15:27:26 2003 @@ -2269,8 +2269,10 @@ /* * Register console. */ -void __init sgi_serial_console_init(void) +static void __init sgi_serial_console_init(void) { register_console(&sgi_console_driver); } +console_initcall(sgi_serial_console_init); + __initcall(rs_init); diff -Nru a/drivers/usb/class/usb-midi.h b/drivers/usb/class/usb-midi.h --- a/drivers/usb/class/usb-midi.h Fri Feb 21 03:06:06 2003 +++ b/drivers/usb/class/usb-midi.h Wed Mar 5 03:07:27 2003 @@ -54,6 +54,10 @@ #define USB_VENDOR_ID_STEINBERG 0x0763 #define USBMIDI_STEINBERG_USB2MIDI 0x1001 +/* Mark of the Unicorn MIDI Devices */ +#define USB_VENDOR_ID_MOTU 0x07fd +#define USBMIDI_MOTU_FASTLANE 0x0001 + /* ------------------------------------------------------------------------- */ /* Supported devices */ @@ -101,8 +105,15 @@ { /* Roland SC8850 */ "Roland SC8850", USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850, 2, -1, - { { 0x81, 15 }, {-1, -1} }, /** cables 0,1,2, and 3 **/ - { { 0x01, 15 }, {-1, -1} }, + { { 0x81, 0x3f }, {-1, -1} }, + { { 0x01, 0x3f }, {-1, -1} }, + }, + + { /* Roland SC8820 */ + "Roland SC8820", + USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1, + { { 0x81, 0x13 }, {-1, -1} }, + { { 0x01, 0x13 }, {-1, -1} }, }, { /* Roland SC8820 */ @@ -123,6 +134,12 @@ USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300, 2, -1, { { 0x81, 1 }, {-1, -1} }, { { 0x01, 1 }, {-1, -1} }, + }, + { /* MOTU Fastlane USB */ + "MOTU Fastlane USB", + USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE, 1, 0, + { { 0x82, 3 }, {-1, -1} }, + { { 0x02, 3 }, {-1, -1} }, } }; @@ -138,7 +155,9 @@ { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G ) }, { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300 ) }, { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850 ) }, + { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820 ) }, { USB_DEVICE( USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000 ) }, + { USB_DEVICE( USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE ) }, /* { USB_DEVICE( USB_VENDOR_ID_STEINBERG, USBMIDI_STEINBERG_USB2MIDI ) },*/ { } /* Terminating entry */ }; diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c Wed Feb 26 03:17:57 2003 +++ b/drivers/usb/core/hub.c Wed Mar 5 07:24:34 2003 @@ -876,6 +876,7 @@ } hub->children[port] = dev; + dev->state = USB_STATE_POWERED; /* Reset the device, and detect its speed */ if (usb_hub_port_reset(hub, port, dev, delay)) { diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c Sat Feb 15 04:07:33 2003 +++ b/drivers/usb/core/message.c Wed Mar 5 07:24:34 2003 @@ -904,17 +904,29 @@ break; } } - if (!cp) { + if ((!cp && configuration != 0) || (cp && configuration == 0)) { warn("selecting invalid configuration %d", configuration); return -EINVAL; } + /* if it's already configured, clear out old state first. */ + if (dev->state != USB_STATE_ADDRESS) { + /* FIXME unbind drivers from all "old" interfaces. + * handshake with hcd to reset cached hc endpoint state. + */ + } + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) return ret; - + if (configuration) + dev->state = USB_STATE_CONFIGURED; + else + dev->state = USB_STATE_ADDRESS; dev->actconfig = cp; + + /* reset more hc/hcd endpoint state */ dev->toggle[0] = 0; dev->toggle[1] = 0; usb_set_maxpacket(dev); diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c --- a/drivers/usb/core/urb.c Tue Feb 18 07:50:22 2003 +++ b/drivers/usb/core/urb.c Thu Mar 6 07:46:03 2003 @@ -195,7 +195,9 @@ if (!urb || urb->hcpriv || !urb->complete) return -EINVAL; - if (!(dev = urb->dev) || !dev->present || !dev->bus || dev->devnum <= 0) + if (!(dev = urb->dev) || + (dev->state < USB_STATE_DEFAULT) || + (!dev->bus) || (dev->devnum <= 0)) return -ENODEV; if (!(op = dev->bus->op) || !op->submit_urb) return -ENODEV; @@ -211,6 +213,9 @@ temp = usb_pipetype (pipe); is_out = usb_pipeout (pipe); + if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED) + return -ENODEV; + /* (actually HCDs may need to duplicate this, endpoint might yet * stall due to queued bulk/intr transactions that complete after * we check) @@ -376,7 +381,16 @@ */ int usb_unlink_urb(struct urb *urb) { - if (urb && urb->dev && urb->dev->present && urb->dev->bus && urb->dev->bus->op) + /* FIXME + * We should not care about the state here, but the host controllers + * die a horrible death if we submit a urb for a device that has been + * physically removed. + */ + if (urb && + urb->dev && + (urb->dev->state >= USB_STATE_DEFAULT) && + urb->dev->bus && + urb->dev->bus->op) return urb->dev->bus->op->unlink_urb(urb); else return -ENODEV; diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Tue Feb 18 07:50:22 2003 +++ b/drivers/usb/core/usb.c Wed Mar 5 07:29:53 2003 @@ -679,7 +679,7 @@ memset(dev, 0, sizeof(*dev)); device_initialize(&dev->dev); - dev->present = 1; + dev->state = USB_STATE_ATTACHED; usb_bus_get(bus); @@ -828,6 +828,11 @@ *pdev = NULL; + /* mark the device as inactive, so any further urb submissions for + * this device will fail. + */ + dev->state = USB_STATE_NOTATTACHED; + dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum); /* Free up all the children before we remove this device */ @@ -855,10 +860,6 @@ } device_unregister(&dev->dev); - /* mark the device as not present so any further urb submissions for - * this device will fail. */ - dev->present = 0; - /* Decrement the reference count, it'll auto free everything when */ /* it hits 0 which could very well be now */ usb_put_dev(dev); @@ -906,9 +907,17 @@ // otherwise used internally, for usb_new_device() int usb_set_address(struct usb_device *dev) { - return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, - // FIXME USB_CTRL_SET_TIMEOUT - 0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT); + int retval; + + if (dev->devnum == 0) + return -EINVAL; + if (dev->state != USB_STATE_DEFAULT && dev->state != USB_STATE_ADDRESS) + return -EINVAL; + retval = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, + 0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); + if (retval == 0) + dev->state = USB_STATE_ADDRESS; + return retval; } @@ -1014,7 +1023,8 @@ /* dma masks come from the controller; readonly, except to hcd */ dev->dev.dma_mask = parent->dma_mask; - /* USB device state == default ... it's not usable yet */ + /* it's not usable yet */ + dev->state = USB_STATE_DEFAULT; /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... * it's fixed size except for full speed devices. @@ -1049,6 +1059,7 @@ if (err < 0) { dev_err(&dev->dev, "USB device not accepting new address=%d (error=%d)\n", dev->devnum, err); + dev->state = USB_STATE_DEFAULT; clear_bit(dev->devnum, dev->bus->devmap.devicemap); dev->devnum = -1; return 1; diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c --- a/drivers/usb/host/ohci-pci.c Mon Feb 24 03:30:39 2003 +++ b/drivers/usb/host/ohci-pci.c Thu Mar 6 20:32:12 2003 @@ -18,6 +18,7 @@ #include #include #include +#include #ifndef CONFIG_PM # define CONFIG_PM #endif diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c --- a/drivers/usb/serial/io_edgeport.c Tue Jan 7 06:50:11 2003 +++ b/drivers/usb/serial/io_edgeport.c Wed Mar 5 03:35:49 2003 @@ -522,7 +522,7 @@ case EDGE_DOWNLOAD_FILE_I930: BootMajorVersion = BootCodeImageVersion_GEN1.MajorVersion; BootMinorVersion = BootCodeImageVersion_GEN1.MinorVersion; - BootBuildNumber = BootCodeImageVersion_GEN1.BuildNumber; + BootBuildNumber = cpu_to_le16(BootCodeImageVersion_GEN1.BuildNumber); BootImage = &BootCodeImage_GEN1[0]; BootSize = sizeof( BootCodeImage_GEN1 ); break; @@ -530,7 +530,7 @@ case EDGE_DOWNLOAD_FILE_80251: BootMajorVersion = BootCodeImageVersion_GEN2.MajorVersion; BootMinorVersion = BootCodeImageVersion_GEN2.MinorVersion; - BootBuildNumber = BootCodeImageVersion_GEN2.BuildNumber; + BootBuildNumber = cpu_to_le16(BootCodeImageVersion_GEN2.BuildNumber); BootImage = &BootCodeImage_GEN2[0]; BootSize = sizeof( BootCodeImage_GEN2 ); break; @@ -542,26 +542,26 @@ // Check Boot Image Version BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) + (edge_serial->boot_descriptor.MinorVersion << 16) + - edge_serial->boot_descriptor.BuildNumber; + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber); BootNewVer = (BootMajorVersion << 24) + (BootMinorVersion << 16) + - BootBuildNumber; + le16_to_cpu(BootBuildNumber); dbg("Current Boot Image version %d.%d.%d", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, - edge_serial->boot_descriptor.BuildNumber); + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); if (BootNewVer > BootCurVer) { dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, - edge_serial->boot_descriptor.BuildNumber, + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber), BootMajorVersion, BootMinorVersion, - BootBuildNumber); + le16_to_cpu(BootBuildNumber)); dbg("Downloading new Boot Image"); @@ -570,12 +570,12 @@ for (;;) { record = (struct edge_firmware_image_record *)firmware; - response = rom_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]); + response = rom_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]); if (response < 0) { - dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len); + dev_err(&edge_serial->serial->dev->dev, "rom_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len)); break; } - firmware += sizeof (struct edge_firmware_image_record) + record->Len; + firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len); if (firmware >= &BootImage[BootSize]) { break; } @@ -678,12 +678,12 @@ if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) { product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN2.MajorVersion; product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN2.MinorVersion; - product_info->FirmwareBuildNumber = OperationalCodeImageVersion_GEN2.BuildNumber; + product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber); product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251; } else { product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN1.MajorVersion; product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN1.MinorVersion; - product_info->FirmwareBuildNumber = OperationalCodeImageVersion_GEN1.BuildNumber; + product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN1.BuildNumber); product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930; } @@ -729,10 +729,10 @@ dbg(" BoardRev %x", product_info->BoardRev); dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion, product_info->BootMinorVersion, - product_info->BootBuildNumber); + le16_to_cpu(product_info->BootBuildNumber)); dbg(" FirmwareMajorVersion %d.%d.%d", product_info->FirmwareMajorVersion, product_info->FirmwareMinorVersion, - product_info->FirmwareBuildNumber); + le16_to_cpu(product_info->FirmwareBuildNumber)); dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0], product_info->ManufactureDescDate[1], product_info->ManufactureDescDate[2]+1900); @@ -2326,7 +2326,7 @@ __u16 current_length; unsigned char *transfer_buffer; -// dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length); + dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length); transfer_buffer = kmalloc (64, GFP_KERNEL); if (!transfer_buffer) { @@ -2811,12 +2811,13 @@ * Turns a string from Unicode into ASCII. * Doesn't do a good job with any characters that are outside the normal * ASCII range, but it's only for debugging... + * NOTE: expects the unicode in LE format ****************************************************************************/ static void unicode_to_ascii (char *string, short *unicode, int unicode_size) { int i; for (i = 0; i < unicode_size; ++i) { - string[i] = (char)(unicode[i]); + string[i] = (char)(le16_to_cpu(unicode[i])); } string[unicode_size] = 0x00; } @@ -2880,11 +2881,11 @@ dev_err(&edge_serial->serial->dev->dev, "error in getting boot descriptor\n"); } else { dbg("**Boot Descriptor:"); - dbg(" BootCodeLength: %d", edge_serial->boot_descriptor.BootCodeLength); + dbg(" BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); dbg(" MajorVersion: %d", edge_serial->boot_descriptor.MajorVersion); dbg(" MinorVersion: %d", edge_serial->boot_descriptor.MinorVersion); - dbg(" BuildNumber: %d", edge_serial->boot_descriptor.BuildNumber); - dbg(" Capabilities: 0x%x", edge_serial->boot_descriptor.Capabilities); + dbg(" BuildNumber: %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); + dbg(" Capabilities: 0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities)); dbg(" UConfig0: %d", edge_serial->boot_descriptor.UConfig0); dbg(" UConfig1: %d", edge_serial->boot_descriptor.UConfig1); } @@ -2936,12 +2937,12 @@ for (;;) { record = (struct edge_firmware_image_record *)firmware; - response = sram_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]); + response = sram_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]); if (response < 0) { - dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len); + dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), record->Len); break; } - firmware += sizeof (struct edge_firmware_image_record) + record->Len; + firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len); if (firmware >= &FirmwareImage[ImageSize]) { break; } diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c --- a/drivers/usb/serial/pl2303.c Fri Feb 21 09:00:54 2003 +++ b/drivers/usb/serial/pl2303.c Wed Mar 5 04:06:21 2003 @@ -75,6 +75,7 @@ { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, + { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, { } /* Terminating entry */ }; diff -Nru a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h --- a/drivers/usb/serial/pl2303.h Tue Feb 4 06:10:14 2003 +++ b/drivers/usb/serial/pl2303.h Wed Mar 5 04:06:21 2003 @@ -31,3 +31,6 @@ #define TRIPP_VENDOR_ID 0x2478 #define TRIPP_PRODUCT_ID 0x2008 + +#define RADIOSHACK_VENDOR_ID 0x1453 +#define RADIOSHACK_PRODUCT_ID 0x4026 diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c --- a/drivers/usb/serial/usb-serial.c Tue Feb 18 07:50:15 2003 +++ b/drivers/usb/serial/usb-serial.c Thu Mar 6 21:31:07 2003 @@ -634,6 +634,7 @@ serial->type->throttle(port); exit: + ; } static void serial_unthrottle (struct tty_struct * tty) @@ -656,6 +657,7 @@ serial->type->unthrottle(port); exit: + ; } static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) @@ -704,6 +706,7 @@ serial->type->set_termios(port, old); exit: + ; } static void serial_break (struct tty_struct *tty, int break_state) @@ -726,6 +729,7 @@ serial->type->break_ctl(port, break_state); exit: + ; } static void serial_shutdown (struct usb_serial *serial) diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c Fri Feb 21 09:00:45 2003 +++ b/drivers/usb/serial/visor.c Wed Mar 5 03:04:53 2003 @@ -12,6 +12,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (03/05/2003) gkh + * Think Treo support is now working. + * * (04/03/2002) gkh * Added support for the Sony OS 4.1 devices. Thanks to Hiroyuki ARAKI * for the information. @@ -156,7 +159,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v2.0" +#define DRIVER_VERSION "v2.1" #define DRIVER_AUTHOR "Greg Kroah-Hartman " #define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clié driver" @@ -177,6 +180,7 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void visor_read_int_callback (struct urb *urb, struct pt_regs *regs); static int clie_3_5_startup (struct usb_serial *serial); +static int treo_attach (struct usb_serial *serial); static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id); static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id); @@ -262,6 +266,7 @@ .close = visor_close, .throttle = visor_throttle, .unthrottle = visor_unthrottle, + .attach = treo_attach, .probe = visor_probe, .calc_num_ports = visor_calc_num_ports, .shutdown = visor_shutdown, @@ -797,6 +802,48 @@ if (result != 1) { dev_err(dev, "%s: get interface number bad return length: %d\n", __FUNCTION__, result); return -EIO; + } + + return 0; +} + +static int treo_attach (struct usb_serial *serial) +{ + struct usb_serial_port *port; + int i; + + /* Only do this endpoint hack for the Handspring devices with + * interrupt in endpoints, which for now are the Treo devices. */ + if ((serial->dev->descriptor.idVendor != HANDSPRING_VENDOR_ID) || + (serial->num_interrupt_in == 0)) + return 0; + + dbg("%s", __FUNCTION__); + + /* Ok, this is pretty ugly, but these devices want to use the + * interrupt endpoint as paired up with a bulk endpoint for a + * "virtual serial port". So let's force the endpoints to be + * where we want them to be. */ + for (i = serial->num_bulk_in; i < serial->num_ports; ++i) { + port = &serial->port[i]; + port->read_urb = serial->port[0].read_urb; + port->bulk_in_endpointAddress = serial->port[0].bulk_in_endpointAddress; + port->bulk_in_buffer = serial->port[0].bulk_in_buffer; + } + + for (i = serial->num_bulk_out; i < serial->num_ports; ++i) { + port = &serial->port[i]; + port->write_urb = serial->port[0].write_urb; + port->bulk_out_size = serial->port[0].bulk_out_size; + port->bulk_out_endpointAddress = serial->port[0].bulk_out_endpointAddress; + port->bulk_out_buffer = serial->port[0].bulk_out_buffer; + } + + for (i = serial->num_interrupt_in; i < serial->num_ports; ++i) { + port = &serial->port[i]; + port->interrupt_in_urb = serial->port[0].interrupt_in_urb; + port->interrupt_in_endpointAddress = serial->port[0].interrupt_in_endpointAddress; + port->interrupt_in_buffer = serial->port[0].interrupt_in_buffer; } return 0; diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Wed Jan 22 03:55:34 2003 +++ b/drivers/usb/storage/transport.c Tue Mar 4 01:58:24 2003 @@ -582,20 +582,26 @@ unsigned short old_sg; unsigned old_request_bufflen; unsigned char old_sc_data_direction; + unsigned char old_cmd_len; unsigned char old_cmnd[MAX_COMMAND_SIZE]; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); /* save the old command */ memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE); + old_cmd_len = srb->cmd_len; /* set the command and the LUN */ + memset(srb->cmnd, 0, MAX_COMMAND_SIZE); srb->cmnd[0] = REQUEST_SENSE; srb->cmnd[1] = old_cmnd[1] & 0xE0; - srb->cmnd[2] = 0; - srb->cmnd[3] = 0; srb->cmnd[4] = 18; - srb->cmnd[5] = 0; + + /* FIXME: we must do the protocol translation here */ + if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI) + srb->cmd_len = 6; + else + srb->cmd_len = 12; /* set the transfer direction */ old_sc_data_direction = srb->sc_data_direction; @@ -621,6 +627,7 @@ srb->request_bufflen = old_request_bufflen; srb->use_sg = old_sg; srb->sc_data_direction = old_sc_data_direction; + srb->cmd_len = old_cmd_len; memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile --- a/drivers/video/Makefile Sun Mar 2 23:19:23 2003 +++ b/drivers/video/Makefile Fri Mar 7 18:42:54 2003 @@ -70,9 +70,6 @@ obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -# One by one these are being converted over to the new APIs -#obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o - obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ @@ -84,6 +81,8 @@ obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ cfbfillrect.o obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ + cfbfillrect.o +obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ cfbfillrect.o # Files generated that shall be removed upon make clean diff -Nru a/drivers/video/bw2.c b/drivers/video/bw2.c --- a/drivers/video/bw2.c Thu Feb 27 12:32:45 2003 +++ b/drivers/video/bw2.c Tue Mar 4 09:55:26 2003 @@ -33,11 +33,11 @@ * Local functions. */ -static int bw2_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int bw2_set_par(struct fb_info *); static int bw2_blank(int, struct fb_info *); static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int bw2_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -45,13 +45,12 @@ static struct fb_ops bw2_ops = { .owner = THIS_MODULE, - .fb_check_var = bw2_check_var, - .fb_set_par = bw2_set_par, .fb_blank = bw2_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = bw2_mmap, + .fb_ioctl = bw2_ioctl, .fb_cursor = soft_cursor, }; @@ -124,39 +123,6 @@ }; /** - * bw2_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int bw2_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 8) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - return 0; -} - -/** - * bw2_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -bw2_set_par(struct fb_info *info) -{ - return 0; -} - -/** * bw2_blank - Optional function. Blanks the display. * @blank_mode: the blank mode we want. * @info: frame buffer structure that represents a single frame buffer @@ -212,6 +178,15 @@ vma); } +static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct bw2_par *par = (struct bw2_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_SUN2BW, 1, par->fbsize); +} + /* * Initialisation */ @@ -387,7 +362,6 @@ bw2_blank(0, &all->info); - bw2_set_par(&all->info); bw2_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/cg14.c b/drivers/video/cg14.c --- a/drivers/video/cg14.c Sun Mar 2 22:28:03 2003 +++ b/drivers/video/cg14.c Tue Mar 4 09:55:26 2003 @@ -28,8 +28,6 @@ * Local functions. */ -static int cg14_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int cg14_set_par(struct fb_info *); static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); @@ -43,8 +41,6 @@ static struct fb_ops cg14_ops = { .owner = THIS_MODULE, - .fb_check_var = cg14_check_var, - .fb_set_par = cg14_set_par, .fb_setcolreg = cg14_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, @@ -220,39 +216,6 @@ } /** - * cg14_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int cg14_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 8) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - return 0; -} - -/** - * cg14_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -cg14_set_par(struct fb_info *info) -{ - return 0; -} - -/** * cg14_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -358,7 +321,8 @@ break; default: - ret = -EINVAL; + ret = sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_MDICOLOR, 24, par->fbsize); break; }; @@ -523,7 +487,6 @@ return; } - cg14_set_par(&all->info); cg14_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/cg3.c b/drivers/video/cg3.c --- a/drivers/video/cg3.c Thu Feb 27 12:32:45 2003 +++ b/drivers/video/cg3.c Tue Mar 4 09:55:26 2003 @@ -29,13 +29,13 @@ * Local functions. */ -static int cg3_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int cg3_set_par(struct fb_info *); static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int cg3_blank(int, struct fb_info *); static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg3_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -43,14 +43,13 @@ static struct fb_ops cg3_ops = { .owner = THIS_MODULE, - .fb_check_var = cg3_check_var, - .fb_set_par = cg3_set_par, .fb_setcolreg = cg3_setcolreg, .fb_blank = cg3_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = cg3_mmap, + .fb_ioctl = cg3_ioctl, .fb_cursor = soft_cursor, }; @@ -127,39 +126,6 @@ }; /** - * cg3_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int cg3_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 8) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - return 0; -} - -/** - * cg3_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -cg3_set_par(struct fb_info *info) -{ - return 0; -} - -/** * cg3_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -269,6 +235,15 @@ vma); } +static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct cg3_par *par = (struct cg3_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_SUN3COLOR, 8, par->fbsize); +} + /* * Initialisation */ @@ -445,7 +420,6 @@ return; } - cg3_set_par(&all->info); cg3_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/cg6.c b/drivers/video/cg6.c --- a/drivers/video/cg6.c Thu Feb 27 12:32:45 2003 +++ b/drivers/video/cg6.c Tue Mar 4 09:55:26 2003 @@ -29,8 +29,6 @@ * Local functions. */ -static int cg6_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int cg6_set_par(struct fb_info *); static int cg6_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int cg6_blank(int, struct fb_info *); @@ -39,6 +37,8 @@ static void cg6_fillrect(struct fb_info *, struct fb_fillrect *); static int cg6_sync(struct fb_info *); static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg6_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -46,8 +46,6 @@ static struct fb_ops cg6_ops = { .owner = THIS_MODULE, - .fb_check_var = cg6_check_var, - .fb_set_par = cg6_set_par, .fb_setcolreg = cg6_setcolreg, .fb_blank = cg6_blank, .fb_fillrect = cg6_fillrect, @@ -55,6 +53,7 @@ .fb_imageblit = cg6_imageblit, .fb_sync = cg6_sync, .fb_mmap = cg6_mmap, + .fb_ioctl = cg6_ioctl, .fb_cursor = soft_cursor, }; @@ -406,39 +405,6 @@ } /** - * cg6_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int cg6_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 8) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - return 0; -} - -/** - * cg6_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -cg6_set_par(struct fb_info *info) -{ - return 0; -} - -/** * cg6_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -535,6 +501,15 @@ vma); } +static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct cg6_par *par = (struct cg6_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_SUNFAST_COLOR, 8, par->fbsize); +} + /* * Initialisation */ @@ -731,7 +706,6 @@ return; } - cg6_set_par(&all->info); cg6_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c --- a/drivers/video/fbmem.c Sun Mar 2 23:19:23 2003 +++ b/drivers/video/fbmem.c Fri Mar 7 18:42:54 2003 @@ -158,6 +158,8 @@ extern int p9100_setup(char*); extern int tcx_init(void); extern int tcx_setup(char*); +extern int leo_init(void); +extern int leo_setup(char*); static struct { const char *name; @@ -269,6 +271,9 @@ #endif #ifdef CONFIG_FB_TCX { "tcx", tcx_init, tcx_setup }, +#endif +#ifdef CONFIG_FB_LEO + { "leo", leo_init, leo_setup }, #endif /* diff -Nru a/drivers/video/ffb.c b/drivers/video/ffb.c --- a/drivers/video/ffb.c Thu Feb 27 04:19:27 2003 +++ b/drivers/video/ffb.c Tue Mar 4 09:55:26 2003 @@ -20,6 +20,7 @@ #include #include #include +#include #include "sbuslib.h" @@ -27,8 +28,6 @@ * Local functions. */ -static int ffb_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int ffb_set_par(struct fb_info *); static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int ffb_blank(int, struct fb_info *); @@ -39,6 +38,8 @@ static void ffb_copyarea(struct fb_info *, struct fb_copyarea *); static int ffb_sync(struct fb_info *); static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int ffb_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -46,8 +47,6 @@ static struct fb_ops ffb_ops = { .owner = THIS_MODULE, - .fb_check_var = ffb_check_var, - .fb_set_par = ffb_set_par, .fb_setcolreg = ffb_setcolreg, .fb_blank = ffb_blank, .fb_fillrect = ffb_fillrect, @@ -55,6 +54,7 @@ .fb_imageblit = ffb_imageblit, .fb_sync = ffb_sync, .fb_mmap = ffb_mmap, + .fb_ioctl = ffb_ioctl, /* XXX Use FFB hw cursor once fb cursor API is better understood... */ .fb_cursor = soft_cursor, @@ -673,41 +673,6 @@ } /** - * ffb_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int ffb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 32) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - ffb_fixup_var_rgb(var); - - return 0; -} - -/** - * ffb_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -ffb_set_par(struct fb_info *info) -{ - return 0; -} - -/** * ffb_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -818,6 +783,15 @@ 0, vma); } +static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct ffb_par *par = (struct ffb_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_CREATOR, 24, par->fbsize); +} + /* * Initialisation */ @@ -972,7 +946,6 @@ return; } - ffb_set_par(&all->info); ffb_init_fix(&all->info); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/leo.c b/drivers/video/leo.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/video/leo.c Fri Mar 7 18:42:32 2003 @@ -0,0 +1,587 @@ +/* leo.c: LEO frame buffer driver + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz) + * + * Driver layout based loosely on tgafb.c, see that file for credits. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "sbuslib.h" + +/* + * Local functions. + */ + +static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned, + unsigned, struct fb_info *); +static int leo_blank(int, struct fb_info *); + +static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int leo_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); + +/* + * Frame buffer operations + */ + +static struct fb_ops leo_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = leo_setcolreg, + .fb_blank = leo_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_mmap = leo_mmap, + .fb_ioctl = leo_ioctl, + .fb_cursor = soft_cursor, +}; + +#define LEO_OFF_LC_SS0_KRN 0x00200000UL +#define LEO_OFF_LC_SS0_USR 0x00201000UL +#define LEO_OFF_LC_SS1_KRN 0x01200000UL +#define LEO_OFF_LC_SS1_USR 0x01201000UL +#define LEO_OFF_LD_SS0 0x00400000UL +#define LEO_OFF_LD_SS1 0x01400000UL +#define LEO_OFF_LD_GBL 0x00401000UL +#define LEO_OFF_LX_KRN 0x00600000UL +#define LEO_OFF_LX_CURSOR 0x00601000UL +#define LEO_OFF_SS0 0x00800000UL +#define LEO_OFF_SS1 0x01800000UL +#define LEO_OFF_UNK 0x00602000UL +#define LEO_OFF_UNK2 0x00000000UL + +#define LEO_CUR_ENABLE 0x00000080 +#define LEO_CUR_UPDATE 0x00000030 +#define LEO_CUR_PROGRESS 0x00000006 +#define LEO_CUR_UPDATECMAP 0x00000003 + +#define LEO_CUR_TYPE_MASK 0x00000000 +#define LEO_CUR_TYPE_IMAGE 0x00000020 +#define LEO_CUR_TYPE_CMAP 0x00000050 + +struct leo_cursor { + u8 xxx0[16]; + volatile u32 cur_type; + volatile u32 cur_misc; + volatile u32 cur_cursxy; + volatile u32 cur_data; +}; + +#define LEO_KRN_TYPE_CLUT0 0x00001000 +#define LEO_KRN_TYPE_CLUT1 0x00001001 +#define LEO_KRN_TYPE_CLUT2 0x00001002 +#define LEO_KRN_TYPE_WID 0x00001003 +#define LEO_KRN_TYPE_UNK 0x00001006 +#define LEO_KRN_TYPE_VIDEO 0x00002003 +#define LEO_KRN_TYPE_CLUTDATA 0x00004000 +#define LEO_KRN_CSR_ENABLE 0x00000008 +#define LEO_KRN_CSR_PROGRESS 0x00000004 +#define LEO_KRN_CSR_UNK 0x00000002 +#define LEO_KRN_CSR_UNK2 0x00000001 + +struct leo_lx_krn { + volatile u32 krn_type; + volatile u32 krn_csr; + volatile u32 krn_value; +}; + +struct leo_lc_ss0_krn { + volatile u32 misc; + u8 xxx0[0x800-4]; + volatile u32 rev; +}; + +struct leo_lc_ss0_usr { + volatile u32 csr; + volatile u32 addrspace; + volatile u32 fontmsk; + volatile u32 fontt; + volatile u32 extent; + volatile u32 src; + u32 dst; + volatile u32 copy; + volatile u32 fill; +}; + +struct leo_lc_ss1_krn { + u8 unknown; +}; + +struct leo_lc_ss1_usr { + u8 unknown; +}; + +struct leo_ld { + u8 xxx0[0xe00]; + volatile u32 csr; + volatile u32 wid; + volatile u32 wmask; + volatile u32 widclip; + volatile u32 vclipmin; + volatile u32 vclipmax; + volatile u32 pickmin; /* SS1 only */ + volatile u32 pickmax; /* SS1 only */ + volatile u32 fg; + volatile u32 bg; + volatile u32 src; /* Copy/Scroll (SS0 only) */ + volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */ + volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */ + u32 xxx1[3]; + volatile u32 setsem; /* SS1 only */ + volatile u32 clrsem; /* SS1 only */ + volatile u32 clrpick; /* SS1 only */ + volatile u32 clrdat; /* SS1 only */ + volatile u32 alpha; /* SS1 only */ + u8 xxx2[0x2c]; + volatile u32 winbg; + volatile u32 planemask; + volatile u32 rop; + volatile u32 z; + volatile u32 dczf; /* SS1 only */ + volatile u32 dczb; /* SS1 only */ + volatile u32 dcs; /* SS1 only */ + volatile u32 dczs; /* SS1 only */ + volatile u32 pickfb; /* SS1 only */ + volatile u32 pickbb; /* SS1 only */ + volatile u32 dcfc; /* SS1 only */ + volatile u32 forcecol; /* SS1 only */ + volatile u32 door[8]; /* SS1 only */ + volatile u32 pick[5]; /* SS1 only */ +}; + +#define LEO_SS1_MISC_ENABLE 0x00000001 +#define LEO_SS1_MISC_STEREO 0x00000002 +struct leo_ld_ss1 { + u8 xxx0[0xef4]; + volatile u32 ss1_misc; +}; + +struct leo_ld_gbl { + u8 unknown; +}; + +struct leo_par { + spinlock_t lock; + struct leo_lx_krn *lx_krn; + struct leo_lc_ss0_usr *lc_ss0_usr; + struct leo_ld_ss0 *ld_ss0; + struct leo_ld_ss1 *ld_ss1; + struct leo_cursor *cursor; + u32 extent; + u32 clut_data[256]; + + u32 flags; +#define LEO_FLAG_BLANKED 0x00000001 + + unsigned long physbase; + unsigned long fbsize; + + struct sbus_dev *sdev; + struct list_head list; +}; + +static void leo_wait(struct leo_lx_krn *lx_krn) +{ + int i; + + for (i = 0; + (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; + i++) + udelay (1); /* Busy wait at most 0.3 sec */ + return; +} + +/** + * leo_setcolreg - Optional function. Sets a color register. + * @regno: boolean, 0 copy local, 1 get_user() function + * @red: frame buffer colormap structure + * @green: The green value which can be up to 16 bits wide + * @blue: The blue value which can be up to 16 bits wide. + * @transp: If supported the alpha value which can be up to 16 bits wide. + * @info: frame buffer info structure + */ +static int leo_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *) info->par; + struct leo_lx_krn *lx_krn = par->lx_krn; + unsigned long flags; + u32 val; + int i; + + if (regno >= 256) + return 1; + + red >>= 8; + green >>= 8; + blue >>= 8; + + par->clut_data[regno] = red | (green << 8) | (blue << 16); + + spin_lock_irqsave(&par->lock, flags); + + leo_wait(lx_krn); + + sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type); + for (i = 0; i < 256; i++) + sbus_writel(par->clut_data[i], &lx_krn->krn_value); + sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type); + + val = sbus_readl(&lx_krn->krn_csr); + val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2); + sbus_writel(val, &lx_krn->krn_csr); + + spin_unlock_irqrestore(&par->lock, flags); + + return 0; +} + +/** + * leo_blank - Optional function. Blanks the display. + * @blank_mode: the blank mode we want. + * @info: frame buffer structure that represents a single frame buffer + */ +static int leo_blank(int blank, struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *) info->par; + struct leo_lx_krn *lx_krn = par->lx_krn; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&par->lock, flags); + + switch (blank) { + case 0: /* Unblanking */ + val = sbus_readl(&lx_krn->krn_csr); + val |= LEO_KRN_CSR_ENABLE; + sbus_writel(val, &lx_krn->krn_csr); + par->flags &= ~LEO_FLAG_BLANKED; + break; + + case 1: /* Normal blanking */ + case 2: /* VESA blank (vsync off) */ + case 3: /* VESA blank (hsync off) */ + case 4: /* Poweroff */ + val = sbus_readl(&lx_krn->krn_csr); + val &= ~LEO_KRN_CSR_ENABLE; + sbus_writel(val, &lx_krn->krn_csr); + par->flags |= LEO_FLAG_BLANKED; + break; + } + + spin_unlock_irqrestore(&par->lock, flags); + + return 0; +} + +static struct sbus_mmap_map leo_mmap_map[] = { + { LEO_SS0_MAP, LEO_OFF_SS0, 0x800000 }, + { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, 0x1000 }, + { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, 0x1000 }, + { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, 0x1000 }, + { LEO_SS1_MAP, LEO_OFF_SS1, 0x800000 }, + { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, 0x1000 }, + { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, 0x1000 }, + { LEO_UNK_MAP, LEO_OFF_UNK, 0x1000 }, + { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, 0x1000 }, + { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, 0x1000 }, + { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, 0x1000 }, + { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, 0x1000 }, + { LEO_UNK2_MAP, LEO_OFF_UNK2, 0x100000 }, + { 0, 0, 0 } +}; + +static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +{ + struct leo_par *par = (struct leo_par *)info->par; + + return sbusfb_mmap_helper(leo_mmap_map, + par->physbase, par->fbsize, + par->sdev->reg_addrs[0].which_io, + vma); +} + +static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_SUNLEO, 32, par->fbsize); +} + +/* + * Initialisation + */ + +static void +leo_init_fix(struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *)info->par; + + strncpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id) - 1); + info->fix.id[sizeof(info->fix.id)-1] = 0; + + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_TRUECOLOR; + + info->fix.line_length = 8192; + + info->fix.accel = FB_ACCEL_SUN_LEO; +} + +static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl) +{ + struct leo_par *par = (struct leo_par *) info->par; + struct leo_lx_krn *lx_krn = par->lx_krn; + struct fb_wid_item *wi; + unsigned long flags; + u32 val; + int i, j; + + spin_lock_irqsave(&par->lock, flags); + + leo_wait(lx_krn); + + for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) { + switch(wi->wi_type) { + case FB_WID_DBL_8: + j = (wi->wi_index & 0xf) + 0x40; + break; + + case FB_WID_DBL_24: + j = wi->wi_index & 0x3f; + break; + + default: + continue; + }; + sbus_writel(0x5800 + j, &lx_krn->krn_type); + sbus_writel(wi->wi_values[0], &lx_krn->krn_value); + } + sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type); + + val = sbus_readl(&lx_krn->krn_csr); + val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2); + sbus_writel(val, &lx_krn->krn_csr); + + spin_unlock_irqrestore(&par->lock, flags); +} + +static void leo_init_wids(struct fb_info *info) +{ + struct fb_wid_item wi; + struct fb_wid_list wl; + + wl.wl_count = 1; + wl.wl_list = &wi; + wi.wi_type = FB_WID_DBL_8; + wi.wi_index = 0; + wi.wi_values [0] = 0x2c0; + leo_wid_put(info, &wl); + wi.wi_index = 1; + wi.wi_values [0] = 0x30; + leo_wid_put(info, &wl); + wi.wi_index = 2; + wi.wi_values [0] = 0x20; + leo_wid_put(info, &wl); + wi.wi_type = FB_WID_DBL_24; + wi.wi_index = 1; + wi.wi_values [0] = 0x30; + leo_wid_put(info, &wl); + +} + +static void leo_init_hw(struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *) info->par; + struct leo_ld *ss = (struct leo_ld *) par->ld_ss0; + u32 val; + + val = sbus_readl(&par->ld_ss1->ss1_misc); + val |= LEO_SS1_MISC_ENABLE; + sbus_writel(val, &par->ld_ss1->ss1_misc); + + par->extent = ((info->var.xres - 1) | + ((info->var.yres - 1) << 16)); + + sbus_writel(0xffffffff, &ss->wid); + sbus_writel(0xffff, &ss->wmask); + sbus_writel(0, &ss->vclipmin); + sbus_writel(par->extent, &ss->vclipmax); + sbus_writel(0, &ss->fg); + sbus_writel(0xff000000, &ss->planemask); + sbus_writel(0x310850, &ss->rop); + sbus_writel(0, &ss->widclip); + sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11), + &par->lc_ss0_usr->extent); + sbus_writel(4, &par->lc_ss0_usr->addrspace); + sbus_writel(0x80000000, &par->lc_ss0_usr->fill); + sbus_writel(0, &par->lc_ss0_usr->fontt); + do { + val = sbus_readl(&par->lc_ss0_usr->csr); + } while (val & 0x20000000); +} + +static void leo_fixup_var_rgb(struct fb_var_screeninfo *var) +{ + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; +} + +struct all_info { + struct fb_info info; + struct leo_par par; + struct list_head list; +}; +static LIST_HEAD(leo_list); + +static void leo_init_one(struct sbus_dev *sdev) +{ + struct all_info *all; + int linebytes; + + all = kmalloc(sizeof(*all), GFP_KERNEL); + if (!all) { + printk(KERN_ERR "leo: Cannot allocate memory.\n"); + return; + } + memset(all, 0, sizeof(*all)); + + INIT_LIST_HEAD(&all->list); + + spin_lock_init(&all->par.lock); + all->par.sdev = sdev; + + all->par.physbase = sdev->reg_addrs[0].phys_addr; + + sbusfb_fill_var(&all->info.var, sdev->prom_node, 32); + leo_fixup_var_rgb(&all->info.var); + + linebytes = prom_getintdefault(sdev->prom_node, "linebytes", + all->info.var.xres); + all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + +#ifdef CONFIG_SPARC32 + all->info.screen_base = (char *) + prom_getintdefault(sdev->prom_node, "address", 0); +#endif + if (!all->info.screen_base) + all->info.screen_base = (char *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0, + 0x800000, "leo ram"); + + all->par.lc_ss0_usr = (struct leo_lc_ss0_usr *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR, + 0x1000, "leolc ss0usr"); + all->par.ld_ss0 = (struct leo_ld_ss0 *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0, + 0x1000, "leold ss0"); + all->par.ld_ss1 = (struct leo_ld_ss1 *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1, + 0x1000, "leold ss1"); + all->par.lx_krn = (struct leo_lx_krn *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN, + 0x1000, "leolx krn"); + all->par.cursor = (struct leo_cursor *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR, + sizeof(struct leo_cursor), "leolx cursor"); + + all->info.node = NODEV; + all->info.flags = FBINFO_FLAG_DEFAULT; + all->info.fbops = &leo_ops; + all->info.currcon = -1; + all->info.par = &all->par; + + leo_init_wids(&all->info); + leo_init_hw(&all->info); + + leo_blank(0, &all->info); + + if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { + printk(KERN_ERR "leo: Could not allocate color map.\n"); + kfree(all); + return; + } + + leo_init_fix(&all->info); + + if (register_framebuffer(&all->info) < 0) { + printk(KERN_ERR "leo: Could not register framebuffer.\n"); + fb_dealloc_cmap(&all->info.cmap); + kfree(all); + return; + } + + list_add(&all->list, &leo_list); + + printk("leo: %s at %lx:%lx\n", + sdev->prom_name, + (long) sdev->reg_addrs[0].which_io, + (long) sdev->reg_addrs[0].phys_addr); +} + +int __init leo_init(void) +{ + struct sbus_bus *sbus; + struct sbus_dev *sdev; + + for_all_sbusdev(sdev, sbus) { + if (!strcmp(sdev->prom_name, "leo")) + leo_init_one(sdev); + } + + return 0; +} + +void __exit leo_exit(void) +{ + struct list_head *pos, *tmp; + + list_for_each_safe(pos, tmp, &leo_list) { + struct all_info *all = list_entry(pos, typeof(*all), list); + + unregister_framebuffer(&all->info); + fb_dealloc_cmap(&all->info.cmap); + kfree(all); + } +} + +int __init +leo_setup(char *arg) +{ + /* No cmdline options yet... */ + return 0; +} + +#ifdef MODULE +module_init(leo_init); +module_exit(leo_exit); +#endif + +MODULE_DESCRIPTION("framebuffer driver for LEO chipsets"); +MODULE_AUTHOR("David S. Miller "); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/video/leofb.c b/drivers/video/leofb.c --- a/drivers/video/leofb.c Mon Oct 28 05:41:23 2002 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,764 +0,0 @@ -/* $Id: leofb.c,v 1.14 2001/10/16 05:44:44 davem Exp $ - * leofb.c: Leo (ZX) 24/8bit frame buffer driver - * - * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) - * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include