diff --git a/debian/changelog b/debian/changelog index 973adea5b..05a50fc3d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -19,6 +19,77 @@ linux-2.6 (2.6.18-3) UNRELEASED; urgency=low [ maximilian attems ] * [mipsel] Disable CONFIG_SECURITY_SECLVL on DECstations too. + * Add stable release 2.6.18.1: + - add utsrelease.h to the dontdiff file + - V4L: copy-paste bug in videodev.c + - block layer: elv_iosched_show should get elv_list_lock + - NETFILTER: NAT: fix NOTRACK checksum handling + - bcm43xx: fix regressions in 2.6.18 + - x86-64: Calgary IOMMU: Fix off by one when calculating register space + location + - ide-generic: jmicron fix + - scx200_hrt: fix precedence bug manifesting as 27x clock in 1 MHz mode + - invalidate_inode_pages2(): ignore page refcounts + - rtc driver rtc-pcf8563 century bit inversed + - fbdev: correct buffer size limit in fbmem_read_proc() + - mm: bug in set_page_dirty_buffers + - TCP: Fix and simplify microsecond rtt sampling + - MD: Fix problem where hot-added drives are not resynced. + - IPV6: Disable SG for GSO unless we have checksum + - PKT_SCHED: cls_basic: Use unsigned int when generating handle + - sata_mv: fix oops + - [SPARC64]: Kill bogus check from bootmem_init(). + - IPV6: bh_lock_sock_nested on tcp_v6_rcv + - [CPUFREQ] Fix some more CPU hotplug locking. + - SPARC64: Fix serious bug in sched_clock() on sparc64 + - Fix VIDIOC_ENUMSTD bug + - load_module: no BUG if module_subsys uninitialized + - i386: fix flat mode numa on a real numa system + - cpu to node relationship fixup: map cpu to node + - cpu to node relationship fixup: acpi_map_cpu2node + - backlight: fix oops in __mutex_lock_slowpath during head + /sys/class/graphics/fb0/* + - do not free non slab allocated per_cpu_pageset + - rtc: lockdep fix/workaround + - powerpc: Fix ohare IDE irq workaround on old powermacs + - sysfs: remove duplicated dput in sysfs_update_file + - powerpc: fix building gdb against asm/ptrace.h + - Remove offsetof() from user-visible + - Clean up exported headers on CRIS + - Fix v850 exported headers + - Don't advertise (or allow) headers_{install,check} where inappropriate. + - Remove UML header export + - Remove ARM26 header export. + - Fix H8300 exported headers. + - Fix m68knommu exported headers + - Fix exported headers for SPARC, SPARC64 + - Fix 'make headers_check' on m32r + - Fix 'make headers_check' on sh64 + - Fix 'make headers_check' on sh + - Fix ARM 'make headers_check' + - One line per header in Kbuild files to reduce conflicts + - sky2 network driver device ids + - sky2: tx pause bug fix + - netdrvr: lp486e: fix typo + - mv643xx_eth: fix obvious typo, which caused build breakage + - zone_reclaim: dynamic slab reclaim + - Fix longstanding load balancing bug in the scheduler + - jbd: fix commit of ordered data buffers + - ALSA: Fix initiailization of user-space controls + - USB: Allow compile in g_ether, fix typo + - IB/mthca: Fix lid used for sending traps + - S390: user readable uninitialised kernel memory (CVE-2006-5174) + - zd1211rw: ZD1211B ASIC/FWT, not jointly decoder + - V4L: pvrusb2: Limit hor res for 24xxx devices + - V4L: pvrusb2: Suppress compiler warning + - V4L: pvrusb2: improve 24XXX config option description + - V4L: pvrusb2: Solve mutex deadlock + - DVB: cx24123: fix PLL divisor setup + - V4L: Fix msp343xG handling regression + - UML: Fix UML build failure + - uml: use DEFCONFIG_LIST to avoid reading host's config + - uml: allow using again x86/x86_64 crypto code + - NET_SCHED: Fix fallout from dev->qdisc RCU change [ Martin Michlmayr ] * [mips] Apply some patches from linux-mips' linux-2.6.18-stable GIT tree: @@ -46,7 +117,7 @@ linux-2.6 (2.6.18-3) UNRELEASED; urgency=low [ Kyle McMartin ] * [hppa] Force CROSS_COMPILE=hppa64-linux-gnu- (closes: #389296) - -- dann frazier Fri, 13 Oct 2006 19:45:39 -0600 + -- maximilian attems Mon, 16 Oct 2006 09:21:32 +0200 linux-2.6 (2.6.18-2) unstable; urgency=low diff --git a/debian/patches/bugfix/2.6.18.1 b/debian/patches/bugfix/2.6.18.1 new file mode 100644 index 000000000..ac486684c --- /dev/null +++ b/debian/patches/bugfix/2.6.18.1 @@ -0,0 +1,8239 @@ +diff --git a/Documentation/dontdiff b/Documentation/dontdiff +index 24adfe9..63c2d0c 100644 +--- a/Documentation/dontdiff ++++ b/Documentation/dontdiff +@@ -135,6 +135,7 @@ tags + times.h* + tkparse + trix_boot.h ++utsrelease.h* + version.h* + vmlinux + vmlinux-* +diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt +index 7cee902..20d0d79 100644 +--- a/Documentation/sysctl/vm.txt ++++ b/Documentation/sysctl/vm.txt +@@ -29,6 +29,7 @@ Currently, these files are in /proc/sys/ + - drop-caches + - zone_reclaim_mode + - min_unmapped_ratio ++- min_slab_ratio + - panic_on_oom + + ============================================================== +@@ -138,7 +139,6 @@ This is value ORed together of + 1 = Zone reclaim on + 2 = Zone reclaim writes dirty pages out + 4 = Zone reclaim swaps pages +-8 = Also do a global slab reclaim pass + + zone_reclaim_mode is set during bootup to 1 if it is determined that pages + from remote zones will cause a measurable performance reduction. The +@@ -162,18 +162,13 @@ Allowing regular swap effectively restri + node unless explicitly overridden by memory policies or cpuset + configurations. + +-It may be advisable to allow slab reclaim if the system makes heavy +-use of files and builds up large slab caches. However, the slab +-shrink operation is global, may take a long time and free slabs +-in all nodes of the system. +- + ============================================================= + + min_unmapped_ratio: + + This is available only on NUMA kernels. + +-A percentage of the file backed pages in each zone. Zone reclaim will only ++A percentage of the total pages in each zone. Zone reclaim will only + occur if more than this percentage of pages are file backed and unmapped. + This is to insure that a minimal amount of local pages is still available for + file I/O even if the node is overallocated. +@@ -182,6 +177,24 @@ The default is 1 percent. + + ============================================================= + ++min_slab_ratio: ++ ++This is available only on NUMA kernels. ++ ++A percentage of the total pages in each zone. On Zone reclaim ++(fallback from the local zone occurs) slabs will be reclaimed if more ++than this percentage of pages in a zone are reclaimable slab pages. ++This insures that the slab growth stays under control even in NUMA ++systems that rarely perform global reclaim. ++ ++The default is 5 percent. ++ ++Note that slab reclaim is triggered in a per zone / node fashion. ++The process of reclaiming slab memory is currently not node specific ++and may not be fast. ++ ++============================================================= ++ + panic_on_oom + + This enables or disables panic on out-of-memory feature. If this is set to 1, +diff --git a/Makefile b/Makefile +index edfc2fd..b803595 100644 +--- a/Makefile ++++ b/Makefile +@@ -894,6 +894,9 @@ export INSTALL_HDR_PATH + + PHONY += headers_install + headers_install: include/linux/version.h ++ @if [ ! -r include/asm-$(ARCH)/Kbuild ]; then \ ++ echo '*** Error: Headers not exportable for this architecture ($(ARCH))'; \ ++ exit 1 ; fi + $(Q)unifdef -Ux /dev/null + $(Q)rm -rf $(INSTALL_HDR_PATH)/include + $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.headersinst obj=include +@@ -1076,13 +1079,17 @@ help: + @echo ' cscope - Generate cscope index' + @echo ' kernelrelease - Output the release version string' + @echo ' kernelversion - Output the version stored in Makefile' +- @echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH' ++ @if [ -r include/asm-$(ARCH)/Kbuild ]; then \ ++ echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \ ++ fi + @echo ' (default: $(INSTALL_HDR_PATH))' + @echo '' + @echo 'Static analysers' + @echo ' checkstack - Generate a list of stack hogs' + @echo ' namespacecheck - Name space analysis on compiled kernel' +- @echo ' headers_check - Sanity check on exported headers' ++ @if [ -r include/asm-$(ARCH)/Kbuild ]; then \ ++ echo ' headers_check - Sanity check on exported headers'; \ ++ fi + @echo '' + @echo 'Kernel packaging:' + @$(MAKE) $(build)=$(package-dir) help +diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c +index f948419..efe0799 100644 +--- a/arch/i386/kernel/smpboot.c ++++ b/arch/i386/kernel/smpboot.c +@@ -642,9 +642,13 @@ static void map_cpu_to_logical_apicid(vo + { + int cpu = smp_processor_id(); + int apicid = logical_smp_processor_id(); ++ int node = apicid_to_node(apicid); ++ ++ if (!node_online(node)) ++ node = first_online_node; + + cpu_2_logical_apicid[cpu] = apicid; +- map_cpu_to_node(cpu, apicid_to_node(apicid)); ++ map_cpu_to_node(cpu, node); + } + + static void unmap_cpu_to_logical_apicid(int cpu) +diff --git a/arch/i386/mm/boot_ioremap.c b/arch/i386/mm/boot_ioremap.c +index 5d44f4f..5cf739a 100644 +--- a/arch/i386/mm/boot_ioremap.c ++++ b/arch/i386/mm/boot_ioremap.c +@@ -29,8 +29,11 @@ #include + */ + + #define BOOT_PTE_PTRS (PTRS_PER_PTE*2) +-#define boot_pte_index(address) \ +- (((address) >> PAGE_SHIFT) & (BOOT_PTE_PTRS - 1)) ++ ++static unsigned long boot_pte_index(unsigned long vaddr) ++{ ++ return __pa(vaddr) >> PAGE_SHIFT; ++} + + static inline boot_pte_t* boot_vaddr_to_pte(void *address) + { +diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c +index 0176556..32c3abe 100644 +--- a/arch/ia64/kernel/acpi.c ++++ b/arch/ia64/kernel/acpi.c +@@ -771,16 +771,19 @@ int acpi_map_cpu2node(acpi_handle handle + { + #ifdef CONFIG_ACPI_NUMA + int pxm_id; ++ int nid; + + pxm_id = acpi_get_pxm(handle); +- + /* +- * Assuming that the container driver would have set the proximity +- * domain and would have initialized pxm_to_node(pxm_id) && pxm_flag ++ * We don't have cpu-only-node hotadd. But if the system equips ++ * SRAT table, pxm is already found and node is ready. ++ * So, just pxm_to_nid(pxm) is OK. ++ * This code here is for the system which doesn't have full SRAT ++ * table for possible cpus. + */ +- node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_node(pxm_id); +- ++ nid = acpi_map_pxm_to_node(pxm_id); + node_cpuid[cpu].phys_id = physid; ++ node_cpuid[cpu].nid = nid; + #endif + return (0); + } +diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c +index 1cc360c..2034063 100644 +--- a/arch/ia64/kernel/numa.c ++++ b/arch/ia64/kernel/numa.c +@@ -29,6 +29,36 @@ EXPORT_SYMBOL(cpu_to_node_map); + + cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; + ++void __cpuinit map_cpu_to_node(int cpu, int nid) ++{ ++ int oldnid; ++ if (nid < 0) { /* just initialize by zero */ ++ cpu_to_node_map[cpu] = 0; ++ return; ++ } ++ /* sanity check first */ ++ oldnid = cpu_to_node_map[cpu]; ++ if (cpu_isset(cpu, node_to_cpu_mask[oldnid])) { ++ return; /* nothing to do */ ++ } ++ /* we don't have cpu-driven node hot add yet... ++ In usual case, node is created from SRAT at boot time. */ ++ if (!node_online(nid)) ++ nid = first_online_node; ++ cpu_to_node_map[cpu] = nid; ++ cpu_set(cpu, node_to_cpu_mask[nid]); ++ return; ++} ++ ++void __cpuinit unmap_cpu_from_node(int cpu, int nid) ++{ ++ WARN_ON(!cpu_isset(cpu, node_to_cpu_mask[nid])); ++ WARN_ON(cpu_to_node_map[cpu] != nid); ++ cpu_to_node_map[cpu] = 0; ++ cpu_clear(cpu, node_to_cpu_mask[nid]); ++} ++ ++ + /** + * build_cpu_to_node_map - setup cpu to node and node to cpumask arrays + * +@@ -49,8 +79,6 @@ void __init build_cpu_to_node_map(void) + node = node_cpuid[i].nid; + break; + } +- cpu_to_node_map[cpu] = (node >= 0) ? node : 0; +- if (node >= 0) +- cpu_set(cpu, node_to_cpu_mask[node]); ++ map_cpu_to_node(cpu, node); + } + } +diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c +index f648c61..5629b45 100644 +--- a/arch/ia64/kernel/topology.c ++++ b/arch/ia64/kernel/topology.c +@@ -36,6 +36,7 @@ #if defined (CONFIG_ACPI) && defined (CO + */ + if (!can_cpei_retarget() && is_cpu_cpei_target(num)) + sysfs_cpus[num].cpu.no_control = 1; ++ map_cpu_to_node(num, node_cpuid[num].nid); + #endif + + return register_cpu(&sysfs_cpus[num].cpu, num); +@@ -45,7 +46,8 @@ #ifdef CONFIG_HOTPLUG_CPU + + void arch_unregister_cpu(int num) + { +- return unregister_cpu(&sysfs_cpus[num].cpu); ++ unregister_cpu(&sysfs_cpus[num].cpu); ++ unmap_cpu_from_node(num, cpu_to_node(num)); + } + EXPORT_SYMBOL(arch_register_cpu); + EXPORT_SYMBOL(arch_unregister_cpu); +diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S +index 8372752..3f5511d 100644 +--- a/arch/s390/lib/uaccess.S ++++ b/arch/s390/lib/uaccess.S +@@ -40,7 +40,17 @@ __copy_from_user_asm: + # move with the reduced length which is < 256 + 5: mvcp 0(%r5,%r2),0(%r4),%r0 + slr %r3,%r5 +-6: lr %r2,%r3 ++ alr %r2,%r5 ++6: lgr %r5,%r3 # copy remaining size ++ ahi %r5,-1 # subtract 1 for xc loop ++ bras %r4,8f ++ xc 0(1,%2),0(%2) ++7: xc 0(256,%2),0(%2) ++ la %r2,256(%r2) ++8: ahji %r5,-256 ++ jnm 7b ++ ex %r5,0(%r2) ++9: lr %r2,%r3 + br %r14 + .section __ex_table,"a" + .long 0b,4b +diff --git a/arch/s390/lib/uaccess64.S b/arch/s390/lib/uaccess64.S +index 1f755be..9376df0 100644 +--- a/arch/s390/lib/uaccess64.S ++++ b/arch/s390/lib/uaccess64.S +@@ -40,7 +40,17 @@ __copy_from_user_asm: + # move with the reduced length which is < 256 + 5: mvcp 0(%r5,%r2),0(%r4),%r0 + slgr %r3,%r5 +-6: lgr %r2,%r3 ++ algr %r2,%r5 ++6: lgr %r5,%r3 # copy remaining size ++ aghi %r5,-1 # subtract 1 for xc loop ++ bras %r4,8f ++ xc 0(1,%r2),0(%r2) ++7: xc 0(256,%r2),0(%r2) ++ la %r2,256(%r2) ++8: aghi %r5,-256 ++ jnm 7b ++ ex %r5,0(%r2) ++9: lgr %r2,%r3 + br %r14 + .section __ex_table,"a" + .quad 0b,4b +diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c +index 22dc9c2..f203131 100644 +--- a/arch/sh/kernel/process.c ++++ b/arch/sh/kernel/process.c +@@ -26,6 +26,7 @@ #include + #include + #include + #include ++#include + + static int hlt_counter=0; + +diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c +index 094d3e3..b0b4fee 100644 +--- a/arch/sparc64/kernel/time.c ++++ b/arch/sparc64/kernel/time.c +@@ -983,7 +983,7 @@ static struct time_interpolator sparc64_ + }; + + /* The quotient formula is taken from the IA64 port. */ +-#define SPARC64_NSEC_PER_CYC_SHIFT 30UL ++#define SPARC64_NSEC_PER_CYC_SHIFT 10UL + void __init time_init(void) + { + unsigned long clock = sparc64_init_timers(); +diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c +index dcba4e6..09cb7fc 100644 +--- a/arch/sparc64/mm/init.c ++++ b/arch/sparc64/mm/init.c +@@ -920,8 +920,7 @@ #ifdef CONFIG_BLK_DEV_INITRD + if (sparc_ramdisk_image || sparc_ramdisk_image64) { + unsigned long ramdisk_image = sparc_ramdisk_image ? + sparc_ramdisk_image : sparc_ramdisk_image64; +- if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE) +- ramdisk_image -= KERNBASE; ++ ramdisk_image -= KERNBASE; + initrd_start = ramdisk_image + phys_base; + initrd_end = initrd_start + sparc_ramdisk_size; + if (initrd_end > end_of_phys_memory) { +diff --git a/arch/um/Kconfig b/arch/um/Kconfig +index 76e85bb..a8dbc61 100644 +--- a/arch/um/Kconfig ++++ b/arch/um/Kconfig +@@ -1,3 +1,8 @@ ++config DEFCONFIG_LIST ++ string ++ option defconfig_list ++ default "arch/$ARCH/defconfig" ++ + # UML uses the generic IRQ sugsystem + config GENERIC_HARDIRQS + bool +diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 +index 9558a7c..3e9b347 100644 +--- a/arch/um/Makefile-x86_64 ++++ b/arch/um/Makefile-x86_64 +@@ -1,7 +1,7 @@ + # Copyright 2003 - 2004 Pathscale, Inc + # Released under the GPL + +-core-y += arch/um/sys-x86_64/ ++core-y += arch/um/sys-x86_64/ arch/x86_64/crypto/ + START := 0x60000000 + + #We #undef __x86_64__ for kernelspace, not for userspace where +diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h +index 356390d..39bb210 100644 +--- a/arch/um/include/common-offsets.h ++++ b/arch/um/include/common-offsets.h +@@ -15,3 +15,4 @@ DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); + DEFINE(UM_ELF_CLASS, ELF_CLASS); + DEFINE(UM_ELFCLASS32, ELFCLASS32); + DEFINE(UM_ELFCLASS64, ELFCLASS64); ++DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); +diff --git a/arch/um/include/sysdep-i386/kernel-offsets.h b/arch/um/include/sysdep-i386/kernel-offsets.h +index 2c13de3..2e58c4c 100644 +--- a/arch/um/include/sysdep-i386/kernel-offsets.h ++++ b/arch/um/include/sysdep-i386/kernel-offsets.h +@@ -1,6 +1,7 @@ + #include + #include + #include ++#include + #include + + #define DEFINE(sym, val) \ +diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h +index 91d129f..4cbfbb9 100644 +--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h ++++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h +@@ -2,6 +2,7 @@ #include + #include + #include + #include ++#include + #include + #include + +diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c +index b98d3ca..c8bf772 100644 +--- a/arch/um/os-Linux/process.c ++++ b/arch/um/os-Linux/process.c +@@ -141,11 +141,9 @@ void os_usr1_process(int pid) + * syscalls, and also breaks with clone(), which does not unshare the TLS. + */ + +-inline _syscall0(pid_t, getpid) +- + int os_getpid(void) + { +- return(getpid()); ++ return syscall(__NR_getpid); + } + + int os_getpgrp(void) +diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c +index 120abbe..64f547f 100644 +--- a/arch/um/os-Linux/sys-i386/tls.c ++++ b/arch/um/os-Linux/sys-i386/tls.c +@@ -3,8 +3,6 @@ #include + #include "sysdep/tls.h" + #include "user_util.h" + +-static _syscall1(int, get_thread_area, user_desc_t *, u_info); +- + /* Checks whether host supports TLS, and sets *tls_min according to the value + * valid on the host. + * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */ +@@ -17,7 +15,7 @@ void check_host_supports_tls(int *suppor + user_desc_t info; + info.entry_number = val[i]; + +- if (get_thread_area(&info) == 0) { ++ if(syscall(__NR_get_thread_area, &info) == 0){ + *tls_min = val[i]; + *supports_tls = 1; + return; +diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c +index 9cb09a4..297f263 100644 +--- a/arch/um/os-Linux/tls.c ++++ b/arch/um/os-Linux/tls.c +@@ -48,14 +48,11 @@ #endif + #ifdef UML_CONFIG_MODE_TT + #include "linux/unistd.h" + +-static _syscall1(int, get_thread_area, user_desc_t *, u_info); +-static _syscall1(int, set_thread_area, user_desc_t *, u_info); +- + int do_set_thread_area_tt(user_desc_t *info) + { + int ret; + +- ret = set_thread_area(info); ++ ret = syscall(__NR_set_thread_area, info); + if (ret < 0) { + ret = -errno; + } +@@ -66,7 +63,7 @@ int do_get_thread_area_tt(user_desc_t *i + { + int ret; + +- ret = get_thread_area(info); ++ ret = syscall(__NR_get_thread_area, info); + if (ret < 0) { + ret = -errno; + } +diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c +index 146924b..53747fb 100644 +--- a/arch/x86_64/kernel/pci-calgary.c ++++ b/arch/x86_64/kernel/pci-calgary.c +@@ -759,7 +759,16 @@ static inline unsigned int __init locate + int rionodeid; + u32 address; + +- rionodeid = (dev->bus->number % 15 > 4) ? 3 : 2; ++ /* ++ * Each Calgary has four busses. The first four busses (first Calgary) ++ * have RIO node ID 2, then the next four (second Calgary) have RIO ++ * node ID 3, the next four (third Calgary) have node ID 2 again, etc. ++ * We use a gross hack - relying on the dev->bus->number ordering, ++ * modulo 14 - to decide which Calgary a given bus is on. Busses 0, 1, ++ * 2 and 4 are on the first Calgary (id 2), 6, 8, a and c are on the ++ * second (id 3), and then it repeats modulo 14. ++ */ ++ rionodeid = (dev->bus->number % 14 > 4) ? 3 : 2; + /* + * register space address calculation as follows: + * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase) +@@ -767,7 +776,7 @@ static inline unsigned int __init locate + * RioNodeId is 2 for first Calgary, 3 for second Calgary + */ + address = START_ADDRESS - +- (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 15)) + ++ (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 14)) + + (0x100000) * (rionodeid - CHASSIS_BASE); + return address; + } +diff --git a/block/elevator.c b/block/elevator.c +index 9b72dc7..8ed2846 100644 +--- a/block/elevator.c ++++ b/block/elevator.c +@@ -892,7 +892,7 @@ ssize_t elv_iosched_show(request_queue_t + struct list_head *entry; + int len = 0; + +- spin_lock_irq(q->queue_lock); ++ spin_lock_irq(&elv_list_lock); + list_for_each(entry, &elv_list) { + struct elevator_type *__e; + +@@ -902,7 +902,7 @@ ssize_t elv_iosched_show(request_queue_t + else + len += sprintf(name+len, "%s ", __e->elevator_name); + } +- spin_unlock_irq(q->queue_lock); ++ spin_unlock_irq(&elv_list_lock); + + len += sprintf(len+name, "\n"); + return len; +diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c +index 6e6a7c7..ab6429b 100644 +--- a/drivers/char/rtc.c ++++ b/drivers/char/rtc.c +@@ -209,11 +209,12 @@ static const unsigned char days_in_mo[] + */ + static inline unsigned char rtc_is_updating(void) + { ++ unsigned long flags; + unsigned char uip; + +- spin_lock_irq(&rtc_lock); ++ spin_lock_irqsave(&rtc_lock, flags); + uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); +- spin_unlock_irq(&rtc_lock); ++ spin_unlock_irqrestore(&rtc_lock, flags); + return uip; + } + +diff --git a/drivers/clocksource/scx200_hrt.c b/drivers/clocksource/scx200_hrt.c +index d418b82..22915cc 100644 +--- a/drivers/clocksource/scx200_hrt.c ++++ b/drivers/clocksource/scx200_hrt.c +@@ -63,7 +63,7 @@ static struct clocksource cs_hrt = { + + static int __init init_hrt_clocksource(void) + { +- /* Make sure scx200 has initializedd the configuration block */ ++ /* Make sure scx200 has initialized the configuration block */ + if (!scx200_cb_present()) + return -ENODEV; + +@@ -76,7 +76,7 @@ static int __init init_hrt_clocksource(v + } + + /* write timer config */ +- outb(HR_TMEN | (mhz27) ? HR_TMCLKSEL : 0, ++ outb(HR_TMEN | (mhz27 ? HR_TMCLKSEL : 0), + scx200_cb_base + SCx200_TMCNFG_OFFSET); + + if (mhz27) { +diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c +index 25eee53..c2ecc59 100644 +--- a/drivers/cpufreq/cpufreq_stats.c ++++ b/drivers/cpufreq/cpufreq_stats.c +@@ -350,12 +350,10 @@ __init cpufreq_stats_init(void) + } + + register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); +- lock_cpu_hotplug(); + for_each_online_cpu(cpu) { + cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, + (void *)(long)cpu); + } +- unlock_cpu_hotplug(); + return 0; + } + static void +diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c +index 78810ba..6a1ddad 100644 +--- a/drivers/ide/pci/generic.c ++++ b/drivers/ide/pci/generic.c +@@ -245,10 +245,12 @@ static int __devinit generic_init_one(st + if (dev->vendor == PCI_VENDOR_ID_JMICRON && PCI_FUNC(dev->devfn) != 1) + goto out; + +- pci_read_config_word(dev, PCI_COMMAND, &command); +- if (!(command & PCI_COMMAND_IO)) { +- printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name); +- goto out; ++ if (dev->vendor != PCI_VENDOR_ID_JMICRON) { ++ pci_read_config_word(dev, PCI_COMMAND, &command); ++ if (!(command & PCI_COMMAND_IO)) { ++ printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name); ++ goto out; ++ } + } + ret = ide_setup_pci_device(dev, d); + out: +diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c +index ebf961f..15b89e8 100644 +--- a/drivers/ide/ppc/pmac.c ++++ b/drivers/ide/ppc/pmac.c +@@ -1326,7 +1326,7 @@ pmac_ide_macio_attach(struct macio_dev * + if (macio_irq_count(mdev) == 0) { + printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n", + i, mdev->ofdev.node->full_name); +- irq = 13; ++ irq = irq_create_mapping(NULL, 13); + } else + irq = macio_irq(mdev, 0); + +diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c +index d9bc030..45e106f 100644 +--- a/drivers/infiniband/hw/mthca/mthca_mad.c ++++ b/drivers/infiniband/hw/mthca/mthca_mad.c +@@ -119,7 +119,7 @@ static void smp_snoop(struct ib_device * + + mthca_update_rate(to_mdev(ibdev), port_num); + update_sm_ah(to_mdev(ibdev), port_num, +- be16_to_cpu(pinfo->lid), ++ be16_to_cpu(pinfo->sm_lid), + pinfo->neighbormtu_mastersmsl & 0xf); + + event.device = ibdev; +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 8dbab2e..c9d2919 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -3867,6 +3867,7 @@ static int hot_add_disk(mddev_t * mddev, + } + clear_bit(In_sync, &rdev->flags); + rdev->desc_nr = -1; ++ rdev->saved_raid_disk = -1; + err = bind_rdev_to_array(rdev, mddev); + if (err) + goto abort_export; +diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c +index 274a87b..1e7e790 100644 +--- a/drivers/media/dvb/frontends/cx24123.c ++++ b/drivers/media/dvb/frontends/cx24123.c +@@ -549,8 +549,8 @@ static int cx24123_pll_calculate(struct + ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff; + adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f; + +- if (adiv == 0) +- ndiv++; ++ if (adiv == 0 && ndiv > 0) ++ ndiv--; + + /* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */ + state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv; +diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c +index 56246b8..cf43df3 100644 +--- a/drivers/media/video/msp3400-driver.c ++++ b/drivers/media/video/msp3400-driver.c +@@ -904,6 +904,8 @@ static int msp_attach(struct i2c_adapter + state->has_virtual_dolby_surround = msp_revision == 'G' && msp_prod_lo == 1; + /* Has Virtual Dolby Surround & Dolby Pro Logic: only in msp34x2 */ + state->has_dolby_pro_logic = msp_revision == 'G' && msp_prod_lo == 2; ++ /* The msp343xG supports BTSC only and cannot do Automatic Standard Detection. */ ++ state->force_btsc = msp_family == 3 && msp_revision == 'G' && msp_prod_hi == 3; + + state->opmode = opmode; + if (state->opmode == OPMODE_AUTO) { +diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h +index 545e4ac..7531efa 100644 +--- a/drivers/media/video/msp3400-driver.h ++++ b/drivers/media/video/msp3400-driver.h +@@ -64,6 +64,7 @@ struct msp_state { + u8 has_sound_processing; + u8 has_virtual_dolby_surround; + u8 has_dolby_pro_logic; ++ u8 force_btsc; + + int radio; + int opmode; +diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c +index ed02ff8..4c7f85b 100644 +--- a/drivers/media/video/msp3400-kthreads.c ++++ b/drivers/media/video/msp3400-kthreads.c +@@ -960,9 +960,10 @@ int msp34xxg_thread(void *data) + + /* setup the chip*/ + msp34xxg_reset(client); +- state->std = state->radio ? 0x40 : msp_standard; +- /* start autodetect */ ++ state->std = state->radio ? 0x40 : ++ (state->force_btsc && msp_standard == 1) ? 32 : msp_standard; + msp_write_dem(client, 0x20, state->std); ++ /* start autodetect */ + if (state->std != 1) + goto unmute; + +diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig +index 7e727fe..e43a979 100644 +--- a/drivers/media/video/pvrusb2/Kconfig ++++ b/drivers/media/video/pvrusb2/Kconfig +@@ -25,14 +25,9 @@ config VIDEO_PVRUSB2_24XXX + form "24xxx" (leading prefix of "24" followed by 3 digits). + To see if you may need this option, examine the white + sticker on the underside of your device. Enabling this +- option will not harm support for older devices, however it +- is a separate option because of the experimental nature of +- this new feature. ++ option will not harm support for older devices. + +- If you are in doubt, say N. +- +- Note: This feature is _very_ experimental. You have been +- warned. ++ If you are in doubt, say Y. + + config VIDEO_PVRUSB2_SYSFS + bool "pvrusb2 sysfs support (EXPERIMENTAL)" +diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +index fb6198f..c77de85 100644 +--- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c ++++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +@@ -43,12 +43,17 @@ int pvr2_ctrl_set_mask_value(struct pvr2 + if (cptr->info->type == pvr2_ctl_bitmask) { + mask &= cptr->info->def.type_bitmask.valid_bits; + } else if (cptr->info->type == pvr2_ctl_int) { +- if (val < cptr->info->def.type_int.min_value) { +- break; ++ int lim; ++ lim = cptr->info->def.type_int.min_value; ++ if (cptr->info->get_min_value) { ++ cptr->info->get_min_value(cptr,&lim); + } +- if (val > cptr->info->def.type_int.max_value) { +- break; ++ if (val < lim) break; ++ lim = cptr->info->def.type_int.max_value; ++ if (cptr->info->get_max_value) { ++ cptr->info->get_max_value(cptr,&lim); + } ++ if (val > lim) break; + } else if (cptr->info->type == pvr2_ctl_enum) { + if (val >= cptr->info->def.type_enum.count) { + break; +@@ -91,7 +96,9 @@ int pvr2_ctrl_get_max(struct pvr2_ctrl * + int ret = 0; + if (!cptr) return 0; + LOCK_TAKE(cptr->hdw->big_lock); do { +- if (cptr->info->type == pvr2_ctl_int) { ++ if (cptr->info->get_max_value) { ++ cptr->info->get_max_value(cptr,&ret); ++ } else if (cptr->info->type == pvr2_ctl_int) { + ret = cptr->info->def.type_int.max_value; + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); +@@ -105,7 +112,9 @@ int pvr2_ctrl_get_min(struct pvr2_ctrl * + int ret = 0; + if (!cptr) return 0; + LOCK_TAKE(cptr->hdw->big_lock); do { +- if (cptr->info->type == pvr2_ctl_int) { ++ if (cptr->info->get_min_value) { ++ cptr->info->get_min_value(cptr,&ret); ++ } else if (cptr->info->type == pvr2_ctl_int) { + ret = cptr->info->def.type_int.min_value; + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); +diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +index 0d6dc33..9a72e6a 100644 +--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h ++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h +@@ -107,6 +107,8 @@ struct pvr2_ctl_info { + + /* Control's implementation */ + pvr2_ctlf_get_value get_value; /* Get its value */ ++ pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ ++ pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ + pvr2_ctlf_set_value set_value; /* Set its value */ + pvr2_ctlf_val_to_sym val_to_sym; /* Custom convert value->symbol */ + pvr2_ctlf_sym_to_val sym_to_val; /* Custom convert symbol->value */ +diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c +index be1e5cc..a36a69d 100644 +--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c ++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c +@@ -362,6 +362,30 @@ static int ctrl_freq_set(struct pvr2_ctr + return 0; + } + ++#ifdef CONFIG_VIDEO_PVRUSB2_24XXX ++static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp) ++{ ++ /* If we're dealing with a 24xxx device, force the horizontal ++ maximum to be 720 no matter what, since we can't get the device ++ to work properly with any other value. Otherwise just return ++ the normal value. */ ++ *vp = cptr->info->def.type_int.max_value; ++ if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; ++ return 0; ++} ++ ++static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp) ++{ ++ /* If we're dealing with a 24xxx device, force the horizontal ++ minimum to be 720 no matter what, since we can't get the device ++ to work properly with any other value. Otherwise just return ++ the normal value. */ ++ *vp = cptr->info->def.type_int.min_value; ++ if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; ++ return 0; ++} ++#endif ++ + static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr) + { + return cptr->hdw->enc_stale != 0; +@@ -720,6 +744,12 @@ static const struct pvr2_ctl_info contro + .default_value = 720, + DEFREF(res_hor), + DEFINT(320,720), ++#ifdef CONFIG_VIDEO_PVRUSB2_24XXX ++ /* Hook in check for clamp on horizontal resolution in ++ order to avoid unsolved problem involving cx25840. */ ++ .get_max_value = ctrl_hres_max_get, ++ .get_min_value = ctrl_hres_min_get, ++#endif + },{ + .desc = "Vertical capture resolution", + .name = "resolution_ver", +diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +index 0caf70b..72f444c 100644 +--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c ++++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +@@ -22,6 +22,7 @@ + + #include + #include ++#include + #include "pvrusb2-context.h" + #include "pvrusb2-hdw.h" + #include "pvrusb2.h" +@@ -31,25 +32,21 @@ #include "pvrusb2-ioread.h" + #include + #include + ++/* Mike Isely 23-Sep-2006 - This function is prototyped ++ * only for V4L1 but is implemented regardless of the V4L1 compatibility ++ * option state. V4L2 has no replacement for this and we need it. For now ++ * copy the prototype here so we can avoid the compiler warning. */ ++extern struct video_device* video_devdata(struct file*); ++ + struct pvr2_v4l2_dev; + struct pvr2_v4l2_fh; + struct pvr2_v4l2; + +-/* V4L no longer provide the ability to set / get a private context pointer +- (i.e. video_get_drvdata / video_set_drvdata), which means we have to +- concoct our own context locating mechanism. Supposedly this is intended +- to simplify driver implementation. It's not clear to me how that can +- possibly be true. Our solution here is to maintain a lookup table of +- our context instances, indexed by the minor device number of the V4L +- device. See pvr2_v4l2_open() for some implications of this approach. */ +-static struct pvr2_v4l2_dev *devices[256]; +-static DEFINE_MUTEX(device_lock); + + struct pvr2_v4l2_dev { + struct pvr2_v4l2 *v4lp; + struct video_device *vdev; + struct pvr2_context_stream *stream; +- int ctxt_idx; + enum pvr2_config config; + }; + +@@ -459,18 +456,26 @@ static int pvr2_v4l2_do_ioctl(struct ino + ret = 0; + switch(vf->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: { ++ int lmin,lmax; ++ struct pvr2_ctrl *hcp,*vcp; + int h = vf->fmt.pix.height; + int w = vf->fmt.pix.width; +- +- if (h < 200) { +- h = 200; +- } else if (h > 625) { +- h = 625; ++ hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES); ++ vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES); ++ ++ lmin = pvr2_ctrl_get_min(hcp); ++ lmax = pvr2_ctrl_get_max(hcp); ++ if (w < lmin) { ++ w = lmin; ++ } else if (w > lmax) { ++ w = lmax; + } +- if (w < 320) { +- w = 320; +- } else if (w > 720) { +- w = 720; ++ lmin = pvr2_ctrl_get_min(vcp); ++ lmax = pvr2_ctrl_get_max(vcp); ++ if (h < lmin) { ++ h = lmin; ++ } else if (h > lmax) { ++ h = lmax; + } + + memcpy(vf, &pvr_format[PVR_FORMAT_PIX], +@@ -479,14 +484,8 @@ static int pvr2_v4l2_do_ioctl(struct ino + vf->fmt.pix.height = h; + + if (cmd == VIDIOC_S_FMT) { +- pvr2_ctrl_set_value( +- pvr2_hdw_get_ctrl_by_id(hdw, +- PVR2_CID_HRES), +- vf->fmt.pix.width); +- pvr2_ctrl_set_value( +- pvr2_hdw_get_ctrl_by_id(hdw, +- PVR2_CID_VRES), +- vf->fmt.pix.height); ++ pvr2_ctrl_set_value(hcp,vf->fmt.pix.width); ++ pvr2_ctrl_set_value(vcp,vf->fmt.pix.height); + } + } break; + case V4L2_BUF_TYPE_VBI_CAPTURE: +@@ -703,12 +702,6 @@ static void pvr2_v4l2_dev_destroy(struct + { + printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n", + dip->vdev->minor,pvr2_config_get_name(dip->config)); +- if (dip->ctxt_idx >= 0) { +- mutex_lock(&device_lock); +- devices[dip->ctxt_idx] = NULL; +- dip->ctxt_idx = -1; +- mutex_unlock(&device_lock); +- } + video_unregister_device(dip->vdev); + } + +@@ -800,33 +793,10 @@ static int pvr2_v4l2_open(struct inode * + struct pvr2_v4l2 *vp; + struct pvr2_hdw *hdw; + +- mutex_lock(&device_lock); +- /* MCI 7-Jun-2006 Even though we're just doing what amounts to an +- atomic read of the device mapping array here, we still need the +- mutex. The problem is that there is a tiny race possible when +- we register the device. We can't update the device mapping +- array until after the device has been registered, owing to the +- fact that we can't know the minor device number until after the +- registration succeeds. And if another thread tries to open the +- device in the window of time after registration but before the +- map is updated, then it will get back an erroneous null pointer +- and the open will result in a spurious failure. The only way to +- prevent that is to (a) be inside the mutex here before we access +- the array, and (b) cover the entire registration process later +- on with this same mutex. Thus if we get inside the mutex here, +- then we can be assured that the registration process actually +- completed correctly. This is an unhappy complication from the +- use of global data in a driver that lives in a preemptible +- environment. It sure would be nice if the video device itself +- had a means for storing and retrieving a local context pointer. +- Oh wait. It did. But now it's gone. Silly me. */ + { +- unsigned int midx = iminor(file->f_dentry->d_inode); +- if (midx < sizeof(devices)/sizeof(devices[0])) { +- dip = devices[midx]; +- } ++ struct video_device *vdev = video_devdata(file); ++ dip = (struct pvr2_v4l2_dev *)video_get_drvdata(vdev); + } +- mutex_unlock(&device_lock); + + if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */ + +@@ -1066,7 +1036,7 @@ static void pvr2_v4l2_dev_init(struct pv + + memcpy(dip->vdev,&vdev_template,sizeof(vdev_template)); + dip->vdev->release = video_device_release; +- mutex_lock(&device_lock); ++ video_set_drvdata(dip->vdev,dip); + + mindevnum = -1; + unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw); +@@ -1081,12 +1051,6 @@ static void pvr2_v4l2_dev_init(struct pv + dip->vdev->minor,pvr2_config_get_name(dip->config)); + } + +- if ((dip->vdev->minor < sizeof(devices)/sizeof(devices[0])) && +- (devices[dip->vdev->minor] == NULL)) { +- dip->ctxt_idx = dip->vdev->minor; +- devices[dip->ctxt_idx] = dip; +- } +- mutex_unlock(&device_lock); + + pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, + dip->vdev->minor); +@@ -1100,7 +1064,6 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struc + vp = kmalloc(sizeof(*vp),GFP_KERNEL); + if (!vp) return vp; + memset(vp,0,sizeof(*vp)); +- vp->video_dev.ctxt_idx = -1; + pvr2_channel_init(&vp->channel,mnp); + pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); + +diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c +index 88bf2af..2299e29 100644 +--- a/drivers/media/video/videodev.c ++++ b/drivers/media/video/videodev.c +@@ -739,13 +739,13 @@ static int __video_do_ioctl(struct inode + case VIDIOC_DQBUF: + { + struct v4l2_buffer *p=arg; +- if (!vfd->vidioc_qbuf) ++ if (!vfd->vidioc_dqbuf) + break; + ret = check_fmt (vfd, p->type); + if (ret) + break; + +- ret=vfd->vidioc_qbuf(file, fh, p); ++ ret=vfd->vidioc_dqbuf(file, fh, p); + if (!ret) + dbgbuf(cmd,vfd,p); + break; +@@ -836,7 +836,7 @@ #endif + break; + } + +- if (index<=0 || index >= vfd->tvnormsize) { ++ if (index < 0 || index >= vfd->tvnormsize) { + ret=-EINVAL; + break; + } +diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c +index b783a69..393aba9 100644 +--- a/drivers/net/lp486e.c ++++ b/drivers/net/lp486e.c +@@ -442,16 +442,16 @@ #if 0 + if (rbd) { + rbd->pad = 0; + rbd->count = 0; +- rbd->skb = dev_alloc_skb(RX_SKB_SIZE); ++ rbd->skb = dev_alloc_skb(RX_SKBSIZE); + if (!rbd->skb) { + printk("dev_alloc_skb failed"); + } + rbd->next = rfd->rbd; + if (i) { + rfd->rbd->prev = rbd; +- rbd->size = RX_SKB_SIZE; ++ rbd->size = RX_SKBSIZE; + } else { +- rbd->size = (RX_SKB_SIZE | RBD_EL); ++ rbd->size = (RX_SKBSIZE | RBD_EL); + lp->rbd_tail = rbd; + } + +diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c +index eeab1df..59de3e7 100644 +--- a/drivers/net/mv643xx_eth.c ++++ b/drivers/net/mv643xx_eth.c +@@ -385,7 +385,7 @@ static int mv643xx_eth_receive_queue(str + struct pkt_info pkt_info; + + while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) { +- dma_unmap_single(NULL, pkt_info.buf_ptr, RX_SKB_SIZE, ++ dma_unmap_single(NULL, pkt_info.buf_ptr, ETH_RX_SKB_SIZE, + DMA_FROM_DEVICE); + mp->rx_desc_count--; + received_packets++; +diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c +index 933e87f..c590c2d 100644 +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -106,6 +106,7 @@ static const struct pci_device_id sky2_i + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, + { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ ++ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, /* DGE-550SX */ + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, +@@ -117,10 +118,17 @@ static const struct pci_device_id sky2_i + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, ++ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, + { 0 } + }; + +diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h +index 2db8d19..ac5248b 100644 +--- a/drivers/net/sky2.h ++++ b/drivers/net/sky2.h +@@ -1566,7 +1566,7 @@ enum { + + GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR | + GMR_FS_FRAGMENT | GMR_FS_LONG_ERR | +- GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC | ++ GMR_FS_MII_ERR | GMR_FS_BAD_FC | + GMR_FS_UN_SIZE | GMR_FS_JABBER, + }; + +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h +index 17a5682..6d4ea36 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx.h ++++ b/drivers/net/wireless/bcm43xx/bcm43xx.h +@@ -33,14 +33,18 @@ #define BCM43xx_PCICFG_SPROMCTL 0x88 + #define BCM43xx_PCICFG_ICR 0x94 + + /* MMIO offsets */ +-#define BCM43xx_MMIO_DMA1_REASON 0x20 +-#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x24 +-#define BCM43xx_MMIO_DMA2_REASON 0x28 +-#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x2C +-#define BCM43xx_MMIO_DMA3_REASON 0x30 +-#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x34 +-#define BCM43xx_MMIO_DMA4_REASON 0x38 +-#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x3C ++#define BCM43xx_MMIO_DMA0_REASON 0x20 ++#define BCM43xx_MMIO_DMA0_IRQ_MASK 0x24 ++#define BCM43xx_MMIO_DMA1_REASON 0x28 ++#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x2C ++#define BCM43xx_MMIO_DMA2_REASON 0x30 ++#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x34 ++#define BCM43xx_MMIO_DMA3_REASON 0x38 ++#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x3C ++#define BCM43xx_MMIO_DMA4_REASON 0x40 ++#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x44 ++#define BCM43xx_MMIO_DMA5_REASON 0x48 ++#define BCM43xx_MMIO_DMA5_IRQ_MASK 0x4C + #define BCM43xx_MMIO_STATUS_BITFIELD 0x120 + #define BCM43xx_MMIO_STATUS2_BITFIELD 0x124 + #define BCM43xx_MMIO_GEN_IRQ_REASON 0x128 +@@ -56,14 +60,27 @@ #define BCM43xx_MMIO_XMITSTAT_0 0x170 + #define BCM43xx_MMIO_XMITSTAT_1 0x174 + #define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ + #define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ +-#define BCM43xx_MMIO_DMA1_BASE 0x200 +-#define BCM43xx_MMIO_DMA2_BASE 0x220 +-#define BCM43xx_MMIO_DMA3_BASE 0x240 +-#define BCM43xx_MMIO_DMA4_BASE 0x260 ++ ++/* 32-bit DMA */ ++#define BCM43xx_MMIO_DMA32_BASE0 0x200 ++#define BCM43xx_MMIO_DMA32_BASE1 0x220 ++#define BCM43xx_MMIO_DMA32_BASE2 0x240 ++#define BCM43xx_MMIO_DMA32_BASE3 0x260 ++#define BCM43xx_MMIO_DMA32_BASE4 0x280 ++#define BCM43xx_MMIO_DMA32_BASE5 0x2A0 ++/* 64-bit DMA */ ++#define BCM43xx_MMIO_DMA64_BASE0 0x200 ++#define BCM43xx_MMIO_DMA64_BASE1 0x240 ++#define BCM43xx_MMIO_DMA64_BASE2 0x280 ++#define BCM43xx_MMIO_DMA64_BASE3 0x2C0 ++#define BCM43xx_MMIO_DMA64_BASE4 0x300 ++#define BCM43xx_MMIO_DMA64_BASE5 0x340 ++/* PIO */ + #define BCM43xx_MMIO_PIO1_BASE 0x300 + #define BCM43xx_MMIO_PIO2_BASE 0x310 + #define BCM43xx_MMIO_PIO3_BASE 0x320 + #define BCM43xx_MMIO_PIO4_BASE 0x330 ++ + #define BCM43xx_MMIO_PHY_VER 0x3E0 + #define BCM43xx_MMIO_PHY_RADIO 0x3E2 + #define BCM43xx_MMIO_ANTENNA 0x3E8 +@@ -233,8 +250,14 @@ #define BCM43xx_SBTMSTATELOW_CLOCK 0x10 + #define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000 + + /* sbtmstatehigh state flags */ +-#define BCM43xx_SBTMSTATEHIGH_SERROR 0x1 +-#define BCM43xx_SBTMSTATEHIGH_BUSY 0x4 ++#define BCM43xx_SBTMSTATEHIGH_SERROR 0x00000001 ++#define BCM43xx_SBTMSTATEHIGH_BUSY 0x00000004 ++#define BCM43xx_SBTMSTATEHIGH_TIMEOUT 0x00000020 ++#define BCM43xx_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000 ++#define BCM43xx_SBTMSTATEHIGH_DMA64BIT 0x10000000 ++#define BCM43xx_SBTMSTATEHIGH_GATEDCLK 0x20000000 ++#define BCM43xx_SBTMSTATEHIGH_BISTFAILED 0x40000000 ++#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000 + + /* sbimstate flags */ + #define BCM43xx_SBIMSTATE_IB_ERROR 0x20000 +@@ -283,6 +306,13 @@ #define BCM43xx_SBF_NO_SSID_BCAST 0x0800 + #define BCM43xx_SBF_TIME_UPDATE 0x10000000 + #define BCM43xx_SBF_80000000 0x80000000 /*FIXME: fix name*/ + ++/* Microcode */ ++#define BCM43xx_UCODE_REVISION 0x0000 ++#define BCM43xx_UCODE_PATCHLEVEL 0x0002 ++#define BCM43xx_UCODE_DATE 0x0004 ++#define BCM43xx_UCODE_TIME 0x0006 ++#define BCM43xx_UCODE_STATUS 0x0040 ++ + /* MicrocodeFlagsBitfield (addr + lo-word values?)*/ + #define BCM43xx_UCODEFLAGS_OFFSET 0x005E + +@@ -504,6 +534,12 @@ struct bcm43xx_phyinfo { + * This lock is only used by bcm43xx_phy_{un}lock() + */ + spinlock_t lock; ++ ++ /* Firmware. */ ++ const struct firmware *ucode; ++ const struct firmware *pcm; ++ const struct firmware *initvals0; ++ const struct firmware *initvals1; + }; + + +@@ -568,8 +604,11 @@ struct bcm43xx_dma { + struct bcm43xx_dmaring *tx_ring1; + struct bcm43xx_dmaring *tx_ring2; + struct bcm43xx_dmaring *tx_ring3; ++ struct bcm43xx_dmaring *tx_ring4; ++ struct bcm43xx_dmaring *tx_ring5; ++ + struct bcm43xx_dmaring *rx_ring0; +- struct bcm43xx_dmaring *rx_ring1; /* only available on core.rev < 5 */ ++ struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */ + }; + + /* Data structures for PIO transmission, per 80211 core. */ +@@ -593,12 +632,14 @@ struct bcm43xx_coreinfo { + u8 available:1, + enabled:1, + initialized:1; +- /** core_id ID number */ +- u16 id; + /** core_rev revision number */ + u8 rev; + /** Index number for _switch_core() */ + u8 index; ++ /** core_id ID number */ ++ u16 id; ++ /** Core-specific data. */ ++ void *priv; + }; + + /* Additional information for each 80211 core. */ +@@ -647,7 +688,23 @@ enum { + BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ + }; + #define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) +-#define bcm43xx_set_status(bcm, stat) atomic_set(&(bcm)->init_status, (stat)) ++#define bcm43xx_set_status(bcm, stat) do { \ ++ atomic_set(&(bcm)->init_status, (stat)); \ ++ smp_wmb(); \ ++ } while (0) ++ ++/* *** THEORY OF LOCKING *** ++ * ++ * We have two different locks in the bcm43xx driver. ++ * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private ++ * and the device registers. This mutex does _not_ protect ++ * against concurrency from the IRQ handler. ++ * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. ++ * ++ * Please note that, if you only take the irq_lock, you are not protected ++ * against concurrency from the periodic work handlers. ++ * Most times you want to take _both_ locks. ++ */ + + struct bcm43xx_private { + struct ieee80211_device *ieee; +@@ -659,7 +716,6 @@ struct bcm43xx_private { + + void __iomem *mmio_addr; + +- /* Locking, see "theory of locking" text below. */ + spinlock_t irq_lock; + struct mutex mutex; + +@@ -691,6 +747,7 @@ struct bcm43xx_private { + struct bcm43xx_sprominfo sprom; + #define BCM43xx_NR_LEDS 4 + struct bcm43xx_led leds[BCM43xx_NR_LEDS]; ++ spinlock_t leds_lock; + + /* The currently active core. */ + struct bcm43xx_coreinfo *current_core; +@@ -708,10 +765,6 @@ #endif + struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; + /* Additional information, specific to the 80211 cores. */ + struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ]; +- /* Index of the current 80211 core. If current_core is not +- * an 80211 core, this is -1. +- */ +- int current_80211_core_idx; + /* Number of available 80211 cores. */ + int nr_80211_available; + +@@ -719,11 +772,13 @@ #endif + + /* Reason code of the last interrupt. */ + u32 irq_reason; +- u32 dma_reason[4]; ++ u32 dma_reason[6]; + /* saved irq enable/disable state bitfield. */ + u32 irq_savedstate; + /* Link Quality calculation context. */ + struct bcm43xx_noise_calculation noisecalc; ++ /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ ++ int mac_suspended; + + /* Threshold values. */ + //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. +@@ -746,12 +801,6 @@ #endif + struct bcm43xx_key key[54]; + u8 default_key_idx; + +- /* Firmware. */ +- const struct firmware *ucode; +- const struct firmware *pcm; +- const struct firmware *initvals0; +- const struct firmware *initvals1; +- + /* Random Number Generator. */ + struct hwrng rng; + char rng_name[20 + 1]; +@@ -763,55 +812,6 @@ #endif + }; + + +-/* *** THEORY OF LOCKING *** +- * +- * We have two different locks in the bcm43xx driver. +- * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private +- * and the device registers. +- * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. +- * +- * We have three types of helper function pairs to utilize these locks. +- * (Always use the helper functions.) +- * 1) bcm43xx_{un}lock_noirq(): +- * Takes bcm->mutex. Does _not_ protect against IRQ concurrency, +- * so it is almost always unsafe, if device IRQs are enabled. +- * So only use this, if device IRQs are masked. +- * Locking may sleep. +- * You can sleep within the critical section. +- * 2) bcm43xx_{un}lock_irqonly(): +- * Takes bcm->irq_lock. Does _not_ protect against +- * bcm43xx_lock_noirq() critical sections. +- * Does only protect against the IRQ handler path and other +- * irqonly() critical sections. +- * Locking does not sleep. +- * You must not sleep within the critical section. +- * 3) bcm43xx_{un}lock_irqsafe(): +- * This is the cummulative lock and takes both, mutex and irq_lock. +- * Protects against noirq() and irqonly() critical sections (and +- * the IRQ handler path). +- * Locking may sleep. +- * You must not sleep within the critical section. +- */ +- +-/* Lock type 1 */ +-#define bcm43xx_lock_noirq(bcm) mutex_lock(&(bcm)->mutex) +-#define bcm43xx_unlock_noirq(bcm) mutex_unlock(&(bcm)->mutex) +-/* Lock type 2 */ +-#define bcm43xx_lock_irqonly(bcm, flags) \ +- spin_lock_irqsave(&(bcm)->irq_lock, flags) +-#define bcm43xx_unlock_irqonly(bcm, flags) \ +- spin_unlock_irqrestore(&(bcm)->irq_lock, flags) +-/* Lock type 3 */ +-#define bcm43xx_lock_irqsafe(bcm, flags) do { \ +- bcm43xx_lock_noirq(bcm); \ +- bcm43xx_lock_irqonly(bcm, flags); \ +- } while (0) +-#define bcm43xx_unlock_irqsafe(bcm, flags) do { \ +- bcm43xx_unlock_irqonly(bcm, flags); \ +- bcm43xx_unlock_noirq(bcm); \ +- } while (0) +- +- + static inline + struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) + { +@@ -863,34 +863,33 @@ #endif + * any of these functions. + */ + static inline ++struct bcm43xx_coreinfo_80211 * ++bcm43xx_current_80211_priv(struct bcm43xx_private *bcm) ++{ ++ assert(bcm->current_core->id == BCM43xx_COREID_80211); ++ return bcm->current_core->priv; ++} ++static inline + struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm) + { + assert(bcm43xx_using_pio(bcm)); +- assert(bcm->current_80211_core_idx >= 0); +- assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); +- return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio); ++ return &(bcm43xx_current_80211_priv(bcm)->pio); + } + static inline + struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm) + { + assert(!bcm43xx_using_pio(bcm)); +- assert(bcm->current_80211_core_idx >= 0); +- assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); +- return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma); ++ return &(bcm43xx_current_80211_priv(bcm)->dma); + } + static inline + struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm) + { +- assert(bcm->current_80211_core_idx >= 0); +- assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); +- return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy); ++ return &(bcm43xx_current_80211_priv(bcm)->phy); + } + static inline + struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) + { +- assert(bcm->current_80211_core_idx >= 0); +- assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES); +- return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio); ++ return &(bcm43xx_current_80211_priv(bcm)->radio); + } + + +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +index ce2e40b..923275e 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +@@ -77,7 +77,8 @@ static ssize_t devinfo_read_file(struct + + down(&big_buffer_sem); + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { + fappend("Board not initialized.\n"); + goto out; +@@ -121,7 +122,8 @@ #undef fappend_core + fappend("\n"); + + out: +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +@@ -159,7 +161,8 @@ static ssize_t spromdump_read_file(struc + unsigned long flags; + + down(&big_buffer_sem); +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { + fappend("Board not initialized.\n"); + goto out; +@@ -169,7 +172,8 @@ static ssize_t spromdump_read_file(struc + fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); + + out: +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +@@ -188,7 +192,8 @@ static ssize_t tsf_read_file(struct file + u64 tsf; + + down(&big_buffer_sem); +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { + fappend("Board not initialized.\n"); + goto out; +@@ -199,7 +204,8 @@ static ssize_t tsf_read_file(struct file + (unsigned int)(tsf & 0xFFFFFFFFULL)); + + out: +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + up(&big_buffer_sem); + return res; +@@ -221,7 +227,8 @@ static ssize_t tsf_write_file(struct fil + res = -EFAULT; + goto out_up; + } +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { + printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); + res = -EFAULT; +@@ -237,7 +244,8 @@ static ssize_t tsf_write_file(struct fil + res = buf_size; + + out_unlock: +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + out_up: + up(&big_buffer_sem); + return res; +@@ -258,7 +266,8 @@ static ssize_t txstat_read_file(struct f + int i, cnt, j = 0; + + down(&big_buffer_sem); +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + + fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", + BCM43xx_NR_LOGGED_XMITSTATUS); +@@ -294,14 +303,51 @@ static ssize_t txstat_read_file(struct f + i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; + } + +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); + res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); +- bcm43xx_lock_irqsafe(bcm, flags); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (*ppos == pos) { + /* Done. Drop the copied data. */ + e->xmitstatus_printing = 0; + } +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); ++ up(&big_buffer_sem); ++ return res; ++} ++ ++static ssize_t restart_write_file(struct file *file, const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct bcm43xx_private *bcm = file->private_data; ++ char *buf = really_big_buffer; ++ ssize_t buf_size; ++ ssize_t res; ++ unsigned long flags; ++ ++ buf_size = min(count, sizeof (really_big_buffer) - 1); ++ down(&big_buffer_sem); ++ if (copy_from_user(buf, user_buf, buf_size)) { ++ res = -EFAULT; ++ goto out_up; ++ } ++ mutex_lock(&(bcm)->mutex); ++ spin_lock_irqsave(&(bcm)->irq_lock, flags); ++ if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { ++ printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); ++ res = -EFAULT; ++ goto out_unlock; ++ } ++ if (count > 0 && buf[0] == '1') { ++ bcm43xx_controller_restart(bcm, "manually restarted"); ++ res = count; ++ } else ++ res = -EINVAL; ++ ++out_unlock: ++ spin_unlock_irqrestore(&(bcm)->irq_lock, flags); ++ mutex_unlock(&(bcm)->mutex); ++out_up: + up(&big_buffer_sem); + return res; + } +@@ -339,6 +385,11 @@ static struct file_operations txstat_fop + .open = open_file_generic, + }; + ++static struct file_operations restart_fops = { ++ .write = restart_write_file, ++ .open = open_file_generic, ++}; ++ + + void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) + { +@@ -390,6 +441,10 @@ void bcm43xx_debugfs_add_device(struct b + bcm, &txstat_fops); + if (!e->dentry_txstat) + printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); ++ e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir, ++ bcm, &restart_fops); ++ if (!e->dentry_restart) ++ printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir); + } + + void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) +@@ -405,6 +460,7 @@ void bcm43xx_debugfs_remove_device(struc + debugfs_remove(e->dentry_devinfo); + debugfs_remove(e->dentry_tsf); + debugfs_remove(e->dentry_txstat); ++ debugfs_remove(e->dentry_restart); + debugfs_remove(e->subdir); + kfree(e->xmitstatus_buffer); + kfree(e->xmitstatus_print_buffer); +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h +index 50ce267..a40d1af 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h +@@ -20,6 +20,7 @@ struct bcm43xx_dfsentry { + struct dentry *dentry_spromdump; + struct dentry *dentry_tsf; + struct dentry *dentry_txstat; ++ struct dentry *dentry_restart; + + struct bcm43xx_private *bcm; + +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +index d0318e5..76e3aed 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +@@ -4,7 +4,7 @@ + + DMA ringbuffer and descriptor allocation/management + +- Copyright (c) 2005 Michael Buesch ++ Copyright (c) 2005, 2006 Michael Buesch + + Some code in this file is derived from the b44.c driver + Copyright (C) 2002 David S. Miller +@@ -109,6 +109,35 @@ void return_slot(struct bcm43xx_dmaring + } + } + ++u16 bcm43xx_dmacontroller_base(int dma64bit, int controller_idx) ++{ ++ static const u16 map64[] = { ++ BCM43xx_MMIO_DMA64_BASE0, ++ BCM43xx_MMIO_DMA64_BASE1, ++ BCM43xx_MMIO_DMA64_BASE2, ++ BCM43xx_MMIO_DMA64_BASE3, ++ BCM43xx_MMIO_DMA64_BASE4, ++ BCM43xx_MMIO_DMA64_BASE5, ++ }; ++ static const u16 map32[] = { ++ BCM43xx_MMIO_DMA32_BASE0, ++ BCM43xx_MMIO_DMA32_BASE1, ++ BCM43xx_MMIO_DMA32_BASE2, ++ BCM43xx_MMIO_DMA32_BASE3, ++ BCM43xx_MMIO_DMA32_BASE4, ++ BCM43xx_MMIO_DMA32_BASE5, ++ }; ++ ++ if (dma64bit) { ++ assert(controller_idx >= 0 && ++ controller_idx < ARRAY_SIZE(map64)); ++ return map64[controller_idx]; ++ } ++ assert(controller_idx >= 0 && ++ controller_idx < ARRAY_SIZE(map32)); ++ return map32[controller_idx]; ++} ++ + static inline + dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring, + unsigned char *buf, +@@ -172,7 +201,6 @@ void sync_descbuffer_for_device(struct b + /* Unmap and free a descriptor buffer. */ + static inline + void free_descriptor_buffer(struct bcm43xx_dmaring *ring, +- struct bcm43xx_dmadesc *desc, + struct bcm43xx_dmadesc_meta *meta, + int irq_context) + { +@@ -188,23 +216,13 @@ static int alloc_ringmemory(struct bcm43 + { + struct device *dev = &(ring->bcm->pci_dev->dev); + +- ring->vbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, +- &(ring->dmabase), GFP_KERNEL); +- if (!ring->vbase) { ++ ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, ++ &(ring->dmabase), GFP_KERNEL); ++ if (!ring->descbase) { + printk(KERN_ERR PFX "DMA ringmemory allocation failed\n"); + return -ENOMEM; + } +- if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { +- printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G " +- "(0x%llx, len: %lu)\n", +- (unsigned long long)ring->dmabase, +- BCM43xx_DMA_RINGMEMSIZE); +- dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, +- ring->vbase, ring->dmabase); +- return -ENOMEM; +- } +- assert(!(ring->dmabase & 0x000003FF)); +- memset(ring->vbase, 0, BCM43xx_DMA_RINGMEMSIZE); ++ memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE); + + return 0; + } +@@ -214,26 +232,34 @@ static void free_ringmemory(struct bcm43 + struct device *dev = &(ring->bcm->pci_dev->dev); + + dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, +- ring->vbase, ring->dmabase); ++ ring->descbase, ring->dmabase); + } + + /* Reset the RX DMA channel */ + int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, +- u16 mmio_base) ++ u16 mmio_base, int dma64) + { + int i; + u32 value; ++ u16 offset; + +- bcm43xx_write32(bcm, +- mmio_base + BCM43xx_DMA_RX_CONTROL, +- 0x00000000); ++ offset = dma64 ? BCM43xx_DMA64_RXCTL : BCM43xx_DMA32_RXCTL; ++ bcm43xx_write32(bcm, mmio_base + offset, 0); + for (i = 0; i < 1000; i++) { +- value = bcm43xx_read32(bcm, +- mmio_base + BCM43xx_DMA_RX_STATUS); +- value &= BCM43xx_DMA_RXSTAT_STAT_MASK; +- if (value == BCM43xx_DMA_RXSTAT_STAT_DISABLED) { +- i = -1; +- break; ++ offset = dma64 ? BCM43xx_DMA64_RXSTATUS : BCM43xx_DMA32_RXSTATUS; ++ value = bcm43xx_read32(bcm, mmio_base + offset); ++ if (dma64) { ++ value &= BCM43xx_DMA64_RXSTAT; ++ if (value == BCM43xx_DMA64_RXSTAT_DISABLED) { ++ i = -1; ++ break; ++ } ++ } else { ++ value &= BCM43xx_DMA32_RXSTATE; ++ if (value == BCM43xx_DMA32_RXSTAT_DISABLED) { ++ i = -1; ++ break; ++ } + } + udelay(10); + } +@@ -247,31 +273,47 @@ int bcm43xx_dmacontroller_rx_reset(struc + + /* Reset the RX DMA channel */ + int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, +- u16 mmio_base) ++ u16 mmio_base, int dma64) + { + int i; + u32 value; ++ u16 offset; + + for (i = 0; i < 1000; i++) { +- value = bcm43xx_read32(bcm, +- mmio_base + BCM43xx_DMA_TX_STATUS); +- value &= BCM43xx_DMA_TXSTAT_STAT_MASK; +- if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED || +- value == BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT || +- value == BCM43xx_DMA_TXSTAT_STAT_STOPPED) +- break; ++ offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS; ++ value = bcm43xx_read32(bcm, mmio_base + offset); ++ if (dma64) { ++ value &= BCM43xx_DMA64_TXSTAT; ++ if (value == BCM43xx_DMA64_TXSTAT_DISABLED || ++ value == BCM43xx_DMA64_TXSTAT_IDLEWAIT || ++ value == BCM43xx_DMA64_TXSTAT_STOPPED) ++ break; ++ } else { ++ value &= BCM43xx_DMA32_TXSTATE; ++ if (value == BCM43xx_DMA32_TXSTAT_DISABLED || ++ value == BCM43xx_DMA32_TXSTAT_IDLEWAIT || ++ value == BCM43xx_DMA32_TXSTAT_STOPPED) ++ break; ++ } + udelay(10); + } +- bcm43xx_write32(bcm, +- mmio_base + BCM43xx_DMA_TX_CONTROL, +- 0x00000000); ++ offset = dma64 ? BCM43xx_DMA64_TXCTL : BCM43xx_DMA32_TXCTL; ++ bcm43xx_write32(bcm, mmio_base + offset, 0); + for (i = 0; i < 1000; i++) { +- value = bcm43xx_read32(bcm, +- mmio_base + BCM43xx_DMA_TX_STATUS); +- value &= BCM43xx_DMA_TXSTAT_STAT_MASK; +- if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED) { +- i = -1; +- break; ++ offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS; ++ value = bcm43xx_read32(bcm, mmio_base + offset); ++ if (dma64) { ++ value &= BCM43xx_DMA64_TXSTAT; ++ if (value == BCM43xx_DMA64_TXSTAT_DISABLED) { ++ i = -1; ++ break; ++ } ++ } else { ++ value &= BCM43xx_DMA32_TXSTATE; ++ if (value == BCM43xx_DMA32_TXSTAT_DISABLED) { ++ i = -1; ++ break; ++ } + } + udelay(10); + } +@@ -285,47 +327,98 @@ int bcm43xx_dmacontroller_tx_reset(struc + return 0; + } + ++static void fill_descriptor(struct bcm43xx_dmaring *ring, ++ struct bcm43xx_dmadesc_generic *desc, ++ dma_addr_t dmaaddr, ++ u16 bufsize, ++ int start, int end, int irq) ++{ ++ int slot; ++ ++ slot = bcm43xx_dma_desc2idx(ring, desc); ++ assert(slot >= 0 && slot < ring->nr_slots); ++ ++ if (ring->dma64) { ++ u32 ctl0 = 0, ctl1 = 0; ++ u32 addrlo, addrhi; ++ u32 addrext; ++ ++ addrlo = (u32)(dmaaddr & 0xFFFFFFFF); ++ addrhi = (((u64)dmaaddr >> 32) & ~BCM43xx_DMA64_ROUTING); ++ addrext = (((u64)dmaaddr >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); ++ addrhi |= ring->routing; ++ if (slot == ring->nr_slots - 1) ++ ctl0 |= BCM43xx_DMA64_DCTL0_DTABLEEND; ++ if (start) ++ ctl0 |= BCM43xx_DMA64_DCTL0_FRAMESTART; ++ if (end) ++ ctl0 |= BCM43xx_DMA64_DCTL0_FRAMEEND; ++ if (irq) ++ ctl0 |= BCM43xx_DMA64_DCTL0_IRQ; ++ ctl1 |= (bufsize - ring->frameoffset) ++ & BCM43xx_DMA64_DCTL1_BYTECNT; ++ ctl1 |= (addrext << BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT) ++ & BCM43xx_DMA64_DCTL1_ADDREXT_MASK; ++ ++ desc->dma64.control0 = cpu_to_le32(ctl0); ++ desc->dma64.control1 = cpu_to_le32(ctl1); ++ desc->dma64.address_low = cpu_to_le32(addrlo); ++ desc->dma64.address_high = cpu_to_le32(addrhi); ++ } else { ++ u32 ctl; ++ u32 addr; ++ u32 addrext; ++ ++ addr = (u32)(dmaaddr & ~BCM43xx_DMA32_ROUTING); ++ addrext = (u32)(dmaaddr & BCM43xx_DMA32_ROUTING) ++ >> BCM43xx_DMA32_ROUTING_SHIFT; ++ addr |= ring->routing; ++ ctl = (bufsize - ring->frameoffset) ++ & BCM43xx_DMA32_DCTL_BYTECNT; ++ if (slot == ring->nr_slots - 1) ++ ctl |= BCM43xx_DMA32_DCTL_DTABLEEND; ++ if (start) ++ ctl |= BCM43xx_DMA32_DCTL_FRAMESTART; ++ if (end) ++ ctl |= BCM43xx_DMA32_DCTL_FRAMEEND; ++ if (irq) ++ ctl |= BCM43xx_DMA32_DCTL_IRQ; ++ ctl |= (addrext << BCM43xx_DMA32_DCTL_ADDREXT_SHIFT) ++ & BCM43xx_DMA32_DCTL_ADDREXT_MASK; ++ ++ desc->dma32.control = cpu_to_le32(ctl); ++ desc->dma32.address = cpu_to_le32(addr); ++ } ++} ++ + static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, +- struct bcm43xx_dmadesc *desc, ++ struct bcm43xx_dmadesc_generic *desc, + struct bcm43xx_dmadesc_meta *meta, + gfp_t gfp_flags) + { + struct bcm43xx_rxhdr *rxhdr; ++ struct bcm43xx_hwxmitstatus *xmitstat; + dma_addr_t dmaaddr; +- u32 desc_addr; +- u32 desc_ctl; +- const int slot = (int)(desc - ring->vbase); + struct sk_buff *skb; + +- assert(slot >= 0 && slot < ring->nr_slots); + assert(!ring->tx); + + skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); + if (unlikely(!skb)) + return -ENOMEM; + dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); +- if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) { +- unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); +- dev_kfree_skb_any(skb); +- printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G " +- "(0x%llx, len: %u)\n", +- (unsigned long long)dmaaddr, ring->rx_buffersize); +- return -ENOMEM; +- } + meta->skb = skb; + meta->dmaaddr = dmaaddr; + skb->dev = ring->bcm->net_dev; +- desc_addr = (u32)(dmaaddr + ring->memoffset); +- desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK & +- (u32)(ring->rx_buffersize - ring->frameoffset)); +- if (slot == ring->nr_slots - 1) +- desc_ctl |= BCM43xx_DMADTOR_DTABLEEND; +- set_desc_addr(desc, desc_addr); +- set_desc_ctl(desc, desc_ctl); ++ ++ fill_descriptor(ring, desc, dmaaddr, ++ ring->rx_buffersize, 0, 0, 0); + + rxhdr = (struct bcm43xx_rxhdr *)(skb->data); + rxhdr->frame_length = 0; + rxhdr->flags1 = 0; ++ xmitstat = (struct bcm43xx_hwxmitstatus *)(skb->data); ++ xmitstat->cookie = 0; + + return 0; + } +@@ -336,17 +429,17 @@ static int setup_rx_descbuffer(struct bc + static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) + { + int i, err = -ENOMEM; +- struct bcm43xx_dmadesc *desc; ++ struct bcm43xx_dmadesc_generic *desc; + struct bcm43xx_dmadesc_meta *meta; + + for (i = 0; i < ring->nr_slots; i++) { +- desc = ring->vbase + i; +- meta = ring->meta + i; ++ desc = bcm43xx_dma_idx2desc(ring, i, &meta); + + err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); + if (err) + goto err_unwind; + } ++ mb(); + ring->used_slots = ring->nr_slots; + err = 0; + out: +@@ -354,8 +447,7 @@ out: + + err_unwind: + for (i--; i >= 0; i--) { +- desc = ring->vbase + i; +- meta = ring->meta + i; ++ desc = bcm43xx_dma_idx2desc(ring, i, &meta); + + unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); + dev_kfree_skb(meta->skb); +@@ -371,27 +463,67 @@ static int dmacontroller_setup(struct bc + { + int err = 0; + u32 value; ++ u32 addrext; + + if (ring->tx) { +- /* Set Transmit Control register to "transmit enable" */ +- bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, +- BCM43xx_DMA_TXCTRL_ENABLE); +- /* Set Transmit Descriptor ring address. */ +- bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, +- ring->dmabase + ring->memoffset); ++ if (ring->dma64) { ++ u64 ringbase = (u64)(ring->dmabase); ++ ++ addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); ++ value = BCM43xx_DMA64_TXENABLE; ++ value |= (addrext << BCM43xx_DMA64_TXADDREXT_SHIFT) ++ & BCM43xx_DMA64_TXADDREXT_MASK; ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, value); ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, ++ (ringbase & 0xFFFFFFFF)); ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, ++ ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING) ++ | ring->routing); ++ } else { ++ u32 ringbase = (u32)(ring->dmabase); ++ ++ addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT); ++ value = BCM43xx_DMA32_TXENABLE; ++ value |= (addrext << BCM43xx_DMA32_TXADDREXT_SHIFT) ++ & BCM43xx_DMA32_TXADDREXT_MASK; ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, value); ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, ++ (ringbase & ~BCM43xx_DMA32_ROUTING) ++ | ring->routing); ++ } + } else { + err = alloc_initial_descbuffers(ring); + if (err) + goto out; +- /* Set Receive Control "receive enable" and frame offset */ +- value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT); +- value |= BCM43xx_DMA_RXCTRL_ENABLE; +- bcm43xx_dma_write(ring, BCM43xx_DMA_RX_CONTROL, value); +- /* Set Receive Descriptor ring address. */ +- bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, +- ring->dmabase + ring->memoffset); +- /* Init the descriptor pointer. */ +- bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, 200); ++ if (ring->dma64) { ++ u64 ringbase = (u64)(ring->dmabase); ++ ++ addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); ++ value = (ring->frameoffset << BCM43xx_DMA64_RXFROFF_SHIFT); ++ value |= BCM43xx_DMA64_RXENABLE; ++ value |= (addrext << BCM43xx_DMA64_RXADDREXT_SHIFT) ++ & BCM43xx_DMA64_RXADDREXT_MASK; ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_RXCTL, value); ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, ++ (ringbase & 0xFFFFFFFF)); ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, ++ ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING) ++ | ring->routing); ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, 200); ++ } else { ++ u32 ringbase = (u32)(ring->dmabase); ++ ++ addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT); ++ value = (ring->frameoffset << BCM43xx_DMA32_RXFROFF_SHIFT); ++ value |= BCM43xx_DMA32_RXENABLE; ++ value |= (addrext << BCM43xx_DMA32_RXADDREXT_SHIFT) ++ & BCM43xx_DMA32_RXADDREXT_MASK; ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_RXCTL, value); ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, ++ (ringbase & ~BCM43xx_DMA32_ROUTING) ++ | ring->routing); ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, 200); ++ } + } + + out: +@@ -402,27 +534,32 @@ out: + static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) + { + if (ring->tx) { +- bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base); +- /* Zero out Transmit Descriptor ring address. */ +- bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, 0); ++ bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base, ring->dma64); ++ if (ring->dma64) { ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, 0); ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, 0); ++ } else ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, 0); + } else { +- bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base); +- /* Zero out Receive Descriptor ring address. */ +- bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, 0); ++ bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base, ring->dma64); ++ if (ring->dma64) { ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, 0); ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, 0); ++ } else ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, 0); + } + } + + static void free_all_descbuffers(struct bcm43xx_dmaring *ring) + { +- struct bcm43xx_dmadesc *desc; ++ struct bcm43xx_dmadesc_generic *desc; + struct bcm43xx_dmadesc_meta *meta; + int i; + + if (!ring->used_slots) + return; + for (i = 0; i < ring->nr_slots; i++) { +- desc = ring->vbase + i; +- meta = ring->meta + i; ++ desc = bcm43xx_dma_idx2desc(ring, i, &meta); + + if (!meta->skb) { + assert(ring->tx); +@@ -430,62 +567,67 @@ static void free_all_descbuffers(struct + } + if (ring->tx) { + unmap_descbuffer(ring, meta->dmaaddr, +- meta->skb->len, 1); ++ meta->skb->len, 1); + } else { + unmap_descbuffer(ring, meta->dmaaddr, +- ring->rx_buffersize, 0); ++ ring->rx_buffersize, 0); + } +- free_descriptor_buffer(ring, desc, meta, 0); ++ free_descriptor_buffer(ring, meta, 0); + } + } + + /* Main initialization function. */ + static + struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, +- u16 dma_controller_base, +- int nr_descriptor_slots, +- int tx) ++ int controller_index, ++ int for_tx, ++ int dma64) + { + struct bcm43xx_dmaring *ring; + int err; ++ int nr_slots; + + ring = kzalloc(sizeof(*ring), GFP_KERNEL); + if (!ring) + goto out; + +- ring->meta = kzalloc(sizeof(*ring->meta) * nr_descriptor_slots, ++ nr_slots = BCM43xx_RXRING_SLOTS; ++ if (for_tx) ++ nr_slots = BCM43xx_TXRING_SLOTS; ++ ++ ring->meta = kcalloc(nr_slots, sizeof(struct bcm43xx_dmadesc_meta), + GFP_KERNEL); + if (!ring->meta) + goto err_kfree_ring; + +- ring->memoffset = BCM43xx_DMA_DMABUSADDROFFSET; ++ ring->routing = BCM43xx_DMA32_CLIENTTRANS; ++ if (dma64) ++ ring->routing = BCM43xx_DMA64_CLIENTTRANS; + #ifdef CONFIG_BCM947XX + if (bcm->pci_dev->bus->number == 0) +- ring->memoffset = 0; ++ ring->routing = dma64 ? BCM43xx_DMA64_NOTRANS : BCM43xx_DMA32_NOTRANS; + #endif + + ring->bcm = bcm; +- ring->nr_slots = nr_descriptor_slots; ++ ring->nr_slots = nr_slots; + ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100; + ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100; + assert(ring->suspend_mark < ring->resume_mark); +- ring->mmio_base = dma_controller_base; +- if (tx) { ++ ring->mmio_base = bcm43xx_dmacontroller_base(dma64, controller_index); ++ ring->index = controller_index; ++ ring->dma64 = !!dma64; ++ if (for_tx) { + ring->tx = 1; + ring->current_slot = -1; + } else { +- switch (dma_controller_base) { +- case BCM43xx_MMIO_DMA1_BASE: +- ring->rx_buffersize = BCM43xx_DMA1_RXBUFFERSIZE; +- ring->frameoffset = BCM43xx_DMA1_RX_FRAMEOFFSET; +- break; +- case BCM43xx_MMIO_DMA4_BASE: +- ring->rx_buffersize = BCM43xx_DMA4_RXBUFFERSIZE; +- ring->frameoffset = BCM43xx_DMA4_RX_FRAMEOFFSET; +- break; +- default: ++ if (ring->index == 0) { ++ ring->rx_buffersize = BCM43xx_DMA0_RX_BUFFERSIZE; ++ ring->frameoffset = BCM43xx_DMA0_RX_FRAMEOFFSET; ++ } else if (ring->index == 3) { ++ ring->rx_buffersize = BCM43xx_DMA3_RX_BUFFERSIZE; ++ ring->frameoffset = BCM43xx_DMA3_RX_FRAMEOFFSET; ++ } else + assert(0); +- } + } + + err = alloc_ringmemory(ring); +@@ -514,7 +656,8 @@ static void bcm43xx_destroy_dmaring(stru + if (!ring) + return; + +- dprintk(KERN_INFO PFX "DMA 0x%04x (%s) max used slots: %d/%d\n", ++ dprintk(KERN_INFO PFX "DMA-%s 0x%04X (%s) max used slots: %d/%d\n", ++ (ring->dma64) ? "64" : "32", + ring->mmio_base, + (ring->tx) ? "TX" : "RX", + ring->max_used_slots, ring->nr_slots); +@@ -537,10 +680,15 @@ void bcm43xx_dma_free(struct bcm43xx_pri + return; + dma = bcm43xx_current_dma(bcm); + +- bcm43xx_destroy_dmaring(dma->rx_ring1); +- dma->rx_ring1 = NULL; ++ bcm43xx_destroy_dmaring(dma->rx_ring3); ++ dma->rx_ring3 = NULL; + bcm43xx_destroy_dmaring(dma->rx_ring0); + dma->rx_ring0 = NULL; ++ ++ bcm43xx_destroy_dmaring(dma->tx_ring5); ++ dma->tx_ring5 = NULL; ++ bcm43xx_destroy_dmaring(dma->tx_ring4); ++ dma->tx_ring4 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring3); + dma->tx_ring3 = NULL; + bcm43xx_destroy_dmaring(dma->tx_ring2); +@@ -556,48 +704,59 @@ int bcm43xx_dma_init(struct bcm43xx_priv + struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); + struct bcm43xx_dmaring *ring; + int err = -ENOMEM; ++ int dma64 = 0; ++ u32 sbtmstatehi; ++ ++ sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); ++ if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT) ++ dma64 = 1; + + /* setup TX DMA channels. */ +- ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, +- BCM43xx_TXRING_SLOTS, 1); ++ ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64); + if (!ring) + goto out; + dma->tx_ring0 = ring; + +- ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE, +- BCM43xx_TXRING_SLOTS, 1); ++ ring = bcm43xx_setup_dmaring(bcm, 1, 1, dma64); + if (!ring) + goto err_destroy_tx0; + dma->tx_ring1 = ring; + +- ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE, +- BCM43xx_TXRING_SLOTS, 1); ++ ring = bcm43xx_setup_dmaring(bcm, 2, 1, dma64); + if (!ring) + goto err_destroy_tx1; + dma->tx_ring2 = ring; + +- ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, +- BCM43xx_TXRING_SLOTS, 1); ++ ring = bcm43xx_setup_dmaring(bcm, 3, 1, dma64); + if (!ring) + goto err_destroy_tx2; + dma->tx_ring3 = ring; + +- /* setup RX DMA channels. */ +- ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE, +- BCM43xx_RXRING_SLOTS, 0); ++ ring = bcm43xx_setup_dmaring(bcm, 4, 1, dma64); + if (!ring) + goto err_destroy_tx3; ++ dma->tx_ring4 = ring; ++ ++ ring = bcm43xx_setup_dmaring(bcm, 5, 1, dma64); ++ if (!ring) ++ goto err_destroy_tx4; ++ dma->tx_ring5 = ring; ++ ++ /* setup RX DMA channels. */ ++ ring = bcm43xx_setup_dmaring(bcm, 0, 0, dma64); ++ if (!ring) ++ goto err_destroy_tx5; + dma->rx_ring0 = ring; + + if (bcm->current_core->rev < 5) { +- ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE, +- BCM43xx_RXRING_SLOTS, 0); ++ ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64); + if (!ring) + goto err_destroy_rx0; +- dma->rx_ring1 = ring; ++ dma->rx_ring3 = ring; + } + +- dprintk(KERN_INFO PFX "DMA initialized\n"); ++ dprintk(KERN_INFO PFX "%s DMA initialized\n", ++ dma64 ? "64-bit" : "32-bit"); + err = 0; + out: + return err; +@@ -605,6 +764,12 @@ out: + err_destroy_rx0: + bcm43xx_destroy_dmaring(dma->rx_ring0); + dma->rx_ring0 = NULL; ++err_destroy_tx5: ++ bcm43xx_destroy_dmaring(dma->tx_ring5); ++ dma->tx_ring5 = NULL; ++err_destroy_tx4: ++ bcm43xx_destroy_dmaring(dma->tx_ring4); ++ dma->tx_ring4 = NULL; + err_destroy_tx3: + bcm43xx_destroy_dmaring(dma->tx_ring3); + dma->tx_ring3 = NULL; +@@ -624,7 +789,7 @@ err_destroy_tx0: + static u16 generate_cookie(struct bcm43xx_dmaring *ring, + int slot) + { +- u16 cookie = 0xF000; ++ u16 cookie = 0x1000; + + /* Use the upper 4 bits of the cookie as + * DMA controller ID and store the slot number +@@ -632,21 +797,25 @@ static u16 generate_cookie(struct bcm43x + * Note that the cookie must never be 0, as this + * is a special value used in RX path. + */ +- switch (ring->mmio_base) { +- default: +- assert(0); +- case BCM43xx_MMIO_DMA1_BASE: ++ switch (ring->index) { ++ case 0: + cookie = 0xA000; + break; +- case BCM43xx_MMIO_DMA2_BASE: ++ case 1: + cookie = 0xB000; + break; +- case BCM43xx_MMIO_DMA3_BASE: ++ case 2: + cookie = 0xC000; + break; +- case BCM43xx_MMIO_DMA4_BASE: ++ case 3: + cookie = 0xD000; + break; ++ case 4: ++ cookie = 0xE000; ++ break; ++ case 5: ++ cookie = 0xF000; ++ break; + } + assert(((u16)slot & 0xF000) == 0x0000); + cookie |= (u16)slot; +@@ -675,6 +844,12 @@ struct bcm43xx_dmaring * parse_cookie(st + case 0xD000: + ring = dma->tx_ring3; + break; ++ case 0xE000: ++ ring = dma->tx_ring4; ++ break; ++ case 0xF000: ++ ring = dma->tx_ring5; ++ break; + default: + assert(0); + } +@@ -687,6 +862,9 @@ struct bcm43xx_dmaring * parse_cookie(st + static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, + int slot) + { ++ u16 offset; ++ int descsize; ++ + /* Everything is ready to start. Buffers are DMA mapped and + * associated with slots. + * "slot" is the last slot of the new frame we want to transmit. +@@ -694,25 +872,26 @@ static void dmacontroller_poke_tx(struct + */ + wmb(); + slot = next_slot(ring, slot); +- bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_INDEX, +- (u32)(slot * sizeof(struct bcm43xx_dmadesc))); ++ offset = (ring->dma64) ? BCM43xx_DMA64_TXINDEX : BCM43xx_DMA32_TXINDEX; ++ descsize = (ring->dma64) ? sizeof(struct bcm43xx_dmadesc64) ++ : sizeof(struct bcm43xx_dmadesc32); ++ bcm43xx_dma_write(ring, offset, ++ (u32)(slot * descsize)); + } + +-static int dma_tx_fragment(struct bcm43xx_dmaring *ring, +- struct sk_buff *skb, +- u8 cur_frag) ++static void dma_tx_fragment(struct bcm43xx_dmaring *ring, ++ struct sk_buff *skb, ++ u8 cur_frag) + { + int slot; +- struct bcm43xx_dmadesc *desc; ++ struct bcm43xx_dmadesc_generic *desc; + struct bcm43xx_dmadesc_meta *meta; +- u32 desc_ctl; +- u32 desc_addr; ++ dma_addr_t dmaaddr; + + assert(skb_shinfo(skb)->nr_frags == 0); + + slot = request_slot(ring); +- desc = ring->vbase + slot; +- meta = ring->meta + slot; ++ desc = bcm43xx_dma_idx2desc(ring, slot, &meta); + + /* Add a device specific TX header. */ + assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); +@@ -729,29 +908,14 @@ static int dma_tx_fragment(struct bcm43x + generate_cookie(ring, slot)); + + meta->skb = skb; +- meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); +- if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { +- return_slot(ring, slot); +- printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G " +- "(0x%llx, len: %u)\n", +- (unsigned long long)meta->dmaaddr, skb->len); +- return -ENOMEM; +- } ++ dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); ++ meta->dmaaddr = dmaaddr; + +- desc_addr = (u32)(meta->dmaaddr + ring->memoffset); +- desc_ctl = BCM43xx_DMADTOR_FRAMESTART | BCM43xx_DMADTOR_FRAMEEND; +- desc_ctl |= BCM43xx_DMADTOR_COMPIRQ; +- desc_ctl |= (BCM43xx_DMADTOR_BYTECNT_MASK & +- (u32)(meta->skb->len - ring->frameoffset)); +- if (slot == ring->nr_slots - 1) +- desc_ctl |= BCM43xx_DMADTOR_DTABLEEND; ++ fill_descriptor(ring, desc, dmaaddr, ++ skb->len, 1, 1, 1); + +- set_desc_ctl(desc, desc_ctl); +- set_desc_addr(desc, desc_addr); + /* Now transfer the whole frame. */ + dmacontroller_poke_tx(ring, slot); +- +- return 0; + } + + int bcm43xx_dma_tx(struct bcm43xx_private *bcm, +@@ -781,7 +945,6 @@ int bcm43xx_dma_tx(struct bcm43xx_privat + /* Take skb from ieee80211_txb_free */ + txb->fragments[i] = NULL; + dma_tx_fragment(ring, skb, i); +- //TODO: handle failure of dma_tx_fragment + } + ieee80211_txb_free(txb); + +@@ -792,23 +955,28 @@ void bcm43xx_dma_handle_xmitstatus(struc + struct bcm43xx_xmitstatus *status) + { + struct bcm43xx_dmaring *ring; +- struct bcm43xx_dmadesc *desc; ++ struct bcm43xx_dmadesc_generic *desc; + struct bcm43xx_dmadesc_meta *meta; + int is_last_fragment; + int slot; ++ u32 tmp; + + ring = parse_cookie(bcm, status->cookie, &slot); + assert(ring); + assert(ring->tx); +- assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART); + while (1) { + assert(slot >= 0 && slot < ring->nr_slots); +- desc = ring->vbase + slot; +- meta = ring->meta + slot; ++ desc = bcm43xx_dma_idx2desc(ring, slot, &meta); + +- is_last_fragment = !!(get_desc_ctl(desc) & BCM43xx_DMADTOR_FRAMEEND); ++ if (ring->dma64) { ++ tmp = le32_to_cpu(desc->dma64.control0); ++ is_last_fragment = !!(tmp & BCM43xx_DMA64_DCTL0_FRAMEEND); ++ } else { ++ tmp = le32_to_cpu(desc->dma32.control); ++ is_last_fragment = !!(tmp & BCM43xx_DMA32_DCTL_FRAMEEND); ++ } + unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); +- free_descriptor_buffer(ring, desc, meta, 1); ++ free_descriptor_buffer(ring, meta, 1); + /* Everything belonging to the slot is unmapped + * and freed, so we can return it. + */ +@@ -824,7 +992,7 @@ void bcm43xx_dma_handle_xmitstatus(struc + static void dma_rx(struct bcm43xx_dmaring *ring, + int *slot) + { +- struct bcm43xx_dmadesc *desc; ++ struct bcm43xx_dmadesc_generic *desc; + struct bcm43xx_dmadesc_meta *meta; + struct bcm43xx_rxhdr *rxhdr; + struct sk_buff *skb; +@@ -832,13 +1000,12 @@ static void dma_rx(struct bcm43xx_dmarin + int err; + dma_addr_t dmaaddr; + +- desc = ring->vbase + *slot; +- meta = ring->meta + *slot; ++ desc = bcm43xx_dma_idx2desc(ring, *slot, &meta); + + sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); + skb = meta->skb; + +- if (ring->mmio_base == BCM43xx_MMIO_DMA4_BASE) { ++ if (ring->index == 3) { + /* We received an xmit status. */ + struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data; + struct bcm43xx_xmitstatus stat; +@@ -894,8 +1061,7 @@ static void dma_rx(struct bcm43xx_dmarin + s32 tmp = len; + + while (1) { +- desc = ring->vbase + *slot; +- meta = ring->meta + *slot; ++ desc = bcm43xx_dma_idx2desc(ring, *slot, &meta); + /* recycle the descriptor buffer. */ + sync_descbuffer_for_device(ring, meta->dmaaddr, + ring->rx_buffersize); +@@ -906,8 +1072,8 @@ static void dma_rx(struct bcm43xx_dmarin + break; + } + printkl(KERN_ERR PFX "DMA RX buffer too small " +- "(len: %u, buffer: %u, nr-dropped: %d)\n", +- len, ring->rx_buffersize, cnt); ++ "(len: %u, buffer: %u, nr-dropped: %d)\n", ++ len, ring->rx_buffersize, cnt); + goto drop; + } + len -= IEEE80211_FCS_LEN; +@@ -945,9 +1111,15 @@ #ifdef CONFIG_BCM43XX_DEBUG + #endif + + assert(!ring->tx); +- status = bcm43xx_dma_read(ring, BCM43xx_DMA_RX_STATUS); +- descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK); +- current_slot = descptr / sizeof(struct bcm43xx_dmadesc); ++ if (ring->dma64) { ++ status = bcm43xx_dma_read(ring, BCM43xx_DMA64_RXSTATUS); ++ descptr = (status & BCM43xx_DMA64_RXSTATDPTR); ++ current_slot = descptr / sizeof(struct bcm43xx_dmadesc64); ++ } else { ++ status = bcm43xx_dma_read(ring, BCM43xx_DMA32_RXSTATUS); ++ descptr = (status & BCM43xx_DMA32_RXDPTR); ++ current_slot = descptr / sizeof(struct bcm43xx_dmadesc32); ++ } + assert(current_slot >= 0 && current_slot < ring->nr_slots); + + slot = ring->current_slot; +@@ -958,8 +1130,13 @@ #ifdef CONFIG_BCM43XX_DEBUG + ring->max_used_slots = used_slots; + #endif + } +- bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, +- (u32)(slot * sizeof(struct bcm43xx_dmadesc))); ++ if (ring->dma64) { ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, ++ (u32)(slot * sizeof(struct bcm43xx_dmadesc64))); ++ } else { ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, ++ (u32)(slot * sizeof(struct bcm43xx_dmadesc32))); ++ } + ring->current_slot = slot; + } + +@@ -967,16 +1144,28 @@ void bcm43xx_dma_tx_suspend(struct bcm43 + { + assert(ring->tx); + bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1); +- bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, +- bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL) +- | BCM43xx_DMA_TXCTRL_SUSPEND); ++ if (ring->dma64) { ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, ++ bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL) ++ | BCM43xx_DMA64_TXSUSPEND); ++ } else { ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, ++ bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL) ++ | BCM43xx_DMA32_TXSUSPEND); ++ } + } + + void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) + { + assert(ring->tx); +- bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL, +- bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL) +- & ~BCM43xx_DMA_TXCTRL_SUSPEND); ++ if (ring->dma64) { ++ bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, ++ bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL) ++ & ~BCM43xx_DMA64_TXSUSPEND); ++ } else { ++ bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, ++ bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL) ++ & ~BCM43xx_DMA32_TXSUSPEND); ++ } + bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1); + } +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +index b7d7763..e04bcad 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +@@ -14,63 +14,179 @@ #define BCM43xx_DMAIRQ_FATALMASK ((1 << + #define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13) + #define BCM43xx_DMAIRQ_RX_DONE (1 << 16) + +-/* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */ +-#define BCM43xx_DMA_TX_CONTROL 0x00 +-#define BCM43xx_DMA_TX_DESC_RING 0x04 +-#define BCM43xx_DMA_TX_DESC_INDEX 0x08 +-#define BCM43xx_DMA_TX_STATUS 0x0c +-#define BCM43xx_DMA_RX_CONTROL 0x10 +-#define BCM43xx_DMA_RX_DESC_RING 0x14 +-#define BCM43xx_DMA_RX_DESC_INDEX 0x18 +-#define BCM43xx_DMA_RX_STATUS 0x1c +- +-/* DMA controller channel control word values. */ +-#define BCM43xx_DMA_TXCTRL_ENABLE (1 << 0) +-#define BCM43xx_DMA_TXCTRL_SUSPEND (1 << 1) +-#define BCM43xx_DMA_TXCTRL_LOOPBACK (1 << 2) +-#define BCM43xx_DMA_TXCTRL_FLUSH (1 << 4) +-#define BCM43xx_DMA_RXCTRL_ENABLE (1 << 0) +-#define BCM43xx_DMA_RXCTRL_FRAMEOFF_MASK 0x000000fe +-#define BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT 1 +-#define BCM43xx_DMA_RXCTRL_PIO (1 << 8) +-/* DMA controller channel status word values. */ +-#define BCM43xx_DMA_TXSTAT_DPTR_MASK 0x00000fff +-#define BCM43xx_DMA_TXSTAT_STAT_MASK 0x0000f000 +-#define BCM43xx_DMA_TXSTAT_STAT_DISABLED 0x00000000 +-#define BCM43xx_DMA_TXSTAT_STAT_ACTIVE 0x00001000 +-#define BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT 0x00002000 +-#define BCM43xx_DMA_TXSTAT_STAT_STOPPED 0x00003000 +-#define BCM43xx_DMA_TXSTAT_STAT_SUSP 0x00004000 +-#define BCM43xx_DMA_TXSTAT_ERROR_MASK 0x000f0000 +-#define BCM43xx_DMA_TXSTAT_FLUSHED (1 << 20) +-#define BCM43xx_DMA_RXSTAT_DPTR_MASK 0x00000fff +-#define BCM43xx_DMA_RXSTAT_STAT_MASK 0x0000f000 +-#define BCM43xx_DMA_RXSTAT_STAT_DISABLED 0x00000000 +-#define BCM43xx_DMA_RXSTAT_STAT_ACTIVE 0x00001000 +-#define BCM43xx_DMA_RXSTAT_STAT_IDLEWAIT 0x00002000 +-#define BCM43xx_DMA_RXSTAT_STAT_RESERVED 0x00003000 +-#define BCM43xx_DMA_RXSTAT_STAT_ERRORS 0x00004000 +-#define BCM43xx_DMA_RXSTAT_ERROR_MASK 0x000f0000 +- +-/* DMA descriptor control field values. */ +-#define BCM43xx_DMADTOR_BYTECNT_MASK 0x00001fff +-#define BCM43xx_DMADTOR_DTABLEEND (1 << 28) /* End of descriptor table */ +-#define BCM43xx_DMADTOR_COMPIRQ (1 << 29) /* IRQ on completion request */ +-#define BCM43xx_DMADTOR_FRAMEEND (1 << 30) +-#define BCM43xx_DMADTOR_FRAMESTART (1 << 31) ++ ++/*** 32-bit DMA Engine. ***/ ++ ++/* 32-bit DMA controller registers. */ ++#define BCM43xx_DMA32_TXCTL 0x00 ++#define BCM43xx_DMA32_TXENABLE 0x00000001 ++#define BCM43xx_DMA32_TXSUSPEND 0x00000002 ++#define BCM43xx_DMA32_TXLOOPBACK 0x00000004 ++#define BCM43xx_DMA32_TXFLUSH 0x00000010 ++#define BCM43xx_DMA32_TXADDREXT_MASK 0x00030000 ++#define BCM43xx_DMA32_TXADDREXT_SHIFT 16 ++#define BCM43xx_DMA32_TXRING 0x04 ++#define BCM43xx_DMA32_TXINDEX 0x08 ++#define BCM43xx_DMA32_TXSTATUS 0x0C ++#define BCM43xx_DMA32_TXDPTR 0x00000FFF ++#define BCM43xx_DMA32_TXSTATE 0x0000F000 ++#define BCM43xx_DMA32_TXSTAT_DISABLED 0x00000000 ++#define BCM43xx_DMA32_TXSTAT_ACTIVE 0x00001000 ++#define BCM43xx_DMA32_TXSTAT_IDLEWAIT 0x00002000 ++#define BCM43xx_DMA32_TXSTAT_STOPPED 0x00003000 ++#define BCM43xx_DMA32_TXSTAT_SUSP 0x00004000 ++#define BCM43xx_DMA32_TXERROR 0x000F0000 ++#define BCM43xx_DMA32_TXERR_NOERR 0x00000000 ++#define BCM43xx_DMA32_TXERR_PROT 0x00010000 ++#define BCM43xx_DMA32_TXERR_UNDERRUN 0x00020000 ++#define BCM43xx_DMA32_TXERR_BUFREAD 0x00030000 ++#define BCM43xx_DMA32_TXERR_DESCREAD 0x00040000 ++#define BCM43xx_DMA32_TXACTIVE 0xFFF00000 ++#define BCM43xx_DMA32_RXCTL 0x10 ++#define BCM43xx_DMA32_RXENABLE 0x00000001 ++#define BCM43xx_DMA32_RXFROFF_MASK 0x000000FE ++#define BCM43xx_DMA32_RXFROFF_SHIFT 1 ++#define BCM43xx_DMA32_RXDIRECTFIFO 0x00000100 ++#define BCM43xx_DMA32_RXADDREXT_MASK 0x00030000 ++#define BCM43xx_DMA32_RXADDREXT_SHIFT 16 ++#define BCM43xx_DMA32_RXRING 0x14 ++#define BCM43xx_DMA32_RXINDEX 0x18 ++#define BCM43xx_DMA32_RXSTATUS 0x1C ++#define BCM43xx_DMA32_RXDPTR 0x00000FFF ++#define BCM43xx_DMA32_RXSTATE 0x0000F000 ++#define BCM43xx_DMA32_RXSTAT_DISABLED 0x00000000 ++#define BCM43xx_DMA32_RXSTAT_ACTIVE 0x00001000 ++#define BCM43xx_DMA32_RXSTAT_IDLEWAIT 0x00002000 ++#define BCM43xx_DMA32_RXSTAT_STOPPED 0x00003000 ++#define BCM43xx_DMA32_RXERROR 0x000F0000 ++#define BCM43xx_DMA32_RXERR_NOERR 0x00000000 ++#define BCM43xx_DMA32_RXERR_PROT 0x00010000 ++#define BCM43xx_DMA32_RXERR_OVERFLOW 0x00020000 ++#define BCM43xx_DMA32_RXERR_BUFWRITE 0x00030000 ++#define BCM43xx_DMA32_RXERR_DESCREAD 0x00040000 ++#define BCM43xx_DMA32_RXACTIVE 0xFFF00000 ++ ++/* 32-bit DMA descriptor. */ ++struct bcm43xx_dmadesc32 { ++ __le32 control; ++ __le32 address; ++} __attribute__((__packed__)); ++#define BCM43xx_DMA32_DCTL_BYTECNT 0x00001FFF ++#define BCM43xx_DMA32_DCTL_ADDREXT_MASK 0x00030000 ++#define BCM43xx_DMA32_DCTL_ADDREXT_SHIFT 16 ++#define BCM43xx_DMA32_DCTL_DTABLEEND 0x10000000 ++#define BCM43xx_DMA32_DCTL_IRQ 0x20000000 ++#define BCM43xx_DMA32_DCTL_FRAMEEND 0x40000000 ++#define BCM43xx_DMA32_DCTL_FRAMESTART 0x80000000 ++ ++/* Address field Routing value. */ ++#define BCM43xx_DMA32_ROUTING 0xC0000000 ++#define BCM43xx_DMA32_ROUTING_SHIFT 30 ++#define BCM43xx_DMA32_NOTRANS 0x00000000 ++#define BCM43xx_DMA32_CLIENTTRANS 0x40000000 ++ ++ ++ ++/*** 64-bit DMA Engine. ***/ ++ ++/* 64-bit DMA controller registers. */ ++#define BCM43xx_DMA64_TXCTL 0x00 ++#define BCM43xx_DMA64_TXENABLE 0x00000001 ++#define BCM43xx_DMA64_TXSUSPEND 0x00000002 ++#define BCM43xx_DMA64_TXLOOPBACK 0x00000004 ++#define BCM43xx_DMA64_TXFLUSH 0x00000010 ++#define BCM43xx_DMA64_TXADDREXT_MASK 0x00030000 ++#define BCM43xx_DMA64_TXADDREXT_SHIFT 16 ++#define BCM43xx_DMA64_TXINDEX 0x04 ++#define BCM43xx_DMA64_TXRINGLO 0x08 ++#define BCM43xx_DMA64_TXRINGHI 0x0C ++#define BCM43xx_DMA64_TXSTATUS 0x10 ++#define BCM43xx_DMA64_TXSTATDPTR 0x00001FFF ++#define BCM43xx_DMA64_TXSTAT 0xF0000000 ++#define BCM43xx_DMA64_TXSTAT_DISABLED 0x00000000 ++#define BCM43xx_DMA64_TXSTAT_ACTIVE 0x10000000 ++#define BCM43xx_DMA64_TXSTAT_IDLEWAIT 0x20000000 ++#define BCM43xx_DMA64_TXSTAT_STOPPED 0x30000000 ++#define BCM43xx_DMA64_TXSTAT_SUSP 0x40000000 ++#define BCM43xx_DMA64_TXERROR 0x14 ++#define BCM43xx_DMA64_TXERRDPTR 0x0001FFFF ++#define BCM43xx_DMA64_TXERR 0xF0000000 ++#define BCM43xx_DMA64_TXERR_NOERR 0x00000000 ++#define BCM43xx_DMA64_TXERR_PROT 0x10000000 ++#define BCM43xx_DMA64_TXERR_UNDERRUN 0x20000000 ++#define BCM43xx_DMA64_TXERR_TRANSFER 0x30000000 ++#define BCM43xx_DMA64_TXERR_DESCREAD 0x40000000 ++#define BCM43xx_DMA64_TXERR_CORE 0x50000000 ++#define BCM43xx_DMA64_RXCTL 0x20 ++#define BCM43xx_DMA64_RXENABLE 0x00000001 ++#define BCM43xx_DMA64_RXFROFF_MASK 0x000000FE ++#define BCM43xx_DMA64_RXFROFF_SHIFT 1 ++#define BCM43xx_DMA64_RXDIRECTFIFO 0x00000100 ++#define BCM43xx_DMA64_RXADDREXT_MASK 0x00030000 ++#define BCM43xx_DMA64_RXADDREXT_SHIFT 16 ++#define BCM43xx_DMA64_RXINDEX 0x24 ++#define BCM43xx_DMA64_RXRINGLO 0x28 ++#define BCM43xx_DMA64_RXRINGHI 0x2C ++#define BCM43xx_DMA64_RXSTATUS 0x30 ++#define BCM43xx_DMA64_RXSTATDPTR 0x00001FFF ++#define BCM43xx_DMA64_RXSTAT 0xF0000000 ++#define BCM43xx_DMA64_RXSTAT_DISABLED 0x00000000 ++#define BCM43xx_DMA64_RXSTAT_ACTIVE 0x10000000 ++#define BCM43xx_DMA64_RXSTAT_IDLEWAIT 0x20000000 ++#define BCM43xx_DMA64_RXSTAT_STOPPED 0x30000000 ++#define BCM43xx_DMA64_RXSTAT_SUSP 0x40000000 ++#define BCM43xx_DMA64_RXERROR 0x34 ++#define BCM43xx_DMA64_RXERRDPTR 0x0001FFFF ++#define BCM43xx_DMA64_RXERR 0xF0000000 ++#define BCM43xx_DMA64_RXERR_NOERR 0x00000000 ++#define BCM43xx_DMA64_RXERR_PROT 0x10000000 ++#define BCM43xx_DMA64_RXERR_UNDERRUN 0x20000000 ++#define BCM43xx_DMA64_RXERR_TRANSFER 0x30000000 ++#define BCM43xx_DMA64_RXERR_DESCREAD 0x40000000 ++#define BCM43xx_DMA64_RXERR_CORE 0x50000000 ++ ++/* 64-bit DMA descriptor. */ ++struct bcm43xx_dmadesc64 { ++ __le32 control0; ++ __le32 control1; ++ __le32 address_low; ++ __le32 address_high; ++} __attribute__((__packed__)); ++#define BCM43xx_DMA64_DCTL0_DTABLEEND 0x10000000 ++#define BCM43xx_DMA64_DCTL0_IRQ 0x20000000 ++#define BCM43xx_DMA64_DCTL0_FRAMEEND 0x40000000 ++#define BCM43xx_DMA64_DCTL0_FRAMESTART 0x80000000 ++#define BCM43xx_DMA64_DCTL1_BYTECNT 0x00001FFF ++#define BCM43xx_DMA64_DCTL1_ADDREXT_MASK 0x00030000 ++#define BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT 16 ++ ++/* Address field Routing value. */ ++#define BCM43xx_DMA64_ROUTING 0xC0000000 ++#define BCM43xx_DMA64_ROUTING_SHIFT 30 ++#define BCM43xx_DMA64_NOTRANS 0x00000000 ++#define BCM43xx_DMA64_CLIENTTRANS 0x80000000 ++ ++ ++ ++struct bcm43xx_dmadesc_generic { ++ union { ++ struct bcm43xx_dmadesc32 dma32; ++ struct bcm43xx_dmadesc64 dma64; ++ } __attribute__((__packed__)); ++} __attribute__((__packed__)); ++ + + /* Misc DMA constants */ + #define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE +-#define BCM43xx_DMA_BUSADDRMAX 0x3FFFFFFF +-#define BCM43xx_DMA_DMABUSADDROFFSET (1 << 30) +-#define BCM43xx_DMA1_RX_FRAMEOFFSET 30 +-#define BCM43xx_DMA4_RX_FRAMEOFFSET 0 ++#define BCM43xx_DMA0_RX_FRAMEOFFSET 30 ++#define BCM43xx_DMA3_RX_FRAMEOFFSET 0 ++ + + /* DMA engine tuning knobs */ + #define BCM43xx_TXRING_SLOTS 512 + #define BCM43xx_RXRING_SLOTS 64 +-#define BCM43xx_DMA1_RXBUFFERSIZE (2304 + 100) +-#define BCM43xx_DMA4_RXBUFFERSIZE 16 ++#define BCM43xx_DMA0_RX_BUFFERSIZE (2304 + 100) ++#define BCM43xx_DMA3_RX_BUFFERSIZE 16 + /* Suspend the tx queue, if less than this percent slots are free. */ + #define BCM43xx_TXSUSPEND_PERCENT 20 + /* Resume the tx queue, if more than this percent slots are free. */ +@@ -86,17 +202,6 @@ struct bcm43xx_private; + struct bcm43xx_xmitstatus; + + +-struct bcm43xx_dmadesc { +- __le32 _control; +- __le32 _address; +-} __attribute__((__packed__)); +- +-/* Macros to access the bcm43xx_dmadesc struct */ +-#define get_desc_ctl(desc) le32_to_cpu((desc)->_control) +-#define set_desc_ctl(desc, ctl) do { (desc)->_control = cpu_to_le32(ctl); } while (0) +-#define get_desc_addr(desc) le32_to_cpu((desc)->_address) +-#define set_desc_addr(desc, addr) do { (desc)->_address = cpu_to_le32(addr); } while (0) +- + struct bcm43xx_dmadesc_meta { + /* The kernel DMA-able buffer. */ + struct sk_buff *skb; +@@ -105,15 +210,14 @@ struct bcm43xx_dmadesc_meta { + }; + + struct bcm43xx_dmaring { +- struct bcm43xx_private *bcm; + /* Kernel virtual base address of the ring memory. */ +- struct bcm43xx_dmadesc *vbase; +- /* DMA memory offset */ +- dma_addr_t memoffset; +- /* (Unadjusted) DMA base bus-address of the ring memory. */ +- dma_addr_t dmabase; ++ void *descbase; + /* Meta data about all descriptors. */ + struct bcm43xx_dmadesc_meta *meta; ++ /* DMA Routing value. */ ++ u32 routing; ++ /* (Unadjusted) DMA base bus-address of the ring memory. */ ++ dma_addr_t dmabase; + /* Number of descriptor slots in the ring. */ + int nr_slots; + /* Number of used descriptor slots. */ +@@ -127,12 +231,17 @@ struct bcm43xx_dmaring { + u32 frameoffset; + /* Descriptor buffer size. */ + u16 rx_buffersize; +- /* The MMIO base register of the DMA controller, this +- * ring is posted to. +- */ ++ /* The MMIO base register of the DMA controller. */ + u16 mmio_base; +- u8 tx:1, /* TRUE, if this is a TX ring. */ +- suspended:1; /* TRUE, if transfers are suspended on this ring. */ ++ /* DMA controller index number (0-5). */ ++ int index; ++ /* Boolean. Is this a TX ring? */ ++ u8 tx; ++ /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */ ++ u8 dma64; ++ /* Boolean. Are transfers suspended on this ring? */ ++ u8 suspended; ++ struct bcm43xx_private *bcm; + #ifdef CONFIG_BCM43XX_DEBUG + /* Maximum number of used slots. */ + int max_used_slots; +@@ -141,6 +250,34 @@ #endif /* CONFIG_BCM43XX_DEBUG*/ + + + static inline ++int bcm43xx_dma_desc2idx(struct bcm43xx_dmaring *ring, ++ struct bcm43xx_dmadesc_generic *desc) ++{ ++ if (ring->dma64) { ++ struct bcm43xx_dmadesc64 *dd64 = ring->descbase; ++ return (int)(&(desc->dma64) - dd64); ++ } else { ++ struct bcm43xx_dmadesc32 *dd32 = ring->descbase; ++ return (int)(&(desc->dma32) - dd32); ++ } ++} ++ ++static inline ++struct bcm43xx_dmadesc_generic * bcm43xx_dma_idx2desc(struct bcm43xx_dmaring *ring, ++ int slot, ++ struct bcm43xx_dmadesc_meta **meta) ++{ ++ *meta = &(ring->meta[slot]); ++ if (ring->dma64) { ++ struct bcm43xx_dmadesc64 *dd64 = ring->descbase; ++ return (struct bcm43xx_dmadesc_generic *)(&(dd64[slot])); ++ } else { ++ struct bcm43xx_dmadesc32 *dd32 = ring->descbase; ++ return (struct bcm43xx_dmadesc_generic *)(&(dd32[slot])); ++ } ++} ++ ++static inline + u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring, + u16 offset) + { +@@ -159,9 +296,13 @@ int bcm43xx_dma_init(struct bcm43xx_priv + void bcm43xx_dma_free(struct bcm43xx_private *bcm); + + int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, +- u16 dmacontroller_mmio_base); ++ u16 dmacontroller_mmio_base, ++ int dma64); + int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, +- u16 dmacontroller_mmio_base); ++ u16 dmacontroller_mmio_base, ++ int dma64); ++ ++u16 bcm43xx_dmacontroller_base(int dma64bit, int dmacontroller_idx); + + void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring); + void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring); +@@ -173,7 +314,6 @@ int bcm43xx_dma_tx(struct bcm43xx_privat + struct ieee80211_txb *txb); + void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); + +- + #else /* CONFIG_BCM43XX_DMA */ + + +@@ -188,13 +328,15 @@ void bcm43xx_dma_free(struct bcm43xx_pri + } + static inline + int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, +- u16 dmacontroller_mmio_base) ++ u16 dmacontroller_mmio_base, ++ int dma64) + { + return 0; + } + static inline + int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, +- u16 dmacontroller_mmio_base) ++ u16 dmacontroller_mmio_base, ++ int dma64) + { + return 0; + } +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +index ec80692..c3f90c8 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +@@ -51,12 +51,12 @@ static void bcm43xx_led_blink(unsigned l + struct bcm43xx_private *bcm = led->bcm; + unsigned long flags; + +- bcm43xx_lock_irqonly(bcm, flags); ++ spin_lock_irqsave(&bcm->leds_lock, flags); + if (led->blink_interval) { + bcm43xx_led_changestate(led); + mod_timer(&led->blink_timer, jiffies + led->blink_interval); + } +- bcm43xx_unlock_irqonly(bcm, flags); ++ spin_unlock_irqrestore(&bcm->leds_lock, flags); + } + + static void bcm43xx_led_blink_start(struct bcm43xx_led *led, +@@ -177,7 +177,9 @@ void bcm43xx_leds_update(struct bcm43xx_ + int i, turn_on; + unsigned long interval = 0; + u16 ledctl; ++ unsigned long flags; + ++ spin_lock_irqsave(&bcm->leds_lock, flags); + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); +@@ -266,6 +268,7 @@ #endif /* CONFIG_BCM43XX_DEBUG */ + ledctl &= ~(1 << i); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); ++ spin_unlock_irqrestore(&bcm->leds_lock, flags); + } + + void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) +@@ -274,7 +277,9 @@ void bcm43xx_leds_switch_all(struct bcm4 + u16 ledctl; + int i; + int bit_on; ++ unsigned long flags; + ++ spin_lock_irqsave(&bcm->leds_lock, flags); + ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); + for (i = 0; i < BCM43xx_NR_LEDS; i++) { + led = &(bcm->leds[i]); +@@ -290,4 +295,5 @@ void bcm43xx_leds_switch_all(struct bcm4 + ledctl &= ~(1 << i); + } + bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); ++ spin_unlock_irqrestore(&bcm->leds_lock, flags); + } +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c +index df317c1..3a73d89 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c +@@ -509,23 +509,20 @@ static void bcm43xx_synchronize_irq(stru + } + + /* Make sure we don't receive more data from the device. */ +-static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate) ++static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm) + { + unsigned long flags; +- u32 old; + +- bcm43xx_lock_irqonly(bcm, flags); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { +- bcm43xx_unlock_irqonly(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); + return -EBUSY; + } +- old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); +- bcm43xx_unlock_irqonly(bcm, flags); ++ bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); ++ bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */ ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); + bcm43xx_synchronize_irq(bcm); + +- if (oldstate) +- *oldstate = old; +- + return 0; + } + +@@ -537,7 +534,6 @@ static int bcm43xx_read_radioinfo(struct + u16 manufact; + u16 version; + u8 revision; +- s8 i; + + if (bcm->chip_id == 0x4317) { + if (bcm->chip_rev == 0x00) +@@ -580,20 +576,11 @@ static int bcm43xx_read_radioinfo(struct + radio->version = version; + radio->revision = revision; + +- /* Set default attenuation values. */ +- radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); +- radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); +- radio->txctl1 = bcm43xx_default_txctl1(bcm); +- radio->txctl2 = 0xFFFF; + if (phy->type == BCM43xx_PHYTYPE_A) + radio->txpower_desired = bcm->sprom.maxpower_aphy; + else + radio->txpower_desired = bcm->sprom.maxpower_bgphy; + +- /* Initialize the in-memory nrssi Lookup Table. */ +- for (i = 0; i < 64; i++) +- radio->nrssi_lt[i] = i; +- + return 0; + + err_unsupported_radio: +@@ -1250,10 +1237,6 @@ int bcm43xx_switch_core(struct bcm43xx_p + goto out; + + bcm->current_core = new_core; +- bcm->current_80211_core_idx = -1; +- if (new_core->id == BCM43xx_COREID_80211) +- bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0])); +- + out: + return err; + } +@@ -1389,6 +1372,7 @@ void bcm43xx_wireless_core_reset(struct + if ((bcm43xx_core_enabled(bcm)) && + !bcm43xx_using_pio(bcm)) { + //FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here? ++#if 0 + #ifndef CONFIG_BCM947XX + /* reset all used DMA controllers. */ + bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE); +@@ -1399,6 +1383,7 @@ #ifndef CONFIG_BCM947XX + if (bcm->current_core->rev < 5) + bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); + #endif ++#endif + } + if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { + bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, +@@ -1423,43 +1408,23 @@ static void bcm43xx_wireless_core_disabl + bcm43xx_core_disable(bcm, 0); + } + +-/* Mark the current 80211 core inactive. +- * "active_80211_core" is the other 80211 core, which is used. +- */ +-static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm, +- struct bcm43xx_coreinfo *active_80211_core) ++/* Mark the current 80211 core inactive. */ ++static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm) + { + u32 sbtmstatelow; +- struct bcm43xx_coreinfo *old_core; +- int err = 0; + + bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + bcm43xx_radio_turn_off(bcm); + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); +- sbtmstatelow &= ~0x200a0000; +- sbtmstatelow |= 0xa0000; ++ sbtmstatelow &= 0xDFF5FFFF; ++ sbtmstatelow |= 0x000A0000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); + sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); +- sbtmstatelow &= ~0xa0000; +- sbtmstatelow |= 0x80000; ++ sbtmstatelow &= 0xFFF5FFFF; ++ sbtmstatelow |= 0x00080000; + bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + udelay(1); +- +- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) { +- old_core = bcm->current_core; +- err = bcm43xx_switch_core(bcm, active_80211_core); +- if (err) +- goto out; +- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); +- sbtmstatelow &= ~0x20000000; +- sbtmstatelow |= 0x20000000; +- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); +- err = bcm43xx_switch_core(bcm, old_core); +- } +- +-out: +- return err; + } + + static void handle_irq_transmit_status(struct bcm43xx_private *bcm) +@@ -1581,17 +1546,7 @@ static void handle_irq_noise(struct bcm4 + else + average -= 48; + +-/* FIXME: This is wrong, but people want fancy stats. well... */ +-bcm->stats.noise = average; +- if (average > -65) +- bcm->stats.link_quality = 0; +- else if (average > -75) +- bcm->stats.link_quality = 1; +- else if (average > -85) +- bcm->stats.link_quality = 2; +- else +- bcm->stats.link_quality = 3; +-// dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average); ++ bcm->stats.noise = average; + drop_calculation: + bcm->noisecalc.calculation_running = 0; + return; +@@ -1709,8 +1664,9 @@ static void handle_irq_beacon(struct bcm + static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) + { + u32 reason; +- u32 dma_reason[4]; +- int activity = 0; ++ u32 dma_reason[6]; ++ u32 merged_dma_reason = 0; ++ int i, activity = 0; + unsigned long flags; + + #ifdef CONFIG_BCM43XX_DEBUG +@@ -1720,12 +1676,12 @@ #else + # define bcmirq_handled(irq) do { /* nothing */ } while (0) + #endif /* CONFIG_BCM43XX_DEBUG*/ + +- bcm43xx_lock_irqonly(bcm, flags); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + reason = bcm->irq_reason; +- dma_reason[0] = bcm->dma_reason[0]; +- dma_reason[1] = bcm->dma_reason[1]; +- dma_reason[2] = bcm->dma_reason[2]; +- dma_reason[3] = bcm->dma_reason[3]; ++ for (i = 5; i >= 0; i--) { ++ dma_reason[i] = bcm->dma_reason[i]; ++ merged_dma_reason |= dma_reason[i]; ++ } + + if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) { + /* TX error. We get this when Template Ram is written in wrong endianess +@@ -1736,27 +1692,25 @@ #endif /* CONFIG_BCM43XX_DEBUG*/ + printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n"); + bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR); + } +- if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_FATALMASK) | +- (dma_reason[1] & BCM43xx_DMAIRQ_FATALMASK) | +- (dma_reason[2] & BCM43xx_DMAIRQ_FATALMASK) | +- (dma_reason[3] & BCM43xx_DMAIRQ_FATALMASK))) { ++ if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_FATALMASK)) { + printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: " +- "0x%08X, 0x%08X, 0x%08X, 0x%08X\n", ++ "0x%08X, 0x%08X, 0x%08X, " ++ "0x%08X, 0x%08X, 0x%08X\n", + dma_reason[0], dma_reason[1], +- dma_reason[2], dma_reason[3]); ++ dma_reason[2], dma_reason[3], ++ dma_reason[4], dma_reason[5]); + bcm43xx_controller_restart(bcm, "DMA error"); + mmiowb(); +- bcm43xx_unlock_irqonly(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); + return; + } +- if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | +- (dma_reason[1] & BCM43xx_DMAIRQ_NONFATALMASK) | +- (dma_reason[2] & BCM43xx_DMAIRQ_NONFATALMASK) | +- (dma_reason[3] & BCM43xx_DMAIRQ_NONFATALMASK))) { ++ if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_NONFATALMASK)) { + printkl(KERN_ERR PFX "DMA error: " +- "0x%08X, 0x%08X, 0x%08X, 0x%08X\n", ++ "0x%08X, 0x%08X, 0x%08X, " ++ "0x%08X, 0x%08X, 0x%08X\n", + dma_reason[0], dma_reason[1], +- dma_reason[2], dma_reason[3]); ++ dma_reason[2], dma_reason[3], ++ dma_reason[4], dma_reason[5]); + } + + if (reason & BCM43xx_IRQ_PS) { +@@ -1791,8 +1745,6 @@ #endif /* CONFIG_BCM43XX_DEBUG*/ + } + + /* Check the DMA reason registers for received data. */ +- assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); +- assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); + if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { + if (bcm43xx_using_pio(bcm)) + bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0); +@@ -1800,13 +1752,17 @@ #endif /* CONFIG_BCM43XX_DEBUG*/ + bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0); + /* We intentionally don't set "activity" to 1, here. */ + } ++ assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); ++ assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); + if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { + if (bcm43xx_using_pio(bcm)) + bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3); + else +- bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring1); ++ bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring3); + activity = 1; + } ++ assert(!(dma_reason[4] & BCM43xx_DMAIRQ_RX_DONE)); ++ assert(!(dma_reason[5] & BCM43xx_DMAIRQ_RX_DONE)); + bcmirq_handled(BCM43xx_IRQ_RX); + + if (reason & BCM43xx_IRQ_XMIT_STATUS) { +@@ -1834,7 +1790,7 @@ #undef bcmirq_handled + bcm43xx_leds_update(bcm, activity); + bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); + mmiowb(); +- bcm43xx_unlock_irqonly(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); + } + + static void pio_irq_workaround(struct bcm43xx_private *bcm, +@@ -1863,14 +1819,18 @@ static void bcm43xx_interrupt_ack(struct + + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason); + +- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_REASON, + bcm->dma_reason[0]); +- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON, ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, + bcm->dma_reason[1]); +- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON, ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON, + bcm->dma_reason[2]); +- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON, ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON, + bcm->dma_reason[3]); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON, ++ bcm->dma_reason[4]); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_REASON, ++ bcm->dma_reason[5]); + } + + /* Interrupt handler top-half */ +@@ -1885,14 +1845,8 @@ static irqreturn_t bcm43xx_interrupt_han + + spin_lock(&bcm->irq_lock); + +- /* Only accept IRQs, if we are initialized properly. +- * This avoids an RX race while initializing. +- * We should probably not enable IRQs before we are initialized +- * completely, but some careful work is needed to fix this. I think it +- * is best to stay with this cheap workaround for now... . +- */ +- if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) +- goto out; ++ assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); ++ assert(bcm->current_core->id == BCM43xx_COREID_80211); + + reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + if (reason == 0xffffffff) { +@@ -1904,14 +1858,18 @@ static irqreturn_t bcm43xx_interrupt_han + if (!reason) + goto out; + +- bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) +- & 0x0001dc00; +- bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) +- & 0x0000dc00; +- bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) +- & 0x0000dc00; +- bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) +- & 0x0001dc00; ++ bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON) ++ & 0x0001DC00; ++ bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) ++ & 0x0000DC00; ++ bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) ++ & 0x0000DC00; ++ bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) ++ & 0x0001DC00; ++ bcm->dma_reason[4] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) ++ & 0x0000DC00; ++ bcm->dma_reason[5] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA5_REASON) ++ & 0x0000DC00; + + bcm43xx_interrupt_ack(bcm, reason); + +@@ -1930,16 +1888,18 @@ out: + + static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) + { ++ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); ++ + if (bcm->firmware_norelease && !force) + return; /* Suspending or controller reset. */ +- release_firmware(bcm->ucode); +- bcm->ucode = NULL; +- release_firmware(bcm->pcm); +- bcm->pcm = NULL; +- release_firmware(bcm->initvals0); +- bcm->initvals0 = NULL; +- release_firmware(bcm->initvals1); +- bcm->initvals1 = NULL; ++ release_firmware(phy->ucode); ++ phy->ucode = NULL; ++ release_firmware(phy->pcm); ++ phy->pcm = NULL; ++ release_firmware(phy->initvals0); ++ phy->initvals0 = NULL; ++ release_firmware(phy->initvals1); ++ phy->initvals1 = NULL; + } + + static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) +@@ -1950,11 +1910,11 @@ static int bcm43xx_request_firmware(stru + int nr; + char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 }; + +- if (!bcm->ucode) { ++ if (!phy->ucode) { + snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw", + (rev >= 5 ? 5 : rev), + modparam_fwpostfix); +- err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev); ++ err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: Microcode \"%s\" not available or load failed.\n", +@@ -1963,12 +1923,12 @@ static int bcm43xx_request_firmware(stru + } + } + +- if (!bcm->pcm) { ++ if (!phy->pcm) { + snprintf(buf, ARRAY_SIZE(buf), + "bcm43xx_pcm%d%s.fw", + (rev < 5 ? 4 : 5), + modparam_fwpostfix); +- err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev); ++ err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: PCM \"%s\" not available or load failed.\n", +@@ -1977,7 +1937,7 @@ static int bcm43xx_request_firmware(stru + } + } + +- if (!bcm->initvals0) { ++ if (!phy->initvals0) { + if (rev == 2 || rev == 4) { + switch (phy->type) { + case BCM43xx_PHYTYPE_A: +@@ -2008,20 +1968,20 @@ static int bcm43xx_request_firmware(stru + snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", + nr, modparam_fwpostfix); + +- err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev); ++ err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: InitVals \"%s\" not available or load failed.\n", + buf); + goto error; + } +- if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) { ++ if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) { + printk(KERN_ERR PFX "InitVals fileformat error.\n"); + goto error; + } + } + +- if (!bcm->initvals1) { ++ if (!phy->initvals1) { + if (rev >= 5) { + u32 sbtmstatehigh; + +@@ -2043,14 +2003,14 @@ static int bcm43xx_request_firmware(stru + snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", + nr, modparam_fwpostfix); + +- err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev); ++ err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev); + if (err) { + printk(KERN_ERR PFX + "Error: InitVals \"%s\" not available or load failed.\n", + buf); + goto error; + } +- if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) { ++ if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) { + printk(KERN_ERR PFX "InitVals fileformat error.\n"); + goto error; + } +@@ -2070,12 +2030,13 @@ err_noinitval: + + static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) + { ++ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + const u32 *data; + unsigned int i, len; + + /* Upload Microcode. */ +- data = (u32 *)(bcm->ucode->data); +- len = bcm->ucode->size / sizeof(u32); ++ data = (u32 *)(phy->ucode->data); ++ len = phy->ucode->size / sizeof(u32); + bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000); + for (i = 0; i < len; i++) { + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, +@@ -2084,8 +2045,8 @@ static void bcm43xx_upload_microcode(str + } + + /* Upload PCM data. */ +- data = (u32 *)(bcm->pcm->data); +- len = bcm->pcm->size / sizeof(u32); ++ data = (u32 *)(phy->pcm->data); ++ len = phy->pcm->size / sizeof(u32); + bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea); + bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000); + bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb); +@@ -2131,15 +2092,16 @@ err_format: + + static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) + { ++ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + int err; + +- err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data, +- bcm->initvals0->size / sizeof(struct bcm43xx_initval)); ++ err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data, ++ phy->initvals0->size / sizeof(struct bcm43xx_initval)); + if (err) + goto out; +- if (bcm->initvals1) { +- err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data, +- bcm->initvals1->size / sizeof(struct bcm43xx_initval)); ++ if (phy->initvals1) { ++ err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data, ++ phy->initvals1->size / sizeof(struct bcm43xx_initval)); + if (err) + goto out; + } +@@ -2156,9 +2118,7 @@ #endif + + static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) + { +- int res; +- unsigned int i; +- u32 data; ++ int err; + + bcm->irq = bcm->pci_dev->irq; + #ifdef CONFIG_BCM947XX +@@ -2175,32 +2135,12 @@ #ifdef CONFIG_BCM947XX + } + } + #endif +- res = request_irq(bcm->irq, bcm43xx_interrupt_handler, ++ err = request_irq(bcm->irq, bcm43xx_interrupt_handler, + IRQF_SHARED, KBUILD_MODNAME, bcm); +- if (res) { ++ if (err) + printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); +- return -ENODEV; +- } +- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff); +- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); +- i = 0; +- while (1) { +- data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); +- if (data == BCM43xx_IRQ_READY) +- break; +- i++; +- if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) { +- printk(KERN_ERR PFX "Card IRQ register not responding. " +- "Giving up.\n"); +- free_irq(bcm->irq, bcm); +- return -ENODEV; +- } +- udelay(10); +- } +- // dummy read +- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); + +- return 0; ++ return err; + } + + /* Switch to the core used to write the GPIO register. +@@ -2298,13 +2238,17 @@ static int bcm43xx_gpio_cleanup(struct b + /* http://bcm-specs.sipsolutions.net/EnableMac */ + void bcm43xx_mac_enable(struct bcm43xx_private *bcm) + { +- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, +- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) +- | BCM43xx_SBF_MAC_ENABLED); +- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); +- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ +- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ +- bcm43xx_power_saving_ctl_bits(bcm, -1, -1); ++ bcm->mac_suspended--; ++ assert(bcm->mac_suspended >= 0); ++ if (bcm->mac_suspended == 0) { ++ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, ++ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) ++ | BCM43xx_SBF_MAC_ENABLED); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); ++ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ ++ bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ ++ bcm43xx_power_saving_ctl_bits(bcm, -1, -1); ++ } + } + + /* http://bcm-specs.sipsolutions.net/SuspendMAC */ +@@ -2313,18 +2257,23 @@ void bcm43xx_mac_suspend(struct bcm43xx_ + int i; + u32 tmp; + +- bcm43xx_power_saving_ctl_bits(bcm, -1, 1); +- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, +- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) +- & ~BCM43xx_SBF_MAC_ENABLED); +- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ +- for (i = 100000; i; i--) { +- tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); +- if (tmp & BCM43xx_IRQ_READY) +- return; +- udelay(10); ++ assert(bcm->mac_suspended >= 0); ++ if (bcm->mac_suspended == 0) { ++ bcm43xx_power_saving_ctl_bits(bcm, -1, 1); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, ++ bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) ++ & ~BCM43xx_SBF_MAC_ENABLED); ++ bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ ++ for (i = 10000; i; i--) { ++ tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); ++ if (tmp & BCM43xx_IRQ_READY) ++ goto out; ++ udelay(1); ++ } ++ printkl(KERN_ERR PFX "MAC suspend failed\n"); + } +- printkl(KERN_ERR PFX "MAC suspend failed\n"); ++out: ++ bcm->mac_suspended++; + } + + void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, +@@ -2394,7 +2343,6 @@ static void bcm43xx_chip_cleanup(struct + if (!modparam_noleds) + bcm43xx_leds_exit(bcm); + bcm43xx_gpio_cleanup(bcm); +- free_irq(bcm->irq, bcm); + bcm43xx_release_firmware(bcm, 0); + } + +@@ -2406,7 +2354,7 @@ static int bcm43xx_chip_init(struct bcm4 + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + int err; +- int tmp; ++ int i, tmp; + u32 value32; + u16 value16; + +@@ -2419,13 +2367,53 @@ static int bcm43xx_chip_init(struct bcm4 + goto out; + bcm43xx_upload_microcode(bcm); + +- err = bcm43xx_initialize_irq(bcm); +- if (err) ++ bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); ++ i = 0; ++ while (1) { ++ value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); ++ if (value32 == BCM43xx_IRQ_READY) ++ break; ++ i++; ++ if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) { ++ printk(KERN_ERR PFX "IRQ_READY timeout\n"); ++ err = -ENODEV; ++ goto err_release_fw; ++ } ++ udelay(10); ++ } ++ bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ ++ ++ value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, ++ BCM43xx_UCODE_REVISION); ++ ++ dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x " ++ "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", value16, ++ bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, ++ BCM43xx_UCODE_PATCHLEVEL), ++ (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, ++ BCM43xx_UCODE_DATE) >> 12) & 0xf, ++ (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, ++ BCM43xx_UCODE_DATE) >> 8) & 0xf, ++ bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, ++ BCM43xx_UCODE_DATE) & 0xff, ++ (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, ++ BCM43xx_UCODE_TIME) >> 11) & 0x1f, ++ (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, ++ BCM43xx_UCODE_TIME) >> 5) & 0x3f, ++ bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, ++ BCM43xx_UCODE_TIME) & 0x1f); ++ ++ if ( value16 > 0x128 ) { ++ dprintk(KERN_ERR PFX ++ "Firmware: no support for microcode rev > 0x128\n"); ++ err = -1; + goto err_release_fw; ++ } + + err = bcm43xx_gpio_init(bcm); + if (err) +- goto err_free_irq; ++ goto err_release_fw; + + err = bcm43xx_upload_initvals(bcm); + if (err) +@@ -2489,10 +2477,12 @@ static int bcm43xx_chip_init(struct bcm4 + bcm43xx_write32(bcm, 0x018C, 0x02000000); + } + bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000); +- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0001DC00); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_IRQ_MASK, 0x0001DC00); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0000DC00); + bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00); +- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0000DC00); +- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0001DC00); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0001DC00); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00); ++ bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00); + + value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); + value32 |= 0x00100000; +@@ -2509,8 +2499,6 @@ err_radio_off: + bcm43xx_radio_turn_off(bcm); + err_gpio_cleanup: + bcm43xx_gpio_cleanup(bcm); +-err_free_irq: +- free_irq(bcm->irq, bcm); + err_release_fw: + bcm43xx_release_firmware(bcm, 1); + goto out; +@@ -2550,11 +2538,9 @@ static void bcm43xx_init_struct_phyinfo( + { + /* Initialize a "phyinfo" structure. The structure is already + * zeroed out. ++ * This is called on insmod time to initialize members. + */ +- phy->antenna_diversity = 0xFFFF; + phy->savedpctlreg = 0xFFFF; +- phy->minlowsig[0] = 0xFFFF; +- phy->minlowsig[1] = 0xFFFF; + spin_lock_init(&phy->lock); + } + +@@ -2562,14 +2548,11 @@ static void bcm43xx_init_struct_radioinf + { + /* Initialize a "radioinfo" structure. The structure is already + * zeroed out. ++ * This is called on insmod time to initialize members. + */ + radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; + radio->channel = 0xFF; + radio->initial_channel = 0xFF; +- radio->lofcal = 0xFFFF; +- radio->initval = 0xFFFF; +- radio->nrssi[0] = -1000; +- radio->nrssi[1] = -1000; + } + + static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) +@@ -2587,7 +2570,6 @@ static int bcm43xx_probe_cores(struct bc + * BCM43xx_MAX_80211_CORES); + memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) + * BCM43xx_MAX_80211_CORES); +- bcm->current_80211_core_idx = -1; + bcm->nr_80211_available = 0; + bcm->current_core = NULL; + bcm->active_80211_core = NULL; +@@ -2757,6 +2739,7 @@ #endif + goto out; + } + bcm->nr_80211_available++; ++ core->priv = ext_80211; + bcm43xx_init_struct_phyinfo(&ext_80211->phy); + bcm43xx_init_struct_radioinfo(&ext_80211->radio); + break; +@@ -2857,7 +2840,8 @@ static void bcm43xx_wireless_core_cleanu + } + + /* http://bcm-specs.sipsolutions.net/80211Init */ +-static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm) ++static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm, ++ int active_wlcore) + { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); +@@ -2939,19 +2923,26 @@ static int bcm43xx_wireless_core_init(st + if (bcm->current_core->rev >= 5) + bcm43xx_write16(bcm, 0x043C, 0x000C); + +- if (bcm43xx_using_pio(bcm)) +- err = bcm43xx_pio_init(bcm); +- else +- err = bcm43xx_dma_init(bcm); +- if (err) +- goto err_chip_cleanup; ++ if (active_wlcore) { ++ if (bcm43xx_using_pio(bcm)) ++ err = bcm43xx_pio_init(bcm); ++ else ++ err = bcm43xx_dma_init(bcm); ++ if (err) ++ goto err_chip_cleanup; ++ } + bcm43xx_write16(bcm, 0x0612, 0x0050); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); + bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); + +- bcm43xx_mac_enable(bcm); +- bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); ++ if (active_wlcore) { ++ if (radio->initial_channel != 0xFF) ++ bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0); ++ } + ++ /* Don't enable MAC/IRQ here, as it will race with the IRQ handler. ++ * We enable it later. ++ */ + bcm->current_core->initialized = 1; + out: + return err; +@@ -3066,11 +3057,6 @@ out: + return err; + } + +-static void bcm43xx_softmac_init(struct bcm43xx_private *bcm) +-{ +- ieee80211softmac_start(bcm->net_dev); +-} +- + static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) + { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); +@@ -3178,51 +3164,43 @@ static void bcm43xx_periodic_work_handle + int badness; + + badness = estimate_periodic_work_badness(bcm->periodic_state); ++ mutex_lock(&bcm->mutex); ++ netif_tx_disable(bcm->net_dev); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (badness > BADNESS_LIMIT) { + /* Periodic work will take a long time, so we want it to + * be preemtible. + */ +- bcm43xx_lock_irqonly(bcm, flags); +- netif_stop_queue(bcm->net_dev); ++ bcm43xx_mac_suspend(bcm); + if (bcm43xx_using_pio(bcm)) + bcm43xx_pio_freeze_txqueues(bcm); + savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); +- bcm43xx_unlock_irqonly(bcm, flags); +- bcm43xx_lock_noirq(bcm); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); + bcm43xx_synchronize_irq(bcm); +- } else { +- /* Periodic work should take short time, so we want low +- * locking overhead. +- */ +- bcm43xx_lock_irqsafe(bcm, flags); + } + + do_periodic_work(bcm); + + if (badness > BADNESS_LIMIT) { +- bcm43xx_lock_irqonly(bcm, flags); +- if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) { +- tasklet_enable(&bcm->isr_tasklet); +- bcm43xx_interrupt_enable(bcm, savedirqs); +- if (bcm43xx_using_pio(bcm)) +- bcm43xx_pio_thaw_txqueues(bcm); +- } +- netif_wake_queue(bcm->net_dev); +- mmiowb(); +- bcm43xx_unlock_irqonly(bcm, flags); +- bcm43xx_unlock_noirq(bcm); +- } else { +- mmiowb(); +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_lock_irqsave(&bcm->irq_lock, flags); ++ tasklet_enable(&bcm->isr_tasklet); ++ bcm43xx_interrupt_enable(bcm, savedirqs); ++ if (bcm43xx_using_pio(bcm)) ++ bcm43xx_pio_thaw_txqueues(bcm); ++ bcm43xx_mac_enable(bcm); + } ++ mmiowb(); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ netif_wake_queue(bcm->net_dev); ++ mutex_unlock(&bcm->mutex); + } + +-static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) ++void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) + { + cancel_rearming_delayed_work(&bcm->periodic_work); + } + +-static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) ++void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) + { + struct work_struct *work = &(bcm->periodic_work); + +@@ -3243,9 +3221,9 @@ static int bcm43xx_rng_read(struct hwrng + struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv; + unsigned long flags; + +- bcm43xx_lock_irqonly(bcm, flags); ++ spin_lock_irqsave(&(bcm)->irq_lock, flags); + *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG); +- bcm43xx_unlock_irqonly(bcm, flags); ++ spin_unlock_irqrestore(&(bcm)->irq_lock, flags); + + return (sizeof(u16)); + } +@@ -3271,139 +3249,329 @@ static int bcm43xx_rng_init(struct bcm43 + return err; + } + +-/* This is the opposite of bcm43xx_init_board() */ +-static void bcm43xx_free_board(struct bcm43xx_private *bcm) ++static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm) + { ++ int ret = 0; + int i, err; ++ struct bcm43xx_coreinfo *core; + +- bcm43xx_lock_noirq(bcm); ++ bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); ++ for (i = 0; i < bcm->nr_80211_available; i++) { ++ core = &(bcm->core_80211[i]); ++ assert(core->available); ++ if (!core->initialized) ++ continue; ++ err = bcm43xx_switch_core(bcm, core); ++ if (err) { ++ dprintk(KERN_ERR PFX "shutdown_all_wireless_cores " ++ "switch_core failed (%d)\n", err); ++ ret = err; ++ continue; ++ } ++ bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); ++ bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ ++ bcm43xx_wireless_core_cleanup(bcm); ++ if (core == bcm->active_80211_core) ++ bcm->active_80211_core = NULL; ++ } ++ free_irq(bcm->irq, bcm); ++ bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); ++ ++ return ret; ++} ++ ++/* This is the opposite of bcm43xx_init_board() */ ++static void bcm43xx_free_board(struct bcm43xx_private *bcm) ++{ ++ bcm43xx_rng_exit(bcm); + bcm43xx_sysfs_unregister(bcm); + bcm43xx_periodic_tasks_delete(bcm); + +- bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); ++ mutex_lock(&(bcm)->mutex); ++ bcm43xx_shutdown_all_wireless_cores(bcm); ++ bcm43xx_pctl_set_crystal(bcm, 0); ++ mutex_unlock(&(bcm)->mutex); ++} + +- bcm43xx_rng_exit(bcm); ++static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy) ++{ ++ phy->antenna_diversity = 0xFFFF; ++ memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); ++ memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos)); ++ ++ /* Flags */ ++ phy->calibrated = 0; ++ phy->is_locked = 0; ++ ++ if (phy->_lo_pairs) { ++ memset(phy->_lo_pairs, 0, ++ sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT); ++ } ++ memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain)); ++} ++ ++static void prepare_radiodata_for_init(struct bcm43xx_private *bcm, ++ struct bcm43xx_radioinfo *radio) ++{ ++ int i; ++ ++ /* Set default attenuation values. */ ++ radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); ++ radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); ++ radio->txctl1 = bcm43xx_default_txctl1(bcm); ++ radio->txctl2 = 0xFFFF; ++ radio->txpwr_offset = 0; ++ ++ /* NRSSI */ ++ radio->nrssislope = 0; ++ for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++) ++ radio->nrssi[i] = -1000; ++ for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++) ++ radio->nrssi_lt[i] = i; ++ ++ radio->lofcal = 0xFFFF; ++ radio->initval = 0xFFFF; ++ ++ radio->aci_enable = 0; ++ radio->aci_wlan_automatic = 0; ++ radio->aci_hw_rssi = 0; ++} ++ ++static void prepare_priv_for_init(struct bcm43xx_private *bcm) ++{ ++ int i; ++ struct bcm43xx_coreinfo *core; ++ struct bcm43xx_coreinfo_80211 *wlext; ++ ++ assert(!bcm->active_80211_core); ++ ++ bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); ++ ++ /* Flags */ ++ bcm->was_initialized = 0; ++ bcm->reg124_set_0x4 = 0; ++ ++ /* Stats */ ++ memset(&bcm->stats, 0, sizeof(bcm->stats)); ++ ++ /* Wireless core data */ + for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { +- if (!bcm->core_80211[i].available) +- continue; +- if (!bcm->core_80211[i].initialized) ++ core = &(bcm->core_80211[i]); ++ wlext = core->priv; ++ ++ if (!core->available) + continue; ++ assert(wlext == &(bcm->core_80211_ext[i])); + +- err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); +- assert(err == 0); +- bcm43xx_wireless_core_cleanup(bcm); ++ prepare_phydata_for_init(&wlext->phy); ++ prepare_radiodata_for_init(bcm, &wlext->radio); + } + +- bcm43xx_pctl_set_crystal(bcm, 0); ++ /* IRQ related flags */ ++ bcm->irq_reason = 0; ++ memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason)); ++ bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; + +- bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); +- bcm43xx_unlock_noirq(bcm); ++ bcm->mac_suspended = 1; ++ ++ /* Noise calculation context */ ++ memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc)); ++ ++ /* Periodic work context */ ++ bcm->periodic_state = 0; + } + +-static int bcm43xx_init_board(struct bcm43xx_private *bcm) ++static int wireless_core_up(struct bcm43xx_private *bcm, ++ int active_wlcore) ++{ ++ int err; ++ ++ if (!bcm43xx_core_enabled(bcm)) ++ bcm43xx_wireless_core_reset(bcm, 1); ++ if (!active_wlcore) ++ bcm43xx_wireless_core_mark_inactive(bcm); ++ err = bcm43xx_wireless_core_init(bcm, active_wlcore); ++ if (err) ++ goto out; ++ if (!active_wlcore) ++ bcm43xx_radio_turn_off(bcm); ++out: ++ return err; ++} ++ ++/* Select and enable the "to be used" wireless core. ++ * Locking: bcm->mutex must be aquired before calling this. ++ * bcm->irq_lock must not be aquired. ++ */ ++int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm, ++ int phytype) + { + int i, err; +- int connect_phy; ++ struct bcm43xx_coreinfo *active_core = NULL; ++ struct bcm43xx_coreinfo_80211 *active_wlext = NULL; ++ struct bcm43xx_coreinfo *core; ++ struct bcm43xx_coreinfo_80211 *wlext; ++ int adjust_active_sbtmstatelow = 0; + + might_sleep(); + +- bcm43xx_lock_noirq(bcm); +- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); ++ if (phytype < 0) { ++ /* If no phytype is requested, select the first core. */ ++ assert(bcm->core_80211[0].available); ++ wlext = bcm->core_80211[0].priv; ++ phytype = wlext->phy.type; ++ } ++ /* Find the requested core. */ ++ for (i = 0; i < bcm->nr_80211_available; i++) { ++ core = &(bcm->core_80211[i]); ++ wlext = core->priv; ++ if (wlext->phy.type == phytype) { ++ active_core = core; ++ active_wlext = wlext; ++ break; ++ } ++ } ++ if (!active_core) ++ return -ESRCH; /* No such PHYTYPE on this board. */ ++ ++ if (bcm->active_80211_core) { ++ /* We already selected a wl core in the past. ++ * So first clean up everything. ++ */ ++ dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n"); ++ ieee80211softmac_stop(bcm->net_dev); ++ bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); ++ err = bcm43xx_disable_interrupts_sync(bcm); ++ assert(!err); ++ tasklet_enable(&bcm->isr_tasklet); ++ err = bcm43xx_shutdown_all_wireless_cores(bcm); ++ if (err) ++ goto error; ++ /* Ok, everything down, continue to re-initialize. */ ++ bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); ++ } ++ ++ /* Reset all data structures. */ ++ prepare_priv_for_init(bcm); + +- err = bcm43xx_pctl_set_crystal(bcm, 1); +- if (err) +- goto out; +- err = bcm43xx_pctl_init(bcm); +- if (err) +- goto err_crystal_off; + err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); + if (err) +- goto err_crystal_off; ++ goto error; + +- tasklet_enable(&bcm->isr_tasklet); ++ /* Mark all unused cores "inactive". */ + for (i = 0; i < bcm->nr_80211_available; i++) { +- err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); +- assert(err != -ENODEV); +- if (err) +- goto err_80211_unwind; ++ core = &(bcm->core_80211[i]); ++ wlext = core->priv; + +- /* Enable the selected wireless core. +- * Connect PHY only on the first core. +- */ +- if (!bcm43xx_core_enabled(bcm)) { +- if (bcm->nr_80211_available == 1) { +- connect_phy = bcm43xx_current_phy(bcm)->connected; +- } else { +- if (i == 0) +- connect_phy = 1; +- else +- connect_phy = 0; +- } +- bcm43xx_wireless_core_reset(bcm, connect_phy); ++ if (core == active_core) ++ continue; ++ err = bcm43xx_switch_core(bcm, core); ++ if (err) { ++ dprintk(KERN_ERR PFX "Could not switch to inactive " ++ "802.11 core (%d)\n", err); ++ goto error; + } ++ err = wireless_core_up(bcm, 0); ++ if (err) { ++ dprintk(KERN_ERR PFX "core_up for inactive 802.11 core " ++ "failed (%d)\n", err); ++ goto error; ++ } ++ adjust_active_sbtmstatelow = 1; ++ } + +- if (i != 0) +- bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]); +- +- err = bcm43xx_wireless_core_init(bcm); +- if (err) +- goto err_80211_unwind; ++ /* Now initialize the active 802.11 core. */ ++ err = bcm43xx_switch_core(bcm, active_core); ++ if (err) { ++ dprintk(KERN_ERR PFX "Could not switch to active " ++ "802.11 core (%d)\n", err); ++ goto error; ++ } ++ if (adjust_active_sbtmstatelow && ++ active_wlext->phy.type == BCM43xx_PHYTYPE_G) { ++ u32 sbtmstatelow; + +- if (i != 0) { +- bcm43xx_mac_suspend(bcm); +- bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); +- bcm43xx_radio_turn_off(bcm); +- } ++ sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); ++ sbtmstatelow |= 0x20000000; ++ bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); + } +- bcm->active_80211_core = &bcm->core_80211[0]; +- if (bcm->nr_80211_available >= 2) { +- bcm43xx_switch_core(bcm, &bcm->core_80211[0]); +- bcm43xx_mac_enable(bcm); ++ err = wireless_core_up(bcm, 1); ++ if (err) { ++ dprintk(KERN_ERR PFX "core_up for active 802.11 core " ++ "failed (%d)\n", err); ++ goto error; + } +- err = bcm43xx_rng_init(bcm); ++ err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); + if (err) +- goto err_80211_unwind; ++ goto error; ++ bcm->active_80211_core = active_core; ++ + bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); + bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); +- dprintk(KERN_INFO PFX "80211 cores initialized\n"); + bcm43xx_security_init(bcm); +- bcm43xx_softmac_init(bcm); ++ ieee80211softmac_start(bcm->net_dev); + +- bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); ++ /* Let's go! Be careful after enabling the IRQs. ++ * Don't switch cores, for example. ++ */ ++ bcm43xx_mac_enable(bcm); ++ bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); ++ err = bcm43xx_initialize_irq(bcm); ++ if (err) ++ goto error; ++ bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); + +- if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) { +- bcm43xx_mac_suspend(bcm); +- bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0); +- bcm43xx_mac_enable(bcm); +- } ++ dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n", ++ active_wlext->phy.type); + +- /* Initialization of the board is done. Flag it as such. */ +- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); ++ return 0; ++ ++error: ++ bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); ++ bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); ++ return err; ++} + ++static int bcm43xx_init_board(struct bcm43xx_private *bcm) ++{ ++ int err; ++ ++ mutex_lock(&(bcm)->mutex); ++ ++ tasklet_enable(&bcm->isr_tasklet); ++ err = bcm43xx_pctl_set_crystal(bcm, 1); ++ if (err) ++ goto err_tasklet; ++ err = bcm43xx_pctl_init(bcm); ++ if (err) ++ goto err_crystal_off; ++ err = bcm43xx_select_wireless_core(bcm, -1); ++ if (err) ++ goto err_crystal_off; ++ err = bcm43xx_sysfs_register(bcm); ++ if (err) ++ goto err_wlshutdown; ++ err = bcm43xx_rng_init(bcm); ++ if (err) ++ goto err_sysfs_unreg; + bcm43xx_periodic_tasks_setup(bcm); +- bcm43xx_sysfs_register(bcm); +- //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though... + + /*FIXME: This should be handled by softmac instead. */ + schedule_work(&bcm->softmac->associnfo.work); + +- assert(err == 0); + out: +- bcm43xx_unlock_noirq(bcm); ++ mutex_unlock(&(bcm)->mutex); + + return err; + +-err_80211_unwind: +- tasklet_disable(&bcm->isr_tasklet); +- /* unwind all 80211 initialization */ +- for (i = 0; i < bcm->nr_80211_available; i++) { +- if (!bcm->core_80211[i].initialized) +- continue; +- bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); +- bcm43xx_wireless_core_cleanup(bcm); +- } ++err_sysfs_unreg: ++ bcm43xx_sysfs_unregister(bcm); ++err_wlshutdown: ++ bcm43xx_shutdown_all_wireless_cores(bcm); + err_crystal_off: + bcm43xx_pctl_set_crystal(bcm, 0); ++err_tasklet: ++ tasklet_disable(&bcm->isr_tasklet); + goto out; + } + +@@ -3647,7 +3815,8 @@ static void bcm43xx_ieee80211_set_chan(s + struct bcm43xx_radioinfo *radio; + unsigned long flags; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { + bcm43xx_mac_suspend(bcm); + bcm43xx_radio_selectchannel(bcm, channel, 0); +@@ -3656,7 +3825,8 @@ static void bcm43xx_ieee80211_set_chan(s + radio = bcm43xx_current_radio(bcm); + radio->initial_channel = channel; + } +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + } + + /* set_security() callback in struct ieee80211_device */ +@@ -3670,7 +3840,8 @@ static void bcm43xx_ieee80211_set_securi + + dprintk(KERN_INFO PFX "set security called"); + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + + for (keyidx = 0; keyidxflags & (1<irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + } + + /* hard_start_xmit() callback in struct ieee80211_device */ +@@ -3751,12 +3923,14 @@ static int bcm43xx_ieee80211_hard_start_ + int err = -ENODEV; + unsigned long flags; + +- bcm43xx_lock_irqonly(bcm, flags); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) + err = bcm43xx_tx(bcm, txb); +- bcm43xx_unlock_irqonly(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); + +- return err; ++ if (unlikely(err)) ++ return NETDEV_TX_BUSY; ++ return NETDEV_TX_OK; + } + + static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev) +@@ -3769,9 +3943,9 @@ static void bcm43xx_net_tx_timeout(struc + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + unsigned long flags; + +- bcm43xx_lock_irqonly(bcm, flags); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + bcm43xx_controller_restart(bcm, "TX timeout"); +- bcm43xx_unlock_irqonly(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); + } + + #ifdef CONFIG_NET_POLL_CONTROLLER +@@ -3781,7 +3955,8 @@ static void bcm43xx_net_poll_controller( + unsigned long flags; + + local_irq_save(flags); +- bcm43xx_interrupt_handler(bcm->irq, bcm, NULL); ++ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) ++ bcm43xx_interrupt_handler(bcm->irq, bcm, NULL); + local_irq_restore(flags); + } + #endif /* CONFIG_NET_POLL_CONTROLLER */ +@@ -3799,9 +3974,10 @@ static int bcm43xx_net_stop(struct net_d + int err; + + ieee80211softmac_stop(net_dev); +- err = bcm43xx_disable_interrupts_sync(bcm, NULL); ++ err = bcm43xx_disable_interrupts_sync(bcm); + assert(!err); + bcm43xx_free_board(bcm); ++ flush_scheduled_work(); + + return 0; + } +@@ -3818,10 +3994,12 @@ static int bcm43xx_init_private(struct b + bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; + + bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; ++ bcm->mac_suspended = 1; + bcm->pci_dev = pci_dev; + bcm->net_dev = net_dev; + bcm->bad_frames_preempt = modparam_bad_frames_preempt; + spin_lock_init(&bcm->irq_lock); ++ spin_lock_init(&bcm->leds_lock); + mutex_init(&bcm->mutex); + tasklet_init(&bcm->isr_tasklet, + (void (*)(unsigned long))bcm43xx_interrupt_tasklet, +@@ -3940,7 +4118,6 @@ static void __devexit bcm43xx_remove_one + bcm43xx_debugfs_remove_device(bcm); + unregister_netdev(net_dev); + bcm43xx_detach_board(bcm); +- assert(bcm->ucode == NULL); + free_ieee80211softmac(net_dev); + } + +@@ -3950,47 +4127,31 @@ static void __devexit bcm43xx_remove_one + static void bcm43xx_chip_reset(void *_bcm) + { + struct bcm43xx_private *bcm = _bcm; +- struct net_device *net_dev = bcm->net_dev; +- struct pci_dev *pci_dev = bcm->pci_dev; +- int err; +- int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); +- +- netif_stop_queue(bcm->net_dev); +- tasklet_disable(&bcm->isr_tasklet); ++ struct bcm43xx_phyinfo *phy; ++ int err = -ENODEV; + +- bcm->firmware_norelease = 1; +- if (was_initialized) +- bcm43xx_free_board(bcm); +- bcm->firmware_norelease = 0; +- bcm43xx_detach_board(bcm); +- err = bcm43xx_init_private(bcm, net_dev, pci_dev); +- if (err) +- goto failure; +- err = bcm43xx_attach_board(bcm); +- if (err) +- goto failure; +- if (was_initialized) { +- err = bcm43xx_init_board(bcm); +- if (err) +- goto failure; ++ mutex_lock(&(bcm)->mutex); ++ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { ++ bcm43xx_periodic_tasks_delete(bcm); ++ phy = bcm43xx_current_phy(bcm); ++ err = bcm43xx_select_wireless_core(bcm, phy->type); ++ if (!err) ++ bcm43xx_periodic_tasks_setup(bcm); + } +- netif_wake_queue(bcm->net_dev); +- printk(KERN_INFO PFX "Controller restarted\n"); ++ mutex_unlock(&(bcm)->mutex); + +- return; +-failure: +- printk(KERN_ERR PFX "Controller restart failed\n"); ++ printk(KERN_ERR PFX "Controller restart%s\n", ++ (err == 0) ? "ed" : " failed"); + } + + /* Hard-reset the chip. + * This can be called from interrupt or process context. +- * Make sure to _not_ re-enable device interrupts after this has been called. +-*/ ++ * bcm->irq_lock must be locked. ++ */ + void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) + { +- bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING); +- bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); +- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ ++ if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) ++ return; + printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); + INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm); + schedule_work(&bcm->restart_work); +@@ -4002,21 +4163,16 @@ static int bcm43xx_suspend(struct pci_de + { + struct net_device *net_dev = pci_get_drvdata(pdev); + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); +- unsigned long flags; +- int try_to_shutdown = 0, err; ++ int err; + + dprintk(KERN_INFO PFX "Suspending...\n"); + +- bcm43xx_lock_irqsafe(bcm, flags); +- bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); +- if (bcm->was_initialized) +- try_to_shutdown = 1; +- bcm43xx_unlock_irqsafe(bcm, flags); +- + netif_device_detach(net_dev); +- if (try_to_shutdown) { ++ bcm->was_initialized = 0; ++ if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { ++ bcm->was_initialized = 1; + ieee80211softmac_stop(net_dev); +- err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate); ++ err = bcm43xx_disable_interrupts_sync(bcm); + if (unlikely(err)) { + dprintk(KERN_ERR PFX "Suspend failed.\n"); + return -EAGAIN; +@@ -4049,17 +4205,14 @@ static int bcm43xx_resume(struct pci_dev + pci_restore_state(pdev); + + bcm43xx_chipset_attach(bcm); +- if (bcm->was_initialized) { +- bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; ++ if (bcm->was_initialized) + err = bcm43xx_init_board(bcm); +- } + if (err) { + printk(KERN_ERR PFX "Resume failed!\n"); + return err; + } +- + netif_device_attach(net_dev); +- ++ + dprintk(KERN_INFO PFX "Device resumed.\n"); + + return 0; +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h +index 1164936..f763571 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h +@@ -133,11 +133,17 @@ void bcm43xx_dummy_transmission(struct b + + int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); + ++int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm, ++ int phytype); ++ + void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); + + void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); + void bcm43xx_mac_enable(struct bcm43xx_private *bcm); + ++void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm); ++void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm); ++ + void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); + + int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +index f8200de..52ce2a9 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +@@ -81,6 +81,16 @@ static const s8 bcm43xx_tssi2dbm_g_table + static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); + + ++static inline ++void bcm43xx_voluntary_preempt(void) ++{ ++ assert(!in_atomic() && !in_irq() && ++ !in_interrupt() && !irqs_disabled()); ++#ifndef CONFIG_PREEMPT ++ cond_resched(); ++#endif /* CONFIG_PREEMPT */ ++} ++ + void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) + { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); +@@ -133,22 +143,14 @@ void bcm43xx_phy_write(struct bcm43xx_pr + void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) + { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); +- unsigned long flags; + + bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ + if (phy->calibrated) + return; + if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { +- /* We do not want to be preempted while calibrating +- * the hardware. +- */ +- local_irq_save(flags); +- + bcm43xx_wireless_core_reset(bcm, 0); + bcm43xx_phy_initg(bcm); + bcm43xx_wireless_core_reset(bcm, 1); +- +- local_irq_restore(flags); + } + phy->calibrated = 1; + } +@@ -359,7 +361,7 @@ static void bcm43xx_phy_setupg(struct bc + if (phy->rev <= 2) + for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) + bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); +- else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200)) ++ else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200)) + for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) + bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); + else +@@ -369,7 +371,7 @@ static void bcm43xx_phy_setupg(struct bc + if (phy->rev == 2) + for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) + bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); +- else if ((phy->rev > 2) && (phy->rev <= 7)) ++ else if ((phy->rev > 2) && (phy->rev <= 8)) + for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) + bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); + +@@ -1195,7 +1197,7 @@ static void bcm43xx_phy_initg(struct bcm + + if (phy->rev == 1) + bcm43xx_phy_initb5(bcm); +- else if (phy->rev >= 2 && phy->rev <= 7) ++ else + bcm43xx_phy_initb6(bcm); + if (phy->rev >= 2 || phy->connected) + bcm43xx_phy_inita(bcm); +@@ -1239,23 +1241,22 @@ static void bcm43xx_phy_initg(struct bcm + bcm43xx_phy_lo_g_measure(bcm); + } else { + if (radio->version == 0x2050 && radio->revision == 8) { +- //FIXME ++ bcm43xx_radio_write16(bcm, 0x0052, ++ (radio->txctl1 << 4) | radio->txctl2); + } else { + bcm43xx_radio_write16(bcm, 0x0052, + (bcm43xx_radio_read16(bcm, 0x0052) + & 0xFFF0) | radio->txctl1); + } + if (phy->rev >= 6) { +- /* + bcm43xx_phy_write(bcm, 0x0036, + (bcm43xx_phy_read(bcm, 0x0036) +- & 0xF000) | (FIXME << 12)); +- */ ++ & 0xF000) | (radio->txctl2 << 12)); + } + if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) + bcm43xx_phy_write(bcm, 0x002E, 0x8075); + else +- bcm43xx_phy_write(bcm, 0x003E, 0x807F); ++ bcm43xx_phy_write(bcm, 0x002E, 0x807F); + if (phy->rev < 2) + bcm43xx_phy_write(bcm, 0x002F, 0x0101); + else +@@ -1299,7 +1300,9 @@ static u16 bcm43xx_phy_lo_b_r15_loop(str + { + int i; + u16 ret = 0; ++ unsigned long flags; + ++ local_irq_save(flags); + for (i = 0; i < 10; i++){ + bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); + udelay(1); +@@ -1309,6 +1312,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(str + udelay(40); + ret += bcm43xx_phy_read(bcm, 0x002C); + } ++ local_irq_restore(flags); ++ bcm43xx_voluntary_preempt(); + + return ret; + } +@@ -1435,6 +1440,7 @@ u16 bcm43xx_phy_lo_g_deviation_subval(st + } + ret = bcm43xx_phy_read(bcm, 0x002D); + local_irq_restore(flags); ++ bcm43xx_voluntary_preempt(); + + return ret; + } +@@ -1760,6 +1766,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm + bcm43xx_radio_write16(bcm, 0x43, i); + bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); + udelay(10); ++ bcm43xx_voluntary_preempt(); + + bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); + +@@ -1803,6 +1810,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm + radio->txctl2 + | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? + udelay(10); ++ bcm43xx_voluntary_preempt(); + + bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); + +@@ -1824,6 +1832,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm + bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); + udelay(2); + bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); ++ bcm43xx_voluntary_preempt(); + } else + bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); + bcm43xx_phy_lo_adjust(bcm, is_initializing); +@@ -2188,12 +2197,6 @@ int bcm43xx_phy_init(struct bcm43xx_priv + { + struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); + int err = -ENODEV; +- unsigned long flags; +- +- /* We do not want to be preempted while calibrating +- * the hardware. +- */ +- local_irq_save(flags); + + switch (phy->type) { + case BCM43xx_PHYTYPE_A: +@@ -2227,7 +2230,6 @@ int bcm43xx_phy_init(struct bcm43xx_priv + err = 0; + break; + } +- local_irq_restore(flags); + if (err) + printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); + +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +index 574085c..c60c174 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +@@ -262,7 +262,7 @@ static void tx_tasklet(unsigned long d) + int err; + u16 txctl; + +- bcm43xx_lock_irqonly(bcm, flags); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + + if (queue->tx_frozen) + goto out_unlock; +@@ -300,7 +300,7 @@ static void tx_tasklet(unsigned long d) + continue; + } + out_unlock: +- bcm43xx_unlock_irqonly(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); + } + + static void setup_txqueues(struct bcm43xx_pioqueue *queue) +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +index 6a23bdc..f41d9e7 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +@@ -120,12 +120,14 @@ static ssize_t bcm43xx_attr_sprom_show(s + GFP_KERNEL); + if (!sprom) + return -ENOMEM; +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + err = bcm43xx_sprom_read(bcm, sprom); + if (!err) + err = sprom2hex(sprom, buf, PAGE_SIZE); + mmiowb(); +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + kfree(sprom); + + return err; +@@ -150,10 +152,14 @@ static ssize_t bcm43xx_attr_sprom_store( + err = hex2sprom(sprom, buf, count); + if (err) + goto out_kfree; +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); ++ spin_lock(&bcm->leds_lock); + err = bcm43xx_sprom_write(bcm, sprom); + mmiowb(); +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock(&bcm->leds_lock); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + out_kfree: + kfree(sprom); + +@@ -170,13 +176,12 @@ static ssize_t bcm43xx_attr_interfmode_s + char *buf) + { + struct bcm43xx_private *bcm = dev_to_bcm(dev); +- int err; + ssize_t count = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + +- bcm43xx_lock_noirq(bcm); ++ mutex_lock(&bcm->mutex); + + switch (bcm43xx_current_radio(bcm)->interfmode) { + case BCM43xx_RADIO_INTERFMODE_NONE: +@@ -191,11 +196,10 @@ static ssize_t bcm43xx_attr_interfmode_s + default: + assert(0); + } +- err = 0; + +- bcm43xx_unlock_noirq(bcm); ++ mutex_unlock(&bcm->mutex); + +- return err ? err : count; ++ return count; + + } + +@@ -229,7 +233,8 @@ static ssize_t bcm43xx_attr_interfmode_s + return -EINVAL; + } + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + + err = bcm43xx_radio_set_interference_mitigation(bcm, mode); + if (err) { +@@ -237,7 +242,8 @@ static ssize_t bcm43xx_attr_interfmode_s + "supported by device\n"); + } + mmiowb(); +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + + return err ? err : count; + } +@@ -251,23 +257,21 @@ static ssize_t bcm43xx_attr_preamble_sho + char *buf) + { + struct bcm43xx_private *bcm = dev_to_bcm(dev); +- int err; + ssize_t count; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + +- bcm43xx_lock_noirq(bcm); ++ mutex_lock(&bcm->mutex); + + if (bcm->short_preamble) + count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); + else + count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); + +- err = 0; +- bcm43xx_unlock_noirq(bcm); ++ mutex_unlock(&bcm->mutex); + +- return err ? err : count; ++ return count; + } + + static ssize_t bcm43xx_attr_preamble_store(struct device *dev, +@@ -276,7 +280,6 @@ static ssize_t bcm43xx_attr_preamble_sto + { + struct bcm43xx_private *bcm = dev_to_bcm(dev); + unsigned long flags; +- int err; + int value; + + if (!capable(CAP_NET_ADMIN)) +@@ -285,14 +288,15 @@ static ssize_t bcm43xx_attr_preamble_sto + value = get_boolean(buf, count); + if (value < 0) + return value; +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + + bcm->short_preamble = !!value; + +- err = 0; +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + +- return err ? err : count; ++ return count; + } + + static DEVICE_ATTR(shortpreamble, 0644, +diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +index 5c36e29..ebe2a84 100644 +--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c ++++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +@@ -56,12 +56,11 @@ static int bcm43xx_wx_get_name(struct ne + { + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + int i; +- unsigned long flags; + struct bcm43xx_phyinfo *phy; + char suffix[7] = { 0 }; + int have_a = 0, have_b = 0, have_g = 0; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + for (i = 0; i < bcm->nr_80211_available; i++) { + phy = &(bcm->core_80211_ext[i].phy); + switch (phy->type) { +@@ -77,7 +76,7 @@ static int bcm43xx_wx_get_name(struct ne + assert(0); + } + } +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + i = 0; + if (have_a) { +@@ -111,7 +110,9 @@ static int bcm43xx_wx_set_channelfreq(st + int freq; + int err = -EINVAL; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); ++ + if ((data->freq.m >= 0) && (data->freq.m <= 1000)) { + channel = data->freq.m; + freq = bcm43xx_channel_to_freq(bcm, channel); +@@ -131,7 +132,8 @@ static int bcm43xx_wx_set_channelfreq(st + err = 0; + } + out_unlock: +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + + return err; + } +@@ -143,11 +145,10 @@ static int bcm43xx_wx_get_channelfreq(st + { + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; +- unsigned long flags; + int err = -ENODEV; + u16 channel; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + radio = bcm43xx_current_radio(bcm); + channel = radio->channel; + if (channel == 0xFF) { +@@ -162,7 +163,7 @@ static int bcm43xx_wx_get_channelfreq(st + + err = 0; + out_unlock: +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + return err; + } +@@ -180,13 +181,15 @@ static int bcm43xx_wx_set_mode(struct ne + if (mode == IW_MODE_AUTO) + mode = BCM43xx_INITIAL_IWMODE; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { + if (bcm->ieee->iw_mode != mode) + bcm43xx_set_iwmode(bcm, mode); + } else + bcm->ieee->iw_mode = mode; +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + + return 0; + } +@@ -197,11 +200,10 @@ static int bcm43xx_wx_get_mode(struct ne + char *extra) + { + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); +- unsigned long flags; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + data->mode = bcm->ieee->iw_mode; +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + return 0; + } +@@ -214,7 +216,6 @@ static int bcm43xx_wx_get_rangeparams(st + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct iw_range *range = (struct iw_range *)extra; + const struct ieee80211_geo *geo; +- unsigned long flags; + int i, j; + struct bcm43xx_phyinfo *phy; + +@@ -254,7 +255,7 @@ static int bcm43xx_wx_get_rangeparams(st + IW_ENC_CAPA_CIPHER_TKIP | + IW_ENC_CAPA_CIPHER_CCMP; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + phy = bcm43xx_current_phy(bcm); + + range->num_bitrates = 0; +@@ -301,7 +302,7 @@ static int bcm43xx_wx_get_rangeparams(st + } + range->num_frequency = j; + +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + return 0; + } +@@ -314,11 +315,11 @@ static int bcm43xx_wx_set_nick(struct ne + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + size_t len; + +- bcm43xx_lock_noirq(bcm); ++ mutex_lock(&bcm->mutex); + len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); + memcpy(bcm->nick, extra, len); + bcm->nick[len] = '\0'; +- bcm43xx_unlock_noirq(bcm); ++ mutex_unlock(&bcm->mutex); + + return 0; + } +@@ -331,12 +332,12 @@ static int bcm43xx_wx_get_nick(struct ne + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + size_t len; + +- bcm43xx_lock_noirq(bcm); ++ mutex_lock(&bcm->mutex); + len = strlen(bcm->nick) + 1; + memcpy(extra, bcm->nick, len); + data->data.length = (__u16)len; + data->data.flags = 1; +- bcm43xx_unlock_noirq(bcm); ++ mutex_unlock(&bcm->mutex); + + return 0; + } +@@ -350,7 +351,8 @@ static int bcm43xx_wx_set_rts(struct net + unsigned long flags; + int err = -EINVAL; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (data->rts.disabled) { + bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; + err = 0; +@@ -361,7 +363,8 @@ static int bcm43xx_wx_set_rts(struct net + err = 0; + } + } +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + + return err; + } +@@ -372,13 +375,12 @@ static int bcm43xx_wx_get_rts(struct net + char *extra) + { + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); +- unsigned long flags; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + data->rts.value = bcm->rts_threshold; + data->rts.fixed = 0; + data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + return 0; + } +@@ -392,7 +394,8 @@ static int bcm43xx_wx_set_frag(struct ne + unsigned long flags; + int err = -EINVAL; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (data->frag.disabled) { + bcm->ieee->fts = MAX_FRAG_THRESHOLD; + err = 0; +@@ -403,7 +406,8 @@ static int bcm43xx_wx_set_frag(struct ne + err = 0; + } + } +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + + return err; + } +@@ -414,13 +418,12 @@ static int bcm43xx_wx_get_frag(struct ne + char *extra) + { + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); +- unsigned long flags; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + data->frag.value = bcm->ieee->fts; + data->frag.fixed = 0; + data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + return 0; + } +@@ -442,7 +445,8 @@ static int bcm43xx_wx_set_xmitpower(stru + return -EOPNOTSUPP; + } + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) + goto out_unlock; + radio = bcm43xx_current_radio(bcm); +@@ -466,7 +470,8 @@ static int bcm43xx_wx_set_xmitpower(stru + err = 0; + + out_unlock: +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + + return err; + } +@@ -478,10 +483,9 @@ static int bcm43xx_wx_get_xmitpower(stru + { + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); + struct bcm43xx_radioinfo *radio; +- unsigned long flags; + int err = -ENODEV; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) + goto out_unlock; + radio = bcm43xx_current_radio(bcm); +@@ -493,7 +497,7 @@ static int bcm43xx_wx_get_xmitpower(stru + + err = 0; + out_unlock: +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + return err; + } +@@ -580,7 +584,8 @@ static int bcm43xx_wx_set_interfmode(str + return -EINVAL; + } + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { + err = bcm43xx_radio_set_interference_mitigation(bcm, mode); + if (err) { +@@ -595,7 +600,8 @@ static int bcm43xx_wx_set_interfmode(str + } else + bcm43xx_current_radio(bcm)->interfmode = mode; + } +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + + return err; + } +@@ -606,12 +612,11 @@ static int bcm43xx_wx_get_interfmode(str + char *extra) + { + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); +- unsigned long flags; + int mode; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + mode = bcm43xx_current_radio(bcm)->interfmode; +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + switch (mode) { + case BCM43xx_RADIO_INTERFMODE_NONE: +@@ -641,9 +646,11 @@ static int bcm43xx_wx_set_shortpreamble( + int on; + + on = *((int *)extra); +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + bcm->short_preamble = !!on; +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + + return 0; + } +@@ -654,12 +661,11 @@ static int bcm43xx_wx_get_shortpreamble( + char *extra) + { + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); +- unsigned long flags; + int on; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + on = bcm->short_preamble; +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + if (on) + strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); +@@ -681,11 +687,13 @@ static int bcm43xx_wx_set_swencryption(s + + on = *((int *)extra); + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + bcm->ieee->host_encrypt = !!on; + bcm->ieee->host_decrypt = !!on; + bcm->ieee->host_build_iv = !on; +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + + return 0; + } +@@ -696,12 +704,11 @@ static int bcm43xx_wx_get_swencryption(s + char *extra) + { + struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); +- unsigned long flags; + int on; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); + on = bcm->ieee->host_encrypt; +- bcm43xx_unlock_irqsafe(bcm, flags); ++ mutex_unlock(&bcm->mutex); + + if (on) + strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); +@@ -764,11 +771,13 @@ static int bcm43xx_wx_sprom_read(struct + if (!sprom) + goto out; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); + err = -ENODEV; + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) + err = bcm43xx_sprom_read(bcm, sprom); +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + if (!err) + data->data.length = sprom2hex(sprom, extra); + kfree(sprom); +@@ -809,11 +818,15 @@ static int bcm43xx_wx_sprom_write(struct + if (err) + goto out_kfree; + +- bcm43xx_lock_irqsafe(bcm, flags); ++ mutex_lock(&bcm->mutex); ++ spin_lock_irqsave(&bcm->irq_lock, flags); ++ spin_lock(&bcm->leds_lock); + err = -ENODEV; + if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) + err = bcm43xx_sprom_write(bcm, sprom); +- bcm43xx_unlock_irqsafe(bcm, flags); ++ spin_unlock(&bcm->leds_lock); ++ spin_unlock_irqrestore(&bcm->irq_lock, flags); ++ mutex_unlock(&bcm->mutex); + out_kfree: + kfree(sprom); + out: +diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c +index aa79282..4b971a9 100644 +--- a/drivers/net/wireless/zd1211rw/zd_chip.c ++++ b/drivers/net/wireless/zd1211rw/zd_chip.c +@@ -717,7 +717,7 @@ static int zd1211b_hw_reset_phy(struct z + { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, + { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, + { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, +- { CR30, 0x49 }, /* jointly decoder, no ASIC */ ++ { CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ + { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, + { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, + { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, +diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c +index ba9a583..bd43106 100644 +--- a/drivers/rtc/rtc-pcf8563.c ++++ b/drivers/rtc/rtc-pcf8563.c +@@ -95,7 +95,7 @@ static int pcf8563_get_datetime(struct i + tm->tm_wday = buf[PCF8563_REG_DW] & 0x07; + tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ + tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]) +- + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 100 : 0); ++ + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 0 : 100); + + dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", +@@ -135,7 +135,7 @@ static int pcf8563_set_datetime(struct i + + /* year and century */ + buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100); +- if (tm->tm_year / 100) ++ if (tm->tm_year < 100) + buf[PCF8563_REG_MO] |= PCF8563_MO_C; + + buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; +diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c +index fa38a41..39ace4c 100644 +--- a/drivers/scsi/sata_mv.c ++++ b/drivers/scsi/sata_mv.c +@@ -463,6 +463,7 @@ static const struct ata_port_operations + + .qc_prep = mv_qc_prep_iie, + .qc_issue = mv_qc_issue, ++ .data_xfer = ata_mmio_data_xfer, + + .eng_timeout = mv_eng_timeout, + +diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c +index 30299c6..fed484d 100644 +--- a/drivers/usb/gadget/ether.c ++++ b/drivers/usb/gadget/ether.c +@@ -262,7 +262,7 @@ #ifdef CONFIG_USB_GADGET_MUSBHSFC + #define DEV_CONFIG_CDC + #endif + +-#ifdef CONFIG_USB_GADGET_MUSBHDRC ++#ifdef CONFIG_USB_GADGET_MUSB_HDRC + #define DEV_CONFIG_CDC + #endif + +@@ -2564,7 +2564,7 @@ static struct usb_gadget_driver eth_driv + + .function = (char *) driver_desc, + .bind = eth_bind, +- .unbind = __exit_p(eth_unbind), ++ .unbind = eth_unbind, + + .setup = eth_setup, + .disconnect = eth_disconnect, +diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c +index 17961e3..93ffcdd 100644 +--- a/drivers/video/fbmem.c ++++ b/drivers/video/fbmem.c +@@ -554,7 +554,8 @@ static int fbmem_read_proc(char *buf, ch + int clen; + + clen = 0; +- for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && len < 4000; fi++) ++ for (fi = registered_fb; fi < ®istered_fb[FB_MAX] && clen < 4000; ++ fi++) + if (*fi) + clen += sprintf(buf + clen, "%d %s\n", + (*fi)->node, +diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c +index 4f78f23..c151dcf 100644 +--- a/drivers/video/fbsysfs.c ++++ b/drivers/video/fbsysfs.c +@@ -397,6 +397,12 @@ static ssize_t store_bl_curve(struct cla + u8 tmp_curve[FB_BACKLIGHT_LEVELS]; + unsigned int i; + ++ /* Some drivers don't use framebuffer_alloc(), but those also ++ * don't have backlights. ++ */ ++ if (!fb_info || !fb_info->bl_dev) ++ return -ENODEV; ++ + if (count != (FB_BACKLIGHT_LEVELS / 8 * 24)) + return -EINVAL; + +@@ -430,6 +436,12 @@ static ssize_t show_bl_curve(struct clas + ssize_t len = 0; + unsigned int i; + ++ /* Some drivers don't use framebuffer_alloc(), but those also ++ * don't have backlights. ++ */ ++ if (!fb_info || !fb_info->bl_dev) ++ return -ENODEV; ++ + mutex_lock(&fb_info->bl_mutex); + for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8) + len += snprintf(&buf[len], PAGE_SIZE, +diff --git a/fs/buffer.c b/fs/buffer.c +index 71649ef..5b329f0 100644 +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -838,7 +838,10 @@ EXPORT_SYMBOL(mark_buffer_dirty_inode); + */ + int __set_page_dirty_buffers(struct page *page) + { +- struct address_space * const mapping = page->mapping; ++ struct address_space * const mapping = page_mapping(page); ++ ++ if (unlikely(!mapping)) ++ return !TestSetPageDirty(page); + + spin_lock(&mapping->private_lock); + if (page_has_buffers(page)) { +diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c +index 42da607..e998a60 100644 +--- a/fs/jbd/commit.c ++++ b/fs/jbd/commit.c +@@ -160,6 +160,117 @@ static int journal_write_commit_record(j + return (ret == -EIO); + } + ++void journal_do_submit_data(struct buffer_head **wbuf, int bufs) ++{ ++ int i; ++ ++ for (i = 0; i < bufs; i++) { ++ wbuf[i]->b_end_io = end_buffer_write_sync; ++ /* We use-up our safety reference in submit_bh() */ ++ submit_bh(WRITE, wbuf[i]); ++ } ++} ++ ++/* ++ * Submit all the data buffers to disk ++ */ ++static void journal_submit_data_buffers(journal_t *journal, ++ transaction_t *commit_transaction) ++{ ++ struct journal_head *jh; ++ struct buffer_head *bh; ++ int locked; ++ int bufs = 0; ++ struct buffer_head **wbuf = journal->j_wbuf; ++ ++ /* ++ * Whenever we unlock the journal and sleep, things can get added ++ * onto ->t_sync_datalist, so we have to keep looping back to ++ * write_out_data until we *know* that the list is empty. ++ * ++ * Cleanup any flushed data buffers from the data list. Even in ++ * abort mode, we want to flush this out as soon as possible. ++ */ ++write_out_data: ++ cond_resched(); ++ spin_lock(&journal->j_list_lock); ++ ++ while (commit_transaction->t_sync_datalist) { ++ jh = commit_transaction->t_sync_datalist; ++ bh = jh2bh(jh); ++ locked = 0; ++ ++ /* Get reference just to make sure buffer does not disappear ++ * when we are forced to drop various locks */ ++ get_bh(bh); ++ /* If the buffer is dirty, we need to submit IO and hence ++ * we need the buffer lock. We try to lock the buffer without ++ * blocking. If we fail, we need to drop j_list_lock and do ++ * blocking lock_buffer(). ++ */ ++ if (buffer_dirty(bh)) { ++ if (test_set_buffer_locked(bh)) { ++ BUFFER_TRACE(bh, "needs blocking lock"); ++ spin_unlock(&journal->j_list_lock); ++ /* Write out all data to prevent deadlocks */ ++ journal_do_submit_data(wbuf, bufs); ++ bufs = 0; ++ lock_buffer(bh); ++ spin_lock(&journal->j_list_lock); ++ } ++ locked = 1; ++ } ++ /* We have to get bh_state lock. Again out of order, sigh. */ ++ if (!inverted_lock(journal, bh)) { ++ jbd_lock_bh_state(bh); ++ spin_lock(&journal->j_list_lock); ++ } ++ /* Someone already cleaned up the buffer? */ ++ if (!buffer_jbd(bh) ++ || jh->b_transaction != commit_transaction ++ || jh->b_jlist != BJ_SyncData) { ++ jbd_unlock_bh_state(bh); ++ if (locked) ++ unlock_buffer(bh); ++ BUFFER_TRACE(bh, "already cleaned up"); ++ put_bh(bh); ++ continue; ++ } ++ if (locked && test_clear_buffer_dirty(bh)) { ++ BUFFER_TRACE(bh, "needs writeout, adding to array"); ++ wbuf[bufs++] = bh; ++ __journal_file_buffer(jh, commit_transaction, ++ BJ_Locked); ++ jbd_unlock_bh_state(bh); ++ if (bufs == journal->j_wbufsize) { ++ spin_unlock(&journal->j_list_lock); ++ journal_do_submit_data(wbuf, bufs); ++ bufs = 0; ++ goto write_out_data; ++ } ++ } ++ else { ++ BUFFER_TRACE(bh, "writeout complete: unfile"); ++ __journal_unfile_buffer(jh); ++ jbd_unlock_bh_state(bh); ++ if (locked) ++ unlock_buffer(bh); ++ journal_remove_journal_head(bh); ++ /* Once for our safety reference, once for ++ * journal_remove_journal_head() */ ++ put_bh(bh); ++ put_bh(bh); ++ } ++ ++ if (lock_need_resched(&journal->j_list_lock)) { ++ spin_unlock(&journal->j_list_lock); ++ goto write_out_data; ++ } ++ } ++ spin_unlock(&journal->j_list_lock); ++ journal_do_submit_data(wbuf, bufs); ++} ++ + /* + * journal_commit_transaction + * +@@ -313,80 +424,13 @@ #endif + * Now start flushing things to disk, in the order they appear + * on the transaction lists. Data blocks go first. + */ +- + err = 0; +- /* +- * Whenever we unlock the journal and sleep, things can get added +- * onto ->t_sync_datalist, so we have to keep looping back to +- * write_out_data until we *know* that the list is empty. +- */ +- bufs = 0; +- /* +- * Cleanup any flushed data buffers from the data list. Even in +- * abort mode, we want to flush this out as soon as possible. +- */ +-write_out_data: +- cond_resched(); +- spin_lock(&journal->j_list_lock); +- +- while (commit_transaction->t_sync_datalist) { +- struct buffer_head *bh; +- +- jh = commit_transaction->t_sync_datalist; +- commit_transaction->t_sync_datalist = jh->b_tnext; +- bh = jh2bh(jh); +- if (buffer_locked(bh)) { +- BUFFER_TRACE(bh, "locked"); +- if (!inverted_lock(journal, bh)) +- goto write_out_data; +- __journal_temp_unlink_buffer(jh); +- __journal_file_buffer(jh, commit_transaction, +- BJ_Locked); +- jbd_unlock_bh_state(bh); +- if (lock_need_resched(&journal->j_list_lock)) { +- spin_unlock(&journal->j_list_lock); +- goto write_out_data; +- } +- } else { +- if (buffer_dirty(bh)) { +- BUFFER_TRACE(bh, "start journal writeout"); +- get_bh(bh); +- wbuf[bufs++] = bh; +- if (bufs == journal->j_wbufsize) { +- jbd_debug(2, "submit %d writes\n", +- bufs); +- spin_unlock(&journal->j_list_lock); +- ll_rw_block(SWRITE, bufs, wbuf); +- journal_brelse_array(wbuf, bufs); +- bufs = 0; +- goto write_out_data; +- } +- } else { +- BUFFER_TRACE(bh, "writeout complete: unfile"); +- if (!inverted_lock(journal, bh)) +- goto write_out_data; +- __journal_unfile_buffer(jh); +- jbd_unlock_bh_state(bh); +- journal_remove_journal_head(bh); +- put_bh(bh); +- if (lock_need_resched(&journal->j_list_lock)) { +- spin_unlock(&journal->j_list_lock); +- goto write_out_data; +- } +- } +- } +- } +- +- if (bufs) { +- spin_unlock(&journal->j_list_lock); +- ll_rw_block(SWRITE, bufs, wbuf); +- journal_brelse_array(wbuf, bufs); +- spin_lock(&journal->j_list_lock); +- } ++ journal_submit_data_buffers(journal, commit_transaction); + + /* + * Wait for all previously submitted IO to complete. + */ ++ spin_lock(&journal->j_list_lock); + while (commit_transaction->t_locked_list) { + struct buffer_head *bh; + +diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c +index cf37866..5bb3e17 100644 +--- a/fs/sysfs/file.c ++++ b/fs/sysfs/file.c +@@ -483,11 +483,6 @@ int sysfs_update_file(struct kobject * k + (victim->d_parent->d_inode == dir->d_inode)) { + victim->d_inode->i_mtime = CURRENT_TIME; + fsnotify_modify(victim); +- +- /** +- * Drop reference from initial sysfs_get_dentry(). +- */ +- dput(victim); + res = 0; + } else + d_drop(victim); +diff --git a/include/Kbuild b/include/Kbuild +index cb25348..2d03f99 100644 +--- a/include/Kbuild ++++ b/include/Kbuild +@@ -1,2 +1,9 @@ +-header-y += asm-generic/ linux/ scsi/ sound/ mtd/ rdma/ video/ +-header-y += asm-$(ARCH)/ ++header-y += asm-generic/ ++header-y += linux/ ++header-y += scsi/ ++header-y += sound/ ++header-y += mtd/ ++header-y += rdma/ ++header-y += video/ ++ ++header-y += asm-$(ARCH)/ +diff --git a/include/asm-alpha/Kbuild b/include/asm-alpha/Kbuild +index 2b06b3b..b7c8f18 100644 +--- a/include/asm-alpha/Kbuild ++++ b/include/asm-alpha/Kbuild +@@ -1,5 +1,11 @@ + include include/asm-generic/Kbuild.asm + +-unifdef-y += console.h fpu.h sysinfo.h compiler.h ++header-y += gentrap.h ++header-y += regdef.h ++header-y += pal.h ++header-y += reg.h + +-header-y += gentrap.h regdef.h pal.h reg.h ++unifdef-y += console.h ++unifdef-y += fpu.h ++unifdef-y += sysinfo.h ++unifdef-y += compiler.h +diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h +index ae7baa6..17f0c65 100644 +--- a/include/asm-arm/elf.h ++++ b/include/asm-arm/elf.h +@@ -8,9 +8,6 @@ #define __ASMARM_ELF_H + + #include + #include +-#ifdef __KERNEL +-#include +-#endif + + typedef unsigned long elf_greg_t; + typedef unsigned long elf_freg_t[3]; +@@ -32,11 +29,6 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR + typedef struct user_fp elf_fpregset_t; + + /* +- * This is used to ensure we don't load something for the wrong architecture. +- */ +-#define elf_check_arch(x) ( ((x)->e_machine == EM_ARM) && (ELF_PROC_OK((x))) ) +- +-/* + * These are used to set parameters in the core dumps. + */ + #define ELF_CLASS ELFCLASS32 +@@ -47,6 +39,14 @@ #define ELF_DATA ELFDATA2LSB + #endif + #define ELF_ARCH EM_ARM + ++#ifdef __KERNEL__ ++#include ++ ++/* ++ * This is used to ensure we don't load something for the wrong architecture. ++ */ ++#define elf_check_arch(x) ( ((x)->e_machine == EM_ARM) && (ELF_PROC_OK((x))) ) ++ + #define USE_ELF_CORE_DUMP + #define ELF_EXEC_PAGESIZE 4096 + +@@ -83,8 +83,6 @@ #define ELF_PLATFORM_SIZE 8 + extern char elf_platform[]; + #define ELF_PLATFORM (elf_platform) + +-#ifdef __KERNEL__ +- + /* + * 32-bit code is always OK. Some cpus can do 26-bit, some can't. + */ +diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h +index b721270..02bd3ee 100644 +--- a/include/asm-arm/page.h ++++ b/include/asm-arm/page.h +@@ -11,13 +11,13 @@ #ifndef _ASMARM_PAGE_H + #define _ASMARM_PAGE_H + + ++#ifdef __KERNEL__ ++ + /* PAGE_SHIFT determines the page size */ + #define PAGE_SHIFT 12 + #define PAGE_SIZE (1UL << PAGE_SHIFT) + #define PAGE_MASK (~(PAGE_SIZE-1)) + +-#ifdef __KERNEL__ +- + /* to align the pointer to the (next) page boundary */ + #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + +diff --git a/include/asm-arm26/Kbuild b/include/asm-arm26/Kbuild +deleted file mode 100644 +index c68e168..0000000 +--- a/include/asm-arm26/Kbuild ++++ /dev/null +@@ -1 +0,0 @@ +-include include/asm-generic/Kbuild.asm +diff --git a/include/asm-cris/Kbuild b/include/asm-cris/Kbuild +index c68e168..14498d5 100644 +--- a/include/asm-cris/Kbuild ++++ b/include/asm-cris/Kbuild +@@ -1 +1,5 @@ + include include/asm-generic/Kbuild.asm ++ ++header-y += arch-v10/ arch-v32/ ++ ++unifdef-y += rs485.h +diff --git a/include/asm-cris/arch-v10/Kbuild b/include/asm-cris/arch-v10/Kbuild +new file mode 100644 +index 0000000..d7f27dc +--- /dev/null ++++ b/include/asm-cris/arch-v10/Kbuild +@@ -0,0 +1,2 @@ ++header-y += ptrace.h ++header-y += user.h +diff --git a/include/asm-cris/arch-v32/Kbuild b/include/asm-cris/arch-v32/Kbuild +new file mode 100644 +index 0000000..d7f27dc +--- /dev/null ++++ b/include/asm-cris/arch-v32/Kbuild +@@ -0,0 +1,2 @@ ++header-y += ptrace.h ++header-y += user.h +diff --git a/include/asm-cris/byteorder.h b/include/asm-cris/byteorder.h +index a1a222a..0cd9db1 100644 +--- a/include/asm-cris/byteorder.h ++++ b/include/asm-cris/byteorder.h +@@ -3,14 +3,15 @@ #define _CRIS_BYTEORDER_H + + #ifdef __GNUC__ + ++#ifdef __KERNEL__ + #include + + /* defines are necessary because the other files detect the presence + * of a defined __arch_swab32, not an inline + */ +- + #define __arch__swab32(x) ___arch__swab32(x) + #define __arch__swab16(x) ___arch__swab16(x) ++#endif /* __KERNEL__ */ + + #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) + # define __BYTEORDER_HAS_U64__ +diff --git a/include/asm-cris/elf.h b/include/asm-cris/elf.h +index 87a60bd..96a40c1 100644 +--- a/include/asm-cris/elf.h ++++ b/include/asm-cris/elf.h +@@ -5,7 +5,6 @@ #define __ASMCRIS_ELF_H + * ELF register definitions.. + */ + +-#include + #include + + #define R_CRIS_NONE 0 +@@ -46,6 +45,9 @@ #define ELF_CLASS ELFCLASS32 + #define ELF_DATA ELFDATA2LSB + #define ELF_ARCH EM_CRIS + ++#ifdef __KERNEL__ ++#include ++ + /* The master for these definitions is {binutils}/include/elf/cris.h: */ + /* User symbols in this file have a leading underscore. */ + #define EF_CRIS_UNDERSCORE 0x00000001 +@@ -87,8 +89,8 @@ #define ELF_HWCAP (0) + + #define ELF_PLATFORM (NULL) + +-#ifdef __KERNEL__ + #define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) +-#endif ++ ++#endif /* __KERNEL__ */ + + #endif +diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h +index 81832e9..9f13c32 100644 +--- a/include/asm-cris/page.h ++++ b/include/asm-cris/page.h +@@ -1,6 +1,8 @@ + #ifndef _CRIS_PAGE_H + #define _CRIS_PAGE_H + ++#ifdef __KERNEL__ ++ + #include + + /* PAGE_SHIFT determines the page size */ +@@ -12,8 +14,6 @@ #define PAGE_SIZE (1 << PAGE_SHIFT) + #endif + #define PAGE_MASK (~(PAGE_SIZE-1)) + +-#ifdef __KERNEL__ +- + #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) + #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE) + +@@ -73,10 +73,10 @@ #endif /* __ASSEMBLY__ */ + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +-#endif /* __KERNEL__ */ +- + #include + #include + ++#endif /* __KERNEL__ */ ++ + #endif /* _CRIS_PAGE_H */ + +diff --git a/include/asm-cris/posix_types.h b/include/asm-cris/posix_types.h +index 6d26fee..7b9ed22 100644 +--- a/include/asm-cris/posix_types.h ++++ b/include/asm-cris/posix_types.h +@@ -6,8 +6,6 @@ + #ifndef __ARCH_CRIS_POSIX_TYPES_H + #define __ARCH_CRIS_POSIX_TYPES_H + +-#include +- + /* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot +@@ -53,9 +51,8 @@ #else /* !defined(__KERNEL__) && !define + #endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ + } __kernel_fsid_t; + +-/* should this ifdef be here ? */ +- +-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) ++#ifdef __KERNEL__ ++#include + + #undef __FD_SET + #define __FD_SET(fd,fdsetp) set_bit(fd, (void *)(fdsetp)) +@@ -69,6 +66,6 @@ #define __FD_ISSET(fd,fdsetp) test_bit(f + #undef __FD_ZERO + #define __FD_ZERO(fdsetp) memset((void *)(fdsetp), 0, __FDSET_LONGS << 2) + +-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ ++#endif /* __KERNEL__ */ + + #endif /* __ARCH_CRIS_POSIX_TYPES_H */ +diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h +index c2954e9..7372efa 100644 +--- a/include/asm-cris/unistd.h ++++ b/include/asm-cris/unistd.h +@@ -1,8 +1,6 @@ + #ifndef _ASM_CRIS_UNISTD_H_ + #define _ASM_CRIS_UNISTD_H_ + +-#include +- + /* + * This file contains the system call numbers, and stub macros for libc. + */ +@@ -299,6 +297,7 @@ #ifdef __KERNEL__ + + #define NR_syscalls 289 + ++#include + + #define __ARCH_WANT_IPC_PARSE_VERSION + #define __ARCH_WANT_OLD_READDIR +@@ -322,7 +321,6 @@ #define __ARCH_WANT_SYS_OLDUMOUNT + #define __ARCH_WANT_SYS_SIGPENDING + #define __ARCH_WANT_SYS_SIGPROCMASK + #define __ARCH_WANT_SYS_RT_SIGACTION +-#endif + + #ifdef __KERNEL_SYSCALLS__ + +diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild +index 70594b2..3c06be3 100644 +--- a/include/asm-generic/Kbuild ++++ b/include/asm-generic/Kbuild +@@ -1,3 +1,12 @@ +-header-y += atomic.h errno-base.h errno.h fcntl.h ioctl.h ipc.h mman.h \ +- signal.h statfs.h +-unifdef-y := resource.h siginfo.h ++header-y += atomic.h ++header-y += errno-base.h ++header-y += errno.h ++header-y += fcntl.h ++header-y += ioctl.h ++header-y += ipc.h ++header-y += mman.h ++header-y += signal.h ++header-y += statfs.h ++ ++unifdef-y += resource.h ++unifdef-y += siginfo.h +diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm +index c00de60..a84c3d8 100644 +--- a/include/asm-generic/Kbuild.asm ++++ b/include/asm-generic/Kbuild.asm +@@ -1,8 +1,34 @@ +-unifdef-y += a.out.h auxvec.h byteorder.h errno.h fcntl.h ioctl.h \ +- ioctls.h ipcbuf.h mman.h msgbuf.h param.h poll.h \ +- posix_types.h ptrace.h resource.h sembuf.h shmbuf.h shmparam.h \ +- sigcontext.h siginfo.h signal.h socket.h sockios.h stat.h \ +- statfs.h termbits.h termios.h types.h unistd.h user.h ++unifdef-y += a.out.h ++unifdef-y += auxvec.h ++unifdef-y += byteorder.h ++unifdef-y += errno.h ++unifdef-y += fcntl.h ++unifdef-y += ioctl.h ++unifdef-y += ioctls.h ++unifdef-y += ipcbuf.h ++unifdef-y += mman.h ++unifdef-y += msgbuf.h ++unifdef-y += param.h ++unifdef-y += poll.h ++unifdef-y += posix_types.h ++unifdef-y += ptrace.h ++unifdef-y += resource.h ++unifdef-y += sembuf.h ++unifdef-y += shmbuf.h ++unifdef-y += sigcontext.h ++unifdef-y += siginfo.h ++unifdef-y += signal.h ++unifdef-y += socket.h ++unifdef-y += sockios.h ++unifdef-y += stat.h ++unifdef-y += statfs.h ++unifdef-y += termbits.h ++unifdef-y += termios.h ++unifdef-y += types.h ++unifdef-y += unistd.h ++unifdef-y += user.h + + # These probably shouldn't be exported +-unifdef-y += elf.h page.h ++unifdef-y += shmparam.h ++unifdef-y += elf.h ++unifdef-y += page.h +diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h +index d673077..3b4f290 100644 +--- a/include/asm-h8300/page.h ++++ b/include/asm-h8300/page.h +@@ -1,6 +1,7 @@ + #ifndef _H8300_PAGE_H + #define _H8300_PAGE_H + ++#ifdef __KERNEL__ + + /* PAGE_SHIFT determines the page size */ + +@@ -8,8 +9,6 @@ #define PAGE_SHIFT (12) + #define PAGE_SIZE (1UL << PAGE_SHIFT) + #define PAGE_MASK (~(PAGE_SIZE-1)) + +-#ifdef __KERNEL__ +- + #include + + #ifndef __ASSEMBLY__ +@@ -76,9 +75,9 @@ #define virt_addr_valid(kaddr) (((void * + + #endif /* __ASSEMBLY__ */ + +-#endif /* __KERNEL__ */ +- + #include + #include + ++#endif /* __KERNEL__ */ ++ + #endif /* _H8300_PAGE_H */ +diff --git a/include/asm-i386/Kbuild b/include/asm-i386/Kbuild +index 2308190..b75a348 100644 +--- a/include/asm-i386/Kbuild ++++ b/include/asm-i386/Kbuild +@@ -1,5 +1,10 @@ + include include/asm-generic/Kbuild.asm + +-header-y += boot.h debugreg.h ldt.h ucontext.h ++header-y += boot.h ++header-y += debugreg.h ++header-y += ldt.h ++header-y += ucontext.h + +-unifdef-y += mtrr.h setup.h vm86.h ++unifdef-y += mtrr.h ++unifdef-y += setup.h ++unifdef-y += vm86.h +diff --git a/include/asm-ia64/Kbuild b/include/asm-ia64/Kbuild +index f1cb00f..15818a1 100644 +--- a/include/asm-ia64/Kbuild ++++ b/include/asm-ia64/Kbuild +@@ -1,7 +1,17 @@ + include include/asm-generic/Kbuild.asm + +-header-y += break.h fpu.h fpswa.h gcc_intrin.h ia64regs.h \ +- intel_intrin.h intrinsics.h perfmon_default_smpl.h \ +- ptrace_offsets.h rse.h setup.h ucontext.h ++header-y += break.h ++header-y += fpu.h ++header-y += fpswa.h ++header-y += gcc_intrin.h ++header-y += ia64regs.h ++header-y += intel_intrin.h ++header-y += intrinsics.h ++header-y += perfmon_default_smpl.h ++header-y += ptrace_offsets.h ++header-y += rse.h ++header-y += setup.h ++header-y += ucontext.h + +-unifdef-y += perfmon.h ustack.h ++unifdef-y += perfmon.h ++unifdef-y += ustack.h +diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h +index e5a8260..7d5e2cc 100644 +--- a/include/asm-ia64/numa.h ++++ b/include/asm-ia64/numa.h +@@ -64,7 +64,13 @@ extern int paddr_to_nid(unsigned long pa + + #define local_nodeid (cpu_to_node_map[smp_processor_id()]) + ++extern void map_cpu_to_node(int cpu, int nid); ++extern void unmap_cpu_from_node(int cpu, int nid); ++ ++ + #else /* !CONFIG_NUMA */ ++#define map_cpu_to_node(cpu, nid) do{}while(0) ++#define unmap_cpu_from_node(cpu, nid) do{}while(0) + + #define paddr_to_nid(addr) 0 + +diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h +index 9688be0..404a4c2 100644 +--- a/include/asm-m32r/page.h ++++ b/include/asm-m32r/page.h +@@ -87,10 +87,9 @@ #define VM_DATA_DEFAULT_FLAGS (VM_READ | + + #define devmem_is_allowed(x) 1 + +-#endif /* __KERNEL__ */ +- + #include + #include + ++#endif /* __KERNEL__ */ + #endif /* _ASM_M32R_PAGE_H */ + +diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h +index a07fa90..2d2a6c9 100644 +--- a/include/asm-m32r/ptrace.h ++++ b/include/asm-m32r/ptrace.h +@@ -12,8 +12,6 @@ #define _ASM_M32R_PTRACE_H + * Copyright (C) 2001-2002, 2004 Hirokazu Takata + */ + +-#include /* M32R_PSW_BSM, M32R_PSW_BPM */ +- + /* 0 - 13 are integer registers (general purpose registers). */ + #define PT_R4 0 + #define PT_R5 1 +@@ -140,6 +138,8 @@ #define PTRACE_O_TRACESYSGOOD 0x00000001 + + #ifdef __KERNEL__ + ++#include /* M32R_PSW_BSM, M32R_PSW_BPM */ ++ + #define __ARCH_SYS_PTRACE 1 + + #if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2) +diff --git a/include/asm-m32r/signal.h b/include/asm-m32r/signal.h +index e750045..65423be 100644 +--- a/include/asm-m32r/signal.h ++++ b/include/asm-m32r/signal.h +@@ -6,7 +6,6 @@ #define _ASM_M32R_SIGNAL_H + /* orig : i386 2.4.18 */ + + #include +-#include + #include + #include + +diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h +index cc31790..89f376e 100644 +--- a/include/asm-m32r/unistd.h ++++ b/include/asm-m32r/unistd.h +@@ -3,8 +3,6 @@ #define _ASM_M32R_UNISTD_H + + /* $Id$ */ + +-#include /* SYSCALL_* */ +- + /* + * This file contains the system call numbers. + */ +@@ -303,6 +301,8 @@ #define NR_syscalls 285 + * + */ + ++#include /* SYSCALL_* */ ++ + #define __syscall_return(type, res) \ + do { \ + if ((unsigned long)(res) >= (unsigned long)(-(124 + 1))) { \ +diff --git a/include/asm-m32r/user.h b/include/asm-m32r/user.h +index 2ffd0c6..1ad4ded 100644 +--- a/include/asm-m32r/user.h ++++ b/include/asm-m32r/user.h +@@ -8,7 +8,6 @@ #define _ASM_M32R_USER_H + */ + + #include +-#include + #include + #include + +diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h +index a22bf5a..2a1b8bd 100644 +--- a/include/asm-m68knommu/page.h ++++ b/include/asm-m68knommu/page.h +@@ -1,6 +1,7 @@ + #ifndef _M68KNOMMU_PAGE_H + #define _M68KNOMMU_PAGE_H + ++#ifdef __KERNEL__ + + /* PAGE_SHIFT determines the page size */ + +@@ -8,8 +9,6 @@ #define PAGE_SHIFT (12) + #define PAGE_SIZE (1UL << PAGE_SHIFT) + #define PAGE_MASK (~(PAGE_SIZE-1)) + +-#ifdef __KERNEL__ +- + #include + + #ifndef __ASSEMBLY__ +@@ -76,8 +75,8 @@ #define virt_addr_valid(kaddr) (((void * + + #endif /* __ASSEMBLY__ */ + +-#endif /* __KERNEL__ */ +- + #include + ++#endif /* __KERNEL__ */ ++ + #endif /* _M68KNOMMU_PAGE_H */ +diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild +index ac61d7e..9827849 100644 +--- a/include/asm-powerpc/Kbuild ++++ b/include/asm-powerpc/Kbuild +@@ -1,10 +1,41 @@ + include include/asm-generic/Kbuild.asm + +-unifdef-y += a.out.h asm-compat.h bootx.h byteorder.h cputable.h elf.h \ +- nvram.h param.h posix_types.h ptrace.h seccomp.h signal.h \ +- termios.h types.h unistd.h ++header-y += auxvec.h ++header-y += ioctls.h ++header-y += mman.h ++header-y += sembuf.h ++header-y += siginfo.h ++header-y += stat.h ++header-y += errno.h ++header-y += ipcbuf.h ++header-y += msgbuf.h ++header-y += shmbuf.h ++header-y += socket.h ++header-y += termbits.h ++header-y += fcntl.h ++header-y += ipc.h ++header-y += poll.h ++header-y += shmparam.h ++header-y += sockios.h ++header-y += ucontext.h ++header-y += ioctl.h ++header-y += linkage.h ++header-y += resource.h ++header-y += sigcontext.h ++header-y += statfs.h + +-header-y += auxvec.h ioctls.h mman.h sembuf.h siginfo.h stat.h errno.h \ +- ipcbuf.h msgbuf.h shmbuf.h socket.h termbits.h fcntl.h ipc.h \ +- poll.h shmparam.h sockios.h ucontext.h ioctl.h linkage.h \ +- resource.h sigcontext.h statfs.h ++unifdef-y += a.out.h ++unifdef-y += asm-compat.h ++unifdef-y += bootx.h ++unifdef-y += byteorder.h ++unifdef-y += cputable.h ++unifdef-y += elf.h ++unifdef-y += nvram.h ++unifdef-y += param.h ++unifdef-y += posix_types.h ++unifdef-y += ptrace.h ++unifdef-y += seccomp.h ++unifdef-y += signal.h ++unifdef-y += termios.h ++unifdef-y += types.h ++unifdef-y += unistd.h +diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h +index dc4cb9c..4435efe 100644 +--- a/include/asm-powerpc/ptrace.h ++++ b/include/asm-powerpc/ptrace.h +@@ -215,12 +215,10 @@ #endif /* __powerpc64__ */ + #define PTRACE_GETVRREGS 18 + #define PTRACE_SETVRREGS 19 + +-#ifndef __powerpc64__ + /* Get/set all the upper 32-bits of the SPE registers, accumulator, and + * spefscr, in one go */ + #define PTRACE_GETEVRREGS 20 + #define PTRACE_SETEVRREGS 21 +-#endif /* __powerpc64__ */ + + /* + * Get or set a debug register. The first 16 are DABR registers and the +@@ -235,7 +233,6 @@ #define PPC_PTRACE_SETREGS 0x98 /* Set G + #define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ + #define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */ + +-#ifdef __powerpc64__ + /* Calls to trace a 64bit program from a 32bit program */ + #define PPC_PTRACE_PEEKTEXT_3264 0x95 + #define PPC_PTRACE_PEEKDATA_3264 0x94 +@@ -243,6 +240,5 @@ #define PPC_PTRACE_POKETEXT_3264 0x93 + #define PPC_PTRACE_POKEDATA_3264 0x92 + #define PPC_PTRACE_PEEKUSR_3264 0x91 + #define PPC_PTRACE_POKEUSR_3264 0x90 +-#endif /* __powerpc64__ */ + + #endif /* _ASM_POWERPC_PTRACE_H */ +diff --git a/include/asm-s390/Kbuild b/include/asm-s390/Kbuild +index ed8955f..14158a4 100644 +--- a/include/asm-s390/Kbuild ++++ b/include/asm-s390/Kbuild +@@ -1,4 +1,11 @@ + include include/asm-generic/Kbuild.asm + +-unifdef-y += cmb.h debug.h +-header-y += dasd.h qeth.h tape390.h ucontext.h vtoc.h z90crypt.h ++header-y += dasd.h ++header-y += qeth.h ++header-y += tape390.h ++header-y += ucontext.h ++header-y += vtoc.h ++header-y += z90crypt.h ++ ++unifdef-y += cmb.h ++unifdef-y += debug.h +diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h +index 5a057b0..6f7eb8a 100644 +--- a/include/asm-sh/page.h ++++ b/include/asm-sh/page.h +@@ -112,9 +112,8 @@ #define virt_addr_valid(kaddr) pfn_valid + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +-#endif /* __KERNEL__ */ +- + #include + #include + ++#endif /* __KERNEL__ */ + #endif /* __ASM_SH_PAGE_H */ +diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h +index 792fc35..ed358a3 100644 +--- a/include/asm-sh/ptrace.h ++++ b/include/asm-sh/ptrace.h +@@ -1,8 +1,6 @@ + #ifndef __ASM_SH_PTRACE_H + #define __ASM_SH_PTRACE_H + +-#include +- + /* + * Copyright (C) 1999, 2000 Niibe Yutaka + * +diff --git a/include/asm-sh64/page.h b/include/asm-sh64/page.h +index 34fb347..472089a 100644 +--- a/include/asm-sh64/page.h ++++ b/include/asm-sh64/page.h +@@ -112,9 +112,8 @@ #define virt_addr_valid(kaddr) pfn_valid + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +-#endif /* __KERNEL__ */ +- + #include + #include + ++#endif /* __KERNEL__ */ + #endif /* __ASM_SH64_PAGE_H */ +diff --git a/include/asm-sh64/shmparam.h b/include/asm-sh64/shmparam.h +index d3a99a4..1bb820c 100644 +--- a/include/asm-sh64/shmparam.h ++++ b/include/asm-sh64/shmparam.h +@@ -2,19 +2,11 @@ #ifndef __ASM_SH64_SHMPARAM_H + #define __ASM_SH64_SHMPARAM_H + + /* +- * This file is subject to the terms and conditions of the GNU General Public +- * License. See the file "COPYING" in the main directory of this archive +- * for more details. +- * +- * include/asm-sh64/shmparam.h +- * +- * Copyright (C) 2000, 2001 Paolo Alberelli +- * ++ * Set this to a sensible safe default, we'll work out the specifics for the ++ * align mask from the cache descriptor at run-time. + */ ++#define SHMLBA 0x4000 + +-#include +- +-/* attach addr a multiple of this */ +-#define SHMLBA (cpu_data->dcache.sets * L1_CACHE_BYTES) ++#define __ARCH_FORCE_SHMLBA + + #endif /* __ASM_SH64_SHMPARAM_H */ +diff --git a/include/asm-sh64/signal.h b/include/asm-sh64/signal.h +index a5a2820..244e134 100644 +--- a/include/asm-sh64/signal.h ++++ b/include/asm-sh64/signal.h +@@ -13,7 +13,6 @@ #define __ASM_SH64_SIGNAL_H + */ + + #include +-#include + + /* Avoid too many header ordering problems. */ + struct siginfo; +diff --git a/include/asm-sh64/user.h b/include/asm-sh64/user.h +index 8f32f39..eb3b33e 100644 +--- a/include/asm-sh64/user.h ++++ b/include/asm-sh64/user.h +@@ -13,7 +13,6 @@ #define __ASM_SH64_USER_H + */ + + #include +-#include + #include + #include + +diff --git a/include/asm-sparc/Kbuild b/include/asm-sparc/Kbuild +index e2a57fd..c6a55cf 100644 +--- a/include/asm-sparc/Kbuild ++++ b/include/asm-sparc/Kbuild +@@ -1,6 +1,15 @@ + include include/asm-generic/Kbuild.asm + +-unifdef-y += fbio.h perfctr.h psr.h +-header-y += apc.h asi.h auxio.h bpp.h head.h ipc.h jsflash.h \ +- openpromio.h pbm.h pconf.h pgtsun4.h reg.h traps.h \ +- turbosparc.h vfc_ioctls.h winmacro.h ++header-y += apc.h ++header-y += asi.h ++header-y += bpp.h ++header-y += jsflash.h ++header-y += openpromio.h ++header-y += pconf.h ++header-y += reg.h ++header-y += traps.h ++header-y += vfc_ioctls.h ++ ++unifdef-y += fbio.h ++unifdef-y += perfctr.h ++unifdef-y += psr.h +diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h +index 5bab8a7..ff57648 100644 +--- a/include/asm-sparc/page.h ++++ b/include/asm-sparc/page.h +@@ -8,6 +8,8 @@ + #ifndef _SPARC_PAGE_H + #define _SPARC_PAGE_H + ++#ifdef __KERNEL__ ++ + #ifdef CONFIG_SUN4 + #define PAGE_SHIFT 13 + #else +@@ -21,8 +23,6 @@ #define PAGE_SIZE (1 << PAGE_SHIFT) + #endif + #define PAGE_MASK (~(PAGE_SIZE-1)) + +-#ifdef __KERNEL__ +- + #include + + #ifndef __ASSEMBLY__ +@@ -160,9 +160,9 @@ #define virt_addr_valid(kaddr) ((((unsig + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +-#endif /* __KERNEL__ */ +- + #include + #include + ++#endif /* __KERNEL__ */ ++ + #endif /* _SPARC_PAGE_H */ +diff --git a/include/asm-sparc64/Kbuild b/include/asm-sparc64/Kbuild +index 9284c3c..a7f4440 100644 +--- a/include/asm-sparc64/Kbuild ++++ b/include/asm-sparc64/Kbuild +@@ -4,7 +4,23 @@ ALTARCH := sparc + ARCHDEF := defined __sparc__ && defined __arch64__ + ALTARCHDEF := defined __sparc__ && !defined __arch64__ + +-unifdef-y += fbio.h perfctr.h +-header-y += apb.h asi.h bbc.h bpp.h display7seg.h envctrl.h floppy.h \ +- ipc.h kdebug.h mostek.h openprom.h openpromio.h parport.h \ +- pconf.h psrcompat.h pstate.h reg.h uctx.h utrap.h watchdog.h ++header-y += apb.h ++header-y += asi.h ++header-y += bbc.h ++header-y += bpp.h ++header-y += const.h ++header-y += display7seg.h ++header-y += envctrl.h ++header-y += ipc.h ++header-y += openprom.h ++header-y += openpromio.h ++header-y += pconf.h ++header-y += psrcompat.h ++header-y += pstate.h ++header-y += reg.h ++header-y += uctx.h ++header-y += utrap.h ++header-y += watchdog.h ++ ++unifdef-y += fbio.h ++unifdef-y += perfctr.h +diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h +index fdf0ceb..ff736ea 100644 +--- a/include/asm-sparc64/page.h ++++ b/include/asm-sparc64/page.h +@@ -3,6 +3,8 @@ + #ifndef _SPARC64_PAGE_H + #define _SPARC64_PAGE_H + ++#ifdef __KERNEL__ ++ + #include + + #if defined(CONFIG_SPARC64_PAGE_SIZE_8KB) +@@ -27,8 +29,6 @@ #if PAGE_SHIFT < 14 + #define DCACHE_ALIASING_POSSIBLE + #endif + +-#ifdef __KERNEL__ +- + #if defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) + #define HPAGE_SHIFT 22 + #elif defined(CONFIG_HUGETLB_PAGE_SIZE_512K) +@@ -141,8 +141,7 @@ #endif /* !(__ASSEMBLY__) */ + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +-#endif /* !(__KERNEL__) */ +- + #include + +-#endif /* !(_SPARC64_PAGE_H) */ ++#endif /* __KERNEL__ */ ++#endif /* _SPARC64_PAGE_H */ +diff --git a/include/asm-sparc64/shmparam.h b/include/asm-sparc64/shmparam.h +index 8c66fde..911d042 100644 +--- a/include/asm-sparc64/shmparam.h ++++ b/include/asm-sparc64/shmparam.h +@@ -1,6 +1,7 @@ + /* $Id: shmparam.h,v 1.5 2001/09/24 21:17:57 kanoj Exp $ */ + #ifndef _ASMSPARC64_SHMPARAM_H + #define _ASMSPARC64_SHMPARAM_H ++#ifdef __KERNEL__ + + #include + +@@ -8,4 +9,5 @@ #define __ARCH_FORCE_SHMLBA 1 + /* attach addr a multiple of this */ + #define SHMLBA ((PAGE_SIZE > L1DCACHE_SIZE) ? PAGE_SIZE : L1DCACHE_SIZE) + ++#endif /* __KERNEL__ */ + #endif /* _ASMSPARC64_SHMPARAM_H */ +diff --git a/include/asm-um/Kbuild b/include/asm-um/Kbuild +deleted file mode 100644 +index c68e168..0000000 +--- a/include/asm-um/Kbuild ++++ /dev/null +@@ -1 +0,0 @@ +-include include/asm-generic/Kbuild.asm +diff --git a/include/asm-v850/page.h b/include/asm-v850/page.h +index ad03c46..d693ffb 100644 +--- a/include/asm-v850/page.h ++++ b/include/asm-v850/page.h +@@ -14,6 +14,8 @@ + #ifndef __V850_PAGE_H__ + #define __V850_PAGE_H__ + ++#ifdef __KERNEL__ ++ + #include + + +@@ -32,7 +34,6 @@ #define PAGE_OFFSET 0x0000000 + #endif + + +-#ifdef __KERNEL__ + #ifndef __ASSEMBLY__ + + #define STRICT_MM_TYPECHECKS +@@ -122,9 +123,9 @@ #define __pa(x) __virt_to_phys ((u + #define __va(x) ((void *)__phys_to_virt ((unsigned long)(x))) + + +-#endif /* KERNEL */ +- + #include + #include + ++#endif /* KERNEL */ ++ + #endif /* __V850_PAGE_H__ */ +diff --git a/include/asm-v850/param.h b/include/asm-v850/param.h +index 8d796e4..3c65bd5 100644 +--- a/include/asm-v850/param.h ++++ b/include/asm-v850/param.h +@@ -14,8 +14,6 @@ + #ifndef __V850_PARAM_H__ + #define __V850_PARAM_H__ + +-#include /* For HZ */ +- + #define EXEC_PAGESIZE 4096 + + #ifndef NOGROUP +@@ -25,6 +23,8 @@ #endif + #define MAXHOSTNAMELEN 64 /* max length of hostname */ + + #ifdef __KERNEL__ ++#include /* For HZ */ ++ + # define USER_HZ 100 + # define CLOCKS_PER_SEC USER_HZ + #endif +diff --git a/include/asm-x86_64/Kbuild b/include/asm-x86_64/Kbuild +index dc4d101..40f2f13 100644 +--- a/include/asm-x86_64/Kbuild ++++ b/include/asm-x86_64/Kbuild +@@ -4,8 +4,18 @@ ALTARCH := i386 + ARCHDEF := defined __x86_64__ + ALTARCHDEF := defined __i386__ + +-header-y += boot.h bootsetup.h cpufeature.h debugreg.h ldt.h \ +- msr.h prctl.h setup.h sigcontext32.h ucontext.h \ +- vsyscall32.h ++header-y += boot.h ++header-y += bootsetup.h ++header-y += cpufeature.h ++header-y += debugreg.h ++header-y += ldt.h ++header-y += msr.h ++header-y += prctl.h ++header-y += setup.h ++header-y += sigcontext32.h ++header-y += ucontext.h ++header-y += vsyscall32.h + +-unifdef-y += mce.h mtrr.h vsyscall.h ++unifdef-y += mce.h ++unifdef-y += mtrr.h ++unifdef-y += vsyscall.h +diff --git a/include/linux/Kbuild b/include/linux/Kbuild +index 2b8a7d6..10d2ca0 100644 +--- a/include/linux/Kbuild ++++ b/include/linux/Kbuild +@@ -1,63 +1,343 @@ +-header-y := byteorder/ dvb/ hdlc/ isdn/ nfsd/ raid/ sunrpc/ tc_act/ \ +- netfilter/ netfilter_arp/ netfilter_bridge/ netfilter_ipv4/ \ +- netfilter_ipv6/ ++header-y += byteorder/ ++header-y += dvb/ ++header-y += hdlc/ ++header-y += isdn/ ++header-y += nfsd/ ++header-y += raid/ ++header-y += sunrpc/ ++header-y += tc_act/ ++header-y += netfilter/ ++header-y += netfilter_arp/ ++header-y += netfilter_bridge/ ++header-y += netfilter_ipv4/ ++header-y += netfilter_ipv6/ + +-header-y += affs_fs.h affs_hardblocks.h aio_abi.h a.out.h arcfb.h \ +- atmapi.h atmbr2684.h atmclip.h atm_eni.h atm_he.h \ +- atm_idt77105.h atmioc.h atmlec.h atmmpc.h atm_nicstar.h \ +- atmppp.h atmsap.h atmsvc.h atm_zatm.h auto_fs4.h auxvec.h \ +- awe_voice.h ax25.h b1lli.h baycom.h bfs_fs.h blkpg.h \ +- bpqether.h cdk.h chio.h coda_psdev.h coff.h comstats.h \ +- consolemap.h cycx_cfm.h dm-ioctl.h dn.h dqblk_v1.h \ +- dqblk_v2.h dqblk_xfs.h efs_fs_sb.h elf-fdpic.h elf.h elf-em.h \ +- fadvise.h fd.h fdreg.h ftape-header-segment.h ftape-vendors.h \ +- fuse.h futex.h genetlink.h gen_stats.h gigaset_dev.h hdsmart.h \ +- hpfs_fs.h hysdn_if.h i2c-dev.h i8k.h icmp.h \ +- if_arcnet.h if_arp.h if_bonding.h if_cablemodem.h if_fc.h \ +- if_fddi.h if.h if_hippi.h if_infiniband.h if_packet.h \ +- if_plip.h if_ppp.h if_slip.h if_strip.h if_tunnel.h in6.h \ +- in_route.h ioctl.h ip.h ipmi_msgdefs.h ip_mp_alg.h ipsec.h \ +- ipx.h irda.h isdn_divertif.h iso_fs.h ite_gpio.h ixjuser.h \ +- jffs2.h keyctl.h limits.h major.h matroxfb.h meye.h minix_fs.h \ +- mmtimer.h mqueue.h mtio.h ncp_no.h netfilter_arp.h netrom.h \ +- nfs2.h nfs4_mount.h nfs_mount.h openprom_fs.h param.h \ +- pci_ids.h pci_regs.h personality.h pfkeyv2.h pg.h pkt_cls.h \ +- pkt_sched.h posix_types.h ppdev.h prctl.h ps2esdi.h qic117.h \ +- qnxtypes.h quotaio_v1.h quotaio_v2.h radeonfb.h raw.h \ +- resource.h rose.h sctp.h smbno.h snmp.h sockios.h som.h \ +- sound.h stddef.h synclink.h telephony.h termios.h ticable.h \ +- times.h tiocl.h tipc.h toshiba.h ultrasound.h un.h utime.h \ +- utsname.h video_decoder.h video_encoder.h videotext.h vt.h \ +- wavefront.h wireless.h xattr.h x25.h zorro_ids.h ++header-y += affs_fs.h ++header-y += affs_hardblocks.h ++header-y += aio_abi.h ++header-y += a.out.h ++header-y += arcfb.h ++header-y += atmapi.h ++header-y += atmbr2684.h ++header-y += atmclip.h ++header-y += atm_eni.h ++header-y += atm_he.h ++header-y += atm_idt77105.h ++header-y += atmioc.h ++header-y += atmlec.h ++header-y += atmmpc.h ++header-y += atm_nicstar.h ++header-y += atmppp.h ++header-y += atmsap.h ++header-y += atmsvc.h ++header-y += atm_zatm.h ++header-y += auto_fs4.h ++header-y += auxvec.h ++header-y += awe_voice.h ++header-y += ax25.h ++header-y += b1lli.h ++header-y += baycom.h ++header-y += bfs_fs.h ++header-y += blkpg.h ++header-y += bpqether.h ++header-y += cdk.h ++header-y += chio.h ++header-y += coda_psdev.h ++header-y += coff.h ++header-y += comstats.h ++header-y += consolemap.h ++header-y += cycx_cfm.h ++header-y += dm-ioctl.h ++header-y += dn.h ++header-y += dqblk_v1.h ++header-y += dqblk_v2.h ++header-y += dqblk_xfs.h ++header-y += efs_fs_sb.h ++header-y += elf-fdpic.h ++header-y += elf.h ++header-y += elf-em.h ++header-y += fadvise.h ++header-y += fd.h ++header-y += fdreg.h ++header-y += ftape-header-segment.h ++header-y += ftape-vendors.h ++header-y += fuse.h ++header-y += futex.h ++header-y += genetlink.h ++header-y += gen_stats.h ++header-y += gigaset_dev.h ++header-y += hdsmart.h ++header-y += hpfs_fs.h ++header-y += hysdn_if.h ++header-y += i2c-dev.h ++header-y += i8k.h ++header-y += icmp.h ++header-y += if_arcnet.h ++header-y += if_arp.h ++header-y += if_bonding.h ++header-y += if_cablemodem.h ++header-y += if_fc.h ++header-y += if_fddi.h ++header-y += if.h ++header-y += if_hippi.h ++header-y += if_infiniband.h ++header-y += if_packet.h ++header-y += if_plip.h ++header-y += if_ppp.h ++header-y += if_slip.h ++header-y += if_strip.h ++header-y += if_tunnel.h ++header-y += in6.h ++header-y += in_route.h ++header-y += ioctl.h ++header-y += ip.h ++header-y += ipmi_msgdefs.h ++header-y += ip_mp_alg.h ++header-y += ipsec.h ++header-y += ipx.h ++header-y += irda.h ++header-y += isdn_divertif.h ++header-y += iso_fs.h ++header-y += ite_gpio.h ++header-y += ixjuser.h ++header-y += jffs2.h ++header-y += keyctl.h ++header-y += limits.h ++header-y += major.h ++header-y += matroxfb.h ++header-y += meye.h ++header-y += minix_fs.h ++header-y += mmtimer.h ++header-y += mqueue.h ++header-y += mtio.h ++header-y += ncp_no.h ++header-y += netfilter_arp.h ++header-y += netrom.h ++header-y += nfs2.h ++header-y += nfs4_mount.h ++header-y += nfs_mount.h ++header-y += openprom_fs.h ++header-y += param.h ++header-y += pci_ids.h ++header-y += pci_regs.h ++header-y += personality.h ++header-y += pfkeyv2.h ++header-y += pg.h ++header-y += pkt_cls.h ++header-y += pkt_sched.h ++header-y += posix_types.h ++header-y += ppdev.h ++header-y += prctl.h ++header-y += ps2esdi.h ++header-y += qic117.h ++header-y += qnxtypes.h ++header-y += quotaio_v1.h ++header-y += quotaio_v2.h ++header-y += radeonfb.h ++header-y += raw.h ++header-y += resource.h ++header-y += rose.h ++header-y += sctp.h ++header-y += smbno.h ++header-y += snmp.h ++header-y += sockios.h ++header-y += som.h ++header-y += sound.h ++header-y += synclink.h ++header-y += telephony.h ++header-y += termios.h ++header-y += ticable.h ++header-y += times.h ++header-y += tiocl.h ++header-y += tipc.h ++header-y += toshiba.h ++header-y += ultrasound.h ++header-y += un.h ++header-y += utime.h ++header-y += utsname.h ++header-y += video_decoder.h ++header-y += video_encoder.h ++header-y += videotext.h ++header-y += vt.h ++header-y += wavefront.h ++header-y += wireless.h ++header-y += xattr.h ++header-y += x25.h ++header-y += zorro_ids.h + +-unifdef-y += acct.h adb.h adfs_fs.h agpgart.h apm_bios.h atalk.h \ +- atmarp.h atmdev.h atm.h atm_tcp.h audit.h auto_fs.h binfmts.h \ +- capability.h capi.h cciss_ioctl.h cdrom.h cm4000_cs.h \ +- cn_proc.h coda.h connector.h cramfs_fs.h cuda.h cyclades.h \ +- dccp.h dirent.h divert.h elfcore.h errno.h errqueue.h \ +- ethtool.h eventpoll.h ext2_fs.h ext3_fs.h fb.h fcntl.h \ +- filter.h flat.h fs.h ftape.h gameport.h generic_serial.h \ +- genhd.h hayesesp.h hdlcdrv.h hdlc.h hdreg.h hiddev.h hpet.h \ +- i2c.h i2o-dev.h icmpv6.h if_bridge.h if_ec.h \ +- if_eql.h if_ether.h if_frad.h if_ltalk.h if_pppox.h \ +- if_shaper.h if_tr.h if_tun.h if_vlan.h if_wanpipe.h igmp.h \ +- inet_diag.h in.h inotify.h input.h ipc.h ipmi.h ipv6.h \ +- ipv6_route.h isdn.h isdnif.h isdn_ppp.h isicom.h jbd.h \ +- joystick.h kdev_t.h kd.h kernelcapi.h kernel.h keyboard.h \ +- llc.h loop.h lp.h mempolicy.h mii.h mman.h mroute.h msdos_fs.h \ +- msg.h nbd.h ncp_fs.h ncp.h ncp_mount.h netdevice.h \ +- netfilter_bridge.h netfilter_decnet.h netfilter.h \ +- netfilter_ipv4.h netfilter_ipv6.h netfilter_logging.h net.h \ +- netlink.h nfs3.h nfs4.h nfsacl.h nfs_fs.h nfs.h nfs_idmap.h \ +- n_r3964.h nubus.h nvram.h parport.h patchkey.h pci.h pktcdvd.h \ +- pmu.h poll.h ppp_defs.h ppp-comp.h ptrace.h qnx4_fs.h quota.h \ +- random.h reboot.h reiserfs_fs.h reiserfs_xattr.h romfs_fs.h \ +- route.h rtc.h rtnetlink.h scc.h sched.h sdla.h \ +- selinux_netlink.h sem.h serial_core.h serial.h serio.h shm.h \ +- signal.h smb_fs.h smb.h smb_mount.h socket.h sonet.h sonypi.h \ +- soundcard.h stat.h sysctl.h tcp.h time.h timex.h tty.h types.h \ +- udf_fs_i.h udp.h uinput.h uio.h unistd.h usb_ch9.h \ +- usbdevice_fs.h user.h videodev2.h videodev.h wait.h \ +- wanrouter.h watchdog.h xfrm.h zftape.h ++unifdef-y += acct.h ++unifdef-y += adb.h ++unifdef-y += adfs_fs.h ++unifdef-y += agpgart.h ++unifdef-y += apm_bios.h ++unifdef-y += atalk.h ++unifdef-y += atmarp.h ++unifdef-y += atmdev.h ++unifdef-y += atm.h ++unifdef-y += atm_tcp.h ++unifdef-y += audit.h ++unifdef-y += auto_fs.h ++unifdef-y += binfmts.h ++unifdef-y += capability.h ++unifdef-y += capi.h ++unifdef-y += cciss_ioctl.h ++unifdef-y += cdrom.h ++unifdef-y += cm4000_cs.h ++unifdef-y += cn_proc.h ++unifdef-y += coda.h ++unifdef-y += connector.h ++unifdef-y += cramfs_fs.h ++unifdef-y += cuda.h ++unifdef-y += cyclades.h ++unifdef-y += dccp.h ++unifdef-y += dirent.h ++unifdef-y += divert.h ++unifdef-y += elfcore.h ++unifdef-y += errno.h ++unifdef-y += errqueue.h ++unifdef-y += ethtool.h ++unifdef-y += eventpoll.h ++unifdef-y += ext2_fs.h ++unifdef-y += ext3_fs.h ++unifdef-y += fb.h ++unifdef-y += fcntl.h ++unifdef-y += filter.h ++unifdef-y += flat.h ++unifdef-y += fs.h ++unifdef-y += ftape.h ++unifdef-y += gameport.h ++unifdef-y += generic_serial.h ++unifdef-y += genhd.h ++unifdef-y += hayesesp.h ++unifdef-y += hdlcdrv.h ++unifdef-y += hdlc.h ++unifdef-y += hdreg.h ++unifdef-y += hiddev.h ++unifdef-y += hpet.h ++unifdef-y += i2c.h ++unifdef-y += i2o-dev.h ++unifdef-y += icmpv6.h ++unifdef-y += if_bridge.h ++unifdef-y += if_ec.h ++unifdef-y += if_eql.h ++unifdef-y += if_ether.h ++unifdef-y += if_frad.h ++unifdef-y += if_ltalk.h ++unifdef-y += if_pppox.h ++unifdef-y += if_shaper.h ++unifdef-y += if_tr.h ++unifdef-y += if_tun.h ++unifdef-y += if_vlan.h ++unifdef-y += if_wanpipe.h ++unifdef-y += igmp.h ++unifdef-y += inet_diag.h ++unifdef-y += in.h ++unifdef-y += inotify.h ++unifdef-y += input.h ++unifdef-y += ipc.h ++unifdef-y += ipmi.h ++unifdef-y += ipv6.h ++unifdef-y += ipv6_route.h ++unifdef-y += isdn.h ++unifdef-y += isdnif.h ++unifdef-y += isdn_ppp.h ++unifdef-y += isicom.h ++unifdef-y += jbd.h ++unifdef-y += joystick.h ++unifdef-y += kdev_t.h ++unifdef-y += kd.h ++unifdef-y += kernelcapi.h ++unifdef-y += kernel.h ++unifdef-y += keyboard.h ++unifdef-y += llc.h ++unifdef-y += loop.h ++unifdef-y += lp.h ++unifdef-y += mempolicy.h ++unifdef-y += mii.h ++unifdef-y += mman.h ++unifdef-y += mroute.h ++unifdef-y += msdos_fs.h ++unifdef-y += msg.h ++unifdef-y += nbd.h ++unifdef-y += ncp_fs.h ++unifdef-y += ncp.h ++unifdef-y += ncp_mount.h ++unifdef-y += netdevice.h ++unifdef-y += netfilter_bridge.h ++unifdef-y += netfilter_decnet.h ++unifdef-y += netfilter.h ++unifdef-y += netfilter_ipv4.h ++unifdef-y += netfilter_ipv6.h ++unifdef-y += netfilter_logging.h ++unifdef-y += net.h ++unifdef-y += netlink.h ++unifdef-y += nfs3.h ++unifdef-y += nfs4.h ++unifdef-y += nfsacl.h ++unifdef-y += nfs_fs.h ++unifdef-y += nfs.h ++unifdef-y += nfs_idmap.h ++unifdef-y += n_r3964.h ++unifdef-y += nubus.h ++unifdef-y += nvram.h ++unifdef-y += parport.h ++unifdef-y += patchkey.h ++unifdef-y += pci.h ++unifdef-y += pktcdvd.h ++unifdef-y += pmu.h ++unifdef-y += poll.h ++unifdef-y += ppp_defs.h ++unifdef-y += ppp-comp.h ++unifdef-y += ptrace.h ++unifdef-y += qnx4_fs.h ++unifdef-y += quota.h ++unifdef-y += random.h ++unifdef-y += reboot.h ++unifdef-y += reiserfs_fs.h ++unifdef-y += reiserfs_xattr.h ++unifdef-y += romfs_fs.h ++unifdef-y += route.h ++unifdef-y += rtc.h ++unifdef-y += rtnetlink.h ++unifdef-y += scc.h ++unifdef-y += sched.h ++unifdef-y += sdla.h ++unifdef-y += selinux_netlink.h ++unifdef-y += sem.h ++unifdef-y += serial_core.h ++unifdef-y += serial.h ++unifdef-y += serio.h ++unifdef-y += shm.h ++unifdef-y += signal.h ++unifdef-y += smb_fs.h ++unifdef-y += smb.h ++unifdef-y += smb_mount.h ++unifdef-y += socket.h ++unifdef-y += sonet.h ++unifdef-y += sonypi.h ++unifdef-y += soundcard.h ++unifdef-y += stat.h ++unifdef-y += stddef.h ++unifdef-y += sysctl.h ++unifdef-y += tcp.h ++unifdef-y += time.h ++unifdef-y += timex.h ++unifdef-y += tty.h ++unifdef-y += types.h ++unifdef-y += udf_fs_i.h ++unifdef-y += udp.h ++unifdef-y += uinput.h ++unifdef-y += uio.h ++unifdef-y += unistd.h ++unifdef-y += usb_ch9.h ++unifdef-y += usbdevice_fs.h ++unifdef-y += user.h ++unifdef-y += videodev2.h ++unifdef-y += videodev.h ++unifdef-y += wait.h ++unifdef-y += wanrouter.h ++unifdef-y += watchdog.h ++unifdef-y += xfrm.h ++unifdef-y += zftape.h + +-objhdr-y := version.h ++objhdr-y += version.h +diff --git a/include/linux/byteorder/Kbuild b/include/linux/byteorder/Kbuild +index 84a57d4..56499ab 100644 +--- a/include/linux/byteorder/Kbuild ++++ b/include/linux/byteorder/Kbuild +@@ -1,2 +1,7 @@ +-unifdef-y += generic.h swabb.h swab.h +-header-y += big_endian.h little_endian.h pdp_endian.h ++header-y += big_endian.h ++header-y += little_endian.h ++header-y += pdp_endian.h ++ ++unifdef-y += generic.h ++unifdef-y += swabb.h ++unifdef-y += swab.h +diff --git a/include/linux/dvb/Kbuild b/include/linux/dvb/Kbuild +index 63973af..d97b3a5 100644 +--- a/include/linux/dvb/Kbuild ++++ b/include/linux/dvb/Kbuild +@@ -1,2 +1,9 @@ +-header-y += ca.h frontend.h net.h osd.h version.h +-unifdef-y := audio.h dmx.h video.h ++header-y += ca.h ++header-y += frontend.h ++header-y += net.h ++header-y += osd.h ++header-y += version.h ++ ++unifdef-y += audio.h ++unifdef-y += dmx.h ++unifdef-y += video.h +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index f45163c..5951364 100644 +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -155,6 +155,7 @@ #ifdef CONFIG_NUMA + * zone reclaim becomes active if more unmapped pages exist. + */ + unsigned long min_unmapped_ratio; ++ unsigned long min_slab_pages; + struct per_cpu_pageset *pageset[NR_CPUS]; + #else + struct per_cpu_pageset pageset[NR_CPUS]; +@@ -421,6 +422,8 @@ int percpu_pagelist_fraction_sysctl_hand + void __user *, size_t *, loff_t *); + int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *, int, + struct file *, void __user *, size_t *, loff_t *); ++int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *, int, ++ struct file *, void __user *, size_t *, loff_t *); + + #include + /* Returns the number of the current Node. */ +diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild +index 1d3a14e..9a285ce 100644 +--- a/include/linux/netfilter/Kbuild ++++ b/include/linux/netfilter/Kbuild +@@ -1,11 +1,38 @@ +-header-y := nf_conntrack_sctp.h nf_conntrack_tuple_common.h \ +- nfnetlink_conntrack.h nfnetlink_log.h nfnetlink_queue.h \ +- xt_CLASSIFY.h xt_comment.h xt_connbytes.h xt_connmark.h \ +- xt_CONNMARK.h xt_conntrack.h xt_dccp.h xt_esp.h \ +- xt_helper.h xt_length.h xt_limit.h xt_mac.h xt_mark.h \ +- xt_MARK.h xt_multiport.h xt_NFQUEUE.h xt_pkttype.h \ +- xt_policy.h xt_realm.h xt_sctp.h xt_state.h xt_string.h \ +- xt_tcpmss.h xt_tcpudp.h xt_SECMARK.h xt_CONNSECMARK.h ++header-y += nf_conntrack_sctp.h ++header-y += nf_conntrack_tuple_common.h ++header-y += nfnetlink_conntrack.h ++header-y += nfnetlink_log.h ++header-y += nfnetlink_queue.h ++header-y += xt_CLASSIFY.h ++header-y += xt_comment.h ++header-y += xt_connbytes.h ++header-y += xt_connmark.h ++header-y += xt_CONNMARK.h ++header-y += xt_conntrack.h ++header-y += xt_dccp.h ++header-y += xt_esp.h ++header-y += xt_helper.h ++header-y += xt_length.h ++header-y += xt_limit.h ++header-y += xt_mac.h ++header-y += xt_mark.h ++header-y += xt_MARK.h ++header-y += xt_multiport.h ++header-y += xt_NFQUEUE.h ++header-y += xt_pkttype.h ++header-y += xt_policy.h ++header-y += xt_realm.h ++header-y += xt_sctp.h ++header-y += xt_state.h ++header-y += xt_string.h ++header-y += xt_tcpmss.h ++header-y += xt_tcpudp.h ++header-y += xt_SECMARK.h ++header-y += xt_CONNSECMARK.h + +-unifdef-y := nf_conntrack_common.h nf_conntrack_ftp.h \ +- nf_conntrack_tcp.h nfnetlink.h x_tables.h xt_physdev.h ++unifdef-y += nf_conntrack_common.h ++unifdef-y += nf_conntrack_ftp.h ++unifdef-y += nf_conntrack_tcp.h ++unifdef-y += nfnetlink.h ++unifdef-y += x_tables.h ++unifdef-y += xt_physdev.h +diff --git a/include/linux/netfilter_arp/Kbuild b/include/linux/netfilter_arp/Kbuild +index 198ec5e..4f13dfc 100644 +--- a/include/linux/netfilter_arp/Kbuild ++++ b/include/linux/netfilter_arp/Kbuild +@@ -1,2 +1,3 @@ +-header-y := arpt_mangle.h +-unifdef-y := arp_tables.h ++header-y += arpt_mangle.h ++ ++unifdef-y += arp_tables.h +diff --git a/include/linux/netfilter_bridge/Kbuild b/include/linux/netfilter_bridge/Kbuild +index 5b1aba6..76ff4c4 100644 +--- a/include/linux/netfilter_bridge/Kbuild ++++ b/include/linux/netfilter_bridge/Kbuild +@@ -1,4 +1,17 @@ +-header-y += ebt_among.h ebt_arp.h ebt_arpreply.h ebt_ip.h ebt_limit.h \ +- ebt_log.h ebt_mark_m.h ebt_mark_t.h ebt_nat.h ebt_pkttype.h \ +- ebt_redirect.h ebt_stp.h ebt_ulog.h ebt_vlan.h +-unifdef-y := ebtables.h ebt_802_3.h ++header-y += ebt_among.h ++header-y += ebt_arp.h ++header-y += ebt_arpreply.h ++header-y += ebt_ip.h ++header-y += ebt_limit.h ++header-y += ebt_log.h ++header-y += ebt_mark_m.h ++header-y += ebt_mark_t.h ++header-y += ebt_nat.h ++header-y += ebt_pkttype.h ++header-y += ebt_redirect.h ++header-y += ebt_stp.h ++header-y += ebt_ulog.h ++header-y += ebt_vlan.h ++ ++unifdef-y += ebtables.h ++unifdef-y += ebt_802_3.h +diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild +index 04e4d27..591c1a8 100644 +--- a/include/linux/netfilter_ipv4/Kbuild ++++ b/include/linux/netfilter_ipv4/Kbuild +@@ -1,21 +1,63 @@ ++header-y += ip_conntrack_helper.h ++header-y += ip_conntrack_helper_h323_asn1.h ++header-y += ip_conntrack_helper_h323_types.h ++header-y += ip_conntrack_protocol.h ++header-y += ip_conntrack_sctp.h ++header-y += ip_conntrack_tcp.h ++header-y += ip_conntrack_tftp.h ++header-y += ip_nat_pptp.h ++header-y += ipt_addrtype.h ++header-y += ipt_ah.h ++header-y += ipt_CLASSIFY.h ++header-y += ipt_CLUSTERIP.h ++header-y += ipt_comment.h ++header-y += ipt_connbytes.h ++header-y += ipt_connmark.h ++header-y += ipt_CONNMARK.h ++header-y += ipt_conntrack.h ++header-y += ipt_dccp.h ++header-y += ipt_dscp.h ++header-y += ipt_DSCP.h ++header-y += ipt_ecn.h ++header-y += ipt_ECN.h ++header-y += ipt_esp.h ++header-y += ipt_hashlimit.h ++header-y += ipt_helper.h ++header-y += ipt_iprange.h ++header-y += ipt_length.h ++header-y += ipt_limit.h ++header-y += ipt_LOG.h ++header-y += ipt_mac.h ++header-y += ipt_mark.h ++header-y += ipt_MARK.h ++header-y += ipt_multiport.h ++header-y += ipt_NFQUEUE.h ++header-y += ipt_owner.h ++header-y += ipt_physdev.h ++header-y += ipt_pkttype.h ++header-y += ipt_policy.h ++header-y += ipt_realm.h ++header-y += ipt_recent.h ++header-y += ipt_REJECT.h ++header-y += ipt_SAME.h ++header-y += ipt_sctp.h ++header-y += ipt_state.h ++header-y += ipt_string.h ++header-y += ipt_tcpmss.h ++header-y += ipt_TCPMSS.h ++header-y += ipt_tos.h ++header-y += ipt_TOS.h ++header-y += ipt_ttl.h ++header-y += ipt_TTL.h ++header-y += ipt_ULOG.h + +-header-y := ip_conntrack_helper.h ip_conntrack_helper_h323_asn1.h \ +- ip_conntrack_helper_h323_types.h ip_conntrack_protocol.h \ +- ip_conntrack_sctp.h ip_conntrack_tcp.h ip_conntrack_tftp.h \ +- ip_nat_pptp.h ipt_addrtype.h ipt_ah.h \ +- ipt_CLASSIFY.h ipt_CLUSTERIP.h ipt_comment.h \ +- ipt_connbytes.h ipt_connmark.h ipt_CONNMARK.h \ +- ipt_conntrack.h ipt_dccp.h ipt_dscp.h ipt_DSCP.h ipt_ecn.h \ +- ipt_ECN.h ipt_esp.h ipt_hashlimit.h ipt_helper.h \ +- ipt_iprange.h ipt_length.h ipt_limit.h ipt_LOG.h ipt_mac.h \ +- ipt_mark.h ipt_MARK.h ipt_multiport.h ipt_NFQUEUE.h \ +- ipt_owner.h ipt_physdev.h ipt_pkttype.h ipt_policy.h \ +- ipt_realm.h ipt_recent.h ipt_REJECT.h ipt_SAME.h \ +- ipt_sctp.h ipt_state.h ipt_string.h ipt_tcpmss.h \ +- ipt_TCPMSS.h ipt_tos.h ipt_TOS.h ipt_ttl.h ipt_TTL.h \ +- ipt_ULOG.h +- +-unifdef-y := ip_conntrack.h ip_conntrack_h323.h ip_conntrack_irc.h \ +- ip_conntrack_pptp.h ip_conntrack_proto_gre.h \ +- ip_conntrack_tuple.h ip_nat.h ip_nat_rule.h ip_queue.h \ +- ip_tables.h ++unifdef-y += ip_conntrack.h ++unifdef-y += ip_conntrack_h323.h ++unifdef-y += ip_conntrack_irc.h ++unifdef-y += ip_conntrack_pptp.h ++unifdef-y += ip_conntrack_proto_gre.h ++unifdef-y += ip_conntrack_tuple.h ++unifdef-y += ip_nat.h ++unifdef-y += ip_nat_rule.h ++unifdef-y += ip_queue.h ++unifdef-y += ip_tables.h +diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild +index 913ddbf..9dd978d 100644 +--- a/include/linux/netfilter_ipv6/Kbuild ++++ b/include/linux/netfilter_ipv6/Kbuild +@@ -1,6 +1,21 @@ +-header-y += ip6t_HL.h ip6t_LOG.h ip6t_MARK.h ip6t_REJECT.h ip6t_ah.h \ +- ip6t_esp.h ip6t_frag.h ip6t_hl.h ip6t_ipv6header.h \ +- ip6t_length.h ip6t_limit.h ip6t_mac.h ip6t_mark.h \ +- ip6t_multiport.h ip6t_opts.h ip6t_owner.h ip6t_policy.h \ +- ip6t_physdev.h ip6t_rt.h +-unifdef-y := ip6_tables.h ++header-y += ip6t_HL.h ++header-y += ip6t_LOG.h ++header-y += ip6t_MARK.h ++header-y += ip6t_REJECT.h ++header-y += ip6t_ah.h ++header-y += ip6t_esp.h ++header-y += ip6t_frag.h ++header-y += ip6t_hl.h ++header-y += ip6t_ipv6header.h ++header-y += ip6t_length.h ++header-y += ip6t_limit.h ++header-y += ip6t_mac.h ++header-y += ip6t_mark.h ++header-y += ip6t_multiport.h ++header-y += ip6t_opts.h ++header-y += ip6t_owner.h ++header-y += ip6t_policy.h ++header-y += ip6t_physdev.h ++header-y += ip6t_rt.h ++ ++unifdef-y += ip6_tables.h +diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild +index c8c5456..d9c5455 100644 +--- a/include/linux/nfsd/Kbuild ++++ b/include/linux/nfsd/Kbuild +@@ -1,2 +1,7 @@ +-unifdef-y := const.h export.h stats.h syscall.h nfsfh.h debug.h auth.h +- ++unifdef-y += const.h ++unifdef-y += export.h ++unifdef-y += stats.h ++unifdef-y += syscall.h ++unifdef-y += nfsfh.h ++unifdef-y += debug.h ++unifdef-y += auth.h +diff --git a/include/linux/raid/Kbuild b/include/linux/raid/Kbuild +index 73fa27a..2415a64 100644 +--- a/include/linux/raid/Kbuild ++++ b/include/linux/raid/Kbuild +@@ -1 +1,2 @@ +-header-y += md_p.h md_u.h ++header-y += md_p.h ++header-y += md_u.h +diff --git a/include/linux/scx200.h b/include/linux/scx200.h +index 693c055..de466e1 100644 +--- a/include/linux/scx200.h ++++ b/include/linux/scx200.h +@@ -32,7 +32,7 @@ #define SCx200_WDT_WDSTS_WDOVF (1<<0) /* + + /* High Resolution Timer */ + #define SCx200_TIMER_OFFSET 0x08 +-#define SCx200_TIMER_SIZE 0x05 ++#define SCx200_TIMER_SIZE 0x06 + + /* Clock Generators */ + #define SCx200_CLOCKGEN_OFFSET 0x10 +diff --git a/include/linux/stddef.h b/include/linux/stddef.h +index b3a2cad..ea65dfb 100644 +--- a/include/linux/stddef.h ++++ b/include/linux/stddef.h +@@ -10,11 +10,13 @@ #else + #define NULL ((void *)0) + #endif + ++#ifdef __KERNEL__ + #undef offsetof + #ifdef __compiler_offsetof + #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER) + #else + #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + #endif ++#endif /* __KERNEL__ */ + + #endif +diff --git a/include/linux/sunrpc/Kbuild b/include/linux/sunrpc/Kbuild +index 0d1d768..fb438f1 100644 +--- a/include/linux/sunrpc/Kbuild ++++ b/include/linux/sunrpc/Kbuild +@@ -1 +1 @@ +-unifdef-y := debug.h ++unifdef-y += debug.h +diff --git a/include/linux/swap.h b/include/linux/swap.h +index 5e59184..e190cd7 100644 +--- a/include/linux/swap.h ++++ b/include/linux/swap.h +@@ -190,6 +190,7 @@ extern long vm_total_pages; + #ifdef CONFIG_NUMA + extern int zone_reclaim_mode; + extern int sysctl_min_unmapped_ratio; ++extern int sysctl_min_slab_ratio; + extern int zone_reclaim(struct zone *, gfp_t, unsigned int); + #else + #define zone_reclaim_mode 0 +diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h +index e4b1a4d..4cd330e 100644 +--- a/include/linux/sysctl.h ++++ b/include/linux/sysctl.h +@@ -191,6 +191,7 @@ enum + VM_MIN_UNMAPPED=32, /* Set min percent of unmapped pages */ + VM_PANIC_ON_OOM=33, /* panic at out-of-memory */ + VM_VDSO_ENABLED=34, /* map VDSO into new processes? */ ++ VM_MIN_SLAB=35, /* Percent pages ignored by zone reclaim */ + }; + + +diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild +index 5251a50..78dfbac 100644 +--- a/include/linux/tc_act/Kbuild ++++ b/include/linux/tc_act/Kbuild +@@ -1 +1,4 @@ +-header-y += tc_gact.h tc_ipt.h tc_mirred.h tc_pedit.h ++header-y += tc_gact.h ++header-y += tc_ipt.h ++header-y += tc_mirred.h ++header-y += tc_pedit.h +diff --git a/include/linux/tc_ematch/Kbuild b/include/linux/tc_ematch/Kbuild +index 381e930..4a58a1c 100644 +--- a/include/linux/tc_ematch/Kbuild ++++ b/include/linux/tc_ematch/Kbuild +@@ -1 +1,4 @@ +-headers-y := tc_em_cmp.h tc_em_meta.h tc_em_nbyte.h tc_em_text.h ++header-y += tc_em_cmp.h ++header-y += tc_em_meta.h ++header-y += tc_em_nbyte.h ++header-y += tc_em_text.h +diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild +index e1da2a5..13e7a3c 100644 +--- a/include/mtd/Kbuild ++++ b/include/mtd/Kbuild +@@ -1,2 +1,6 @@ +-unifdef-y := mtd-abi.h +-header-y := inftl-user.h jffs2-user.h mtd-user.h nftl-user.h ++header-y += inftl-user.h ++header-y += jffs2-user.h ++header-y += mtd-user.h ++header-y += nftl-user.h ++ ++unifdef-y += mtd-abi.h +diff --git a/include/rdma/Kbuild b/include/rdma/Kbuild +index eb710ba..e7c0432 100644 +--- a/include/rdma/Kbuild ++++ b/include/rdma/Kbuild +@@ -1 +1 @@ +-header-y := ib_user_mad.h ++header-y += ib_user_mad.h +diff --git a/include/scsi/Kbuild b/include/scsi/Kbuild +index 14a033d..744f850 100644 +--- a/include/scsi/Kbuild ++++ b/include/scsi/Kbuild +@@ -1,2 +1,4 @@ + header-y += scsi.h +-unifdef-y := scsi_ioctl.h sg.h ++ ++unifdef-y += scsi_ioctl.h ++unifdef-y += sg.h +diff --git a/include/sound/Kbuild b/include/sound/Kbuild +index 3a5a3df..fd054a3 100644 +--- a/include/sound/Kbuild ++++ b/include/sound/Kbuild +@@ -1,2 +1,10 @@ +-header-y := asound_fm.h hdsp.h hdspm.h sfnt_info.h sscape_ioctl.h +-unifdef-y := asequencer.h asound.h emu10k1.h sb16_csp.h ++header-y += asound_fm.h ++header-y += hdsp.h ++header-y += hdspm.h ++header-y += sfnt_info.h ++header-y += sscape_ioctl.h ++ ++unifdef-y += asequencer.h ++unifdef-y += asound.h ++unifdef-y += emu10k1.h ++unifdef-y += sb16_csp.h +diff --git a/include/video/Kbuild b/include/video/Kbuild +index 76a6073..a14f9c0 100644 +--- a/include/video/Kbuild ++++ b/include/video/Kbuild +@@ -1 +1 @@ +-unifdef-y := sisfb.h ++unifdef-y += sisfb.h +diff --git a/init/Kconfig b/init/Kconfig +index 9a7656f..32be672 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -1,5 +1,6 @@ + config DEFCONFIG_LIST + string ++ depends on !UML + option defconfig_list + default "/lib/modules/$UNAME_RELEASE/.config" + default "/etc/kernel-config" +diff --git a/kernel/module.c b/kernel/module.c +index 2a19cd4..b7fe6e8 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -1054,6 +1054,12 @@ static int mod_sysfs_setup(struct module + { + int err; + ++ if (!module_subsys.kset.subsys) { ++ printk(KERN_ERR "%s: module_subsys not initialized\n", ++ mod->name); ++ err = -EINVAL; ++ goto out; ++ } + memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); + err = kobject_set_name(&mod->mkobj.kobj, "%s", mod->name); + if (err) +diff --git a/kernel/sched.c b/kernel/sched.c +index a234fbe..5c848fd 100644 +--- a/kernel/sched.c ++++ b/kernel/sched.c +@@ -238,6 +238,7 @@ #ifdef CONFIG_SMP + /* For active balancing */ + int active_balance; + int push_cpu; ++ int cpu; /* cpu of this runqueue */ + + struct task_struct *migration_thread; + struct list_head migration_queue; +@@ -267,6 +268,15 @@ #endif + + static DEFINE_PER_CPU(struct rq, runqueues); + ++static inline int cpu_of(struct rq *rq) ++{ ++#ifdef CONFIG_SMP ++ return rq->cpu; ++#else ++ return 0; ++#endif ++} ++ + /* + * The domain tree (rq->sd) is protected by RCU's quiescent state transition. + * See detach_destroy_domains: synchronize_sched for details. +@@ -2211,7 +2221,8 @@ out: + */ + static struct sched_group * + find_busiest_group(struct sched_domain *sd, int this_cpu, +- unsigned long *imbalance, enum idle_type idle, int *sd_idle) ++ unsigned long *imbalance, enum idle_type idle, int *sd_idle, ++ cpumask_t *cpus) + { + struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups; + unsigned long max_load, avg_load, total_load, this_load, total_pwr; +@@ -2248,7 +2259,12 @@ #endif + sum_weighted_load = sum_nr_running = avg_load = 0; + + for_each_cpu_mask(i, group->cpumask) { +- struct rq *rq = cpu_rq(i); ++ struct rq *rq; ++ ++ if (!cpu_isset(i, *cpus)) ++ continue; ++ ++ rq = cpu_rq(i); + + if (*sd_idle && !idle_cpu(i)) + *sd_idle = 0; +@@ -2466,13 +2482,17 @@ #endif + */ + static struct rq * + find_busiest_queue(struct sched_group *group, enum idle_type idle, +- unsigned long imbalance) ++ unsigned long imbalance, cpumask_t *cpus) + { + struct rq *busiest = NULL, *rq; + unsigned long max_load = 0; + int i; + + for_each_cpu_mask(i, group->cpumask) { ++ ++ if (!cpu_isset(i, *cpus)) ++ continue; ++ + rq = cpu_rq(i); + + if (rq->nr_running == 1 && rq->raw_weighted_load > imbalance) +@@ -2511,6 +2531,7 @@ static int load_balance(int this_cpu, st + struct sched_group *group; + unsigned long imbalance; + struct rq *busiest; ++ cpumask_t cpus = CPU_MASK_ALL; + + if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER && + !sched_smt_power_savings) +@@ -2518,13 +2539,15 @@ static int load_balance(int this_cpu, st + + schedstat_inc(sd, lb_cnt[idle]); + +- group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle); ++redo: ++ group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle, ++ &cpus); + if (!group) { + schedstat_inc(sd, lb_nobusyg[idle]); + goto out_balanced; + } + +- busiest = find_busiest_queue(group, idle, imbalance); ++ busiest = find_busiest_queue(group, idle, imbalance, &cpus); + if (!busiest) { + schedstat_inc(sd, lb_nobusyq[idle]); + goto out_balanced; +@@ -2549,8 +2572,12 @@ static int load_balance(int this_cpu, st + double_rq_unlock(this_rq, busiest); + + /* All tasks on this runqueue were pinned by CPU affinity */ +- if (unlikely(all_pinned)) ++ if (unlikely(all_pinned)) { ++ cpu_clear(cpu_of(busiest), cpus); ++ if (!cpus_empty(cpus)) ++ goto redo; + goto out_balanced; ++ } + } + + if (!nr_moved) { +@@ -2639,18 +2666,22 @@ load_balance_newidle(int this_cpu, struc + unsigned long imbalance; + int nr_moved = 0; + int sd_idle = 0; ++ cpumask_t cpus = CPU_MASK_ALL; + + if (sd->flags & SD_SHARE_CPUPOWER && !sched_smt_power_savings) + sd_idle = 1; + + schedstat_inc(sd, lb_cnt[NEWLY_IDLE]); +- group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE, &sd_idle); ++redo: ++ group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE, ++ &sd_idle, &cpus); + if (!group) { + schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]); + goto out_balanced; + } + +- busiest = find_busiest_queue(group, NEWLY_IDLE, imbalance); ++ busiest = find_busiest_queue(group, NEWLY_IDLE, imbalance, ++ &cpus); + if (!busiest) { + schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]); + goto out_balanced; +@@ -2668,6 +2699,12 @@ load_balance_newidle(int this_cpu, struc + minus_1_or_zero(busiest->nr_running), + imbalance, sd, NEWLY_IDLE, NULL); + spin_unlock(&busiest->lock); ++ ++ if (!nr_moved) { ++ cpu_clear(cpu_of(busiest), cpus); ++ if (!cpus_empty(cpus)) ++ goto redo; ++ } + } + + if (!nr_moved) { +@@ -6747,6 +6784,7 @@ #ifdef CONFIG_SMP + rq->cpu_load[j] = 0; + rq->active_balance = 0; + rq->push_cpu = 0; ++ rq->cpu = i; + rq->migration_thread = NULL; + INIT_LIST_HEAD(&rq->migration_queue); + #endif +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index 362a0cc..fd43c3e 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -943,6 +943,17 @@ #ifdef CONFIG_NUMA + .extra1 = &zero, + .extra2 = &one_hundred, + }, ++ { ++ .ctl_name = VM_MIN_SLAB, ++ .procname = "min_slab_ratio", ++ .data = &sysctl_min_slab_ratio, ++ .maxlen = sizeof(sysctl_min_slab_ratio), ++ .mode = 0644, ++ .proc_handler = &sysctl_min_slab_ratio_sysctl_handler, ++ .strategy = &sysctl_intvec, ++ .extra1 = &zero, ++ .extra2 = &one_hundred, ++ }, + #endif + #ifdef CONFIG_X86_32 + { +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 54a4f53..7e92c94 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1845,8 +1845,10 @@ static inline void free_zone_pagesets(in + for_each_zone(zone) { + struct per_cpu_pageset *pset = zone_pcp(zone, cpu); + ++ /* Free per_cpu_pageset if it is slab allocated */ ++ if (pset != &boot_pageset[cpu]) ++ kfree(pset); + zone_pcp(zone, cpu) = NULL; +- kfree(pset); + } + } + +@@ -2008,6 +2010,7 @@ static void __meminit free_area_init_cor + #ifdef CONFIG_NUMA + zone->min_unmapped_ratio = (realsize*sysctl_min_unmapped_ratio) + / 100; ++ zone->min_slab_pages = (realsize * sysctl_min_slab_ratio) / 100; + #endif + zone->name = zone_names[j]; + spin_lock_init(&zone->lock); +@@ -2318,6 +2321,22 @@ int sysctl_min_unmapped_ratio_sysctl_han + sysctl_min_unmapped_ratio) / 100; + return 0; + } ++ ++int sysctl_min_slab_ratio_sysctl_handler(ctl_table *table, int write, ++ struct file *file, void __user *buffer, size_t *length, loff_t *ppos) ++{ ++ struct zone *zone; ++ int rc; ++ ++ rc = proc_dointvec_minmax(table, write, file, buffer, length, ppos); ++ if (rc) ++ return rc; ++ ++ for_each_zone(zone) ++ zone->min_slab_pages = (zone->present_pages * ++ sysctl_min_slab_ratio) / 100; ++ return 0; ++} + #endif + + /* +diff --git a/mm/truncate.c b/mm/truncate.c +index c6ab55e..91f1f47 100644 +--- a/mm/truncate.c ++++ b/mm/truncate.c +@@ -270,9 +270,39 @@ unsigned long invalidate_inode_pages(str + { + return invalidate_mapping_pages(mapping, 0, ~0UL); + } +- + EXPORT_SYMBOL(invalidate_inode_pages); + ++/* ++ * This is like invalidate_complete_page(), except it ignores the page's ++ * refcount. We do this because invalidate_inode_pages2() needs stronger ++ * invalidation guarantees, and cannot afford to leave pages behind because ++ * shrink_list() has a temp ref on them, or because they're transiently sitting ++ * in the lru_cache_add() pagevecs. ++ */ ++static int ++invalidate_complete_page2(struct address_space *mapping, struct page *page) ++{ ++ if (page->mapping != mapping) ++ return 0; ++ ++ if (PagePrivate(page) && !try_to_release_page(page, 0)) ++ return 0; ++ ++ write_lock_irq(&mapping->tree_lock); ++ if (PageDirty(page)) ++ goto failed; ++ ++ BUG_ON(PagePrivate(page)); ++ __remove_from_page_cache(page); ++ write_unlock_irq(&mapping->tree_lock); ++ ClearPageUptodate(page); ++ page_cache_release(page); /* pagecache ref */ ++ return 1; ++failed: ++ write_unlock_irq(&mapping->tree_lock); ++ return 0; ++} ++ + /** + * invalidate_inode_pages2_range - remove range of pages from an address_space + * @mapping: the address_space +@@ -339,7 +369,7 @@ int invalidate_inode_pages2_range(struct + } + } + was_dirty = test_clear_page_dirty(page); +- if (!invalidate_complete_page(mapping, page)) { ++ if (!invalidate_complete_page2(mapping, page)) { + if (was_dirty) + set_page_dirty(page); + ret = -EIO; +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 5d4c4d0..1dad4b6 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -1510,7 +1510,6 @@ #define RECLAIM_OFF 0 + #define RECLAIM_ZONE (1<<0) /* Run shrink_cache on the zone */ + #define RECLAIM_WRITE (1<<1) /* Writeout pages during reclaim */ + #define RECLAIM_SWAP (1<<2) /* Swap pages out during reclaim */ +-#define RECLAIM_SLAB (1<<3) /* Do a global slab shrink if the zone is out of memory */ + + /* + * Priority for ZONE_RECLAIM. This determines the fraction of pages +@@ -1526,6 +1525,12 @@ #define ZONE_RECLAIM_PRIORITY 4 + int sysctl_min_unmapped_ratio = 1; + + /* ++ * If the number of slab pages in a zone grows beyond this percentage then ++ * slab reclaim needs to occur. ++ */ ++int sysctl_min_slab_ratio = 5; ++ ++/* + * Try to free up some pages from this zone through reclaim. + */ + static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) +@@ -1556,29 +1561,37 @@ static int __zone_reclaim(struct zone *z + reclaim_state.reclaimed_slab = 0; + p->reclaim_state = &reclaim_state; + +- /* +- * Free memory by calling shrink zone with increasing priorities +- * until we have enough memory freed. +- */ +- priority = ZONE_RECLAIM_PRIORITY; +- do { +- nr_reclaimed += shrink_zone(priority, zone, &sc); +- priority--; +- } while (priority >= 0 && nr_reclaimed < nr_pages); ++ if (zone_page_state(zone, NR_FILE_PAGES) - ++ zone_page_state(zone, NR_FILE_MAPPED) > ++ zone->min_unmapped_ratio) { ++ /* ++ * Free memory by calling shrink zone with increasing ++ * priorities until we have enough memory freed. ++ */ ++ priority = ZONE_RECLAIM_PRIORITY; ++ do { ++ nr_reclaimed += shrink_zone(priority, zone, &sc); ++ priority--; ++ } while (priority >= 0 && nr_reclaimed < nr_pages); ++ } + +- if (nr_reclaimed < nr_pages && (zone_reclaim_mode & RECLAIM_SLAB)) { ++ if (zone_page_state(zone, NR_SLAB) > zone->min_slab_pages) { + /* + * shrink_slab() does not currently allow us to determine how +- * many pages were freed in this zone. So we just shake the slab +- * a bit and then go off node for this particular allocation +- * despite possibly having freed enough memory to allocate in +- * this zone. If we freed local memory then the next +- * allocations will be local again. ++ * many pages were freed in this zone. So we take the current ++ * number of slab pages and shake the slab until it is reduced ++ * by the same nr_pages that we used for reclaiming unmapped ++ * pages. + * +- * shrink_slab will free memory on all zones and may take +- * a long time. ++ * Note that shrink_slab will free memory on all zones and may ++ * take a long time. + */ +- shrink_slab(sc.nr_scanned, gfp_mask, order); ++ unsigned long limit = zone_page_state(zone, ++ NR_SLAB) - nr_pages; ++ ++ while (shrink_slab(sc.nr_scanned, gfp_mask, order) && ++ zone_page_state(zone, NR_SLAB) > limit) ++ ; + } + + p->reclaim_state = NULL; +@@ -1592,7 +1605,8 @@ int zone_reclaim(struct zone *zone, gfp_ + int node_id; + + /* +- * Zone reclaim reclaims unmapped file backed pages. ++ * Zone reclaim reclaims unmapped file backed pages and ++ * slab pages if we are over the defined limits. + * + * A small portion of unmapped file backed pages is needed for + * file I/O otherwise pages read by file I/O will be immediately +@@ -1601,7 +1615,9 @@ int zone_reclaim(struct zone *zone, gfp_ + * unmapped file backed pages. + */ + if (zone_page_state(zone, NR_FILE_PAGES) - +- zone_page_state(zone, NR_FILE_MAPPED) <= zone->min_unmapped_ratio) ++ zone_page_state(zone, NR_FILE_MAPPED) <= zone->min_unmapped_ratio ++ && zone_page_state(zone, NR_SLAB) ++ <= zone->min_slab_pages) + return 0; + + /* +diff --git a/net/core/dev.c b/net/core/dev.c +index d4a1ec3..a34f7c6 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1478,14 +1478,16 @@ #endif + if (q->enqueue) { + /* Grab device queue */ + spin_lock(&dev->queue_lock); ++ q = dev->qdisc; ++ if (q->enqueue) { ++ rc = q->enqueue(skb, q); ++ qdisc_run(dev); ++ spin_unlock(&dev->queue_lock); + +- rc = q->enqueue(skb, q); +- +- qdisc_run(dev); +- ++ rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc; ++ goto out; ++ } + spin_unlock(&dev->queue_lock); +- rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc; +- goto out; + } + + /* The device has no queue. Common case for software devices: +diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c +index 17de077..6db485f 100644 +--- a/net/ipv4/netfilter/ip_nat_standalone.c ++++ b/net/ipv4/netfilter/ip_nat_standalone.c +@@ -110,12 +110,17 @@ ip_nat_fn(unsigned int hooknum, + IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off + & htons(IP_MF|IP_OFFSET))); + ++ ct = ip_conntrack_get(*pskb, &ctinfo); ++ ++ /* Don't try to NAT if this packet is not conntracked */ ++ if (ct == &ip_conntrack_untracked) ++ return NF_ACCEPT; ++ + /* If we had a hardware checksum before, it's now invalid */ + if ((*pskb)->ip_summed == CHECKSUM_HW) + if (skb_checksum_help(*pskb, (out == NULL))) + return NF_DROP; + +- ct = ip_conntrack_get(*pskb, &ctinfo); + /* Can't track? It's not due to stress, or conntrack would + have dropped it. Hence it's the user's responsibilty to + packet filter it out, or implement conntrack/NAT for that +@@ -137,10 +142,6 @@ ip_nat_fn(unsigned int hooknum, + return NF_ACCEPT; + } + +- /* Don't try to NAT if this packet is not conntracked */ +- if (ct == &ip_conntrack_untracked) +- return NF_ACCEPT; +- + switch (ctinfo) { + case IP_CT_RELATED: + case IP_CT_RELATED+IP_CT_IS_REPLY: +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 159fa3f..020f3e1 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -2237,13 +2237,12 @@ static int tcp_tso_acked(struct sock *sk + return acked; + } + +-static u32 tcp_usrtt(const struct sk_buff *skb) ++static u32 tcp_usrtt(struct timeval *tv) + { +- struct timeval tv, now; ++ struct timeval now; + + do_gettimeofday(&now); +- skb_get_timestamp(skb, &tv); +- return (now.tv_sec - tv.tv_sec) * 1000000 + (now.tv_usec - tv.tv_usec); ++ return (now.tv_sec - tv->tv_sec) * 1000000 + (now.tv_usec - tv->tv_usec); + } + + /* Remove acknowledged frames from the retransmission queue. */ +@@ -2258,6 +2257,7 @@ static int tcp_clean_rtx_queue(struct so + u32 pkts_acked = 0; + void (*rtt_sample)(struct sock *sk, u32 usrtt) + = icsk->icsk_ca_ops->rtt_sample; ++ struct timeval tv; + + while ((skb = skb_peek(&sk->sk_write_queue)) && + skb != sk->sk_send_head) { +@@ -2306,8 +2306,7 @@ static int tcp_clean_rtx_queue(struct so + seq_rtt = -1; + } else if (seq_rtt < 0) { + seq_rtt = now - scb->when; +- if (rtt_sample) +- (*rtt_sample)(sk, tcp_usrtt(skb)); ++ skb_get_timestamp(skb, &tv); + } + if (sacked & TCPCB_SACKED_ACKED) + tp->sacked_out -= tcp_skb_pcount(skb); +@@ -2320,8 +2319,7 @@ static int tcp_clean_rtx_queue(struct so + } + } else if (seq_rtt < 0) { + seq_rtt = now - scb->when; +- if (rtt_sample) +- (*rtt_sample)(sk, tcp_usrtt(skb)); ++ skb_get_timestamp(skb, &tv); + } + tcp_dec_pcount_approx(&tp->fackets_out, skb); + tcp_packets_out_dec(tp, skb); +@@ -2333,6 +2331,8 @@ static int tcp_clean_rtx_queue(struct so + if (acked&FLAG_ACKED) { + tcp_ack_update_rtt(sk, acked, seq_rtt); + tcp_ack_packets_out(sk, tp); ++ if (rtt_sample && !(acked & FLAG_RETRANS_DATA_ACKED)) ++ (*rtt_sample)(sk, tcp_usrtt(&tv)); + + if (icsk->icsk_ca_ops->pkts_acked) + icsk->icsk_ca_ops->pkts_acked(sk, pkts_acked); +diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c +index a5eaaf6..1c50e6a 100644 +--- a/net/ipv6/ipv6_sockglue.c ++++ b/net/ipv6/ipv6_sockglue.c +@@ -123,6 +123,9 @@ static struct sk_buff *ipv6_gso_segment( + struct ipv6hdr *ipv6h; + struct inet6_protocol *ops; + ++ if (!(features & NETIF_F_HW_CSUM)) ++ features &= ~NETIF_F_SG; ++ + if (unlikely(skb_shinfo(skb)->gso_type & + ~(SKB_GSO_UDP | + SKB_GSO_DODGY | +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 802a1a6..72c074c 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1228,7 +1228,7 @@ process: + + skb->dev = NULL; + +- bh_lock_sock(sk); ++ bh_lock_sock_nested(sk); + ret = 0; + if (!sock_owned_by_user(sk)) { + #ifdef CONFIG_NET_DMA +diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c +index 7e14f14..37a1840 100644 +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -401,7 +401,7 @@ static int tc_dump_tfilter(struct sk_buf + if ((dev = dev_get_by_index(tcm->tcm_ifindex)) == NULL) + return skb->len; + +- read_lock_bh(&qdisc_tree_lock); ++ read_lock(&qdisc_tree_lock); + if (!tcm->tcm_parent) + q = dev->qdisc_sleeping; + else +@@ -458,7 +458,7 @@ errout: + if (cl) + cops->put(q, cl); + out: +- read_unlock_bh(&qdisc_tree_lock); ++ read_unlock(&qdisc_tree_lock); + dev_put(dev); + return skb->len; + } +diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c +index 86cac49..09fda68 100644 +--- a/net/sched/cls_basic.c ++++ b/net/sched/cls_basic.c +@@ -194,7 +194,7 @@ static int basic_change(struct tcf_proto + if (handle) + f->handle = handle; + else { +- int i = 0x80000000; ++ unsigned int i = 0x80000000; + do { + if (++head->hgenerator == 0x7FFFFFFF) + head->hgenerator = 1; +diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c +index a19eff1..0b64892 100644 +--- a/net/sched/sch_api.c ++++ b/net/sched/sch_api.c +@@ -195,14 +195,14 @@ struct Qdisc *qdisc_lookup(struct net_de + { + struct Qdisc *q; + +- read_lock_bh(&qdisc_tree_lock); ++ read_lock(&qdisc_tree_lock); + list_for_each_entry(q, &dev->qdisc_list, list) { + if (q->handle == handle) { +- read_unlock_bh(&qdisc_tree_lock); ++ read_unlock(&qdisc_tree_lock); + return q; + } + } +- read_unlock_bh(&qdisc_tree_lock); ++ read_unlock(&qdisc_tree_lock); + return NULL; + } + +@@ -837,7 +837,7 @@ static int tc_dump_qdisc(struct sk_buff + continue; + if (idx > s_idx) + s_q_idx = 0; +- read_lock_bh(&qdisc_tree_lock); ++ read_lock(&qdisc_tree_lock); + q_idx = 0; + list_for_each_entry(q, &dev->qdisc_list, list) { + if (q_idx < s_q_idx) { +@@ -846,12 +846,12 @@ static int tc_dump_qdisc(struct sk_buff + } + if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) { +- read_unlock_bh(&qdisc_tree_lock); ++ read_unlock(&qdisc_tree_lock); + goto done; + } + q_idx++; + } +- read_unlock_bh(&qdisc_tree_lock); ++ read_unlock(&qdisc_tree_lock); + } + + done: +@@ -1074,7 +1074,7 @@ static int tc_dump_tclass(struct sk_buff + s_t = cb->args[0]; + t = 0; + +- read_lock_bh(&qdisc_tree_lock); ++ read_lock(&qdisc_tree_lock); + list_for_each_entry(q, &dev->qdisc_list, list) { + if (t < s_t || !q->ops->cl_ops || + (tcm->tcm_parent && +@@ -1096,7 +1096,7 @@ static int tc_dump_tclass(struct sk_buff + break; + t++; + } +- read_unlock_bh(&qdisc_tree_lock); ++ read_unlock(&qdisc_tree_lock); + + cb->args[0] = t; + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 6f91518..88c6a99 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -45,11 +45,10 @@ #include + The idea is the following: + - enqueue, dequeue are serialized via top level device + spinlock dev->queue_lock. +- - tree walking is protected by read_lock_bh(qdisc_tree_lock) ++ - tree walking is protected by read_lock(qdisc_tree_lock) + and this lock is used only in process context. +- - updates to tree are made under rtnl semaphore or +- from softirq context (__qdisc_destroy rcu-callback) +- hence this lock needs local bh disabling. ++ - updates to tree are made only under rtnl semaphore, ++ hence this lock may be made without local bh disabling. + + qdisc_tree_lock must be grabbed BEFORE dev->queue_lock! + */ +@@ -57,14 +56,14 @@ DEFINE_RWLOCK(qdisc_tree_lock); + + void qdisc_lock_tree(struct net_device *dev) + { +- write_lock_bh(&qdisc_tree_lock); ++ write_lock(&qdisc_tree_lock); + spin_lock_bh(&dev->queue_lock); + } + + void qdisc_unlock_tree(struct net_device *dev) + { + spin_unlock_bh(&dev->queue_lock); +- write_unlock_bh(&qdisc_tree_lock); ++ write_unlock(&qdisc_tree_lock); + } + + /* +@@ -483,20 +482,6 @@ void qdisc_reset(struct Qdisc *qdisc) + static void __qdisc_destroy(struct rcu_head *head) + { + struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu); +- struct Qdisc_ops *ops = qdisc->ops; +- +-#ifdef CONFIG_NET_ESTIMATOR +- gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est); +-#endif +- write_lock(&qdisc_tree_lock); +- if (ops->reset) +- ops->reset(qdisc); +- if (ops->destroy) +- ops->destroy(qdisc); +- write_unlock(&qdisc_tree_lock); +- module_put(ops->owner); +- +- dev_put(qdisc->dev); + kfree((char *) qdisc - qdisc->padded); + } + +@@ -504,32 +489,23 @@ #endif + + void qdisc_destroy(struct Qdisc *qdisc) + { +- struct list_head cql = LIST_HEAD_INIT(cql); +- struct Qdisc *cq, *q, *n; ++ struct Qdisc_ops *ops = qdisc->ops; + + if (qdisc->flags & TCQ_F_BUILTIN || +- !atomic_dec_and_test(&qdisc->refcnt)) ++ !atomic_dec_and_test(&qdisc->refcnt)) + return; + +- if (!list_empty(&qdisc->list)) { +- if (qdisc->ops->cl_ops == NULL) +- list_del(&qdisc->list); +- else +- list_move(&qdisc->list, &cql); +- } +- +- /* unlink inner qdiscs from dev->qdisc_list immediately */ +- list_for_each_entry(cq, &cql, list) +- list_for_each_entry_safe(q, n, &qdisc->dev->qdisc_list, list) +- if (TC_H_MAJ(q->parent) == TC_H_MAJ(cq->handle)) { +- if (q->ops->cl_ops == NULL) +- list_del_init(&q->list); +- else +- list_move_tail(&q->list, &cql); +- } +- list_for_each_entry_safe(cq, n, &cql, list) +- list_del_init(&cq->list); ++ list_del(&qdisc->list); ++#ifdef CONFIG_NET_ESTIMATOR ++ gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est); ++#endif ++ if (ops->reset) ++ ops->reset(qdisc); ++ if (ops->destroy) ++ ops->destroy(qdisc); + ++ module_put(ops->owner); ++ dev_put(qdisc->dev); + call_rcu(&qdisc->q_rcu, __qdisc_destroy); + } + +@@ -549,15 +525,15 @@ void dev_activate(struct net_device *dev + printk(KERN_INFO "%s: activation failed\n", dev->name); + return; + } +- write_lock_bh(&qdisc_tree_lock); ++ write_lock(&qdisc_tree_lock); + list_add_tail(&qdisc->list, &dev->qdisc_list); +- write_unlock_bh(&qdisc_tree_lock); ++ write_unlock(&qdisc_tree_lock); + } else { + qdisc = &noqueue_qdisc; + } +- write_lock_bh(&qdisc_tree_lock); ++ write_lock(&qdisc_tree_lock); + dev->qdisc_sleeping = qdisc; +- write_unlock_bh(&qdisc_tree_lock); ++ write_unlock(&qdisc_tree_lock); + } + + if (!netif_carrier_ok(dev)) +diff --git a/sound/core/control.c b/sound/core/control.c +index bb397ea..ac890d9 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -997,6 +997,7 @@ static int snd_ctl_elem_add(struct snd_c + if (ue == NULL) + return -ENOMEM; + ue->info = *info; ++ ue->info.access = 0; + ue->elem_data = (char *)ue + sizeof(*ue); + ue->elem_data_size = private_size; + kctl.private_free = snd_ctl_elem_user_free; diff --git a/debian/patches/series/3 b/debian/patches/series/3 index 4e5b56316..45abfe546 100644 --- a/debian/patches/series/3 +++ b/debian/patches/series/3 @@ -15,3 +15,5 @@ + features/all/drivers/cciss-support-for-gt-2TB-volumes.patch + bugfix/ia64/sal-flush-fix.patch + bugfix/sym2-dont-claim-raid-devs.patch +- bugfix/proc-fb-reading.patch ++ bugfix/2.6.18.1