diff options
| author | Patrick Mochel <mochel@osdl.org> | 2003-09-05 00:52:09 -0700 |
|---|---|---|
| committer | Patrick Mochel <mochel@osdl.org> | 2003-09-05 00:52:09 -0700 |
| commit | a01cb2dfa8e91cb773483b2d83c778407515c876 (patch) | |
| tree | 638647b50108536fef8d62a271b4d8096e33c1d7 | |
| parent | f5b61a1fb00721206413b25f64e78edfb6b87777 (diff) | |
| parent | 7c2dd86b82e5d4e44a41c871b9d8cdad5317645f (diff) | |
Merge
223 files changed, 2600 insertions, 2594 deletions
diff --git a/Documentation/Changes b/Documentation/Changes index 5ce920c736c7..f26c7c282164 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -54,7 +54,7 @@ o binutils 2.12 # ld -v o util-linux 2.10o # fdformat --version o module-init-tools 0.9.9 # depmod -V o e2fsprogs 1.29 # tune2fs -o jfsutils 1.0.14 # fsck.jfs -V +o jfsutils 1.1.3 # fsck.jfs -V o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs o xfsprogs 2.1.0 # xfs_db -V o pcmcia-cs 3.1.21 # cardmgr -V diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index be5c94d0f753..43c743903dd7 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -64,6 +64,12 @@ And optionally cpufreq_driver.exit - A pointer to a per-CPU cleanup function. +cpufreq_driver.resume - A pointer to a per-CPU resume function + which is called with interrupts disabled + and _before_ the pre-suspend frequency + and/or policy is restored by a call to + ->target or ->setpolicy. + cpufreq_driver.attr - A pointer to a NULL-terminated list of "struct freq_attr" which allow to export values to sysfs. @@ -119,7 +125,7 @@ section 2 for details on frequency table helpers. You need to make sure that at least one valid frequency (or operating range) is within policy->min and policy->max. If necessary, increase -policy->max fist, and only if this is no solution, decreas policy->min. +policy->max first, and only if this is no solution, decrease policy->min. 1.4 target or setpolicy? diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f4846273df06..31cca56d8e2f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -542,39 +542,15 @@ config CPU_FREQ_SA1100 bool depends on CPU_FREQ && SA1100_LART default y + select CPU_FREQ_DEFAULT_GOV_USERSPACE + select CPU_FREQ_24_API if SYSCTL 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 - tristate - depends on CPU_FREQ - default y - -config CPU_FREQ_24_API - bool - depends on CPU_FREQ_GOV_USERSPACE && SYSCTL - default y - -config CPU_FREQ_PROC_INTF - 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 + select CPU_FREQ_DEFAULT_GOV_USERSPACE + select CPU_FREQ_24_API if SYSCTL config CPU_FREQ_INTEGRATOR tristate "CPUfreq driver for ARM Integrator CPUs" @@ -587,7 +563,7 @@ config CPU_FREQ_INTEGRATOR If in doubt, say Y. -if (CPU_FREQ_INTEGRATOR) +if (CPU_FREQ_INTEGRATOR) || (CPU_FREQ_SA1110) || (CPU_FREQ_SA1100) source "drivers/cpufreq/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c2181d7de0a7..c6c817b0f9ef 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -34,7 +34,7 @@ comma = , # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes # testing for a specific architecture or later rather impossible. -arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call check_gcc,-march=armv5te,-march=armv4 -Wa$(comma)-mxscale) +arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call check_gcc,-march=armv5te,-march=armv4) arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 @@ -47,8 +47,9 @@ tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 -tune-$(CONFIG_CPU_XSCALE) :=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) +tune-$(CONFIG_CPU_XSCALE) :=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale +# Need -Uarm for gcc < 3.x CFLAGS_BOOT :=-mapcs-32 $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm CFLAGS +=-mapcs-32 $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm AFLAGS +=-mapcs-32 $(arch-y) $(tune-y) -msoft-float -Wa,-mno-fpu diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 0a5c2ea51b99..f6f64875dfd4 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -772,8 +772,8 @@ __irq_svc: sub sp, sp, #S_FRAME_SIZE preempt_return: ldr r0, [r8, #TI_PREEMPT] @ read preempt value teq r0, r7 - strne r0, [r0, -r0] @ bug() str r9, [r8, #TI_PREEMPT] @ restore preempt count + strne r0, [r0, -r0] @ bug() #endif ldr r0, [sp, #S_PSR] @ irqs are already disabled msr spsr, r0 @@ -908,8 +908,8 @@ __irq_usr: sub sp, sp, #S_FRAME_SIZE #ifdef CONFIG_PREEMPT ldr r0, [r8, #TI_PREEMPT] teq r0, r7 - strne r0, [r0, -r0] str r9, [r8, #TI_PREEMPT] + strne r0, [r0, -r0] mov tsk, r8 #else get_thread_info tsk diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 4b233763aa0c..4de9941c54e2 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -120,9 +120,9 @@ __turn_mmu_on: orr r0, r0, #2 @ ...........A. #endif mcr p15, 0, r0, c1, c0, 0 @ write control reg - mrc p15, 0, r0, c1, c0, 0 @ read it back. - mov r0, r0 - mov r0, r0 + mrc p15, 0, r3, c0, c0, 0 @ read id reg + mov r3, r3 + mov r3, r3 mov pc, lr /* diff --git a/arch/arm/kernel/pm.c b/arch/arm/kernel/pm.c index e4a71e4e438f..fbe2d7a89580 100644 --- a/arch/arm/kernel/pm.c +++ b/arch/arm/kernel/pm.c @@ -11,6 +11,7 @@ #include <linux/config.h> #include <linux/pm.h> #include <linux/device.h> +#include <linux/sysdev.h> #include <linux/errno.h> #include <linux/sched.h> @@ -36,18 +37,25 @@ int suspend(void) if (ret != 0) goto out; - device_suspend(3); + ret = device_suspend(3); + if (ret) + goto resume_legacy; local_irq_disable(); leds_event(led_stop); + sysdev_suspend(3); + ret = pm_do_suspend(); + sysdev_resume(); + leds_event(led_start); local_irq_enable(); device_resume(); + resume_legacy: pm_send_all(PM_RESUME, (void *)0); out: diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index cb3a112f2905..1e16dd88c251 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -28,6 +28,7 @@ #include <asm/procinfo.h> #include <asm/setup.h> #include <asm/mach-types.h> +#include <asm/cacheflush.h> #include <asm/tlbflush.h> #include <asm/mach/arch.h> diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index c14943864287..50eab0a09c11 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -170,7 +170,7 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy) vco.r = 22; /* set default policy and cpuinfo */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.max_freq = 160000; policy->cpuinfo.min_freq = 12000; policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */ diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 29608b2f91fa..15e2e27da2de 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -186,7 +186,7 @@ static int impd1_probe(struct device *dev) memset(d, 0, sizeof(struct amba_device)); snprintf(d->dev.bus_id, sizeof(d->dev.bus_id), - "lm%x:%5.5x", pdev->id, idev->offset >> 12); + "lm%x:%5.5lx", pdev->id, idev->offset >> 12); d->dev.parent = &pdev->dev; d->res.start = res->start + idev->offset; diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 98b4d76cf7c3..c8183c873e1a 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -12,6 +12,7 @@ */ #include <linux/errno.h> +#include <linux/time.h> #include <asm/hardware.h> #include <asm/memory.h> @@ -63,15 +64,11 @@ int pm_do_suspend(void) { unsigned long sleep_save[SLEEP_SAVE_SIZE]; unsigned long checksum = 0; + unsigned long delta; int i; - cli(); - clf(); - - leds_event(led_stop); - /* preserve current time */ - RCNR = xtime.tv_sec; + delta = xtime.tv_sec - RCNR; /* * Temporary solution. This won't be necessary once @@ -184,16 +181,12 @@ int pm_do_suspend(void) RESTORE(FFIER); /* restore current time */ - xtime.tv_sec = RCNR; + xtime.tv_sec = RCNR + delta; #ifdef DEBUG printk(KERN_DEBUG "*** made it back from resume\n"); #endif - leds_event(led_start); - - sti(); - return 0; } diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index f71a28cdcf26..2ec95ad1db47 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c @@ -222,7 +222,7 @@ 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->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = 59000; policy->cpuinfo.max_freq = 287000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c index 87a0d789e34a..8643bb5b0aa3 100644 --- a/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/arch/arm/mach-sa1100/cpu-sa1110.c @@ -270,8 +270,12 @@ static int sa1110_target(struct cpufreq_policy *policy, * We wait 20ms to be safe. */ sdram_set_refresh(2); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(20 * HZ / 1000); + if (!irqs_disabled()) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(20 * HZ / 1000); + } else { + mdelay(20); + } /* * Reprogram the DRAM timings with interrupts disabled, and @@ -317,7 +321,7 @@ 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->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = 59000; policy->cpuinfo.max_freq = 287000; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index ca55d99f678e..5c37635429bd 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -57,9 +57,11 @@ enum { SLEEP_SAVE_SP = 0, int pm_do_suspend(void) { unsigned long sleep_save[SLEEP_SAVE_SIZE]; + unsigned long delta, gpio; /* preserve current time */ - RCNR = xtime.tv_sec; + delta = xtime.tv_sec - RCNR; + gpio = GPLR; /* save vital registers */ SAVE(OSCR); @@ -112,6 +114,9 @@ int pm_do_suspend(void) RESTORE(Ser1SDCR0); + GPSR = gpio; + GPCR = ~gpio; + /* * Clear the peripheral sleep-hold bit. */ @@ -125,7 +130,7 @@ int pm_do_suspend(void) RESTORE(OIER); /* restore current time */ - xtime.tv_sec = RCNR; + xtime.tv_sec = RCNR + delta; return 0; } diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 1712b9682de9..4808a860d216 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -79,7 +79,7 @@ ENTRY(cpu_arm1020_proc_fin) stmfd sp!, {lr} mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE msr cpsr_c, ip - bl cpu_arm1020_cache_clean_invalidate_all + bl arm1020_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 150ff18161a8..c51259a5dbf4 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -718,7 +718,7 @@ CONFIG_AGP=y # CONFIG_AGP_ALI is not set # CONFIG_AGP_ATI is not set # CONFIG_AGP_AMD is not set -# CONFIG_AGP_AMD_8151 is not set +# CONFIG_AGP_AMD64 is not set CONFIG_AGP_INTEL=y # CONFIG_AGP_NVIDIA is not set # CONFIG_AGP_SIS is not set diff --git a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c index 36cbb5015deb..2b1e68cb66a6 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi.c @@ -580,7 +580,7 @@ acpi_cpufreq_cpu_init ( if (perf->states[i].transition_latency > policy->cpuinfo.transition_latency) policy->cpuinfo.transition_latency = perf->states[i].transition_latency; } - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cur = perf->states[pr->limit.state.px].core_frequency * 1000; /* table init */ diff --git a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c index 9214b2e0c360..a15f1ee967ad 100644 --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c @@ -216,7 +216,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) } /* cpuinfo and default policy values */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = elanfreq_get_cpu_frequency(); diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c index 0cec751f8ae8..bb5471e2bc81 100644 --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c @@ -434,7 +434,7 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy) policy->min = maxfreq / POLICY_MIN_DIV; policy->max = maxfreq; policy->cur = curfreq; - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.min_freq = maxfreq / max_duration; policy->cpuinfo.max_freq = maxfreq; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 808f7f5079b1..42a5ddf38d4e 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -10,10 +10,11 @@ * +---------------------+----------+---------------------------------+ * | Marketing name | Codename | longhaul version / features. | * +---------------------+----------+---------------------------------+ - * | Samuel/CyrixIII | C5A | v1 : multipliers only | + * | Samuel/CyrixIII | C5A | v1 : multipliers only | * | Samuel2/C3 | C3E/C5B | v1 : multiplier only | - * | Ezra | C5C | v2 : multipliers & voltage | - * | Ezra-T | C5M/C5N | v3 : multipliers, voltage & FSB | + * | Ezra | C5C | v2 : multipliers & voltage | + * | Ezra-T | C5M | v3 : multipliers, voltage & FSB | + * | Nehemiah | C5N | v3 : multipliers, voltage & FSB | * +---------------------+----------+---------------------------------+ * * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* @@ -54,197 +55,6 @@ static unsigned int fsb; #define __hlt() __asm__ __volatile__("hlt": : :"memory") -/* - * Clock ratio tables. - * The eblcr ones specify the ratio read from the CPU. - * The clock_ratio ones specify what to write to the CPU. - */ - -/* VIA C3 Samuel 1 & Samuel 2 (stepping 0)*/ -static int __initdata longhaul1_clock_ratio[16] = { - -1, /* 0000 -> RESERVED */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - -1, /* 0011 -> RESERVED */ - -1, /* 0100 -> RESERVED */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 55, /* 0111 -> 5.5x */ - 60, /* 1000 -> 6.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 50, /* 1011 -> 5.0x */ - 65, /* 1100 -> 6.5x */ - 75, /* 1101 -> 7.5x */ - -1, /* 1110 -> RESERVED */ - -1, /* 1111 -> RESERVED */ -}; - -static int __initdata samuel1_eblcr[16] = { - 50, /* 0000 -> RESERVED */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - -1, /* 0011 -> RESERVED */ - 55, /* 0100 -> 5.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - -1, /* 0111 -> RESERVED */ - -1, /* 1000 -> RESERVED */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 60, /* 1011 -> 6.0x */ - -1, /* 1100 -> RESERVED */ - 75, /* 1101 -> 7.5x */ - -1, /* 1110 -> RESERVED */ - 65, /* 1111 -> 6.5x */ -}; - -/* VIA C3 Samuel2 Stepping 1->15 & VIA C3 Ezra */ -static int __initdata longhaul2_clock_ratio[16] = { - 100, /* 0000 -> 10.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 90, /* 0011 -> 9.0x */ - 95, /* 0100 -> 9.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 55, /* 0111 -> 5.5x */ - 60, /* 1000 -> 6.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 50, /* 1011 -> 5.0x */ - 65, /* 1100 -> 6.5x */ - 75, /* 1101 -> 7.5x */ - 85, /* 1110 -> 8.5x */ - 120, /* 1111 -> 12.0x */ -}; - -static int __initdata samuel2_eblcr[16] = { - 50, /* 0000 -> 5.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 100, /* 0011 -> 10.0x */ - 55, /* 0100 -> 5.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 110, /* 0111 -> 11.0x */ - 90, /* 1000 -> 9.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 60, /* 1011 -> 6.0x */ - 120, /* 1100 -> 12.0x */ - 75, /* 1101 -> 7.5x */ - 130, /* 1110 -> 13.0x */ - 65, /* 1111 -> 6.5x */ -}; - -static int __initdata ezra_eblcr[16] = { - 50, /* 0000 -> 5.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 100, /* 0011 -> 10.0x */ - 55, /* 0100 -> 5.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 95, /* 0111 -> 9.5x */ - 90, /* 1000 -> 9.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 60, /* 1011 -> 6.0x */ - 120, /* 1100 -> 12.0x */ - 75, /* 1101 -> 7.5x */ - 85, /* 1110 -> 8.5x */ - 65, /* 1111 -> 6.5x */ -}; - -/* VIA C5M. */ -static int __initdata longhaul3_clock_ratio[32] = { - 100, /* 0000 -> 10.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 90, /* 0011 -> 9.0x */ - 95, /* 0100 -> 9.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 55, /* 0111 -> 5.5x */ - 60, /* 1000 -> 6.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 50, /* 1011 -> 5.0x */ - 65, /* 1100 -> 6.5x */ - 75, /* 1101 -> 7.5x */ - 85, /* 1110 -> 8.5x */ - 120, /* 1111 -> 12.0x */ - - -1, /* 0000 -> RESERVED (10.0x) */ - 110, /* 0001 -> 11.0x */ - 120, /* 0010 -> 12.0x */ - -1, /* 0011 -> RESERVED (9.0x)*/ - 105, /* 0100 -> 10.5x */ - 115, /* 0101 -> 11.5x */ - 125, /* 0110 -> 12.5x */ - 135, /* 0111 -> 13.5x */ - 140, /* 1000 -> 14.0x */ - 150, /* 1001 -> 15.0x */ - 160, /* 1010 -> 16.0x */ - 130, /* 1011 -> 13.0x */ - 145, /* 1100 -> 14.5x */ - 155, /* 1101 -> 15.5x */ - -1, /* 1110 -> RESERVED (13.0x) */ - -1, /* 1111 -> RESERVED (12.0x) */ -}; - -static int __initdata c5m_eblcr[32] = { - 50, /* 0000 -> 5.0x */ - 30, /* 0001 -> 3.0x */ - 40, /* 0010 -> 4.0x */ - 100, /* 0011 -> 10.0x */ - 55, /* 0100 -> 5.5x */ - 35, /* 0101 -> 3.5x */ - 45, /* 0110 -> 4.5x */ - 95, /* 0111 -> 9.5x */ - 90, /* 1000 -> 9.0x */ - 70, /* 1001 -> 7.0x */ - 80, /* 1010 -> 8.0x */ - 60, /* 1011 -> 6.0x */ - 120, /* 1100 -> 12.0x */ - 75, /* 1101 -> 7.5x */ - 85, /* 1110 -> 8.5x */ - 65, /* 1111 -> 6.5x */ - - -1, /* 0000 -> RESERVED (9.0x) */ - 110, /* 0001 -> 11.0x */ - 120, /* 0010 -> 12.0x */ - -1, /* 0011 -> RESERVED (10.0x)*/ - 135, /* 0100 -> 13.5x */ - 115, /* 0101 -> 11.5x */ - 125, /* 0110 -> 12.5x */ - 105, /* 0111 -> 10.5x */ - 130, /* 1000 -> 13.0x */ - 150, /* 1001 -> 15.0x */ - 160, /* 1010 -> 16.0x */ - 140, /* 1011 -> 14.0x */ - -1, /* 1100 -> RESERVED (12.0x) */ - 155, /* 1101 -> 15.5x */ - -1, /* 1110 -> RESERVED (13.0x) */ - 145, /* 1111 -> 14.5x */ -}; - -/* Voltage scales. Div by 1000 to get actual voltage. */ -static int __initdata vrm85scales[32] = { - 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, - 1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300, - 1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725, - 1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325, -}; - -static int __initdata mobilevrmscales[32] = { - 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, - 1600, 1550, 1500, 1450, 1500, 1350, 1300, -1, - 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, - 1075, 1050, 1025, 1000, 975, 950, 925, -1, -}; - /* Clock ratios multiplied by 10 */ static int clock_ratio[32]; static int eblcr_table[32]; @@ -254,18 +64,24 @@ static int longhaul_version; static struct cpufreq_frequency_table *longhaul_table; -static int longhaul_get_cpu_fsb (void) +static unsigned int calc_speed (int mult, int fsb) { + return ((mult/10)*fsb) + ((mult%10)*(fsb/2)); +} + + +static unsigned int longhaul_get_cpu_fsb (void) +{ + unsigned long lo, hi; unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; - unsigned long invalue=0,lo, hi; + unsigned int invalue=0; if (fsb == 0) { rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<18|1<<19)) >>18; - return eblcr_fsb_table[invalue]; - } else { - return fsb; + fsb = eblcr_fsb_table[invalue]; } + return fsb; } @@ -292,26 +108,27 @@ static int longhaul_get_cpu_mult (void) static void longhaul_setstate (unsigned int clock_ratio_index) { - int vidindex, i; + int speed, mult; struct cpufreq_freqs freqs; union msr_longhaul longhaul; union msr_bcr2 bcr2; - if (clock_ratio[clock_ratio_index] == -1) + mult = clock_ratio[clock_ratio_index]; + if (mult == -1) return; - if (((clock_ratio[clock_ratio_index] * fsb * 100) > highest_speed) || - ((clock_ratio[clock_ratio_index] * fsb * 100) < lowest_speed)) + speed = calc_speed (mult, fsb); + if ((speed > highest_speed) || (speed < lowest_speed)) return; - freqs.old = longhaul_get_cpu_mult() * longhaul_get_cpu_fsb() * 100; - freqs.new = clock_ratio[clock_ratio_index] * fsb * 100; + freqs.old = calc_speed (longhaul_get_cpu_mult(), fsb); + freqs.new = speed; freqs.cpu = 0; /* longhaul.c is UP only driver */ - + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - dprintk (KERN_INFO PFX "FSB:%d Mult(x10):%d\n", - fsb * 100, clock_ratio[clock_ratio_index]); + dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, + mult/10, mult%10); switch (longhaul_version) { case 1: @@ -329,6 +146,14 @@ static void longhaul_setstate (unsigned int clock_ratio_index) wrmsrl (MSR_VIA_BCR2, bcr2.val); break; + /* + * Longhaul v2. (Ezra [C5C]) + * We can scale voltage with this too, but that's currently + * disabled until we come up with a decent 'match freq to voltage' + * algorithm. + * We also need to do the voltage/freq setting in order depending + * on the direction of scaling (like we do in powernow-k7.c) + */ case 2: rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; @@ -337,39 +162,16 @@ static void longhaul_setstate (unsigned int clock_ratio_index) /* We must program the revision key only with values we * know about, not blindly copy it from 0:3 */ longhaul.bits.RevisionKey = 1; - - if (can_scale_voltage) { - /* PB: TODO fix this up */ - vidindex = (((highest_speed-lowest_speed) / (fsb/2)) - - ((highest_speed-((clock_ratio[clock_ratio_index] * fsb * 100)/1000)) / (fsb/2))); - for (i=0;i<32;i++) { - dprintk (KERN_INFO "VID hunting. Looking for %d, found %d\n", - minvid+(vidindex*25), voltage_table[i]); - if (voltage_table[i]==(minvid + (vidindex * 25))) - break; - } - if (i==32) - goto bad_voltage; - - dprintk (KERN_INFO PFX "Desired vid index=%d\n", i); -#if 0 - longhaul.bits.SoftVID = i; - longhaul.bits.EnableSoftVID = 1; -#endif - } -/* FIXME: Do voltage and freq seperatly like we do in powernow-k7 */ -bad_voltage: wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); __hlt(); - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - longhaul.bits.EnableSoftBusRatio = 0; - if (can_scale_voltage) - longhaul.bits.EnableSoftVID = 0; - longhaul.bits.RevisionKey = 1; - wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); break; + /* + * Longhaul v3. (Ezra-T [C5M], Nehemiag [C5N]) + * This can also do voltage scaling, but see above. + * Ezra-T was alleged to do FSB scaling too, but it never worked in practice. + */ case 3: rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; @@ -378,7 +180,6 @@ bad_voltage: /* We must program the revision key only with values we * know about, not blindly copy it from 0:3 */ longhaul.bits.RevisionKey = 3; /* SoftVID & SoftBSEL */ - wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); __hlt(); @@ -403,6 +204,8 @@ static int __init longhaul_get_ranges (void) unsigned int j, k = 0; union msr_longhaul longhaul; + fsb = longhaul_get_cpu_fsb(); + switch (longhaul_version) { case 1: /* Ugh, Longhaul v1 didn't have the min/max MSRs. @@ -430,23 +233,25 @@ static int __init longhaul_get_ranges (void) break; } - highest_speed = maxmult * fsb * 100; - lowest_speed = minmult * fsb * 100; - dprintk (KERN_INFO PFX "MinMult(x10)=%d MaxMult(x10)=%d\n", - minmult, maxmult); - dprintk (KERN_INFO PFX "Lowestspeed=%d Highestspeed=%d\n", - lowest_speed, highest_speed); + dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n", + minmult/10, minmult%10, maxmult/10, maxmult%10); + highest_speed = calc_speed (maxmult, fsb); + lowest_speed = calc_speed (minmult,fsb); + dprintk (KERN_INFO PFX "FSB: %dMHz Lowestspeed=%dMHz Highestspeed=%dMHz\n", + fsb, lowest_speed, highest_speed); longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if(!longhaul_table) return -ENOMEM; - for (j=0; (j<numscales); j++) { - if (clock_ratio[j] == -1) + for (j=0; j < numscales; j++) { + unsigned int ratio; + ratio = clock_ratio[j]; + if (ratio == -1) continue; - if (((unsigned int)clock_ratio[j] > maxmult) || ((unsigned int)clock_ratio[j] < minmult)) + if (ratio > maxmult || ratio < minmult) continue; - longhaul_table[k].frequency= clock_ratio[j] * fsb * 100; + longhaul_table[k].frequency = calc_speed (ratio, fsb); longhaul_table[k].index = (j << 8); k++; } @@ -541,10 +346,12 @@ static int longhaul_target (struct cpufreq_policy *policy, static int longhaul_cpu_init (struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = cpu_data; + char *cpuname=NULL; int ret; switch (c->x86_model) { - case 6: /* VIA C3 Samuel C5A */ + case 6: + cpuname = "C3 'Samuel' [C5A]"; longhaul_version=1; memcpy (clock_ratio, longhaul1_clock_ratio, sizeof(longhaul1_clock_ratio)); memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr)); @@ -553,11 +360,13 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) case 7: /* C5B / C5C */ switch (c->x86_mask) { case 0: + cpuname = "C3 'Samuel 2' [C5B]"; longhaul_version=1; memcpy (clock_ratio, longhaul1_clock_ratio, sizeof(longhaul1_clock_ratio)); memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr)); break; case 1 ... 15: + cpuname = "C3 'Ezra' [C5C]"; longhaul_version=2; memcpy (clock_ratio, longhaul2_clock_ratio, sizeof(longhaul2_clock_ratio)); memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr)); @@ -565,17 +374,26 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) } break; - case 8: /* C5M/C5N */ - return -ENODEV; // Waiting on updated docs from VIA before this is usable + case 8: + cpuname = "C3 'Ezra-T [C5M]"; longhaul_version=3; numscales=32; memcpy (clock_ratio, longhaul3_clock_ratio, sizeof(longhaul3_clock_ratio)); memcpy (eblcr_table, c5m_eblcr, sizeof(c5m_eblcr)); break; + /* + case 9: + cpuname = "C3 'Nehemiah' [C5N]"; + longhaul_version=3; + numscales=32; + */ + default: + cpuname = "Unknown"; + break; } - printk (KERN_INFO PFX "VIA CPU detected. Longhaul version %d supported\n", - longhaul_version); + printk (KERN_INFO PFX "VIA %s CPU detected. Longhaul v%d supported.\n", + cpuname, longhaul_version); if ((longhaul_version==2 || longhaul_version==3) && (dont_scale_voltage==0)) longhaul_setup_voltagescaling(); @@ -584,10 +402,9 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy) if (ret != 0) return ret; - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - - policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100); + policy->cur = calc_speed (longhaul_get_cpu_mult(), fsb); return cpufreq_frequency_table_cpuinfo(policy, longhaul_table); } @@ -604,14 +421,20 @@ static int __init longhaul_init (void) { struct cpuinfo_x86 *c = cpu_data; - if ((c->x86_vendor != X86_VENDOR_CENTAUR) || (c->x86 !=6) ) + if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6) return -ENODEV; switch (c->x86_model) { case 6 ... 7: return cpufreq_register_driver(&longhaul_driver); case 8: - return -ENODEV; + printk (KERN_INFO PFX "Ezra-T unsupported: Waiting on updated docs " + "from VIA before this is usable.\n"); + break; + case 9: + printk (KERN_INFO PFX "Nehemiah unsupported: Waiting on working silicon " + "from VIA before this is usable.\n"); + break; default: printk (KERN_INFO PFX "Unknown VIA CPU. Contact davej@codemonkey.org.uk\n"); } diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h index 3070d708cb56..f4d4a472b449 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.h +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h @@ -47,3 +47,204 @@ union msr_longhaul { unsigned long long val; }; +/* + * Clock ratio tables. Div/Mod by 10 to get ratio. + * The eblcr ones specify the ratio read from the CPU. + * The clock_ratio ones specify what to write to the CPU. + */ + +/* + * VIA C3 Samuel 1 & Samuel 2 (stepping 0) + */ +static int __initdata longhaul1_clock_ratio[16] = { + -1, /* 0000 -> RESERVED */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + -1, /* 0011 -> RESERVED */ + -1, /* 0100 -> RESERVED */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 55, /* 0111 -> 5.5x */ + 60, /* 1000 -> 6.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 50, /* 1011 -> 5.0x */ + 65, /* 1100 -> 6.5x */ + 75, /* 1101 -> 7.5x */ + -1, /* 1110 -> RESERVED */ + -1, /* 1111 -> RESERVED */ +}; + +static int __initdata samuel1_eblcr[16] = { + 50, /* 0000 -> RESERVED */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + -1, /* 0011 -> RESERVED */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + -1, /* 0111 -> RESERVED */ + -1, /* 1000 -> RESERVED */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + -1, /* 1100 -> RESERVED */ + 75, /* 1101 -> 7.5x */ + -1, /* 1110 -> RESERVED */ + 65, /* 1111 -> 6.5x */ +}; + +/* + * VIA C3 Samuel2 Stepping 1->15 & VIA C3 Ezra + */ +static int __initdata longhaul2_clock_ratio[16] = { + 100, /* 0000 -> 10.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 90, /* 0011 -> 9.0x */ + 95, /* 0100 -> 9.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 55, /* 0111 -> 5.5x */ + 60, /* 1000 -> 6.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 50, /* 1011 -> 5.0x */ + 65, /* 1100 -> 6.5x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 120, /* 1111 -> 12.0x */ +}; + +static int __initdata samuel2_eblcr[16] = { + 50, /* 0000 -> 5.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 100, /* 0011 -> 10.0x */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 110, /* 0111 -> 11.0x */ + 90, /* 1000 -> 9.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + 120, /* 1100 -> 12.0x */ + 75, /* 1101 -> 7.5x */ + 130, /* 1110 -> 13.0x */ + 65, /* 1111 -> 6.5x */ +}; + +static int __initdata ezra_eblcr[16] = { + 50, /* 0000 -> 5.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 100, /* 0011 -> 10.0x */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 95, /* 0111 -> 9.5x */ + 90, /* 1000 -> 9.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + 120, /* 1100 -> 12.0x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 65, /* 1111 -> 6.5x */ +}; + +/* + * VIA C3 (Ezra-T) [C5M]. + */ +static int __initdata longhaul3_clock_ratio[32] = { + 100, /* 0000 -> 10.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 90, /* 0011 -> 9.0x */ + 95, /* 0100 -> 9.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 55, /* 0111 -> 5.5x */ + 60, /* 1000 -> 6.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 50, /* 1011 -> 5.0x */ + 65, /* 1100 -> 6.5x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 120, /* 1111 -> 12.0x */ + + -1, /* 0000 -> RESERVED (10.0x) */ + 110, /* 0001 -> 11.0x */ + 120, /* 0010 -> 12.0x */ + -1, /* 0011 -> RESERVED (9.0x)*/ + 105, /* 0100 -> 10.5x */ + 115, /* 0101 -> 11.5x */ + 125, /* 0110 -> 12.5x */ + 135, /* 0111 -> 13.5x */ + 140, /* 1000 -> 14.0x */ + 150, /* 1001 -> 15.0x */ + 160, /* 1010 -> 16.0x */ + 130, /* 1011 -> 13.0x */ + 145, /* 1100 -> 14.5x */ + 155, /* 1101 -> 15.5x */ + -1, /* 1110 -> RESERVED (13.0x) */ + -1, /* 1111 -> RESERVED (12.0x) */ +}; + +static int __initdata c5m_eblcr[32] = { + 50, /* 0000 -> 5.0x */ + 30, /* 0001 -> 3.0x */ + 40, /* 0010 -> 4.0x */ + 100, /* 0011 -> 10.0x */ + 55, /* 0100 -> 5.5x */ + 35, /* 0101 -> 3.5x */ + 45, /* 0110 -> 4.5x */ + 95, /* 0111 -> 9.5x */ + 90, /* 1000 -> 9.0x */ + 70, /* 1001 -> 7.0x */ + 80, /* 1010 -> 8.0x */ + 60, /* 1011 -> 6.0x */ + 120, /* 1100 -> 12.0x */ + 75, /* 1101 -> 7.5x */ + 85, /* 1110 -> 8.5x */ + 65, /* 1111 -> 6.5x */ + + -1, /* 0000 -> RESERVED (9.0x) */ + 110, /* 0001 -> 11.0x */ + 120, /* 0010 -> 12.0x */ + -1, /* 0011 -> RESERVED (10.0x)*/ + 135, /* 0100 -> 13.5x */ + 115, /* 0101 -> 11.5x */ + 125, /* 0110 -> 12.5x */ + 105, /* 0111 -> 10.5x */ + 130, /* 1000 -> 13.0x */ + 150, /* 1001 -> 15.0x */ + 160, /* 1010 -> 16.0x */ + 140, /* 1011 -> 14.0x */ + -1, /* 1100 -> RESERVED (12.0x) */ + 155, /* 1101 -> 15.5x */ + -1, /* 1110 -> RESERVED (13.0x) */ + 145, /* 1111 -> 14.5x */ +}; + + +/* + * Voltage scales. Div/Mod by 1000 to get actual voltage. + * Which scale to use depends on the VRM type in use. + */ +static int __initdata vrm85scales[32] = { + 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, + 1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300, + 1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725, + 1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325, +}; + +static int __initdata mobilevrmscales[32] = { + 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, + 1600, 1550, 1500, 1450, 1500, 1350, 1300, -1, + 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, + 1075, 1050, 1025, 1000, 975, 950, 925, -1, +}; + diff --git a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c index 2adb51a8d3d4..8633cf069d07 100644 --- a/arch/i386/kernel/cpu/cpufreq/longrun.c +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c @@ -120,7 +120,8 @@ static int longrun_verify_policy(struct cpufreq_policy *policy) policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - if (policy->policy == CPUFREQ_POLICY_GOVERNOR) + if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) && + (policy->policy != CPUFREQ_POLICY_PERFORMANCE)) return -EINVAL; return 0; diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index a1d257e3fa29..4bf4fee0d372 100644 --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -211,7 +211,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); /* cpuinfo and default policy values */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 1000; policy->cur = stock_freq; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c index 5d967dfe4dbc..bfb2b6b5468c 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c @@ -157,7 +157,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) } /* cpuinfo and default policy values */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = busfreq * max_multiplier; diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index bf923ee095fe..c0b9bf22b7e9 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -1,6 +1,7 @@ /* * AMD K7 Powernow driver. * (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs. + * (C) 2003 Dave Jones <davej@redhat.com> * * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by AMD. @@ -325,6 +326,8 @@ static int powernow_decode_bios (int maxfid, int startvid) p+=2; } } + printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple); + printk ("This is indicative of a broken BIOS. Email davej@redhat.com\n"); return -EINVAL; } p++; @@ -372,7 +375,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n", minimum_speed, maximum_speed); - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = latency; policy->cur = maximum_speed; diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 19c7821cc15c..2653cc2f3b0c 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c @@ -201,9 +201,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) freq = get_cur_freq(); - policy->policy = (freq == centrino_model->max_freq) ? - CPUFREQ_POLICY_PERFORMANCE : - CPUFREQ_POLICY_POWERSAVE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 10; /* 10uS transition latency */ policy->cur = freq; diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index 500b95d66a79..aeeaefd33789 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -299,8 +299,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) (speed / 1000)); /* cpuinfo and default policy values */ - policy->policy = (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? - CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; @@ -309,7 +308,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver speedstep_driver = { - .name = "speedstep", + .name = "speedstep-ich", .verify = speedstep_verify, .target = speedstep_target, .init = speedstep_cpu_init, diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c index 9e8ff72c542f..8db66f34640f 100644 --- a/arch/i386/pci/pcbios.c +++ b/arch/i386/pci/pcbios.c @@ -430,7 +430,8 @@ struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void) "xor %%ah, %%ah\n" "1:" : "=a" (ret), - "=b" (map) + "=b" (map), + "+m" (opt) : "0" (PCIBIOS_GET_ROUTING_OPTIONS), "1" (0), "D" ((long) &opt), diff --git a/arch/ia64/sn/io/hwgfs/ramfs.c b/arch/ia64/sn/io/hwgfs/ramfs.c index 0ec5807cc73a..5a112ccbfd27 100644 --- a/arch/ia64/sn/io/hwgfs/ramfs.c +++ b/arch/ia64/sn/io/hwgfs/ramfs.c @@ -56,7 +56,7 @@ static struct backing_dev_info hwgfs_backing_dev_info = { .memory_backed = 1, /* Does not contribute to dirty memory */ }; -struct inode *hwgfs_get_inode(struct super_block *sb, int mode, dev_t dev) +static struct inode *hwgfs_get_inode(struct super_block *sb, int mode, dev_t dev) { struct inode * inode = new_inode(sb); @@ -66,7 +66,6 @@ struct inode *hwgfs_get_inode(struct super_block *sb, int mode, dev_t dev) inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_mapping->a_ops = &hwgfs_aops; inode->i_mapping->backing_dev_info = &hwgfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index 95152f2f2c65..3e3531a38a13 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -34,12 +34,6 @@ #include <linux/swapops.h> -#ifdef CONFIG_STRAM_SWAP -#define MAJOR_NR Z2RAM_MAJOR -#define do_z2_request do_stram_request -#define DEVICE_NR(device) (minor(device)) -#endif - #undef DEBUG #ifdef DEBUG diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c index a748cb0109db..be861eebab62 100644 --- a/arch/ppc/platforms/pmac_cpufreq.c +++ b/arch/ppc/platforms/pmac_cpufreq.c @@ -257,8 +257,7 @@ pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) if (policy->cpu != 0) return -ENODEV; - policy->policy = (cur_freq == low_freq) ? - CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = cur_freq; diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c index 15de29c7b588..189e8d0d18b8 100644 --- a/arch/ppc/platforms/pmac_setup.c +++ b/arch/ppc/platforms/pmac_setup.c @@ -399,7 +399,7 @@ note_scsi_host(struct device_node *node, void *host) #endif #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) -dev_t __init +static dev_t __init find_ide_boot(void) { char *p; diff --git a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c index 4a5330f0479f..85516164e866 100644 --- a/arch/sh/kernel/cpufreq.c +++ b/arch/sh/kernel/cpufreq.c @@ -160,7 +160,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) sh_freqs[SH_FREQ_MIN].frequency = min_freq; /* cpuinfo and default policy values */ - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = max_freq; diff --git a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc64/kernel/us2e_cpufreq.c index 74926fbbe52e..7aae0a18aabe 100644 --- a/arch/sparc64/kernel/us2e_cpufreq.c +++ b/arch/sparc64/kernel/us2e_cpufreq.c @@ -309,7 +309,7 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) table[2].index = 5; table[3].frequency = CPUFREQ_TABLE_END; - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 0; policy->cur = clock_tick; diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c index b5475e7295ef..18fe54b8aa55 100644 --- a/arch/sparc64/kernel/us3_cpufreq.c +++ b/arch/sparc64/kernel/us3_cpufreq.c @@ -163,7 +163,7 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) table[3].index = 0; table[3].frequency = CPUFREQ_TABLE_END; - policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = 0; policy->cur = clock_tick; diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 39fa46ec2db6..0c3890b3ea12 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -55,9 +55,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); #define MAX_DEV (8) -#define MAX_MINOR (MAX_DEV << UBD_SHIFT) - -#define DEVICE_NR(n) (minor(n) >> UBD_SHIFT) static struct block_device_operations ubd_blops = { .owner = THIS_MODULE, diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index c0474ff8674b..d9870aaa4833 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -561,7 +561,7 @@ CONFIG_RTC=y # # CONFIG_FTAPE is not set CONFIG_AGP=y -CONFIG_AGP_AMD_8151=y +CONFIG_AGP_AMD64=y # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c index 6842d5823465..3510604677d8 100644 --- a/arch/x86_64/kernel/pci-gart.c +++ b/arch/x86_64/kernel/pci-gart.c @@ -675,7 +675,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info) return -1; } -extern int agp_amdk8_init(void); +extern int agp_amd64_init(void); static int __init pci_iommu_init(void) { @@ -690,7 +690,7 @@ static int __init pci_iommu_init(void) /* Makefile puts PCI initialization via subsys_initcall first. */ /* Add other K8 AGP bridge drivers here */ no_agp = no_agp || - (agp_amdk8_init() < 0) || + (agp_amd64_init() < 0) || (agp_copy_info(&info) < 0); #endif diff --git a/crypto/Makefile b/crypto/Makefile index f3325db1ee76..8326b4fb5be4 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -2,11 +2,10 @@ # Cryptographic API # -autoload-crypto-$(CONFIG_KMOD) = autoload.o proc-crypto-$(CONFIG_PROC_FS) = proc.o obj-$(CONFIG_CRYPTO) += api.o cipher.o digest.o compress.o \ - $(autoload-crypto-y) $(proc-crypto-y) + $(proc-crypto-y) obj-$(CONFIG_CRYPTO_HMAC) += hmac.o obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o diff --git a/crypto/autoload.c b/crypto/autoload.c deleted file mode 100644 index 7cda40b39ddf..000000000000 --- a/crypto/autoload.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Cryptographic API. - * - * Algorithm autoloader. - * - * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> - * - * 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 of the License, or (at your option) - * any later version. - * - */ -#include <linux/kernel.h> -#include <linux/crypto.h> -#include <linux/string.h> -#include <linux/kmod.h> -#include "internal.h" - -/* - * A far more intelligent version of this is planned. For now, just - * try an exact match on the name of the algorithm. - */ -void crypto_alg_autoload(const char *name) -{ - request_module("%s", name); -} - -struct crypto_alg *crypto_alg_mod_lookup(const char *name) -{ - struct crypto_alg *alg = crypto_alg_lookup(name); - if (alg == NULL) { - crypto_alg_autoload(name); - alg = crypto_alg_lookup(name); - } - return alg; -} diff --git a/crypto/internal.h b/crypto/internal.h index 10880d149afe..8ba30b772ee3 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -15,6 +15,7 @@ #include <linux/highmem.h> #include <linux/interrupt.h> #include <linux/init.h> +#include <linux/kmod.h> #include <asm/hardirq.h> #include <asm/kmap_types.h> @@ -48,15 +49,12 @@ static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) struct crypto_alg *crypto_alg_lookup(const char *name); -#ifdef CONFIG_KMOD -void crypto_alg_autoload(const char *name); -struct crypto_alg *crypto_alg_mod_lookup(const char *name); -#else +/* A far more intelligent version of this is planned. For now, just + * try an exact match on the name of the algorithm. */ static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) { - return crypto_alg_lookup(name); + return try_then_request_module(crypto_alg_lookup(name), name); } -#endif #ifdef CONFIG_CRYPTO_HMAC int crypto_alloc_hmac_block(struct crypto_tfm *tfm); diff --git a/drivers/base/map.c b/drivers/base/map.c index 0fc8e3a10756..af7ae91d8145 100644 --- a/drivers/base/map.c +++ b/drivers/base/map.c @@ -28,11 +28,6 @@ struct kobj_map { struct rw_semaphore *sem; }; -static inline int dev_to_index(dev_t dev) -{ - return MAJOR(dev) % 255; -} - int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, struct module *module, kobj_probe_t *probe, int (*lock)(dev_t, void *), void *data) diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h index 14b90438a30f..28fb52af3af4 100644 --- a/drivers/block/DAC960.h +++ b/drivers/block/DAC960.h @@ -2063,38 +2063,6 @@ extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument); #define DAC960_MaxPartitions 8 #define DAC960_MaxPartitionsBits 3 - -/* - Define macros to extract the Controller Number, Logical Drive Number, and - Partition Number from a Kernel Device, and to construct a Major Number, Minor - Number, and Kernel Device from the Controller Number, Logical Drive Number, - and Partition Number. There is one Major Number assigned to each Controller. - The associated Minor Number is divided into the Logical Drive Number and - Partition Number. -*/ - -#define DAC960_ControllerNumber(Device) \ - (major(Device) - DAC960_MAJOR) - -#define DAC960_LogicalDriveNumber(Device) \ - (minor(Device) >> DAC960_MaxPartitionsBits) - -#define DAC960_MajorNumber(ControllerNumber) \ - (DAC960_MAJOR + (ControllerNumber)) - -#define DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber) \ - (((LogicalDriveNumber) << DAC960_MaxPartitionsBits) | (PartitionNumber)) - -#define DAC960_MinorCount (DAC960_MaxLogicalDrives \ - * DAC960_MaxPartitions) - -#define DAC960_KernelDevice(ControllerNumber, \ - LogicalDriveNumber, \ - PartitionNumber) \ - mk_kdev(DAC960_MajorNumber(ControllerNumber), \ - DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber)) - - /* Define the DAC960 Controller fixed Block Size and Block Size Bits. */ diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index 27384d27b566..3d9c58788373 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c @@ -255,7 +255,7 @@ static void as_remove_merge_hints(request_queue_t *q, struct as_rq *arq) { as_del_arq_hash(arq); - if (q->last_merge == &arq->request->queuelist) + if (q->last_merge == arq->request) q->last_merge = NULL; } @@ -1347,50 +1347,39 @@ static void as_requeue_request(request_queue_t *q, struct request *rq) } static void -as_insert_request(request_queue_t *q, struct request *rq, - struct list_head *insert_here) +as_insert_request(request_queue_t *q, struct request *rq, int where) { struct as_data *ad = q->elevator.elevator_data; struct as_rq *arq = RQ_DATA(rq); - if (unlikely(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) { - q->last_merge = NULL; - - if (insert_here != ad->dispatch) { + switch (where) { + case ELEVATOR_INSERT_BACK: while (ad->next_arq[REQ_SYNC]) as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]); while (ad->next_arq[REQ_ASYNC]) as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); - } - - if (!insert_here) - insert_here = ad->dispatch->prev; - } - - if (unlikely(!blk_fs_request(rq))) { - if (!insert_here) - insert_here = ad->dispatch; - } - - if (insert_here) { - list_add(&rq->queuelist, insert_here); - - /* Stop anticipating - let this request get through */ - if (list_empty(ad->dispatch)) + list_add_tail(&rq->queuelist, ad->dispatch); + break; + case ELEVATOR_INSERT_FRONT: + list_add(&rq->queuelist, ad->dispatch); as_antic_stop(ad); - - return; + break; + case ELEVATOR_INSERT_SORT: + BUG_ON(!blk_fs_request(rq)); + as_add_request(ad, arq); + break; + default: + printk("%s: bad insert point %d\n", __FUNCTION__,where); + return; } if (rq_mergeable(rq)) { as_add_arq_hash(ad, arq); if (!q->last_merge) - q->last_merge = &rq->queuelist; + q->last_merge = rq; } - - as_add_request(ad, arq); } /* @@ -1438,7 +1427,7 @@ as_latter_request(request_queue_t *q, struct request *rq) } static int -as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) +as_merge(request_queue_t *q, struct request **req, struct bio *bio) { struct as_data *ad = q->elevator.elevator_data; sector_t rb_key = bio->bi_sector + bio_sectors(bio); @@ -1450,7 +1439,7 @@ as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) */ ret = elv_try_last_merge(q, bio); if (ret != ELEVATOR_NO_MERGE) { - __rq = list_entry_rq(q->last_merge); + __rq = q->last_merge; goto out_insert; } @@ -1482,11 +1471,11 @@ as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) return ELEVATOR_NO_MERGE; out: - q->last_merge = &__rq->queuelist; + q->last_merge = __rq; out_insert: if (ret) as_hot_arq_hash(ad, RQ_DATA(__rq)); - *insert = &__rq->queuelist; + *req = __rq; return ret; } @@ -1514,7 +1503,7 @@ static void as_merged_request(request_queue_t *q, struct request *req) */ } - q->last_merge = &req->queuelist; + q->last_merge = req; } static void diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index ce0927b36889..8d2fd57b1b3a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -120,10 +120,10 @@ static int cciss_release(struct inode *inode, struct file *filep); static int cciss_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); -static int revalidate_allvol(kdev_t dev); +static int revalidate_allvol(ctlr_info_t *host); static int cciss_revalidate(struct gendisk *disk); -static int deregister_disk(int ctlr, int logvol); -static int register_new_disk(int cltr); +static int deregister_disk(struct gendisk *disk); +static int register_new_disk(ctlr_info_t *h); static void cciss_getgeometry(int cntl_num); @@ -351,34 +351,42 @@ static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool) } } +static inline ctlr_info_t *get_host(struct gendisk *disk) +{ + return disk->queue->queuedata; +} + +static inline drive_info_struct *get_drv(struct gendisk *disk) +{ + return disk->private_data; +} + /* * Open. Make sure the device is really there. */ static int cciss_open(struct inode *inode, struct file *filep) { - int ctlr = imajor(inode) - COMPAQ_CISS_MAJOR; - int dsk = iminor(inode) >> NWD_SHIFT; + ctlr_info_t *host = get_host(inode->i_bdev->bd_disk); + drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk); #ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_open %s (%x:%x)\n", inode->i_bdev->bd_disk->disk_name, ctlr, dsk); + printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name); #endif /* CCISS_DEBUG */ - if (ctlr >= MAX_CTLR || hba[ctlr] == NULL) - return -ENXIO; /* * Root is allowed to open raw volume zero even if it's not configured * so array config can still work. I don't think I really like this, * but I'm already using way to many device nodes to claim another one * for "raw controller". */ - if (hba[ctlr]->drv[dsk].nr_blocks == 0) { + if (drv->nr_blocks == 0) { if (iminor(inode) != 0) return -ENXIO; if (!capable(CAP_SYS_ADMIN)) return -EPERM; } - hba[ctlr]->drv[dsk].usage_count++; - hba[ctlr]->usage_count++; + drv->usage_count++; + host->usage_count++; return 0; } /* @@ -386,17 +394,15 @@ static int cciss_open(struct inode *inode, struct file *filep) */ static int cciss_release(struct inode *inode, struct file *filep) { - int ctlr = imajor(inode) - COMPAQ_CISS_MAJOR; - int dsk = iminor(inode) >> NWD_SHIFT; + ctlr_info_t *host = get_host(inode->i_bdev->bd_disk); + drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk); #ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss_release %s (%x:%x)\n", inode->i_bdev->bd_disk->disk_name, ctlr, dsk); + printk(KERN_DEBUG "cciss_release %s\n", inode->i_bdev->bd_disk->disk_name); #endif /* CCISS_DEBUG */ - /* fsync_dev(inode->i_rdev); */ - - hba[ctlr]->drv[dsk].usage_count--; - hba[ctlr]->usage_count--; + drv->usage_count--; + host->usage_count--; return 0; } @@ -406,8 +412,11 @@ static int cciss_release(struct inode *inode, struct file *filep) static int cciss_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { - int ctlr = imajor(inode) - COMPAQ_CISS_MAJOR; - int dsk = iminor(inode) >> NWD_SHIFT; + struct block_device *bdev = inode->i_bdev; + struct gendisk *disk = bdev->bd_disk; + ctlr_info_t *host = get_host(disk); + drive_info_struct *drv = get_drv(disk); + int ctlr = host->ctlr; #ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg); @@ -417,14 +426,14 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case HDIO_GETGEO: { struct hd_geometry driver_geo; - if (hba[ctlr]->drv[dsk].cylinders) { - driver_geo.heads = hba[ctlr]->drv[dsk].heads; - driver_geo.sectors = hba[ctlr]->drv[dsk].sectors; - driver_geo.cylinders = hba[ctlr]->drv[dsk].cylinders; + if (drv->cylinders) { + driver_geo.heads = drv->heads; + driver_geo.sectors = drv->sectors; + driver_geo.cylinders = drv->cylinders; } else { driver_geo.heads = 0xff; driver_geo.sectors = 0x3f; - driver_geo.cylinders = (int)hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f); + driver_geo.cylinders = (int)drv->nr_blocks / (0xff*0x3f); } driver_geo.start= get_start_sect(inode->i_bdev); if (copy_to_user((void *) arg, &driver_geo, @@ -438,9 +447,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, cciss_pci_info_struct pciinfo; if (!arg) return -EINVAL; - pciinfo.bus = hba[ctlr]->pdev->bus->number; - pciinfo.dev_fn = hba[ctlr]->pdev->devfn; - pciinfo.board_id = hba[ctlr]->board_id; + pciinfo.bus = host->pdev->bus->number; + pciinfo.dev_fn = host->pdev->devfn; + pciinfo.board_id = host->board_id; if (copy_to_user((void *) arg, &pciinfo, sizeof( cciss_pci_info_struct ))) return -EFAULT; return(0); @@ -448,11 +457,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_GETINTINFO: { cciss_coalint_struct intinfo; - ctlr_info_t *c = hba[ctlr]; - if (!arg) return -EINVAL; - intinfo.delay = readl(&c->cfgtable->HostWrite.CoalIntDelay); - intinfo.count = readl(&c->cfgtable->HostWrite.CoalIntCount); + intinfo.delay = readl(&host->cfgtable->HostWrite.CoalIntDelay); + intinfo.count = readl(&host->cfgtable->HostWrite.CoalIntCount); if (copy_to_user((void *) arg, &intinfo, sizeof( cciss_coalint_struct ))) return -EFAULT; return(0); @@ -460,7 +467,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_SETINTINFO: { cciss_coalint_struct intinfo; - ctlr_info_t *c = hba[ctlr]; unsigned long flags; int i; @@ -477,13 +483,13 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, spin_lock_irqsave(CCISS_LOCK(ctlr), flags); /* Update the field, and then ring the doorbell */ writel( intinfo.delay, - &(c->cfgtable->HostWrite.CoalIntDelay)); + &(host->cfgtable->HostWrite.CoalIntDelay)); writel( intinfo.count, - &(c->cfgtable->HostWrite.CoalIntCount)); - writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); + &(host->cfgtable->HostWrite.CoalIntCount)); + writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); for(i=0;i<MAX_IOCTL_CONFIG_WAIT;i++) { - if (!(readl(c->vaddr + SA5_DOORBELL) + if (!(readl(host->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) break; /* delay and try again */ @@ -497,12 +503,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_GETNODENAME: { NodeName_type NodeName; - ctlr_info_t *c = hba[ctlr]; int i; if (!arg) return -EINVAL; for(i=0;i<16;i++) - NodeName[i] = readb(&c->cfgtable->ServerName[i]); + NodeName[i] = readb(&host->cfgtable->ServerName[i]); if (copy_to_user((void *) arg, NodeName, sizeof( NodeName_type))) return -EFAULT; return(0); @@ -510,7 +515,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_SETNODENAME: { NodeName_type NodeName; - ctlr_info_t *c = hba[ctlr]; unsigned long flags; int i; @@ -524,12 +528,12 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, /* Update the field, and then ring the doorbell */ for(i=0;i<16;i++) - writeb( NodeName[i], &c->cfgtable->ServerName[i]); + writeb( NodeName[i], &host->cfgtable->ServerName[i]); - writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL); + writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL); for(i=0;i<MAX_IOCTL_CONFIG_WAIT;i++) { - if (!(readl(c->vaddr + SA5_DOORBELL) + if (!(readl(host->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq)) break; /* delay and try again */ @@ -544,10 +548,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_GETHEARTBEAT: { Heartbeat_type heartbeat; - ctlr_info_t *c = hba[ctlr]; if (!arg) return -EINVAL; - heartbeat = readl(&c->cfgtable->HeartBeat); + heartbeat = readl(&host->cfgtable->HeartBeat); if (copy_to_user((void *) arg, &heartbeat, sizeof( Heartbeat_type))) return -EFAULT; return(0); @@ -555,10 +558,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, case CCISS_GETBUSTYPES: { BusTypes_type BusTypes; - ctlr_info_t *c = hba[ctlr]; if (!arg) return -EINVAL; - BusTypes = readl(&c->cfgtable->BusTypes); + BusTypes = readl(&host->cfgtable->BusTypes); if (copy_to_user((void *) arg, &BusTypes, sizeof( BusTypes_type) )) return -EFAULT; return(0); @@ -568,7 +570,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, FirmwareVer_type firmware; if (!arg) return -EINVAL; - memcpy(firmware, hba[ctlr]->firm_ver, 4); + memcpy(firmware, host->firm_ver, 4); if (copy_to_user((void *) arg, firmware, sizeof( FirmwareVer_type))) return -EFAULT; @@ -586,12 +588,12 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, } case CCISS_REVALIDVOLS: - return( revalidate_allvol(inode->i_rdev)); + if (bdev != bdev->bd_contains || drv != host->drv) + return -ENXIO; + return revalidate_allvol(host); case CCISS_GETLUNINFO: { LogvolInfo_struct luninfo; - struct gendisk *disk = hba[ctlr]->gendisk[dsk]; - drive_info_struct *drv = &hba[ctlr]->drv[dsk]; int i; luninfo.LunID = drv->LunID; @@ -610,16 +612,14 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, return(0); } case CCISS_DEREGDISK: - return( deregister_disk(ctlr,dsk)); + return deregister_disk(disk); case CCISS_REGNEWD: - { - return(register_new_disk(ctlr)); - } + return register_new_disk(host); + case CCISS_PASSTHRU: { IOCTL_Command_struct iocommand; - ctlr_info_t *h = hba[ctlr]; CommandList_struct *c; char *buff = NULL; u64bit temp64; @@ -655,7 +655,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, return -EFAULT; } } - if ((c = cmd_alloc(h , 0)) == NULL) + if ((c = cmd_alloc(host , 0)) == NULL) { kfree(buff); return -ENOMEM; @@ -682,7 +682,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, // Fill in the scatter gather information if (iocommand.buf_size > 0 ) { - temp64.val = pci_map_single( h->pdev, buff, + temp64.val = pci_map_single( host->pdev, buff, iocommand.buf_size, PCI_DMA_BIDIRECTIONAL); c->SG[0].Addr.lower = temp64.val32.lower; @@ -694,9 +694,9 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, /* Put the request on the tail of the request queue */ spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&h->reqQ, c); - h->Qdepth++; - start_io(h); + addQ(&host->reqQ, c); + host->Qdepth++; + start_io(host); spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); wait_for_completion(&wait); @@ -704,7 +704,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, /* unlock the buffers from DMA */ temp64.val32.lower = c->SG[0].Addr.lower; temp64.val32.upper = c->SG[0].Addr.upper; - pci_unmap_single( h->pdev, (dma_addr_t) temp64.val, + pci_unmap_single( host->pdev, (dma_addr_t) temp64.val, iocommand.buf_size, PCI_DMA_BIDIRECTIONAL); /* Copy the error information out */ @@ -712,7 +712,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, if ( copy_to_user((void *) arg, &iocommand, sizeof( IOCTL_Command_struct) ) ) { kfree(buff); - cmd_free(h, c, 0); + cmd_free(host, c, 0); return( -EFAULT); } @@ -722,17 +722,16 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) { kfree(buff); - cmd_free(h, c, 0); + cmd_free(host, c, 0); return -EFAULT; } } kfree(buff); - cmd_free(h, c, 0); + cmd_free(host, c, 0); return(0); } case CCISS_BIG_PASSTHRU: { BIG_IOCTL_Command_struct *ioc; - ctlr_info_t *h = hba[ctlr]; CommandList_struct *c; unsigned char **buff = NULL; int *buff_size = NULL; @@ -798,7 +797,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, data_ptr += sz; sg_used++; } - if ((c = cmd_alloc(h , 0)) == NULL) { + if ((c = cmd_alloc(host , 0)) == NULL) { status = -ENOMEM; goto cleanup1; } @@ -819,7 +818,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, if (ioc->buf_size > 0 ) { int i; for(i=0; i<sg_used; i++) { - temp64.val = pci_map_single( h->pdev, buff[i], + temp64.val = pci_map_single( host->pdev, buff[i], buff_size[i], PCI_DMA_BIDIRECTIONAL); c->SG[i].Addr.lower = temp64.val32.lower; @@ -831,22 +830,22 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, c->waiting = &wait; /* Put the request on the tail of the request queue */ spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - addQ(&h->reqQ, c); - h->Qdepth++; - start_io(h); + addQ(&host->reqQ, c); + host->Qdepth++; + start_io(host); spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); wait_for_completion(&wait); /* unlock the buffers from DMA */ for(i=0; i<sg_used; i++) { temp64.val32.lower = c->SG[i].Addr.lower; temp64.val32.upper = c->SG[i].Addr.upper; - pci_unmap_single( h->pdev, (dma_addr_t) temp64.val, + pci_unmap_single( host->pdev, (dma_addr_t) temp64.val, buff_size[i], PCI_DMA_BIDIRECTIONAL); } /* Copy the error information out */ ioc->error_info = *(c->err_info); if (copy_to_user((void *) arg, ioc, sizeof(*ioc))) { - cmd_free(h, c, 0); + cmd_free(host, c, 0); status = -EFAULT; goto cleanup1; } @@ -855,14 +854,14 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, BYTE *ptr = (BYTE *) ioc->buf; for(i=0; i< sg_used; i++) { if (copy_to_user(ptr, buff[i], buff_size[i])) { - cmd_free(h, c, 0); + cmd_free(host, c, 0); status = -EFAULT; goto cleanup1; } ptr += buff_size[i]; } } - cmd_free(h, c, 0); + cmd_free(host, c, 0); status = 0; cleanup1: if (buff) { @@ -901,27 +900,23 @@ static int cciss_revalidate(struct gendisk *disk) * particualar logical volume (instead of all of them on a particular * controller). */ -static int revalidate_allvol(kdev_t dev) +static int revalidate_allvol(ctlr_info_t *host) { - int ctlr, i; + int ctlr = host->ctlr, i; unsigned long flags; - ctlr = major(dev) - COMPAQ_CISS_MAJOR; - if (minor(dev) != 0) - return -ENXIO; - spin_lock_irqsave(CCISS_LOCK(ctlr), flags); - if (hba[ctlr]->usage_count > 1) { + if (host->usage_count > 1) { spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); printk(KERN_WARNING "cciss: Device busy for volume" - " revalidation (usage=%d)\n", hba[ctlr]->usage_count); + " revalidation (usage=%d)\n", host->usage_count); return -EBUSY; } - hba[ctlr]->usage_count++; + host->usage_count++; spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); for(i=0; i< NWD; i++) { - struct gendisk *disk = hba[ctlr]->gendisk[i]; + struct gendisk *disk = host->gendisk[i]; if (disk->flags & GENHD_FL_UP) del_gendisk(disk); } @@ -930,54 +925,55 @@ static int revalidate_allvol(kdev_t dev) * Set the partition and block size structures for all volumes * on this controller to zero. We will reread all of this data */ - memset(hba[ctlr]->drv, 0, sizeof(drive_info_struct) + memset(host->drv, 0, sizeof(drive_info_struct) * CISS_MAX_LUN); /* * Tell the array controller not to give us any interrupts while * we check the new geometry. Then turn interrupts back on when * we're done. */ - hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_OFF); + host->access.set_intr_mask(host, CCISS_INTR_OFF); cciss_getgeometry(ctlr); - hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_ON); + host->access.set_intr_mask(host, CCISS_INTR_ON); /* Loop through each real device */ for (i = 0; i < NWD; i++) { - struct gendisk *disk = hba[ctlr]->gendisk[i]; - drive_info_struct *drv = &(hba[ctlr]->drv[i]); + struct gendisk *disk = host->gendisk[i]; + drive_info_struct *drv = &(host->drv[i]); if (!drv->nr_blocks) continue; - blk_queue_hardsect_size(hba[ctlr]->queue, drv->block_size); + blk_queue_hardsect_size(host->queue, drv->block_size); set_capacity(disk, drv->nr_blocks); add_disk(disk); } - hba[ctlr]->usage_count--; + host->usage_count--; return 0; } -static int deregister_disk(int ctlr, int logvol) +static int deregister_disk(struct gendisk *disk) { unsigned long flags; - struct gendisk *disk = hba[ctlr]->gendisk[logvol]; - ctlr_info_t *h = hba[ctlr]; + ctlr_info_t *h = get_host(disk); + drive_info_struct *drv = get_drv(disk); + int ctlr = h->ctlr; if (!capable(CAP_SYS_RAWIO)) return -EPERM; spin_lock_irqsave(CCISS_LOCK(ctlr), flags); /* make sure logical volume is NOT is use */ - if( h->drv[logvol].usage_count > 1) { + if( drv->usage_count > 1) { spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); return -EBUSY; } - h->drv[logvol].usage_count++; + drv->usage_count++; spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); /* invalidate the devices and deregister the disk */ if (disk->flags & GENHD_FL_UP) del_gendisk(disk); /* check to see if it was the last disk */ - if (logvol == h->highest_lun) { + if (drv == h->drv + h->highest_lun) { /* if so, find the new hightest lun */ int i, newhighest =-1; for(i=0; i<h->highest_lun; i++) { @@ -990,10 +986,10 @@ static int deregister_disk(int ctlr, int logvol) } --h->num_luns; /* zero out the disk size info */ - h->drv[logvol].nr_blocks = 0; - h->drv[logvol].block_size = 0; - h->drv[logvol].cylinders = 0; - h->drv[logvol].LunID = 0; + drv->nr_blocks = 0; + drv->block_size = 0; + drv->cylinders = 0; + drv->LunID = 0; return(0); } static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, @@ -1304,10 +1300,10 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, *total_size, *block_size); return; } -static int register_new_disk(int ctlr) +static int register_new_disk(ctlr_info_t *h) { struct gendisk *disk; - ctlr_info_t *h = hba[ctlr]; + int ctlr = h->ctlr; int i; int num_luns; int logvol; @@ -1417,7 +1413,7 @@ static int register_new_disk(int ctlr) #ifdef CCISS_DEBUG printk("Checking Index %d\n", i); #endif /* CCISS_DEBUG */ - if(hba[ctlr]->drv[i].LunID == 0) + if(h->drv[i].LunID == 0) { #ifdef CCISS_DEBUG printk("free index found at %d\n", i); @@ -1434,19 +1430,19 @@ static int register_new_disk(int ctlr) } logvol = free_index; - hba[ctlr]->drv[logvol].LunID = lunid; + h->drv[logvol].LunID = lunid; /* there could be gaps in lun numbers, track hightest */ - if(hba[ctlr]->highest_lun < lunid) - hba[ctlr]->highest_lun = logvol; + if(h->highest_lun < lunid) + h->highest_lun = logvol; cciss_read_capacity(ctlr, logvol, size_buff, 1, &total_size, &block_size); cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size, - inq_buff, &hba[ctlr]->drv[logvol]); - hba[ctlr]->drv[logvol].usage_count = 0; - ++hba[ctlr]->num_luns; + inq_buff, &h->drv[logvol]); + h->drv[logvol].usage_count = 0; + ++h->num_luns; /* setup partitions per disk */ - disk = hba[ctlr]->gendisk[logvol]; - set_capacity(disk, hba[ctlr]->drv[logvol].nr_blocks); + disk = h->gendisk[logvol]; + set_capacity(disk, h->drv[logvol].nr_blocks); add_disk(disk); freeret: kfree(ld_buff); diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c index dc2b121a9239..8bb37f65d536 100644 --- a/drivers/block/deadline-iosched.c +++ b/drivers/block/deadline-iosched.c @@ -33,13 +33,7 @@ static const int deadline_hash_shift = 5; #define DL_HASH_ENTRIES (1 << deadline_hash_shift) #define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors) #define list_entry_hash(ptr) list_entry((ptr), struct deadline_rq, hash) -#define ON_HASH(drq) (drq)->hash_valid_count - -#define DL_INVALIDATE_HASH(dd) \ - do { \ - if (!++(dd)->hash_valid_count) \ - (dd)->hash_valid_count = 1; \ - } while (0) +#define ON_HASH(drq) (drq)->on_hash struct deadline_data { /* @@ -58,7 +52,6 @@ struct deadline_data { struct deadline_rq *next_drq[2]; struct list_head *dispatch; /* driver dispatch queue */ struct list_head *hash; /* request hash */ - unsigned long hash_valid_count; /* barrier hash count */ unsigned int batching; /* number of sequential requests made */ sector_t last_sector; /* head position */ unsigned int starved; /* times reads have starved writes */ @@ -90,7 +83,7 @@ struct deadline_rq { * request hash, key is the ending offset (for back merge lookup) */ struct list_head hash; - unsigned long hash_valid_count; + char on_hash; /* * expire fifo @@ -110,7 +103,7 @@ static kmem_cache_t *drq_pool; */ static inline void __deadline_del_drq_hash(struct deadline_rq *drq) { - drq->hash_valid_count = 0; + drq->on_hash = 0; list_del_init(&drq->hash); } @@ -125,7 +118,7 @@ deadline_remove_merge_hints(request_queue_t *q, struct deadline_rq *drq) { deadline_del_drq_hash(drq); - if (q->last_merge == &drq->request->queuelist) + if (q->last_merge == drq->request) q->last_merge = NULL; } @@ -136,7 +129,7 @@ deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) BUG_ON(ON_HASH(drq)); - drq->hash_valid_count = dd->hash_valid_count; + drq->on_hash = 1; list_add(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); } @@ -169,8 +162,7 @@ deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) BUG_ON(!ON_HASH(drq)); - if (!rq_mergeable(__rq) - || drq->hash_valid_count != dd->hash_valid_count) { + if (!rq_mergeable(__rq)) { __deadline_del_drq_hash(drq); continue; } @@ -324,7 +316,7 @@ static void deadline_remove_request(request_queue_t *q, struct request *rq) } static int -deadline_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) +deadline_merge(request_queue_t *q, struct request **req, struct bio *bio) { struct deadline_data *dd = q->elevator.elevator_data; struct request *__rq; @@ -335,7 +327,7 @@ deadline_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) */ ret = elv_try_last_merge(q, bio); if (ret != ELEVATOR_NO_MERGE) { - __rq = list_entry_rq(q->last_merge); + __rq = q->last_merge; goto out_insert; } @@ -371,11 +363,11 @@ deadline_merge(request_queue_t *q, struct list_head **insert, struct bio *bio) return ELEVATOR_NO_MERGE; out: - q->last_merge = &__rq->queuelist; + q->last_merge = __rq; out_insert: if (ret) deadline_hot_drq_hash(dd, RQ_DATA(__rq)); - *insert = &__rq->queuelist; + *req = __rq; return ret; } @@ -398,7 +390,7 @@ static void deadline_merged_request(request_queue_t *q, struct request *req) deadline_add_drq_rb(dd, drq); } - q->last_merge = &req->queuelist; + q->last_merge = req; } static void @@ -621,43 +613,35 @@ dispatch: } static void -deadline_insert_request(request_queue_t *q, struct request *rq, - struct list_head *insert_here) +deadline_insert_request(request_queue_t *q, struct request *rq, int where) { struct deadline_data *dd = q->elevator.elevator_data; struct deadline_rq *drq = RQ_DATA(rq); - if (unlikely(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) { - DL_INVALIDATE_HASH(dd); - q->last_merge = NULL; - - if (insert_here != dd->dispatch) { + switch (where) { + case ELEVATOR_INSERT_BACK: while (deadline_dispatch_requests(dd)) ; - } - - if (!insert_here) - insert_here = dd->dispatch->prev; - } - - if (unlikely(!blk_fs_request(rq))) { - if (!insert_here) - insert_here = dd->dispatch; - } - - if (insert_here) { - list_add(&rq->queuelist, insert_here); - return; + list_add_tail(&rq->queuelist, dd->dispatch); + break; + case ELEVATOR_INSERT_FRONT: + list_add(&rq->queuelist, dd->dispatch); + break; + case ELEVATOR_INSERT_SORT: + BUG_ON(!blk_fs_request(rq)); + deadline_add_request(dd, drq); + break; + default: + printk("%s: bad insert point %d\n", __FUNCTION__,where); + return; } if (rq_mergeable(rq)) { deadline_add_drq_hash(dd, drq); if (!q->last_merge) - q->last_merge = &rq->queuelist; + q->last_merge = rq; } - - deadline_add_request(dd, drq); } static int deadline_queue_empty(request_queue_t *q) @@ -748,7 +732,6 @@ static int deadline_init(request_queue_t *q, elevator_t *e) dd->dispatch = &q->queue_head; dd->fifo_expire[READ] = read_expire; dd->fifo_expire[WRITE] = write_expire; - dd->hash_valid_count = 1; dd->writes_starved = writes_starved; dd->front_merges = 1; dd->fifo_batch = fifo_batch; @@ -779,7 +762,7 @@ deadline_set_request(request_queue_t *q, struct request *rq, int gfp_mask) drq->request = rq; INIT_LIST_HEAD(&drq->hash); - drq->hash_valid_count = 0; + drq->on_hash = 0; INIT_LIST_HEAD(&drq->fifo); diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c index 4654fddecd7d..fcb00cfa4fd7 100644 --- a/drivers/block/elevator.c +++ b/drivers/block/elevator.c @@ -81,7 +81,7 @@ inline int elv_try_merge(struct request *__rq, struct bio *bio) inline int elv_try_last_merge(request_queue_t *q, struct bio *bio) { if (q->last_merge) - return elv_try_merge(list_entry_rq(q->last_merge), bio); + return elv_try_merge(q->last_merge, bio); return ELEVATOR_NO_MERGE; } @@ -117,12 +117,12 @@ int elevator_global_init(void) return 0; } -int elv_merge(request_queue_t *q, struct list_head **entry, struct bio *bio) +int elv_merge(request_queue_t *q, struct request **req, struct bio *bio) { elevator_t *e = &q->elevator; if (e->elevator_merge_fn) - return e->elevator_merge_fn(q, entry, bio); + return e->elevator_merge_fn(q, req, bio); return ELEVATOR_NO_MERGE; } @@ -140,7 +140,7 @@ void elv_merge_requests(request_queue_t *q, struct request *rq, { elevator_t *e = &q->elevator; - if (q->last_merge == &next->queuelist) + if (q->last_merge == next) q->last_merge = NULL; if (e->elevator_merge_req_fn) @@ -156,29 +156,25 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) if (q->elevator.elevator_requeue_req_fn) q->elevator.elevator_requeue_req_fn(q, rq); else - __elv_add_request(q, rq, 0, 0); + __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); } -void __elv_add_request(request_queue_t *q, struct request *rq, int at_end, +void __elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { - struct list_head *insert = NULL; - - if (!at_end) - insert = &q->queue_head; if (plug) blk_plug_device(q); - q->elevator.elevator_add_req_fn(q, rq, insert); + q->elevator.elevator_add_req_fn(q, rq, where); } -void elv_add_request(request_queue_t *q, struct request *rq, int at_end, +void elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { unsigned long flags; spin_lock_irqsave(q->queue_lock, flags); - __elv_add_request(q, rq, at_end, plug); + __elv_add_request(q, rq, where, plug); spin_unlock_irqrestore(q->queue_lock, flags); } @@ -200,7 +196,7 @@ struct request *elv_next_request(request_queue_t *q) */ rq->flags |= REQ_STARTED; - if (&rq->queuelist == q->last_merge) + if (rq == q->last_merge) q->last_merge = NULL; if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn) @@ -238,7 +234,7 @@ void elv_remove_request(request_queue_t *q, struct request *rq) * deleted without ever being given to driver (merged with another * request). */ - if (&rq->queuelist == q->last_merge) + if (rq == q->last_merge) q->last_merge = NULL; if (e->elevator_remove_req_fn) diff --git a/drivers/block/floppy98.c b/drivers/block/floppy98.c index d861fdbc3466..9513de5f11cf 100644 --- a/drivers/block/floppy98.c +++ b/drivers/block/floppy98.c @@ -4249,6 +4249,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) return NULL; if (((*part>>2) & 0x1f) >= NUMBER(floppy_type)) return NULL; + *part = 0; return get_disk(disks[drive]); } diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index c57d8d0f42c2..541b45c519ef 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -703,7 +703,7 @@ void blk_queue_invalidate_tags(request_queue_t *q) blk_queue_end_tag(q, rq); rq->flags &= ~REQ_STARTED; - __elv_add_request(q, rq, 0, 0); + __elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0); } } @@ -1632,11 +1632,16 @@ void blk_insert_request(request_queue_t *q, struct request *rq, if(reinsert) { blk_requeue_request(q, rq); } else { + int where = ELEVATOR_INSERT_BACK; + + if (at_head) + where = ELEVATOR_INSERT_FRONT; + if (blk_rq_tagged(rq)) blk_queue_end_tag(q, rq); drive_stat_acct(rq, rq->nr_sectors, 1); - __elv_add_request(q, rq, !at_head, 0); + __elv_add_request(q, rq, where, 0); } q->request_fn(q); spin_unlock_irqrestore(q->queue_lock, flags); @@ -1669,8 +1674,7 @@ void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) * queue lock is held and interrupts disabled, as we muck with the * request queue list. */ -static inline void add_request(request_queue_t * q, struct request * req, - struct list_head *insert_here) +static inline void add_request(request_queue_t * q, struct request * req) { drive_stat_acct(req, req->nr_sectors, 1); @@ -1681,7 +1685,7 @@ static inline void add_request(request_queue_t * q, struct request * req, * elevator indicated where it wants this request to be * inserted at elevator_merge time */ - __elv_add_request_pos(q, req, insert_here); + __elv_add_request(q, req, ELEVATOR_INSERT_SORT, 0); } /* @@ -1880,7 +1884,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) { struct request *req, *freereq = NULL; int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra; - struct list_head *insert_here; sector_t sector; sector = bio->bi_sector; @@ -1903,7 +1906,6 @@ static int __make_request(request_queue_t *q, struct bio *bio) ra = bio->bi_rw & (1 << BIO_RW_AHEAD); again: - insert_here = NULL; spin_lock_irq(q->queue_lock); if (elv_queue_empty(q)) { @@ -1913,17 +1915,13 @@ again: if (barrier) goto get_rq; - el_ret = elv_merge(q, &insert_here, bio); + el_ret = elv_merge(q, &req, bio); switch (el_ret) { case ELEVATOR_BACK_MERGE: - req = list_entry_rq(insert_here); - BUG_ON(!rq_mergeable(req)); - if (!q->back_merge_fn(q, req, bio)) { - insert_here = &req->queuelist; + if (!q->back_merge_fn(q, req, bio)) break; - } req->biotail->bi_next = bio; req->biotail = bio; @@ -1934,14 +1932,10 @@ again: goto out; case ELEVATOR_FRONT_MERGE: - req = list_entry_rq(insert_here); - BUG_ON(!rq_mergeable(req)); - if (!q->front_merge_fn(q, req, bio)) { - insert_here = req->queuelist.prev; + if (!q->front_merge_fn(q, req, bio)) break; - } bio->bi_next = req->bio; req->cbio = req->bio = bio; @@ -2029,7 +2023,7 @@ get_rq: req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; - add_request(q, req, insert_here); + add_request(q, req); out: if (freereq) __blk_put_request(q, freereq); diff --git a/drivers/block/noop-iosched.c b/drivers/block/noop-iosched.c index 2eadd041914b..7511b955de70 100644 --- a/drivers/block/noop-iosched.c +++ b/drivers/block/noop-iosched.c @@ -17,17 +17,15 @@ /* * See if we can find a request that this buffer can be coalesced with. */ -int elevator_noop_merge(request_queue_t *q, struct list_head **insert, +int elevator_noop_merge(request_queue_t *q, struct request **req, struct bio *bio) { struct list_head *entry = &q->queue_head; struct request *__rq; int ret; - if ((ret = elv_try_last_merge(q, bio))) { - *insert = q->last_merge; + if ((ret = elv_try_last_merge(q, bio))) return ret; - } while ((entry = entry->prev) != &q->queue_head) { __rq = list_entry_rq(entry); @@ -41,8 +39,8 @@ int elevator_noop_merge(request_queue_t *q, struct list_head **insert, continue; if ((ret = elv_try_merge(__rq, bio))) { - *insert = &__rq->queuelist; - q->last_merge = &__rq->queuelist; + *req = __rq; + q->last_merge = __rq; return ret; } } @@ -57,8 +55,13 @@ void elevator_noop_merge_requests(request_queue_t *q, struct request *req, } void elevator_noop_add_request(request_queue_t *q, struct request *rq, - struct list_head *insert_here) + int where) { + struct list_head *insert = q->queue_head.prev; + + if (where == ELEVATOR_INSERT_FRONT) + insert = &q->queue_head; + list_add_tail(&rq->queuelist, &q->queue_head); /* @@ -67,7 +70,7 @@ void elevator_noop_add_request(request_queue_t *q, struct request *rq, if (rq->flags & REQ_HARDBARRIER) q->last_merge = NULL; else if (!q->last_merge) - q->last_merge = &rq->queuelist; + q->last_merge = rq; } struct request *elevator_noop_next_request(request_queue_t *q) diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index feb1d9950dc7..7db4fc7584c0 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -126,7 +126,6 @@ static int drive2[6] = { 0, 0, 0, -1, -1, -1 }; static int drive3[6] = { 0, 0, 0, -1, -1, -1 }; static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; -static int pt_drive_count; #define D_PRT 0 #define D_PRO 1 @@ -218,9 +217,7 @@ static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t * ppos); static int pt_detect(void); -static int pt_identify(int unit); - -/* bits in PT.flags */ +/* bits in tape->flags */ #define PT_MEDIA 1 #define PT_WRITE_OK 2 @@ -246,12 +243,9 @@ struct pt_unit { char name[PT_NAMELEN]; /* pf0, pf1, ... */ }; -struct pt_unit pt[PT_UNITS]; - -/* 'unit' must be defined in all functions - either as a local or a param */ +static int pt_identify(struct pt_unit *tape); -#define PT pt[unit] -#define PI PT.pi +struct pt_unit pt[PT_UNITS]; static char pt_scratch[512]; /* scratch block buffer */ @@ -266,156 +260,139 @@ static struct file_operations pt_fops = { .release = pt_release, }; -static void pt_init_units(void) +static inline int status_reg(struct pi_adapter *pi) { - int unit, j; - - pt_drive_count = 0; - for (unit = 0; unit < PT_UNITS; unit++) { - PT.pi = &PT.pia; - atomic_set(&PT.available, 1); - PT.flags = 0; - PT.last_sense = 0; - PT.present = 0; - PT.bufptr = NULL; - PT.drive = DU[D_SLV]; - j = 0; - while ((j < PT_NAMELEN - 2) && (PT.name[j] = name[j])) - j++; - PT.name[j++] = '0' + unit; - PT.name[j] = 0; - if (DU[D_PRT]) - pt_drive_count++; - } + return pi_read_regr(pi, 1, 6); } -static inline int status_reg(int unit) +static inline int read_reg(struct pi_adapter *pi, int reg) { - return pi_read_regr(PI, 1, 6); + return pi_read_regr(pi, 0, reg); } -static inline int read_reg(int unit, int reg) +static inline void write_reg(struct pi_adapter *pi, int reg, int val) { - return pi_read_regr(PI, 0, reg); + pi_write_regr(pi, 0, reg, val); } -static inline void write_reg(int unit, int reg, int val) +static inline u8 DRIVE(struct pt_unit *tape) { - pi_write_regr(PI, 0, reg, val); + return 0xa0+0x10*tape->drive; } -#define DRIVE (0xa0+0x10*PT.drive) - -static int pt_wait(int unit, int go, int stop, char *fun, char *msg) +static int pt_wait(struct pt_unit *tape, int go, int stop, char *fun, char *msg) { int j, r, e, s, p; + struct pi_adapter *pi = tape->pi; j = 0; - while ((((r = status_reg(unit)) & go) || (stop && (!(r & stop)))) + while ((((r = status_reg(pi)) & go) || (stop && (!(r & stop)))) && (j++ < PT_SPIN)) udelay(PT_SPIN_DEL); if ((r & (STAT_ERR & stop)) || (j >= PT_SPIN)) { - s = read_reg(unit, 7); - e = read_reg(unit, 1); - p = read_reg(unit, 2); + s = read_reg(pi, 7); + e = read_reg(pi, 1); + p = read_reg(pi, 2); if (j >= PT_SPIN) e |= 0x100; if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" " loop=%d phase=%d\n", - PT.name, fun, msg, r, s, e, j, p); + tape->name, fun, msg, r, s, e, j, p); return (e << 8) + s; } return 0; } -static int pt_command(int unit, char *cmd, int dlen, char *fun) +static int pt_command(struct pt_unit *tape, char *cmd, int dlen, char *fun) { - pi_connect(PI); + struct pi_adapter *pi = tape->pi; + pi_connect(pi); - write_reg(unit, 6, DRIVE); + write_reg(pi, 6, DRIVE(tape)); - if (pt_wait(unit, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) { - pi_disconnect(PI); + if (pt_wait(tape, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) { + pi_disconnect(pi); return -1; } - write_reg(unit, 4, dlen % 256); - write_reg(unit, 5, dlen / 256); - write_reg(unit, 7, 0xa0); /* ATAPI packet command */ + write_reg(pi, 4, dlen % 256); + write_reg(pi, 5, dlen / 256); + write_reg(pi, 7, 0xa0); /* ATAPI packet command */ - if (pt_wait(unit, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) { - pi_disconnect(PI); + if (pt_wait(tape, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) { + pi_disconnect(pi); return -1; } - if (read_reg(unit, 2) != 1) { - printk("%s: %s: command phase error\n", PT.name, fun); - pi_disconnect(PI); + if (read_reg(pi, 2) != 1) { + printk("%s: %s: command phase error\n", tape->name, fun); + pi_disconnect(pi); return -1; } - pi_write_block(PI, cmd, 12); + pi_write_block(pi, cmd, 12); return 0; } -static int pt_completion(int unit, char *buf, char *fun) +static int pt_completion(struct pt_unit *tape, char *buf, char *fun) { + struct pi_adapter *pi = tape->pi; int r, s, n, p; - r = pt_wait(unit, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, + r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, fun, "completion"); - if (read_reg(unit, 7) & STAT_DRQ) { - n = (((read_reg(unit, 4) + 256 * read_reg(unit, 5)) + + if (read_reg(pi, 7) & STAT_DRQ) { + n = (((read_reg(pi, 4) + 256 * read_reg(pi, 5)) + 3) & 0xfffc); - p = read_reg(unit, 2) & 3; + p = read_reg(pi, 2) & 3; if (p == 0) - pi_write_block(PI, buf, n); + pi_write_block(pi, buf, n); if (p == 2) - pi_read_block(PI, buf, n); + pi_read_block(pi, buf, n); } - s = pt_wait(unit, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done"); + s = pt_wait(tape, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done"); - pi_disconnect(PI); + pi_disconnect(pi); return (r ? r : s); } -static void pt_req_sense(int unit, int quiet) +static void pt_req_sense(struct pt_unit *tape, int quiet) { char rs_cmd[12] = { ATAPI_REQ_SENSE, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; char buf[16]; int r; - r = pt_command(unit, rs_cmd, 16, "Request sense"); + r = pt_command(tape, rs_cmd, 16, "Request sense"); mdelay(1); if (!r) - pt_completion(unit, buf, "Request sense"); + pt_completion(tape, buf, "Request sense"); - PT.last_sense = -1; + tape->last_sense = -1; if (!r) { if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n", - PT.name, buf[2] & 0xf, buf[12], buf[13]); - PT.last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8) + tape->name, buf[2] & 0xf, buf[12], buf[13]); + tape->last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16); } } -static int pt_atapi(int unit, char *cmd, int dlen, char *buf, char *fun) +static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *fun) { int r; - r = pt_command(unit, cmd, dlen, fun); + r = pt_command(tape, cmd, dlen, fun); mdelay(1); if (!r) - r = pt_completion(unit, buf, fun); + r = pt_completion(tape, buf, fun); if (r) - pt_req_sense(unit, !fun); + pt_req_sense(tape, !fun); return r; } @@ -426,8 +403,9 @@ static void pt_sleep(int cs) schedule_timeout(cs); } -static int pt_poll_dsc(int unit, int pause, int tmo, char *msg) +static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg) { + struct pi_adapter *pi = tape->pi; int k, e, s; k = 0; @@ -436,94 +414,95 @@ static int pt_poll_dsc(int unit, int pause, int tmo, char *msg) while (k < tmo) { pt_sleep(pause); k++; - pi_connect(PI); - write_reg(unit, 6, DRIVE); - s = read_reg(unit, 7); - e = read_reg(unit, 1); - pi_disconnect(PI); + pi_connect(pi); + write_reg(pi, 6, DRIVE(tape)); + s = read_reg(pi, 7); + e = read_reg(pi, 1); + pi_disconnect(pi); if (s & (STAT_ERR | STAT_SEEK)) break; } if ((k >= tmo) || (s & STAT_ERR)) { if (k >= tmo) - printk("%s: %s DSC timeout\n", PT.name, msg); + printk("%s: %s DSC timeout\n", tape->name, msg); else - printk("%s: %s stat=0x%x err=0x%x\n", PT.name, msg, s, + printk("%s: %s stat=0x%x err=0x%x\n", tape->name, msg, s, e); - pt_req_sense(unit, 0); + pt_req_sense(tape, 0); return 0; } return 1; } -static void pt_media_access_cmd(int unit, int tmo, char *cmd, char *fun) +static void pt_media_access_cmd(struct pt_unit *tape, int tmo, char *cmd, char *fun) { - if (pt_command(unit, cmd, 0, fun)) { - pt_req_sense(unit, 0); + if (pt_command(tape, cmd, 0, fun)) { + pt_req_sense(tape, 0); return; } - pi_disconnect(PI); - pt_poll_dsc(unit, HZ, tmo, fun); + pi_disconnect(tape->pi); + pt_poll_dsc(tape, HZ, tmo, fun); } -static void pt_rewind(int unit) +static void pt_rewind(struct pt_unit *tape) { char rw_cmd[12] = { ATAPI_REWIND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - pt_media_access_cmd(unit, PT_REWIND_TMO, rw_cmd, "rewind"); + pt_media_access_cmd(tape, PT_REWIND_TMO, rw_cmd, "rewind"); } -static void pt_write_fm(int unit) +static void pt_write_fm(struct pt_unit *tape) { char wm_cmd[12] = { ATAPI_WFM, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }; - pt_media_access_cmd(unit, PT_TMO, wm_cmd, "write filemark"); + pt_media_access_cmd(tape, PT_TMO, wm_cmd, "write filemark"); } #define DBMSG(msg) ((verbose>1)?(msg):NULL) -static int pt_reset(int unit) +static int pt_reset(struct pt_unit *tape) { + struct pi_adapter *pi = tape->pi; int i, k, flg; int expect[5] = { 1, 1, 1, 0x14, 0xeb }; - pi_connect(PI); - write_reg(unit, 6, DRIVE); - write_reg(unit, 7, 8); + pi_connect(pi); + write_reg(pi, 6, DRIVE(tape)); + write_reg(pi, 7, 8); pt_sleep(20 * HZ / 1000); k = 0; - while ((k++ < PT_RESET_TMO) && (status_reg(unit) & STAT_BUSY)) + while ((k++ < PT_RESET_TMO) && (status_reg(pi) & STAT_BUSY)) pt_sleep(HZ / 10); flg = 1; for (i = 0; i < 5; i++) - flg &= (read_reg(unit, i + 1) == expect[i]); + flg &= (read_reg(pi, i + 1) == expect[i]); if (verbose) { - printk("%s: Reset (%d) signature = ", PT.name, k); + printk("%s: Reset (%d) signature = ", tape->name, k); for (i = 0; i < 5; i++) - printk("%3x", read_reg(unit, i + 1)); + printk("%3x", read_reg(pi, i + 1)); if (!flg) printk(" (incorrect)"); printk("\n"); } - pi_disconnect(PI); + pi_disconnect(pi); return flg - 1; } -static int pt_ready_wait(int unit, int tmo) +static int pt_ready_wait(struct pt_unit *tape, int tmo) { char tr_cmd[12] = { ATAPI_TEST_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int k, p; k = 0; while (k < tmo) { - PT.last_sense = 0; - pt_atapi(unit, tr_cmd, 0, NULL, DBMSG("test unit ready")); - p = PT.last_sense; + tape->last_sense = 0; + pt_atapi(tape, tr_cmd, 0, NULL, DBMSG("test unit ready")); + p = tape->last_sense; if (!p) return 0; if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6))) @@ -558,7 +537,7 @@ static int xn(char *buf, int offs, int size) return v; } -static int pt_identify(int unit) +static int pt_identify(struct pt_unit *tape) { int dt, s; char *ms[2] = { "master", "slave" }; @@ -570,7 +549,7 @@ static int pt_identify(int unit) { ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 }; char buf[36]; - s = pt_atapi(unit, id_cmd, 36, buf, "identify"); + s = pt_atapi(tape, id_cmd, 36, buf, "identify"); if (s) return -1; @@ -578,36 +557,36 @@ static int pt_identify(int unit) if (dt != 1) { if (verbose) printk("%s: Drive %d, unsupported type %d\n", - PT.name, PT.drive, dt); + tape->name, tape->drive, dt); return -1; } xs(buf, mf, 8, 8); xs(buf, id, 16, 16); - PT.flags = 0; - PT.capacity = 0; - PT.bs = 0; + tape->flags = 0; + tape->capacity = 0; + tape->bs = 0; - if (!pt_ready_wait(unit, PT_READY_TMO)) - PT.flags |= PT_MEDIA; + if (!pt_ready_wait(tape, PT_READY_TMO)) + tape->flags |= PT_MEDIA; - if (!pt_atapi(unit, ms_cmd, 36, buf, "mode sense")) { + if (!pt_atapi(tape, ms_cmd, 36, buf, "mode sense")) { if (!(buf[2] & 0x80)) - PT.flags |= PT_WRITE_OK; - PT.bs = xn(buf, 10, 2); + tape->flags |= PT_WRITE_OK; + tape->bs = xn(buf, 10, 2); } - if (!pt_atapi(unit, ls_cmd, 36, buf, "log sense")) - PT.capacity = xn(buf, 24, 4); + if (!pt_atapi(tape, ls_cmd, 36, buf, "log sense")) + tape->capacity = xn(buf, 24, 4); - printk("%s: %s %s, %s", PT.name, mf, id, ms[PT.drive]); - if (!(PT.flags & PT_MEDIA)) + printk("%s: %s %s, %s", tape->name, mf, id, ms[tape->drive]); + if (!(tape->flags & PT_MEDIA)) printk(", no media\n"); else { - if (!(PT.flags & PT_WRITE_OK)) + if (!(tape->flags & PT_WRITE_OK)) printk(", RO"); - printk(", blocksize %d, %d MB\n", PT.bs, PT.capacity / 1024); + printk(", blocksize %d, %d MB\n", tape->bs, tape->capacity / 1024); } return 0; @@ -618,109 +597,117 @@ static int pt_identify(int unit) * returns 0, with id set if drive is detected * -1, if drive detection failed */ -static int pt_probe(int unit) +static int pt_probe(struct pt_unit *tape) { - if (PT.drive == -1) { - for (PT.drive = 0; PT.drive <= 1; PT.drive++) - if (!pt_reset(unit)) - return pt_identify(unit); + if (tape->drive == -1) { + for (tape->drive = 0; tape->drive <= 1; tape->drive++) + if (!pt_reset(tape)) + return pt_identify(tape); } else { - if (!pt_reset(unit)) - return pt_identify(unit); + if (!pt_reset(tape)) + return pt_identify(tape); } return -1; } static int pt_detect(void) { - int k, unit; + struct pt_unit *tape; + int specified = 0, found = 0; + int unit; printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major); - k = 0; - if (pt_drive_count == 0) { - unit = 0; - if (pi_init(PI, 1, -1, -1, -1, -1, -1, pt_scratch, - PI_PT, verbose, PT.name)) { - if (!pt_probe(unit)) { - PT.present = 1; - k++; + specified = 0; + for (unit = 0; unit < PT_UNITS; unit++) { + struct pt_unit *tape = &pt[unit]; + tape->pi = &tape->pia; + atomic_set(&tape->available, 1); + tape->flags = 0; + tape->last_sense = 0; + tape->present = 0; + tape->bufptr = NULL; + tape->drive = DU[D_SLV]; + snprintf(tape->name, PT_NAMELEN, "%s%d", name, unit); + if (!DU[D_PRT]) + continue; + specified++; + if (pi_init(tape->pi, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI], + DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT, + verbose, tape->name)) { + if (!pt_probe(tape)) { + tape->present = 1; + found++; } else - pi_release(PI); + pi_release(tape->pi); + } + } + if (specified == 0) { + tape = pt; + if (pi_init(tape->pi, 1, -1, -1, -1, -1, -1, pt_scratch, + PI_PT, verbose, tape->name)) { + if (!pt_probe(tape)) { + tape->present = 1; + found++; + } else + pi_release(tape->pi); } - } else - for (unit = 0; unit < PT_UNITS; unit++) - if (DU[D_PRT]) - if (pi_init - (PI, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI], - DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT, - verbose, PT.name)) { - if (!pt_probe(unit)) { - PT.present = 1; - k++; - } else - pi_release(PI); - } - - if (k) + } + if (found) return 0; printk("%s: No ATAPI tape drive detected\n", name); return -1; } -#define DEVICE_NR(inode) (iminor(inode) & 0x7F) - static int pt_open(struct inode *inode, struct file *file) { - int unit = DEVICE_NR(inode); + int unit = iminor(inode) & 0x7F; + struct pt_unit *tape = pt + unit; + int err; - if ((unit >= PT_UNITS) || (!PT.present)) + if (unit >= PT_UNITS || (!tape->present)) return -ENODEV; - if (!atomic_dec_and_test(&PT.available)) { - atomic_inc(&PT.available); - return -EBUSY; - } + err = -EBUSY; + if (!atomic_dec_and_test(&tape->available)) + goto out; - pt_identify(unit); + pt_identify(tape); - if (!PT.flags & PT_MEDIA) { - atomic_inc(&PT.available); - return -ENODEV; - } + err = -ENODEV; + if (!tape->flags & PT_MEDIA) + goto out; - if ((!PT.flags & PT_WRITE_OK) && (file->f_mode & 2)) { - atomic_inc(&PT.available); - return -EROFS; - } + err = -EROFS; + if ((!tape->flags & PT_WRITE_OK) && (file->f_mode & 2)) + goto out; if (!(iminor(inode) & 128)) - PT.flags |= PT_REWIND; + tape->flags |= PT_REWIND; - PT.bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL); - if (PT.bufptr == NULL) { - atomic_inc(&PT.available); - printk("%s: buffer allocation failed\n", PT.name); - return -ENOMEM; + err = -ENOMEM; + tape->bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL); + if (tape->bufptr == NULL) { + printk("%s: buffer allocation failed\n", tape->name); + goto out; } + file->private_data = tape; return 0; + +out: + atomic_inc(&tape->available); + return err; } static int pt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int unit; + struct pt_unit *tape = file->private_data; struct mtop mtop; - unit = DEVICE_NR(inode); - if (unit >= PT_UNITS) - return -EINVAL; - if (!PT.present) - return -ENODEV; - switch (cmd) { case MTIOCTOP: if (copy_from_user((char *) &mtop, (char *) arg, @@ -730,21 +717,21 @@ static int pt_ioctl(struct inode *inode, struct file *file, switch (mtop.mt_op) { case MTREW: - pt_rewind(unit); + pt_rewind(tape); return 0; case MTWEOF: - pt_write_fm(unit); + pt_write_fm(tape); return 0; default: - printk("%s: Unimplemented mt_op %d\n", PT.name, + printk("%s: Unimplemented mt_op %d\n", tape->name, mtop.mt_op); return -EINVAL; } default: - printk("%s: Unimplemented ioctl 0x%x\n", PT.name, cmd); + printk("%s: Unimplemented ioctl 0x%x\n", tape->name, cmd); return -EINVAL; } @@ -753,21 +740,21 @@ static int pt_ioctl(struct inode *inode, struct file *file, static int pt_release(struct inode *inode, struct file *file) { - int unit = DEVICE_NR(inode); + struct pt_unit *tape = file->private_data; - if ((unit >= PT_UNITS) || (atomic_read(&PT.available) > 1)) + if (atomic_read(&tape->available) > 1) return -EINVAL; - if (PT.flags & PT_WRITING) - pt_write_fm(unit); + if (tape->flags & PT_WRITING) + pt_write_fm(tape); - if (PT.flags & PT_REWIND) - pt_rewind(unit); + if (tape->flags & PT_REWIND) + pt_rewind(tape); - kfree(PT.bufptr); - PT.bufptr = NULL; + kfree(tape->bufptr); + tape->bufptr = NULL; - atomic_inc(&PT.available); + atomic_inc(&tape->available); return 0; @@ -775,70 +762,70 @@ pt_release(struct inode *inode, struct file *file) static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos) { - struct inode *ino = filp->f_dentry->d_inode; - int unit = DEVICE_NR(ino); + struct pt_unit *tape = filp->private_data; + struct pi_adapter *pi = tape->pi; char rd_cmd[12] = { ATAPI_READ_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int k, n, r, p, s, t, b; - if (!(PT.flags & (PT_READING | PT_WRITING))) { - PT.flags |= PT_READING; - if (pt_atapi(unit, rd_cmd, 0, NULL, "start read-ahead")) + if (!(tape->flags & (PT_READING | PT_WRITING))) { + tape->flags |= PT_READING; + if (pt_atapi(tape, rd_cmd, 0, NULL, "start read-ahead")) return -EIO; - } else if (PT.flags & PT_WRITING) + } else if (tape->flags & PT_WRITING) return -EIO; - if (PT.flags & PT_EOF) + if (tape->flags & PT_EOF) return 0; t = 0; while (count > 0) { - if (!pt_poll_dsc(unit, HZ / 100, PT_TMO, "read")) + if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "read")) return -EIO; n = count; if (n > 32768) n = 32768; /* max per command */ - b = (n - 1 + PT.bs) / PT.bs; - n = b * PT.bs; /* rounded up to even block */ + b = (n - 1 + tape->bs) / tape->bs; + n = b * tape->bs; /* rounded up to even block */ rd_cmd[4] = b; - r = pt_command(unit, rd_cmd, n, "read"); + r = pt_command(tape, rd_cmd, n, "read"); mdelay(1); if (r) { - pt_req_sense(unit, 0); + pt_req_sense(tape, 0); return -EIO; } while (1) { - r = pt_wait(unit, STAT_BUSY, + r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_ERR | STAT_READY, DBMSG("read DRQ"), ""); if (r & STAT_SENSE) { - pi_disconnect(PI); - pt_req_sense(unit, 0); + pi_disconnect(pi); + pt_req_sense(tape, 0); return -EIO; } if (r) - PT.flags |= PT_EOF; + tape->flags |= PT_EOF; - s = read_reg(unit, 7); + s = read_reg(pi, 7); if (!(s & STAT_DRQ)) break; - n = (read_reg(unit, 4) + 256 * read_reg(unit, 5)); - p = (read_reg(unit, 2) & 3); + n = (read_reg(pi, 4) + 256 * read_reg(pi, 5)); + p = (read_reg(pi, 2) & 3); if (p != 2) { - pi_disconnect(PI); - printk("%s: Phase error on read: %d\n", PT.name, + pi_disconnect(pi); + printk("%s: Phase error on read: %d\n", tape->name, p); return -EIO; } @@ -847,13 +834,13 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos k = n; if (k > PT_BUFSIZE) k = PT_BUFSIZE; - pi_read_block(PI, PT.bufptr, k); + pi_read_block(pi, tape->bufptr, k); n -= k; b = k; if (b > count) b = count; - if (copy_to_user(buf + t, PT.bufptr, b)) { - pi_disconnect(PI); + if (copy_to_user(buf + t, tape->bufptr, b)) { + pi_disconnect(pi); return -EFAULT; } t += b; @@ -861,8 +848,8 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos } } - pi_disconnect(PI); - if (PT.flags & PT_EOF) + pi_disconnect(pi); + if (tape->flags & PT_EOF) break; } @@ -872,75 +859,75 @@ static ssize_t pt_read(struct file *filp, char *buf, size_t count, loff_t * ppos static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t * ppos) { - struct inode *ino = filp->f_dentry->d_inode; - int unit = DEVICE_NR(ino); + struct pt_unit *tape = filp->private_data; + struct pi_adapter *pi = tape->pi; char wr_cmd[12] = { ATAPI_WRITE_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int k, n, r, p, s, t, b; - if (!(PT.flags & PT_WRITE_OK)) + if (!(tape->flags & PT_WRITE_OK)) return -EROFS; - if (!(PT.flags & (PT_READING | PT_WRITING))) { - PT.flags |= PT_WRITING; + if (!(tape->flags & (PT_READING | PT_WRITING))) { + tape->flags |= PT_WRITING; if (pt_atapi - (unit, wr_cmd, 0, NULL, "start buffer-available mode")) + (tape, wr_cmd, 0, NULL, "start buffer-available mode")) return -EIO; - } else if (PT.flags & PT_READING) + } else if (tape->flags & PT_READING) return -EIO; - if (PT.flags & PT_EOF) + if (tape->flags & PT_EOF) return -ENOSPC; t = 0; while (count > 0) { - if (!pt_poll_dsc(unit, HZ / 100, PT_TMO, "write")) + if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "write")) return -EIO; n = count; if (n > 32768) n = 32768; /* max per command */ - b = (n - 1 + PT.bs) / PT.bs; - n = b * PT.bs; /* rounded up to even block */ + b = (n - 1 + tape->bs) / tape->bs; + n = b * tape->bs; /* rounded up to even block */ wr_cmd[4] = b; - r = pt_command(unit, wr_cmd, n, "write"); + r = pt_command(tape, wr_cmd, n, "write"); mdelay(1); if (r) { /* error delivering command only */ - pt_req_sense(unit, 0); + pt_req_sense(tape, 0); return -EIO; } while (1) { - r = pt_wait(unit, STAT_BUSY, + r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_ERR | STAT_READY, DBMSG("write DRQ"), NULL); if (r & STAT_SENSE) { - pi_disconnect(PI); - pt_req_sense(unit, 0); + pi_disconnect(pi); + pt_req_sense(tape, 0); return -EIO; } if (r) - PT.flags |= PT_EOF; + tape->flags |= PT_EOF; - s = read_reg(unit, 7); + s = read_reg(pi, 7); if (!(s & STAT_DRQ)) break; - n = (read_reg(unit, 4) + 256 * read_reg(unit, 5)); - p = (read_reg(unit, 2) & 3); + n = (read_reg(pi, 4) + 256 * read_reg(pi, 5)); + p = (read_reg(pi, 2) & 3); if (p != 0) { - pi_disconnect(PI); + pi_disconnect(pi); printk("%s: Phase error on write: %d \n", - PT.name, p); + tape->name, p); return -EIO; } @@ -951,19 +938,19 @@ static ssize_t pt_write(struct file *filp, const char *buf, size_t count, loff_t b = k; if (b > count) b = count; - if (copy_from_user(PT.bufptr, buf + t, b)) { - pi_disconnect(PI); + if (copy_from_user(tape->bufptr, buf + t, b)) { + pi_disconnect(pi); return -EFAULT; } - pi_write_block(PI, PT.bufptr, k); + pi_write_block(pi, tape->bufptr, k); t += b; count -= b; n -= k; } } - pi_disconnect(PI); - if (PT.flags & PT_EOF) + pi_disconnect(pi); + if (tape->flags & PT_EOF) break; } @@ -977,22 +964,20 @@ static int __init pt_init(void) if (disable) return -1; - pt_init_units(); - if (pt_detect()) return -1; if (register_chrdev(major, name, &pt_fops)) { printk("pt_init: unable to get major number %d\n", major); for (unit = 0; unit < PT_UNITS; unit++) - if (PT.present) - pi_release(PI); + if (pt[unit].present) + pi_release(pt[unit].pi); return -1; } devfs_mk_dir("pt"); for (unit = 0; unit < PT_UNITS; unit++) - if (PT.present) { + if (pt[unit].present) { devfs_mk_cdev(MKDEV(major, unit), S_IFCHR | S_IRUSR | S_IWUSR, "pt/%d", unit); @@ -1007,15 +992,15 @@ static void __exit pt_exit(void) { int unit; for (unit = 0; unit < PT_UNITS; unit++) - if (PT.present) { + if (pt[unit].present) { devfs_remove("pt/%d", unit); devfs_remove("pt/%dn", unit); } devfs_remove("pt"); unregister_chrdev(major, name); for (unit = 0; unit < PT_UNITS; unit++) - if (PT.present) - pi_release(PI); + if (pt[unit].present) + pi_release(pt[unit].pi); } MODULE_LICENSE("GPL"); diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 94574b14f30b..3d18a7a70108 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -68,7 +68,7 @@ static int blk_do_rq(request_queue_t *q, struct block_device *bdev, rq->flags |= REQ_NOMERGE; rq->waiting = &wait; - elv_add_request(q, rq, 1, 1); + elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); generic_unplug_device(q); wait_for_completion(&wait); diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 7358eed7a348..3e30720a167c 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -63,8 +63,7 @@ config AGP_AMD You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI. If unsure, say N. -# RED-PEN this option is misnamed, it's not 8151 specific -config AGP_AMD_8151 +config AGP_AMD64 tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU depends on AGP && X86 default y if GART_IOMMU diff --git a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile index b537a8394cf1..16194948cc54 100644 --- a/drivers/char/agp/Makefile +++ b/drivers/char/agp/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_AGP) += agpgart.o obj-$(CONFIG_AGP_ALI) += ali-agp.o obj-$(CONFIG_AGP_ATI) += ati-agp.o obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o -obj-$(CONFIG_AGP_AMD_8151) += amd-k8-agp.o +obj-$(CONFIG_AGP_AMD64) += amd64-agp.o obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o obj-$(CONFIG_AGP_I460) += i460-agp.o diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 2a4b9e0dc363..ee679cbdf6d2 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -302,7 +302,7 @@ struct agp_bridge_data { #define AMD64_GARTAPERTUREBASE 0x94 #define AMD64_GARTTABLEBASE 0x98 #define AMD64_GARTCACHECTL 0x9c -#define AMD64_GARTEN 1<<0 +#define AMD64_GARTEN (1<<0) /* ALi registers */ #define ALI_AGPCTRL 0xb8 diff --git a/drivers/char/agp/amd-k8-agp.c b/drivers/char/agp/amd64-agp.c index d147b09056bc..f60cb63720d8 100644 --- a/drivers/char/agp/amd-k8-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -14,7 +14,7 @@ #include <linux/agp_backend.h> #include "agp.h" -/* Will need to be increased if hammer ever goes >8-way. */ +/* Will need to be increased if AMD64 ever goes >8-way. */ #ifdef CONFIG_SMP #define MAX_HAMMER_GARTS 8 #else @@ -26,13 +26,13 @@ #define GPTE_COHERENT 2 /* Aperture control register bits. */ -#define GARTEN 1<<0 -#define DISGARTCPU 1<<4 -#define DISGARTIO 1<<5 +#define GARTEN (1<<0) +#define DISGARTCPU (1<<4) +#define DISGARTIO (1<<5) /* GART cache control register bits. */ -#define INVGART 1<<0 -#define GARTPTEERR 1<<1 +#define INVGART (1<<0) +#define GARTPTEERR (1<<1) static int nr_garts; static struct pci_dev * hammers[MAX_HAMMER_GARTS]; @@ -42,7 +42,7 @@ static int __initdata agp_try_unsupported; static int gart_iterator; #define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++) -static void flush_x86_64_tlb(struct pci_dev *dev) +static void flush_amd64_tlb(struct pci_dev *dev) { u32 tmp; @@ -51,13 +51,13 @@ static void flush_x86_64_tlb(struct pci_dev *dev) pci_write_config_dword (dev, AMD64_GARTCACHECTL, tmp); } -static void amd_x86_64_tlbflush(struct agp_memory *temp) +static void amd64_tlbflush(struct agp_memory *temp) { for_each_nb() - flush_x86_64_tlb(hammers[gart_iterator]); + flush_amd64_tlb(hammers[gart_iterator]); } -static int x86_64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) +static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { int i, j, num_entries; long tmp; @@ -97,7 +97,7 @@ static int x86_64_insert_memory(struct agp_memory *mem, off_t pg_start, int type agp_bridge->gatt_table[j] = pte; } - amd_x86_64_tlbflush(mem); + amd64_tlbflush(mem); return 0; } @@ -106,7 +106,7 @@ static int x86_64_insert_memory(struct agp_memory *mem, off_t pg_start, int type * to the size of a long. It sucks. I totally disown this, even * though it does appear to work for the most part. */ -static struct aper_size_info_32 x86_64_aperture_sizes[7] = +static struct aper_size_info_32 amd64_aperture_sizes[7] = { {32, 8192, 3+(sizeof(long)/8), 0 }, {64, 16384, 4+(sizeof(long)/8), 1<<1 }, @@ -124,7 +124,7 @@ static struct aper_size_info_32 x86_64_aperture_sizes[7] = * the value from the first one we find. The set_size functions * keep the rest coherent anyway. Or at least should do. */ -static int amd_x86_64_fetch_size(void) +static int amd64_fetch_size(void) { struct pci_dev *dev; int i; @@ -137,7 +137,7 @@ static int amd_x86_64_fetch_size(void) pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &temp); temp = (temp & 0xe); - values = A_SIZE_32(x86_64_aperture_sizes); + values = A_SIZE_32(amd64_aperture_sizes); for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { @@ -155,7 +155,7 @@ static int amd_x86_64_fetch_size(void) * In a multiprocessor x86-64 system, this function gets * called once for each CPU. */ -static u64 amd_x86_64_configure (struct pci_dev *hammer, u64 gatt_table) +static u64 amd64_configure (struct pci_dev *hammer, u64 gatt_table) { u64 aperturebase; u32 tmp; @@ -180,7 +180,7 @@ static u64 amd_x86_64_configure (struct pci_dev *hammer, u64 gatt_table) pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp); /* keep CPU's coherent. */ - flush_x86_64_tlb (hammer); + flush_amd64_tlb (hammer); return aper_base; } @@ -204,13 +204,13 @@ static int amd_8151_configure(void) /* Configure AGP regs in each x86-64 host bridge. */ for_each_nb() { agp_bridge->gart_bus_addr = - amd_x86_64_configure(hammers[gart_iterator],gatt_bus); + amd64_configure(hammers[gart_iterator],gatt_bus); } return 0; } -static void amd_8151_cleanup(void) +static void amd64_cleanup(void) { u32 tmp; @@ -229,16 +229,16 @@ struct agp_bridge_driver amd_8151_driver = { .size_type = U32_APER_SIZE, .num_aperture_sizes = 7, .configure = amd_8151_configure, - .fetch_size = amd_x86_64_fetch_size, - .cleanup = amd_8151_cleanup, - .tlb_flush = amd_x86_64_tlbflush, + .fetch_size = amd64_fetch_size, + .cleanup = amd64_cleanup, + .tlb_flush = amd64_tlbflush, .mask_memory = agp_generic_mask_memory, .masks = NULL, .agp_enable = agp_generic_enable, .cache_flush = global_cache_flush, .create_gatt_table = agp_generic_create_gatt_table, .free_gatt_table = agp_generic_free_gatt_table, - .insert_memory = x86_64_insert_memory, + .insert_memory = amd64_insert_memory, .remove_memory = agp_generic_remove_memory, .alloc_by_type = agp_generic_alloc_by_type, .free_by_type = agp_generic_free_by_type, @@ -364,13 +364,13 @@ static __init int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) return i == 0 ? -1 : 0; } -static int __init agp_amdk8_probe(struct pci_dev *pdev, +static int __init agp_amd64_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_bridge_data *bridge; u8 rev_id; u8 cap_ptr; - char *revstring=" "; + char *revstring=NULL; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); if (!cap_ptr) @@ -431,17 +431,17 @@ static int __init agp_amdk8_probe(struct pci_dev *pdev, return agp_add_bridge(bridge); } -static void __devexit agp_amdk8_remove(struct pci_dev *pdev) +static void __devexit agp_amd64_remove(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); release_mem_region(virt_to_phys(bridge->gatt_table_real), - x86_64_aperture_sizes[bridge->aperture_size_idx].size); + amd64_aperture_sizes[bridge->aperture_size_idx].size); agp_remove_bridge(bridge); agp_put_bridge(bridge); } -static struct pci_device_id agp_amdk8_pci_table[] = { +static struct pci_device_id agp_amd64_pci_table[] = { { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, @@ -479,23 +479,23 @@ static struct pci_device_id agp_amdk8_pci_table[] = { { } }; -MODULE_DEVICE_TABLE(pci, agp_amdk8_pci_table); +MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); -static struct pci_driver agp_amdk8_pci_driver = { - .name = "agpgart-amd-k8", - .id_table = agp_amdk8_pci_table, - .probe = agp_amdk8_probe, - .remove = agp_amdk8_remove, +static struct pci_driver agp_amd64_pci_driver = { + .name = "agpgart-amd64", + .id_table = agp_amd64_pci_table, + .probe = agp_amd64_probe, + .remove = agp_amd64_remove, }; /* Not static due to IOMMU code calling it early. */ -int __init agp_amdk8_init(void) +int __init agp_amd64_init(void) { int err = 0; if (agp_off) return -EINVAL; - if (pci_module_init(&agp_amdk8_pci_driver) == 0) { + if (pci_module_init(&agp_amd64_pci_driver) == 0) { struct pci_dev *dev; if (!agp_try_unsupported && !agp_try_unsupported_boot) { printk(KERN_INFO "No supported AGP bridge found.\n"); @@ -507,7 +507,7 @@ int __init agp_amdk8_init(void) return -ENODEV; } - /* First check that we have at least one K8 NB */ + /* First check that we have at least one AMD64 NB */ if (!pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, NULL)) return -ENODEV; @@ -518,7 +518,7 @@ int __init agp_amdk8_init(void) if (!pci_find_capability(dev, PCI_CAP_ID_AGP)) continue; /* Only one bridge supported right now */ - if (agp_amdk8_probe(dev, NULL) == 0) { + if (agp_amd64_probe(dev, NULL) == 0) { err = 0; break; } @@ -527,16 +527,16 @@ int __init agp_amdk8_init(void) return err; } -static void __exit agp_amdk8_cleanup(void) +static void __exit agp_amd64_cleanup(void) { - pci_unregister_driver(&agp_amdk8_pci_driver); + pci_unregister_driver(&agp_amd64_pci_driver); } -/* On x86-64 the PCI driver needs to initialize this driver early +/* On AMD64 the PCI driver needs to initialize this driver early for the IOMMU, so it has to be called via a backdoor. */ #ifndef CONFIG_GART_IOMMU -module_init(agp_amdk8_init); -module_exit(agp_amdk8_cleanup); +module_init(agp_amd64_init); +module_exit(agp_amd64_cleanup); #endif MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>, Andi Kleen"); diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 336fdda5fe91..2f70f417f221 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -128,7 +128,7 @@ static int i460_fetch_size (void) if (temp & I460_BAPBASE_ENABLE) i460.dynamic_apbase = INTEL_I460_BAPBASE; else - i460.dynamic_apbase = INTEL_I460_APBASE; + i460.dynamic_apbase = AGP_APBASE; for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { /* diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index b410b22f907e..2cfca61b9801 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -158,10 +158,6 @@ /** \name Backward compatibility section */ /*@{*/ -#ifndef minor -#define minor(x) MINOR((x)) -#endif - #ifndef MODULE_LICENSE #define MODULE_LICENSE(x) #endif diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 883066efbd72..6cc938bbbf30 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -50,9 +50,6 @@ #include <asm/system.h> #include <asm/bitops.h> -#define IS_CONSOLE_DEV(dev) (kdev_val(dev) == __mkdev(TTY_MAJOR,0)) -#define IS_SYSCONS_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1)) - /* number of characters left in xmit buffer before select has we have room */ #define WAKEUP_CHARS 256 @@ -951,6 +948,8 @@ static inline int copy_from_read_buf(struct tty_struct *tty, return retval; } +extern ssize_t redirected_tty_write(struct file *,const char *,size_t,loff_t *); + static ssize_t read_chan(struct tty_struct *tty, struct file *file, unsigned char *buf, size_t nr) { @@ -975,9 +974,7 @@ do_it_again: /* NOTE: not yet done after every sleep pending a thorough check of the logic of this change. -- jlc */ /* don't stop on /dev/console */ - if (!IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) && - !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev) && - current->tty == tty) { + if (file->f_op->write != redirected_tty_write && current->tty == tty) { if (tty->pgrp <= 0) printk("read_chan: tty->pgrp <= 0!\n"); else if (current->pgrp != tty->pgrp) { @@ -1168,9 +1165,7 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file, ssize_t retval = 0; /* Job control check -- must be done at start (POSIX.1 7.1.1.4). */ - if (L_TOSTOP(tty) && - !IS_CONSOLE_DEV(file->f_dentry->d_inode->i_rdev) && - !IS_SYSCONS_DEV(file->f_dentry->d_inode->i_rdev)) { + if (L_TOSTOP(tty) && file->f_op->write != redirected_tty_write) { retval = tty_check_change(tty); if (retval) return retval; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 3ecc2b9a666e..e14a3ce8928d 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/pcmcia/synclink_cs.c * - * $Id: synclink_cs.c,v 4.13 2003/06/18 15:29:32 paulkf Exp $ + * $Id: synclink_cs.c,v 4.15 2003/09/05 15:26:02 paulkf Exp $ * * Device driver for Microgate SyncLink PC Card * multiprotocol serial adapter. @@ -491,7 +491,7 @@ MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i"); MODULE_LICENSE("GPL"); static char *driver_name = "SyncLink PC Card driver"; -static char *driver_version = "$Revision: 4.13 $"; +static char *driver_version = "$Revision: 4.15 $"; static struct tty_driver *serial_driver; @@ -838,6 +838,9 @@ static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, printk(badmagic, name, routine); return 1; } +#else + if (!info) + return 1; #endif return 0; } diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 4275bb8521f0..8f969928c68b 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1460,17 +1460,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, return 0; } -#if (defined(ROCKET_DEBUG_FLOW) || defined(ROCKET_DEBUG_THROTTLE)) -static char *rp_tty_name(struct tty_struct *tty, char *buf) -{ - if (tty) - sprintf(buf, "%s%d", TTY_DRIVER_NAME(tty), MINOR(tty->device) - TTY_DRIVER_MINOR_START(tty) + TTY_DRIVER_NAME_BASE); - else - strcpy(buf, "NULL tty"); - return buf; -} -#endif - static void rp_send_xchar(struct tty_struct *tty, char ch) { struct r_port *info = (struct r_port *) tty->driver_data; @@ -1490,10 +1479,9 @@ static void rp_throttle(struct tty_struct *tty) { struct r_port *info = (struct r_port *) tty->driver_data; CHANNEL_t *cp; -#ifdef ROCKET_DEBUG_THROTTLE - char buf[64]; - printk(KERN_INFO "throttle %s: %d....\n", rp_tty_name(tty, buf), +#ifdef ROCKET_DEBUG_THROTTLE + printk(KERN_INFO "throttle %s: %d....\n", tty->name, tty->ldisc.chars_in_buffer(tty)); #endif @@ -1512,9 +1500,7 @@ static void rp_unthrottle(struct tty_struct *tty) struct r_port *info = (struct r_port *) tty->driver_data; CHANNEL_t *cp; #ifdef ROCKET_DEBUG_THROTTLE - char buf[64]; - - printk(KERN_INFO "unthrottle %s: %d....\n", rp_tty_name(tty, buf), + printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, tty->ldisc.chars_in_buffer(tty)); #endif @@ -1539,10 +1525,9 @@ static void rp_unthrottle(struct tty_struct *tty) static void rp_stop(struct tty_struct *tty) { struct r_port *info = (struct r_port *) tty->driver_data; -#ifdef ROCKET_DEBUG_FLOW - char buf[64]; - printk(KERN_INFO "stop %s: %d %d....\n", rp_tty_name(tty, buf), +#ifdef ROCKET_DEBUG_FLOW + printk(KERN_INFO "stop %s: %d %d....\n", tty->name, info->xmit_cnt, info->xmit_fifo_room); #endif @@ -1556,10 +1541,9 @@ static void rp_stop(struct tty_struct *tty) static void rp_start(struct tty_struct *tty) { struct r_port *info = (struct r_port *) tty->driver_data; -#ifdef ROCKET_DEBUG_FLOW - char buf[64]; - printk(KERN_INFO "start %s: %d %d....\n", rp_tty_name(tty, buf), +#ifdef ROCKET_DEBUG_FLOW + printk(KERN_INFO "start %s: %d %d....\n", tty->name, info->xmit_cnt, info->xmit_fifo_room); #endif diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index bf80e670091d..e55e9abb184d 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * $Id: synclink.c,v 4.12 2003/06/18 15:29:32 paulkf Exp $ + * $Id: synclink.c,v 4.16 2003/09/05 15:26:02 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -261,6 +261,7 @@ struct mgsl_struct { int rx_enabled; int rx_overflow; + int rx_rcc_underrun; int tx_enabled; int tx_active; @@ -910,7 +911,7 @@ MODULE_PARM(txdmabufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "$Revision: 4.12 $"; +static char *driver_version = "$Revision: 4.16 $"; static int synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent); @@ -983,6 +984,9 @@ static inline int mgsl_paranoia_check(struct mgsl_struct *info, printk(badmagic, name, routine); return 1; } +#else + if (!info) + return 1; #endif return 0; } @@ -1125,7 +1129,16 @@ void mgsl_bh_receive(struct mgsl_struct *info) printk( "%s(%d):mgsl_bh_receive(%s)\n", __FILE__,__LINE__,info->device_name); - while( (get_rx_frame)(info) ); + do + { + if (info->rx_rcc_underrun) { + unsigned long flags; + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_start_receiver(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + return; + } + } while(get_rx_frame(info)); } void mgsl_bh_transmit(struct mgsl_struct *info) @@ -1567,6 +1580,21 @@ void mgsl_isr_misc( struct mgsl_struct *info ) printk("%s(%d):mgsl_isr_misc status=%04X\n", __FILE__,__LINE__,status); + if ((status & MISCSTATUS_RCC_UNDERRUN) && + (info->params.mode == MGSL_MODE_HDLC)) { + + /* turn off receiver and rx DMA */ + usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); + usc_DmaCmd(info, DmaCmd_ResetRxChannel); + usc_UnlatchRxstatusBits(info, RXSTATUS_ALL); + usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS); + usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS); + + /* schedule BH handler to restart receiver */ + info->pending_bh |= BH_RECEIVE; + info->rx_rcc_underrun = 1; + } + usc_ClearIrqPendingBits( info, MISC ); usc_UnlatchMiscstatusBits( info, status ); @@ -3625,7 +3653,7 @@ static inline int line_info(char *buf, struct mgsl_struct *info) if (info->icount.rxover) ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); if (info->icount.rxcrc) - ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc); + ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); } else { ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", info->icount.tx, info->icount.rx); @@ -5190,7 +5218,11 @@ void usc_set_sdlc_mode( struct mgsl_struct *info ) usc_EnableMasterIrqBit( info ); usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA + - TRANSMIT_STATUS + TRANSMIT_DATA ); + TRANSMIT_STATUS + TRANSMIT_DATA + MISC); + + /* arm RCC underflow interrupt */ + usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3)); + usc_EnableInterrupts(info, MISC); info->mbre_bit = 0; outw( 0, info->io_base ); /* clear Master Bus Enable (DCAR) */ @@ -5628,6 +5660,7 @@ void usc_stop_receiver( struct mgsl_struct *info ) info->rx_enabled = 0; info->rx_overflow = 0; + info->rx_rcc_underrun = 0; } /* end of stop_receiver() */ diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index ae3d9c41b668..587dcb3a669d 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -1,5 +1,5 @@ /* - * $Id: synclinkmp.c,v 4.12 2003/06/18 15:29:33 paulkf Exp $ + * $Id: synclinkmp.c,v 4.14 2003/09/05 15:26:03 paulkf Exp $ * * Device driver for Microgate SyncLink Multiport * high speed multiprotocol serial adapter. @@ -496,7 +496,7 @@ MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICES) "i"); MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i"); static char *driver_name = "SyncLink MultiPort driver"; -static char *driver_version = "$Revision: 4.12 $"; +static char *driver_version = "$Revision: 4.14 $"; static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); static void synclinkmp_remove_one(struct pci_dev *dev); @@ -713,6 +713,9 @@ static inline int sanity_check(SLMP_INFO *info, printk(badmagic, name, routine); return 1; } +#else + if (!info) + return 1; #endif return 0; } diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 660f7b0f1487..fc1558cab6e0 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -74,7 +74,6 @@ #define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) #if LINUX_VERSION_CODE < VERSION(2,5,0) -# define minor(x) MINOR(x) # define need_resched() (current->need_resched) #endif diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index aab1780082fc..8d1f8c6d3c23 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -103,11 +103,6 @@ #include <linux/kmod.h> -#define IS_CONSOLE_DEV(dev) (kdev_val(dev) == __mkdev(TTY_MAJOR,0)) -#define IS_TTY_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,0)) -#define IS_SYSCONS_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,1)) -#define IS_PTMX_DEV(dev) (kdev_val(dev) == __mkdev(TTYAUX_MAJOR,2)) - #undef TTY_DEBUG_HANGUP #define TTY_PARANOIA_CHECK 1 @@ -136,6 +131,7 @@ static void initialize_tty_struct(struct tty_struct *tty); static ssize_t tty_read(struct file *, char *, size_t, loff_t *); static ssize_t tty_write(struct file *, const char *, size_t, loff_t *); +ssize_t redirected_tty_write(struct file *, const char *, size_t, loff_t *); static unsigned int tty_poll(struct file *, poll_table *); static int tty_open(struct inode *, struct file *); static int tty_release(struct inode *, struct file *); @@ -181,17 +177,16 @@ inline int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, const char *routine) { #ifdef TTY_PARANOIA_CHECK - static const char badmagic[] = KERN_WARNING - "Warning: bad magic number for tty struct (%s) in %s\n"; - static const char badtty[] = KERN_WARNING - "Warning: null TTY for (%s) in %s\n"; - if (!tty) { - printk(badtty, cdevname(inode->i_rdev), routine); + printk(KERN_WARNING + "null TTY for (%d:%d) in %s\n", + imajor(inode), iminor(inode), routine); return 1; } if (tty->magic != TTY_MAGIC) { - printk(badmagic, cdevname(inode->i_rdev), routine); + printk(KERN_WARNING + "bad magic number for tty struct (%d:%d) in %s\n", + imajor(inode), iminor(inode), routine); return 1; } #endif @@ -383,6 +378,17 @@ static struct file_operations tty_fops = { .fasync = tty_fasync, }; +static struct file_operations console_fops = { + .llseek = no_llseek, + .read = tty_read, + .write = redirected_tty_write, + .poll = tty_poll, + .ioctl = tty_ioctl, + .open = tty_open, + .release = tty_release, + .fasync = tty_fasync, +}; + static struct file_operations hung_up_tty_fops = { .llseek = no_llseek, .read = hung_up_tty_read, @@ -426,12 +432,9 @@ void do_tty_hangup(void *data) check_tty_count(tty, "do_tty_hangup"); file_list_lock(); list_for_each_entry(filp, &tty->tty_files, f_list) { - if (IS_CONSOLE_DEV(filp->f_dentry->d_inode->i_rdev) || - IS_SYSCONS_DEV(filp->f_dentry->d_inode->i_rdev)) { + if (filp->f_op->write == redirected_tty_write) cons_filp = filp; - continue; - } - if (filp->f_op != &tty_fops) + if (filp->f_op->write != tty_write) continue; closecount++; tty_fasync(-1, filp, 0); /* can't block */ @@ -651,22 +654,6 @@ static ssize_t tty_read(struct file * file, char * buf, size_t count, if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags))) return -EIO; - /* This check not only needs to be done before reading, but also - whenever read_chan() gets woken up after sleeping, so I've - moved it to there. This should only be done for the N_TTY - line discipline, anyway. Same goes for write_chan(). -- jlc. */ -#if 0 - if (!IS_CONSOLE_DEV(inode->i_rdev) && /* don't stop on /dev/console */ - (tty->pgrp > 0) && - (current->tty == tty) && - (tty->pgrp != current->pgrp)) - if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp)) - return -EIO; - else { - (void) kill_pg(current->pgrp, SIGTTIN, 1); - return -ERESTARTSYS; - } -#endif lock_kernel(); if (tty->ldisc.read) i = (tty->ldisc.read)(tty,file,buf,count); @@ -731,37 +718,13 @@ static inline ssize_t do_tty_write( static ssize_t tty_write(struct file * file, const char * buf, size_t count, loff_t *ppos) { - int is_console; struct tty_struct * tty; struct inode *inode = file->f_dentry->d_inode; - /* - * For now, we redirect writes from /dev/console as - * well as /dev/tty0. - */ - is_console = IS_SYSCONS_DEV(inode->i_rdev) || - IS_CONSOLE_DEV(inode->i_rdev); /* Can't seek (pwrite) on ttys. */ if (ppos != &file->f_pos) return -ESPIPE; - if (is_console) { - struct file *p = NULL; - - spin_lock(&redirect_lock); - if (redirect) { - get_file(redirect); - p = redirect; - } - spin_unlock(&redirect_lock); - - if (p) { - ssize_t res = vfs_write(p, buf, count, &p->f_pos); - fput(p); - return res; - } - } - tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode, "tty_write")) return -EIO; @@ -773,6 +736,31 @@ static ssize_t tty_write(struct file * file, const char * buf, size_t count, (const unsigned char *)buf, count); } +ssize_t redirected_tty_write(struct file * file, const char * buf, size_t count, + loff_t *ppos) +{ + struct file *p = NULL; + + spin_lock(&redirect_lock); + if (redirect) { + get_file(redirect); + p = redirect; + } + spin_unlock(&redirect_lock); + + if (p) { + ssize_t res; + /* Can't seek (pwrite) on ttys. */ + if (ppos != &file->f_pos) + return -ESPIPE; + res = vfs_write(p, buf, count, &p->f_pos); + fput(p); + return res; + } + + return tty_write(file, buf, count, ppos); +} + /* Semaphore to protect creating and releasing a tty */ static DECLARE_MUTEX(tty_sem); @@ -1307,14 +1295,11 @@ static int tty_open(struct inode * inode, struct file * filp) int noctty, retval; struct tty_driver *driver; int index; - kdev_t device; - unsigned short saved_flags; - - saved_flags = filp->f_flags; + dev_t device = inode->i_rdev; + unsigned short saved_flags = filp->f_flags; retry_open: noctty = filp->f_flags & O_NOCTTY; - device = inode->i_rdev; - if (IS_TTY_DEV(device)) { + if (device == MKDEV(TTYAUX_MAJOR,0)) { if (!current->tty) return -ENXIO; driver = current->tty->driver; @@ -1324,7 +1309,7 @@ retry_open: goto got_driver; } #ifdef CONFIG_VT - if (IS_CONSOLE_DEV(device)) { + if (device == MKDEV(TTY_MAJOR,0)) { extern int fg_console; extern struct tty_driver *console_driver; driver = console_driver; @@ -1333,7 +1318,7 @@ retry_open: goto got_driver; } #endif - if (IS_SYSCONS_DEV(device)) { + if (device == MKDEV(TTYAUX_MAJOR,1)) { struct console *c = console_drivers; for (c = console_drivers; c; c = c->next) { if (!c->device) @@ -1349,7 +1334,7 @@ retry_open: return -ENODEV; } - if (IS_PTMX_DEV(device)) { + if (device == MKDEV(TTYAUX_MAJOR,2)) { #ifdef CONFIG_UNIX98_PTYS /* find a device that is not in use. */ retval = -1; @@ -1366,7 +1351,7 @@ retry_open: return -ENODEV; #endif /* CONFIG_UNIX_98_PTYS */ } else { - driver = get_tty_driver(kdev_t_to_nr(device), &index); + driver = get_tty_driver(device, &index); if (!driver) return -ENODEV; got_driver: @@ -1408,7 +1393,8 @@ got_driver: /* * Need to reset f_op in case a hangup happened. */ - filp->f_op = &tty_fops; + if (filp->f_op == &hung_up_tty_fops) + filp->f_op = &tty_fops; goto retry_open; } if (!noctty && @@ -1517,10 +1503,9 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, return 0; } -static int tioccons(struct inode *inode, struct file *file) +static int tioccons(struct file *file) { - if (IS_SYSCONS_DEV(inode->i_rdev) || - IS_CONSOLE_DEV(inode->i_rdev)) { + if (file->f_op->write == redirected_tty_write) { struct file *f; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1787,7 +1772,7 @@ int tty_ioctl(struct inode * inode, struct file * file, case TIOCSWINSZ: return tiocswinsz(tty, real_tty, (struct winsize *) arg); case TIOCCONS: - return real_tty!=tty ? -EINVAL : tioccons(inode, file); + return real_tty!=tty ? -EINVAL : tioccons(file); case FIONBIO: return fionbio(file, (int *) arg); case TIOCEXCL: @@ -1918,8 +1903,10 @@ static void __do_SAK(void *arg) spin_lock(&p->files->file_lock); for (i=0; i < p->files->max_fds; i++) { filp = fcheck_files(p->files, i); - if (filp && (filp->f_op == &tty_fops) && - (filp->private_data == tty)) { + if (!filp) + continue; + if (filp->f_op->read == tty_read && + filp->private_data == tty) { printk(KERN_NOTICE "SAK: killed process %d" " (%s): fd#%d opened to the tty\n", p->pid, p->comm, i); @@ -2140,7 +2127,7 @@ error: kfree(tty_dev); } -void tty_remove_class_device(dev_t dev) +static void tty_remove_class_device(dev_t dev) { struct tty_dev *tty_dev = NULL; struct list_head *tmp; @@ -2149,19 +2136,15 @@ void tty_remove_class_device(dev_t dev) spin_lock(&tty_dev_list_lock); list_for_each (tmp, &tty_dev_list) { tty_dev = list_entry(tmp, struct tty_dev, node); - if ((MAJOR(tty_dev->dev) == MAJOR(dev)) && - (MINOR(tty_dev->dev) == MINOR(dev))) { + if (tty_dev->dev == dev) { + list_del(&tty_dev->node); found = 1; break; } } - if (found) { - list_del(&tty_dev->node); - spin_unlock(&tty_dev_list_lock); + spin_unlock(&tty_dev_list_lock); + if (found) class_device_unregister(&tty_dev->class_dev); - } else { - spin_unlock(&tty_dev_list_lock); - } } /** @@ -2451,7 +2434,7 @@ void __init tty_init(void) tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL); strcpy(console_cdev.kobj.name, "dev.console"); - cdev_init(&console_cdev, &tty_fops); + cdev_init(&console_cdev, &console_fops); if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) panic("Couldn't register /dev/console driver\n"); @@ -2473,7 +2456,7 @@ void __init tty_init(void) #ifdef CONFIG_VT strcpy(vc0_cdev.kobj.name, "dev.vc0"); - cdev_init(&vc0_cdev, &tty_fops); + cdev_init(&vc0_cdev, &console_fops); if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) panic("Couldn't register /dev/tty0 driver\n"); diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 88686c3d71f0..d6fc18d3c927 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -10,9 +10,54 @@ config CPU_FREQ_PROC_INTF If in doubt, say N. +choice + prompt "Default CPUFreq governor" + depends on CPU_FREQ + default CPU_FREQ_DEFAULT_GOV_PERFORMANCE + help + This option sets which CPUFreq governor shall be loaded at + startup. If in doubt, select 'performance'. + +config CPU_FREQ_DEFAULT_GOV_PERFORMANCE + bool "performance" + select CPU_FREQ_GOV_PERFORMANCE + help + Use the CPUFreq governor 'performance' as default. This sets + the frequency statically to the highest frequency supported by + the CPU. + +config CPU_FREQ_DEFAULT_GOV_USERSPACE + bool "userspace" + select CPU_FREQ_GOV_USERSPACE + help + Use the CPUFreq governor 'userspace' as default. This allows + you to set the CPU frequency manually or when an userspace + programm shall be able to set the CPU dynamically without having + to enable the userspace governor manually. + +endchoice + +config CPU_FREQ_GOV_PERFORMANCE + tristate "'performance' governor" + depends on CPU_FREQ + help + This cpufreq governors set the frequency statically to the + highest available CPU frequency. + + If in doubt, say Y. + +config CPU_FREQ_GOV_POWERSAVE + tristate "'powersave' governor" + depends on CPU_FREQ + help + Theis cpufreq governors set the frequency statically to the + lowest available CPU frequency. + + If in doubt, say Y. + config CPU_FREQ_GOV_USERSPACE tristate "'userspace' governor for userspace frequency scaling" - depends on CPU_FREQ + depends on CPU_FREQ help Enable this cpufreq governor when you either want to set the CPU frequency manually or when an userspace programm shall diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 85b512348acd..1eebf3c6edc3 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -1,5 +1,10 @@ +# CPUfreq core +obj-$(CONFIG_CPU_FREQ) += cpufreq.o + # CPUfreq governors -obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += userspace.o +obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o +obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o +obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o # CPUfreq cross-arch helpers obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o diff --git a/kernel/cpufreq.c b/drivers/cpufreq/cpufreq.c index 7f80c321c785..04cfcc54fa1f 100644 --- a/kernel/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -109,13 +109,18 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data) int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) { - if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { - *policy = CPUFREQ_POLICY_PERFORMANCE; - return 0; - } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { - *policy = CPUFREQ_POLICY_POWERSAVE; - return 0; - } else { + if (!cpufreq_driver) + return -EINVAL; + if (cpufreq_driver->setpolicy) { + if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { + *policy = CPUFREQ_POLICY_PERFORMANCE; + return 0; + } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { + *policy = CPUFREQ_POLICY_POWERSAVE; + return 0; + } + return -EINVAL; + } else { struct cpufreq_governor *t; down(&cpufreq_governor_sem); if (!cpufreq_driver || !cpufreq_driver->target) @@ -123,7 +128,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, list_for_each_entry(t, &cpufreq_governor_list, governor_list) { if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { *governor = t; - *policy = CPUFREQ_POLICY_GOVERNOR; up(&cpufreq_governor_sem); return 0; } @@ -190,16 +194,13 @@ store_one(scaling_max_freq,max); */ static ssize_t show_scaling_governor (struct cpufreq_policy * policy, char *buf) { - switch (policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: + if(policy->policy == CPUFREQ_POLICY_POWERSAVE) return sprintf(buf, "powersave\n"); - case CPUFREQ_POLICY_PERFORMANCE: + else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) return sprintf(buf, "performance\n"); - case CPUFREQ_POLICY_GOVERNOR: + else if (policy->governor) return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); - default: - return -EINVAL; - } + return -EINVAL; } @@ -246,15 +247,15 @@ static ssize_t show_scaling_available_governors (struct cpufreq_policy * policy, ssize_t i = 0; struct cpufreq_governor *t; - i += sprintf(buf, "performance powersave"); - - if (!cpufreq_driver->target) + if (!cpufreq_driver->target) { + i += sprintf(buf, "performance powersave"); goto out; + } list_for_each_entry(t, &cpufreq_governor_list, governor_list) { if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) goto out; - i += snprintf(&buf[i], CPUFREQ_NAME_LEN, " %s", t->name); + i += snprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); } out: i += sprintf(&buf[i], "\n"); @@ -396,10 +397,12 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) spin_lock_irqsave(&cpufreq_driver_lock, flags); cpufreq_cpu_data[cpu] = policy; spin_unlock_irqrestore(&cpufreq_driver_lock, flags); - + policy->governor = NULL; /* to assure that the starting sequence is + * run in cpufreq_set_policy */ up(&policy->lock); /* set default policy */ + ret = cpufreq_set_policy(&new_policy); if (ret) goto err_out_unregister; @@ -492,6 +495,13 @@ static int cpufreq_resume(struct sys_device * sysdev) if (!cpu_policy) return -EINVAL; + if (cpufreq_driver->resume) + ret = cpufreq_driver->resume(cpu_policy); + if (ret) { + printk(KERN_ERR "cpufreq: resume failed in ->resume step on CPU %u\n", cpu_policy->cpu); + goto out; + } + if (cpufreq_driver->setpolicy) ret = cpufreq_driver->setpolicy(cpu_policy); else @@ -500,6 +510,12 @@ static int cpufreq_resume(struct sys_device * sysdev) */ ret = cpufreq_driver->target(cpu_policy, cpu_policy->cur, CPUFREQ_RELATION_H); + if (ret) { + printk(KERN_ERR "cpufreq: resume failed in ->setpolicy/target step on CPU %u\n", cpu_policy->cpu); + goto out; + } + + out: cpufreq_cpu_put(cpu_policy); return ret; @@ -622,33 +638,18 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target); static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) { - int ret = 0; + int ret = -EINVAL; - switch (policy->policy) { - case CPUFREQ_POLICY_POWERSAVE: - if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { - ret = __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); - } - break; - case CPUFREQ_POLICY_PERFORMANCE: - if ((event == CPUFREQ_GOV_LIMITS) || (event == CPUFREQ_GOV_START)) { - ret = __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); - } - break; - case CPUFREQ_POLICY_GOVERNOR: - ret = -EINVAL; - if (!try_module_get(policy->governor->owner)) - break; - ret = policy->governor->governor(policy, event); - /* we keep one module reference alive for each CPU governed by this CPU */ - if ((event != CPUFREQ_GOV_START) || ret) - module_put(policy->governor->owner); - if ((event == CPUFREQ_GOV_STOP) && !ret) - module_put(policy->governor->owner); - break; - default: - ret = -EINVAL; - } + if (!try_module_get(policy->governor->owner)) + return -EINVAL; + + ret = policy->governor->governor(policy, event); + + /* we keep one module reference alive for each CPU governed by this CPU */ + if ((event != CPUFREQ_GOV_START) || ret) + module_put(policy->governor->owner); + if ((event == CPUFREQ_GOV_STOP) && !ret) + module_put(policy->governor->owner); return ret; } @@ -680,11 +681,6 @@ int cpufreq_register_governor(struct cpufreq_governor *governor) if (!governor) return -EINVAL; - if (!strnicmp(governor->name,"powersave",CPUFREQ_NAME_LEN)) - return -EBUSY; - if (!strnicmp(governor->name,"performance",CPUFREQ_NAME_LEN)) - return -EBUSY; - down(&cpufreq_governor_sem); list_for_each_entry(t, &cpufreq_governor_list, governor_list) { @@ -808,23 +804,24 @@ int cpufreq_set_policy(struct cpufreq_policy *policy) data->policy = policy->policy; ret = cpufreq_driver->setpolicy(policy); } else { - if ((policy->policy != data->policy) || - ((policy->policy == CPUFREQ_POLICY_GOVERNOR) && (policy->governor != data->governor))) { + if (policy->governor != data->governor) { /* save old, working values */ - unsigned int old_pol = data->policy; struct cpufreq_governor *old_gov = data->governor; /* end old governor */ - __cpufreq_governor(data, CPUFREQ_GOV_STOP); + if (data->governor) + __cpufreq_governor(data, CPUFREQ_GOV_STOP); /* start new governor */ - data->policy = policy->policy; data->governor = policy->governor; if (__cpufreq_governor(data, CPUFREQ_GOV_START)) { /* new governor failed, so re-start old one */ - data->policy = old_pol; - data->governor = old_gov; - __cpufreq_governor(data, CPUFREQ_GOV_START); + if (old_gov) { + data->governor = old_gov; + __cpufreq_governor(data, CPUFREQ_GOV_START); + } + ret = -EINVAL; + goto error_out; } /* might be a policy change, too, so fall through */ } diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c new file mode 100644 index 000000000000..f2348e790569 --- /dev/null +++ b/drivers/cpufreq/cpufreq_performance.c @@ -0,0 +1,57 @@ +/* + * linux/drivers/cpufreq/cpufreq_performance.c + * + * Copyright (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de> + * + * + * 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. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/cpufreq.h> +#include <linux/init.h> + +static int cpufreq_governor_performance(struct cpufreq_policy *policy, + unsigned int event) +{ + switch (event) { + case CPUFREQ_GOV_START: + case CPUFREQ_GOV_LIMITS: + __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); + break; + default: + break; + } + return 0; +} + +struct cpufreq_governor cpufreq_gov_performance = { + .name = "performance", + .governor = cpufreq_governor_performance, + .owner = THIS_MODULE, +}; +EXPORT_SYMBOL(cpufreq_gov_performance); + + +static int __init cpufreq_gov_performance_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_performance); +} + + +static void __exit cpufreq_gov_performance_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_performance); +} + + +MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); +MODULE_DESCRIPTION("CPUfreq policy governor 'performance'"); +MODULE_LICENSE("GPL"); + +fs_initcall(cpufreq_gov_performance_init); +module_exit(cpufreq_gov_performance_exit); diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c new file mode 100644 index 000000000000..ec8544885693 --- /dev/null +++ b/drivers/cpufreq/cpufreq_powersave.c @@ -0,0 +1,56 @@ +/* + * linux/drivers/cpufreq/cpufreq_powersave.c + * + * Copyright (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de> + * + * + * 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. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/cpufreq.h> +#include <linux/init.h> + +static int cpufreq_governor_powersave(struct cpufreq_policy *policy, + unsigned int event) +{ + switch (event) { + case CPUFREQ_GOV_START: + case CPUFREQ_GOV_LIMITS: + __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); + break; + default: + break; + } + return 0; +} + +static struct cpufreq_governor cpufreq_gov_powersave = { + .name = "powersave", + .governor = cpufreq_governor_powersave, + .owner = THIS_MODULE, +}; + + +static int __init cpufreq_gov_powersave_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_powersave); +} + + +static void __exit cpufreq_gov_powersave_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_powersave); +} + + +MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); +MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'"); +MODULE_LICENSE("GPL"); + +module_init(cpufreq_gov_powersave_init); +module_exit(cpufreq_gov_powersave_exit); diff --git a/drivers/cpufreq/userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 7df32a97c50a..9f51fbe9b149 100644 --- a/drivers/cpufreq/userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -498,9 +498,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, unsigned int cpu = policy->cpu; switch (event) { case CPUFREQ_GOV_START: - if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE)) || - !policy->cur) + if ((!cpu_online(cpu)) || (!try_module_get(THIS_MODULE))) return -EINVAL; + BUG_ON(!policy->cur); down(&userspace_sem); cpu_is_managed[cpu] = 1; cpu_min_freq[cpu] = policy->min; @@ -551,7 +551,7 @@ static void cpufreq_sa11x0_compat(void) #endif -static struct cpufreq_governor cpufreq_gov_userspace = { +struct cpufreq_governor cpufreq_gov_userspace = { .name = "userspace", .governor = cpufreq_governor_userspace, .owner = THIS_MODULE, @@ -587,5 +587,5 @@ MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>, Russell King <rmk@arm.linux. MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'"); MODULE_LICENSE ("GPL"); -module_init(cpufreq_gov_userspace_init); +fs_initcall(cpufreq_gov_userspace_init); module_exit(cpufreq_gov_userspace_exit); diff --git a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c index d314e526af9c..b8d6b056051a 100644 --- a/drivers/cpufreq/proc_intf.c +++ b/drivers/cpufreq/proc_intf.c @@ -126,20 +126,20 @@ static int cpufreq_proc_read ( p += sprintf(p, "CPU%3d %9d kHz (%3d %%) - %9d kHz (%3d %%) - ", i , policy.min, min_pctg, policy.max, max_pctg); - switch (policy.policy) { - case CPUFREQ_POLICY_POWERSAVE: - p += sprintf(p, "powersave\n"); - break; - case CPUFREQ_POLICY_PERFORMANCE: - p += sprintf(p, "performance\n"); - break; - case CPUFREQ_POLICY_GOVERNOR: + if (policy.policy) { + switch (policy.policy) { + case CPUFREQ_POLICY_POWERSAVE: + p += sprintf(p, "powersave\n"); + break; + case CPUFREQ_POLICY_PERFORMANCE: + p += sprintf(p, "performance\n"); + break; + default: + p += sprintf(p, "INVALID\n"); + break; + } + } else p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name); - break; - default: - p += sprintf(p, "INVALID\n"); - break; - } } end: len = (p - page); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 39693bcc7d0f..8bf402224197 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -1689,7 +1689,8 @@ static void idedisk_setup (ide_drive_t *drive) write_cache(drive, (id->cfs_enable_2 & 0x3000)); #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT - HWIF(drive)->ide_dma_queued_on(drive); + if (drive->using_dma) + HWIF(drive)->ide_dma_queued_on(drive); #endif } diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 2b94c9450336..0d9fff1f883d 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1387,7 +1387,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio unsigned long flags; ide_hwgroup_t *hwgroup = HWGROUP(drive); DECLARE_COMPLETION(wait); - int insert_end = 1, err; + int where = ELEVATOR_INSERT_BACK, err; int must_wait = (action == ide_wait || action == ide_head_wait); #ifdef CONFIG_BLK_DEV_PDC4030 @@ -1419,10 +1419,10 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio spin_lock_irqsave(&ide_lock, flags); if (action == ide_preempt || action == ide_head_wait) { hwgroup->rq = NULL; - insert_end = 0; + where = ELEVATOR_INSERT_FRONT; rq->flags |= REQ_PREEMPT; } - __elv_add_request(drive->queue, rq, insert_end, 0); + __elv_add_request(drive->queue, rq, where, 0); ide_do_request(hwgroup, IDE_NO_IRQ); spin_unlock_irqrestore(&ide_lock, flags); diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h index e2e8ec8d78a5..60efa9ec9a07 100644 --- a/drivers/ieee1394/ieee1394_types.h +++ b/drivers/ieee1394/ieee1394_types.h @@ -16,10 +16,6 @@ /* The great kdev_t changeover in 2.5.x */ #include <linux/kdev_t.h> -#ifndef minor -#define minor(dev) MINOR(dev) -#endif - /* Transaction Label handling */ struct hpsb_tlabel_pool { diff --git a/drivers/md/dm-ioctl-v1.c b/drivers/md/dm-ioctl-v1.c index 3afe5e55ae66..0dc24d76de3f 100644 --- a/drivers/md/dm-ioctl-v1.c +++ b/drivers/md/dm-ioctl-v1.c @@ -577,7 +577,7 @@ static int create(struct dm_ioctl *param, struct dm_ioctl *user) } if (param->flags & DM_PERSISTENT_DEV_FLAG) - r = dm_create_with_minor(minor(to_kdev_t(param->dev)), &md); + r = dm_create_with_minor(MINOR(param->dev), &md); else r = dm_create(&md); diff --git a/drivers/md/dm-ioctl-v4.c b/drivers/md/dm-ioctl-v4.c index 2c8243aab6f5..0ea9a58b8daf 100644 --- a/drivers/md/dm-ioctl-v4.c +++ b/drivers/md/dm-ioctl-v4.c @@ -481,7 +481,7 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) return r; if (param->flags & DM_PERSISTENT_DEV_FLAG) - r = dm_create_with_minor(minor(to_kdev_t(param->dev)), &md); + r = dm_create_with_minor(MINOR(param->dev), &md); else r = dm_create(&md); diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 5d0e4c662599..aae61522d1f7 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -312,7 +312,7 @@ static int lookup_device(const char *path, dev_t *dev) goto out; } - *dev = kdev_t_to_nr(inode->i_rdev); + *dev = inode->i_rdev; out: path_release(&nd); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 9da446a143ec..322782c4cda2 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -25,7 +25,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -#define DEVICE_NR(device) (minor(device)) /* * find which device holds a particular offset diff --git a/drivers/md/md.c b/drivers/md/md.c index b95a323cdf41..6a67e10393e2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -50,7 +50,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER -#define DEVICE_NR(device) (minor(device)) #define DEBUG 0 #define dprintk(x...) ((void)(DEBUG && printk(x))) diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 4d19a4bd6808..afa7e3e87b21 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -29,7 +29,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -#define DEVICE_NR(device) (minor(device)) #define MAX_WORK_PER_DISK 128 diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index eb4368751307..ad7a468c6831 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -24,7 +24,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -#define DEVICE_NR(device) (minor(device)) static int create_strip_zones (mddev_t *mddev) { diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index cb7acbfb87cf..83533c262986 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -27,7 +27,6 @@ #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY -#define DEVICE_NR(device) (minor(device)) /* * Number of guaranteed r1bios in case of extreme VM load: diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 777f59a1f6c9..e7d60fcfbb12 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -52,7 +52,7 @@ static ssize_t show_dev(struct class_device *cd, char *buf) { struct video_device *vfd = container_of(cd, struct video_device, class_dev); dev_t dev = MKDEV(VIDEO_MAJOR, vfd->minor); - return sprintf(buf,"%04x\n",(int)dev); + return sprintf(buf,"%04x\n",old_encode_dev(dev)); } static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL); diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index bd5b10bbc08d..6cc67f746eb2 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -1265,7 +1265,7 @@ static int zoran_open (struct inode *inode, struct file *file) { - unsigned int minor = minor(inode->i_rdev); + unsigned int minor = iminor(inode); struct zoran *zr = NULL; struct zoran_fh *fh; int i, res, first_open = 0, have_module_locks = 0; diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 1963e60de0b2..be24e20a5cb1 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -97,15 +97,9 @@ extern int macsonic_probe(struct net_device *dev); extern int mac8390_probe(struct net_device *dev); extern int mac89x0_probe(struct net_device *dev); extern int mc32_probe(struct net_device *dev); -#ifdef CONFIG_SDLA extern struct net_device *sdla_init(void); -#endif -#ifdef CONFIG_COPS extern struct net_device *cops_probe(int unit); -#endif -#ifdef CONFIG_LTPC extern struct net_device *ltpc_probe(void); -#endif /* Detachable devices ("pocket adaptors") */ extern int de620_probe(struct net_device *); diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 49e75710594c..df80c5c25e37 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -465,7 +465,7 @@ config DLCI_MAX config SDLA tristate "SDLA (Sangoma S502/S508) support" - depends on DLCI && ISA && BROKEN_ON_SMP + depends on DLCI && ISA help Say Y here if you need a driver for the Sangoma S502A, S502E, and S508 Frame Relay Access Devices. These are multi-protocol cards, but diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index d445e916a18b..8a440eea9c60 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -357,11 +357,7 @@ static void debug_status_out(struct cosa_data *cosa, int status); /* ---------- Initialization stuff ---------- */ -#ifdef MODULE -int init_module(void) -#else static int __init cosa_init(void) -#endif { int i; @@ -398,9 +394,9 @@ static int __init cosa_init(void) } return 0; } +module_init(cosa_init); -#ifdef MODULE -void cleanup_module (void) +static void __exit cosa_exit(void) { struct cosa_data *cosa; int i; @@ -424,7 +420,7 @@ void cleanup_module (void) } unregister_chrdev(cosa_major, "cosa"); } -#endif +module_exit(cosa_exit); /* * This function should register all the net devices needed for the @@ -513,7 +509,6 @@ static int cosa_probe(int base, int irq, int dma) if (irq < 0) { unsigned long irqs; /* printk(KERN_INFO "IRQ autoprobe\n"); */ - sti(); irqs = probe_irq_on(); /* * Enable interrupt on tx buffer empty (it sure is) @@ -624,6 +619,7 @@ static void sppp_channel_init(struct channel_data *chan) if (register_netdev(d) == -1) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); sppp_detach(chan->pppdev.dev); + free_netdev(chan->pppdev.dev); return; } } @@ -658,7 +654,6 @@ static int cosa_sppp_open(struct net_device *d) chan->rx_done = sppp_rx_done; chan->usage=-1; chan->cosa->usage++; - MOD_INC_USE_COUNT; spin_unlock_irqrestore(&chan->cosa->lock, flags); err = sppp_open(d); @@ -666,7 +661,6 @@ static int cosa_sppp_open(struct net_device *d) spin_lock_irqsave(&chan->cosa->lock, flags); chan->usage=0; chan->cosa->usage--; - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&chan->cosa->lock, flags); return err; @@ -726,7 +720,6 @@ static int cosa_sppp_close(struct net_device *d) } chan->usage=0; chan->cosa->usage--; - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&chan->cosa->lock, flags); return 0; } @@ -1187,21 +1180,6 @@ static int cosa_ioctl_common(struct cosa_data *cosa, return cosa_gettype(cosa, (char *)arg); case COSAIORIDSTR: return cosa_getidstr(cosa, (char *)arg); -/* - * These two are _very_ugly_hack_(tm). Don't even look at this. - * Implementing this saved me few reboots after some process segfaulted - * inside this module. - */ -#ifdef MODULE -#if 0 - case COSAIOMINC: - MOD_INC_USE_COUNT; - return 0; - case COSAIOMDEC: - MOD_DEC_USE_COUNT; - return 0; -#endif -#endif case COSAIONRCARDS: return nr_cards; case COSAIONRCHANS: diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index c91e59da2ed9..e11984b2bb03 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -1633,12 +1633,26 @@ static void setup_sdla(struct net_device *dev) dev->mtu = SDLA_MAX_MTU; } +static int frad_registered; + struct net_device * __init sdla_init(void) { struct net_device *dev; struct frad_local *flp; int err = -ENOMEM; + if (!frad_registered) { + err = register_frad(devname); + if (err) { + printk(KERN_ERR "%s: frad registration failed %d\n", + devname, err); + return ERR_PTR(err); + } + frad_registered = 1; + printk("%s.\n", version); + } + + dev = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla); if (!dev) goto out; @@ -1677,39 +1691,35 @@ out: return ERR_PTR(err); } -int __init sdla_c_setup(void) -{ - printk("%s.\n", version); - register_frad(devname); - return 0; -} - #ifdef MODULE static struct net_device *sdla0; -#endif /* MODULE */ static int __init init_sdla(void) { int result = 0; - sdla_c_setup(); -#ifdef MODULE sdla0 = sdla_init(); if (IS_ERR(sdla0)) result = PTR_ERR(sdla0); -#endif + return result; } static void __exit exit_sdla(void) { -#ifdef MODULE + struct frad_local *flp; + unregister_netdev(sdla0); if (sdla0->irq) free_irq(sdla0->irq, sdla0); + + flp = sdla0->priv; + del_timer_sync(&flp->timer); free_netdev(sdla0); -#endif + + unregister_frad(devname); } +#endif MODULE_LICENSE("GPL"); diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 7656f1eddc6e..48fb7e002944 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -178,7 +178,7 @@ tape_assign_minor(struct tape_device *device) break; minor += TAPE_MINORS_PER_DEV; } - if (minor >= (1 << KDEV_MINOR_BITS)) { + if (minor >= 256) { write_unlock(&tape_device_lock); return -ENODEV; } diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c index da3a4d3ed310..5857f846101f 100644 --- a/drivers/s390/char/tape_proc.c +++ b/drivers/s390/char/tape_proc.c @@ -80,7 +80,7 @@ static int tape_proc_show(struct seq_file *m, void *v) static void *tape_proc_start(struct seq_file *m, loff_t *pos) { - if (*pos >= (1 << KDEV_MINOR_BITS) / TAPE_MINORS_PER_DEV) + if (*pos >= 256 / TAPE_MINORS_PER_DEV) return NULL; return (void *)((unsigned long) *pos + 1); } diff --git a/drivers/s390/char/tubio.h b/drivers/s390/char/tubio.h index 92cd4fe8dbd1..cd04879e4048 100644 --- a/drivers/s390/char/tubio.h +++ b/drivers/s390/char/tubio.h @@ -158,7 +158,6 @@ enum tubwhat { /* echo what= proc actions */ #define TUBMAXMINS 256 -#define TUB_DEV MKDEV(IBM_FS3270_MAJ, 0) /* Generic /dev/3270/tub */ #define _GEOM_ROWS 24 #define _GEOM_COLS 80 #define GEOM_ROWS (tubp->geom_rows) @@ -294,23 +293,6 @@ typedef struct tub_s { #define TUB_UE_BUSY 0x0800 #define TUB_INPUT_HACK 0x1000 /* Early init of command line */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)) -#define S390_CONSOLE_DEV MKDEV(TTY_MAJOR, 64) -#define tub_major(x) MAJOR(x) -#define tub_minor(x) MINOR(x) -#define tub_mkdev(x, y) MKDEV(x, y) -#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#define S390_CONSOLE_DEV MKDEV(TTYAUX_MAJOR, 1) -#define tub_major(x) MAJOR(x) -#define tub_minor(x) MINOR(x) -#define tub_mkdev(x, y) MKDEV(x, y) -#else -#define S390_CONSOLE_DEV mk_kdev(TTYAUX_MAJOR, 1) -#define tub_major(x) major(x) -#define tub_minor(x) minor(x) -#define tub_mkdev(x, y) mk_kdev(x, y) -#endif - /* * Extra stuff for 3270 console support */ diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 0a5497ea2389..facb6f9fee35 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -83,7 +83,7 @@ static void sg_proc_cleanup(void); #define SG_ALLOW_DIO_DEF 0 #define SG_ALLOW_DIO_CODE /* compile out by commenting this define */ -#define SG_MAX_DEVS_MASK ((1U << KDEV_MINOR_BITS) - 1) +#define SG_MAX_DEVS_MASK (256 - 1) /* * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d) diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 089510b7a819..d3a646260380 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -59,7 +59,7 @@ MODULE_PARM(xa_test, "i"); /* see sr_ioctl.c */ -#define SR_DISKS (1 << KDEV_MINOR_BITS) +#define SR_DISKS 256 #define MAX_RETRIES 3 #define SR_TIMEOUT (30 * HZ) diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 870900b513da..8474deb3f277 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -152,7 +152,6 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; switch (mode & S_IFMT) { default: diff --git a/fs/afs/inode.c b/fs/afs/inode.c index a58e32b26acb..1c83000f2c3d 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -68,7 +68,6 @@ static int afs_inode_map_status(afs_vnode_t *vnode) inode->i_nlink = vnode->status.nlink; inode->i_uid = vnode->status.owner; inode->i_gid = 0; - inode->i_rdev = NODEV; inode->i_size = vnode->status.size; inode->i_atime.tv_sec = inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = vnode->status.mtime_server; inode->i_atime.tv_nsec = diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 090a7e961c08..35647d8eca94 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -298,7 +298,6 @@ struct inode *autofs4_get_inode(struct super_block *sb, } inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; if (S_ISDIR(inf->mode)) { diff --git a/fs/block_dev.c b/fs/block_dev.c index ddfcb6284b5a..e08095251aab 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -345,7 +345,7 @@ struct block_device *bdget(dev_t dev) bdev->bd_part_count = 0; bdev->bd_invalidated = 0; inode->i_mode = S_IFBLK; - inode->i_rdev = to_kdev_t(dev); + inode->i_rdev = dev; inode->i_bdev = bdev; inode->i_data.a_ops = &def_blk_aops; mapping_set_gfp_mask(&inode->i_data, GFP_USER); @@ -386,7 +386,7 @@ int bd_acquire(struct inode *inode) return 0; } spin_unlock(&bdev_lock); - bdev = bdget(kdev_t_to_nr(inode->i_rdev)); + bdev = bdget(inode->i_rdev); if (!bdev) return -ENOMEM; spin_lock(&bdev_lock); diff --git a/fs/char_dev.c b/fs/char_dev.c index 3c6258c73384..44303f85e624 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -265,7 +265,7 @@ int chrdev_open(struct inode * inode, struct file * filp) struct kobject *kobj; int idx; spin_unlock(&cdev_lock); - kobj = kobj_lookup(cdev_map, kdev_t_to_nr(inode->i_rdev), &idx); + kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); if (!kobj) return -ENODEV; new = container_of(kobj, struct cdev, kobj); @@ -328,27 +328,6 @@ struct file_operations def_chr_fops = { .open = chrdev_open, }; -const char *cdevname(kdev_t dev) -{ - static char buffer[40]; - const char *name = "unknown-char"; - unsigned int major = major(dev); - unsigned int minor = minor(dev); - int i = major_to_index(major); - struct char_device_struct *cd; - - read_lock(&chrdevs_lock); - for (cd = chrdevs[i]; cd; cd = cd->next) - if (cd->major == major) - break; - if (cd) - name = cd->name; - sprintf(buffer, "%s(%d,%d)", name, major, minor); - read_unlock(&chrdevs_lock); - - return buffer; -} - static struct kobject *exact_match(dev_t dev, int *part, void *data) { struct cdev *p = data; diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 8873ca0447c9..b1245a53db80 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -265,6 +265,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev char *full_path = NULL; struct inode * newinode = NULL; + if (!old_valid_dev(device_number)) + return -EINVAL; + xid = GetXid(); cifs_sb = CIFS_SB(inode->i_sb); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 247a39b899b3..5e223961e9fb 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1024,7 +1024,7 @@ fill_in_inode(struct inode *tmp_inode, } else { cFYI(1, (" Init special inode ")); init_special_inode(tmp_inode, tmp_inode->i_mode, - kdev_t_to_nr(tmp_inode->i_rdev)); + tmp_inode->i_rdev); } } @@ -1094,7 +1094,7 @@ unix_fill_in_inode(struct inode *tmp_inode, } else { cFYI(1, (" Init special inode ")); init_special_inode(tmp_inode, tmp_inode->i_mode, - kdev_t_to_nr(tmp_inode->i_rdev)); + tmp_inode->i_rdev); } } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 3625916ca351..6524d6d1f883 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -154,7 +154,7 @@ cifs_get_inode_info_unix(struct inode **pinode, } else { cFYI(1, (" Init special inode ")); init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + inode->i_rdev); } } FreeXid(xid); @@ -298,7 +298,7 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path, inode->i_op = &cifs_symlink_inode_ops; } else { init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + inode->i_rdev); } } if(buf) diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 2917ab9f4976..4c75d774e0dd 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -242,6 +242,9 @@ static int coda_mknod(struct inode *dir, struct dentry *de, int mode, dev_t rdev if ( coda_hasmknod == 0 ) return -EIO; + if (!old_valid_dev(rdev)) + return -EINVAL; + lock_kernel(); coda_vfs_stat.create++; diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 1789afd1298d..8fcd03bec9f7 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -71,7 +71,8 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod inode->i_data.a_ops = &cramfs_aops; } else { inode->i_size = 0; - init_special_inode(inode, inode->i_mode, cramfs_inode->size); + init_special_inode(inode, inode->i_mode, + old_decode_dev(cramfs_inode->size)); } } return inode; diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 69a91269e0e9..fda21d6af987 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -2010,14 +2010,13 @@ static struct inode *_devfs_get_vfs_inode (struct super_block *sb, inode->i_blksize = FAKE_BLOCK_SIZE; inode->i_op = &devfs_iops; inode->i_fop = &devfs_fops; - inode->i_rdev = NODEV; if ( S_ISCHR (de->mode) ) { - inode->i_rdev = to_kdev_t(de->u.cdev.dev); + inode->i_rdev = de->u.cdev.dev; } else if ( S_ISBLK (de->mode) ) { - inode->i_rdev = to_kdev_t(de->u.bdev.dev); + inode->i_rdev = de->u.bdev.dev; if (bd_acquire (inode) != 0) PRINTK ("(%d): no block device from bdget()\n",(int)inode->i_ino); } @@ -2494,8 +2493,8 @@ static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode, struct devfs_entry *parent, *de; struct inode *inode; - DPRINTK (DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %d\n", - dentry->d_name.name, mode, rdev); + DPRINTK (DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %u:%u\n", + dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); parent = get_devfs_entry_from_vfs_inode (dir); if (parent == NULL) return -ENOENT; de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode); diff --git a/fs/efs/inode.c b/fs/efs/inode.c index e0a73e28e004..5901ab61e0b1 100644 --- a/fs/efs/inode.c +++ b/fs/efs/inode.c @@ -117,7 +117,7 @@ void efs_read_inode(struct inode *inode) { * to see whether odev contains 65535. if this is the case then we * should then do device = be32_to_cpu(efs_inode->di_u.di_dev.ndev). */ - device = be16_to_cpu(efs_inode->di_u.di_dev.odev); + device = old_decode_dev(be16_to_cpu(efs_inode->di_u.di_dev.odev)); /* get the number of extents for this object */ in->numextents = be16_to_cpu(efs_inode->di_numextents); diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 8a009a159469..9247dc703f31 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1127,7 +1127,7 @@ void ext2_read_inode (struct inode * inode) } else { inode->i_op = &ext2_special_inode_operations; init_special_inode(inode, inode->i_mode, - le32_to_cpu(raw_inode->i_block[0])); + old_decode_dev(le32_to_cpu(raw_inode->i_block[0]))); } brelse (bh); ext2_set_inode_flags(inode); @@ -1216,7 +1216,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync) raw_inode->i_generation = cpu_to_le32(inode->i_generation); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); + raw_inode->i_block[0] = cpu_to_le32(old_encode_dev(inode->i_rdev)); else for (n = 0; n < EXT2_N_BLOCKS; n++) raw_inode->i_block[n] = ei->i_data[n]; mark_buffer_dirty(bh); diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index 72d5690b2450..8079e2ee4684 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -139,8 +139,14 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { - struct inode * inode = ext2_new_inode (dir, mode); - int err = PTR_ERR(inode); + struct inode * inode; + int err; + + if (!old_valid_dev(rdev)) + return -EINVAL; + + inode = ext2_new_inode (dir, mode); + err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); #ifdef CONFIG_EXT2_FS_XATTR diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 84f41589a02a..c4fc83552763 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -2566,7 +2566,7 @@ void ext3_read_inode(struct inode * inode) } else { inode->i_op = &ext3_special_inode_operations; init_special_inode(inode, inode->i_mode, - le32_to_cpu(raw_inode->i_block[0])); + old_decode_dev(le32_to_cpu(raw_inode->i_block[0]))); } brelse (iloc.bh); ext3_set_inode_flags(inode); @@ -2668,7 +2668,7 @@ static int ext3_do_update_inode(handle_t *handle, raw_inode->i_generation = cpu_to_le32(inode->i_generation); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) raw_inode->i_block[0] = - cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); + cpu_to_le32(old_encode_dev(inode->i_rdev)); else for (block = 0; block < EXT3_N_BLOCKS; block++) raw_inode->i_block[block] = ei->i_data[block]; diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 78daed5cee0f..769392cf8ea9 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -1659,6 +1659,9 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry, struct inode *inode; int err; + if (!old_valid_dev(rdev)) + return -EINVAL; + handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3); if (IS_ERR(handle)) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 4ac414b82e68..e5148cb001d8 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1603,7 +1603,7 @@ static int ext3_load_journal(struct super_block * sb, { journal_t *journal; int journal_inum = le32_to_cpu(es->s_journal_inum); - dev_t journal_dev = le32_to_cpu(es->s_journal_dev); + dev_t journal_dev = old_decode_dev(le32_to_cpu(es->s_journal_dev)); int err = 0; int really_read_only; diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c index 06d7fe84a421..bbaeef8b63d2 100644 --- a/fs/freevxfs/vxfs_inode.c +++ b/fs/freevxfs/vxfs_inode.c @@ -333,7 +333,7 @@ vxfs_read_inode(struct inode *ip) } else ip->i_op = &vxfs_immed_symlink_iops; } else - init_special_inode(ip, ip->i_mode, vip->vii_rdev); + init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); return; } diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 21f14fcf8ccf..398de286c3e7 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -322,7 +322,6 @@ struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type, /* Initialize the inode */ struct hfs_sb_info *hsb = HFS_SB(sb); - inode->i_rdev = NODEV; inode->i_ctime.tv_sec = inode->i_atime.tv_sec = inode->i_mtime.tv_sec = hfs_m_to_utime(entry->modify_date); inode->i_ctime.tv_nsec = 0; diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c index 2d4042ac2ae0..7b0a4f1c7fbc 100644 --- a/fs/hpfs/inode.c +++ b/fs/hpfs/inode.c @@ -114,14 +114,14 @@ void hpfs_read_inode(struct inode *i) if (hpfs_sb(i->i_sb)->sb_eas) { if ((ea = hpfs_get_ea(i->i_sb, fnode, "UID", &ea_size))) { if (ea_size == 2) { - i->i_uid = ea[0] + (ea[1] << 8); + i->i_uid = le16_to_cpu(*(u16*)ea); hpfs_inode->i_ea_uid = 1; } kfree(ea); } if ((ea = hpfs_get_ea(i->i_sb, fnode, "GID", &ea_size))) { if (ea_size == 2) { - i->i_gid = ea[0] + (ea[1] << 8); + i->i_gid = le16_to_cpu(*(u16*)ea); hpfs_inode->i_ea_gid = 1; } kfree(ea); @@ -141,7 +141,7 @@ void hpfs_read_inode(struct inode *i) int rdev = 0; umode_t mode = hpfs_sb(sb)->sb_mode; if (ea_size == 2) { - mode = ea[0] + (ea[1] << 8); + mode = le16_to_cpu(*(u16*)ea); hpfs_inode->i_ea_mode = 1; } kfree(ea); @@ -149,7 +149,7 @@ void hpfs_read_inode(struct inode *i) if (S_ISBLK(mode) || S_ISCHR(mode)) { if ((ea = hpfs_get_ea(i->i_sb, fnode, "DEV", &ea_size))) { if (ea_size == 4) - rdev = ea[0] + (ea[1] << 8) + (ea[2] << 16) + (ea[3] << 24); + rdev = le32_to_cpu(*(u32*)ea); kfree(ea); } } @@ -158,7 +158,8 @@ void hpfs_read_inode(struct inode *i) i->i_nlink = 1; i->i_size = 0; i->i_blocks = 1; - init_special_inode(i, mode, rdev); + init_special_inode(i, mode, + old_decode_dev(rdev)); return; } } @@ -201,17 +202,15 @@ void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode) we'd better not overwrite them */ hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino); } else if (hpfs_sb(i->i_sb)->sb_eas >= 2) { - unsigned char ea[4]; + u32 ea; if ((i->i_uid != hpfs_sb(i->i_sb)->sb_uid) || hpfs_inode->i_ea_uid) { - ea[0] = i->i_uid & 0xff; - ea[1] = i->i_uid >> 8; - hpfs_set_ea(i, fnode, "UID", ea, 2); + ea = cpu_to_le32(i->i_uid); + hpfs_set_ea(i, fnode, "UID", (char*)&ea, 2); hpfs_inode->i_ea_uid = 1; } if ((i->i_gid != hpfs_sb(i->i_sb)->sb_gid) || hpfs_inode->i_ea_gid) { - ea[0] = i->i_gid & 0xff; - ea[1] = i->i_gid >> 8; - hpfs_set_ea(i, fnode, "GID", ea, 2); + ea = cpu_to_le32(i->i_gid); + hpfs_set_ea(i, fnode, "GID", (char *)&ea, 2); hpfs_inode->i_ea_gid = 1; } if (!S_ISLNK(i->i_mode)) @@ -219,18 +218,13 @@ void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode) | (S_ISDIR(i->i_mode) ? S_IFDIR : S_IFREG)) && i->i_mode != ((hpfs_sb(i->i_sb)->sb_mode & ~(S_ISDIR(i->i_mode) ? 0222 : 0333)) | (S_ISDIR(i->i_mode) ? S_IFDIR : S_IFREG))) || hpfs_inode->i_ea_mode) { - ea[0] = i->i_mode & 0xff; - ea[1] = i->i_mode >> 8; - hpfs_set_ea(i, fnode, "MODE", ea, 2); + ea = cpu_to_le32(i->i_mode); + hpfs_set_ea(i, fnode, "MODE", (char *)&ea, 2); hpfs_inode->i_ea_mode = 1; } if (S_ISBLK(i->i_mode) || S_ISCHR(i->i_mode)) { - int d = kdev_t_to_nr(i->i_rdev); - ea[0] = d & 0xff; - ea[1] = (d >> 8) & 0xff; - ea[2] = (d >> 16) & 0xff; - ea[3] = d >> 24; - hpfs_set_ea(i, fnode, "DEV", ea, 4); + ea = cpu_to_le32(old_encode_dev(i->i_rdev)); + hpfs_set_ea(i, fnode, "DEV", (char *)&ea, 4); } } } diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 18f8b1c00e93..030d3de7d01f 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c @@ -194,6 +194,8 @@ int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) int err; if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err; if (hpfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM; + if (!old_valid_dev(rdev)) + return -EINVAL; lock_kernel(); if (!(fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh))) goto bail; memset(&dee, 0, sizeof dee); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 7b196a5024ae..effaa5bc5a96 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -406,7 +406,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, inode->i_gid = gid; inode->i_blksize = HPAGE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_mapping->a_ops = &hugetlbfs_aops; inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; diff --git a/fs/inode.c b/fs/inode.c index bd116dc1fadc..df29026f21c1 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -130,7 +130,7 @@ static struct inode *alloc_inode(struct super_block *sb) inode->i_pipe = NULL; inode->i_bdev = NULL; inode->i_cdev = NULL; - inode->i_rdev = to_kdev_t(0); + inode->i_rdev = 0; inode->i_security = NULL; if (security_inode_alloc(inode)) { if (inode->i_sb->s_op->destroy_inode) @@ -1363,10 +1363,10 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) inode->i_mode = mode; if (S_ISCHR(mode)) { inode->i_fop = &def_chr_fops; - inode->i_rdev = to_kdev_t(rdev); + inode->i_rdev = rdev; } else if (S_ISBLK(mode)) { inode->i_fop = &def_blk_fops; - inode->i_rdev = to_kdev_t(rdev); + inode->i_rdev = rdev; } else if (S_ISFIFO(mode)) inode->i_fop = &def_fifo_fops; else if (S_ISSOCK(mode)) diff --git a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c index 4794ee0a3822..b07d6ae8bb74 100644 --- a/fs/intermezzo/dir.c +++ b/fs/intermezzo/dir.c @@ -726,6 +726,9 @@ static int presto_mknod(struct inode * dir, struct dentry * dentry, int mode, de struct dentry *parent = dentry->d_parent; struct lento_vfs_context info; + if (!old_valid_dev(rdev)) + return -EINVAL; + ENTRY; error = presto_check_set_fsdata(dentry); if ( error ) { diff --git a/fs/intermezzo/journal.c b/fs/intermezzo/journal.c index 0b62b1364855..74396076f10d 100644 --- a/fs/intermezzo/journal.c +++ b/fs/intermezzo/journal.c @@ -391,13 +391,11 @@ static inline char *log_version(char *buf, struct presto_version *pv) static inline char *log_rollback(char *buf, struct izo_rollback_data *rb) { struct izo_rollback_data rollback; - - memcpy(&rollback, rb, sizeof(rollback)); - rollback.rb_mode = HTON__u32(rollback.rb_mode); - rollback.rb_rdev = HTON__u32(rollback.rb_rdev); - rollback.rb_uid = HTON__u64(rollback.rb_uid); - rollback.rb_gid = HTON__u64(rollback.rb_gid); + rollback.rb_mode = HTON__u32(rb->rb_mode); + rollback.rb_rdev = HTON__u32(rb->rb_rdev); + rollback.rb_uid = HTON__u64(rb->rb_uid); + rollback.rb_gid = HTON__u64(rb->rb_gid); return logit(buf, &rollback, sizeof(rollback)); } diff --git a/fs/intermezzo/kml_reint.c b/fs/intermezzo/kml_reint.c index f05915ee0dc0..f244abb962f9 100644 --- a/fs/intermezzo/kml_reint.c +++ b/fs/intermezzo/kml_reint.c @@ -236,7 +236,8 @@ static int reint_mknod(struct kml_rec *rec, struct file *dir, struct lento_vfs_context *info) { struct run_ctxt saved_ctxt; - int error, dev; + int error; + dev_t dev; ENTRY; @@ -245,7 +246,7 @@ static int reint_mknod(struct kml_rec *rec, struct file *dir, info->updated_time.tv_nsec = rec->new_objectv->pv_ctime_nsec; kmlreint_pre_secure(rec, dir, &saved_ctxt); - dev = rec->rdev ?: MKDEV(rec->major, rec->minor); + dev = rec->rdev ? old_decode_dev(rec->rdev) : MKDEV(rec->major, rec->minor); error = lento_mknod(rec->path, rec->mode, dev, info); pop_ctxt(&saved_ctxt); diff --git a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c index 920ba2773961..40b08d332d25 100644 --- a/fs/intermezzo/vfs.c +++ b/fs/intermezzo/vfs.c @@ -290,7 +290,7 @@ int presto_settime(struct presto_file_set *fset, void izo_get_rollback_data(struct inode *inode, struct izo_rollback_data *rb) { rb->rb_mode = (__u32)inode->i_mode; - rb->rb_rdev = (__u32)kdev_t_to_nr(inode->i_rdev); + rb->rb_rdev = (__u32)old_encode_dev(inode->i_rdev); rb->rb_uid = (__u64)inode->i_uid; rb->rb_gid = (__u64)inode->i_gid; } diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index a28d5f174b9b..bbff5798e2d3 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -1329,8 +1329,7 @@ static void isofs_read_inode(struct inode * inode) inode->i_data.a_ops = &isofs_symlink_aops; } else /* XXX - parse_rock_ridge_inode() had already set i_rdev. */ - init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + init_special_inode(inode, inode->i_mode, inode->i_rdev); out: if (tmpde) diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 8d66d202f04e..ec218349feb1 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -228,9 +228,9 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de, * stored in the low field, and use that. */ if((low & ~0xff) && high == 0) { - inode->i_rdev = mk_kdev(low >> 8, low & 0xff); + inode->i_rdev = MKDEV(low >> 8, low & 0xff); } else { - inode->i_rdev = mk_kdev(high, low); + inode->i_rdev = MKDEV(high, low); } } break; diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 77b102d65299..915f3a57af46 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c @@ -362,7 +362,6 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, inode->i_nlink = raw_inode->nlink; inode->i_uid = raw_inode->uid; inode->i_gid = raw_inode->gid; - inode->i_rdev = NODEV; inode->i_size = raw_inode->dsize; inode->i_atime.tv_sec = raw_inode->atime; inode->i_mtime.tv_sec = raw_inode->mtime; @@ -1080,13 +1079,13 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) struct jffs_control *c; struct inode *inode; int result = 0; - u16 data; + u16 data = old_encode_dev(rdev); int err; - data = (MAJOR(rdev) << 8) | MINOR(rdev); - D1(printk("***jffs_mknod()\n")); + if (!old_valid_dev(rdev)) + return -EINVAL; lock_kernel(); dir_f = (struct jffs_file *)dir->u.generic_ip; c = dir_f->c; @@ -1737,7 +1736,7 @@ jffs_read_inode(struct inode *inode) u16 val; jffs_read_data(f, (char *)val, 0, 2); init_special_inode(inode, inode->i_mode, - MKDEV((val >> 8) & 255, val & 255)); + old_decode_dev(val)); } D3(printk (KERN_NOTICE "read_inode(): up biglock\n")); diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 9a2df58cb486..93742552a9e9 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -594,6 +594,9 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, mk uint32_t writtenlen; int ret; + if (!old_valid_dev(rdev)) + return -EINVAL; + ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; @@ -601,7 +604,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, mk c = JFFS2_SB_INFO(dir_i->i_sb); if (S_ISBLK(mode) || S_ISCHR(mode)) { - dev = cpu_to_je16((MAJOR(rdev) << 8) | MINOR(rdev)); + dev = cpu_to_je16(old_encode_dev(rdev)); devlen = sizeof(dev); } diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 4c43d597d0aa..531d79dea640 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -147,7 +147,8 @@ void jffs2_read_inode (struct inode *inode) case S_IFSOCK: case S_IFIFO: inode->i_op = &jffs2_file_inode_operations; - init_special_inode(inode, inode->i_mode, kdev_t_to_nr(mk_kdev(je16_to_cpu(rdev)>>8, je16_to_cpu(rdev)&0xff))); + init_special_inode(inode, inode->i_mode, + old_decode_dev(je16_to_cpu(rdev))); break; default: diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 8bc53c400875..991dcaf15c72 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -174,7 +174,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, int err; struct nameidata nd; int mtdnr; - kdev_t dev; + dev_t dev; if (!dev_name) return ERR_PTR(-EINVAL); @@ -240,14 +240,14 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, dev = nd.dentry->d_inode->i_rdev; path_release(&nd); - if (major(dev) != MTD_BLOCK_MAJOR) { + if (MAJOR(dev) != MTD_BLOCK_MAJOR) { if (!(flags & MS_VERBOSE)) /* Yes I mean this. Strangely */ printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", dev_name); return ERR_PTR(-EINVAL); } - return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, minor(dev)); + return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, MINOR(dev)); } diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 4ad780e83e73..989621a380b6 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -61,8 +61,7 @@ void jfs_read_inode(struct inode *inode) inode->i_op = &jfs_symlink_inode_operations; } else { inode->i_op = &jfs_file_inode_operations; - init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + init_special_inode(inode, inode->i_mode, inode->i_rdev); } } diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 847afd3030d8..cb40b149bd12 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -3041,9 +3041,10 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip) jfs_ip->next_index = le32_to_cpu(dip->di_next_index); jfs_ip->otime = le32_to_cpu(dip->di_otime.tv_sec); jfs_ip->acltype = le32_to_cpu(dip->di_acltype); + jfs_ip->dev = le32_to_cpu(dip->di_rdev); if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) - ip->i_rdev = to_kdev_t(le32_to_cpu(dip->di_rdev)); + ip->i_rdev = old_decode_dev(jfs_ip->dev); if (S_ISDIR(ip->i_mode)) { memcpy(&jfs_ip->i_dirtable, &dip->di_dirtable, 384); @@ -3100,9 +3101,7 @@ static void copy_to_dinode(struct dinode * dip, struct inode *ip) dip->di_otime.tv_sec = cpu_to_le32(jfs_ip->otime); dip->di_otime.tv_nsec = 0; dip->di_acltype = cpu_to_le32(jfs_ip->acltype); - - if (S_ISCHR(ip->i_mode) || S_ISBLK(ip->i_mode)) - dip->di_rdev = cpu_to_le32(kdev_t_to_nr(ip->i_rdev)); + dip->di_rdev = cpu_to_le32(jfs_ip->dev); } #ifdef _JFS_DEBUG_IMAP diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h index 2164d5cdfc10..15a99b075387 100644 --- a/fs/jfs/jfs_incore.h +++ b/fs/jfs/jfs_incore.h @@ -93,6 +93,7 @@ struct jfs_inode_info { unchar _inline_ea[128]; /* 128: inline extended attr */ } link; } u; + u32 dev; /* will die when we get wide dev_t */ struct inode vfs_inode; }; #define i_xtroot u.file._xtroot @@ -143,7 +144,7 @@ struct jfs_sb_info { short nbperpage; /* blocks per page */ short l2nbperpage; /* log2 blocks per page */ short l2niperblk; /* log2 inodes per page */ - u32 logdev; /* external log device */ + dev_t logdev; /* external log device */ uint aggregate; /* volume identifier in log record */ pxd_t logpxd; /* pxd describing log */ pxd_t fsckpxd; /* pxd describing fsck wkspc */ diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index b97311299412..4180b7c87d8d 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -395,7 +395,7 @@ static int chkSuper(struct super_block *sb) if (sbi->mntflag & JFS_INLINELOG) sbi->logpxd = j_sb->s_logpxd; else { - sbi->logdev = le32_to_cpu(j_sb->s_logdev); + sbi->logdev = old_decode_dev(le32_to_cpu(j_sb->s_logdev)); memcpy(sbi->uuid, j_sb->s_uuid, sizeof(sbi->uuid)); memcpy(sbi->loguuid, j_sb->s_loguuid, sizeof(sbi->uuid)); } diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 5062dc50b02d..71f3ccf53b77 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -1302,6 +1302,7 @@ int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, */ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { + struct jfs_inode_info *jfs_ip; struct btstack btstack; struct component_name dname; ino_t ino; @@ -1311,6 +1312,9 @@ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) tid_t tid; struct tblock *tblk; + if (!old_valid_dev(rdev)) + return -EINVAL; + jfs_info("jfs_mknod: %s", dentry->d_name.name); if ((rc = get_UCSname(&dname, dentry, JFS_SBI(dir->i_sb)->nls_tab))) @@ -1321,6 +1325,7 @@ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) rc = -ENOSPC; goto out1; } + jfs_ip = JFS_IP(ip); tid = txBegin(dir->i_sb, 0); @@ -1339,6 +1344,7 @@ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) goto out3; ip->i_op = &jfs_file_inode_operations; + jfs_ip->dev = old_encode_dev(rdev); init_special_inode(ip, ip->i_mode, rdev); insert_inode_hash(ip); diff --git a/fs/libfs.c b/fs/libfs.c index befcf41b0e30..fbf1d0e6e3e4 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -3,6 +3,7 @@ * Library for filesystems writers. */ +#include <linux/module.h> #include <linux/pagemap.h> #include <linux/mount.h> #include <linux/vfs.h> @@ -428,3 +429,22 @@ void simple_release_fs(struct vfsmount **mount, int *count) spin_unlock(&pin_fs_lock); mntput(mnt); } + +/* acceptable for old filesystems */ +int old_valid_dev(dev_t dev) +{ + return MAJOR(dev) < 256 && MINOR(dev) < 256; +} +EXPORT_SYMBOL(old_valid_dev); + +u16 old_encode_dev(dev_t dev) +{ + return (MAJOR(dev) << 8) | MINOR(dev); +} +EXPORT_SYMBOL(old_encode_dev); + +dev_t old_decode_dev(u16 val) +{ + return MKDEV((val >> 8) & 255, val & 255); +} +EXPORT_SYMBOL(old_decode_dev); diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 710e46886609..946f5812efc1 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -392,7 +392,7 @@ static void V1_minix_read_inode(struct inode * inode) inode->i_blocks = inode->i_blksize = 0; for (i = 0; i < 9; i++) minix_inode->u.i1_data[i] = raw_inode->i_zone[i]; - minix_set_inode(inode, raw_inode->i_zone[0]); + minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0])); brelse(bh); } @@ -425,7 +425,7 @@ static void V2_minix_read_inode(struct inode * inode) inode->i_blocks = inode->i_blksize = 0; for (i = 0; i < 10; i++) minix_inode->u.i2_data[i] = raw_inode->i_zone[i]; - minix_set_inode(inode, raw_inode->i_zone[0]); + minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0])); brelse(bh); } @@ -460,7 +460,7 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode) raw_inode->i_size = inode->i_size; raw_inode->i_time = inode->i_mtime.tv_sec; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev); + raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev); else for (i = 0; i < 9; i++) raw_inode->i_zone[i] = minix_inode->u.i1_data[i]; mark_buffer_dirty(bh); @@ -489,7 +489,7 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode) raw_inode->i_atime = inode->i_atime.tv_sec; raw_inode->i_ctime = inode->i_ctime.tv_sec; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - raw_inode->i_zone[0] = kdev_t_to_nr(inode->i_rdev); + raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev); else for (i = 0; i < 10; i++) raw_inode->i_zone[i] = minix_inode->u.i2_data[i]; mark_buffer_dirty(bh); diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 2b9e6c64d25a..9f2682641f7f 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -78,7 +78,12 @@ static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, st static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { int error; - struct inode * inode = minix_new_inode(dir, &error); + struct inode *inode; + + if (!old_valid_dev(rdev)) + return -EINVAL; + + inode = minix_new_inode(dir, &error); if (inode) { inode->i_mode = mode; diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index f10460e559a5..0e84d722cf0b 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c @@ -929,10 +929,10 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode, finfo.access = opmode; if (ncp_is_nfs_extras(server, finfo.volume)) { finfo.i.nfs.mode = mode; - finfo.i.nfs.rdev = rdev; + finfo.i.nfs.rdev = old_encode_dev(rdev); if (ncp_modify_nfs_info(server, finfo.volume, finfo.i.dirEntNum, - mode, rdev) != 0) + mode, old_encode_dev(rdev)) != 0) goto out; } @@ -1170,6 +1170,8 @@ out: static int ncp_mknod(struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { + if (!old_valid_dev(rdev)) + return -EINVAL; if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) { DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode); return ncp_create_new(dir, dentry, mode, rdev, 0); diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 70eab7961377..f3fe78dbfb66 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -220,7 +220,6 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) inode->i_nlink = 1; inode->i_uid = server->m.uid; inode->i_gid = server->m.gid; - inode->i_rdev = NODEV; inode->i_blksize = NCP_BLOCK_SIZE; ncp_update_dates(inode, &nwinfo->i); @@ -262,7 +261,8 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info) inode->i_fop = &ncp_dir_operations; #ifdef CONFIG_NCPFS_NFS_NS } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - init_special_inode(inode, inode->i_mode, info->i.nfs.rdev); + init_special_inode(inode, inode->i_mode, + old_decode_dev(info->i.nfs.rdev)); #endif #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) } else if (S_ISLNK(inode->i_mode)) { diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e7ba8d084182..f9f494a60e4b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -859,6 +859,9 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); + if (!old_valid_dev(rdev)) + return -EINVAL; + attr.ia_mode = mode; attr.ia_valid = ATTR_MODE; diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 1461252f66fe..d5f552dd7f4e 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -106,6 +106,7 @@ xdr_decode_time(u32 *p, struct timespec *timep) static u32 * xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) { + u32 rdev; fattr->type = (enum nfs_ftype) ntohl(*p++); fattr->mode = ntohl(*p++); fattr->nlink = ntohl(*p++); @@ -113,7 +114,7 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) fattr->gid = ntohl(*p++); fattr->size = ntohl(*p++); fattr->du.nfs2.blocksize = ntohl(*p++); - fattr->rdev = ntohl(*p++); + rdev = ntohl(*p++); fattr->du.nfs2.blocks = ntohl(*p++); fattr->fsid_u.nfs3 = ntohl(*p++); fattr->fileid = ntohl(*p++); @@ -121,7 +122,8 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) p = xdr_decode_time(p, &fattr->mtime); p = xdr_decode_time(p, &fattr->ctime); fattr->valid |= NFS_ATTR_FATTR; - if (fattr->type == NFCHR && fattr->rdev == NFS2_FIFO_DEV) { + fattr->rdev = old_decode_dev(rdev); + if (fattr->type == NFCHR && rdev == NFS2_FIFO_DEV) { fattr->type = NFFIFO; fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; fattr->rdev = 0; diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index b41f63972df7..c64ebaf8818e 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -242,7 +242,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, case S_IFCHR: case S_IFBLK: /* reserve rdev for later checking */ - attr->ia_size = kdev_t_to_nr(inode->i_rdev); + attr->ia_size = inode->i_rdev; attr->ia_valid |= ATTR_SIZE; /* FALLTHROUGH */ @@ -279,7 +279,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, int is_borc = 0; u32 size = attr->ia_size; - rdev = (dev_t) size; + /* may need to change when we widen dev_t */ + rdev = old_decode_dev(size); if (type != S_IFBLK && type != S_IFCHR) { rdev = 0; } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) { @@ -300,7 +301,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, /* Make sure the type and device matches */ nfserr = nfserr_exist; if (inode && (type != (inode->i_mode & S_IFMT) || - (is_borc && kdev_t_to_nr(inode->i_rdev) != rdev))) + (is_borc && inode->i_rdev != rdev))) goto out_unlock; } diff --git a/fs/partitions/nec98.c b/fs/partitions/nec98.c index 5f78e5b4895c..08c72aecea1f 100644 --- a/fs/partitions/nec98.c +++ b/fs/partitions/nec98.c @@ -73,10 +73,9 @@ int nec98_partition(struct parsed_partitions *state, struct block_device *bdev) const struct nec98_partition *part; unsigned char *data; int sector_size = bdev_hardsect_size(bdev); - int major = MAJOR(bdev->bd_dev); if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)&geo) != 0) { - printk(" unsupported disk (major = %u)\n", major); + printk(" unsupported disk (%s)\n", bdev->bd_disk->disk_name); return 0; } diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 362ee3135e69..267691bb5174 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -58,7 +58,6 @@ static struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_mapping->a_ops = &ramfs_aops; inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 3f621de0ba22..e33ddbab7552 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1003,7 +1003,7 @@ static void init_inode (struct inode * inode, struct path * path) inode->i_mapping->a_ops = &reiserfs_address_space_operations; } else { inode->i_blocks = 0; - init_special_inode(inode, inode->i_mode, rdev) ; + init_special_inode(inode, inode->i_mode, old_decode_dev(rdev)); } } @@ -1024,7 +1024,7 @@ static void inode2sd (void * sd, struct inode * inode) set_sd_v2_ctime(sd_v2, inode->i_ctime.tv_sec ); set_sd_v2_blocks(sd_v2, inode->i_blocks ); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - set_sd_v2_rdev(sd_v2, kdev_t_to_nr(inode->i_rdev) ); + set_sd_v2_rdev(sd_v2, old_encode_dev(inode->i_rdev)); else set_sd_v2_generation(sd_v2, inode->i_generation); flags = REISERFS_I(inode)->i_attrs; @@ -1048,7 +1048,7 @@ static void inode2sd_v1 (void * sd, struct inode * inode) set_sd_v1_mtime(sd_v1, inode->i_mtime.tv_sec ); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - set_sd_v1_rdev(sd_v1, kdev_t_to_nr(inode->i_rdev) ); + set_sd_v1_rdev(sd_v1, old_encode_dev(inode->i_rdev)); else set_sd_v1_blocks(sd_v1, inode->i_blocks ); diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 55f12082022b..803d414747e3 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1906,7 +1906,7 @@ static int journal_init_dev( struct super_block *super, journal -> j_dev_bd = NULL; journal -> j_dev_file = NULL; jdev = SB_ONDISK_JOURNAL_DEVICE( super ) ? - SB_ONDISK_JOURNAL_DEVICE( super ) : super->s_dev; + old_decode_dev(SB_ONDISK_JOURNAL_DEVICE(super)) : super->s_dev; if (bdev_read_only(super->s_bdev)) blkdev_mode = FMODE_READ; @@ -1939,7 +1939,6 @@ static int journal_init_dev( struct super_block *super, result = -ENOMEM; } else { /* ok */ - jdev = jdev_inode -> i_bdev -> bd_dev; set_blocksize(journal->j_dev_bd, super->s_blocksize); } } else { diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 85dddb7a83b3..8c1485504ffe 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -613,6 +613,9 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode, struct reiserfs_transaction_handle th ; int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3; + if (!old_valid_dev(rdev)) + return -EINVAL; + if (!(inode = new_inode(dir->i_sb))) { return -ENOMEM ; } diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 24cd428a521e..80b17af9bb0d 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -542,10 +542,8 @@ romfs_read_inode(struct inode *i) default: /* depending on MBZ for sock/fifos */ nextfh = ntohl(ri.spec); - /* convert back and forth for typechecking and - * source tagging */ - nextfh = kdev_t_to_nr(mk_kdev(nextfh>>16,nextfh&0xffff)); - init_special_inode(i, ino, nextfh); + init_special_inode(i, ino, + MKDEV(nextfh>>16,nextfh&0xffff)); } } diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index f0b62740ae89..aa5974edc203 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c @@ -661,6 +661,9 @@ smb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) attr.ia_uid = current->euid; attr.ia_gid = current->egid; + if (!old_valid_dev(dev)) + return -EINVAL; + smb_invalid_dir_cache(dir); error = smb_proc_setattr_unix(dentry, &attr, MAJOR(dev), MINOR(dev)); if (!error) { diff --git a/fs/stat.c b/fs/stat.c index 7f034fa65d88..a1f3d7d874fa 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -24,7 +24,7 @@ void generic_fillattr(struct inode *inode, struct kstat *stat) stat->nlink = inode->i_nlink; stat->uid = inode->i_uid; stat->gid = inode->i_gid; - stat->rdev = kdev_t_to_nr(inode->i_rdev); + stat->rdev = inode->i_rdev; stat->atime = inode->i_atime; stat->mtime = inode->i_mtime; stat->ctime = inode->i_ctime; diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index c22313b1fa7a..965b5e9eaba1 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -33,7 +33,6 @@ struct inode * sysfs_new_inode(mode_t mode) inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 9a4564610aae..09c131fbb36f 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -164,10 +164,8 @@ static void sysv_read_inode(struct inode *inode) struct buffer_head * bh; struct sysv_inode * raw_inode; struct sysv_inode_info * si; - unsigned int block, ino; - dev_t rdev = 0; + unsigned int block, ino = inode->i_ino; - ino = inode->i_ino; if (!ino || ino > sbi->s_ninodes) { printk("Bad inode number on dev %s: %d is out of range\n", inode->i_sb->s_id, ino); @@ -198,10 +196,12 @@ static void sysv_read_inode(struct inode *inode) read3byte(sbi, &raw_inode->i_data[3*block], (u8 *)&si->i_data[block]); brelse(bh); - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - rdev = (u16)fs32_to_cpu(sbi, si->i_data[0]); si->i_dir_start_lookup = 0; - sysv_set_inode(inode, rdev); + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) + sysv_set_inode(inode, + old_decode_dev(fs32_to_cpu(sbi, si->i_data[0]))); + else + sysv_set_inode(inode, 0); return; bad_inode: @@ -241,7 +241,7 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) si = SYSV_I(inode); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - si->i_data[0] = cpu_to_fs32(sbi, kdev_t_to_nr(inode->i_rdev)); + si->i_data[0] = cpu_to_fs32(sbi, old_encode_dev(inode->i_rdev)); for (block = 0; block < 10+1+1+1; block++) write3byte(sbi, (u8 *)&si->i_data[block], &raw_inode->i_data[3*block]); diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index cbf08f04d07c..c24d0be87e74 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -85,8 +85,14 @@ static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, st static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t rdev) { - struct inode * inode = sysv_new_inode(dir, mode); - int err = PTR_ERR(inode); + struct inode * inode; + int err; + + if (!old_valid_dev(rdev)) + return -EINVAL; + + inode = sysv_new_inode(dir, mode); + err = PTR_ERR(inode); if (!IS_ERR(inode)) { sysv_set_inode(inode, rdev); diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 2fa65ab370d7..d892081d73ab 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1234,9 +1234,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) if (dsea) { - init_special_inode(inode, inode->i_mode, - ((le32_to_cpu(dsea->majorDeviceIdent)) << 8) | - (le32_to_cpu(dsea->minorDeviceIdent) & 0xFF)); + init_special_inode(inode, inode->i_mode, MKDEV( + le32_to_cpu(dsea->majorDeviceIdent), + le32_to_cpu(dsea->minorDeviceIdent) + )); /* Developer ID ??? */ udf_release_data(tbh); } @@ -1392,8 +1393,8 @@ udf_update_inode(struct inode *inode, int do_sync) strcpy(eid->ident, UDF_ID_DEVELOPER); eid->identSuffix[0] = UDF_OS_CLASS_UNIX; eid->identSuffix[1] = UDF_OS_ID_LINUX; - dsea->majorDeviceIdent = kdev_t_to_nr(inode->i_rdev) >> 8; - dsea->minorDeviceIdent = kdev_t_to_nr(inode->i_rdev) & 0xFF; + dsea->majorDeviceIdent = cpu_to_le32(imajor(inode)); + dsea->minorDeviceIdent = cpu_to_le32(iminor(inode)); mark_buffer_dirty_inode(tbh, inode); udf_release_data(tbh); } diff --git a/fs/udf/namei.c b/fs/udf/namei.c index d2ac88dae447..a7350413f9b8 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -677,6 +677,9 @@ static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t int err; struct fileIdentDesc cfi, *fi; + if (!old_valid_dev(rdev)) + return -EINVAL; + lock_kernel(); err = -EIO; inode = udf_new_inode(dir, mode, &err); diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 442c28e17739..647c7bef9680 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -475,6 +475,7 @@ void ufs_read_inode (struct inode * inode) struct ufs_sb_private_info * uspi; struct ufs_inode * ufs_inode; struct buffer_head * bh; + mode_t mode; unsigned i; unsigned flags; @@ -500,7 +501,7 @@ void ufs_read_inode (struct inode * inode) /* * Copy data to the in-core inode. */ - inode->i_mode = fs16_to_cpu(sb, ufs_inode->ui_mode); + inode->i_mode = mode = fs16_to_cpu(sb, ufs_inode->ui_mode); inode->i_nlink = fs16_to_cpu(sb, ufs_inode->ui_nlink); if (inode->i_nlink == 0) ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino); @@ -527,9 +528,7 @@ void ufs_read_inode (struct inode * inode) ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); ufsi->i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - ; - else if (inode->i_blocks) { + if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) ufsi->i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i]; } @@ -555,7 +554,7 @@ void ufs_read_inode (struct inode * inode) } } else init_special_inode(inode, inode->i_mode, - fs32_to_cpu(sb, ufs_inode->ui_u2.ui_addr.ui_db[0])); + old_decode_dev(fs32_to_cpu(sb, ufsi->i_u1.i_data[0]))); brelse (bh); @@ -618,9 +617,10 @@ static int ufs_update_inode(struct inode * inode, int do_sync) ufs_inode->ui_u3.ui_sun.ui_oeftflag = cpu_to_fs32(sb, ufsi->i_oeftflag); } - if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) - ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, kdev_t_to_nr(inode->i_rdev)); - else if (inode->i_blocks) { + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { + /* ufs_inode->ui_u2.ui_addr.ui_db[0] = cpu_to_fs32(sb, inode->i_rdev); */ + ufs_inode->ui_u2.ui_addr.ui_db[0] = ufsi->i_u1.i_data[0]; + } else if (inode->i_blocks) { for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) ufs_inode->ui_u2.ui_addr.ui_db[i] = ufsi->i_u1.i_data[i]; } diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 82f391298c48..224d2c08d771 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -29,6 +29,7 @@ #include <linux/ufs_fs.h> #include <linux/smp_lock.h> #include <linux/buffer_head.h> +#include "swab.h" /* will go away - see comment in mknod() */ #undef UFS_NAMEI_DEBUG @@ -111,10 +112,16 @@ static int ufs_create (struct inode * dir, struct dentry * dentry, int mode, static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { - struct inode * inode = ufs_new_inode(dir, mode); + struct inode * inode; + if (!old_valid_dev(rdev)) + return -EINVAL; + inode = ufs_new_inode(dir, mode); int err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, mode, rdev); + /* NOTE: that'll go when we get wide dev_t */ + UFS_I(inode)->i_u1.i_data[0] = cpu_to_fs32(inode->i_sb, + old_encode_dev(rdev)); mark_inode_dirty(inode); lock_kernel(); err = ufs_add_nondir(dentry, inode); diff --git a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c index 11eac5784afa..cb9bcdda6d01 100644 --- a/fs/xfs/linux/xfs_iops.c +++ b/fs/xfs/linux/xfs_iops.c @@ -113,6 +113,9 @@ linvfs_mknod( xattr_exists_t test_default_acl = _ACL_DEFAULT_EXISTS; int error; + if (!old_valid_dev(rdev)) + return -EINVAL; + if (test_default_acl && test_default_acl(dvp)) { if (!_ACL_ALLOC(default_acl)) return -ENOMEM; @@ -178,7 +181,7 @@ linvfs_mknod( ip = LINVFS_GET_IP(vp); if (S_ISCHR(mode) || S_ISBLK(mode)) - ip->i_rdev = to_kdev_t(rdev); + ip->i_rdev = rdev; else if (S_ISDIR(mode)) validate_fields(ip); d_instantiate(dentry, ip); diff --git a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c index 49c173f9e5d0..1bd4b3a4a604 100644 --- a/fs/xfs/linux/xfs_super.c +++ b/fs/xfs/linux/xfs_super.c @@ -154,7 +154,7 @@ xfs_set_inodeops( } else { inode->i_op = &linvfs_file_inode_operations; init_special_inode(inode, inode->i_mode, - kdev_t_to_nr(inode->i_rdev)); + inode->i_rdev); } } @@ -171,7 +171,7 @@ xfs_revalidate_inode( inode->i_uid = ip->i_d.di_uid; inode->i_gid = ip->i_d.di_gid; if (((1 << vp->v_type) & ((1<<VBLK) | (1<<VCHR))) == 0) { - inode->i_rdev = NODEV; + inode->i_rdev = 0; } else { xfs_dev_t dev = ip->i_df.if_u2.if_rdev; inode->i_rdev = XFS_DEV_TO_KDEVT(dev); diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h index bdb7ca141927..3c163b46160e 100644 --- a/fs/xfs/xfs_types.h +++ b/fs/xfs/xfs_types.h @@ -210,6 +210,6 @@ typedef enum { #define XFS_MKDEV(major,minor) ((xfs_dev_t)(((major)<<XFS_DEV_BITSMINOR) \ | (minor&XFS_DEV_MAXMIN))) -#define XFS_DEV_TO_KDEVT(dev) mk_kdev(XFS_DEV_MAJOR(dev),XFS_DEV_MINOR(dev)) +#define XFS_DEV_TO_KDEVT(dev) MKDEV(XFS_DEV_MAJOR(dev),XFS_DEV_MINOR(dev)) #endif /* !__XFS_TYPES_H */ diff --git a/fs/xfs/xfsidbg.c b/fs/xfs/xfsidbg.c index 9d463a3e85cf..785c52cc23a5 100644 --- a/fs/xfs/xfsidbg.c +++ b/fs/xfs/xfsidbg.c @@ -1687,7 +1687,7 @@ static void printinode(struct inode *ip) kdb_printf( " i_mode = 0x%x i_nlink = %d i_rdev = 0x%x i_state = 0x%lx\n", ip->i_mode, ip->i_nlink, - kdev_t_to_nr(ip->i_rdev), ip->i_state); + ip->i_rdev, ip->i_state); kdb_printf(" i_hash.nxt = 0x%p i_hash.prv = 0x%p\n", ip->i_hash.next, ip->i_hash.prev); diff --git a/include/asm-i386/termios.h b/include/asm-i386/termios.h index c0fded995489..03f548536d6b 100644 --- a/include/asm-i386/termios.h +++ b/include/asm-i386/termios.h @@ -102,8 +102,6 @@ struct termio { #define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) #define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) -#define MODULE_ALIAS_LDISC(ldisc) \ - MODULE_ALIAS("tty-ldisc-" __stringify(ldisc)) #endif /* __KERNEL__ */ #endif /* _I386_TERMIOS_H */ diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h index 48ba080c0794..0a8ad4cac125 100644 --- a/include/asm-sparc/termios.h +++ b/include/asm-sparc/termios.h @@ -169,9 +169,6 @@ struct winsize { 0; \ }) -#define MODULE_ALIAS_LDISC(ldisc) \ - MODULE_ALIAS("tty-ldisc-" __stringify(ldisc)) - #endif /* __KERNEL__ */ #endif /* _SPARC_TERMIOS_H */ diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h index 4e7fef518a25..8effce0da087 100644 --- a/include/asm-sparc64/termios.h +++ b/include/asm-sparc64/termios.h @@ -168,9 +168,6 @@ struct winsize { 0; \ }) -#define MODULE_ALIAS_LDISC(ldisc) \ - MODULE_ALIAS("tty-ldisc-" __stringify(ldisc)) - #endif /* __KERNEL__ */ #endif /* _SPARC64_TERMIOS_H */ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9c7e6d86e810..285fd86e2b48 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -270,7 +270,7 @@ struct request_queue * Together with queue_head for cacheline sharing */ struct list_head queue_head; - struct list_head *last_merge; + struct request *last_merge; elevator_t elevator; /* diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 3d466f6680cb..f747117285f4 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -36,11 +36,13 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); #define CPUFREQ_POLICY_NOTIFIER (1) -/********************** cpufreq policy notifiers *********************/ +/* if (cpufreq_driver->target) exists, the ->governor decides what frequency + * within the limits is used. If (cpufreq_driver->setpolicy> exists, these + * two generic policies are available: + */ #define CPUFREQ_POLICY_POWERSAVE (1) #define CPUFREQ_POLICY_PERFORMANCE (2) -#define CPUFREQ_POLICY_GOVERNOR (3) /* Frequency values here are CPU kHz so that hardware which doesn't run * with some frequencies can complain without having to guess what per @@ -151,6 +153,7 @@ int cpufreq_governor(unsigned int cpu, unsigned int event); int cpufreq_register_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor); + /********************************************************************* * CPUFREQ DRIVER INTERFACE * *********************************************************************/ @@ -176,6 +179,7 @@ struct cpufreq_driver { /* optional */ int (*exit) (struct cpufreq_policy *policy); + int (*resume) (struct cpufreq_policy *policy); struct freq_attr **attr; }; @@ -221,7 +225,6 @@ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpu /********************************************************************* * CPUFREQ USERSPACE GOVERNOR * *********************************************************************/ -extern struct cpufreq_governor cpufreq_gov_userspace; int cpufreq_gov_userspace_init(void); int cpufreq_setmax(unsigned int cpu); @@ -280,6 +283,19 @@ enum { /********************************************************************* + * CPUFREQ DEFAULT GOVERNOR * + *********************************************************************/ + + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE +extern struct cpufreq_governor cpufreq_gov_performance; +#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance +#elif CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +extern struct cpufreq_governor cpufreq_gov_userspace; +#define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace +#endif + +/********************************************************************* * FREQUENCY TABLE HELPERS * *********************************************************************/ diff --git a/include/linux/elevator.h b/include/linux/elevator.h index ac30ae089069..e43d670c1371 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -1,7 +1,7 @@ #ifndef _LINUX_ELEVATOR_H #define _LINUX_ELEVATOR_H -typedef int (elevator_merge_fn) (request_queue_t *, struct list_head **, +typedef int (elevator_merge_fn) (request_queue_t *, struct request **, struct bio *); typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struct request *); @@ -10,7 +10,7 @@ typedef void (elevator_merged_fn) (request_queue_t *, struct request *); typedef struct request *(elevator_next_req_fn) (request_queue_t *); -typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *); +typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, int); typedef int (elevator_queue_empty_fn) (request_queue_t *); typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *); typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *); @@ -62,7 +62,7 @@ struct elevator_s */ extern void elv_add_request(request_queue_t *, struct request *, int, int); extern void __elv_add_request(request_queue_t *, struct request *, int, int); -extern int elv_merge(request_queue_t *, struct list_head **, struct bio *); +extern int elv_merge(request_queue_t *, struct request **, struct bio *); extern void elv_merge_requests(request_queue_t *, struct request *, struct request *); extern void elv_merged_request(request_queue_t *, struct request *); @@ -79,9 +79,6 @@ extern void elv_completed_request(request_queue_t *, struct request *); extern int elv_set_request(request_queue_t *, struct request *, int); extern void elv_put_request(request_queue_t *, struct request *); -#define __elv_add_request_pos(q, rq, pos) \ - (q)->elevator.elevator_add_req_fn((q), (rq), (pos)) - /* * noop I/O scheduler. always merges, always inserts new request at tail */ @@ -111,4 +108,11 @@ extern inline int elv_try_last_merge(request_queue_t *, struct bio *); #define ELEVATOR_FRONT_MERGE 1 #define ELEVATOR_BACK_MERGE 2 +/* + * Insertion selection + */ +#define ELEVATOR_INSERT_FRONT 1 +#define ELEVATOR_INSERT_BACK 2 +#define ELEVATOR_INSERT_SORT 3 + #endif diff --git a/include/linux/fs.h b/include/linux/fs.h index 87ae270bf96c..d10db09f6164 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -373,7 +373,7 @@ struct inode { unsigned int i_nlink; uid_t i_uid; gid_t i_gid; - kdev_t i_rdev; + dev_t i_rdev; loff_t i_size; struct timespec i_atime; struct timespec i_mtime; @@ -469,12 +469,12 @@ static inline void i_size_write(struct inode *inode, loff_t i_size) static inline unsigned iminor(struct inode *inode) { - return minor(inode->i_rdev); + return MINOR(inode->i_rdev); } static inline unsigned imajor(struct inode *inode) { - return major(inode->i_rdev); + return MAJOR(inode->i_rdev); } struct fown_struct { @@ -1156,7 +1156,6 @@ extern struct block_device *lookup_bdev(const char *); extern struct block_device *open_bdev_excl(const char *, int, int, void *); extern void close_bdev_excl(struct block_device *, int); -extern const char * cdevname(kdev_t); extern void init_special_inode(struct inode *, umode_t, dev_t); /* Invalid inode operations -- fs/bad_inode.c */ @@ -1390,6 +1389,9 @@ struct tree_descr { char *name; struct file_operations *ops; int mode; }; extern int simple_fill_super(struct super_block *, int, struct tree_descr *); extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count); extern void simple_release_fs(struct vfsmount **mount, int *count); +extern int old_valid_dev(dev_t); +extern u16 old_encode_dev(dev_t); +extern dev_t old_decode_dev(u16); extern int inode_change_ok(struct inode *, struct iattr *); extern int inode_setattr(struct inode *, struct iattr *); diff --git a/include/linux/kdev_t.h b/include/linux/kdev_t.h index 900a4a1e1282..f60508da024d 100644 --- a/include/linux/kdev_t.h +++ b/include/linux/kdev_t.h @@ -1,101 +1,6 @@ #ifndef _LINUX_KDEV_T_H #define _LINUX_KDEV_T_H #ifdef __KERNEL__ -/* -As a preparation for the introduction of larger device numbers, -we introduce a type kdev_t to hold them. No information about -this type is known outside of this include file. - -Objects of type kdev_t designate a device. Outside of the kernel -the corresponding things are objects of type dev_t - usually an -integral type with the device major and minor in the high and low -bits, respectively. Conversion is done by - -extern kdev_t to_kdev_t(int); - -It is up to the various file systems to decide how objects of type -dev_t are stored on disk. -The only other point of contact between kernel and outside world -are the system calls stat and mknod, new versions of which will -eventually have to be used in libc. - -[Unfortunately, the floppy control ioctls fail to hide the internal -kernel structures, and the fd_device field of a struct floppy_drive_struct -is user-visible. So, it remains a dev_t for the moment, with some ugly -conversions in floppy.c.] - -Inside the kernel, we aim for a kdev_t type that is a pointer -to a structure with information about the device (like major, -minor, size, blocksize, sectorsize, name, read-only flag, -struct file_operations etc.). - -However, for the time being we let kdev_t be almost the same as dev_t: - -typedef struct { unsigned short major, minor; } kdev_t; - -Admissible operations on an object of type kdev_t: -- passing it along -- comparing it for equality with another such object -- storing it in inode->i_rdev or tty->device -- using its bit pattern as argument in a hash function -- finding its major and minor -- complaining about it - -An object of type kdev_t is created only by the function MKDEV(), -with the single exception of the constant 0 (no device). - -Right now the other information mentioned above is usually found -in static arrays indexed by major or major,minor. - -An obstacle to immediately using - typedef struct { ... (* lots of information *) } *kdev_t -is the case of mknod used to create a block device that the -kernel doesn't know about at present (but first learns about -when some module is inserted). - -aeb - 950811 -*/ - - -/* - * NOTE NOTE NOTE! - * - * The kernel-internal "kdev_t" will eventually have - * 20 bits for minor numbers, and 12 bits for majors. - * - * HOWEVER, the external representation is still 8+8 - * bits, and there is no way to generate the extended - * "kdev_t" format yet. Which is just as well, since - * we still use "minor" as an index into various - * static arrays, and they are sized for a 8-bit index. - */ -typedef struct { - unsigned short value; -} kdev_t; - -#define KDEV_MINOR_BITS 8 -#define KDEV_MAJOR_BITS 8 - -#define __mkdev(major,minor) (((major) << KDEV_MINOR_BITS) + (minor)) - -#define mk_kdev(major, minor) ((kdev_t) { __mkdev(major,minor) } ) - -/* - * The "values" are just _cookies_, usable for - * internal equality comparisons and for things - * like NFS filehandle conversion. - */ -static inline unsigned int kdev_val(kdev_t dev) -{ - return dev.value; -} - -#define NODEV (mk_kdev(0,0)) - -/* Mask off the high bits for now.. */ -#define minor(dev) ((dev).value & 0xff) -#define major(dev) (((dev).value >> KDEV_MINOR_BITS) & 0xff) - /* These are for user-level "dev_t" */ #define MINORBITS 8 #define MINORMASK ((1U << MINORBITS) - 1) @@ -104,20 +9,6 @@ static inline unsigned int kdev_val(kdev_t dev) #define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) #define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi)) -/* - * Conversion functions - */ - -static inline int kdev_t_to_nr(kdev_t dev) -{ - return MKDEV(major(dev), minor(dev)); -} - -static inline kdev_t to_kdev_t(int dev) -{ - return mk_kdev(MAJOR(dev),MINOR(dev)); -} - #define print_dev_t(buffer, dev) \ sprintf((buffer), "%u:%u\n", MAJOR(dev), MINOR(dev)) diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 7fa02a737518..8412faeea0f7 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h @@ -29,7 +29,7 @@ extern int request_module(const char * name, ...) __attribute__ ((format (printf static inline int request_module(const char * name, ...) { return -ENOSYS; } #endif -#define try_then_request_module(x, mod...) ((x) ?: request_module(mod), (x)) +#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x))) extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait); #ifdef CONFIG_HOTPLUG diff --git a/include/linux/mm.h b/include/linux/mm.h index 445fc58751c7..9f9743146b54 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -110,6 +110,7 @@ struct vm_area_struct { #define VM_RESERVED 0x00080000 /* Don't unmap it from swap_out */ #define VM_ACCOUNT 0x00100000 /* Is a VM accounted object */ #define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ +#define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS diff --git a/include/linux/mman.h b/include/linux/mman.h index a8956f6588ad..cfb6ac61bbde 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -2,6 +2,7 @@ #define _LINUX_MMAN_H #include <linux/config.h> +#include <linux/mm.h> #include <asm/atomic.h> #include <asm/mman.h> @@ -27,4 +28,32 @@ static inline void vm_unacct_memory(long pages) vm_acct_memory(-pages); } +/* Optimisation macro. */ +#define _calc_vm_trans(x,bit1,bit2) \ + ((bit1) <= (bit2) ? ((x) & (bit1)) * ((bit2) / (bit1)) \ + : ((x) & (bit1)) / ((bit1) / (bit2))) + +/* + * Combine the mmap "prot" argument into "vm_flags" used internally. + */ +static inline unsigned long +calc_vm_prot_bits(unsigned long prot) +{ + return _calc_vm_trans(prot, PROT_READ, VM_READ ) | + _calc_vm_trans(prot, PROT_WRITE, VM_WRITE) | + _calc_vm_trans(prot, PROT_EXEC, VM_EXEC ); +} + +/* + * Combine the mmap "flags" argument into "vm_flags" used internally. + */ +static inline unsigned long +calc_vm_flag_bits(unsigned long flags) +{ + return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) | + _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) | + _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) | + _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ); +} + #endif /* _LINUX_MMAN_H */ diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 3d46a2caaade..88b705d8cefe 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -23,7 +23,7 @@ struct nfs_fattr { __u64 used; } nfs3; } du; - __u32 rdev; + dev_t rdev; union { __u64 nfs3; /* also nfs2 */ struct { diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 3e3a26916a12..fd8b35209ccc 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -3,9 +3,6 @@ #include <linux/netlink.h> -#define RTNL_DEBUG 1 - - /**** * Routing/neighbour discovery messages. ****/ diff --git a/include/linux/sctp.h b/include/linux/sctp.h index 6ebaff34570c..6131e3c9aa45 100644 --- a/include/linux/sctp.h +++ b/include/linux/sctp.h @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -42,6 +42,8 @@ * randall@sctp.chicago.il.us * kmorneau@cisco.com * qxie1@email.mot.com + * Sridhar Samudrala <sri@us.ibm.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -507,6 +509,11 @@ typedef struct sctp_cwr_chunk { * The ASCONF Parameter Response is used in the ASCONF-ACK to * report status of ASCONF processing. */ +typedef struct sctp_addip_param { + sctp_paramhdr_t param_hdr; + __u32 crr_id; +}sctp_addip_param_t __attribute__((packed)); + typedef struct sctp_addiphdr { __u32 serial; __u8 params[0]; diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index ac8ac46845ba..c851b7dc997e 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -138,4 +138,7 @@ struct tty_ldisc { #define LDISC_FLAG_DEFINED 0x00000001 +#define MODULE_ALIAS_LDISC(ldisc) \ + MODULE_ALIAS("tty-ldisc-" __stringify(ldisc)) + #endif /* _LINUX_TTY_LDISC_H */ diff --git a/include/linux/vcache.h b/include/linux/vcache.h deleted file mode 100644 index 5708fe6a908a..000000000000 --- a/include/linux/vcache.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * virtual => physical mapping cache support. - */ -#ifndef _LINUX_VCACHE_H -#define _LINUX_VCACHE_H - -typedef struct vcache_s { - unsigned long address; - struct mm_struct *mm; - struct list_head hash_entry; - void (*callback)(struct vcache_s *data, struct page *new_page); -} vcache_t; - -extern spinlock_t vcache_lock; - -extern void __attach_vcache(vcache_t *vcache, - unsigned long address, - struct mm_struct *mm, - void (*callback)(struct vcache_s *data, struct page *new_page)); - -extern void __detach_vcache(vcache_t *vcache); - -extern void invalidate_vcache(unsigned long address, struct mm_struct *mm, - struct page *new_page); - -#endif diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 506fd2cb1305..3f21f1985699 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001-2003 Intel Corp. * * This file is part of the SCTP kernel reference Implementation @@ -40,6 +40,7 @@ * Sridhar Samudrala <sri@us.ibm.com> * Ardelle Fan <ardelle.fan@intel.com> * Ryan Layer <rmlayer@us.ibm.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -145,6 +146,7 @@ int sctp_primitive_SHUTDOWN(struct sctp_association *, void *arg); int sctp_primitive_ABORT(struct sctp_association *, void *arg); int sctp_primitive_SEND(struct sctp_association *, void *arg); int sctp_primitive_REQUESTHEARTBEAT(struct sctp_association *, void *arg); +int sctp_primitive_ASCONF(struct sctp_association *, void *arg); /* * sctp/crc32c.c @@ -404,6 +406,12 @@ static inline struct list_head *sctp_list_dequeue(struct list_head *list) return result; } +/* Tests if the list has one and only one entry. */ +static inline int sctp_list_single_entry(struct list_head *head) +{ + return ((head->next != head) && (head->next == head->prev)); +} + /* Calculate the size (in bytes) occupied by the data of an iovec. */ static inline size_t get_user_iov_size(struct iovec *iov, int iovlen) { @@ -525,6 +533,19 @@ static inline int ipver2af(__u8 ipver) }; } +/* Convert from an address parameter type to an address family. */ +static inline int param_type2af(__u16 type) +{ + switch (type) { + case SCTP_PARAM_IPV4_ADDRESS: + return AF_INET; + case SCTP_PARAM_IPV6_ADDRESS: + return AF_INET6; + default: + return 0; + }; +} + /* Perform some sanity checks. */ static inline int sctp_sanity_check(void) { diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 28d4c6409247..3eb9c18df0c5 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -41,6 +41,7 @@ * Sridhar Samudrala <sri@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com> * Ardelle Fan <ardelle.fan@intel.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -268,6 +269,9 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, struct sctp_chunk *asconf, int vparam_len); +struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr); + void sctp_chunk_assign_tsn(struct sctp_chunk *); void sctp_chunk_assign_ssn(struct sctp_chunk *); @@ -330,12 +334,6 @@ void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, __u32 sctp_generate_tag(const struct sctp_endpoint *); __u32 sctp_generate_tsn(const struct sctp_endpoint *); -/* 4th level prototypes */ -void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *, - __u16 port, int iif); -int sctp_addr2sockaddr(const union sctp_params, union sctp_addr *); -int sockaddr2sctp_addr(const union sctp_addr *, union sctp_addr_param *); - /* Extern declarations for major data structures. */ const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t); extern const sctp_sm_table_entry_t diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index f77373f18e7e..7ba32701be00 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001 Intel Corp. - * Copyright (c) 2001-2003 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -45,6 +45,7 @@ * Ardelle Fan <ardelle.fan@intel.com> * Ryan Layer <rmlayer@us.ibm.com> * Anup Pemmaiah <pemmaiah@cc.usu.edu> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -217,86 +218,6 @@ extern struct sctp_globals { #define sctp_local_addr_list (sctp_globals.local_addr_list) #define sctp_local_addr_lock (sctp_globals.local_addr_lock) -/* - * Pointers to address related SCTP functions. - * (i.e. things that depend on the address family.) - */ -struct sctp_af { - int (*sctp_xmit) (struct sk_buff *skb, - struct sctp_transport *, - int ipfragok); - int (*setsockopt) (struct sock *sk, - int level, - int optname, - char *optval, - int optlen); - int (*getsockopt) (struct sock *sk, - int level, - int optname, - char *optval, - int *optlen); - struct dst_entry *(*get_dst) (struct sctp_association *asoc, - union sctp_addr *daddr, - union sctp_addr *saddr); - void (*get_saddr) (struct sctp_association *asoc, - struct dst_entry *dst, - union sctp_addr *daddr, - union sctp_addr *saddr); - void (*copy_addrlist) (struct list_head *, - struct net_device *); - void (*dst_saddr) (union sctp_addr *saddr, - struct dst_entry *dst, - unsigned short port); - int (*cmp_addr) (const union sctp_addr *addr1, - const union sctp_addr *addr2); - void (*addr_copy) (union sctp_addr *dst, - union sctp_addr *src); - void (*from_skb) (union sctp_addr *, - struct sk_buff *skb, - int saddr); - void (*from_sk) (union sctp_addr *, - struct sock *sk); - void (*to_sk_saddr) (union sctp_addr *, - struct sock *sk); - void (*to_sk_daddr) (union sctp_addr *, - struct sock *sk); - int (*addr_valid) (union sctp_addr *, - struct sctp_opt *); - sctp_scope_t (*scope) (union sctp_addr *); - void (*inaddr_any) (union sctp_addr *, unsigned short); - int (*is_any) (const union sctp_addr *); - int (*available) (union sctp_addr *, - struct sctp_opt *); - int (*skb_iif) (const struct sk_buff *sk); - int (*is_ce) (const struct sk_buff *sk); - void (*seq_dump_addr)(struct seq_file *seq, - union sctp_addr *addr); - __u16 net_header_len; - int sockaddr_len; - sa_family_t sa_family; - struct list_head list; -}; - -struct sctp_af *sctp_get_af_specific(sa_family_t); -int sctp_register_af(struct sctp_af *); - -/* Protocol family functions. */ -struct sctp_pf { - void (*event_msgname)(struct sctp_ulpevent *, char *, int *); - void (*skb_msgname) (struct sk_buff *, char *, int *); - int (*af_supported) (sa_family_t, struct sctp_opt *); - int (*cmp_addr) (const union sctp_addr *, - const union sctp_addr *, - struct sctp_opt *); - int (*bind_verify) (struct sctp_opt *, union sctp_addr *); - int (*send_verify) (struct sctp_opt *, union sctp_addr *); - int (*supported_addrs)(const struct sctp_opt *, __u16 *); - struct sock *(*create_accept_sk) (struct sock *sk, - struct sctp_association *asoc); - void (*addr_v4map) (struct sctp_opt *, union sctp_addr *); - struct sctp_af *af; -}; - /* SCTP Socket type: UDP or TCP style. */ typedef enum { SCTP_SOCKET_UDP = 0, @@ -488,6 +409,92 @@ static inline __u16 sctp_ssn_next(struct sctp_stream *stream, __u16 id) return stream->ssn[id]++; } +/* + * Pointers to address related SCTP functions. + * (i.e. things that depend on the address family.) + */ +struct sctp_af { + int (*sctp_xmit) (struct sk_buff *skb, + struct sctp_transport *, + int ipfragok); + int (*setsockopt) (struct sock *sk, + int level, + int optname, + char *optval, + int optlen); + int (*getsockopt) (struct sock *sk, + int level, + int optname, + char *optval, + int *optlen); + struct dst_entry *(*get_dst) (struct sctp_association *asoc, + union sctp_addr *daddr, + union sctp_addr *saddr); + void (*get_saddr) (struct sctp_association *asoc, + struct dst_entry *dst, + union sctp_addr *daddr, + union sctp_addr *saddr); + void (*copy_addrlist) (struct list_head *, + struct net_device *); + void (*dst_saddr) (union sctp_addr *saddr, + struct dst_entry *dst, + unsigned short port); + int (*cmp_addr) (const union sctp_addr *addr1, + const union sctp_addr *addr2); + void (*addr_copy) (union sctp_addr *dst, + union sctp_addr *src); + void (*from_skb) (union sctp_addr *, + struct sk_buff *skb, + int saddr); + void (*from_sk) (union sctp_addr *, + struct sock *sk); + void (*to_sk_saddr) (union sctp_addr *, + struct sock *sk); + void (*to_sk_daddr) (union sctp_addr *, + struct sock *sk); + void (*from_addr_param) (union sctp_addr *, + union sctp_addr_param *, + __u16 port, int iif); + int (*to_addr_param) (const union sctp_addr *, + union sctp_addr_param *); + int (*addr_valid) (union sctp_addr *, + struct sctp_opt *); + sctp_scope_t (*scope) (union sctp_addr *); + void (*inaddr_any) (union sctp_addr *, unsigned short); + int (*is_any) (const union sctp_addr *); + int (*available) (union sctp_addr *, + struct sctp_opt *); + int (*skb_iif) (const struct sk_buff *sk); + int (*is_ce) (const struct sk_buff *sk); + void (*seq_dump_addr)(struct seq_file *seq, + union sctp_addr *addr); + __u16 net_header_len; + int sockaddr_len; + sa_family_t sa_family; + struct list_head list; +}; + +struct sctp_af *sctp_get_af_specific(sa_family_t); +int sctp_register_af(struct sctp_af *); + +/* Protocol family functions. */ +struct sctp_pf { + void (*event_msgname)(struct sctp_ulpevent *, char *, int *); + void (*skb_msgname) (struct sk_buff *, char *, int *); + int (*af_supported) (sa_family_t, struct sctp_opt *); + int (*cmp_addr) (const union sctp_addr *, + const union sctp_addr *, + struct sctp_opt *); + int (*bind_verify) (struct sctp_opt *, union sctp_addr *); + int (*send_verify) (struct sctp_opt *, union sctp_addr *); + int (*supported_addrs)(const struct sctp_opt *, __u16 *); + struct sock *(*create_accept_sk) (struct sock *sk, + struct sctp_association *asoc); + void (*addr_v4map) (struct sctp_opt *, union sctp_addr *); + struct sctp_af *af; +}; + + /* Structure to track chunk fragments that have been acked, but peer * fragments of the same message have not. */ @@ -1688,6 +1695,8 @@ struct sctp_transport *sctp_assoc_choose_shutdown_transport( void sctp_assoc_update_retran_path(struct sctp_association *); struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *, const union sctp_addr *); +int sctp_assoc_lookup_laddr(struct sctp_association *asoc, + const union sctp_addr *laddr); struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, const union sctp_addr *address, const int gfp); diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index da96859dba92..45f96479510f 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -551,13 +551,15 @@ struct sctp_status { }; /* - * 8.3, 8.5 get all peer/local addresses on a socket - * This parameter struct is for getsockopt + * 8.3, 8.5 get all peer/local addresses in an association. + * This parameter struct is used by SCTP_GET_PEER_ADDRS and + * SCTP_GET_LOCAL_ADDRS socket options used internally to implement + * sctp_getpaddrs() and sctp_getladdrs() API. */ struct sctp_getaddrs { sctp_assoc_t assoc_id; int addr_num; - struct sockaddr_storage *addrs; + struct sockaddr *addrs; }; /* These are bit fields for msghdr->msg_flags. See section 5.1. */ diff --git a/kernel/Makefile b/kernel/Makefile index 9bf11ae7195b..638a2f6c341c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += ksyms.o module.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PM) += power/ -obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_IKCONFIG) += configs.o diff --git a/kernel/futex.c b/kernel/futex.c index 4557addfc6d6..a4feceee661a 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -5,6 +5,9 @@ * Generalized futexes, futex requeueing, misc fixes by Ingo Molnar * (C) Copyright 2003 Red Hat Inc, All Rights Reserved * + * Removed page pinning, fix privately mapped COW pages and other cleanups + * (C) Copyright 2003 Jamie Lokier + * * Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly * enough at me, Linus for the original (flawed) idea, Matthew * Kirkwood for proof-of-concept implementation. @@ -33,12 +36,32 @@ #include <linux/hash.h> #include <linux/init.h> #include <linux/futex.h> -#include <linux/vcache.h> #include <linux/mount.h> +#include <linux/pagemap.h> #define FUTEX_HASHBITS 8 /* + * Futexes are matched on equal values of this key. + * The key type depends on whether it's a shared or private mapping. + */ +union futex_key { + struct { + unsigned long pgoff; + struct inode *inode; + } shared; + struct { + unsigned long uaddr; + struct mm_struct *mm; + } private; + struct { + unsigned long word; + void *ptr; + } both; + int offset; +}; + +/* * We use this hashed waitqueue instead of a normal wait_queue_t, so * we can wake only the relevant ones (hashed queues may be shared): */ @@ -46,12 +69,8 @@ struct futex_q { struct list_head list; wait_queue_head_t waiters; - /* Page struct and offset within it. */ - struct page *page; - int offset; - - /* the virtual => physical COW-safe cache */ - vcache_t vcache; + /* Key which the futex is hashed on. */ + union futex_key key; /* For fd, sigio sent using these. */ int fd; @@ -66,111 +85,149 @@ static spinlock_t futex_lock = SPIN_LOCK_UNLOCKED; static struct vfsmount *futex_mnt; /* - * These are all locks that are necessery to look up a physical - * mapping safely, and modify/search the futex hash, atomically: + * We hash on the keys returned from get_futex_key (see below). */ -static inline void lock_futex_mm(void) +static inline struct list_head *hash_futex(union futex_key *key) { - spin_lock(¤t->mm->page_table_lock); - spin_lock(&vcache_lock); - spin_lock(&futex_lock); -} - -static inline void unlock_futex_mm(void) -{ - spin_unlock(&futex_lock); - spin_unlock(&vcache_lock); - spin_unlock(¤t->mm->page_table_lock); + return &futex_queues[hash_long(key->both.word + + (unsigned long) key->both.ptr + + key->offset, FUTEX_HASHBITS)]; } /* - * The physical page is shared, so we can hash on its address: + * Return 1 if two futex_keys are equal, 0 otherwise. */ -static inline struct list_head *hash_futex(struct page *page, int offset) +static inline int match_futex(union futex_key *key1, union futex_key *key2) { - return &futex_queues[hash_long((unsigned long)page + offset, - FUTEX_HASHBITS)]; + return (key1->both.word == key2->both.word + && key1->both.ptr == key2->both.ptr + && key1->offset == key2->offset); } /* - * Get kernel address of the user page and pin it. + * Get parameters which are the keys for a futex. + * + * For shared mappings, it's (page->index, vma->vm_file->f_dentry->d_inode, + * offset_within_page). For private mappings, it's (uaddr, current->mm). + * We can usually work out the index without swapping in the page. * - * Must be called with (and returns with) all futex-MM locks held. + * Returns: 0, or negative error code. + * The key words are stored in *key on success. + * + * Should be called with ¤t->mm->mmap_sem, + * but NOT &futex_lock or ¤t->mm->page_table_lock. */ -static inline struct page *__pin_page_atomic (struct page *page) -{ - if (!PageReserved(page)) - get_page(page); - return page; -} - -static struct page *__pin_page(unsigned long addr) +static int get_futex_key(unsigned long uaddr, union futex_key *key) { struct mm_struct *mm = current->mm; - struct page *page, *tmp; + struct vm_area_struct *vma; + struct page *page; int err; /* - * Do a quick atomic lookup first - this is the fastpath. + * The futex address must be "naturally" aligned. + */ + key->offset = uaddr % PAGE_SIZE; + if (unlikely((key->offset % sizeof(u32)) != 0)) + return -EINVAL; + uaddr -= key->offset; + + /* + * The futex is hashed differently depending on whether + * it's in a shared or private mapping. So check vma first. + */ + vma = find_extend_vma(mm, uaddr); + if (unlikely(!vma)) + return -EFAULT; + + /* + * Permissions. */ - page = follow_page(mm, addr, 0); - if (likely(page != NULL)) - return __pin_page_atomic(page); + if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ)) + return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES; /* - * No luck - need to fault in the page: + * Private mappings are handled in a simple way. + * + * NOTE: When userspace waits on a MAP_SHARED mapping, even if + * it's a read-only handle, it's expected that futexes attach to + * the object not the particular process. Therefore we use + * VM_MAYSHARE here, not VM_SHARED which is restricted to shared + * mappings of _writable_ handles. */ -repeat_lookup: + if (likely(!(vma->vm_flags & VM_MAYSHARE))) { + key->private.mm = mm; + key->private.uaddr = uaddr; + return 0; + } - unlock_futex_mm(); + /* + * Linear mappings are also simple. + */ + key->shared.inode = vma->vm_file->f_dentry->d_inode; + if (likely(!(vma->vm_flags & VM_NONLINEAR))) { + key->shared.pgoff = (((uaddr - vma->vm_start) >> PAGE_SHIFT) + + vma->vm_pgoff); + return 0; + } - down_read(&mm->mmap_sem); - err = get_user_pages(current, mm, addr, 1, 0, 0, &page, NULL); - up_read(&mm->mmap_sem); + /* + * We could walk the page table to read the non-linear + * pte, and get the page index without fetching the page + * from swap. But that's a lot of code to duplicate here + * for a rare case, so we simply fetch the page. + */ - lock_futex_mm(); + /* + * Do a quick atomic lookup first - this is the fastpath. + */ + spin_lock(¤t->mm->page_table_lock); + page = follow_page(mm, uaddr, 0); + if (likely(page != NULL)) { + key->shared.pgoff = + page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); + spin_unlock(¤t->mm->page_table_lock); + return 0; + } + spin_unlock(¤t->mm->page_table_lock); - if (err < 0) - return NULL; /* - * Since the faulting happened with locks released, we have to - * check for races: + * Do it the general way. */ - tmp = follow_page(mm, addr, 0); - if (tmp != page) { + err = get_user_pages(current, mm, uaddr, 1, 0, 0, &page, NULL); + if (err >= 0) { + key->shared.pgoff = + page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); put_page(page); - goto repeat_lookup; } - - return page; + return err; } + /* * Wake up all waiters hashed on the physical page that is mapped * to this virtual address: */ -static inline int futex_wake(unsigned long uaddr, int offset, int num) +static inline int futex_wake(unsigned long uaddr, int num) { struct list_head *i, *next, *head; - struct page *page; - int ret = 0; + union futex_key key; + int ret; - lock_futex_mm(); + down_read(¤t->mm->mmap_sem); - page = __pin_page(uaddr - offset); - if (!page) { - unlock_futex_mm(); - return -EFAULT; - } + ret = get_futex_key(uaddr, &key); + if (unlikely(ret != 0)) + goto out; - head = hash_futex(page, offset); + head = hash_futex(&key); + spin_lock(&futex_lock); list_for_each_safe(i, next, head) { struct futex_q *this = list_entry(i, struct futex_q, list); - if (this->page == page && this->offset == offset) { + if (match_futex (&this->key, &key)) { list_del_init(i); - __detach_vcache(&this->vcache); wake_up_all(&this->waiters); if (this->filp) send_sigio(&this->filp->f_owner, this->fd, POLL_IN); @@ -179,113 +236,74 @@ static inline int futex_wake(unsigned long uaddr, int offset, int num) break; } } + spin_unlock(&futex_lock); - unlock_futex_mm(); - put_page(page); - +out: + up_read(¤t->mm->mmap_sem); return ret; } /* - * This gets called by the COW code, we have to rehash any - * futexes that were pending on the old physical page, and - * rehash it to the new physical page. The pagetable_lock - * and vcache_lock is already held: - */ -static void futex_vcache_callback(vcache_t *vcache, struct page *new_page) -{ - struct futex_q *q = container_of(vcache, struct futex_q, vcache); - struct list_head *head = hash_futex(new_page, q->offset); - - spin_lock(&futex_lock); - - if (!list_empty(&q->list)) { - put_page(q->page); - q->page = new_page; - __pin_page_atomic(new_page); - list_del(&q->list); - list_add_tail(&q->list, head); - } - - spin_unlock(&futex_lock); -} - -/* * Requeue all waiters hashed on one physical page to another * physical page. */ -static inline int futex_requeue(unsigned long uaddr1, int offset1, - unsigned long uaddr2, int offset2, int nr_wake, int nr_requeue) +static inline int futex_requeue(unsigned long uaddr1, unsigned long uaddr2, + int nr_wake, int nr_requeue) { struct list_head *i, *next, *head1, *head2; - struct page *page1 = NULL, *page2 = NULL; - int ret = 0; + union futex_key key1, key2; + int ret; - lock_futex_mm(); + down_read(¤t->mm->mmap_sem); - page1 = __pin_page(uaddr1 - offset1); - if (!page1) + ret = get_futex_key(uaddr1, &key1); + if (unlikely(ret != 0)) goto out; - page2 = __pin_page(uaddr2 - offset2); - if (!page2) + ret = get_futex_key(uaddr2, &key2); + if (unlikely(ret != 0)) goto out; - head1 = hash_futex(page1, offset1); - head2 = hash_futex(page2, offset2); + head1 = hash_futex(&key1); + head2 = hash_futex(&key2); + spin_lock(&futex_lock); list_for_each_safe(i, next, head1) { struct futex_q *this = list_entry(i, struct futex_q, list); - if (this->page == page1 && this->offset == offset1) { + if (match_futex (&this->key, &key1)) { list_del_init(i); - __detach_vcache(&this->vcache); if (++ret <= nr_wake) { wake_up_all(&this->waiters); if (this->filp) send_sigio(&this->filp->f_owner, this->fd, POLL_IN); } else { - put_page(this->page); - __pin_page_atomic (page2); list_add_tail(i, head2); - __attach_vcache(&this->vcache, uaddr2, - current->mm, futex_vcache_callback); - this->offset = offset2; - this->page = page2; + this->key = key2; if (ret - nr_wake >= nr_requeue) break; } } } + spin_unlock(&futex_lock); out: - unlock_futex_mm(); - - if (page1) - put_page(page1); - if (page2) - put_page(page2); - + up_read(¤t->mm->mmap_sem); return ret; } -static inline void __queue_me(struct futex_q *q, struct page *page, - unsigned long uaddr, int offset, - int fd, struct file *filp) +static inline void queue_me(struct futex_q *q, union futex_key *key, + int fd, struct file *filp) { - struct list_head *head = hash_futex(page, offset); + struct list_head *head = hash_futex(key); - q->offset = offset; + q->key = *key; q->fd = fd; q->filp = filp; - q->page = page; + spin_lock(&futex_lock); list_add_tail(&q->list, head); - /* - * We register a futex callback to this virtual address, - * to make sure a COW properly rehashes the futex-queue. - */ - __attach_vcache(&q->vcache, uaddr, current->mm, futex_vcache_callback); + spin_unlock(&futex_lock); } /* Return 1 if we were still queued (ie. 0 means we were woken) */ @@ -293,83 +311,107 @@ static inline int unqueue_me(struct futex_q *q) { int ret = 0; - spin_lock(&vcache_lock); spin_lock(&futex_lock); if (!list_empty(&q->list)) { list_del(&q->list); - __detach_vcache(&q->vcache); ret = 1; } spin_unlock(&futex_lock); - spin_unlock(&vcache_lock); return ret; } -static inline int futex_wait(unsigned long uaddr, - int offset, - int val, - unsigned long time) +static inline int futex_wait(unsigned long uaddr, int val, unsigned long time) { DECLARE_WAITQUEUE(wait, current); - int ret = 0, curval; - struct page *page; + int ret, curval; + union futex_key key; struct futex_q q; + try_again: init_waitqueue_head(&q.waiters); - lock_futex_mm(); + down_read(¤t->mm->mmap_sem); - page = __pin_page(uaddr - offset); - if (!page) { - unlock_futex_mm(); - return -EFAULT; - } - __queue_me(&q, page, uaddr, offset, -1, NULL); + ret = get_futex_key(uaddr, &key); + if (unlikely(ret != 0)) + goto out_release_sem; + + queue_me(&q, &key, -1, NULL); /* - * Page is pinned, but may no longer be in this address space. - * It cannot schedule, so we access it with the spinlock held. + * Access the page after the futex is queued. + * We hold the mmap semaphore, so the mapping cannot have changed + * since we looked it up. */ if (get_user(curval, (int *)uaddr) != 0) { - unlock_futex_mm(); ret = -EFAULT; - goto out; + goto out_unqueue; } if (curval != val) { - unlock_futex_mm(); ret = -EWOULDBLOCK; - goto out; + goto out_unqueue; } + + /* + * Now the futex is queued and we have checked the data, we + * don't want to hold mmap_sem while we sleep. + */ + up_read(¤t->mm->mmap_sem); + /* - * The get_user() above might fault and schedule so we - * cannot just set TASK_INTERRUPTIBLE state when queueing - * ourselves into the futex hash. This code thus has to + * There might have been scheduling since the queue_me(), as we + * cannot hold a spinlock across the get_user() in case it + * faults. So we cannot just set TASK_INTERRUPTIBLE state when + * queueing ourselves into the futex hash. This code thus has to * rely on the futex_wake() code doing a wakeup after removing * the waiter from the list. */ add_wait_queue(&q.waiters, &wait); + spin_lock(&futex_lock); set_current_state(TASK_INTERRUPTIBLE); - if (!list_empty(&q.list)) { - unlock_futex_mm(); - time = schedule_timeout(time); + + if (unlikely(list_empty(&q.list))) { + /* + * We were woken already. + */ + spin_unlock(&futex_lock); + set_current_state(TASK_RUNNING); + return 0; } + + spin_unlock(&futex_lock); + time = schedule_timeout(time); set_current_state(TASK_RUNNING); + /* * NOTE: we don't remove ourselves from the waitqueue because * we are the only user of it. */ - if (time == 0) { - ret = -ETIMEDOUT; - goto out; - } + + /* + * Were we woken or interrupted for a valid reason? + */ + ret = unqueue_me(&q); + if (ret == 0) + return 0; + if (time == 0) + return -ETIMEDOUT; if (signal_pending(current)) - ret = -EINTR; -out: - /* Were we woken up anyway? */ + return -EINTR; + + /* + * No, it was a spurious wakeup. Try again. Should never happen. :) + */ + goto try_again; + + out_unqueue: + /* + * Were we unqueued anyway? + */ if (!unqueue_me(&q)) ret = 0; - put_page(q.page); - + out_release_sem: + up_read(¤t->mm->mmap_sem); return ret; } @@ -378,7 +420,6 @@ static int futex_close(struct inode *inode, struct file *filp) struct futex_q *q = filp->private_data; unqueue_me(q); - put_page(q->page); kfree(filp->private_data); return 0; } @@ -406,12 +447,12 @@ static struct file_operations futex_fops = { /* Signal allows caller to avoid the race which would occur if they set the sigio stuff up afterwards. */ -static int futex_fd(unsigned long uaddr, int offset, int signal) +static int futex_fd(unsigned long uaddr, int signal) { - struct page *page = NULL; struct futex_q *q; + union futex_key key; struct file *filp; - int ret; + int ret, err; ret = -EINVAL; if (signal < 0 || signal > _NSIG) @@ -450,69 +491,47 @@ static int futex_fd(unsigned long uaddr, int offset, int signal) goto out; } - lock_futex_mm(); - - page = __pin_page(uaddr - offset); - if (!page) { - unlock_futex_mm(); + down_read(¤t->mm->mmap_sem); + err = get_futex_key(uaddr, &key); + up_read(¤t->mm->mmap_sem); + if (unlikely(err != 0)) { put_unused_fd(ret); put_filp(filp); kfree(q); - return -EFAULT; + return err; } init_waitqueue_head(&q->waiters); filp->private_data = q; - __queue_me(q, page, uaddr, offset, ret, filp); - - unlock_futex_mm(); + queue_me(q, &key, ret, filp); /* Now we map fd to filp, so userspace can access it */ fd_install(ret, filp); - page = NULL; out: - if (page) - put_page(page); return ret; } long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout, unsigned long uaddr2, int val2) { - unsigned long pos_in_page; int ret; - pos_in_page = uaddr % PAGE_SIZE; - - /* Must be "naturally" aligned */ - if (pos_in_page % sizeof(u32)) - return -EINVAL; - switch (op) { case FUTEX_WAIT: - ret = futex_wait(uaddr, pos_in_page, val, timeout); + ret = futex_wait(uaddr, val, timeout); break; case FUTEX_WAKE: - ret = futex_wake(uaddr, pos_in_page, val); + ret = futex_wake(uaddr, val); break; case FUTEX_FD: /* non-zero val means F_SETOWN(getpid()) & F_SETSIG(val) */ - ret = futex_fd(uaddr, pos_in_page, val); + ret = futex_fd(uaddr, val); break; case FUTEX_REQUEUE: - { - unsigned long pos_in_page2 = uaddr2 % PAGE_SIZE; - - /* Must be "naturally" aligned */ - if (pos_in_page2 % sizeof(u32)) - return -EINVAL; - - ret = futex_requeue(uaddr, pos_in_page, uaddr2, pos_in_page2, - val, val2); + ret = futex_requeue(uaddr, uaddr2, val, val2); break; - } default: ret = -ENOSYS; } diff --git a/kernel/ksyms.c b/kernel/ksyms.c index e503bd8b0349..9f61a0496c2a 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -511,7 +511,6 @@ EXPORT_SYMBOL(vsnprintf); EXPORT_SYMBOL(vsscanf); EXPORT_SYMBOL(__bdevname); EXPORT_SYMBOL(bdevname); -EXPORT_SYMBOL(cdevname); EXPORT_SYMBOL(simple_strtoull); EXPORT_SYMBOL(simple_strtoul); EXPORT_SYMBOL(simple_strtol); diff --git a/mm/Makefile b/mm/Makefile index a8de64ff3525..c66aba5886f8 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -9,6 +9,6 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ page_alloc.o page-writeback.o pdflush.o readahead.o \ - slab.o swap.o truncate.o vcache.o vmscan.o $(mmu-y) + slab.o swap.o truncate.o vmscan.o $(mmu-y) obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o diff --git a/mm/fremap.c b/mm/fremap.c index 8f96af82b4e8..b19bdde07bb6 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -144,9 +144,10 @@ long sys_remap_file_pages(unsigned long start, unsigned long size, return err; #endif - down_read(&mm->mmap_sem); - + /* We need down_write() to change vma->vm_flags. */ + down_write(&mm->mmap_sem); vma = find_vma(mm, start); + /* * Make sure the vma is shared, that it supports prefaulting, * and that the remapped range is valid and fully within @@ -155,11 +156,27 @@ long sys_remap_file_pages(unsigned long start, unsigned long size, if (vma && (vma->vm_flags & VM_SHARED) && vma->vm_ops && vma->vm_ops->populate && end > start && start >= vma->vm_start && - end <= vma->vm_end) - err = vma->vm_ops->populate(vma, start, size, vma->vm_page_prot, - pgoff, flags & MAP_NONBLOCK); - - up_read(&mm->mmap_sem); + end <= vma->vm_end) { + + /* Must set VM_NONLINEAR before any pages are populated. */ + if (pgoff != ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff) + vma->vm_flags |= VM_NONLINEAR; + + /* ->populate can take a long time, so downgrade the lock. */ + downgrade_write(&mm->mmap_sem); + err = vma->vm_ops->populate(vma, start, size, + vma->vm_page_prot, + pgoff, flags & MAP_NONBLOCK); + + /* + * We can't clear VM_NONLINEAR because we'd have to do + * it after ->populate completes, and that would prevent + * downgrading the lock. (Locks can't be upgraded). + */ + up_read(&mm->mmap_sem); + } else { + up_write(&mm->mmap_sem); + } return err; } diff --git a/mm/memory.c b/mm/memory.c index 61b782f40df9..980953dbbfb4 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -43,7 +43,6 @@ #include <linux/swap.h> #include <linux/highmem.h> #include <linux/pagemap.h> -#include <linux/vcache.h> #include <linux/rmap-locking.h> #include <linux/module.h> @@ -962,7 +961,6 @@ static inline void establish_pte(struct vm_area_struct * vma, unsigned long addr static inline void break_cow(struct vm_area_struct * vma, struct page * new_page, unsigned long address, pte_t *page_table) { - invalidate_vcache(address, vma->vm_mm, new_page); flush_cache_page(vma, address); establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)))); } diff --git a/mm/mmap.c b/mm/mmap.c index bcc28864eab6..61c9f5ca5f82 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -136,29 +136,6 @@ out: return retval; } -/* Combine the mmap "prot" and "flags" argument into one "vm_flags" used - * internally. Essentially, translate the "PROT_xxx" and "MAP_xxx" bits - * into "VM_xxx". - */ -static inline unsigned long -calc_vm_flags(unsigned long prot, unsigned long flags) -{ -#define _trans(x,bit1,bit2) \ -((bit1==bit2)?(x&bit1):(x&bit1)?bit2:0) - - unsigned long prot_bits, flag_bits; - prot_bits = - _trans(prot, PROT_READ, VM_READ) | - _trans(prot, PROT_WRITE, VM_WRITE) | - _trans(prot, PROT_EXEC, VM_EXEC); - flag_bits = - _trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN) | - _trans(flags, MAP_DENYWRITE, VM_DENYWRITE) | - _trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE); - return prot_bits | flag_bits; -#undef _trans -} - #ifdef DEBUG_MM_RB static int browse_rb(struct rb_node * rb_node) { int i = 0; @@ -500,8 +477,8 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, * to. we assume access permissions have been handled by the open * of the memory object, so we don't do any here. */ - vm_flags = calc_vm_flags(prot,flags) | mm->def_flags | - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; + vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) | + mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; if (flags & MAP_LOCKED) { if (!capable(CAP_IPC_LOCK)) diff --git a/mm/mprotect.c b/mm/mprotect.c index 2c015794e3c1..699962ebd1e4 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -224,7 +224,7 @@ fail: asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) { - unsigned long nstart, end, tmp; + unsigned long vm_flags, nstart, end, tmp; struct vm_area_struct * vma, * next, * prev; int error = -EINVAL; @@ -239,6 +239,8 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot) if (end == start) return 0; + vm_flags = calc_vm_prot_bits(prot); + down_write(¤t->mm->mmap_sem); vma = find_vma_prev(current->mm, start, &prev); @@ -257,7 +259,8 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot) goto out; } - newflags = prot | (vma->vm_flags & ~(PROT_READ | PROT_WRITE | PROT_EXEC)); + newflags = vm_flags | (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC)); + if ((newflags & ~(newflags >> 4)) & 0xf) { error = -EACCES; goto out; diff --git a/mm/shmem.c b/mm/shmem.c index a106bfec7709..bb429eee7ebd 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1040,7 +1040,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) inode->i_gid = current->fsgid; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; - inode->i_rdev = NODEV; inode->i_mapping->a_ops = &shmem_aops; inode->i_mapping->backing_dev_info = &shmem_backing_dev_info; inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; diff --git a/mm/vcache.c b/mm/vcache.c deleted file mode 100644 index 599e0f25490d..000000000000 --- a/mm/vcache.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * linux/mm/vcache.c - * - * virtual => physical page mapping cache. Users of this mechanism - * register callbacks for a given (virt,mm,phys) page mapping, and - * the kernel guarantees to call back when this mapping is invalidated. - * (ie. upon COW or unmap.) - * - * Started by Ingo Molnar, Copyright (C) 2002 - */ - -#include <linux/mm.h> -#include <linux/init.h> -#include <linux/hash.h> -#include <linux/vcache.h> - -#define VCACHE_HASHBITS 8 -#define VCACHE_HASHSIZE (1 << VCACHE_HASHBITS) - -spinlock_t vcache_lock = SPIN_LOCK_UNLOCKED; - -static struct list_head hash[VCACHE_HASHSIZE]; - -static struct list_head *hash_vcache(unsigned long address, - struct mm_struct *mm) -{ - return &hash[hash_long(address + (unsigned long)mm, VCACHE_HASHBITS)]; -} - -void __attach_vcache(vcache_t *vcache, - unsigned long address, - struct mm_struct *mm, - void (*callback)(struct vcache_s *data, struct page *new)) -{ - struct list_head *hash_head; - - address &= PAGE_MASK; - vcache->address = address; - vcache->mm = mm; - vcache->callback = callback; - - hash_head = hash_vcache(address, mm); - - list_add_tail(&vcache->hash_entry, hash_head); -} - -void __detach_vcache(vcache_t *vcache) -{ - list_del_init(&vcache->hash_entry); -} - -void invalidate_vcache(unsigned long address, struct mm_struct *mm, - struct page *new_page) -{ - struct list_head *l, *hash_head; - vcache_t *vcache; - - address &= PAGE_MASK; - - hash_head = hash_vcache(address, mm); - /* - * This is safe, because this path is called with the pagetable - * lock held. So while other mm's might add new entries in - * parallel, *this* mm is locked out, so if the list is empty - * now then we do not have to take the vcache lock to see it's - * really empty. - */ - if (likely(list_empty(hash_head))) - return; - - spin_lock(&vcache_lock); - list_for_each(l, hash_head) { - vcache = list_entry(l, vcache_t, hash_entry); - if (vcache->address != address || vcache->mm != mm) - continue; - vcache->callback(vcache, new_page); - } - spin_unlock(&vcache_lock); -} - -static int __init vcache_init(void) -{ - unsigned int i; - - for (i = 0; i < VCACHE_HASHSIZE; i++) - INIT_LIST_HEAD(hash + i); - return 0; -} -__initcall(vcache_init); - diff --git a/net/README b/net/README deleted file mode 100644 index e509ec526c25..000000000000 --- a/net/README +++ /dev/null @@ -1,26 +0,0 @@ - -Maintainers and developers for networking code sections - -Code Section Bug Report Contact --------------------+------------------------------------------- -802 [other ] alan@lxorguk.ukuu.org.uk - [token ring ] p.norton@computer.org -appletalk jschlst@samba.org -ax25 g4klx@g4klx.demon.co.uk -bridge buytenh@gnu.org -core alan@lxorguk.ukuu.org.uk -decnet SteveW@ACM.org -ethernet alan@lxorguk.ukuu.org.uk -ipv4 davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se -ipv6 davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se -ipx acme@conectiva.com.br -spx jschlst@samba.org -irda dagb@cs.uit.no -lapb g4klx@g4klx.demon.co.uk -netrom g4klx@g4klx.demon.co.uk -rose g4klx@g4klx.demon.co.uk -wanrouter gene@compuserve.com, jaspreet@sangoma and dm@sangoma.com -unix alan@lxorguk.ukuu.org.uk -x25 g4klx@g4klx.demon.co.uk -bluetooth maxk@qualcomm.com -8021q greearb@candelatech.com, vlan@scry.wanfear.com diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 4d5469bd8140..217244bd611d 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1888,8 +1888,6 @@ EXPORT_SYMBOL(aarp_send_ddp); EXPORT_SYMBOL(atrtr_get_dev); EXPORT_SYMBOL(atalk_find_dev_addr); -static char atalk_banner[] __initdata = - KERN_INFO "NET4: AppleTalk 0.20 for Linux NET4.0\n"; static char atalk_err_snap[] __initdata = KERN_CRIT "Unable to register DDP with SNAP.\n"; @@ -1908,7 +1906,6 @@ static int __init atalk_init(void) aarp_proto_init(); atalk_proc_init(); atalk_register_sysctl(); - printk(atalk_banner); return 0; } module_init(atalk_init); @@ -1939,5 +1936,5 @@ module_exit(atalk_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alan Cox <Alan.Cox@linux.org>"); -MODULE_DESCRIPTION("AppleTalk 0.20 for Linux NET4.0\n"); +MODULE_DESCRIPTION("AppleTalk 0.20\n"); MODULE_ALIAS_NETPROTO(PF_APPLETALK); diff --git a/net/atm/br2684.c b/net/atm/br2684.c index fa25cbdd9a80..0f9d98463a69 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -18,6 +18,7 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary #include <net/arp.h> #include <linux/atm.h> #include <linux/atmdev.h> +#include <linux/seq_file.h> #include <linux/atmbr2684.h> @@ -666,31 +667,57 @@ static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, return -ENOIOCTLCMD; } -/* Never put more than 256 bytes in at once */ -static int br2684_proc_engine(loff_t pos, char *buf) +#ifdef CONFIG_PROC_FS +static void *br2684_seq_start(struct seq_file *seq, loff_t *pos) { - struct list_head *lhd, *lhc; - struct net_device *net_dev; - struct br2684_dev *brdev; - struct br2684_vcc *brvcc; - list_for_each(lhd, &br2684_devs) { - net_dev = list_entry_brdev(lhd); - brdev = BRPRIV(net_dev); - if (pos-- == 0) - return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:" - "%02X:%02X:%02X:%02X (%s)\n", net_dev->name, - brdev->number, - net_dev->dev_addr[0], - net_dev->dev_addr[1], - net_dev->dev_addr[2], - net_dev->dev_addr[3], - net_dev->dev_addr[4], - net_dev->dev_addr[5], - brdev->mac_was_set ? "set" : "auto"); - list_for_each(lhc, &brdev->brvccs) { - brvcc = list_entry_brvcc(lhc); - if (pos-- == 0) - return sprintf(buf, " vcc %d.%d.%d: encaps=%s" + loff_t offs = 0; + struct br2684_dev *brd; + + read_lock(&devs_lock); + + list_for_each_entry(brd, &br2684_devs, br2684_devs) { + if (offs == *pos) + return brd; + ++offs; + } + return NULL; +} + +static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct br2684_dev *brd = v; + + ++*pos; + + brd = list_entry(brd->br2684_devs.next, + struct br2684_dev, br2684_devs); + return (&brd->br2684_devs != &br2684_devs) ? brd : NULL; +} + +static void br2684_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock(&devs_lock); +} + +static int br2684_seq_show(struct seq_file *seq, void *v) +{ + const struct br2684_dev *brdev = v; + const struct net_device *net_dev = brdev->net_dev; + const struct br2684_vcc *brvcc; + + seq_printf(seq, "dev %.16s: num=%d, mac=%02X:%02X:" + "%02X:%02X:%02X:%02X (%s)\n", net_dev->name, + brdev->number, + net_dev->dev_addr[0], + net_dev->dev_addr[1], + net_dev->dev_addr[2], + net_dev->dev_addr[3], + net_dev->dev_addr[4], + net_dev->dev_addr[5], + brdev->mac_was_set ? "set" : "auto"); + + list_for_each_entry(brvcc, &brdev->brvccs, brvccs) { + seq_printf(seq, " vcc %d.%d.%d: encaps=%s" #ifndef FASTER_VERSION ", failed copies %u/%u" #endif /* FASTER_VERSION */ @@ -711,63 +738,41 @@ static int br2684_proc_engine(loff_t pos, char *buf) #undef bs #undef b1 #endif /* CONFIG_ATM_BR2684_IPFILTER */ - } } return 0; } -static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count, - loff_t *pos) +static struct seq_operations br2684_seq_ops = { + .start = br2684_seq_start, + .next = br2684_seq_next, + .stop = br2684_seq_stop, + .show = br2684_seq_show, +}; + +static int br2684_proc_open(struct inode *inode, struct file *file) { - unsigned long page; - int len = 0, x, left; - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - left = PAGE_SIZE - 256; - if (count < left) - left = count; - read_lock(&devs_lock); - for (;;) { - x = br2684_proc_engine(*pos, &((char *) page)[len]); - if (x == 0) - break; - if (x > left) - /* - * This should only happen if the user passed in - * a "count" too small for even one line - */ - x = -EINVAL; - if (x < 0) { - len = x; - break; - } - len += x; - left -= x; - (*pos)++; - if (left < 256) - break; - } - read_unlock(&devs_lock); - if (len > 0 && copy_to_user(buf, (char *) page, len)) - len = -EFAULT; - free_page(page); - return len; + return seq_open(file, &br2684_seq_ops); } -static struct file_operations br2684_proc_operations = { - .owner = THIS_MODULE, - .read = br2684_proc_read, +static struct file_operations br2684_proc_ops = { + .owner = THIS_MODULE, + .open = br2684_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, }; extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ +#endif static int __init br2684_init(void) { +#ifdef CONFIG_PROC_FS struct proc_dir_entry *p; if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL) return -ENOMEM; - p->proc_fops = &br2684_proc_operations; + p->proc_fops = &br2684_proc_ops; +#endif br2684_ioctl_set(br2684_ioctl); return 0; } @@ -779,7 +784,9 @@ static void __exit br2684_exit(void) struct br2684_vcc *brvcc; br2684_ioctl_set(NULL); +#ifdef CONFIG_PROC_FS remove_proc_entry("br2684", atm_proc_root); +#endif while (!list_empty(&br2684_devs)) { net_dev = list_entry_brdev(br2684_devs.next); diff --git a/net/atm/common.c b/net/atm/common.c index 6fde6b018418..62c8f0a72179 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -422,26 +422,31 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, int vpi, } if (!error) error = adjust_tp(&vcc->qos.txtp,vcc->qos.aal); if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->qos.aal); - if (error) { - vcc_remove_socket(vcc->sk); - return error; - } + if (error) + goto fail; DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->qos.aal); DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class, vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu); DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.traffic_class, vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu); - if (!try_module_get(dev->ops->owner)) - return -ENODEV; + if (!try_module_get(dev->ops->owner)) { + error = -ENODEV; + goto fail; + } + if (dev->ops->open) { - error = dev->ops->open(vcc,vpi,vci); - if (error) { - module_put(dev->ops->owner); - vcc_remove_socket(vcc->sk); - return error; - } + if ((error = dev->ops->open(vcc,vpi,vci))) + goto put_module_fail; } return 0; + +put_module_fail: + module_put(dev->ops->owner); +fail: + vcc_remove_socket(vcc->sk); + /* ensure we get dev module ref count correct */ + vcc->dev = NULL; + return error; } @@ -1109,12 +1114,10 @@ static int __init atm_init(void) printk(KERN_ERR "atmsvc_init() failed with %d\n", error); goto failure; } -#ifdef CONFIG_PROC_FS if ((error = atm_proc_init()) < 0) { printk(KERN_ERR "atm_proc_init() failed with %d\n",error); goto failure; } -#endif return 0; failure: @@ -1125,9 +1128,7 @@ failure: static void __exit atm_exit(void) { -#ifdef CONFIG_PROC_FS atm_proc_exit(); -#endif atmsvc_exit(); atmpvc_exit(); } diff --git a/net/atm/common.h b/net/atm/common.h index eb98c9357431..426f1fa8bbb1 100644 --- a/net/atm/common.h +++ b/net/atm/common.h @@ -33,8 +33,21 @@ int atmpvc_init(void); void atmpvc_exit(void); int atmsvc_init(void); void atmsvc_exit(void); + +#ifdef CONFIG_PROC_FS int atm_proc_init(void); void atm_proc_exit(void); +#else +static inline int atm_proc_init(void) +{ + return 0; +} + +static inline void atm_proc_exit(void) +{ + /* nothing */ +} +#endif /* CONFIG_PROC_FS */ /* SVC */ diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index cca22da87ae6..4a8f73b41edf 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c @@ -341,16 +341,13 @@ static int pppoatm_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, return -ENOIOCTLCMD; } -/* the following avoids some spurious warnings from the compiler */ -#define UNUSED __attribute__((unused)) - -static int __init UNUSED pppoatm_init(void) +static int __init pppoatm_init(void) { pppoatm_ioctl_set(pppoatm_ioctl); return 0; } -static void __exit UNUSED pppoatm_exit(void) +static void __exit pppoatm_exit(void) { pppoatm_ioctl_set(NULL); } diff --git a/net/atm/proc.c b/net/atm/proc.c index 05c41491b431..d493ab2cd420 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -593,6 +593,10 @@ int atm_proc_dev_register(struct atm_dev *dev) int digits,num; int error; + /* No proc info */ + if (!dev->ops->proc_read) + return 0; + error = -ENOMEM; digits = 0; for (num = dev->number; num; num /= 10) digits++; @@ -619,6 +623,9 @@ fail1: void atm_proc_dev_deregister(struct atm_dev *dev) { + if (!dev->ops->proc_read) + return; + remove_proc_entry(dev->proc_name, atm_proc_root); kfree(dev->proc_name); } diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 9dee7f22c801..c0ce4d4d20b6 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -104,6 +104,7 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr, static struct proto_ops pvc_proto_ops = { .family = PF_ATMPVC, + .owner = THIS_MODULE, .release = vcc_release, .bind = pvc_bind, @@ -134,6 +135,7 @@ static int pvc_create(struct socket *sock,int protocol) static struct net_proto_family pvc_family_ops = { .family = PF_ATMPVC, .create = pvc_create, + .owner = THIS_MODULE, }; diff --git a/net/atm/resources.c b/net/atm/resources.c index ae3009c6eb4f..bd32c0caabe4 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -110,20 +110,16 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, list_add_tail(&dev->dev_list, &atm_devs); spin_unlock(&atm_dev_lock); -#ifdef CONFIG_PROC_FS - if (ops->proc_read) { - if (atm_proc_dev_register(dev) < 0) { - printk(KERN_ERR "atm_dev_register: " - "atm_proc_dev_register failed for dev %s\n", - type); - spin_lock(&atm_dev_lock); - list_del(&dev->dev_list); - spin_unlock(&atm_dev_lock); - __free_atm_dev(dev); - return NULL; - } + if (atm_proc_dev_register(dev) < 0) { + printk(KERN_ERR "atm_dev_register: " + "atm_proc_dev_register failed for dev %s\n", + type); + spin_lock(&atm_dev_lock); + list_del(&dev->dev_list); + spin_unlock(&atm_dev_lock); + __free_atm_dev(dev); + return NULL; } -#endif return dev; } @@ -133,10 +129,8 @@ void atm_dev_deregister(struct atm_dev *dev) { unsigned long warning_time; -#ifdef CONFIG_PROC_FS - if (dev->ops->proc_read) - atm_proc_dev_deregister(dev); -#endif + atm_proc_dev_deregister(dev); + spin_lock(&atm_dev_lock); list_del(&dev->dev_list); spin_unlock(&atm_dev_lock); diff --git a/net/atm/resources.h b/net/atm/resources.h index c4ecc1be6a26..1b6bad8db9cc 100644 --- a/net/atm/resources.h +++ b/net/atm/resources.h @@ -24,6 +24,18 @@ int atm_dev_ioctl(unsigned int cmd, unsigned long arg); int atm_proc_dev_register(struct atm_dev *dev); void atm_proc_dev_deregister(struct atm_dev *dev); -#endif +#else + +static inline int atm_proc_dev_register(struct atm_dev *dev) +{ + return 0; +} + +static inline void atm_proc_dev_deregister(struct atm_dev *dev) +{ + /* nothing */ +} + +#endif /* CONFIG_PROC_FS */ #endif diff --git a/net/atm/svc.c b/net/atm/svc.c index 07c0849b37c7..aa46d6ae96d5 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -513,6 +513,7 @@ out: static struct proto_ops svc_proto_ops = { .family = PF_ATMSVC, + .owner = THIS_MODULE, .release = svc_release, .bind = svc_bind, @@ -549,6 +550,7 @@ static int svc_create(struct socket *sock,int protocol) static struct net_proto_family svc_family_ops = { .family = PF_ATMSVC, .create = svc_create, + .owner = THIS_MODULE, }; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 4bb3798a2638..43662ed9a619 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -2003,8 +2003,6 @@ EXPORT_SYMBOL(asc2ax); EXPORT_SYMBOL(null_ax25_address); EXPORT_SYMBOL(ax25_display_timer); -static char banner[] __initdata = KERN_INFO "NET4: G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET4.0\n"; - static int __init ax25_init(void) { sock_register(&ax25_family_ops); @@ -2016,7 +2014,6 @@ static int __init ax25_init(void) proc_net_fops_create("ax25", S_IRUGO, &ax25_info_fops); proc_net_fops_create("ax25_calls", S_IRUGO, &ax25_uid_fops); - printk(banner); return 0; } module_init(ax25_init); diff --git a/net/bridge/br.c b/net/bridge/br.c index bf41aa2c61dd..3d90a9017bfc 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -32,8 +32,6 @@ int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; static int __init br_init(void) { - printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n"); - #if defined(CONFIG_INET) && defined(CONFIG_NETFILTER) if (br_netfilter_init()) return 1; diff --git a/net/core/dv.c b/net/core/dv.c index 62352d7c9bcc..e7de41f94f9c 100644 --- a/net/core/dv.c +++ b/net/core/dv.c @@ -40,7 +40,6 @@ const char sysctl_divert_version[32]="0.46"; /* Current version */ static int __init dv_init(void) { - printk(KERN_INFO "NET4: Frame Diverter %s\n", sysctl_divert_version); return 0; } module_init(dv_init); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4215e4a7dcd0..444f07e51e27 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -559,9 +559,6 @@ struct notifier_block rtnetlink_dev_notifier = { void __init rtnetlink_init(void) { -#ifdef RTNL_DEBUG - printk("Initializing RT netlink socket\n"); -#endif rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv); if (rtnl == NULL) panic("rtnetlink_init: cannot initialize rtnetlink\n"); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8a5dbadd51f3..3879dca72b92 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1097,8 +1097,6 @@ static int __init inet_init(void) struct inet_protosw *q; struct list_head *r; - printk(KERN_INFO "NET4: Linux TCP/IP 1.0 for NET4.0\n"); - if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "%s: panic\n", __FUNCTION__); return -EINVAL; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 3f671efed9e6..9f5a0485e0a7 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1744,7 +1744,6 @@ static struct inet_protocol pim_protocol = { void __init ip_mr_init(void) { - printk(KERN_INFO "Linux IP multicast router 0.06 plus PIM-SM\n"); mrt_cachep = kmem_cache_create("ip_mrt_cache", sizeof(struct mfc_cache), 0, SLAB_HWCACHE_ALIGN, diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index e55d83a6f14d..df60b4030a44 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -723,8 +723,6 @@ static int __init inet6_init(void) #endif #endif - printk(KERN_INFO "IPv6 v0.8 for NET4.0\n"); - if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "inet6_proto_init: size fault\n"); diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 083155a233a6..8c9091ede27d 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1940,10 +1940,6 @@ extern void destroy_8023_client(struct datalink_proto *); static unsigned char ipx_8022_type = 0xE0; static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; -static char ipx_banner[] __initdata = - KERN_INFO "NET4: Linux IPX 0.51 for NET4.0\n" - KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n" \ - KERN_INFO "IPX Portions Copyright (c) 2000-2003 Conectiva, Inc.\n"; static char ipx_EII_err_msg[] __initdata = KERN_CRIT "IPX: Unable to register with Ethernet II\n"; static char ipx_8023_err_msg[] __initdata = @@ -1980,7 +1976,6 @@ static int __init ipx_init(void) register_netdevice_notifier(&ipx_dev_notifier); ipx_register_sysctl(); ipx_proc_init(); - printk(ipx_banner); return 0; } diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index fbb552adc243..fc71309e7e9b 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c @@ -435,11 +435,8 @@ EXPORT_SYMBOL(lapb_disconnect_request); EXPORT_SYMBOL(lapb_data_request); EXPORT_SYMBOL(lapb_data_received); -static char banner[] __initdata = KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0\n"; - static int __init lapb_init(void) { - printk(banner); return 0; } diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 5b011b872d94..ff2710542e4b 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -1042,15 +1042,10 @@ static struct proto_ops llc_ui_ops = { .sendpage = sock_no_sendpage, }; -static char llc_ui_banner[] __initdata = - KERN_INFO "NET4.0 IEEE 802.2 BSD sockets, Jay Schulist, 2001, " - "Arnaldo C. Melo, 2002-2003\n"; - int __init llc_ui_init(void) { llc_ui_sap_last_autoport = LLC_SAP_DYN_START; sock_register(&llc_ui_family_ops); - printk(llc_ui_banner); return 0; } diff --git a/net/llc/llc_main.c b/net/llc/llc_main.c index 3ee7b0aa16ae..8f2fc4d7ec71 100644 --- a/net/llc/llc_main.c +++ b/net/llc/llc_main.c @@ -603,5 +603,5 @@ module_exit(llc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001-2003"); -MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support"); +MODULE_DESCRIPTION("LLC 2.0, IEEE 802.2 extended support"); MODULE_ALIAS_NETPROTO(PF_LLC); diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 849b7a589ac0..c1323ddd5576 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 La Monte H.P. Yarroll * @@ -42,6 +42,7 @@ * Sridhar Samudrala <sri@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com> * Ryan Layer <rmlayer@us.ibm.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -1155,3 +1156,23 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc, return sctp_raw_to_bind_addrs(&asoc->base.bind_addr, raw, var_size3, asoc->ep->base.bind_addr.port, gfp); } + +/* Lookup laddr in the bind address list of an association. */ +int sctp_assoc_lookup_laddr(struct sctp_association *asoc, + const union sctp_addr *laddr) +{ + int found; + + sctp_read_lock(&asoc->base.addr_lock); + if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) && + sctp_bind_addr_match(&asoc->base.bind_addr, laddr, + sctp_sk(asoc->base.sk))) { + found = 1; + goto out; + } + + found = 0; +out: + sctp_read_unlock(&asoc->base.addr_lock); + return found; +} diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 58d6a3bb7c3e..c2a288bcca39 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 * Copyright (c) Cisco 1999,2000 * Copyright (c) Motorola 1999,2000,2001 - * Copyright (c) International Business Machines Corp., 2001,2002 * Copyright (c) La Monte H.P. Yarroll 2001 * * This file is part of the SCTP kernel reference implementation. @@ -223,6 +223,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, int len; struct sctp_sockaddr_entry *addr; struct list_head *pos; + struct sctp_af *af; + addrparms_len = 0; len = 0; @@ -247,7 +249,8 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, list_for_each(pos, &bp->address_list) { addr = list_entry(pos, struct sctp_sockaddr_entry, list); - len = sockaddr2sctp_addr(&addr->a, &rawaddr); + af = sctp_get_af_specific(addr->a.v4.sin_family); + len = af->to_addr_param(&addr->a, &rawaddr); memcpy(addrparms.v, &rawaddr, len); addrparms.v += len; addrparms_len += len; @@ -270,34 +273,31 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, union sctp_addr addr; int retval = 0; int len; + struct sctp_af *af; /* Convert the raw address to standard address format */ while (addrs_len) { param = (struct sctp_paramhdr *)raw_addr_list; rawaddr = (union sctp_addr_param *)raw_addr_list; - switch (param->type) { - case SCTP_PARAM_IPV4_ADDRESS: - case SCTP_PARAM_IPV6_ADDRESS: - sctp_param2sockaddr(&addr, rawaddr, port, 0); - retval = sctp_add_bind_addr(bp, &addr, gfp); - if (retval) { - /* Can't finish building the list, clean up. */ - sctp_bind_addr_clean(bp); - break;; - } - len = ntohs(param->length); - addrs_len -= len; - raw_addr_list += len; - break; - default: - /* Corrupted raw addr list! */ + af = sctp_get_af_specific(param_type2af(param->type)); + if (unlikely(!af)) { retval = -EINVAL; sctp_bind_addr_clean(bp); break; } - if (retval) - break; + + af->from_addr_param(&addr, rawaddr, port, 0); + retval = sctp_add_bind_addr(bp, &addr, gfp); + if (retval) { + /* Can't finish building the list, clean up. */ + sctp_bind_addr_clean(bp); + break;; + } + + len = ntohs(param->length); + addrs_len -= len; + raw_addr_list += len; } return retval; diff --git a/net/sctp/input.c b/net/sctp/input.c index 2c62c2171f6a..cc3e9314dd91 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -768,6 +768,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, union sctp_params params; sctp_init_chunk_t *init; struct sctp_transport *transport; + struct sctp_af *af; ch = (sctp_chunkhdr_t *) skb->data; @@ -802,11 +803,12 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, sctp_walk_params(params, init, init_hdr.params) { /* Note: Ignoring hostname addresses. */ - if ((SCTP_PARAM_IPV4_ADDRESS != params.p->type) && - (SCTP_PARAM_IPV6_ADDRESS != params.p->type)) + af = sctp_get_af_specific(param_type2af(params.p->type)); + if (!af) continue; - sctp_param2sockaddr(paddr, params.addr, ntohs(sh->source), 0); + af->from_addr_param(paddr, params.addr, ntohs(sh->source), 0); + asoc = __sctp_lookup_association(laddr, paddr, &transport); if (asoc) return asoc; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 3bce456b895f..32ec1d5176ff 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -399,6 +399,33 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) } } +/* Initialize a sctp_addr from an address parameter. */ +static void sctp_v6_from_addr_param(union sctp_addr *addr, + union sctp_addr_param *param, + __u16 port, int iif) +{ + addr->v6.sin6_family = AF_INET6; + addr->v6.sin6_port = port; + addr->v6.sin6_flowinfo = 0; /* BUG */ + ipv6_addr_copy(&addr->v6.sin6_addr, ¶m->v6.addr); + addr->v6.sin6_scope_id = iif; +} + +/* Initialize an address parameter from a sctp_addr and return the length + * of the address parameter. + */ +static int sctp_v6_to_addr_param(const union sctp_addr *addr, + union sctp_addr_param *param) +{ + int length = sizeof(sctp_ipv6addr_param_t); + + param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; + param->v6.param_hdr.length = ntohs(length); + ipv6_addr_copy(¶m->v6.addr, &addr->v6.sin6_addr); + + return length; +} + /* Initialize a sctp_addr from a dst_entry. */ static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, unsigned short port) @@ -903,6 +930,8 @@ static struct sctp_af sctp_ipv6_specific = { .from_sk = sctp_v6_from_sk, .to_sk_saddr = sctp_v6_to_sk_saddr, .to_sk_daddr = sctp_v6_to_sk_daddr, + .from_addr_param = sctp_v6_from_addr_param, + .to_addr_param = sctp_v6_to_addr_param, .dst_saddr = sctp_v6_dst_saddr, .cmp_addr = sctp_v6_cmp_addr, .scope = sctp_v6_scope, diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c index 243b1d5a8657..3a7ebfcc1fdb 100644 --- a/net/sctp/primitive.c +++ b/net/sctp/primitive.c @@ -39,6 +39,7 @@ * Narasimha Budihal <narasimha@refcode.org> * Karl Knutson <karl@athena.chicago.il.us> * Ardelle Fan <ardelle.fan@intel.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -203,3 +204,16 @@ DECLARE_PRIMITIVE(SEND); */ DECLARE_PRIMITIVE(REQUESTHEARTBEAT); + +/* ADDIP +* 3.1.1 Address Configuration Change Chunk (ASCONF) +* +* This chunk is used to communicate to the remote endpoint one of the +* configuration change requests that MUST be acknowledged. The +* information carried in the ASCONF Chunk uses the form of a +* Type-Length-Value (TLV), as described in "3.2.1 Optional/ +* Variable-length Parameter Format" in RFC2960 [5], forall variable +* parameters. +*/ + +DECLARE_PRIMITIVE(ASCONF); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 727f237b1475..986460afaa6b 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -295,6 +295,31 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) inet_sk(sk)->daddr = addr->v4.sin_addr.s_addr; } +/* Initialize a sctp_addr from an address parameter. */ +static void sctp_v4_from_addr_param(union sctp_addr *addr, + union sctp_addr_param *param, + __u16 port, int iif) +{ + addr->v4.sin_family = AF_INET; + addr->v4.sin_port = port; + addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; +} + +/* Initialize an address parameter from a sctp_addr and return the length + * of the address parameter. + */ +static int sctp_v4_to_addr_param(const union sctp_addr *addr, + union sctp_addr_param *param) +{ + int length = sizeof(sctp_ipv4addr_param_t); + + param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; + param->v4.param_hdr.length = ntohs(length); + param->v4.addr.s_addr = addr->v4.sin_addr.s_addr; + + return length; +} + /* Initialize a sctp_addr from a dst_entry. */ static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst, unsigned short port) @@ -862,6 +887,8 @@ struct sctp_af sctp_ipv4_specific = { .from_sk = sctp_v4_from_sk, .to_sk_saddr = sctp_v4_to_sk_saddr, .to_sk_daddr = sctp_v4_to_sk_daddr, + .from_addr_param= sctp_v4_from_addr_param, + .to_addr_param = sctp_v4_to_addr_param, .dst_saddr = sctp_v4_dst_saddr, .cmp_addr = sctp_v4_cmp_addr, .addr_valid = sctp_v4_addr_valid, diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index bf3f373d9feb..40a7a4f7116f 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1,8 +1,8 @@ /* SCTP kernel reference Implementation + * Copyright (C) IBM Corp. 2001, 2003 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001-2002 Intel Corp. - * Copyright (c) 2001-2002 International Business Machines Corp. * * This file is part of the SCTP kernel reference Implementation * @@ -48,6 +48,7 @@ * Sridhar Samudrala <sri@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com> * Ardelle Fan <ardelle.fan@intel.com> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -1213,6 +1214,7 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, struct sctp_association *asoc; struct sk_buff *skb; sctp_scope_t scope; + struct sctp_af *af; /* Create the bare association. */ scope = sctp_scope(sctp_source(chunk)); @@ -1222,29 +1224,10 @@ struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *ep, asoc->temp = 1; skb = chunk->skb; /* Create an entry for the source address of the packet. */ - /* FIXME: Use the af specific helpers. */ - switch (skb->nh.iph->version) { - case 4: - asoc->c.peer_addr.v4.sin_family = AF_INET; - asoc->c.peer_addr.v4.sin_port = ntohs(chunk->sctp_hdr->source); - asoc->c.peer_addr.v4.sin_addr.s_addr = skb->nh.iph->saddr; - break; - - case 6: - asoc->c.peer_addr.v6.sin6_family = AF_INET6; - asoc->c.peer_addr.v6.sin6_port - = ntohs(chunk->sctp_hdr->source); - asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */ - asoc->c.peer_addr.v6.sin6_addr = skb->nh.ipv6h->saddr; - asoc->c.peer_addr.v6.sin6_scope_id = - ((struct inet6_skb_parm *)skb->cb)->iif; - break; - - default: - /* Yikes! I never heard of this kind of address. */ + af = sctp_get_af_specific(ipver2af(skb->nh.iph->version)); + if (unlikely(!af)) goto fail; - }; - + af->from_skb(&asoc->c.peer_addr, skb, 1); nodata: return asoc; @@ -1830,11 +1813,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, * stream sequence number shall be set to 0. */ - /* Allocate storage for the negotiated streams. */ - asoc->ssnmap = sctp_ssnmap_new(asoc->peer.i.num_outbound_streams, - asoc->c.sinit_num_ostreams, gfp); - if (!asoc->ssnmap) - goto nomem_ssnmap; + /* Allocate storage for the negotiated streams if it is not a temporary * association. + */ + if (!asoc->temp) { + asoc->ssnmap = sctp_ssnmap_new(asoc->c.sinit_max_instreams, + asoc->c.sinit_num_ostreams, gfp); + if (!asoc->ssnmap) + goto nomem_ssnmap; + } /* ADDIP Section 4.1 ASCONF Chunk Procedures * @@ -1882,6 +1868,7 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param, int retval = 1; sctp_scope_t scope; time_t stale; + struct sctp_af *af; /* We maintain all INIT parameters in network byte order all the * time. This allows us to not worry about whether the parameters @@ -1893,7 +1880,8 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param, break; /* Fall through. */ case SCTP_PARAM_IPV4_ADDRESS: - sctp_param2sockaddr(&addr, param.addr, asoc->peer.port, 0); + af = sctp_get_af_specific(param_type2af(param.p->type)); + af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); scope = sctp_scope(peer_addr); if (sctp_in_scope(&addr, scope)) if (!sctp_assoc_add_peer(asoc, &addr, gfp)) @@ -2005,90 +1993,6 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep) return retval; } -/******************************************************************** - * 4th Level Abstractions - ********************************************************************/ - -/* Convert from an SCTP IP parameter to a union sctp_addr. */ -void sctp_param2sockaddr(union sctp_addr *addr, union sctp_addr_param *param, - __u16 port, int iif) -{ - switch(param->v4.param_hdr.type) { - case SCTP_PARAM_IPV4_ADDRESS: - addr->v4.sin_family = AF_INET; - addr->v4.sin_port = port; - addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; - break; - - case SCTP_PARAM_IPV6_ADDRESS: - addr->v6.sin6_family = AF_INET6; - addr->v6.sin6_port = port; - addr->v6.sin6_flowinfo = 0; /* BUG */ - addr->v6.sin6_addr = param->v6.addr; - addr->v6.sin6_scope_id = iif; - break; - - default: - SCTP_DEBUG_PRINTK("Illegal address type %d\n", - ntohs(param->v4.param_hdr.type)); - break; - }; -} - -/* Convert an IP address in an SCTP param into a sockaddr_in. */ -/* Returns true if a valid conversion was possible. */ -int sctp_addr2sockaddr(union sctp_params p, union sctp_addr *sa) -{ - switch (p.p->type) { - case SCTP_PARAM_IPV4_ADDRESS: - sa->v4.sin_addr = *((struct in_addr *)&p.v4->addr); - sa->v4.sin_family = AF_INET; - break; - - case SCTP_PARAM_IPV6_ADDRESS: - *((struct in6_addr *)&sa->v4.sin_addr) - = p.v6->addr; - sa->v4.sin_family = AF_INET6; - break; - - default: - return 0; - }; - - return 1; -} - -/* Convert a sockaddr_in to an IP address in an SCTP param. - * Returns len if a valid conversion was possible. - */ -int sockaddr2sctp_addr(const union sctp_addr *sa, union sctp_addr_param *p) -{ - int len = 0; - - switch (sa->v4.sin_family) { - case AF_INET: - p->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS; - p->v4.param_hdr.length = ntohs(sizeof(sctp_ipv4addr_param_t)); - len = sizeof(sctp_ipv4addr_param_t); - p->v4.addr.s_addr = sa->v4.sin_addr.s_addr; - break; - - case AF_INET6: - p->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; - p->v6.param_hdr.length = ntohs(sizeof(sctp_ipv6addr_param_t)); - len = sizeof(sctp_ipv6addr_param_t); - p->v6.addr = *(&sa->v6.sin6_addr); - break; - - default: - printk(KERN_WARNING "sockaddr2sctp_addr: Illegal family %d.\n", - sa->v4.sin_family); - return 0; - }; - - return len; -} - /* * ADDIP 3.1.1 Address Configuration Change Chunk (ASCONF) * 0 1 2 3 @@ -2119,8 +2023,9 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, int length = sizeof(asconf) + vparam_len; union sctp_params addrparam; int addrlen; + struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family); - addrlen = sockaddr2sctp_addr(addr, (union sctp_addr_param *)&addrparam); + addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam); if (!addrlen) return NULL; length += addrlen; @@ -2135,7 +2040,51 @@ struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc, retval->subh.addip_hdr = sctp_addto_chunk(retval, sizeof(asconf), &asconf); retval->param_hdr.v = - sctp_addto_chunk(retval, addrlen, &addr); + sctp_addto_chunk(retval, addrlen, &addrparam); + + return retval; +} + +/* ADDIP + * 3.2.4 Set Primary IP Address + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type =0xC004 | Length = Variable | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ASCONF-Request Correlation ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Address Parameter | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Create an ASCONF chunk with Set Primary IP address parameter. + */ +struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc, + union sctp_addr *addr) +{ + sctp_addip_param_t param; + struct sctp_chunk *retval; + int len = sizeof(param); + union sctp_params addrparam; + int addrlen; + struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family); + + addrlen = af->to_addr_param(addr, (union sctp_addr_param *)&addrparam); + if (!addrlen) + return NULL; + len += addrlen; + + /* Create the chunk and make asconf header. */ + retval = sctp_make_asconf(asoc, addr, len); + if (!retval) + return NULL; + + param.param_hdr.type = SCTP_PARAM_SET_PRIMARY; + param.param_hdr.length = htons(len); + param.crr_id = 0; + + sctp_addto_chunk(retval, sizeof(param), ¶m); + sctp_addto_chunk(retval, addrlen, &addrparam); return retval; } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 531ff1606429..86208c51ba36 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -929,6 +929,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, struct sctp_errhdr *errhdr; struct sctp_endpoint *ep; char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)]; + struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family); /* Build the error on the stack. We are way to malloc crazy * throughout the code today. @@ -937,7 +938,7 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, addrparm = (union sctp_addr_param *)errhdr->variable; /* Copy into a parm format. */ - len = sockaddr2sctp_addr(ssa, addrparm); + len = af->to_addr_param(ssa, addrparm); len += sizeof(sctp_errhdr_t); errhdr->cause = SCTP_ERROR_RESTART; diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 722ddbc57c09..a7db6e38441a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1,6 +1,7 @@ -/* Copyright (c) 1999-2000 Cisco, Inc. +/* SCTP kernel reference Implementation + * (C) Copyright IBM Corp. 2001, 2003 + * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001-2003 Intel Corp. * Copyright (c) 2001-2002 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -50,6 +51,7 @@ * Ardelle Fan <ardelle.fan@intel.com> * Ryan Layer <rmlayer@us.ibm.com> * Anup Pemmaiah <pemmaiah@cc.usu.edu> + * Kevin Gao <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. @@ -93,8 +95,8 @@ static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p); static int sctp_wait_for_accept(struct sock *sk, long timeo); static void sctp_wait_for_close(struct sock *sk, long timeo); static inline int sctp_verify_addr(struct sock *, union sctp_addr *, int); -static int sctp_bindx_add(struct sock *, struct sockaddr_storage *, int); -static int sctp_bindx_rem(struct sock *, struct sockaddr_storage *, int); +static int sctp_bindx_add(struct sock *, struct sockaddr *, int); +static int sctp_bindx_rem(struct sock *, struct sockaddr *, int); static int sctp_do_bind(struct sock *, union sctp_addr *, int); static int sctp_autobind(struct sock *sk); static void sctp_sock_migrate(struct sock *, struct sock *, @@ -170,10 +172,7 @@ struct sctp_transport *sctp_addr_id2transport(struct sock *sk, * sd - the socket descriptor returned by socket(). * addr - the address structure (struct sockaddr_in or struct * sockaddr_in6 [RFC 2553]), - * addrlen - the size of the address structure. - * - * The caller should use struct sockaddr_storage described in RFC 2553 - * to represent addr for portability reason. + * addr_len - the size of the address structure. */ int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { @@ -298,112 +297,6 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) return ret; } -/* API 8.1 sctp_bindx() - * - * The syntax of sctp_bindx() is, - * - * ret = sctp_bindx(int sd, - * struct sockaddr_storage *addrs, - * int addrcnt, - * int flags); - * - * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. - * If the sd is an IPv6 socket, the addresses passed can either be IPv4 - * or IPv6 addresses. - * - * A single address may be specified as INADDR_ANY or IPV6_ADDR_ANY, see - * section 3.1.2 for this usage. - * - * addrs is a pointer to an array of one or more socket addresses. Each - * address is contained in a struct sockaddr_storage, so each address is - * fixed length. The caller specifies the number of addresses in the - * array with addrcnt. - * - * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns -1, - * and sets errno to the appropriate error code. [ Editor's note: need - * to fill in all error code? ] - * - * For SCTP, the port given in each socket address must be the same, or - * sctp_bindx() will fail, setting errno to EINVAL . - * - * The flags parameter is formed from the bitwise OR of zero or - * more of the following currently defined flags: - * - * SCTP_BINDX_ADD_ADDR - * SCTP_BINDX_REM_ADDR - * - * SCTP_BIND_ADD_ADDR directs SCTP to add the given addresses to the - * association, and SCTP_BIND_REM_ADDR directs SCTP to remove the given - * addresses from the association. The two flags are mutually exclusive; - * if both are given, sctp_bindx() will fail with EINVAL. A caller may not - * remove all addresses from an association; sctp_bindx() will reject such - * an attempt with EINVAL. - * - * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate - * additional addresses with an endpoint after calling bind(). Or use - * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening - * socket is associated with so that no new association accepted will be - * associated with those addresses. - * - * SCTP_BIND_ADD_ADDR is defined as 0, so that it becomes the default - * behavior for sctp_bindx() when no flags are given. - * - * Adding and removing addresses from a connected association is optional - * functionality. Implementations that do not support this functionality - * should return EOPNOTSUPP. - * - * NOTE: This could be integrated into sctp_setsockopt_bindx(), - * but keeping it this way makes it easier if sometime sys_bindx is - * added. - */ - -/* Unprotected by locks. Call only with socket lock sk->sk_lock held! See - * sctp_bindx() for a lock-protected call. - */ - -static int __sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, - int addrcnt, int flags) -{ - int retval = 0; - - SCTP_DEBUG_PRINTK("__sctp_bindx(sk: %p, addrs: %p, addrcnt: %d, " - "flags: %s)\n", sk, addrs, addrcnt, - (SCTP_BINDX_ADD_ADDR == flags) ? "ADD" : - ((SCTP_BINDX_REM_ADDR == flags) ? "REM" : "BOGUS")); - - switch (flags) { - case SCTP_BINDX_ADD_ADDR: - retval = sctp_bindx_add(sk, addrs, addrcnt); - break; - - case SCTP_BINDX_REM_ADDR: - retval = sctp_bindx_rem(sk, addrs, addrcnt); - break; - - default: - retval = -EINVAL; - break; - }; - - return retval; -} - -/* BINDX with locks. - * - * NOTE: Currently unused at all ... - */ -int sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt, - int flags) -{ - int retval; - - sctp_lock_sock(sk); - retval = __sctp_bindx(sk, addrs, addrcnt, flags); - sctp_release_sock(sk); - - return retval; -} - /* Add a list of addresses as bind addresses to local endpoint or * association. * @@ -414,41 +307,39 @@ int sctp_bindx(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt, * If any of them fails, then the operation will be reversed and the * ones that were added will be removed. * - * Only __sctp_bindx() is supposed to call this function. + * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_add(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) +int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt) { int cnt; int retval = 0; - int addr_len; + void *addr_buf; + struct sockaddr *sa_addr; + struct sctp_af *af; SCTP_DEBUG_PRINTK("sctp_bindx_add (sk: %p, addrs: %p, addrcnt: %d)\n", sk, addrs, addrcnt); + addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { /* The list may contain either IPv4 or IPv6 address; * determine the address length for walking thru the list. */ - switch (((struct sockaddr *)&addrs[cnt])->sa_family) { - case AF_INET: - addr_len = sizeof(struct sockaddr_in); - break; - - case AF_INET6: - addr_len = sizeof(struct sockaddr_in6); - break; - - default: + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + if (!af) { retval = -EINVAL; goto err_bindx_add; - }; + } - retval = sctp_do_bind(sk, (union sctp_addr *)&addrs[cnt], - addr_len); + retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr, + af->sockaddr_len); + + addr_buf += af->sockaddr_len; err_bindx_add: if (retval < 0) { - /* Failed. Cleanup the ones that has been added */ + /* Failed. Cleanup the ones that have been added */ if (cnt > 0) sctp_bindx_rem(sk, addrs, cnt); return retval; @@ -471,9 +362,9 @@ err_bindx_add: * At least one address has to be left; if only one address is * available, the operation will return -EBUSY. * - * Only __sctp_bindx() is supposed to call this function. + * Only sctp_setsockopt_bindx() is supposed to call this function. */ -int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) +int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) { struct sctp_opt *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; @@ -481,50 +372,41 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) struct sctp_bind_addr *bp = &ep->base.bind_addr; int retval = 0; union sctp_addr saveaddr; + void *addr_buf; + struct sockaddr *sa_addr; + struct sctp_af *af; SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n", sk, addrs, addrcnt); + addr_buf = addrs; for (cnt = 0; cnt < addrcnt; cnt++) { - /* If there is only one bind address, there is nothing more - * to be removed (we need at least one address here). + /* If the bind address list is empty or if there is only one + * bind address, there is nothing more to be removed (we need + * at least one address here). */ - if (list_empty(&bp->address_list)) { + if (list_empty(&bp->address_list) || + (sctp_list_single_entry(&bp->address_list))) { retval = -EBUSY; goto err_bindx_rem; } /* The list may contain either IPv4 or IPv6 address; - * determine the address length for walking thru the list. + * determine the address length to copy the address to + * saveaddr. */ - switch (((struct sockaddr *)&addrs[cnt])->sa_family) { - case AF_INET: - saveaddr = *((union sctp_addr *) - &addrs[cnt]); - saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); - /* Verify the port. */ - if (saveaddr.v4.sin_port != bp->port) { - retval = -EINVAL; - goto err_bindx_rem; - } - break; - - case AF_INET6: - saveaddr = *((union sctp_addr *) - &addrs[cnt]); - saveaddr.v6.sin6_port = - ntohs(saveaddr.v6.sin6_port); - /* verify the port */ - if (saveaddr.v6.sin6_port != bp->port) { - retval = -EINVAL; - goto err_bindx_rem; - } - break; - - default: + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + if (!af) { retval = -EINVAL; goto err_bindx_rem; - }; + } + memcpy(&saveaddr, sa_addr, af->sockaddr_len); + saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); + if (saveaddr.v4.sin_port != bp->port) { + retval = -EINVAL; + goto err_bindx_rem; + } /* FIXME - There is probably a need to check if sk->sk_saddr and * sk->sk_rcv_addr are currently set to one of the addresses to @@ -541,6 +423,7 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr_storage *addrs, int addrcnt) sctp_write_unlock(&ep->base.addr_lock); sctp_local_bh_enable(); + addr_buf += af->sockaddr_len; err_bindx_rem: if (retval < 0) { /* Failed. Add the ones that has been removed back */ @@ -553,18 +436,62 @@ err_bindx_rem: return retval; } -/* Helper for tunneling sys_bindx() requests through sctp_setsockopt() +/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt() + * + * API 8.1 + * int sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, + * int flags); + * + * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. + * If the sd is an IPv6 socket, the addresses passed can either be IPv4 + * or IPv6 addresses. + * + * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see + * Section 3.1.2 for this usage. + * + * addrs is a pointer to an array of one or more socket addresses. Each + * address is contained in its appropriate structure (i.e. struct + * sockaddr_in or struct sockaddr_in6) the family of the address type + * must be used to distengish the address length (note that this + * representation is termed a "packed array" of addresses). The caller + * specifies the number of addresses in the array with addrcnt. + * + * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns + * -1, and sets errno to the appropriate error code. + * + * For SCTP, the port given in each socket address must be the same, or + * sctp_bindx() will fail, setting errno to EINVAL. + * + * The flags parameter is formed from the bitwise OR of zero or more of + * the following currently defined flags: + * + * SCTP_BINDX_ADD_ADDR + * + * SCTP_BINDX_REM_ADDR + * + * SCTP_BINDX_ADD_ADDR directs SCTP to add the given addresses to the + * association, and SCTP_BINDX_REM_ADDR directs SCTP to remove the given + * addresses from the association. The two flags are mutually exclusive; + * if both are given, sctp_bindx() will fail with EINVAL. A caller may + * not remove all addresses from an association; sctp_bindx() will + * reject such an attempt with EINVAL. + * + * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate + * additional addresses with an endpoint after calling bind(). Or use + * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening + * socket is associated with so that no new association accepted will be + * associated with those addresses. If the endpoint supports dynamic + * address a SCTP_BINDX_REM_ADDR or SCTP_BINDX_ADD_ADDR may cause a + * endpoint to send the appropriate message to the peer to change the + * peers address lists. + * + * Adding and removing addresses from a connected association is + * optional functionality. Implementations that do not support this + * functionality should return EOPNOTSUPP. * * Basically do nothing but copying the addresses from user to kernel - * land and invoking sctp_bindx on the sk. This is used for tunneling - * the sctp_bindx() [sys_bindx()] request through sctp_setsockopt() - * from userspace. - * - * Note I don't use move_addr_to_kernel(): the reason is we would be - * iterating over an array of struct sockaddr_storage passing always - * what we know is a good size (sizeof (struct sock...)), so it is - * pointless. Instead check the whole area for read access and copy - * it. + * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. + * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace. * * We don't use copy_from_user() for optimization: we first do the * sanity checks (buffer size -fast- and access check-healthy @@ -584,38 +511,70 @@ err_bindx_rem: * * Returns 0 if ok, <0 errno code on error. */ -SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, - struct sockaddr_storage *addrs, - int addrssize, int op) +SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, struct sockaddr *addrs, + int addrs_size, int op) { - struct sockaddr_storage *kaddrs; + struct sockaddr *kaddrs; int err; - size_t addrcnt; + int addrcnt = 0; + int walk_size = 0; + struct sockaddr *sa_addr; + void *addr_buf; + struct sctp_af *af; - SCTP_DEBUG_PRINTK("sctp_do_setsocktopt_bindx: sk %p addrs %p" - " addrssize %d opt %d\n", sk, addrs, addrssize, op); + SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p" + " addrs_size %d opt %d\n", sk, addrs, addrs_size, op); - /* Do we have an integer number of structs sockaddr_storage? */ - if (unlikely(addrssize <= 0 || - addrssize % sizeof(struct sockaddr_storage) != 0)) + if (unlikely(addrs_size <= 0)) return -EINVAL; /* Check the user passed a healthy pointer. */ - if (unlikely(!access_ok(VERIFY_READ, addrs, addrssize))) + if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) return -EFAULT; /* Alloc space for the address array in kernel memory. */ - kaddrs = (struct sockaddr_storage *) kmalloc(addrssize, GFP_KERNEL); + kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL); if (unlikely(!kaddrs)) return -ENOMEM; - if (copy_from_user(kaddrs, addrs, addrssize)) { + if (__copy_from_user(kaddrs, addrs, addrs_size)) { kfree(kaddrs); return -EFAULT; } - addrcnt = addrssize / sizeof(struct sockaddr_storage); - err = __sctp_bindx(sk, kaddrs, addrcnt, op); /* Do the work. */ + /* Walk through the addrs buffer and count the number of addresses. */ + addr_buf = kaddrs; + while (walk_size < addrs_size) { + sa_addr = (struct sockaddr *)addr_buf; + af = sctp_get_af_specific(sa_addr->sa_family); + + /* If the address family is not supported or if this address + * causes the address buffer to overflow return EINVAL. + */ + if (!af || (walk_size + af->sockaddr_len) > addrs_size) { + kfree(kaddrs); + return -EINVAL; + } + addrcnt++; + addr_buf += af->sockaddr_len; + walk_size += af->sockaddr_len; + } + + /* Do the work. */ + switch (op) { + case SCTP_BINDX_ADD_ADDR: + err = sctp_bindx_add(sk, kaddrs, addrcnt); + break; + + case SCTP_BINDX_REM_ADDR: + err = sctp_bindx_rem(sk, kaddrs, addrcnt); + break; + + default: + err = -EINVAL; + break; + }; + kfree(kaddrs); return err; @@ -1476,7 +1435,7 @@ static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen) } /* - * 7.1.14 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied @@ -1522,7 +1481,7 @@ static int sctp_setsockopt_default_send_param(struct sock *sk, return 0; } -/* 7.1.10 Set Peer Primary Address (SCTP_PRIMARY_ADDR) +/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) * * Requests that the local SCTP stack use the enclosed peer address as * the association primary. The enclosed address must be one of the @@ -1727,6 +1686,62 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char *optval, int optlen) return 0; } + +/* + * 7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR) + * + * Requests that the peer mark the enclosed address as the association + * primary. The enclosed address must be one of the association's + * locally bound addresses. The following structure is used to make a + * set primary request: + */ +static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char *optval, + int optlen) +{ + struct sctp_opt *sp; + struct sctp_endpoint *ep; + struct sctp_association *asoc = NULL; + struct sctp_setpeerprim prim; + struct sctp_chunk *chunk; + int err; + + sp = sctp_sk(sk); + ep = sp->ep; + + if (optlen != sizeof(struct sctp_setpeerprim)) + return -EINVAL; + + if (copy_from_user(&prim, optval, optlen)) + return -EFAULT; + + asoc = sctp_id2assoc(sk, prim.sspp_assoc_id); + if (!asoc) + return -EINVAL; + + if (!sctp_state(asoc, ESTABLISHED)) + return -ENOTCONN; + + if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr)) + return -EADDRNOTAVAIL; + + /* Create an ASCONF chunk with SET_PRIMARY parameter */ + chunk = sctp_make_asconf_set_prim(asoc, + (union sctp_addr *)&prim.sspp_addr); + if (!chunk) + return -ENOMEM; + + err = sctp_primitive_ASCONF(asoc, chunk); + if (err) { + sctp_chunk_free(chunk); + return err; + } + + SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n"); + + return 0; +} + + /* API 6.2 setsockopt(), getsockopt() * * Applications use setsockopt() and getsockopt() to set or retrieve @@ -1771,16 +1786,14 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, switch (optname) { case SCTP_SOCKOPT_BINDX_ADD: /* 'optlen' is the size of the addresses buffer. */ - retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *) - optval, optlen, - SCTP_BINDX_ADD_ADDR); + retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval, + optlen, SCTP_BINDX_ADD_ADDR); break; case SCTP_SOCKOPT_BINDX_REM: /* 'optlen' is the size of the addresses buffer. */ - retval = sctp_setsockopt_bindx(sk, (struct sockaddr_storage *) - optval, optlen, - SCTP_BINDX_REM_ADDR); + retval = sctp_setsockopt_bindx(sk, (struct sockaddr *)optval, + optlen, SCTP_BINDX_REM_ADDR); break; case SCTP_DISABLE_FRAGMENTS: @@ -1809,6 +1822,9 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, case SCTP_PRIMARY_ADDR: retval = sctp_setsockopt_primary_addr(sk, optval, optlen); break; + case SCTP_SET_PEER_PRIMARY_ADDR: + retval = sctp_setsockopt_peer_primary_addr(sk, optval, optlen); + break; case SCTP_NODELAY: retval = sctp_setsockopt_nodelay(sk, optval, optlen); break; @@ -2056,9 +2072,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) return -ESOCKTNOSUPPORT; } - /* FIXME: The next draft (04) of the SCTP Sockets Extensions - * should include a socket option for manipulating these - * message parameters (and a few others). + /* Initialize default send parameters. These parameters can be + * modified with the SCTP_DEFAULT_SEND_PARAM socket option. */ sp->default_stream = 0; sp->default_ppid = 0; @@ -2077,7 +2092,6 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) /* Initialize default RTO related parameters. These parameters can * be modified for with the SCTP_RTOINFO socket option. - * FIXME: These are not used yet. */ sp->rtoinfo.srto_initial = (sctp_rto_initial / HZ) * 1000; sp->rtoinfo.srto_max = (sctp_rto_max / HZ) * 1000; @@ -2093,15 +2107,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) sp->assocparams.sasoc_cookie_life = (sctp_valid_cookie_life / HZ) * 1000; - /* Initialize default event subscriptions. - * the struct sock is initialized to zero, so only - * enable the events needed. By default, UDP-style - * sockets enable io and association change notifications. + /* Initialize default event subscriptions. By default, all the + * options are off. */ - if (sctp_style(sk, UDP)) { - sp->subscribe.sctp_data_io_event = 1; - sp->subscribe.sctp_association_event = 1; - } + memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe)); /* Default Peer Address Parameters. These defaults can * be modified via SCTP_PEER_ADDR_PARAMS @@ -2552,7 +2561,7 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int * } static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, - char *optval, int *optlen) + char *optval, int *optlen) { sctp_assoc_t id; struct sctp_association *asoc; @@ -2565,9 +2574,7 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) return -EFAULT; - /* - * For UDP-style sockets, id specifies the association to query. - */ + /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, id); if (!asoc) return -EINVAL; @@ -2582,16 +2589,17 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len, } static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, - char *optval, int *optlen) + char *optval, int *optlen) { struct sctp_association *asoc; struct list_head *pos; int cnt = 0; struct sctp_getaddrs getaddrs; struct sctp_transport *from; - struct sockaddr_storage *to; + void *to; union sctp_addr temp; struct sctp_opt *sp = sctp_sk(sk); + int addrlen; if (len != sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -2600,21 +2608,21 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, return -EFAULT; if (getaddrs.addr_num <= 0) return -EINVAL; - /* - * For UDP-style sockets, id specifies the association to query. - */ + + /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, getaddrs.assoc_id); if (!asoc) return -EINVAL; - to = getaddrs.addrs; + to = (void *)getaddrs.addrs; list_for_each(pos, &asoc->peer.transport_addr_list) { from = list_entry(pos, struct sctp_transport, transports); memcpy(&temp, &from->ipaddr, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); - if (copy_to_user(to, &temp, sizeof(temp))) + addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len; + if (copy_to_user(to, &temp, addrlen)) return -EFAULT; - to ++; + to += addrlen ; cnt ++; if (cnt >= getaddrs.addr_num) break; } @@ -2673,9 +2681,10 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, int cnt = 0; struct sctp_getaddrs getaddrs; struct sctp_sockaddr_entry *from; - struct sockaddr_storage *to; + void *to; union sctp_addr temp; struct sctp_opt *sp = sctp_sk(sk); + int addrlen; if (len != sizeof(struct sctp_getaddrs)) return -EINVAL; @@ -2699,16 +2708,17 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, bp = &asoc->base.bind_addr; } - to = getaddrs.addrs; + to = (void *)getaddrs.addrs; list_for_each(pos, &bp->address_list) { from = list_entry(pos, struct sctp_sockaddr_entry, list); memcpy(&temp, &from->a, sizeof(temp)); sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); - if (copy_to_user(to, &temp, sizeof(temp))) + addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; + if (copy_to_user(to, &temp, addrlen)) return -EFAULT; - to ++; + to += addrlen; cnt ++; if (cnt >= getaddrs.addr_num) break; } @@ -2759,7 +2769,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, /* * - * 7.1.14 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied @@ -3331,9 +3341,19 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog) if (!sctp_style(sk, UDP)) return -EINVAL; + /* If backlog is zero, disable listening. */ + if (!backlog) { + if (sctp_sstate(sk, CLOSED)) + return 0; + + sctp_unhash_endpoint(ep); + sk->sk_state = SCTP_SS_CLOSED; + } + + /* Return if we are already listening. */ if (sctp_sstate(sk, LISTENING)) return 0; - + /* * If a bind() or sctp_bindx() is not called prior to a listen() * call that allows new associations to be accepted, the system @@ -3364,6 +3384,15 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) struct sctp_opt *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; + /* If backlog is zero, disable listening. */ + if (!backlog) { + if (sctp_sstate(sk, CLOSED)) + return 0; + + sctp_unhash_endpoint(ep); + sk->sk_state = SCTP_SS_CLOSED; + } + if (sctp_sstate(sk, LISTENING)) return 0; diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index cdcf6d09d24f..edffe9cc8f21 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -214,7 +214,7 @@ static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen, if (olen != sizeof (int)) return -EINVAL; } - if (put_user((*(int *)(table->data) / HZ) * 1000, + if (put_user((*(int *)(table->data) * 1000) / HZ, (int *)oldval) || (oldlenp && put_user(sizeof (int), oldlenp))) return -EFAULT; @@ -228,7 +228,7 @@ static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen, if (get_user(new, (int *)newval)) return -EFAULT; - *(int *)(table->data) = (new * HZ) * 1000; + *(int *)(table->data) = (new * HZ) / 1000; } return 1; } diff --git a/net/socket.c b/net/socket.c index 74fd11fdd7a8..f0a1a3da7500 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1894,6 +1894,8 @@ int sock_register(struct net_proto_family *ops) err = 0; } net_family_write_unlock(); + printk(KERN_INFO "NET: Registered protocol family %d\n", + ops->family); return err; } @@ -1911,6 +1913,8 @@ int sock_unregister(int family) net_family_write_lock(); net_families[family]=NULL; net_family_write_unlock(); + printk(KERN_INFO "NET: Unregistered protocol family %d\n", + family); return 0; } diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d9dd8a2f3914..61ea1a9f2a2b 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -57,7 +57,7 @@ * [TO FIX] * ECONNREFUSED is not returned from one end of a connected() socket to the * other the moment one end closes. - * fstat() doesn't return st_dev=NODEV, and give the blksize as high water mark + * fstat() doesn't return st_dev=0, and give the blksize as high water mark * and a fake inode identifier (nor the BSD first socket fstat twice bug). * [NOT TO FIX] * accept() returns a path name even if the connecting socket has closed @@ -111,6 +111,7 @@ #include <linux/tcp.h> #include <net/af_unix.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <net/scm.h> #include <linux/init.h> #include <linux/poll.h> @@ -1805,25 +1806,52 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl #ifdef CONFIG_PROC_FS -static int unix_read_proc(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) +static struct sock *unix_seq_idx(int *iter, loff_t pos) { - off_t pos=0; - off_t begin=0; - int len=0; - int i; + loff_t off = 0; struct sock *s; - - len+= sprintf(buffer,"Num RefCount Protocol Flags Type St " - "Inode Path\n"); + for (s = first_unix_socket(iter); s; s = next_unix_socket(iter, s)) { + if (off == pos) + return s; + ++off; + } + return NULL; +} + + +static void *unix_seq_start(struct seq_file *seq, loff_t *pos) +{ read_lock(&unix_table_lock); - forall_unix_sockets (i,s) - { + return *pos ? unix_seq_idx(seq->private, *pos - 1) : ((void *) 1); +} + +static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + + if (v == (void *)1) + return first_unix_socket(seq->private); + return next_unix_socket(seq->private, v); +} + +static void unix_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock(&unix_table_lock); +} + +static int unix_seq_show(struct seq_file *seq, void *v) +{ + + if (v == (void *)1) + seq_puts(seq, "Num RefCount Protocol Flags Type St " + "Inode Path\n"); + else { + struct sock *s = v; struct unix_sock *u = unix_sk(s); unix_state_rlock(s); - len+=sprintf(buffer+len,"%p: %08X %08X %08X %04X %02X %5lu", + seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu", s, atomic_read(&s->sk_refcnt), 0, @@ -1835,39 +1863,61 @@ static int unix_read_proc(char *buffer, char **start, off_t offset, sock_i_ino(s)); if (u->addr) { - buffer[len++] = ' '; - memcpy(buffer+len, u->addr->name->sun_path, - u->addr->len-sizeof(short)); - if (!UNIX_ABSTRACT(s)) - len--; - else - buffer[len] = '@'; - len += u->addr->len - sizeof(short); - } - unix_state_runlock(s); + int i; + seq_putc(seq, ' '); + + for (i = 0; i < u->addr->len-sizeof(short); i++) + seq_putc(seq, u->addr->name->sun_path[i]); - buffer[len++]='\n'; - - pos = begin + len; - if(pos<offset) - { - len=0; - begin=pos; + if (UNIX_ABSTRACT(s)) + seq_putc(seq, '@'); } - if(pos>offset+length) - goto done; + unix_state_runlock(s); + seq_putc(seq, '\n'); } - *eof = 1; -done: - read_unlock(&unix_table_lock); - *start=buffer+(offset-begin); - len-=(offset-begin); - if(len>length) - len=length; - if (len < 0) - len = 0; - return len; + + return 0; } + +struct seq_operations unix_seq_ops = { + .start = unix_seq_start, + .next = unix_seq_next, + .stop = unix_seq_stop, + .show = unix_seq_show, +}; + + +static int unix_seq_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int rc = -ENOMEM; + int *iter = kmalloc(sizeof(int), GFP_KERNEL); + + if (!iter) + goto out; + + rc = seq_open(file, &unix_seq_ops); + if (rc) + goto out_kfree; + + seq = file->private_data; + seq->private = iter; + *iter = 0; +out: + return rc; +out_kfree: + kfree(iter); + goto out; +} + +static struct file_operations unix_seq_fops = { + .owner = THIS_MODULE, + .open = unix_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + #endif struct proto_ops unix_stream_ops = { @@ -1926,13 +1976,10 @@ static inline void unix_sysctl_register(void) {} static inline void unix_sysctl_unregister(void) {} #endif -static char banner[] __initdata = KERN_INFO "NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.\n"; - static int __init af_unix_init(void) { struct sk_buff *dummy_skb; - printk(banner); if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)) { printk(KERN_CRIT "%s: panic\n", __FUNCTION__); return -1; @@ -1947,7 +1994,7 @@ static int __init af_unix_init(void) sock_register(&unix_family_ops); #ifdef CONFIG_PROC_FS - create_proc_read_entry("net/unix", 0, 0, unix_read_proc, NULL); + proc_net_fops_create("unix", 0, &unix_seq_fops); #endif unix_sysctl_register(); return 0; @@ -1957,7 +2004,7 @@ static void __exit af_unix_exit(void) { sock_unregister(PF_UNIX); unix_sysctl_unregister(); - remove_proc_entry("net/unix", 0); + proc_net_remove("unix"); kmem_cache_destroy(unix_sk_cachep); } |
