Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: Bug#588196: b43: does not join multicast groups
From: Ben Hutchings @ 2010-07-11 22:25 UTC (permalink / raw)
  To: Michael Buesch, Stefano Brivio, linux-wireless; +Cc: Simon Richter, 588196
In-Reply-To: <20100706021937.11147.78230.reportbug@debian.hogyros.de>

[-- Attachment #1: Type: text/plain, Size: 79686 bytes --]

On Tue, 2010-07-06 at 04:19 +0200, Simon Richter wrote:
> Package: linux-2.6
> Version: 2.6.34-1~experimental.1
> Severity: normal
> 
> Hi,
> 
> I'm using a B43 based SSB card with LP-PHY, and find myself unable to
> join an IPv6 network as router advertisements are never seen on my
> system. ping6 using link-local addresses works fine.
> 
> The issue persists even if I enable promiscuous mode.

I don't see any changes after 2.6.34 that might address this; therefore
I'm forwarding this upstream.

Ben.

>    Simon
> 
> -- Package-specific info:
> ** Version:
> Linux version 2.6.34-1-686 (Debian 2.6.34-1~experimental.1) (maks@debian.org) (gcc version 4.3.4 (Debian 4.3.4-10) ) #1 SMP Thu May 20 12:14:21 UTC 2010
> 
> ** Command line:
> root=UUID=67d4bec9-8770-46d3-b483-a53af24245f9 ro quiet
> 
> ** Not tainted
> 
> ** Kernel log:
> [    0.000000] Initializing cgroup subsys cpuset
> [    0.000000] Initializing cgroup subsys cpu
> [    0.000000] Linux version 2.6.34-1-686 (Debian 2.6.34-1~experimental.1) (maks@debian.org) (gcc version 4.3.4 (Debian 4.3.4-10) ) #1 SMP Thu May 20 12:14:21 UTC 2010
> [    0.000000] Atom PSE erratum detected, BIOS microcode update recommended
> [    0.000000] BIOS-provided physical RAM map:
> [    0.000000]  BIOS-e820: 0000000000000000 - 000000000009f800 (usable)
> [    0.000000]  BIOS-e820: 000000000009f800 - 00000000000a0000 (reserved)
> [    0.000000]  BIOS-e820: 00000000000e0000 - 0000000000100000 (reserved)
> [    0.000000]  BIOS-e820: 0000000000100000 - 000000003f6d0000 (usable)
> [    0.000000]  BIOS-e820: 000000003f6d0000 - 000000003f6e2000 (ACPI data)
> [    0.000000]  BIOS-e820: 000000003f6e2000 - 000000003f6e3000 (ACPI NVS)
> [    0.000000]  BIOS-e820: 000000003f6e3000 - 0000000040000000 (reserved)
> [    0.000000]  BIOS-e820: 00000000e0000000 - 00000000f0000000 (reserved)
> [    0.000000]  BIOS-e820: 00000000fec00000 - 00000000fec10000 (reserved)
> [    0.000000]  BIOS-e820: 00000000fed00000 - 00000000fed00400 (reserved)
> [    0.000000]  BIOS-e820: 00000000fed14000 - 00000000fed1a000 (reserved)
> [    0.000000]  BIOS-e820: 00000000fed1c000 - 00000000fed90000 (reserved)
> [    0.000000]  BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved)
> [    0.000000]  BIOS-e820: 00000000ff000000 - 0000000100000000 (reserved)
> [    0.000000] Notice: NX (Execute Disable) protection cannot be enabled: non-PAE kernel!
> [    0.000000] DMI present.
> [    0.000000] e820 update range: 0000000000000000 - 0000000000001000 (usable) ==> (reserved)
> [    0.000000] e820 remove range: 00000000000a0000 - 0000000000100000 (usable)
> [    0.000000] last_pfn = 0x3f6d0 max_arch_pfn = 0x100000
> [    0.000000] MTRR default type: uncachable
> [    0.000000] MTRR fixed ranges enabled:
> [    0.000000]   00000-9FFFF write-back
> [    0.000000]   A0000-BFFFF uncachable
> [    0.000000]   C0000-CFFFF write-protect
> [    0.000000]   D0000-DFFFF uncachable
> [    0.000000]   E0000-FFFFF write-protect
> [    0.000000] MTRR variable ranges enabled:
> [    0.000000]   0 base 000000000 mask 0C0000000 write-back
> [    0.000000]   1 base 03F700000 mask 0FFF00000 uncachable
> [    0.000000]   2 base 03F800000 mask 0FF800000 uncachable
> [    0.000000]   3 disabled
> [    0.000000]   4 disabled
> [    0.000000]   5 disabled
> [    0.000000]   6 disabled
> [    0.000000]   7 disabled
> [    0.000000] x86 PAT enabled: cpu 0, old 0x7040600070406, new 0x7010600070106
> [    0.000000] initial memory mapped : 0 - 01800000
> [    0.000000] found SMP MP-table at [c00f7fa0] f7fa0
> [    0.000000] init_memory_mapping: 0000000000000000-00000000377fe000
> [    0.000000]  0000000000 - 00377fe000 page 4k
> [    0.000000] kernel direct mapping tables up to 377fe000 @ 100000-1e1000
> [    0.000000] RAMDISK: 37903000 - 37ff0000
> [    0.000000] Allocated new RAMDISK: 001d8000 - 008c4269
> [    0.000000] Move RAMDISK from 0000000037903000 - 0000000037fef268 to 001d8000 - 008c4268
> [    0.000000] ACPI: RSDP 000f7f70 00024 (v02 PTLTD )
> [    0.000000] ACPI: XSDT 3f6dc066 0006C (v01 PTLTD  ? XSDT   06040000  LTP 00000000)
> [    0.000000] ACPI: FACP 3f6e1d48 000F4 (v03 INTEL  CALISTGA 06040000 ALAN 00000001)
> [    0.000000] ACPI: DSDT 3f6dcf4b 04D89 (v01 INTEL  CALISTGA 06040000 INTL 20050624)
> [    0.000000] ACPI: FACS 3f6e2fc0 00040
> [    0.000000] ACPI: APIC 3f6e1e3c 00068 (v01 INTEL  CALISTGA 06040000 LOHR 0000005A)
> [    0.000000] ACPI: HPET 3f6e1ea4 00038 (v01 INTEL  CALISTGA 06040000 LOHR 0000005A)
> [    0.000000] ACPI: MCFG 3f6e1edc 0003C (v01 INTEL  CALISTGA 06040000 LOHR 0000005A)
> [    0.000000] ACPI: TCPA 3f6e1f18 00032 (v01 PTLTD  CALISTGA 06040000  PTL 00000001)
> [    0.000000] ACPI: TMOR 3f6e1f4a 00026 (v01 PTLTD           06040000 PTL  00000003)
> [    0.000000] ACPI: APIC 3f6e1f70 00068 (v01 PTLTD  ? APIC   06040000  LTP 00000000)
> [    0.000000] ACPI: BOOT 3f6e1fd8 00028 (v01 PTLTD  $SBFTBL$ 06040000  LTP 00000001)
> [    0.000000] ACPI: SSDT 3f6dc0d2 004F6 (v02  PmRef    CpuPm 00003000 INTL 20050624)
> [    0.000000] ACPI: BIOS bug: multiple APIC/MADT found, using 0
> [    0.000000] ACPI: If "acpi_apic_instance=2" works better, notify linux-acpi@vger.kernel.org
> [    0.000000] ACPI: Local APIC address 0xfee00000
> [    0.000000] 126MB HIGHMEM available.
> [    0.000000] 887MB LOWMEM available.
> [    0.000000]   mapped low ram: 0 - 377fe000
> [    0.000000]   low ram: 0 - 377fe000
> [    0.000000]   node 0 low ram: 00000000 - 377fe000
> [    0.000000]   node 0 bootmap 00007000 - 0000df00
> [    0.000000] (13/32 early reservations) ==> bootmem [0000000000 - 00377fe000]
> [    0.000000]   #0 [0000001000 - 0000002000]    EX TRAMPOLINE ==> [0000001000 - 0000002000]
> [    0.000000]   #1 [0001000000 - 00014cf9c4]    TEXT DATA BSS ==> [0001000000 - 00014cf9c4]
> [    0.000000]   #2 [00014d0000 - 00014d6124]              BRK ==> [00014d0000 - 00014d6124]
> [    0.000000]   #3 [00000f7fb0 - 0000100000]    BIOS reserved ==> [00000f7fb0 - 0000100000]
> [    0.000000]   #4 [00000f7fa0 - 00000f7fb0]     MP-table mpf ==> [00000f7fa0 - 00000f7fb0]
> [    0.000000]   #5 [000009f800 - 000009fc71]    BIOS reserved ==> [000009f800 - 000009fc71]
> [    0.000000]   #6 [000009fdd1 - 00000f7fa0]    BIOS reserved ==> [000009fdd1 - 00000f7fa0]
> [    0.000000]   #7 [000009fc71 - 000009fdd1]     MP-table mpc ==> [000009fc71 - 000009fdd1]
> [    0.000000]   #8 [0000002000 - 0000003000]       TRAMPOLINE ==> [0000002000 - 0000003000]
> [    0.000000]   #9 [0000003000 - 0000007000]      ACPI WAKEUP ==> [0000003000 - 0000007000]
> [    0.000000]   #10 [0000100000 - 00001d8000]          PGTABLE ==> [0000100000 - 00001d8000]
> [    0.000000]   #11 [00001d8000 - 00008c5000]      NEW RAMDISK ==> [00001d8000 - 00008c5000]
> [    0.000000]   #12 [0000007000 - 000000e000]          BOOTMAP ==> [0000007000 - 000000e000]
> [    0.000000] Zone PFN ranges:
> [    0.000000]   DMA      0x00000001 -> 0x00001000
> [    0.000000]   Normal   0x00001000 -> 0x000377fe
> [    0.000000]   HighMem  0x000377fe -> 0x0003f6d0
> [    0.000000] Movable zone start PFN for each node
> [    0.000000] early_node_map[2] active PFN ranges
> [    0.000000]     0: 0x00000001 -> 0x0000009f
> [    0.000000]     0: 0x00000100 -> 0x0003f6d0
> [    0.000000] On node 0 totalpages: 259694
> [    0.000000] free_area_init_node: node 0, pgdat c13b3fc0, node_mem_map c14d8020
> [    0.000000]   DMA zone: 32 pages used for memmap
> [    0.000000]   DMA zone: 0 pages reserved
> [    0.000000]   DMA zone: 3966 pages, LIFO batch:0
> [    0.000000]   Normal zone: 1744 pages used for memmap
> [    0.000000]   Normal zone: 221486 pages, LIFO batch:31
> [    0.000000]   HighMem zone: 254 pages used for memmap
> [    0.000000]   HighMem zone: 32212 pages, LIFO batch:7
> [    0.000000] Using APIC driver default
> [    0.000000] ACPI: PM-Timer IO Port: 0x1008
> [    0.000000] ACPI: Local APIC address 0xfee00000
> [    0.000000] ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
> [    0.000000] ACPI: LAPIC (acpi_id[0x01] lapic_id[0x01] enabled)
> [    0.000000] ACPI: LAPIC_NMI (acpi_id[0x00] high edge lint[0x1])
> [    0.000000] ACPI: LAPIC_NMI (acpi_id[0x01] high edge lint[0x1])
> [    0.000000] ACPI: IOAPIC (id[0x01] address[0xfec00000] gsi_base[0])
> [    0.000000] IOAPIC[0]: apic_id 1, version 32, address 0xfec00000, GSI 0-23
> [    0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
> [    0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
> [    0.000000] ACPI: IRQ0 used by override.
> [    0.000000] ACPI: IRQ2 used by override.
> [    0.000000] ACPI: IRQ9 used by override.
> [    0.000000] Using ACPI (MADT) for SMP configuration information
> [    0.000000] ACPI: HPET id: 0x8086a201 base: 0xfed00000
> [    0.000000] SMP: Allowing 2 CPUs, 0 hotplug CPUs
> [    0.000000] nr_irqs_gsi: 24
> [    0.000000] PM: Registered nosave memory: 000000000009f000 - 00000000000a0000
> [    0.000000] PM: Registered nosave memory: 00000000000a0000 - 00000000000e0000
> [    0.000000] PM: Registered nosave memory: 00000000000e0000 - 0000000000100000
> [    0.000000] Allocating PCI resources starting at 40000000 (gap: 40000000:a0000000)
> [    0.000000] Booting paravirtualized kernel on bare hardware
> [    0.000000] setup_percpu: NR_CPUS:32 nr_cpumask_bits:32 nr_cpu_ids:2 nr_node_ids:1
> [    0.000000] PERCPU: Embedded 14 pages/cpu @c1cce000 s33940 r0 d23404 u65536
> [    0.000000] pcpu-alloc: s33940 r0 d23404 u65536 alloc=16*4096
> [    0.000000] pcpu-alloc: [0] 0 [0] 1 
> [    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 257664
> [    0.000000] Kernel command line: root=UUID=67d4bec9-8770-46d3-b483-a53af24245f9 ro quiet
> [    0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
> [    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
> [    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
> [    0.000000] Enabling fast FPU save and restore... done.
> [    0.000000] Enabling unmasked SIMD FPU exception support... done.
> [    0.000000] Initializing CPU#0
> [    0.000000] Initializing HighMem for node 0 (000377fe:0003f6d0)
> [    0.000000] Memory: 1016784k/1039168k available (2523k kernel code, 21992k reserved, 1301k data, 380k init, 129864k highmem)
> [    0.000000] virtual kernel memory layout:
> [    0.000000]     fixmap  : 0xffd56000 - 0xfffff000   (2724 kB)
> [    0.000000]     pkmap   : 0xff800000 - 0xffc00000   (4096 kB)
> [    0.000000]     vmalloc : 0xf7ffe000 - 0xff7fe000   ( 120 MB)
> [    0.000000]     lowmem  : 0xc0000000 - 0xf77fe000   ( 887 MB)
> [    0.000000]       .init : 0xc13bd000 - 0xc141c000   ( 380 kB)
> [    0.000000]       .data : 0xc1276d83 - 0xc13bc400   (1301 kB)
> [    0.000000]       .text : 0xc1000000 - 0xc1276d83   (2523 kB)
> [    0.000000] Checking if this processor honours the WP bit even in supervisor mode...Ok.
> [    0.000000] SLUB: Genslabs=13, HWalign=64, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
> [    0.000000] Hierarchical RCU implementation.
> [    0.000000] NR_IRQS:1280
> [    0.000000] Extended CMOS year: 2000
> [    0.000000] Console: colour VGA+ 80x25
> [    0.000000] console [tty0] enabled
> [    0.000000] hpet clockevent registered
> [    0.000000] Fast TSC calibration using PIT
> [    0.000000] Detected 1596.130 MHz processor.
> [    0.004009] Calibrating delay loop (skipped), value calculated using timer frequency.. 3192.26 BogoMIPS (lpj=6384520)
> [    0.004059] Security Framework initialized
> [    0.004067] SELinux:  Disabled at boot.
> [    0.004083] Mount-cache hash table entries: 512
> [    0.004318] Initializing cgroup subsys ns
> [    0.004327] Initializing cgroup subsys cpuacct
> [    0.004336] Initializing cgroup subsys devices
> [    0.004342] Initializing cgroup subsys freezer
> [    0.004347] Initializing cgroup subsys net_cls
> [    0.004383] Atom PSE erratum detected, BIOS microcode update recommended
> [    0.004392] CPU: Physical Processor ID: 0
> [    0.004396] CPU: Processor Core ID: 0
> [    0.004402] mce: CPU supports 5 MCE banks
> [    0.004415] CPU0: Thermal monitoring enabled (TM1)
> [    0.004422] using mwait in idle threads.
> [    0.004435] Performance Events: Atom events, Intel PMU driver.
> [    0.004448] ... version:                3
> [    0.004452] ... bit width:              40
> [    0.004455] ... generic registers:      2
> [    0.004460] ... value mask:             000000ffffffffff
> [    0.004464] ... max period:             000000007fffffff
> [    0.004468] ... fixed-purpose events:   3
> [    0.004472] ... event mask:             0000000700000003
> [    0.008014] Checking 'hlt' instruction... OK.
> [    0.025383] ACPI: Core revision 20100121
> [    0.040096] Enabling APIC mode:  Flat.  Using 1 I/O APICs
> [    0.040574] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
> [    0.082098] CPU0: Intel(R) Atom(TM) CPU N270   @ 1.60GHz stepping 02
> [    0.084000] Booting Node   0, Processors  #1 Ok.
> [    0.008000] Initializing CPU#1
> [    0.008000] Atom PSE erratum detected, BIOS microcode update recommended
> [    0.172028] Brought up 2 CPUs
> [    0.172037] Total of 2 processors activated (6384.20 BogoMIPS).
> [    0.172587] devtmpfs: initialized
> [    0.173213] regulator: core version 0.5
> [    0.173297] NET: Registered protocol family 16
> [    0.173506] ACPI: bus type pci registered
> [    0.173647] PCI: MMCONFIG for domain 0000 [bus 00-ff] at [mem 0xe0000000-0xefffffff] (base 0xe0000000)
> [    0.173656] PCI: MMCONFIG at [mem 0xe0000000-0xefffffff] reserved in E820
> [    0.173661] PCI: Using MMCONFIG for extended config space
> [    0.173665] PCI: Using configuration type 1 for base access
> [    0.174457] bio: create slab <bio-0> at 0
> [    0.176878] ACPI: EC: Look up EC in DSDT
> [    0.181062] ACPI: BIOS _OSI(Linux) query ignored
> [    0.183250] ACPI: SSDT 3f6dcc32 00245 (v02  PmRef  Cpu0Ist 00003000 INTL 20050624)
> [    0.184303] ACPI: SSDT 3f6dc5c8 005E5 (v02  PmRef  Cpu0Cst 00003001 INTL 20050624)
> [    0.185530] ACPI: SSDT 3f6dce77 000D4 (v02  PmRef  Cpu1Ist 00003000 INTL 20050624)
> [    0.186276] ACPI: SSDT 3f6dcbad 00085 (v02  PmRef  Cpu1Cst 00003000 INTL 20050624)
> [    0.240069] ACPI: Interpreter enabled
> [    0.240085] ACPI: (supports S0 S3 S4 S5)
> [    0.240136] ACPI: Using IOAPIC for interrupt routing
> [    0.289266] ACPI: EC: GPE = 0x19, I/O: command/status = 0x66, data = 0x62
> [    0.289714] ACPI: No dock devices found.
> [    0.289722] PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug
> [    0.290670] ACPI: PCI Root Bridge [PCI0] (0000:00)
> [    0.292534] pci_root PNP0A08:00: host bridge window [io  0x0000-0x0cf7]
> [    0.292542] pci_root PNP0A08:00: host bridge window [io  0x0d00-0xffff]
> [    0.292549] pci_root PNP0A08:00: host bridge window [mem 0x000a0000-0x000bffff]
> [    0.292556] pci_root PNP0A08:00: host bridge window [mem 0x000d0000-0x000d3fff]
> [    0.292562] pci_root PNP0A08:00: host bridge window [mem 0x000d4000-0x000d7fff]
> [    0.292569] pci_root PNP0A08:00: host bridge window [mem 0x000d8000-0x000dbfff]
> [    0.292575] pci_root PNP0A08:00: host bridge window [mem 0x000dc000-0x000dffff]
> [    0.292582] pci_root PNP0A08:00: host bridge window [mem 0x40000000-0xfebfffff]
> [    0.292672] pci 0000:00:02.0: reg 10: [mem 0xf0000000-0xf007ffff]
> [    0.292681] pci 0000:00:02.0: reg 14: [io  0x1800-0x1807]
> [    0.292690] pci 0000:00:02.0: reg 18: [mem 0xd0000000-0xdfffffff pref]
> [    0.292699] pci 0000:00:02.0: reg 1c: [mem 0xf0300000-0xf033ffff]
> [    0.292749] pci 0000:00:02.1: reg 10: [mem 0xf0080000-0xf00fffff]
> [    0.292879] pci 0000:00:1b.0: reg 10: [mem 0xf0540000-0xf0543fff 64bit]
> [    0.292956] pci 0000:00:1b.0: PME# supported from D0 D3hot D3cold
> [    0.292965] pci 0000:00:1b.0: PME# disabled
> [    0.293090] pci 0000:00:1c.0: PME# supported from D0 D3hot D3cold
> [    0.293098] pci 0000:00:1c.0: PME# disabled
> [    0.293223] pci 0000:00:1c.1: PME# supported from D0 D3hot D3cold
> [    0.293231] pci 0000:00:1c.1: PME# disabled
> [    0.293356] pci 0000:00:1c.2: PME# supported from D0 D3hot D3cold
> [    0.293364] pci 0000:00:1c.2: PME# disabled
> [    0.293450] pci 0000:00:1d.0: reg 20: [io  0x1820-0x183f]
> [    0.293533] pci 0000:00:1d.1: reg 20: [io  0x1840-0x185f]
> [    0.293617] pci 0000:00:1d.2: reg 20: [io  0x1860-0x187f]
> [    0.293700] pci 0000:00:1d.3: reg 20: [io  0x1880-0x189f]
> [    0.293779] pci 0000:00:1d.7: reg 10: [mem 0xf0544000-0xf05443ff]
> [    0.293858] pci 0000:00:1d.7: PME# supported from D0 D3hot D3cold
> [    0.293866] pci 0000:00:1d.7: PME# disabled
> [    0.294058] pci 0000:00:1f.0: quirk: [io  0x1000-0x107f] claimed by ICH6 ACPI/GPIO/TCO
> [    0.294067] pci 0000:00:1f.0: quirk: [io  0x1180-0x11bf] claimed by ICH6 GPIO
> [    0.294076] pci 0000:00:1f.0: ICH7 LPC Generic IO decode 1 PIO at 0680 (mask 007f)
> [    0.294084] pci 0000:00:1f.0: ICH7 LPC Generic IO decode 2 PIO at ff2c (mask 007f)
> [    0.294094] pci 0000:00:1f.0: ICH7 LPC Generic IO decode 4 PIO at 0068 (mask 0007)
> [    0.294157] pci 0000:00:1f.1: reg 10: [io  0x0000-0x0007]
> [    0.294170] pci 0000:00:1f.1: reg 14: [io  0x0000-0x0003]
> [    0.294182] pci 0000:00:1f.1: reg 18: [io  0x0000-0x0007]
> [    0.294195] pci 0000:00:1f.1: reg 1c: [io  0x0000-0x0003]
> [    0.294207] pci 0000:00:1f.1: reg 20: [io  0x1810-0x181f]
> [    0.294306] pci 0000:00:1f.3: reg 20: [io  0x18a0-0x18bf]
> [    0.294477] pci 0000:02:00.0: reg 10: [mem 0xf0100000-0xf01000ff]
> [    0.294562] pci 0000:02:00.0: reg 30: [mem 0x00000000-0x0000ffff pref]
> [    0.294727] pci 0000:02:00.2: reg 10: [mem 0xf0100400-0xf01004ff]
> [    0.294963] pci 0000:02:00.3: reg 10: [mem 0xf0100800-0xf01008ff]
> [    0.300066] pci 0000:00:1c.0: PCI bridge to [bus 02-02]
> [    0.300076] pci 0000:00:1c.0:   bridge window [io  0xf000-0x0000] (disabled)
> [    0.300085] pci 0000:00:1c.0:   bridge window [mem 0xf0100000-0xf01fffff]
> [    0.300098] pci 0000:00:1c.0:   bridge window [mem 0xfff00000-0x000fffff pref] (disabled)
> [    0.300488] pci 0000:03:00.0: reg 10: [mem 0xf0200000-0xf0203fff 64bit]
> [    0.300715] pci 0000:03:00.0: supports D1 D2
> [    0.300720] pci 0000:03:00.0: PME# supported from D0 D3hot D3cold
> [    0.300734] pci 0000:03:00.0: PME# disabled
> [    0.300928] pci 0000:00:1c.1: PCI bridge to [bus 03-03]
> [    0.300937] pci 0000:00:1c.1:   bridge window [io  0xf000-0x0000] (disabled)
> [    0.300946] pci 0000:00:1c.1:   bridge window [mem 0xf0200000-0xf02fffff]
> [    0.300958] pci 0000:00:1c.1:   bridge window [mem 0xfff00000-0x000fffff pref] (disabled)
> [    0.301152] pci 0000:04:00.0: reg 10: [io  0x2000-0x20ff]
> [    0.301248] pci 0000:04:00.0: reg 18: [mem 0xf0610000-0xf0610fff 64bit pref]
> [    0.301318] pci 0000:04:00.0: reg 20: [mem 0xf0600000-0xf060ffff 64bit pref]
> [    0.301379] pci 0000:04:00.0: reg 30: [mem 0x00000000-0x0001ffff pref]
> [    0.301555] pci 0000:04:00.0: supports D1 D2
> [    0.301560] pci 0000:04:00.0: PME# supported from D0 D1 D2 D3hot D3cold
> [    0.301605] pci 0000:04:00.0: PME# disabled
> [    0.301804] pci 0000:00:1c.2: PCI bridge to [bus 04-04]
> [    0.301813] pci 0000:00:1c.2:   bridge window [io  0x2000-0x2fff]
> [    0.301822] pci 0000:00:1c.2:   bridge window [mem 0xfff00000-0x000fffff] (disabled)
> [    0.301835] pci 0000:00:1c.2:   bridge window [mem 0xf0600000-0xf06fffff 64bit pref]
> [    0.301934] pci 0000:00:1e.0: PCI bridge to [bus 05-05] (subtractive decode)
> [    0.301943] pci 0000:00:1e.0:   bridge window [io  0xf000-0x0000] (disabled)
> [    0.301953] pci 0000:00:1e.0:   bridge window [mem 0xfff00000-0x000fffff] (disabled)
> [    0.301965] pci 0000:00:1e.0:   bridge window [mem 0xfff00000-0x000fffff pref] (disabled)
> [    0.301972] pci 0000:00:1e.0:   bridge window [io  0x0000-0x0cf7] (subtractive decode)
> [    0.301978] pci 0000:00:1e.0:   bridge window [io  0x0d00-0xffff] (subtractive decode)
> [    0.301984] pci 0000:00:1e.0:   bridge window [mem 0x000a0000-0x000bffff] (subtractive decode)
> [    0.301999] pci 0000:00:1e.0:   bridge window [mem 0x000d0000-0x000d3fff] (subtractive decode)
> [    0.302005] pci 0000:00:1e.0:   bridge window [mem 0x000d4000-0x000d7fff] (subtractive decode)
> [    0.302012] pci 0000:00:1e.0:   bridge window [mem 0x000d8000-0x000dbfff] (subtractive decode)
> [    0.302018] pci 0000:00:1e.0:   bridge window [mem 0x000dc000-0x000dffff] (subtractive decode)
> [    0.302025] pci 0000:00:1e.0:   bridge window [mem 0x40000000-0xfebfffff] (subtractive decode)
> [    0.302061] pci_bus 0000:00: on NUMA node 0
> [    0.302071] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
> [    0.302443] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.RP01._PRT]
> [    0.302670] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.RP02._PRT]
> [    0.302823] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.RP03._PRT]
> [    0.303044] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.PCIB._PRT]
> [    0.316808] ACPI: PCI Interrupt Link [LNKA] (IRQs 1 3 4 5 6 *7 10 12 14 15)
> [    0.317001] ACPI: PCI Interrupt Link [LNKB] (IRQs 1 3 4 5 6 7 *11 12 14 15)
> [    0.317190] ACPI: PCI Interrupt Link [LNKC] (IRQs 1 3 4 5 6 7 10 12 14 15) *11
> [    0.317380] ACPI: PCI Interrupt Link [LNKD] (IRQs 1 3 4 5 6 7 11 12 14 15) *10
> [    0.317571] ACPI: PCI Interrupt Link [LNKE] (IRQs 1 3 4 5 6 7 10 12 14 15) *0, disabled.
> [    0.317763] ACPI: PCI Interrupt Link [LNKF] (IRQs 1 3 4 5 6 7 11 12 14 15) *0, disabled.
> [    0.317956] ACPI: PCI Interrupt Link [LNKG] (IRQs 1 3 4 5 6 7 *10 12 14 15)
> [    0.318146] ACPI: PCI Interrupt Link [LNKH] (IRQs 1 3 4 *5 6 7 11 12 14 15)
> [    0.318380] vgaarb: device added: PCI:0000:00:02.0,decodes=io+mem,owns=io+mem,locks=none
> [    0.318403] vgaarb: loaded
> [    0.318447] PCI: Using ACPI for IRQ routing
> [    0.318447] PCI: pci_cache_line_size set to 64 bytes
> [    0.318447] reserve RAM buffer: 000000000009f800 - 000000000009ffff 
> [    0.318447] reserve RAM buffer: 000000003f6d0000 - 000000003fffffff 
> [    0.318447] HPET: 3 timers in total, 0 timers will be used for per-cpu timer
> [    0.318447] hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0
> [    0.318447] hpet0: 3 comparators, 64-bit 14.318180 MHz counter
> [    0.324041] Switching to clocksource tsc
> [    0.326350] pnp: PnP ACPI init
> [    0.326386] ACPI: bus type pnp registered
> [    0.348153] pnp: PnP ACPI: found 11 devices
> [    0.348159] ACPI: ACPI bus type pnp unregistered
> [    0.348167] PnPBIOS: Disabled by ACPI PNP
> [    0.348197] system 00:01: [mem 0xe0000000-0xefffffff] has been reserved
> [    0.348205] system 00:01: [mem 0xfed14000-0xfed17fff] has been reserved
> [    0.348212] system 00:01: [mem 0xfed18000-0xfed18fff] has been reserved
> [    0.348219] system 00:01: [mem 0xfed19000-0xfed19fff] has been reserved
> [    0.348226] system 00:01: [mem 0xfed1c000-0xfed1ffff] has been reserved
> [    0.348233] system 00:01: [mem 0xfed20000-0xfed3ffff] has been reserved
> [    0.348240] system 00:01: [mem 0xfed40000-0xfed44fff] has been reserved
> [    0.348247] system 00:01: [mem 0xfed45000-0xfed8ffff] has been reserved
> [    0.348262] system 00:04: [mem 0xfed00000-0xfed003ff] has been reserved
> [    0.348277] system 00:06: [io  0x0680-0x069f] has been reserved
> [    0.348284] system 00:06: [io  0x0800-0x080f] has been reserved
> [    0.348291] system 00:06: [io  0x1000-0x107f] has been reserved
> [    0.348297] system 00:06: [io  0x1180-0x11bf] has been reserved
> [    0.348304] system 00:06: [io  0x1640-0x164f] has been reserved
> [    0.348311] system 00:06: [io  0xfe00-0xfe7f] has been reserved
> [    0.348318] system 00:06: [io  0xff00-0xff7f] has been reserved
> [    0.348330] system 00:07: [io  0x06a0-0x06af] has been reserved
> [    0.348336] system 00:07: [io  0x06b0-0x06ff] has been reserved
> [    0.383471] pci 0000:00:1c.0: BAR 15: assigned [mem 0x40000000-0x401fffff pref]
> [    0.383483] pci 0000:00:1c.1: BAR 15: assigned [mem 0x40200000-0x403fffff 64bit pref]
> [    0.383491] pci 0000:00:1c.2: BAR 14: assigned [mem 0x40400000-0x407fffff]
> [    0.383500] pci 0000:00:1c.0: BAR 13: assigned [io  0x3000-0x3fff]
> [    0.383507] pci 0000:00:1c.1: BAR 13: assigned [io  0x4000-0x4fff]
> [    0.383515] pci 0000:02:00.0: BAR 6: assigned [mem 0x40000000-0x4000ffff pref]
> [    0.383522] pci 0000:00:1c.0: PCI bridge to [bus 02-02]
> [    0.383529] pci 0000:00:1c.0:   bridge window [io  0x3000-0x3fff]
> [    0.383540] pci 0000:00:1c.0:   bridge window [mem 0xf0100000-0xf01fffff]
> [    0.383549] pci 0000:00:1c.0:   bridge window [mem 0x40000000-0x401fffff pref]
> [    0.383561] pci 0000:00:1c.1: PCI bridge to [bus 03-03]
> [    0.383568] pci 0000:00:1c.1:   bridge window [io  0x4000-0x4fff]
> [    0.383578] pci 0000:00:1c.1:   bridge window [mem 0xf0200000-0xf02fffff]
> [    0.383587] pci 0000:00:1c.1:   bridge window [mem 0x40200000-0x403fffff 64bit pref]
> [    0.383602] pci 0000:04:00.0: BAR 6: assigned [mem 0xf0620000-0xf063ffff pref]
> [    0.383607] pci 0000:00:1c.2: PCI bridge to [bus 04-04]
> [    0.383614] pci 0000:00:1c.2:   bridge window [io  0x2000-0x2fff]
> [    0.383624] pci 0000:00:1c.2:   bridge window [mem 0x40400000-0x407fffff]
> [    0.383634] pci 0000:00:1c.2:   bridge window [mem 0xf0600000-0xf06fffff 64bit pref]
> [    0.383646] pci 0000:00:1e.0: PCI bridge to [bus 05-05]
> [    0.383650] pci 0000:00:1e.0:   bridge window [io  disabled]
> [    0.383659] pci 0000:00:1e.0:   bridge window [mem disabled]
> [    0.383666] pci 0000:00:1e.0:   bridge window [mem pref disabled]
> [    0.383711] pci 0000:00:1c.0: PCI INT A -> GSI 17 (level, low) -> IRQ 17
> [    0.383720] pci 0000:00:1c.0: setting latency timer to 64
> [    0.383739] pci 0000:00:1c.1: PCI INT B -> GSI 16 (level, low) -> IRQ 16
> [    0.383749] pci 0000:00:1c.1: setting latency timer to 64
> [    0.383768] pci 0000:00:1c.2: PCI INT C -> GSI 18 (level, low) -> IRQ 18
> [    0.383776] pci 0000:00:1c.2: setting latency timer to 64
> [    0.383790] pci 0000:00:1e.0: setting latency timer to 64
> [    0.383798] pci_bus 0000:00: resource 4 [io  0x0000-0x0cf7]
> [    0.383804] pci_bus 0000:00: resource 5 [io  0x0d00-0xffff]
> [    0.383810] pci_bus 0000:00: resource 6 [mem 0x000a0000-0x000bffff]
> [    0.383816] pci_bus 0000:00: resource 7 [mem 0x000d0000-0x000d3fff]
> [    0.383821] pci_bus 0000:00: resource 8 [mem 0x000d4000-0x000d7fff]
> [    0.383827] pci_bus 0000:00: resource 9 [mem 0x000d8000-0x000dbfff]
> [    0.383833] pci_bus 0000:00: resource 10 [mem 0x000dc000-0x000dffff]
> [    0.383839] pci_bus 0000:00: resource 11 [mem 0x40000000-0xfebfffff]
> [    0.383847] pci_bus 0000:02: resource 0 [io  0x3000-0x3fff]
> [    0.383855] pci_bus 0000:02: resource 1 [mem 0xf0100000-0xf01fffff]
> [    0.383862] pci_bus 0000:02: resource 2 [mem 0x40000000-0x401fffff pref]
> [    0.383868] pci_bus 0000:03: resource 0 [io  0x4000-0x4fff]
> [    0.383874] pci_bus 0000:03: resource 1 [mem 0xf0200000-0xf02fffff]
> [    0.383880] pci_bus 0000:03: resource 2 [mem 0x40200000-0x403fffff 64bit pref]
> [    0.383886] pci_bus 0000:04: resource 0 [io  0x2000-0x2fff]
> [    0.383892] pci_bus 0000:04: resource 1 [mem 0x40400000-0x407fffff]
> [    0.383898] pci_bus 0000:04: resource 2 [mem 0xf0600000-0xf06fffff 64bit pref]
> [    0.383905] pci_bus 0000:05: resource 4 [io  0x0000-0x0cf7]
> [    0.383910] pci_bus 0000:05: resource 5 [io  0x0d00-0xffff]
> [    0.383916] pci_bus 0000:05: resource 6 [mem 0x000a0000-0x000bffff]
> [    0.383922] pci_bus 0000:05: resource 7 [mem 0x000d0000-0x000d3fff]
> [    0.383928] pci_bus 0000:05: resource 8 [mem 0x000d4000-0x000d7fff]
> [    0.383934] pci_bus 0000:05: resource 9 [mem 0x000d8000-0x000dbfff]
> [    0.383940] pci_bus 0000:05: resource 10 [mem 0x000dc000-0x000dffff]
> [    0.383946] pci_bus 0000:05: resource 11 [mem 0x40000000-0xfebfffff]
> [    0.384001] NET: Registered protocol family 2
> [    0.384127] IP route cache hash table entries: 32768 (order: 5, 131072 bytes)
> [    0.384679] TCP established hash table entries: 131072 (order: 8, 1048576 bytes)
> [    0.385644] TCP bind hash table entries: 65536 (order: 7, 524288 bytes)
> [    0.386100] TCP: Hash tables configured (established 131072 bind 65536)
> [    0.386107] TCP reno registered
> [    0.386116] UDP hash table entries: 512 (order: 2, 16384 bytes)
> [    0.386137] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
> [    0.386346] NET: Registered protocol family 1
> [    0.386389] pci 0000:00:02.0: Boot video device
> [    0.386784] PCI: CLS 64 bytes, default 64
> [    0.386896] Unpacking initramfs...
> [    0.763249] Freeing initrd memory: 7092k freed
> [    0.770033] Simple Boot Flag at 0x36 set to 0x1
> [    0.770720] audit: initializing netlink socket (disabled)
> [    0.770746] type=2000 audit(1278020463.767:1): initialized
> [    0.771065] highmem bounce pool size: 64 pages
> [    0.771075] HugeTLB registered 4 MB page size, pre-allocated 0 pages
> [    0.774308] VFS: Disk quotas dquot_6.5.2
> [    0.774418] Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
> [    0.774596] msgmni has been set to 1746
> [    0.774982] alg: No test for stdrng (krng)
> [    0.775113] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
> [    0.775120] io scheduler noop registered
> [    0.775124] io scheduler deadline registered
> [    0.775213] io scheduler cfq registered (default)
> [    0.775393] pcieport 0000:00:1c.0: setting latency timer to 64
> [    0.775465] pcieport 0000:00:1c.0: irq 24 for MSI/MSI-X
> [    0.775656] pcieport 0000:00:1c.1: setting latency timer to 64
> [    0.775721] pcieport 0000:00:1c.1: irq 25 for MSI/MSI-X
> [    0.775895] pcieport 0000:00:1c.2: setting latency timer to 64
> [    0.775959] pcieport 0000:00:1c.2: irq 26 for MSI/MSI-X
> [    0.776164] pcieport 0000:00:1c.0: Requesting control of PCIe PME from ACPI BIOS
> [    0.776181] pcieport 0000:00:1c.0: Failed to receive control of PCIe PME service: no _OSC support
> [    0.776192] pcie_pme: probe of 0000:00:1c.0:pcie01 failed with error -13
> [    0.776202] pcieport 0000:00:1c.1: Requesting control of PCIe PME from ACPI BIOS
> [    0.776210] pcieport 0000:00:1c.1: Failed to receive control of PCIe PME service: no _OSC support
> [    0.776218] pcie_pme: probe of 0000:00:1c.1:pcie01 failed with error -13
> [    0.776227] pcieport 0000:00:1c.2: Requesting control of PCIe PME from ACPI BIOS
> [    0.776234] pcieport 0000:00:1c.2: Failed to receive control of PCIe PME service: no _OSC support
> [    0.776242] pcie_pme: probe of 0000:00:1c.2:pcie01 failed with error -13
> [    0.776480] isapnp: Scanning for PnP cards...
> [    1.130188] isapnp: No Plug & Play device found
> [    1.133880] Linux agpgart interface v0.103
> [    1.134041] agpgart-intel 0000:00:00.0: Intel 945GME Chipset
> [    1.134408] agpgart-intel 0000:00:00.0: detected 7932K stolen memory
> [    1.137095] agpgart-intel 0000:00:00.0: AGP aperture is 256M @ 0xd0000000
> [    1.137257] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
> [    1.138035] PNP: PS/2 Controller [PNP0303:PS2K,PNP0f13:PS2M] at 0x60,0x64 irq 1,12
> [    1.177108] serio: i8042 KBD port at 0x60,0x64 irq 1
> [    1.177124] serio: i8042 AUX port at 0x60,0x64 irq 12
> [    1.177379] mice: PS/2 mouse device common for all mice
> [    1.179147] rtc_cmos 00:08: RTC can wake from S4
> [    1.179231] rtc_cmos 00:08: rtc core: registered rtc_cmos as rtc0
> [    1.179277] rtc0: alarms up to one month, y3k, 242 bytes nvram, hpet irqs
> [    1.179302] cpuidle: using governor ladder
> [    1.179307] cpuidle: using governor menu
> [    1.179316] No iBFT detected.
> [    1.179896] TCP cubic registered
> [    1.180273] NET: Registered protocol family 10
> [    1.181060] lo: Disabled Privacy Extensions
> [    1.181578] Mobile IPv6
> [    1.181584] NET: Registered protocol family 17
> [    1.181614] Using IPI No-Shortcut mode
> [    1.181804] PM: Resume from disk failed.
> [    1.181818] registered taskstats version 1
> [    1.182663] rtc_cmos 00:08: setting system clock to 2010-07-01 21:41:04 UTC (1278020464)
> [    1.182753] Initalizing network drop monitor service
> [    1.182857] Freeing unused kernel memory: 380k freed
> [    1.183141] Write protecting the kernel text: 2524k
> [    1.183183] Write protecting the kernel read-only data: 924k
> [    1.213820] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input0
> [    1.402848] thermal LNXTHERM:01: registered as thermal_zone0
> [    1.402868] ACPI: Thermal Zone [TZ01] (40 C)
> [    2.054768] r8169 Gigabit Ethernet driver 2.3LK-NAPI loaded
> [    2.054867] r8169 0000:04:00.0: PCI INT A -> GSI 18 (level, low) -> IRQ 18
> [    2.055022] r8169 0000:04:00.0: setting latency timer to 64
> [    2.055280] r8169 0000:04:00.0: irq 27 for MSI/MSI-X
> [    2.056894] r8169 0000:04:00.0: eth0: RTL8102e at 0xf80f8000, 00:21:70:ce:d2:2a, XID 04a00000 IRQ 27
> [    2.101785] usbcore: registered new interface driver usbfs
> [    2.101852] usbcore: registered new interface driver hub
> [    2.101965] usbcore: registered new device driver usb
> [    2.189005] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
> [    2.189087] ehci_hcd 0000:00:1d.7: PCI INT A -> GSI 23 (level, low) -> IRQ 23
> [    2.189134] ehci_hcd 0000:00:1d.7: setting latency timer to 64
> [    2.189144] ehci_hcd 0000:00:1d.7: EHCI Host Controller
> [    2.189201] ehci_hcd 0000:00:1d.7: new USB bus registered, assigned bus number 1
> [    2.189254] ehci_hcd 0000:00:1d.7: using broken periodic workaround
> [    2.189275] ehci_hcd 0000:00:1d.7: debug port 1
> [    2.193166] ehci_hcd 0000:00:1d.7: cache line size of 64 is not supported
> [    2.265080] ehci_hcd 0000:00:1d.7: irq 23, io mem 0xf0544000
> [    2.277032] ehci_hcd 0000:00:1d.7: USB 2.0 started, EHCI 1.00
> [    2.277103] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
> [    2.277113] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> [    2.277121] usb usb1: Product: EHCI Host Controller
> [    2.277128] usb usb1: Manufacturer: Linux 2.6.34-1-686 ehci_hcd
> [    2.277135] usb usb1: SerialNumber: 0000:00:1d.7
> [    2.277476] hub 1-0:1.0: USB hub found
> [    2.277493] hub 1-0:1.0: 8 ports detected
> [    2.589050] usb 1-2: new high speed USB device using ehci_hcd and address 2
> [    2.683218] uhci_hcd: USB Universal Host Controller Interface driver
> [    2.683392] uhci_hcd 0000:00:1d.0: power state changed by ACPI to D0
> [    2.683455] uhci_hcd 0000:00:1d.0: power state changed by ACPI to D0
> [    2.683475] uhci_hcd 0000:00:1d.0: PCI INT A -> GSI 23 (level, low) -> IRQ 23
> [    2.683497] uhci_hcd 0000:00:1d.0: setting latency timer to 64
> [    2.683507] uhci_hcd 0000:00:1d.0: UHCI Host Controller
> [    2.683543] uhci_hcd 0000:00:1d.0: new USB bus registered, assigned bus number 2
> [    2.683598] uhci_hcd 0000:00:1d.0: irq 23, io base 0x00001820
> [    2.683721] usb usb2: New USB device found, idVendor=1d6b, idProduct=0001
> [    2.683730] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> [    2.683738] usb usb2: Product: UHCI Host Controller
> [    2.683744] usb usb2: Manufacturer: Linux 2.6.34-1-686 uhci_hcd
> [    2.683751] usb usb2: SerialNumber: 0000:00:1d.0
> [    2.684152] hub 2-0:1.0: USB hub found
> [    2.684173] hub 2-0:1.0: 2 ports detected
> [    2.684406] uhci_hcd 0000:00:1d.1: PCI INT B -> GSI 19 (level, low) -> IRQ 19
> [    2.684429] uhci_hcd 0000:00:1d.1: setting latency timer to 64
> [    2.684438] uhci_hcd 0000:00:1d.1: UHCI Host Controller
> [    2.684467] uhci_hcd 0000:00:1d.1: new USB bus registered, assigned bus number 3
> [    2.684534] uhci_hcd 0000:00:1d.1: irq 19, io base 0x00001840
> [    2.684650] usb usb3: New USB device found, idVendor=1d6b, idProduct=0001
> [    2.684660] usb usb3: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> [    2.684667] usb usb3: Product: UHCI Host Controller
> [    2.684673] usb usb3: Manufacturer: Linux 2.6.34-1-686 uhci_hcd
> [    2.684680] usb usb3: SerialNumber: 0000:00:1d.1
> [    2.685026] hub 3-0:1.0: USB hub found
> [    2.685043] hub 3-0:1.0: 2 ports detected
> [    2.685227] uhci_hcd 0000:00:1d.2: PCI INT C -> GSI 18 (level, low) -> IRQ 18
> [    2.685247] uhci_hcd 0000:00:1d.2: setting latency timer to 64
> [    2.685256] uhci_hcd 0000:00:1d.2: UHCI Host Controller
> [    2.685281] uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus number 4
> [    2.685351] uhci_hcd 0000:00:1d.2: irq 18, io base 0x00001860
> [    2.685471] usb usb4: New USB device found, idVendor=1d6b, idProduct=0001
> [    2.685480] usb usb4: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> [    2.685488] usb usb4: Product: UHCI Host Controller
> [    2.685495] usb usb4: Manufacturer: Linux 2.6.34-1-686 uhci_hcd
> [    2.685502] usb usb4: SerialNumber: 0000:00:1d.2
> [    2.685880] hub 4-0:1.0: USB hub found
> [    2.685895] hub 4-0:1.0: 2 ports detected
> [    2.686126] uhci_hcd 0000:00:1d.3: power state changed by ACPI to D0
> [    2.686189] uhci_hcd 0000:00:1d.3: power state changed by ACPI to D0
> [    2.686207] uhci_hcd 0000:00:1d.3: PCI INT D -> GSI 16 (level, low) -> IRQ 16
> [    2.686227] uhci_hcd 0000:00:1d.3: setting latency timer to 64
> [    2.686236] uhci_hcd 0000:00:1d.3: UHCI Host Controller
> [    2.686263] uhci_hcd 0000:00:1d.3: new USB bus registered, assigned bus number 5
> [    2.686330] uhci_hcd 0000:00:1d.3: irq 16, io base 0x00001880
> [    2.686445] usb usb5: New USB device found, idVendor=1d6b, idProduct=0001
> [    2.686454] usb usb5: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> [    2.686462] usb usb5: Product: UHCI Host Controller
> [    2.686469] usb usb5: Manufacturer: Linux 2.6.34-1-686 uhci_hcd
> [    2.686476] usb usb5: SerialNumber: 0000:00:1d.3
> [    2.686781] hub 5-0:1.0: USB hub found
> [    2.686795] hub 5-0:1.0: 2 ports detected
> [    2.799854] usb 1-2: New USB device found, idVendor=064e, idProduct=a102
> [    2.799865] usb 1-2: New USB device strings: Mfr=2, Product=1, SerialNumber=0
> [    2.799874] usb 1-2: Product: Laptop_Integrated_Webcam_0.3M
> [    2.799881] usb 1-2: Manufacturer: SuYin
> [    3.156047] usb 5-1: new full speed USB device using uhci_hcd and address 2
> [    3.335401] usb 5-1: New USB device found, idVendor=413c, idProduct=02b0
> [    3.335412] usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> [    3.335421] usb 5-1: Product: BCM2046 Bluetooth Device
> [    3.335427] usb 5-1: Manufacturer: Broadcom Corp
> [    3.335433] usb 5-1: SerialNumber: 002269EA00DE
> [    3.898258] SCSI subsystem initialized
> [    4.280501] sdhci: Secure Digital Host Controller Interface driver
> [    4.280510] sdhci: Copyright(c) Pierre Ossman
> [    4.300926] sdhci-pci 0000:02:00.0: SDHCI controller found [197b:2382] (rev 0)
> [    4.300969] sdhci-pci 0000:02:00.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
> [    4.301093] sdhci-pci 0000:02:00.0: setting latency timer to 64
> [    4.301844] Registered led device: mmc0::
> [    4.302114] mmc0: SDHCI controller on PCI [0000:02:00.0] using ADMA
> [    4.302156] sdhci-pci 0000:02:00.2: SDHCI controller found [197b:2381] (rev 0)
> [    4.302198] sdhci-pci 0000:02:00.2: PCI INT A -> GSI 16 (level, low) -> IRQ 16
> [    4.302217] sdhci-pci 0000:02:00.2: Refusing to bind to secondary interface.
> [    4.302233] sdhci-pci 0000:02:00.2: PCI INT A disabled
> [    4.310143] libata version 3.00 loaded.
> [    4.321763] ata_piix 0000:00:1f.1: version 2.13
> [    4.321799] ata_piix 0000:00:1f.1: PCI INT B -> GSI 19 (level, low) -> IRQ 19
> [    4.321887] ata_piix 0000:00:1f.1: setting latency timer to 64
> [    4.322063] scsi0 : ata_piix
> [    4.322904] scsi1 : ata_piix
> [    4.324786] ata1: PATA max UDMA/100 cmd 0x1f0 ctl 0x3f6 bmdma 0x1810 irq 14
> [    4.324796] ata2: PATA max UDMA/100 cmd 0x170 ctl 0x376 bmdma 0x1818 irq 15
> [    4.328145] ata2: port disabled. ignoring.
> [    4.419058] mmc0: new MMC card at address 0001
> [    4.457070] mmcblk0: mmc0:0001 AF MC  122 MiB 
> [    4.457199]  mmcblk0: p1
> [    4.489521] ata1.00: CFA: STEC PATA 8GB, D5221-10, max UDMA/133
> [    4.489530] ata1.00: 15005088 sectors, multi 0: LBA 
> [    4.497434] ata1.00: configured for UDMA/100
> [    4.497657] scsi 0:0:0:0: Direct-Access     ATA      STEC PATA 8GB    D522 PQ: 0 ANSI: 5
> [    4.568362] sd 0:0:0:0: [sda] 15005088 512-byte logical blocks: (7.68 GB/7.15 GiB)
> [    4.568608] sd 0:0:0:0: [sda] Write Protect is off
> [    4.568620] sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
> [    4.568719] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
> [    4.569333]  sda: sda1
> [    4.570591] sd 0:0:0:0: [sda] Attached SCSI disk
> [    5.175260] kjournald starting.  Commit interval 5 seconds
> [    5.175280] EXT3-fs (sda1): mounted filesystem with ordered data mode
> [    5.811653] udev: starting version 141
> [    8.117342] input: PC Speaker as /devices/platform/pcspkr/input/input1
> [    8.153161] i801_smbus 0000:00:1f.3: PCI INT B -> GSI 19 (level, low) -> IRQ 19
> [    8.153177] ACPI: resource 0000:00:1f.3 [io  0x18a0-0x18bf] conflicts with ACPI region SMBI [??? 0x000018a0-0x000018af flags 0x49]
> [    8.153187] ACPI: If an ACPI driver is available for this device, you should use it instead of the native driver
> [    8.517463] Bluetooth: Core ver 2.15
> [    8.522884] NET: Registered protocol family 31
> [    8.522892] Bluetooth: HCI device and connection manager initialized
> [    8.522900] Bluetooth: HCI socket layer initialized
> [    8.837401] Linux video capture interface: v2.00
> [    8.844608] jmb38x_ms 0000:02:00.3: PCI INT A -> GSI 16 (level, low) -> IRQ 16
> [    8.844625] jmb38x_ms 0000:02:00.3: setting latency timer to 64
> [    8.863808] Bluetooth: Generic Bluetooth USB driver ver 0.6
> [    8.865577] usbcore: registered new interface driver btusb
> [    9.073009] uvcvideo: Found UVC 1.00 device Laptop_Integrated_Webcam_0.3M (064e:a102)
> [    9.095152] input: Laptop_Integrated_Webcam_0.3M as /devices/pci0000:00/0000:00:1d.7/usb1/1-2/1-2:1.0/input/input2
> [    9.095240] usbcore: registered new interface driver uvcvideo
> [    9.095246] USB Video Class driver (v0.1.0)
> [    9.311319] leds_ss4200: no LED devices found
> [    9.824092] intel_rng: FWH not detected
> [    9.904095] compal-laptop: Identified laptop model 'Dell Mini 9'.
> [    9.918041] compal-laptop: driver 0.2.6 successfully loaded.
> [   10.000761] dcdbas dcdbas: Dell Systems Management Base Driver (version 5.6.0-3.2)
> [   10.031878] dell-laptop: Blacklisted hardware detected - not enabling rfkill
> [   10.748521] b43-pci-bridge 0000:03:00.0: PCI INT A -> GSI 17 (level, low) -> IRQ 17
> [   10.748549] b43-pci-bridge 0000:03:00.0: setting latency timer to 64
> [   10.772520] ssb: Core 0 found: ChipCommon (cc 0x800, rev 0x16, vendor 0x4243)
> [   10.772549] ssb: Core 1 found: IEEE 802.11 (cc 0x812, rev 0x0F, vendor 0x4243)
> [   10.772573] ssb: Core 2 found: PCMCIA (cc 0x80D, rev 0x0A, vendor 0x4243)
> [   10.772597] ssb: Core 3 found: PCI-E (cc 0x820, rev 0x09, vendor 0x4243)
> [   10.872370] ssb: Sonics Silicon Backplane found on PCI device 0000:03:00.0
> [   11.009241] input: Lid Switch as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0D:00/input/input3
> [   11.009721] ACPI: Lid Switch [LID0]
> [   11.010191] input: Power Button as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input4
> [   11.010522] ACPI: Power Button [PWRB]
> [   11.010957] input: Sleep Button as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input5
> [   11.011274] ACPI: Sleep Button [SLPB]
> [   11.024053] Monitor-Mwait will be used to enter C-1 state
> [   11.041306] Monitor-Mwait will be used to enter C-2 state
> [   11.048032] Monitor-Mwait will be used to enter C-3 state
> [   11.048057] Marking TSC unstable due to TSC halts in idle
> [   11.050585] input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input6
> [   11.050733] ACPI: Power Button [PWRF]
> [   11.067788] Switching to clocksource hpet
> [   12.524036] Synaptics Touchpad, model: 1, fw: 7.0, id: 0x1c0b1, caps: 0xd04711/0xa00000/0x20000
> [   12.872262] input: SynPS/2 Synaptics TouchPad as /devices/platform/i8042/serio1/input/input7
> [   14.343456] cfg80211: Calling CRDA to update world regulatory domain
> [   16.225360] b43-phy0: Broadcom 4312 WLAN found (core revision 15)
> [   16.322859] acpi device:00: registered as cooling_device2
> [   16.323284] input: Video Bus as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input8
> [   16.323421] ACPI: Video Device [GFX0] (multi-head: yes  rom: no  post: no)
> [   20.377806] ACPI: AC Adapter [ACAD] (on-line)
> [   20.536445] ACPI: EC: GPE storm detected, transactions will use polling mode
> [   20.661328] ACPI: Battery Slot [BAT1] (battery present)
> [   20.859305] HDA Intel 0000:00:1b.0: PCI INT A -> GSI 22 (level, low) -> IRQ 22
> [   20.859456] HDA Intel 0000:00:1b.0: irq 28 for MSI/MSI-X
> [   20.859521] HDA Intel 0000:00:1b.0: setting latency timer to 64
> [   21.080215] phy0: Selected rate control algorithm 'minstrel'
> [   21.082001] Registered led device: b43-phy0::tx
> [   21.082070] Registered led device: b43-phy0::rx
> [   21.082134] Registered led device: b43-phy0::radio
> [   21.082324] Broadcom 43xx driver loaded [ Features: PMLS, Firmware-ID: FW13 ]
> [   21.280993] input: HDA Digital PCBeep as /devices/pci0000:00/0000:00:1b.0/input/input9
> [   22.541029] EXT3-fs (sda1): using internal journal
> [   23.638269] loop: module loaded
> [   24.343487] NET: Registered protocol family 15
> [   24.541323] alg: No test for cipher_null (cipher_null-generic)
> [   24.541427] alg: No test for ecb(cipher_null) (ecb-cipher_null)
> [   24.541517] alg: No test for digest_null (digest_null-generic)
> [   24.541605] alg: No test for compress_null (compress_null-generic)
> [   25.700500] padlock: VIA PadLock Hash Engine not detected.
> [   26.372455] padlock: VIA PadLock Hash Engine not detected.
> [   28.349988] padlock: VIA PadLock not detected.
> [   34.820268] b43 ssb0:0: firmware: requesting b43/ucode15.fw
> [   34.840703] b43 ssb0:0: firmware: requesting b43/lp0initvals15.fw
> [   34.861071] b43 ssb0:0: firmware: requesting b43/lp0bsinitvals15.fw
> [   35.016266] b43-phy0: Loading firmware version 410.2160 (2007-05-26 15:32:10)
> [   40.562226] ADDRCONF(NETDEV_UP): wlan0: link is not ready
> [   40.562777] r8169 0000:04:00.0: eth0: link down
> [   40.563220] ADDRCONF(NETDEV_UP): eth0: link is not ready
> [   43.209460] wlan0: deauthenticating from 06:18:4d:49:80:07 by local choice (reason=3)
> [   43.209812] wlan0: authenticate with 06:18:4d:49:80:07 (try 1)
> [   43.212491] wlan0: authenticated
> [   43.213172] wlan0: associate with 06:18:4d:49:80:07 (try 1)
> [   43.215732] wlan0: RX AssocResp from 06:18:4d:49:80:07 (capab=0x431 status=0 aid=1)
> [   43.215742] wlan0: associated
> [   43.218281] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> [   43.218439] cfg80211: Calling CRDA for country: DE
> [   45.065099] Bluetooth: L2CAP ver 2.14
> [   45.065106] Bluetooth: L2CAP socket layer initialized
> [   45.191342] Bluetooth: RFCOMM TTY layer initialized
> [   45.191356] Bluetooth: RFCOMM socket layer initialized
> [   45.191362] Bluetooth: RFCOMM ver 1.11
> [   46.686696] b43-phy0 ERROR: Fatal DMA error: 0x00000800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
> [   46.686878] b43-phy0 ERROR: This device does not support DMA on your system. Please use PIO instead.
> [   46.687041] b43-phy0: Controller RESET (DMA error) ...
> [   46.900338] b43-phy0: Loading firmware version 410.2160 (2007-05-26 15:32:10)
> [   52.421312] b43-phy0: Controller restarted
> [   54.024144] wlan0: no IPv6 routers present
> [   54.920178] No probe response from AP 06:18:4d:49:80:07 after 500ms, disconnecting.
> [   54.964212] cfg80211: Calling CRDA to update world regulatory domain
> [   56.360816] wlan0: authenticate with 06:18:4d:49:80:07 (try 1)
> [   56.363612] wlan0: authenticated
> [   56.363672] wlan0: associate with 06:18:4d:49:80:07 (try 1)
> [   56.366338] wlan0: RX AssocResp from 06:18:4d:49:80:07 (capab=0x431 status=0 aid=1)
> [   56.366351] wlan0: associated
> [   67.820276] ACPI Warning: _BQC returned an invalid level (20100121/video-644)
> [   70.530545] [drm] Initialized drm 1.1.0 20060810
> [   70.600147] pci 0000:00:02.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16
> [   70.600162] pci 0000:00:02.0: setting latency timer to 64
> [   70.643287] [drm] Initialized i915 1.6.0 20080730 for 0000:00:02.0 on minor 0
> [  161.121253] device wlan0 entered promiscuous mode
> [  179.304185] No probe response from AP 06:18:4d:49:80:07 after 500ms, disconnecting.
> [  179.624164] b43-phy0 ERROR: MAC suspend failed
> [  180.064154] b43-phy0 ERROR: MAC suspend failed
> [  180.081243] cfg80211: Calling CRDA to update world regulatory domain
> [  182.157138] wlan0: authenticate with 06:18:4d:49:80:07 (try 1)
> [  182.356188] wlan0: authenticate with 06:18:4d:49:80:07 (try 2)
> [  182.556200] wlan0: authenticate with 06:18:4d:49:80:07 (try 3)
> [  182.756182] wlan0: authentication with 06:18:4d:49:80:07 timed out
> [  199.256153] b43-phy0 ERROR: MAC suspend failed
> [  212.176142] b43-phy0 ERROR: MAC suspend failed
> [  212.776164] b43-phy0 ERROR: MAC suspend failed
> [  239.640171] b43-phy0 ERROR: MAC suspend failed
> [  240.028146] b43-phy0 ERROR: MAC suspend failed
> [  240.416165] b43-phy0 ERROR: MAC suspend failed
> [  240.804181] b43-phy0 ERROR: MAC suspend failed
> [  241.192161] b43-phy0 ERROR: MAC suspend failed
> [  241.580183] b43-phy0 ERROR: MAC suspend failed
> [  241.968183] b43-phy0 ERROR: MAC suspend failed
> [  252.669784] b43-phy1: Broadcom 4312 WLAN found (core revision 15)
> [  252.738905] phy1: Selected rate control algorithm 'minstrel'
> [  252.744804] Registered led device: b43-phy1::tx
> [  252.746101] Registered led device: b43-phy1::rx
> [  252.747464] Registered led device: b43-phy1::radio
> [  252.751118] Broadcom 43xx driver loaded [ Features: PMLS, Firmware-ID: FW13 ]
> [  252.784267] b43 ssb0:0: firmware: requesting b43/ucode15.fw
> [  252.803020] b43 ssb0:0: firmware: requesting b43/lp0initvals15.fw
> [  252.823455] b43 ssb0:0: firmware: requesting b43/lp0bsinitvals15.fw
> [  252.980256] b43-phy1: Loading firmware version 410.2160 (2007-05-26 15:32:10)
> [  258.513407] b43-phy1 ERROR: Fatal DMA error: 0x00000400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
> [  258.513437] b43-phy1 ERROR: This device does not support DMA on your system. Please use PIO instead.
> [  258.513456] b43-phy1: Controller RESET (DMA error) ...
> [  258.740369] b43-phy1: Loading firmware version 410.2160 (2007-05-26 15:32:10)
> [  264.281323] b43-phy1: Controller restarted
> [  264.282886] ADDRCONF(NETDEV_UP): wlan0: link is not ready
> [  270.912390] b43-phy1: Loading firmware version 410.2160 (2007-05-26 15:32:10)
> [  276.458667] ADDRCONF(NETDEV_UP): wlan0: link is not ready
> [  277.756823] wlan0: direct probe to 06:18:4d:49:80:07 (try 1)
> [  277.765756] wlan0: direct probe responded
> [  277.780112] wlan0: authenticate with 06:18:4d:49:80:07 (try 1)
> [  277.785071] wlan0: authenticated
> [  277.785139] wlan0: associate with 06:18:4d:49:80:07 (try 1)
> [  277.787782] wlan0: RX AssocResp from 06:18:4d:49:80:07 (capab=0x431 status=0 aid=1)
> [  277.787794] wlan0: associated
> [  277.798160] ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> [  288.192054] wlan0: no IPv6 routers present
> 
> ** Model information
> not available
> 
> ** Loaded modules:
> Module                  Size  Used by
> b43                   136010  0 
> i915                  219529  2 
> drm_kms_helper         18209  1 i915
> drm                   113797  4 i915,drm_kms_helper
> i2c_algo_bit            3541  1 i915
> binfmt_misc             5022  1 
> rfcomm                 24743  2 
> l2cap                  22579  3 rfcomm
> crc16                   1031  1 l2cap
> acpi_cpufreq            5139  1 
> cpufreq_conservative     6210  0 
> cpufreq_stats           1944  0 
> cpufreq_powersave        606  0 
> cpufreq_userspace       1496  0 
> deflate                 1291  0 
> zlib_deflate           15762  1 deflate
> ctr                     2687  0 
> twofish                 5669  0 
> twofish_common         12564  1 twofish
> camellia               16843  0 
> serpent                16191  0 
> blowfish                7256  0 
> cast5                  15585  0 
> des_generic            15043  0 
> cbc                     1987  0 
> aes_i586                6820  1 
> aes_generic            25742  1 aes_i586
> xcbc                    1845  0 
> rmd160                  9408  0 
> sha512_generic          8005  0 
> sha256_generic         10828  0 
> sha1_generic            1403  0 
> hmac                    2005  0 
> crypto_null             1864  0 
> af_key                 22390  2 
> loop                    9748  0 
> snd_hda_codec_realtek   173780  1 
> arc4                     978  2 
> snd_hda_intel          16543  3 
> ecb                     1409  2 
> snd_hda_codec          54225  2 snd_hda_codec_realtek,snd_hda_intel
> snd_hwdep               4070  1 snd_hda_codec
> snd_pcm_oss            28706  0 
> snd_mixer_oss          10474  1 snd_pcm_oss
> battery                 4074  0 
> ac                      1644  0 
> snd_pcm                47768  4 snd_hda_intel,snd_hda_codec,snd_pcm_oss
> joydev                  6855  0 
> video                  15177  1 i915
> output                  1200  1 video
> snd_seq_midi            3604  0 
> mac80211              134629  1 b43
> cfg80211              100055  2 b43,mac80211
> snd_rawmidi            12636  1 snd_seq_midi
> snd_seq_midi_event      3676  1 snd_seq_midi
> button                  3642  1 i915
> processor              25241  3 acpi_cpufreq
> ssb                    33351  1 b43
> serio_raw               2912  0 
> snd_seq                35397  2 snd_seq_midi,snd_seq_midi_event
> pcmcia                 27272  2 b43,ssb
> pcmcia_core             8972  1 pcmcia
> snd_timer              12341  3 snd_pcm,snd_seq
> snd_seq_device          3677  3 snd_seq_midi,snd_rawmidi,snd_seq
> dell_laptop             4268  0 
> dcdbas                  3868  1 dell_laptop
> compal_laptop           1344  0 
> rng_core                2354  1 b43
> psmouse                39043  0 
> evdev                   5657  14 
> snd                    34771  15 snd_hda_codec_realtek,snd_hda_intel,snd_hda_codec,snd_hwdep,snd_pcm_oss,snd_mixer_oss,snd_pcm,snd_rawmidi,snd_seq,snd_timer,snd_seq_device
> uvcvideo               44515  0 
> btusb                   8009  0 
> jmb38x_ms               5510  0 
> videodev               27052  1 uvcvideo
> v4l1_compat            10318  2 uvcvideo,videodev
> memstick                4352  1 jmb38x_ms
> tpm_tis                 5500  0 
> tpm                     8113  1 tpm_tis
> tpm_bios                3561  1 tpm
> bluetooth              35931  3 rfcomm,l2cap,btusb
> i2c_i801                6506  0 
> pcspkr                  1211  0 
> rfkill                 10512  4 cfg80211,dell_laptop,compal_laptop,bluetooth
> i2c_core               12610  6 i915,drm_kms_helper,drm,i2c_algo_bit,videodev,i2c_i801
> soundcore               3626  1 snd
> snd_page_alloc          5133  2 snd_hda_intel,snd_pcm
> ext3                   93348  1 
> jbd                    32625  1 ext3
> mbcache                 3766  1 ext3
> sd_mod                 26889  2 
> crc_t10dif              1016  1 sd_mod
> ata_generic             1951  0 
> mmc_block               6516  0 
> ata_piix               17348  1 
> sdhci_pci               5146  0 
> sdhci                  12099  1 sdhci_pci
> libata                116217  2 ata_generic,ata_piix
> scsi_mod              103057  2 sd_mod,libata
> uhci_hcd               16157  0 
> mmc_core               39971  4 b43,ssb,mmc_block,sdhci
> led_class               1571  2 b43,sdhci
> ehci_hcd               28211  0 
> usbcore               101657  5 uvcvideo,btusb,uhci_hcd,ehci_hcd
> nls_base                4529  1 usbcore
> r8169                  25630  0 
> mii                     2718  1 r8169
> thermal                 9533  0 
> fan                     2510  0 
> thermal_sys             9406  4 video,processor,thermal,fan
> 
> ** Network interface configuration:
> # This file describes the network interfaces available on your system
> # and how to activate them. For more information, see interfaces(5).
> 
> # The loopback network interface
> auto lo
> iface lo inet loopback
> 
> # The primary network interface
> allow-hotplug eth0
> iface eth0 inet dhcp
> 
> allow-hotplug wlan0
> iface wlan0 inet dhcp
>         wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
> 
> ** Network status:
> *** IP interfaces and addresses:
> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
>     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
>     inet 127.0.0.1/8 scope host lo
>     inet6 ::1/128 scope host 
>        valid_lft forever preferred_lft forever
> 2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN qlen 1000
>     link/ether 00:21:70:ce:d2:2a brd ff:ff:ff:ff:ff:ff
>     inet 169.254.7.134/16 brd 169.254.255.255 scope link eth0:avahi
> 4: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
>     link/ether 00:23:08:49:6f:45 brd ff:ff:ff:ff:ff:ff
>     inet 10.0.0.2/24 brd 1.0.23.255 scope global wlan0
>     inet6 fe80::223:8ff:fe49:6f45/64 scope link 
>        valid_lft forever preferred_lft forever
> 
> *** Device statistics:
> Inter-|   Receive                                                |  Transmit
>  face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
>     lo:   45053     452    0    0    0     0          0         0    45053     452    0    0    0     0       0          0
>   eth0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
>  wlan0: 1101320207  839055    0    0    0     0          0         0 73887028  647167    0    0    0     0       0          0
> 
> *** Protocol statistics:
> Ip:
>     836651 total packets received
>     70 with invalid addresses
>     0 forwarded
>     0 incoming packets discarded
>     836581 incoming packets delivered
>     644863 requests sent out
>     18 dropped because of missing route
> Icmp:
>     443 ICMP messages received
>     4 input ICMP message failed.
>     ICMP-Eingabehistogramm:
>         destination unreachable: 440
>         timeout in transit: 3
>     442 ICMP messages sent
>     0 ICMP messages failed
>     ICMP-Ausgabehistogramm:
>         destination unreachable: 440
>         echo request: 2
> IcmpMsg:
>         InType3: 440
>         InType11: 3
>         OutType3: 440
>         OutType8: 2
> Tcp:
>     4978 active connections openings
>     120 passive connection openings
>     37 failed connection attempts
>     226 connection resets received
>     4 connections established
>     830699 segments received
>     632056 segments send out
>     6389 segments retransmited
>     0 bad segments received.
>     511 resets sent
> Udp:
>     5439 packets received
>     0 packets to unknown port received.
>     0 packet receive errors
>     6010 packets sent
> UdpLite:
> TcpExt:
>     33 resets received for embryonic SYN_RECV sockets
>     2 packets pruned from receive queue because of socket buffer overrun
>     2036 TCP sockets finished time wait in fast timer
>     7 packets rejects in established connections because of timestamp
>     99731 delayed acks sent
>     5 delayed acks further delayed because of locked socket
>     Quick ack mode was activated 469 times
>     79228 packets directly queued to recvmsg prequeue.
>     49965 bytes directly in process context from backlog
>     94674441 bytes directly received in process context from prequeue
>     529133 packet headers predicted
>     88167 packets header predicted and directly queued to user
>     12958 acknowledgments not containing data payload received
>     3164 predicted acknowledgments
>     37 times recovered from packet loss by selective acknowledgements
>     164 congestion windows recovered without slow start after partial ack
>     13 TCP data loss events
>     253 timeouts after reno fast retransmit
>     792 timeouts after SACK recovery
>     77 timeouts in loss state
>     53 fast retransmits
>     746 retransmits in slow start
>     3129 other TCP timeouts
>     6 SACK retransmits failed
>     1 times receiver scheduled too late for direct processing
>     183 packets collapsed in receive queue due to low socket buffer
>     423 DSACKs sent for old packets
>     6 DSACKs sent for out of order packets
>     104 DSACKs received
>     87 connections reset due to unexpected data
>     24 connections reset due to early user close
>     122 connections aborted due to timeout
>     TCPDSACKIgnoredOld: 46
>     TCPDSACKIgnoredNoUndo: 21
>     TCPSackShiftFallback: 624
> IpExt:
>     InOctets: 1089504067
>     OutOctets: 53173986
> 
> *** Device features:
> eth0: 0x180
> lo: 0x13865
> wlan0: 0x2000
> 
> ** PCI devices:
> 00:00.0 Host bridge [0600]: Intel Corporation Mobile 945GME Express Memory Controller Hub [8086:27ac] (rev 03)
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ >SERR- <PERR- INTx-
>         Latency: 0
>         Capabilities: <access denied>
>         Kernel driver in use: agpgart-intel
> 
> 00:02.0 VGA compatible controller [0300]: Intel Corporation Mobile 945GME Express Integrated Graphics Controller [8086:27ae] (rev 03) (prog-if 00 [VGA controller])
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Interrupt: pin A routed to IRQ 16
>         Region 0: Memory at f0000000 (32-bit, non-prefetchable) [size=512K]
>         Region 1: I/O ports at 1800 [size=8]
>         Region 2: Memory at d0000000 (32-bit, prefetchable) [size=256M]
>         Region 3: Memory at f0300000 (32-bit, non-prefetchable) [size=256K]
>         Capabilities: <access denied>
>         Kernel modules: i915
> 
> 00:02.1 Display controller [0380]: Intel Corporation Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller [8086:27a6] (rev 03)
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Region 0: Memory at f0080000 (32-bit, non-prefetchable) [size=512K]
>         Capabilities: <access denied>
> 
> 00:1b.0 Audio device [0403]: Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller [8086:27d8] (rev 02)
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0, Cache Line Size: 64 bytes
>         Interrupt: pin A routed to IRQ 28
>         Region 0: Memory at f0540000 (64-bit, non-prefetchable) [size=16K]
>         Capabilities: <access denied>
>         Kernel driver in use: HDA Intel
>         Kernel modules: snd-hda-intel
> 
> 00:1c.0 PCI bridge [0604]: Intel Corporation 82801G (ICH7 Family) PCI Express Port 1 [8086:27d0] (rev 02) (prog-if 00 [Normal decode])
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0, Cache Line Size: 64 bytes
>         Bus: primary=00, secondary=02, subordinate=02, sec-latency=0
>         I/O behind bridge: 00003000-00003fff
>         Memory behind bridge: f0100000-f01fffff
>         Prefetchable memory behind bridge: 0000000040000000-00000000401fffff
>         Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ <SERR- <PERR-
>         BridgeCtl: Parity- SERR- NoISA+ VGA- MAbort- >Reset- FastB2B-
>                 PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
>         Capabilities: <access denied>
>         Kernel driver in use: pcieport
>         Kernel modules: shpchp
> 
> 00:1c.1 PCI bridge [0604]: Intel Corporation 82801G (ICH7 Family) PCI Express Port 2 [8086:27d2] (rev 02) (prog-if 00 [Normal decode])
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0, Cache Line Size: 64 bytes
>         Bus: primary=00, secondary=03, subordinate=03, sec-latency=0
>         I/O behind bridge: 00004000-00004fff
>         Memory behind bridge: f0200000-f02fffff
>         Prefetchable memory behind bridge: 0000000040200000-00000000403fffff
>         Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ <SERR- <PERR-
>         BridgeCtl: Parity- SERR- NoISA+ VGA- MAbort- >Reset- FastB2B-
>                 PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
>         Capabilities: <access denied>
>         Kernel driver in use: pcieport
>         Kernel modules: shpchp
> 
> 00:1c.2 PCI bridge [0604]: Intel Corporation 82801G (ICH7 Family) PCI Express Port 3 [8086:27d4] (rev 02) (prog-if 00 [Normal decode])
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0, Cache Line Size: 64 bytes
>         Bus: primary=00, secondary=04, subordinate=04, sec-latency=0
>         I/O behind bridge: 00002000-00002fff
>         Memory behind bridge: 40400000-407fffff
>         Prefetchable memory behind bridge: 00000000f0600000-00000000f06fffff
>         Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ <SERR- <PERR-
>         BridgeCtl: Parity- SERR- NoISA+ VGA- MAbort- >Reset- FastB2B-
>                 PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
>         Capabilities: <access denied>
>         Kernel driver in use: pcieport
>         Kernel modules: shpchp
> 
> 00:1d.0 USB Controller [0c03]: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #1 [8086:27c8] (rev 02) (prog-if 00 [UHCI])
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Interrupt: pin A routed to IRQ 23
>         Region 4: I/O ports at 1820 [size=32]
>         Kernel driver in use: uhci_hcd
>         Kernel modules: uhci-hcd
> 
> 00:1d.1 USB Controller [0c03]: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #2 [8086:27c9] (rev 02) (prog-if 00 [UHCI])
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Interrupt: pin B routed to IRQ 19
>         Region 4: I/O ports at 1840 [size=32]
>         Kernel driver in use: uhci_hcd
>         Kernel modules: uhci-hcd
> 
> 00:1d.2 USB Controller [0c03]: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #3 [8086:27ca] (rev 02) (prog-if 00 [UHCI])
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Interrupt: pin C routed to IRQ 18
>         Region 4: I/O ports at 1860 [size=32]
>         Kernel driver in use: uhci_hcd
>         Kernel modules: uhci-hcd
> 
> 00:1d.3 USB Controller [0c03]: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #4 [8086:27cb] (rev 02) (prog-if 00 [UHCI])
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Interrupt: pin D routed to IRQ 16
>         Region 4: I/O ports at 1880 [size=32]
>         Kernel driver in use: uhci_hcd
>         Kernel modules: uhci-hcd
> 
> 00:1d.7 USB Controller [0c03]: Intel Corporation 82801G (ICH7 Family) USB2 EHCI Controller [8086:27cc] (rev 02) (prog-if 20 [EHCI])
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Interrupt: pin A routed to IRQ 23
>         Region 0: Memory at f0544000 (32-bit, non-prefetchable) [size=1K]
>         Capabilities: <access denied>
>         Kernel driver in use: ehci_hcd
>         Kernel modules: ehci-hcd
> 
> 00:1e.0 PCI bridge [0604]: Intel Corporation 82801 Mobile PCI Bridge [8086:2448] (rev e2) (prog-if 01 [Subtractive decode])
>         Control: I/O- Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Bus: primary=00, secondary=05, subordinate=05, sec-latency=32
>         Secondary status: 66MHz- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort+ <SERR- <PERR-
>         BridgeCtl: Parity- SERR- NoISA- VGA- MAbort- >Reset- FastB2B-
>                 PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
>         Capabilities: <access denied>
> 
> 00:1f.0 ISA bridge [0601]: Intel Corporation 82801GBM (ICH7-M) LPC Interface Bridge [8086:27b9] (rev 02)
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Capabilities: <access denied>
>         Kernel modules: intel-rng, leds-ss4200, iTCO_wdt
> 
> 00:1f.1 IDE interface [0101]: Intel Corporation 82801G (ICH7 Family) IDE Controller [8086:27df] (rev 02) (prog-if 8a [Master SecP PriP])
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0
>         Interrupt: pin B routed to IRQ 19
>         Region 0: I/O ports at 01f0 [size=8]
>         Region 1: I/O ports at 03f4 [size=1]
>         Region 2: I/O ports at 0170 [size=8]
>         Region 3: I/O ports at 0374 [size=1]
>         Region 4: I/O ports at 1810 [size=16]
>         Kernel driver in use: ata_piix
>         Kernel modules: ata_piix
> 
> 00:1f.3 SMBus [0c05]: Intel Corporation 82801G (ICH7 Family) SMBus Controller [8086:27da] (rev 02)
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Interrupt: pin B routed to IRQ 19
>         Region 4: I/O ports at 18a0 [size=32]
>         Kernel modules: i2c-i801
> 
> 02:00.0 System peripheral [0880]: JMicron Technologies, Inc. Device [197b:2382]
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0, Cache Line Size: 64 bytes
>         Interrupt: pin A routed to IRQ 16
>         Region 0: Memory at f0100000 (32-bit, non-prefetchable) [size=256]
>         [virtual] Expansion ROM at 40000000 [disabled] [size=64K]
>         Capabilities: <access denied>
>         Kernel driver in use: sdhci-pci
>         Kernel modules: sdhci-pci
> 
> 02:00.2 SD Host controller [0805]: JMicron Technologies, Inc. Device [197b:2381] (prog-if 01)
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Interrupt: pin A routed to IRQ 16
>         Region 0: Memory at f0100400 (32-bit, non-prefetchable) [size=256]
>         Capabilities: <access denied>
>         Kernel modules: sdhci-pci
> 
> 02:00.3 System peripheral [0880]: JMicron Technologies, Inc. Device [197b:2383]
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0, Cache Line Size: 64 bytes
>         Interrupt: pin A routed to IRQ 16
>         Region 0: Memory at f0100800 (32-bit, non-prefetchable) [size=256]
>         Capabilities: <access denied>
>         Kernel driver in use: jmb38x_ms
>         Kernel modules: jmb38x_ms
> 
> 03:00.0 Network controller [0280]: Broadcom Corporation BCM4312 802.11b/g [14e4:4315] (rev 01)
>         Subsystem: Broadcom Corporation Device [14e4:04b5]
>         Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0, Cache Line Size: 64 bytes
>         Interrupt: pin A routed to IRQ 17
>         Region 0: Memory at f0200000 (64-bit, non-prefetchable) [size=16K]
>         Capabilities: <access denied>
>         Kernel driver in use: b43-pci-bridge
>         Kernel modules: ssb
> 
> 04:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8101E/RTL8102E PCI Express Fast Ethernet controller [10ec:8136] (rev 02)
>         Subsystem: Dell Device [1028:02b0]
>         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
>         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>         Latency: 0, Cache Line Size: 64 bytes
>         Interrupt: pin A routed to IRQ 27
>         Region 0: I/O ports at 2000 [size=256]
>         Region 2: Memory at f0610000 (64-bit, prefetchable) [size=4K]
>         Region 4: Memory at f0600000 (64-bit, prefetchable) [size=64K]
>         [virtual] Expansion ROM at f0620000 [disabled] [size=128K]
>         Capabilities: <access denied>
>         Kernel driver in use: r8169
>         Kernel modules: r8169
> 
> 
> ** USB devices:
> Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
> Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
> Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
> Bus 005 Device 002: ID 413c:02b0 Dell Computer Corp. 
> Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
> Bus 001 Device 002: ID 064e:a102 Suyin Corp. Lenovo Webcam
> Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
> 
> 
> -- System Information:
> Debian Release: squeeze/sid
>   APT prefers stable
>   APT policy: (990, 'stable')
> Architecture: i386 (i686)
> 
> Kernel: Linux 2.6.34-1-686 (SMP w/2 CPU cores)
> Locale: LANG=de_DE.UTF-8, LC_CTYPE=ja_JP.UTF-8 (charmap=UTF-8)
> Shell: /bin/sh linked to /bin/bash
> 
> Versions of packages linux-image-2.6.34-1-686 depends on:
> ii  debconf [debconf 1.5.24                  Debian configuration management sy
> ii  initramfs-tools  0.92o                   tools for generating an initramfs
> ii  linux-base       2.6.34-1~experimental.1 Linux image base package
> ii  module-init-tool 3.4-1                   tools for managing Linux kernel mo
> 
> Versions of packages linux-image-2.6.34-1-686 recommends:
> pn  firmware-linux-free         <none>       (no description available)
> ii  libc6-i686                  2.7-18lenny4 GNU C Library: Shared libraries [i
> 
> Versions of packages linux-image-2.6.34-1-686 suggests:
> ii  grub                       0.97-47lenny2 GRand Unified Bootloader (Legacy v
> pn  linux-doc-2.6.34           <none>        (no description available)
> 
> Versions of packages linux-image-2.6.34-1-686 is related to:
> pn  firmware-bnx2                 <none>     (no description available)
> pn  firmware-bnx2x                <none>     (no description available)
> pn  firmware-ipw2x00              <none>     (no description available)
> pn  firmware-ivtv                 <none>     (no description available)
> pn  firmware-iwlwifi              <none>     (no description available)
> pn  firmware-linux                <none>     (no description available)
> pn  firmware-linux-nonfree        <none>     (no description available)
> pn  firmware-qlogic               <none>     (no description available)
> pn  firmware-ralink               <none>     (no description available)
> pn  xen-hypervisor                <none>     (no description available)
> 
> -- debconf information excluded

-- 
Ben Hutchings
Once a job is fouled up, anything done to improve it makes it worse.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply

* [PATCH] compat-wireless: fix build of ath5k for CONFIG_PM_SLEEP=n
From: Hauke Mehrtens @ 2010-07-11 20:23 UTC (permalink / raw)
  To: lrodriguez; +Cc: linux-wireless, mcgrof, philipp_subx, Hauke Mehrtens

suspend and resume are activated in ath5k if CONFIG_PM_SLEEP is set and
not if just CONFIG_PM is set.

This should fix the problems reported by Philip Prindeville.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
 patches/11-dev-pm-ops.patch |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/patches/11-dev-pm-ops.patch b/patches/11-dev-pm-ops.patch
index 3e97ed9..688da84 100644
--- a/patches/11-dev-pm-ops.patch
+++ b/patches/11-dev-pm-ops.patch
@@ -49,7 +49,7 @@ calls on compat code with only slight modifications.
  	.remove		= __devexit_p(ath5k_pci_remove),
 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
  	.driver.pm	= ATH5K_PM_OPS,
-+#elif defined(CONFIG_PM)
++#elif defined(CONFIG_PM_SLEEP)
 +	.suspend        = ath5k_pci_suspend_compat,
 +	.resume         = ath5k_pci_resume_compat,
 +#endif
-- 
1.7.0.4


^ permalink raw reply related

* Compat-wireless release for 2010-07-11 is baked
From: Compat-wireless cronjob account @ 2010-07-11 19:02 UTC (permalink / raw)
  To: linux-wireless


compat-wireless code metrics

    495293 - Total upstream lines of code being pulled
      1419 - backport code changes
      1186 - backport code additions
       233 - backport code deletions
      5766 - backport from compat module
      7185 - total backport code
    1.4507 - % of code consists of backport work
      1218 - Crap changes not yet posted
      1179 - Crap additions not yet posted
        39 - Crap deletions not yet posted
    0.2459 - % of crap code

Base tree: linux-next.git
Base tree version: next-20100709
compat-wireless release: compat-wireless-2010-07-08-2-gbea1297

^ permalink raw reply

* Re: Ath5k breaking in ath5k_pci_suspend_compat going on 2 weeks
From: Philip Prindeville @ 2010-07-11 17:53 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <4C395F03.40200@redfish-solutions.com>

The latest revision that I could build was 2010-06-02, and that panics 
the box:

ompat-wireless backport release: compat-wireles-20100526-1-g9a89e44
Backport based on linux-next.git next-20100526
cfg80211: Calling CRDA to update world regulatory domain
cfg80211: World regulatory domain updated:
     (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
     (2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
     (2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
     (2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm)
     (5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
     (5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm)
ath5k 0000:00:11.0: registered as 'phy0'
BUG: unable to handle kernel NULL pointer dereference at 00000000
IP: [<00000000>]
*pde = 00000000
Oops: 0000 [#1] PREEMPT
Modules linked in: ath5k(+) mac80211 ath cfg80211 rfkill_backport compat dahdi s
ha512_generic sha256_generic deflate zlib_deflate arc4 ecb sha1_generic blowfish
  des_generic cbc cryptosoft cryptodev(P) ocf(P) geodewdt geode_rng geode_aes cry
pto_blkcipher via_rhine rtc cs5535_gpio

Pid: 1438, comm: modprobe Tainted: P          (2.6.27.48-astlinux #1)
EIP: 0060:[<00000000>] EFLAGS: 00010286 CPU: 0
EIP is at 0x0
EAX: cea68000 EBX: cf9b3490 ECX: 00000000 EDX: 00000000
ESI: cea68154 EDI: cea83be0 EBP: cea68000 ESP: cea87cec
  DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068
Process modprobe (pid: 1438, ti=cea86000 task=cf994460 task.ti=cea86000)
Stack: c0259ceb cf9b3400 cea87cf4 cea87cf4 00000000 00000000 00000000 00000000
        00000000 00000000 00000000 000005dc cea68000 cea83be0 ffffffff 00000010
        c025a0e2 00000000 00000000 ffffffff 00000000 c034e8cc ffffffff 00000000
Call Trace:
  [<c0259ceb>] rtnl_fill_ifinfo+0x2a8/0x45e
  [<c025a0e2>] rtmsg_ifinfo+0x40/0xa7
  [<c025a17e>] rtnetlink_event+0x35/0x38
  [<c02aa0ab>] notifier_call_chain+0x2a/0x47
  [<c012716e>] raw_notifier_call_chain+0x9/0xc
  [<c0252ee8>] register_netdevice+0x228/0x25d
  [<d09449d3>] ieee80211_if_add+0x60e/0x704 [mac80211]
  [<c015fff4>] alloc_inode+0xda/0x150
  [<c01b8bd8>] debugfs_mknod+0x10d/0x119
  [<c0115cfb>] printk+0x14/0x18
  [<d09453eb>] ieee80211_init_rate_ctrl_alg+0x18b/0x1b4 [mac80211]
  [<d093992a>] ieee80211_register_hw+0x28c/0x320 [mac80211]
  [<d08c6742>] ath5k_pci_probe+0xb03/0xde2 [ath5k]
  [<c01da23c>] pci_device_probe+0x36/0x55
  [<c01f7f8b>] driver_probe_device+0x9c/0x112
  [<c01f8038>] __driver_attach+0x37/0x55
  [<c01f7911>] bus_for_each_dev+0x31/0x52
  [<c01f7e3f>] driver_attach+0x11/0x13
  [<c01f8001>] __driver_attach+0x0/0x55
  [<c01f7c5d>] bus_add_driver+0x91/0x194
  [<d086e000>] init_ath5k_pci+0x0/0x2f [ath5k]
  [<c01f8239>] driver_register+0x6d/0xc2
  [<d086e000>] init_ath5k_pci+0x0/0x2f [ath5k]
  [<c01da2fe>] __pci_register_driver+0x35/0x60
  [<d086e01a>] init_ath5k_pci+0x1a/0x2f [ath5k]
  [<c0101037>] _stext+0x37/0xfb
  [<c013068d>] sys_init_module+0x87/0x176
  [<c01037e6>] syscall_call+0x7/0xb
  =======================
Code:  Bad EIP value.
EIP: [<00000000>] 0x0 SS:ESP 0068:cea87cec
---[ end trace d08207f47ddcaa64 ]---
/etc/runlevels/default/S02wifi: line 11:  1438 Segmentation fault      modprobe
$i
Configuring WiFi cards...





On 7/11/10 12:04 AM, Philip Prindeville wrote:
> I take it back... it seems to go back at least to 2010-06-12.
>
>
> On 7/10/10 8:05 PM, Philip Prindeville wrote:
>> This still seems to be broken, a couple of weeks later:
>>
>>   CC [M]  
>> /home/philipp/kernel/build_i586/compat-wireless-2010-06-26/drivers/net/wireless/ath/ath5k/attach.o 
>>
>>   CC [M]  
>> /home/philipp/kernel/build_i586/compat-wireless-2010-06-26/drivers/net/wireless/ath/ath5k/base.o 
>>
>> /home/philipp/kernel/build_i586/compat-wireless-2010-06-26/drivers/net/wireless/ath/ath5k/base.c:243: 
>> error: 'ath5k_pci_suspend_compat' undeclared here (not in a function)
>> /home/philipp/kernel/build_i586/compat-wireless-2010-06-26/drivers/net/wireless/ath/ath5k/base.c:244: 
>> error: 'ath5k_pci_resume_compat' undeclared here (not in a function)
>> make[6]: *** 
>> [/home/philipp/kernel/build_i586/compat-wireless-2010-06-26/drivers/net/wireless/ath/ath5k/base.o] 
>> Error 1
>> make[5]: *** 
>> [/home/philipp/kernel/build_i586/compat-wireless-2010-06-26/drivers/net/wireless/ath/ath5k] 
>> Error 2
>> make[4]: *** 
>> [/home/philipp/kernel/build_i586/compat-wireless-2010-06-26/drivers/net/wireless/ath] 
>> Error 2
>> make[3]: *** 
>> [/home/philipp/kernel/build_i586/compat-wireless-2010-06-26/drivers/net/wireless] 
>> Error 2
>>
>>
>> and from today's tarball:
>>
>>
>>   CC [M]  
>> /home/philipp/kernel/build_i586/compat-wireless-2010-07-10/drivers/net/wireless/ath/ath5k/base.o 
>>
>> /home/philipp/kernel/build_i586/compat-wireless-2010-07-10/drivers/net/wireless/ath/ath5k/base.c:243: 
>> error: 'ath5k_pci_suspend_compat' undeclared here (not in a function)
>> /home/philipp/kernel/build_i586/compat-wireless-2010-07-10/drivers/net/wireless/ath/ath5k/base.c:244: 
>> error: 'ath5k_pci_resume_compat' undeclared here (not in a function)
>> make[6]: *** 
>> [/home/philipp/kernel/build_i586/compat-wireless-2010-07-10/drivers/net/wireless/ath/ath5k/base.o] 
>> Error 1
>> make[5]: *** 
>> [/home/philipp/kernel/build_i586/compat-wireless-2010-07-10/drivers/net/wireless/ath/ath5k] 
>> Error 2
>> make[4]: *** 
>> [/home/philipp/kernel/build_i586/compat-wireless-2010-07-10/drivers/net/wireless/ath] 
>> Error 2
>> make[3]: *** 
>> [/home/philipp/kernel/build_i586/compat-wireless-2010-07-10/drivers/net/wireless] 
>> Error 2
>>
>>
>> Can someone please have a look and fix their regression?
>>
>> Thanks,
>>
>> -Philip
>


^ permalink raw reply

* [PATCH] ath9k: merge noisefloor load implementations
From: Felix Fietkau @ 2010-07-11 13:44 UTC (permalink / raw)
  To: linux-wireless; +Cc: Luis R. Rodriguez, John W. Linville

AR5008+ and AR9003 currently use two separate implementations of the
ath9k_hw_loadnf function. There are three main differences:

 - PHY registers for AR9003 are different
 - AR9003 always uses 3 chains, earlier versions are more selective
 - The AR9003 variant contains a fix for NF load timeouts

This patch merges the two implementations into one, storing the
register array in the ath_hw struct. The fix for NF load timeouts is
not just relevant for AR9003, but also important for earlier hardware,
so it's better to just keep one common implementation.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -1518,77 +1518,6 @@ static void ar5008_hw_do_getnf(struct at
 	nfarray[5] = sign_extend(nf, 9);
 }
 
-static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	struct ath9k_nfcal_hist *h;
-	int i, j;
-	int32_t val;
-	const u32 ar5416_cca_regs[6] = {
-		AR_PHY_CCA,
-		AR_PHY_CH1_CCA,
-		AR_PHY_CH2_CCA,
-		AR_PHY_EXT_CCA,
-		AR_PHY_CH1_EXT_CCA,
-		AR_PHY_CH2_EXT_CCA
-	};
-	u8 chainmask, rx_chain_status;
-
-	rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK);
-	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
-		chainmask = 0x9;
-	else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
-		if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4))
-			chainmask = 0x1B;
-		else
-			chainmask = 0x09;
-	} else {
-		if (rx_chain_status & 0x4)
-			chainmask = 0x3F;
-		else if (rx_chain_status & 0x2)
-			chainmask = 0x1B;
-		else
-			chainmask = 0x09;
-	}
-
-	h = ah->nfCalHist;
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		if (chainmask & (1 << i)) {
-			val = REG_READ(ah, ar5416_cca_regs[i]);
-			val &= 0xFFFFFE00;
-			val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
-			REG_WRITE(ah, ar5416_cca_regs[i], val);
-		}
-	}
-
-	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_ENABLE_NF);
-	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
-
-	for (j = 0; j < 5; j++) {
-		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
-		     AR_PHY_AGC_CONTROL_NF) == 0)
-			break;
-		udelay(50);
-	}
-
-	ENABLE_REGWRITE_BUFFER(ah);
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		if (chainmask & (1 << i)) {
-			val = REG_READ(ah, ar5416_cca_regs[i]);
-			val &= 0xFFFFFE00;
-			val |= (((u32) (-50) << 1) & 0x1ff);
-			REG_WRITE(ah, ar5416_cca_regs[i], val);
-		}
-	}
-
-	REGWRITE_BUFFER_FLUSH(ah);
-	DISABLE_REGWRITE_BUFFER(ah);
-}
-
 /*
  * Initialize the ANI register values with default (ini) values.
  * This routine is called during a (full) hardware reset after
@@ -1666,6 +1595,14 @@ static void ar5008_hw_set_nf_limits(stru
 void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
 {
 	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+	const u32 ar5416_cca_regs[6] = {
+		AR_PHY_CCA,
+		AR_PHY_CH1_CCA,
+		AR_PHY_CH2_CCA,
+		AR_PHY_EXT_CCA,
+		AR_PHY_CH1_EXT_CCA,
+		AR_PHY_CH2_EXT_CCA
+	};
 
 	priv_ops->rf_set_freq = ar5008_hw_set_channel;
 	priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
@@ -1685,7 +1622,6 @@ void ar5008_hw_attach_phy_ops(struct ath
 	priv_ops->restore_chainmask = ar5008_restore_chainmask;
 	priv_ops->set_diversity = ar5008_set_diversity;
 	priv_ops->do_getnf = ar5008_hw_do_getnf;
-	priv_ops->loadnf = ar5008_hw_loadnf;
 
 	if (modparam_force_new_ani) {
 		priv_ops->ani_control = ar5008_hw_ani_control_new;
@@ -1701,4 +1637,5 @@ void ar5008_hw_attach_phy_ops(struct ath
 		priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
 
 	ar5008_hw_set_nf_limits(ah);
+	memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs));
 }
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1050,106 +1050,6 @@ static void ar9003_hw_set_nf_limits(stru
 }
 
 /*
- * Find out which of the RX chains are enabled
- */
-static u32 ar9003_hw_get_rx_chainmask(struct ath_hw *ah)
-{
-	u32 chain = REG_READ(ah, AR_PHY_RX_CHAINMASK);
-	/*
-	 * The bits [2:0] indicate the rx chain mask and are to be
-	 * interpreted as follows:
-	 * 00x => Only chain 0 is enabled
-	 * 01x => Chain 1 and 0 enabled
-	 * 1xx => Chain 2,1 and 0 enabled
-	 */
-	return chain & 0x7;
-}
-
-static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
-{
-	struct ath9k_nfcal_hist *h;
-	unsigned i, j;
-	int32_t val;
-	const u32 ar9300_cca_regs[6] = {
-		AR_PHY_CCA_0,
-		AR_PHY_CCA_1,
-		AR_PHY_CCA_2,
-		AR_PHY_EXT_CCA,
-		AR_PHY_EXT_CCA_1,
-		AR_PHY_EXT_CCA_2,
-	};
-	u8 chainmask, rx_chain_status;
-	struct ath_common *common = ath9k_hw_common(ah);
-
-	rx_chain_status = ar9003_hw_get_rx_chainmask(ah);
-
-	chainmask = 0x3F;
-	h = ah->nfCalHist;
-
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		if (chainmask & (1 << i)) {
-			val = REG_READ(ah, ar9300_cca_regs[i]);
-			val &= 0xFFFFFE00;
-			val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
-			REG_WRITE(ah, ar9300_cca_regs[i], val);
-		}
-	}
-
-	/*
-	 * Load software filtered NF value into baseband internal minCCApwr
-	 * variable.
-	 */
-	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_ENABLE_NF);
-	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
-		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
-	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
-
-	/*
-	 * Wait for load to complete, should be fast, a few 10s of us.
-	 * The max delay was changed from an original 250us to 10000us
-	 * since 250us often results in NF load timeout and causes deaf
-	 * condition during stress testing 12/12/2009
-	 */
-	for (j = 0; j < 1000; j++) {
-		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
-		     AR_PHY_AGC_CONTROL_NF) == 0)
-			break;
-		udelay(10);
-	}
-
-	/*
-	 * We timed out waiting for the noisefloor to load, probably due to an
-	 * in-progress rx. Simply return here and allow the load plenty of time
-	 * to complete before the next calibration interval.  We need to avoid
-	 * trying to load -50 (which happens below) while the previous load is
-	 * still in progress as this can cause rx deafness. Instead by returning
-	 * here, the baseband nf cal will just be capped by our present
-	 * noisefloor until the next calibration timer.
-	 */
-	if (j == 1000) {
-		ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf "
-			  "to load: AR_PHY_AGC_CONTROL=0x%x\n",
-			  REG_READ(ah, AR_PHY_AGC_CONTROL));
-		return;
-	}
-
-	/*
-	 * Restore maxCCAPower register parameter again so that we're not capped
-	 * by the median we just loaded.  This will be initial (and max) value
-	 * of next noise floor calibration the baseband does.
-	 */
-	for (i = 0; i < NUM_NF_READINGS; i++) {
-		if (chainmask & (1 << i)) {
-			val = REG_READ(ah, ar9300_cca_regs[i]);
-			val &= 0xFFFFFE00;
-			val |= (((u32) (-50) << 1) & 0x1ff);
-			REG_WRITE(ah, ar9300_cca_regs[i], val);
-		}
-	}
-}
-
-/*
  * Initialize the ANI register values with default (ini) values.
  * This routine is called during a (full) hardware reset after
  * all the registers are initialised from the INI.
@@ -1216,6 +1116,14 @@ static void ar9003_hw_ani_cache_ini_regs
 void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
 {
 	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+	const u32 ar9300_cca_regs[6] = {
+		AR_PHY_CCA_0,
+		AR_PHY_CCA_1,
+		AR_PHY_CCA_2,
+		AR_PHY_EXT_CCA,
+		AR_PHY_EXT_CCA_1,
+		AR_PHY_EXT_CCA_2,
+	};
 
 	priv_ops->rf_set_freq = ar9003_hw_set_channel;
 	priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate;
@@ -1232,10 +1140,10 @@ void ar9003_hw_attach_phy_ops(struct ath
 	priv_ops->set_diversity = ar9003_hw_set_diversity;
 	priv_ops->ani_control = ar9003_hw_ani_control;
 	priv_ops->do_getnf = ar9003_hw_do_getnf;
-	priv_ops->loadnf = ar9003_hw_loadnf;
 	priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
 
 	ar9003_hw_set_nf_limits(ah);
+	memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs));
 }
 
 void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -167,6 +167,100 @@ void ath9k_hw_start_nfcal(struct ath_hw 
 	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
 }
 
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+	struct ath9k_nfcal_hist *h;
+	unsigned i, j;
+	int32_t val;
+	u8 chainmask;
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (AR_SREV_9300_20_OR_LATER(ah))
+		chainmask = 0x3F;
+	else if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+		chainmask = 0x9;
+	else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) {
+		if ((ah->rxchainmask & 0x2) || (ah->rxchainmask & 0x4))
+			chainmask = 0x1B;
+		else
+			chainmask = 0x09;
+	} else {
+		if (ah->rxchainmask & 0x4)
+			chainmask = 0x3F;
+		else if (ah->rxchainmask & 0x2)
+			chainmask = 0x1B;
+		else
+			chainmask = 0x09;
+	}
+	h = ah->nfCalHist;
+
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		if (chainmask & (1 << i)) {
+			val = REG_READ(ah, ah->nf_regs[i]);
+			val &= 0xFFFFFE00;
+			val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
+			REG_WRITE(ah, ah->nf_regs[i], val);
+		}
+	}
+
+	/*
+	 * Load software filtered NF value into baseband internal minCCApwr
+	 * variable.
+	 */
+	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_ENABLE_NF);
+	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+	/*
+	 * Wait for load to complete, should be fast, a few 10s of us.
+	 * The max delay was changed from an original 250us to 10000us
+	 * since 250us often results in NF load timeout and causes deaf
+	 * condition during stress testing 12/12/2009
+	 */
+	for (j = 0; j < 1000; j++) {
+		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
+		     AR_PHY_AGC_CONTROL_NF) == 0)
+			break;
+		udelay(10);
+	}
+
+	/*
+	 * We timed out waiting for the noisefloor to load, probably due to an
+	 * in-progress rx. Simply return here and allow the load plenty of time
+	 * to complete before the next calibration interval.  We need to avoid
+	 * trying to load -50 (which happens below) while the previous load is
+	 * still in progress as this can cause rx deafness. Instead by returning
+	 * here, the baseband nf cal will just be capped by our present
+	 * noisefloor until the next calibration timer.
+	 */
+	if (j == 1000) {
+		ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf "
+			  "to load: AR_PHY_AGC_CONTROL=0x%x\n",
+			  REG_READ(ah, AR_PHY_AGC_CONTROL));
+		return;
+	}
+
+	/*
+	 * Restore maxCCAPower register parameter again so that we're not capped
+	 * by the median we just loaded.  This will be initial (and max) value
+	 * of next noise floor calibration the baseband does.
+	 */
+	ENABLE_REGWRITE_BUFFER(ah);
+	for (i = 0; i < NUM_NF_READINGS; i++) {
+		if (chainmask & (1 << i)) {
+			val = REG_READ(ah, ah->nf_regs[i]);
+			val &= 0xFFFFFE00;
+			val |= (((u32) (-50) << 1) & 0x1ff);
+			REG_WRITE(ah, ah->nf_regs[i], val);
+		}
+	}
+	REGWRITE_BUFFER_FLUSH(ah);
+	DISABLE_REGWRITE_BUFFER(ah);
+}
+
+
 static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -109,6 +109,7 @@ struct ath9k_pacal_info{
 
 bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
 void ath9k_hw_start_nfcal(struct ath_hw *ah);
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
 int16_t ath9k_hw_getnf(struct ath_hw *ah,
 		       struct ath9k_channel *chan);
 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -264,12 +264,6 @@ static inline void ath9k_hw_do_getnf(str
 	ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray);
 }
 
-static inline void ath9k_hw_loadnf(struct ath_hw *ah,
-				   struct ath9k_channel *chan)
-{
-	ath9k_hw_private_ops(ah)->loadnf(ah, chan);
-}
-
 static inline bool ath9k_hw_init_cal(struct ath_hw *ah,
 				     struct ath9k_channel *chan)
 {
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -510,7 +510,6 @@ struct ath_gen_timer_table {
  *	AR_RTC_PLL_CONTROL for a given channel
  * @setup_calibration: set up calibration
  * @iscal_supported: used to query if a type of calibration is supported
- * @loadnf: load noise floor read from each chain on the CCA registers
  *
  * @ani_reset: reset ANI parameters to default values
  * @ani_lower_immunity: lower the noise immunity level. The level controls
@@ -564,7 +563,6 @@ struct ath_hw_private_ops {
 	bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
 			    int param);
 	void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
-	void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan);
 
 	/* ANI */
 	void (*ani_reset)(struct ath_hw *ah, bool is_scanning);
@@ -658,6 +656,7 @@ struct ath_hw {
 	bool need_an_top2_fixup;
 	u16 tx_trig_level;
 
+	u32 nf_regs[6];
 	struct ath_nf_limits nf_2g;
 	struct ath_nf_limits nf_5g;
 	u16 rfsilent;

^ permalink raw reply

* [PATCH 2/7] ath9k_hw: fix a sign error in the IQ calibration code
From: Felix Fietkau @ 2010-07-11 10:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: lrodriguez, linville
In-Reply-To: <1278845325-62000-1-git-send-email-nbd@openwrt.org>

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: stable@kernel.org
---
 drivers/net/wireless/ath/ath9k/ar9002_calib.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 5fdbb53..dabafb8 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -239,7 +239,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
 			if (qCoff > 15)
 				qCoff = 15;
 			else if (qCoff <= -16)
-				qCoff = 16;
+				qCoff = -16;
 
 			ath_print(common, ATH_DBG_CALIBRATE,
 				  "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n",
-- 
1.6.4.2


^ permalink raw reply related

* [PATCH 4/7] ath9k_hw: prevent a fast channel change after a rx DMA stuck issue
From: Felix Fietkau @ 2010-07-11 10:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: lrodriguez, linville
In-Reply-To: <1278845325-62000-3-git-send-email-nbd@openwrt.org>

If the receive path gets stuck, a full hardware reset is necessary to
recover from it. If this happens during a scan, the whole scan might fail,
as each channel change bypasses the full reset sequence.
Fix this by resetting the fast channel change flag if stopping the
receive path fails.

This will reduce the number of error messages that look like this:
ath: DMA failed to stop in 10 ms AR_CR=0x00000024 AR_DIAG_SW=0x40000020

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: stable@kernel.org
---
 drivers/net/wireless/ath/ath9k/hw.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2acd799..2f83f97 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1232,9 +1232,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 	if (!ah->chip_fullsleep) {
 		ath9k_hw_abortpcurecv(ah);
-		if (!ath9k_hw_stopdmarecv(ah))
+		if (!ath9k_hw_stopdmarecv(ah)) {
 			ath_print(common, ATH_DBG_XMIT,
 				"Failed to stop receive dma\n");
+			bChannelChange = false;
+		}
 	}
 
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
-- 
1.6.4.2


^ permalink raw reply related

* [PATCH 7/7] ath9k_hw: handle an rx key miss properly
From: Felix Fietkau @ 2010-07-11 10:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: lrodriguez, linville
In-Reply-To: <1278845325-62000-6-git-send-email-nbd@openwrt.org>

If the hardware reports an rx key miss, then the frame has not been
decrypted at all, and this must be recognized by the software, otherwise
mac80211 can generate bogus MIC failure events.

Fix this by reporting an invalid key index if a key miss is detected
in the rx status.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: stable@kernel.org
---
 drivers/net/wireless/ath/ath9k/ar9003_mac.c |    3 +++
 drivers/net/wireless/ath/ath9k/mac.c        |    2 ++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 06ef710..9de8554 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -578,6 +578,9 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
 	if (rxsp->status11 & AR_DecryptBusyErr)
 		rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
 
+	if (rxsp->status11 & AR_KeyMiss)
+		rxs->rs_keyix = ATH9K_RXKEYIX_INVALID;
+
 	if ((rxsp->status11 & AR_RxFrameOK) == 0) {
 		if (rxsp->status11 & AR_CRCErr) {
 			rxs->rs_status |= ATH9K_RXERR_CRC;
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index e955bb9..8d0bb5a 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -701,6 +701,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
 		rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
 	if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
 		rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
+	if (ads.ds_rxstatus8 & AR_KeyMiss)
+		rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
 
 	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
 		if (ads.ds_rxstatus8 & AR_CRCErr)
-- 
1.6.4.2


^ permalink raw reply related

* [PATCH 5/7] ath9k_hw: report the TID in the tx status on AR5008-AR9002
From: Felix Fietkau @ 2010-07-11 10:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: lrodriguez, linville
In-Reply-To: <1278845325-62000-4-git-send-email-nbd@openwrt.org>

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
 drivers/net/wireless/ath/ath9k/ar9002_mac.c |    1 +
 drivers/net/wireless/ath/ath9k/ar9003_mac.h |    3 ---
 drivers/net/wireless/ath/ath9k/mac.h        |    3 +++
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 2be20d2..50dda39 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -287,6 +287,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 	ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
 	ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
 	ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
+	ts->tid = MS(ads->ds_txstatus9, AR_TxTid);
 	ts->ts_antenna = 0;
 
 	return 0;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h
index f76f27d..9f2cea7 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h
@@ -33,9 +33,6 @@
 #define AR_TxDescId_S	16
 #define AR_TxPtrChkSum	0x0000ffff
 
-#define AR_TxTid	0xf0000000
-#define AR_TxTid_S	28
-
 #define AR_LowRxChain	0x00004000
 
 #define AR_Not_Sounding	0x20000000
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 7559fb2..2633896 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -485,6 +485,9 @@ struct ar5416_desc {
 #define AR_TxRSSICombined   0xff000000
 #define AR_TxRSSICombined_S 24
 
+#define AR_TxTid	0xf0000000
+#define AR_TxTid_S	28
+
 #define AR_TxEVM0           ds_txstatus5
 #define AR_TxEVM1           ds_txstatus6
 #define AR_TxEVM2           ds_txstatus7
-- 
1.6.4.2


^ permalink raw reply related

* [PATCH 1/7] ath9k_hw: fix antenna diversity on AR9285
From: Felix Fietkau @ 2010-07-11 10:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: lrodriguez, linville

On AR9285, the antenna switch configuration register uses more than just
16 bits. Because of an arbitrary mask applied to the EEPROM value that
stores this configuration, diversity was broken in some cases, leading
to a significant degradation in signal strength.
Fix this by changing the callback to return a 32 bit value and remove
the arbitrary mask.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: stable@kernel.org
---
 drivers/net/wireless/ath/ath9k/ar9003_eeprom.c |    2 +-
 drivers/net/wireless/ath/ath9k/eeprom.h        |    2 +-
 drivers/net/wireless/ath/ath9k/eeprom_4k.c     |    4 ++--
 drivers/net/wireless/ath/ath9k/eeprom_9287.c   |    4 ++--
 drivers/net/wireless/ath/ath9k/eeprom_def.c    |    4 ++--
 5 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 343c9a4..ace8d26 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -951,7 +951,7 @@ static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
 	return 1;
 }
 
-static u16 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
+static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
 						  struct ath9k_channel *chan)
 {
 	return -EINVAL;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index bdd8aa0..8750c55 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -670,7 +670,7 @@ struct eeprom_ops {
 	int (*get_eeprom_ver)(struct ath_hw *hw);
 	int (*get_eeprom_rev)(struct ath_hw *hw);
 	u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band);
-	u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
+	u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
 				      struct ath9k_channel *chan);
 	void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
 	void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index e25a2ab..afafc4d 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -1150,13 +1150,13 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
 	}
 }
 
-static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
+static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
 					      struct ath9k_channel *chan)
 {
 	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
 	struct modal_eep_4k_header *pModal = &eep->modalHeader;
 
-	return pModal->antCtrlCommon & 0xFFFF;
+	return pModal->antCtrlCommon;
 }
 
 static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 39a4105..37207df 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -1130,13 +1130,13 @@ static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah,
 	return 1;
 }
 
-static u16 ath9k_hw_ar9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
+static u32 ath9k_hw_ar9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
 						  struct ath9k_channel *chan)
 {
 	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
 	struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
 
-	return pModal->antCtrlCommon & 0xFFFF;
+	return pModal->antCtrlCommon;
 }
 
 static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 77b1433..60480a1 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -1438,14 +1438,14 @@ static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
 	return num_ant_config;
 }
 
-static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
+static u32 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
 					       struct ath9k_channel *chan)
 {
 	struct ar5416_eeprom_def *eep = &ah->eeprom.def;
 	struct modal_eep_header *pModal =
 		&(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
 
-	return pModal->antCtrlCommon & 0xFFFF;
+	return pModal->antCtrlCommon;
 }
 
 static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
-- 
1.6.4.2


^ permalink raw reply related

* [PATCH 3/7] ath9k_hw: fix an off-by-one error in the PDADC boundaries calculation
From: Felix Fietkau @ 2010-07-11 10:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: lrodriguez, linville
In-Reply-To: <1278845325-62000-2-git-send-email-nbd@openwrt.org>

PDADC values were only generated for values surrounding the target
index, however not for the target index itself, leading to a minor
error in the generated curve.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: stable@kernel.org
---
 drivers/net/wireless/ath/ath9k/eeprom_def.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 60480a1..02e6c2a 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -730,7 +730,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
 				    vpdTableI[i][sizeCurrVpdTable - 2]);
 		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
 
-		if (tgtIndex > maxIndex) {
+		if (tgtIndex >= maxIndex) {
 			while ((ss <= tgtIndex) &&
 			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
 				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
-- 
1.6.4.2


^ permalink raw reply related

* [PATCH 6/7] ath9k: validate the TID in the tx status information
From: Felix Fietkau @ 2010-07-11 10:48 UTC (permalink / raw)
  To: linux-wireless; +Cc: lrodriguez, linville
In-Reply-To: <1278845325-62000-5-git-send-email-nbd@openwrt.org>

Occasionally the hardware can send out tx status information with the wrong
TID. In that case, the BA status cannot be trusted and the aggregate
must be retransmitted.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
 drivers/net/wireless/ath/ath9k/xmit.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 05ec36a..bd52ac1 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -355,6 +355,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	an = (struct ath_node *)sta->drv_priv;
 	tid = ATH_AN_2_TID(an, bf->bf_tidno);
 
+	/*
+	 * The hardware occasionally sends a tx status for the wrong TID.
+	 * In this case, the BA status cannot be considered valid and all
+	 * subframes need to be retransmitted
+	 */
+	if (bf->bf_tidno != ts->tid)
+		txok = false;
+
 	isaggr = bf_isaggr(bf);
 	memset(ba, 0, WME_BA_BMP_SIZE >> 3);
 
-- 
1.6.4.2


^ permalink raw reply related

* [PATCH 17/17] rt2x00: Move driver callback functions into the ops structure
From: Ivo van Doorn @ 2010-07-11 10:31 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111230.38605.IvDoorn@gmail.com>

All callback functions are gathered in rt2x00dev->ops except
for the callback functions which are used in rt2800lib to
acces rt2800pci/usb.

Move the priv pointer from rt2x00dev to rt2x00dev->ops and
rename it to drv to make it obvious that it is the driver callback
structure.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.h |   18 +++++++++---------
 drivers/net/wireless/rt2x00/rt2800pci.c |   30 +++++++++++++-----------------
 drivers/net/wireless/rt2x00/rt2800usb.c |   30 +++++++++++++-----------------
 drivers/net/wireless/rt2x00/rt2x00.h    |    6 +-----
 4 files changed, 36 insertions(+), 48 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index cecbd3a..091641e 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -50,7 +50,7 @@ static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
 					const unsigned int offset,
 					u32 *value)
 {
-	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
 	rt2800ops->register_read(rt2x00dev, offset, value);
 }
@@ -59,7 +59,7 @@ static inline void rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
 					     const unsigned int offset,
 					     u32 *value)
 {
-	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
 	rt2800ops->register_read_lock(rt2x00dev, offset, value);
 }
@@ -68,7 +68,7 @@ static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
 					 const unsigned int offset,
 					 u32 value)
 {
-	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
 	rt2800ops->register_write(rt2x00dev, offset, value);
 }
@@ -77,7 +77,7 @@ static inline void rt2800_register_write_lock(struct rt2x00_dev *rt2x00dev,
 					      const unsigned int offset,
 					      u32 value)
 {
-	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
 	rt2800ops->register_write_lock(rt2x00dev, offset, value);
 }
@@ -86,7 +86,7 @@ static inline void rt2800_register_multiread(struct rt2x00_dev *rt2x00dev,
 					     const unsigned int offset,
 					     void *value, const u32 length)
 {
-	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
 	rt2800ops->register_multiread(rt2x00dev, offset, value, length);
 }
@@ -96,7 +96,7 @@ static inline void rt2800_register_multiwrite(struct rt2x00_dev *rt2x00dev,
 					      const void *value,
 					      const u32 length)
 {
-	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
 	rt2800ops->register_multiwrite(rt2x00dev, offset, value, length);
 }
@@ -106,7 +106,7 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,
 				      const struct rt2x00_field32 field,
 				      u32 *reg)
 {
-	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
 	return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg);
 }
@@ -114,14 +114,14 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,
 static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev,
 					    const u8 *data, const size_t len)
 {
-	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
 	return rt2800ops->drv_write_firmware(rt2x00dev, data, len);
 }
 
 static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev)
 {
-	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
 
 	return rt2800ops->drv_init_registers(rt2x00dev);
 }
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 0fdd58b..39b3846 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -926,27 +926,10 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 	return rt2800_validate_eeprom(rt2x00dev);
 }
 
-static const struct rt2800_ops rt2800pci_rt2800_ops = {
-	.register_read		= rt2x00pci_register_read,
-	.register_read_lock	= rt2x00pci_register_read, /* same for PCI */
-	.register_write		= rt2x00pci_register_write,
-	.register_write_lock	= rt2x00pci_register_write, /* same for PCI */
-
-	.register_multiread	= rt2x00pci_register_multiread,
-	.register_multiwrite	= rt2x00pci_register_multiwrite,
-
-	.regbusy_read		= rt2x00pci_regbusy_read,
-
-	.drv_write_firmware	= rt2800pci_write_firmware,
-	.drv_init_registers	= rt2800pci_init_registers,
-};
-
 static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
 	int retval;
 
-	rt2x00dev->priv = (void *)&rt2800pci_rt2800_ops;
-
 	/*
 	 * Allocate eeprom data.
 	 */
@@ -1018,6 +1001,18 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
 	.ampdu_action		= rt2800_ampdu_action,
 };
 
+static const struct rt2800_ops rt2800pci_rt2800_ops = {
+	.register_read		= rt2x00pci_register_read,
+	.register_read_lock	= rt2x00pci_register_read, /* same for PCI */
+	.register_write		= rt2x00pci_register_write,
+	.register_write_lock	= rt2x00pci_register_write, /* same for PCI */
+	.register_multiread	= rt2x00pci_register_multiread,
+	.register_multiwrite	= rt2x00pci_register_multiwrite,
+	.regbusy_read		= rt2x00pci_regbusy_read,
+	.drv_write_firmware	= rt2800pci_write_firmware,
+	.drv_init_registers	= rt2800pci_init_registers,
+};
+
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.irq_handler		= rt2800pci_interrupt,
 	.irq_handler_thread	= rt2800pci_interrupt_thread,
@@ -1082,6 +1077,7 @@ static const struct rt2x00_ops rt2800pci_ops = {
 	.tx			= &rt2800pci_queue_tx,
 	.bcn			= &rt2800pci_queue_bcn,
 	.lib			= &rt2800pci_rt2x00_ops,
+	.drv			= &rt2800pci_rt2800_ops,
 	.hw			= &rt2800pci_mac80211_ops,
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 	.debugfs		= &rt2800_rt2x00debug,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 7b8d51f..5a2dfe8 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -470,27 +470,10 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 	return rt2800_validate_eeprom(rt2x00dev);
 }
 
-static const struct rt2800_ops rt2800usb_rt2800_ops = {
-	.register_read		= rt2x00usb_register_read,
-	.register_read_lock	= rt2x00usb_register_read_lock,
-	.register_write		= rt2x00usb_register_write,
-	.register_write_lock	= rt2x00usb_register_write_lock,
-
-	.register_multiread	= rt2x00usb_register_multiread,
-	.register_multiwrite	= rt2x00usb_register_multiwrite,
-
-	.regbusy_read		= rt2x00usb_regbusy_read,
-
-	.drv_write_firmware	= rt2800usb_write_firmware,
-	.drv_init_registers	= rt2800usb_init_registers,
-};
-
 static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
 	int retval;
 
-	rt2x00dev->priv = (void *)&rt2800usb_rt2800_ops;
-
 	/*
 	 * Allocate eeprom data.
 	 */
@@ -556,6 +539,18 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
 	.ampdu_action		= rt2800_ampdu_action,
 };
 
+static const struct rt2800_ops rt2800usb_rt2800_ops = {
+	.register_read		= rt2x00usb_register_read,
+	.register_read_lock	= rt2x00usb_register_read_lock,
+	.register_write		= rt2x00usb_register_write,
+	.register_write_lock	= rt2x00usb_register_write_lock,
+	.register_multiread	= rt2x00usb_register_multiread,
+	.register_multiwrite	= rt2x00usb_register_multiwrite,
+	.regbusy_read		= rt2x00usb_regbusy_read,
+	.drv_write_firmware	= rt2800usb_write_firmware,
+	.drv_init_registers	= rt2800usb_init_registers,
+};
+
 static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.probe_hw		= rt2800usb_probe_hw,
 	.get_firmware_name	= rt2800usb_get_firmware_name,
@@ -619,6 +614,7 @@ static const struct rt2x00_ops rt2800usb_ops = {
 	.tx			= &rt2800usb_queue_tx,
 	.bcn			= &rt2800usb_queue_bcn,
 	.lib			= &rt2800usb_rt2x00_ops,
+	.drv			= &rt2800usb_rt2800_ops,
 	.hw			= &rt2800usb_mac80211_ops,
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 	.debugfs		= &rt2800_rt2x00debug,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 9dd0d17..c21af38 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -621,6 +621,7 @@ struct rt2x00_ops {
 	const struct data_queue_desc *bcn;
 	const struct data_queue_desc *atim;
 	const struct rt2x00lib_ops *lib;
+	const void *drv;
 	const struct ieee80211_ops *hw;
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 	const struct rt2x00debug *debugfs;
@@ -881,11 +882,6 @@ struct rt2x00_dev {
 	 * and interrupt thread routine.
 	 */
 	u32 irqvalue[2];
-
-	/*
-	 * Driver specific data.
-	 */
-	void *priv;
 };
 
 /*
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 16/17] rt2x00: Move common firmware loading into rt2800lib
From: Ivo van Doorn @ 2010-07-11 10:30 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111230.14710.IvDoorn@gmail.com>

Large parts of the firmware initialization are shared
between rt2800pci and rt2800usb. Move this code into
rt2800lib.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |  155 +++++++++++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2800lib.h |   15 +++
 drivers/net/wireless/rt2x00/rt2800pci.c |  101 +-------------------
 drivers/net/wireless/rt2x00/rt2800usb.c |  119 +-----------------------
 4 files changed, 179 insertions(+), 211 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 9587236..b66e0fd 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -33,6 +33,7 @@
 	Abstract: rt2800 generic device routines.
  */
 
+#include <linux/crc-ccitt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -272,6 +273,160 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready);
 
+static bool rt2800_check_firmware_crc(const u8 *data, const size_t len)
+{
+	u16 fw_crc;
+	u16 crc;
+
+	/*
+	 * The last 2 bytes in the firmware array are the crc checksum itself,
+	 * this means that we should never pass those 2 bytes to the crc
+	 * algorithm.
+	 */
+	fw_crc = (data[len - 2] << 8 | data[len - 1]);
+
+	/*
+	 * Use the crc ccitt algorithm.
+	 * This will return the same value as the legacy driver which
+	 * used bit ordering reversion on the both the firmware bytes
+	 * before input input as well as on the final output.
+	 * Obviously using crc ccitt directly is much more efficient.
+	 */
+	crc = crc_ccitt(~0, data, len - 2);
+
+	/*
+	 * There is a small difference between the crc-itu-t + bitrev and
+	 * the crc-ccitt crc calculation. In the latter method the 2 bytes
+	 * will be swapped, use swab16 to convert the crc to the correct
+	 * value.
+	 */
+	crc = swab16(crc);
+
+	return fw_crc == crc;
+}
+
+int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
+			  const u8 *data, const size_t len)
+{
+	size_t offset = 0;
+	size_t fw_len;
+	bool multiple;
+
+	/*
+	 * PCI(e) & SOC devices require firmware with a length
+	 * of 8kb. USB devices require firmware files with a length
+	 * of 4kb. Certain USB chipsets however require different firmware,
+	 * which Ralink only provides attached to the original firmware
+	 * file. Thus for USB devices, firmware files have a length
+	 * which is a multiple of 4kb.
+	 */
+	if (rt2x00_is_usb(rt2x00dev)) {
+		fw_len = 4096;
+		multiple = true;
+	} else {
+		fw_len = 8192;
+		multiple = true;
+	}
+
+	/*
+	 * Validate the firmware length
+	 */
+	if (len != fw_len && (!multiple || (len % fw_len) != 0))
+		return FW_BAD_LENGTH;
+
+	/*
+	 * Check if the chipset requires one of the upper parts
+	 * of the firmware.
+	 */
+	if (rt2x00_is_usb(rt2x00dev) &&
+	    !rt2x00_rt(rt2x00dev, RT2860) &&
+	    !rt2x00_rt(rt2x00dev, RT2872) &&
+	    !rt2x00_rt(rt2x00dev, RT3070) &&
+	    ((len / fw_len) == 1))
+		return FW_BAD_VERSION;
+
+	/*
+	 * 8kb firmware files must be checked as if it were
+	 * 2 separate firmware files.
+	 */
+	while (offset < len) {
+		if (!rt2800_check_firmware_crc(data + offset, fw_len))
+			return FW_BAD_CRC;
+
+		offset += fw_len;
+	}
+
+	return FW_OK;
+}
+EXPORT_SYMBOL_GPL(rt2800_check_firmware);
+
+int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
+			 const u8 *data, const size_t len)
+{
+	unsigned int i;
+	u32 reg;
+
+	/*
+	 * Wait for stable hardware.
+	 */
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+		if (reg && reg != ~0)
+			break;
+		msleep(1);
+	}
+
+	if (i == REGISTER_BUSY_COUNT) {
+		ERROR(rt2x00dev, "Unstable hardware.\n");
+		return -EBUSY;
+	}
+
+	if (rt2x00_is_pci(rt2x00dev))
+		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
+
+	/*
+	 * Disable DMA, will be reenabled later when enabling
+	 * the radio.
+	 */
+	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
+	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
+	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+
+	/*
+	 * Write firmware to the device.
+	 */
+	rt2800_drv_write_firmware(rt2x00dev, data, len);
+
+	/*
+	 * Wait for device to stabilize.
+	 */
+	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+		rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+		if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
+			break;
+		msleep(1);
+	}
+
+	if (i == REGISTER_BUSY_COUNT) {
+		ERROR(rt2x00dev, "PBF system register not ready.\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * Initialize firmware.
+	 */
+	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+	msleep(1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_load_firmware);
+
 void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc)
 {
 	u32 word;
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 10f8f2f..cecbd3a 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -41,6 +41,8 @@ struct rt2800_ops {
 			    const unsigned int offset,
 			    const struct rt2x00_field32 field, u32 *reg);
 
+	int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,
+				  const u8 *data, const size_t len);
 	int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev);
 };
 
@@ -109,6 +111,14 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,
 	return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg);
 }
 
+static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev,
+					    const u8 *data, const size_t len)
+{
+	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+
+	return rt2800ops->drv_write_firmware(rt2x00dev, data, len);
+}
+
 static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev)
 {
 	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
@@ -120,6 +130,11 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
 			const u8 command, const u8 token,
 			const u8 arg0, const u8 arg1);
 
+int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
+			  const u8 *data, const size_t len);
+int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
+			 const u8 *data, const size_t len);
+
 void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc);
 void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc);
 
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 520236d..0fdd58b 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -31,7 +31,6 @@
 	Supported chipsets: RT2800E & RT2800ED.
  */
 
-#include <linux/crc-ccitt.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -192,82 +191,14 @@ static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
 	return FIRMWARE_RT2860;
 }
 
-static int rt2800pci_check_firmware(struct rt2x00_dev *rt2x00dev,
+static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,
 				    const u8 *data, const size_t len)
 {
-	u16 fw_crc;
-	u16 crc;
-
-	/*
-	 * Only support 8kb firmware files.
-	 */
-	if (len != 8192)
-		return FW_BAD_LENGTH;
-
-	/*
-	 * The last 2 bytes in the firmware array are the crc checksum itself,
-	 * this means that we should never pass those 2 bytes to the crc
-	 * algorithm.
-	 */
-	fw_crc = (data[len - 2] << 8 | data[len - 1]);
-
-	/*
-	 * Use the crc ccitt algorithm.
-	 * This will return the same value as the legacy driver which
-	 * used bit ordering reversion on the both the firmware bytes
-	 * before input input as well as on the final output.
-	 * Obviously using crc ccitt directly is much more efficient.
-	 */
-	crc = crc_ccitt(~0, data, len - 2);
-
-	/*
-	 * There is a small difference between the crc-itu-t + bitrev and
-	 * the crc-ccitt crc calculation. In the latter method the 2 bytes
-	 * will be swapped, use swab16 to convert the crc to the correct
-	 * value.
-	 */
-	crc = swab16(crc);
-
-	return (fw_crc == crc) ? FW_OK : FW_BAD_CRC;
-}
-
-static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev,
-				   const u8 *data, const size_t len)
-{
-	unsigned int i;
 	u32 reg;
 
-	/*
-	 * Wait for stable hardware.
-	 */
-	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-		rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-		if (reg && reg != ~0)
-			break;
-		msleep(1);
-	}
-
-	if (i == REGISTER_BUSY_COUNT) {
-		ERROR(rt2x00dev, "Unstable hardware.\n");
-		return -EBUSY;
-	}
-
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
 	rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);
 
 	/*
-	 * Disable DMA, will be reenabled later when enabling
-	 * the radio.
-	 */
-	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
-	/*
 	 * enable Host program ram write selection
 	 */
 	reg = 0;
@@ -278,34 +209,11 @@ static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev,
 	 * Write firmware to device.
 	 */
 	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
-				      data, len);
+				   data, len);
 
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
 
-	/*
-	 * Wait for device to stabilize.
-	 */
-	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-		rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
-		if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
-			break;
-		msleep(1);
-	}
-
-	if (i == REGISTER_BUSY_COUNT) {
-		ERROR(rt2x00dev, "PBF system register not ready.\n");
-		return -EBUSY;
-	}
-
-	/*
-	 * Disable interrupts
-	 */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF);
-
-	/*
-	 * Initialize BBP R/W access agent
-	 */
 	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
 	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
 
@@ -1029,6 +937,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
 
 	.regbusy_read		= rt2x00pci_regbusy_read,
 
+	.drv_write_firmware	= rt2800pci_write_firmware,
 	.drv_init_registers	= rt2800pci_init_registers,
 };
 
@@ -1114,8 +1023,8 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.irq_handler_thread	= rt2800pci_interrupt_thread,
 	.probe_hw		= rt2800pci_probe_hw,
 	.get_firmware_name	= rt2800pci_get_firmware_name,
-	.check_firmware		= rt2800pci_check_firmware,
-	.load_firmware		= rt2800pci_load_firmware,
+	.check_firmware		= rt2800_check_firmware,
+	.load_firmware		= rt2800_load_firmware,
 	.initialize		= rt2x00pci_initialize,
 	.uninitialize		= rt2x00pci_uninitialize,
 	.get_entry_state	= rt2800pci_get_entry_state,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index f8eb6d7..7b8d51f 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -28,7 +28,6 @@
 	Supported chipsets: RT2800U.
  */
 
-#include <linux/crc-ccitt.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
@@ -57,84 +56,10 @@ static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
 	return FIRMWARE_RT2870;
 }
 
-static bool rt2800usb_check_crc(const u8 *data, const size_t len)
-{
-	u16 fw_crc;
-	u16 crc;
-
-	/*
-	 * The last 2 bytes in the firmware array are the crc checksum itself,
-	 * this means that we should never pass those 2 bytes to the crc
-	 * algorithm.
-	 */
-	fw_crc = (data[len - 2] << 8 | data[len - 1]);
-
-	/*
-	 * Use the crc ccitt algorithm.
-	 * This will return the same value as the legacy driver which
-	 * used bit ordering reversion on the both the firmware bytes
-	 * before input input as well as on the final output.
-	 * Obviously using crc ccitt directly is much more efficient.
-	 */
-	crc = crc_ccitt(~0, data, len - 2);
-
-	/*
-	 * There is a small difference between the crc-itu-t + bitrev and
-	 * the crc-ccitt crc calculation. In the latter method the 2 bytes
-	 * will be swapped, use swab16 to convert the crc to the correct
-	 * value.
-	 */
-	crc = swab16(crc);
-
-	return fw_crc == crc;
-}
-
-static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev,
+static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
 				    const u8 *data, const size_t len)
 {
-	size_t offset = 0;
-
-	/*
-	 * Firmware files:
-	 * There are 2 variations of the rt2870 firmware.
-	 * a) size: 4kb
-	 * b) size: 8kb
-	 * Note that (b) contains 2 separate firmware blobs of 4k
-	 * within the file. The first blob is the same firmware as (a),
-	 * but the second blob is for the additional chipsets.
-	 */
-	if (len != 4096 && len != 8192)
-		return FW_BAD_LENGTH;
-
-	/*
-	 * Check if we need the upper 4kb firmware data or not.
-	 */
-	if ((len == 4096) &&
-	    !rt2x00_rt(rt2x00dev, RT2860) &&
-	    !rt2x00_rt(rt2x00dev, RT2872) &&
-	    !rt2x00_rt(rt2x00dev, RT3070))
-		return FW_BAD_VERSION;
-
-	/*
-	 * 8kb firmware files must be checked as if it were
-	 * 2 separate firmware files.
-	 */
-	while (offset < len) {
-		if (!rt2800usb_check_crc(data + offset, 4096))
-			return FW_BAD_CRC;
-
-		offset += 4096;
-	}
-
-	return FW_OK;
-}
-
-static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
-				   const u8 *data, const size_t len)
-{
-	unsigned int i;
 	int status;
-	u32 reg;
 	u32 offset;
 	u32 length;
 
@@ -152,21 +77,6 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
 	}
 
 	/*
-	 * Wait for stable hardware.
-	 */
-	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-		rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-		if (reg && reg != ~0)
-			break;
-		msleep(1);
-	}
-
-	if (i == REGISTER_BUSY_COUNT) {
-		ERROR(rt2x00dev, "Unstable hardware.\n");
-		return -EBUSY;
-	}
-
-	/*
 	 * Write firmware to device.
 	 */
 	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
@@ -203,28 +113,6 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
 		udelay(10);
 	}
 
-	/*
-	 * Wait for device to stabilize.
-	 */
-	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-		rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
-		if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
-			break;
-		msleep(1);
-	}
-
-	if (i == REGISTER_BUSY_COUNT) {
-		ERROR(rt2x00dev, "PBF system register not ready.\n");
-		return -EBUSY;
-	}
-
-	/*
-	 * Initialize firmware.
-	 */
-	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
-	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
-	msleep(1);
-
 	return 0;
 }
 
@@ -593,6 +481,7 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = {
 
 	.regbusy_read		= rt2x00usb_regbusy_read,
 
+	.drv_write_firmware	= rt2800usb_write_firmware,
 	.drv_init_registers	= rt2800usb_init_registers,
 };
 
@@ -670,8 +559,8 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
 static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.probe_hw		= rt2800usb_probe_hw,
 	.get_firmware_name	= rt2800usb_get_firmware_name,
-	.check_firmware		= rt2800usb_check_firmware,
-	.load_firmware		= rt2800usb_load_firmware,
+	.check_firmware		= rt2800_check_firmware,
+	.load_firmware		= rt2800_load_firmware,
 	.initialize		= rt2x00usb_initialize,
 	.uninitialize		= rt2x00usb_uninitialize,
 	.clear_entry		= rt2x00usb_clear_entry,
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 15/17] rt2x00: Add missing TSF sync mode for AP operation
From: Ivo van Doorn @ 2010-07-11 10:30 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111229.50936.IvDoorn@gmail.com>

From: Helmut Schaa <helmut.schaa@googlemail.com>

Currently rt2x00 uses the TSF_SYNC_BEACON mode for all beaconing
interface types. However, TSF_SYNC_BEACON is meant for IBSS networks and
thus implements TSF merging in the hardware. Rename TSF_SYNC_BEACON to
TSF_SYNC_ADHOC to better express its purpose and introduce the missing
TSF sync mode TSF_SYNC_AP_NONE which should be used for beaconing modes
that don't need TSF merging.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c    |    5 +++--
 drivers/net/wireless/rt2x00/rt2x00config.c |    4 +++-
 drivers/net/wireless/rt2x00/rt2x00reg.h    |    3 ++-
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index cfe199b..9587236 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -805,7 +805,8 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE,
-				   (conf->sync == TSF_SYNC_BEACON));
+				   (conf->sync == TSF_SYNC_ADHOC ||
+				    conf->sync == TSF_SYNC_AP_NONE));
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
 		/*
@@ -813,7 +814,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 		 */
 		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
 		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER,
-				   (conf->sync == TSF_SYNC_BEACON));
+				   (conf->sync == TSF_SYNC_AP_NONE));
 		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
 
 	}
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 8dbd634..953dc4f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -41,10 +41,12 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
 
 	switch (type) {
 	case NL80211_IFTYPE_ADHOC:
+		conf.sync = TSF_SYNC_ADHOC;
+		break;
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_MESH_POINT:
 	case NL80211_IFTYPE_WDS:
-		conf.sync = TSF_SYNC_BEACON;
+		conf.sync = TSF_SYNC_AP_NONE;
 		break;
 	case NL80211_IFTYPE_STATION:
 		conf.sync = TSF_SYNC_INFRA;
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 055501c..cef9462 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -63,7 +63,8 @@ enum led_mode {
 enum tsf_sync {
 	TSF_SYNC_NONE = 0,
 	TSF_SYNC_INFRA = 1,
-	TSF_SYNC_BEACON = 2,
+	TSF_SYNC_ADHOC = 2,
+	TSF_SYNC_AP_NONE = 3,
 };
 
 /*
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 14/17] rt2x00: Don't initialize beacon interval to 0 on rt2800 devices
From: Ivo van Doorn @ 2010-07-11 10:29 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111229.27800.IvDoorn@gmail.com>

From: Helmut Schaa <helmut.schaa@googlemail.com>

Activating the TBTT interrupt when a beacon interval of 0 is configured
results in an interrupt storm causing the machine to hang. Hence,
initialize the beacon interval to a reasonable default of 100TUs.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 64bfa6e..cfe199b 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -1419,7 +1419,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
 
 	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 0);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 1600);
 	rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
 	rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, 0);
 	rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 13/17] rt2x00: Remove set_tim callback from PCI drivers
From: Ivo van Doorn @ 2010-07-11 10:29 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111228.56050.IvDoorn@gmail.com>

From: Helmut Schaa <helmut.schaa@googlemail.com>

Using the set_tim callback without managing the DTIM count and the
broad- and multicast buffering in hw, fw or the driver results in wrong
DTIM count values being sent out in beacons. Since all PCI drivers
fetch new beacons periodically and hence get an updated TIM we can just
remove the set_tim callback from these.

The rt2x00 USB drivers don't update the beacon periodically and thus
rely on the set_tim callback to get a correct TIM for beacon
transmission. USB devices still suffer from the DTIM count being wrong
under some circumstances but removing the set_tim callback from these
would cause more harm then good.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2400pci.c |    1 -
 drivers/net/wireless/rt2x00/rt2500pci.c |    1 -
 drivers/net/wireless/rt2x00/rt2800pci.c |    1 -
 drivers/net/wireless/rt2x00/rt61pci.c   |    1 -
 4 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 116244b..5063e01 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1589,7 +1589,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
 	.remove_interface	= rt2x00mac_remove_interface,
 	.config			= rt2x00mac_config,
 	.configure_filter	= rt2x00mac_configure_filter,
-	.set_tim		= rt2x00mac_set_tim,
 	.sw_scan_start		= rt2x00mac_sw_scan_start,
 	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
 	.get_stats		= rt2x00mac_get_stats,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 5e80948..c2a555d 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1883,7 +1883,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
 	.remove_interface	= rt2x00mac_remove_interface,
 	.config			= rt2x00mac_config,
 	.configure_filter	= rt2x00mac_configure_filter,
-	.set_tim		= rt2x00mac_set_tim,
 	.sw_scan_start		= rt2x00mac_sw_scan_start,
 	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
 	.get_stats		= rt2x00mac_get_stats,
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 4c138eb..520236d 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1096,7 +1096,6 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
 	.remove_interface	= rt2x00mac_remove_interface,
 	.config			= rt2x00mac_config,
 	.configure_filter	= rt2x00mac_configure_filter,
-	.set_tim		= rt2x00mac_set_tim,
 	.set_key		= rt2x00mac_set_key,
 	.sw_scan_start		= rt2x00mac_sw_scan_start,
 	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 049433f..e539c6c 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2805,7 +2805,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
 	.remove_interface	= rt2x00mac_remove_interface,
 	.config			= rt2x00mac_config,
 	.configure_filter	= rt2x00mac_configure_filter,
-	.set_tim		= rt2x00mac_set_tim,
 	.set_key		= rt2x00mac_set_key,
 	.sw_scan_start		= rt2x00mac_sw_scan_start,
 	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 12/17] rt2x00: Use separate mac80211_ops for rt2800pci and rt2800usb
From: Ivo van Doorn @ 2010-07-11 10:28 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111228.24393.IvDoorn@gmail.com>

From: Helmut Schaa <helmut.schaa@googlemail.com>

Use separate mac80211_ops for rt2800pci and rt2800usb in preparation
for further fixes. This shouldn't introduce functional changes.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |   48 +++++++++----------------------
 drivers/net/wireless/rt2x00/rt2800lib.h |   10 ++++++-
 drivers/net/wireless/rt2x00/rt2800pci.c |   24 +++++++++++++++-
 drivers/net/wireless/rt2x00/rt2800usb.c |   24 +++++++++++++++-
 4 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 5572732..64bfa6e 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2740,8 +2740,8 @@ EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode);
 /*
  * IEEE80211 stack callback functions.
  */
-static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx,
-				u32 *iv32, u16 *iv16)
+void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,
+			 u16 *iv16)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct mac_iveiv_entry iveiv_entry;
@@ -2754,8 +2754,9 @@ static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx,
 	memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16));
 	memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32));
 }
+EXPORT_SYMBOL_GPL(rt2800_get_tkip_seq);
 
-static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	u32 reg;
@@ -2791,9 +2792,10 @@ static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold);
 
-static int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
-			  const struct ieee80211_tx_queue_params *params)
+int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+		   const struct ieee80211_tx_queue_params *params)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct data_queue *queue;
@@ -2858,8 +2860,9 @@ static int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(rt2800_conf_tx);
 
-static u64 rt2800_get_tsf(struct ieee80211_hw *hw)
+u64 rt2800_get_tsf(struct ieee80211_hw *hw)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	u64 tsf;
@@ -2872,12 +2875,11 @@ static u64 rt2800_get_tsf(struct ieee80211_hw *hw)
 
 	return tsf;
 }
+EXPORT_SYMBOL_GPL(rt2800_get_tsf);
 
-static int rt2800_ampdu_action(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta,
-			       u16 tid, u16 *ssn)
+int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			enum ieee80211_ampdu_mlme_action action,
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
 	int ret = 0;
 
@@ -2901,29 +2903,7 @@ static int rt2800_ampdu_action(struct ieee80211_hw *hw,
 
 	return ret;
 }
-
-const struct ieee80211_ops rt2800_mac80211_ops = {
-	.tx			= rt2x00mac_tx,
-	.start			= rt2x00mac_start,
-	.stop			= rt2x00mac_stop,
-	.add_interface		= rt2x00mac_add_interface,
-	.remove_interface	= rt2x00mac_remove_interface,
-	.config			= rt2x00mac_config,
-	.configure_filter	= rt2x00mac_configure_filter,
-	.set_tim		= rt2x00mac_set_tim,
-	.set_key		= rt2x00mac_set_key,
-	.sw_scan_start		= rt2x00mac_sw_scan_start,
-	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
-	.get_stats		= rt2x00mac_get_stats,
-	.get_tkip_seq		= rt2800_get_tkip_seq,
-	.set_rts_threshold	= rt2800_set_rts_threshold,
-	.bss_info_changed	= rt2x00mac_bss_info_changed,
-	.conf_tx		= rt2800_conf_tx,
-	.get_tsf		= rt2800_get_tsf,
-	.rfkill_poll		= rt2x00mac_rfkill_poll,
-	.ampdu_action		= rt2800_ampdu_action,
-};
-EXPORT_SYMBOL_GPL(rt2800_mac80211_ops);
+EXPORT_SYMBOL_GPL(rt2800_ampdu_action);
 
 MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
 MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index eb3a4f5..10f8f2f 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -159,6 +159,14 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev);
 int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev);
 int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev);
 
-extern const struct ieee80211_ops rt2800_mac80211_ops;
+void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,
+			 u16 *iv16);
+int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
+int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+		   const struct ieee80211_tx_queue_params *params);
+u64 rt2800_get_tsf(struct ieee80211_hw *hw);
+int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			enum ieee80211_ampdu_mlme_action action,
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn);
 
 #endif /* RT2800LIB_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index c0c38f9..4c138eb 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1088,6 +1088,28 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	return 0;
 }
 
+static const struct ieee80211_ops rt2800pci_mac80211_ops = {
+	.tx			= rt2x00mac_tx,
+	.start			= rt2x00mac_start,
+	.stop			= rt2x00mac_stop,
+	.add_interface		= rt2x00mac_add_interface,
+	.remove_interface	= rt2x00mac_remove_interface,
+	.config			= rt2x00mac_config,
+	.configure_filter	= rt2x00mac_configure_filter,
+	.set_tim		= rt2x00mac_set_tim,
+	.set_key		= rt2x00mac_set_key,
+	.sw_scan_start		= rt2x00mac_sw_scan_start,
+	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
+	.get_stats		= rt2x00mac_get_stats,
+	.get_tkip_seq		= rt2800_get_tkip_seq,
+	.set_rts_threshold	= rt2800_set_rts_threshold,
+	.bss_info_changed	= rt2x00mac_bss_info_changed,
+	.conf_tx		= rt2800_conf_tx,
+	.get_tsf		= rt2800_get_tsf,
+	.rfkill_poll		= rt2x00mac_rfkill_poll,
+	.ampdu_action		= rt2800_ampdu_action,
+};
+
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.irq_handler		= rt2800pci_interrupt,
 	.irq_handler_thread	= rt2800pci_interrupt_thread,
@@ -1152,7 +1174,7 @@ static const struct rt2x00_ops rt2800pci_ops = {
 	.tx			= &rt2800pci_queue_tx,
 	.bcn			= &rt2800pci_queue_bcn,
 	.lib			= &rt2800pci_rt2x00_ops,
-	.hw			= &rt2800_mac80211_ops,
+	.hw			= &rt2800pci_mac80211_ops,
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 	.debugfs		= &rt2800_rt2x00debug,
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index df78e28..f8eb6d7 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -645,6 +645,28 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	return 0;
 }
 
+static const struct ieee80211_ops rt2800usb_mac80211_ops = {
+	.tx			= rt2x00mac_tx,
+	.start			= rt2x00mac_start,
+	.stop			= rt2x00mac_stop,
+	.add_interface		= rt2x00mac_add_interface,
+	.remove_interface	= rt2x00mac_remove_interface,
+	.config			= rt2x00mac_config,
+	.configure_filter	= rt2x00mac_configure_filter,
+	.set_tim		= rt2x00mac_set_tim,
+	.set_key		= rt2x00mac_set_key,
+	.sw_scan_start		= rt2x00mac_sw_scan_start,
+	.sw_scan_complete	= rt2x00mac_sw_scan_complete,
+	.get_stats		= rt2x00mac_get_stats,
+	.get_tkip_seq		= rt2800_get_tkip_seq,
+	.set_rts_threshold	= rt2800_set_rts_threshold,
+	.bss_info_changed	= rt2x00mac_bss_info_changed,
+	.conf_tx		= rt2800_conf_tx,
+	.get_tsf		= rt2800_get_tsf,
+	.rfkill_poll		= rt2x00mac_rfkill_poll,
+	.ampdu_action		= rt2800_ampdu_action,
+};
+
 static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.probe_hw		= rt2800usb_probe_hw,
 	.get_firmware_name	= rt2800usb_get_firmware_name,
@@ -708,7 +730,7 @@ static const struct rt2x00_ops rt2800usb_ops = {
 	.tx			= &rt2800usb_queue_tx,
 	.bcn			= &rt2800usb_queue_bcn,
 	.lib			= &rt2800usb_rt2x00_ops,
-	.hw			= &rt2800_mac80211_ops,
+	.hw			= &rt2800usb_mac80211_ops,
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 	.debugfs		= &rt2800_rt2x00debug,
 #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 11/17] rt2x00: Use pretbtt irq for fetching beacons on rt2800pci
From: Ivo van Doorn @ 2010-07-11 10:28 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111227.58927.IvDoorn@gmail.com>

From: Helmut Schaa <helmut.schaa@googlemail.com>

Updating the beacon on pre tbtt instead of beacondone allows much lower
latency in regard to TIM updates. Hence, use the pre tbtt interrupt for
updating the beacon in rt2800pci (older devices don't provide a pre tbtt
interrupt).

Also, add a new driver flag to indicate if a driver has pre tbtt support
or not and implement the according behavior in rt2x00lib.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800.h    |    8 +++++++-
 drivers/net/wireless/rt2x00/rt2800lib.c |   16 ++++++++++++++++
 drivers/net/wireless/rt2x00/rt2800pci.c |   28 +++++++++++++++++++++++-----
 drivers/net/wireless/rt2x00/rt2x00.h    |    2 ++
 drivers/net/wireless/rt2x00/rt2x00dev.c |   26 ++++++++++++++++++++++----
 5 files changed, 70 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index edd3734..dc93e14 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -719,14 +719,20 @@
 #define TBTT_TIMER			0x1124
 
 /*
- * INT_TIMER_CFG:
+ * INT_TIMER_CFG: timer configuration
+ * PRE_TBTT_TIMER: leadtime to tbtt for pretbtt interrupt in units of 1/16 TU
+ * GP_TIMER: period of general purpose timer in units of 1/16 TU
  */
 #define INT_TIMER_CFG			0x1128
+#define INT_TIMER_CFG_PRE_TBTT_TIMER	FIELD32(0x0000ffff)
+#define INT_TIMER_CFG_GP_TIMER		FIELD32(0xffff0000)
 
 /*
  * INT_TIMER_EN: GP-timer and pre-tbtt Int enable
  */
 #define INT_TIMER_EN			0x112c
+#define INT_TIMER_EN_PRE_TBTT_TIMER	FIELD32(0x00000001)
+#define INT_TIMER_EN_GP_TIMER		FIELD32(0x00000002)
 
 /*
  * CH_IDLE_STA: channel idle time
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index afad3e1..5572732 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -807,6 +807,15 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE,
 				   (conf->sync == TSF_SYNC_BEACON));
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+		/*
+		 * Enable pre tbtt interrupt for beaconing modes
+		 */
+		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER,
+				   (conf->sync == TSF_SYNC_BEACON));
+		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+
 	}
 
 	if (flags & CONFIG_UPDATE_MAC) {
@@ -1732,6 +1741,13 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_read(rt2x00dev, TX_STA_CNT1, &reg);
 	rt2800_register_read(rt2x00dev, TX_STA_CNT2, &reg);
 
+	/*
+	 * Setup leadtime for pre tbtt interrupt to 6ms
+	 */
+	rt2800_register_read(rt2x00dev, INT_TIMER_CFG, &reg);
+	rt2x00_set_field32(&reg, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);
+	rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(rt2800_init_registers);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index f21b77c..c0c38f9 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -938,20 +938,32 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
 	u32 reg = rt2x00dev->irqvalue[0];
 
 	/*
-	 * 1 - Rx ring done interrupt.
+	 * 1 - Pre TBTT interrupt.
+	 */
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
+		rt2x00lib_pretbtt(rt2x00dev);
+
+	/*
+	 * 2 - Beacondone interrupt.
+	 */
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
+		rt2x00lib_beacondone(rt2x00dev);
+
+	/*
+	 * 3 - Rx ring done interrupt.
 	 */
 	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
 		rt2x00pci_rxdone(rt2x00dev);
 
+	/*
+	 * 4 - Tx done interrupt.
+	 */
 	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
 		rt2800pci_txdone(rt2x00dev);
 
 	/*
-	 * Current beacon was sent out, fetch the next one
+	 * 5 - Auto wakeup interrupt.
 	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
-		rt2x00lib_beacondone(rt2x00dev);
-
 	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
 		rt2800pci_wakeup(rt2x00dev);
 
@@ -1052,6 +1064,12 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	__set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
 
 	/*
+	 * This device has a pre tbtt interrupt and thus fetches
+	 * a new beacon directly prior to transmission.
+	 */
+	__set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags);
+
+	/*
 	 * This device requires firmware.
 	 */
 	if (!rt2x00_is_soc(rt2x00dev))
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 0fa2141..9dd0d17 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -658,6 +658,7 @@ enum rt2x00_flags {
 	CONFIG_SUPPORT_HW_CRYPTO,
 	DRIVER_SUPPORT_CONTROL_FILTERS,
 	DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
+	DRIVER_SUPPORT_PRE_TBTT_INTERRUPT,
 	DRIVER_SUPPORT_LINK_TUNING,
 	DRIVER_SUPPORT_WATCHDOG,
 
@@ -1071,6 +1072,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
  * Interrupt context handlers.
  */
 void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev);
 void rt2x00lib_txdone(struct queue_entry *entry,
 		      struct txdone_entry_desc *txdesc);
 void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index ae0adff..f59b9f7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -200,8 +200,8 @@ static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac,
 	}
 }
 
-static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
-				      struct ieee80211_vif *vif)
+static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac,
+					struct ieee80211_vif *vif)
 {
 	struct rt2x00_dev *rt2x00dev = data;
 
@@ -223,15 +223,33 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
 	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
 					    rt2x00lib_bc_buffer_iter,
 					    rt2x00dev);
+	/*
+	 * Devices with pre tbtt interrupt don't need to update the beacon
+	 * here as they will fetch the next beacon directly prior to
+	 * transmission.
+	 */
+	if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags))
+		return;
 
 	/* fetch next beacon */
 	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-					    rt2x00lib_beacondone_iter,
+					    rt2x00lib_beaconupdate_iter,
 					    rt2x00dev);
-
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
 
+void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
+{
+	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		return;
+
+	/* fetch next beacon */
+	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+					    rt2x00lib_beaconupdate_iter,
+					    rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
+
 void rt2x00lib_txdone(struct queue_entry *entry,
 		      struct txdone_entry_desc *txdesc)
 {
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 09/17] rt2x00: Allow beacon update without scheduling a work
From: Ivo van Doorn @ 2010-07-11 10:27 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111226.49015.IvDoorn@gmail.com>

From: Helmut Schaa <helmut.schaa@googlemail.com>

Since all rt2x00 PCI drivers use threaded interrupts now we don't need
to schedule a work just to update the beacon. The only place where the
beacon still gets updated in atomic context is from the set_tim
callback. Hence, move the work scheduling there.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2x00dev.c |   13 +++++--------
 drivers/net/wireless/rt2x00/rt2x00mac.c |   26 +++++++++++++++++++++++++-
 2 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index d3ebb41..e255725 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -181,7 +181,7 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
 static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
 				      struct ieee80211_vif *vif)
 {
-	struct rt2x00_intf *intf = vif_to_intf(vif);
+	struct rt2x00_dev *rt2x00dev = data;
 
 	if (vif->type != NL80211_IFTYPE_AP &&
 	    vif->type != NL80211_IFTYPE_ADHOC &&
@@ -189,9 +189,7 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
 	    vif->type != NL80211_IFTYPE_WDS)
 		return;
 
-	spin_lock(&intf->lock);
-	intf->delayed_flags |= DELAYED_UPDATE_BEACON;
-	spin_unlock(&intf->lock);
+	rt2x00queue_update_beacon(rt2x00dev, vif, true);
 }
 
 void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
@@ -199,11 +197,10 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return;
 
-	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
-						   rt2x00lib_beacondone_iter,
-						   rt2x00dev);
+	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+					   rt2x00lib_beacondone_iter,
+					   rt2x00dev);
 
-	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index bbce496..4d8d232 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -433,12 +433,36 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
 
+static void rt2x00mac_set_tim_iter(void *data, u8 *mac,
+				   struct ieee80211_vif *vif)
+{
+	struct rt2x00_intf *intf = vif_to_intf(vif);
+
+	if (vif->type != NL80211_IFTYPE_AP &&
+	    vif->type != NL80211_IFTYPE_ADHOC &&
+	    vif->type != NL80211_IFTYPE_MESH_POINT &&
+	    vif->type != NL80211_IFTYPE_WDS)
+		return;
+
+	spin_lock(&intf->lock);
+	intf->delayed_flags |= DELAYED_UPDATE_BEACON;
+	spin_unlock(&intf->lock);
+}
+
 int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 		      bool set)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 
-	rt2x00lib_beacondone(rt2x00dev);
+	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		return 0;
+
+	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+						   rt2x00mac_set_tim_iter,
+						   rt2x00dev);
+
+	/* queue work to upodate the beacon template */
+	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_set_tim);
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 10/17] rt2x00: Implement broad- and multicast buffering
From: Ivo van Doorn @ 2010-07-11 10:27 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111227.27070.IvDoorn@gmail.com>

From: Helmut Schaa <helmut.schaa@googlemail.com>

Although mac80211 buffers broad- and mutlicast frames for us in AP mode
we still have to send them out after a DTIM beacon. Implement this
behavior by sending out the buffered frames when the beacondone
interrupt is processed.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2x00dev.c |   32 +++++++++++++++++++++++++++++-
 1 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index e255725..ae0adff 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -178,6 +178,28 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
 /*
  * Interrupt context handlers.
  */
+static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac,
+				     struct ieee80211_vif *vif)
+{
+	struct rt2x00_dev *rt2x00dev = data;
+	struct sk_buff *skb;
+
+	/*
+	 * Only AP mode interfaces do broad- and multicast buffering
+	 */
+	if (vif->type != NL80211_IFTYPE_AP)
+		return;
+
+	/*
+	 * Send out buffered broad- and multicast frames
+	 */
+	skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
+	while (skb) {
+		rt2x00mac_tx(rt2x00dev->hw, skb);
+		skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
+	}
+}
+
 static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
 				      struct ieee80211_vif *vif)
 {
@@ -197,9 +219,15 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return;
 
+	/* send buffered bc/mc frames out for every bssid */
 	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-					   rt2x00lib_beacondone_iter,
-					   rt2x00dev);
+					    rt2x00lib_bc_buffer_iter,
+					    rt2x00dev);
+
+	/* fetch next beacon */
+	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
+					    rt2x00lib_beacondone_iter,
+					    rt2x00dev);
 
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 08/17] rt2x00: Convert rt2x00 to use threaded interrupts
From: Ivo van Doorn @ 2010-07-11 10:26 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111226.13314.IvDoorn@gmail.com>

From: Helmut Schaa <helmut.schaa@googlemail.com>

Use threaded interrupts for all rt2x00 PCI devices.

This has several generic advantages:
- Reduce the time we spend in hard irq context
- Use non-atmic mac80211 functions for rx/tx

Furthermore implementing broad- and multicast buffering will be
much easier in process context while maintaining low latency and
updating the beacon just before transmission (pre tbtt interrupt)
can also be done in process context.

Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2400pci.c |   54 ++++++++++++++++++--------
 drivers/net/wireless/rt2x00/rt2500pci.c |   55 +++++++++++++++++++--------
 drivers/net/wireless/rt2x00/rt2500usb.c |    2 +
 drivers/net/wireless/rt2x00/rt2800pci.c |   50 ++++++++++++++++++------
 drivers/net/wireless/rt2x00/rt2800usb.c |    2 +
 drivers/net/wireless/rt2x00/rt2x00.h    |   11 +++++
 drivers/net/wireless/rt2x00/rt2x00dev.c |   23 ++++++++++-
 drivers/net/wireless/rt2x00/rt2x00pci.c |    6 ++-
 drivers/net/wireless/rt2x00/rt2x00reg.h |    2 +
 drivers/net/wireless/rt2x00/rt61pci.c   |   64 +++++++++++++++++++++----------
 drivers/net/wireless/rt2x00/rt73usb.c   |    2 +
 11 files changed, 201 insertions(+), 70 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 25e9dcf..116244b 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -879,7 +879,8 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
 static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_OFF);
+	int mask = (state == STATE_RADIO_IRQ_OFF) ||
+		   (state == STATE_RADIO_IRQ_OFF_ISR);
 	u32 reg;
 
 	/*
@@ -980,7 +981,9 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2400pci_toggle_rx(rt2x00dev, state);
 		break;
 	case STATE_RADIO_IRQ_ON:
+	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
+	case STATE_RADIO_IRQ_OFF_ISR:
 		rt2400pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1235,23 +1238,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
 	}
 }
 
-static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
+static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg;
-
-	/*
-	 * Get the interrupt sources & saved to local variable.
-	 * Write register value back to clear pending interrupts.
-	 */
-	rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
-	rt2x00pci_register_write(rt2x00dev, CSR7, reg);
-
-	if (!reg)
-		return IRQ_NONE;
-
-	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-		return IRQ_HANDLED;
+	u32 reg = rt2x00dev->irqvalue[0];
 
 	/*
 	 * Handle interrupts, walk through all bits
@@ -1289,9 +1279,40 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
 	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
 		rt2400pci_txdone(rt2x00dev, QID_AC_BK);
 
+	/* Enable interrupts again. */
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+					      STATE_RADIO_IRQ_ON_ISR);
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
+{
+	struct rt2x00_dev *rt2x00dev = dev_instance;
+	u32 reg;
+
+	/*
+	 * Get the interrupt sources & saved to local variable.
+	 * Write register value back to clear pending interrupts.
+	 */
+	rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
+	rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+
+	if (!reg)
+		return IRQ_NONE;
+
+	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		return IRQ_HANDLED;
+
+	/* Store irqvalues for use in the interrupt thread. */
+	rt2x00dev->irqvalue[0] = reg;
+
+	/* Disable interrupts, will be enabled again in the interrupt thread. */
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+					      STATE_RADIO_IRQ_OFF_ISR);
+
+	return IRQ_WAKE_THREAD;
+}
+
 /*
  * Device probe functions.
  */
@@ -1581,6 +1602,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
 	.irq_handler		= rt2400pci_interrupt,
+	.irq_handler_thread	= rt2400pci_interrupt_thread,
 	.probe_hw		= rt2400pci_probe_hw,
 	.initialize		= rt2x00pci_initialize,
 	.uninitialize		= rt2x00pci_uninitialize,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index faa804c..5e80948 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1033,7 +1033,8 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
 static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_OFF);
+	int mask = (state == STATE_RADIO_IRQ_OFF) ||
+		   (state == STATE_RADIO_IRQ_OFF_ISR);
 	u32 reg;
 
 	/*
@@ -1134,7 +1135,9 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2500pci_toggle_rx(rt2x00dev, state);
 		break;
 	case STATE_RADIO_IRQ_ON:
+	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
+	case STATE_RADIO_IRQ_OFF_ISR:
 		rt2500pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1367,23 +1370,10 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
 	}
 }
 
-static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
+static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg;
-
-	/*
-	 * Get the interrupt sources & saved to local variable.
-	 * Write register value back to clear pending interrupts.
-	 */
-	rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
-	rt2x00pci_register_write(rt2x00dev, CSR7, reg);
-
-	if (!reg)
-		return IRQ_NONE;
-
-	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-		return IRQ_HANDLED;
+	u32 reg = rt2x00dev->irqvalue[0];
 
 	/*
 	 * Handle interrupts, walk through all bits
@@ -1421,9 +1411,41 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
 	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
 		rt2500pci_txdone(rt2x00dev, QID_AC_BK);
 
+	/* Enable interrupts again. */
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+					      STATE_RADIO_IRQ_ON_ISR);
+
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
+{
+	struct rt2x00_dev *rt2x00dev = dev_instance;
+	u32 reg;
+
+	/*
+	 * Get the interrupt sources & saved to local variable.
+	 * Write register value back to clear pending interrupts.
+	 */
+	rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
+	rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+
+	if (!reg)
+		return IRQ_NONE;
+
+	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		return IRQ_HANDLED;
+
+	/* Store irqvalues for use in the interrupt thread. */
+	rt2x00dev->irqvalue[0] = reg;
+
+	/* Disable interrupts, will be enabled again in the interrupt thread. */
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+					      STATE_RADIO_IRQ_OFF_ISR);
+
+	return IRQ_WAKE_THREAD;
+}
+
 /*
  * Device probe functions.
  */
@@ -1874,6 +1896,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
 	.irq_handler		= rt2500pci_interrupt,
+	.irq_handler_thread	= rt2500pci_interrupt_thread,
 	.probe_hw		= rt2500pci_probe_hw,
 	.initialize		= rt2x00pci_initialize,
 	.uninitialize		= rt2x00pci_uninitialize,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 009323e..242d595 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1004,7 +1004,9 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2500usb_toggle_rx(rt2x00dev, state);
 		break;
 	case STATE_RADIO_IRQ_ON:
+	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
+	case STATE_RADIO_IRQ_OFF_ISR:
 		/* No support, but no error either */
 		break;
 	case STATE_DEEP_SLEEP:
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index a9eca99..f21b77c 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -422,7 +422,8 @@ static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
 static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_ON);
+	int mask = (state == STATE_RADIO_IRQ_ON) ||
+		   (state == STATE_RADIO_IRQ_ON_ISR);
 	u32 reg;
 
 	/*
@@ -631,7 +632,9 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2800pci_toggle_rx(rt2x00dev, state);
 		break;
 	case STATE_RADIO_IRQ_ON:
+	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
+	case STATE_RADIO_IRQ_OFF_ISR:
 		rt2800pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -929,20 +932,10 @@ static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
 	rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
-static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
+static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg;
-
-	/* Read status and ACK all interrupts */
-	rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-	rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
-	if (!reg)
-		return IRQ_NONE;
-
-	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-		return IRQ_HANDLED;
+	u32 reg = rt2x00dev->irqvalue[0];
 
 	/*
 	 * 1 - Rx ring done interrupt.
@@ -962,9 +955,39 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
 	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
 		rt2800pci_wakeup(rt2x00dev);
 
+	/* Enable interrupts again. */
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+					      STATE_RADIO_IRQ_ON_ISR);
+
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
+{
+	struct rt2x00_dev *rt2x00dev = dev_instance;
+	u32 reg;
+
+	/* Read status and ACK all interrupts */
+	rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+	rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+	if (!reg)
+		return IRQ_NONE;
+
+	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		return IRQ_HANDLED;
+
+	/* Store irqvalue for use in the interrupt thread. */
+	rt2x00dev->irqvalue[0] = reg;
+
+	/* Disable interrupts, will be enabled again in the interrupt thread. */
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+					      STATE_RADIO_IRQ_OFF_ISR);
+
+
+	return IRQ_WAKE_THREAD;
+}
+
 /*
  * Device probe functions.
  */
@@ -1049,6 +1072,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.irq_handler		= rt2800pci_interrupt,
+	.irq_handler_thread	= rt2800pci_interrupt_thread,
 	.probe_hw		= rt2800pci_probe_hw,
 	.get_firmware_name	= rt2800pci_get_firmware_name,
 	.check_firmware		= rt2800pci_check_firmware,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 5aa7563..df78e28 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -406,7 +406,9 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2800usb_toggle_rx(rt2x00dev, state);
 		break;
 	case STATE_RADIO_IRQ_ON:
+	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
+	case STATE_RADIO_IRQ_OFF_ISR:
 		/* No support, but no error either */
 		break;
 	case STATE_DEEP_SLEEP:
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 97b6261..0fa2141 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -515,6 +515,11 @@ struct rt2x00lib_ops {
 	irq_handler_t irq_handler;
 
 	/*
+	 * Threaded Interrupt handlers.
+	 */
+	irq_handler_t irq_handler_thread;
+
+	/*
 	 * Device init handlers.
 	 */
 	int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
@@ -871,6 +876,12 @@ struct rt2x00_dev {
 	const struct firmware *fw;
 
 	/*
+	 * Interrupt values, stored between interrupt service routine
+	 * and interrupt thread routine.
+	 */
+	u32 irqvalue[2];
+
+	/*
 	 * Driver specific data.
 	 */
 	void *priv;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 0906e14..d3ebb41 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -340,9 +340,17 @@ void rt2x00lib_txdone(struct queue_entry *entry,
 	 * send the status report back.
 	 */
 	if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
-		ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
+		/*
+		 * Only PCI and SOC devices process the tx status in process
+		 * context. Hence use ieee80211_tx_status for PCI and SOC
+		 * devices and stick to ieee80211_tx_status_irqsafe for USB.
+		 */
+		if (rt2x00_is_usb(rt2x00dev))
+			ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
+		else
+			ieee80211_tx_status(rt2x00dev->hw, entry->skb);
 	else
-		dev_kfree_skb_irq(entry->skb);
+		dev_kfree_skb_any(entry->skb);
 
 	/*
 	 * Make this entry available for reuse.
@@ -489,7 +497,16 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
 	 */
 	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
 	memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status));
-	ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);
+
+	/*
+	 * Currently only PCI and SOC devices handle rx interrupts in process
+	 * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni
+	 * for PCI and SOC devices.
+	 */
+	if (rt2x00_is_usb(rt2x00dev))
+		ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);
+	else
+		ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
 
 	/*
 	 * Replace the skb with the freshly allocated one.
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index fc9da83..19b262e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -153,8 +153,10 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Register interrupt handler.
 	 */
-	status = request_irq(rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler,
-			     IRQF_SHARED, rt2x00dev->name, rt2x00dev);
+	status = request_threaded_irq(rt2x00dev->irq,
+				      rt2x00dev->ops->lib->irq_handler,
+				      rt2x00dev->ops->lib->irq_handler_thread,
+				      IRQF_SHARED, rt2x00dev->name, rt2x00dev);
 	if (status) {
 		ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
 		      rt2x00dev->irq, status);
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index b9fe948..055501c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -88,6 +88,8 @@ enum dev_state {
 	STATE_RADIO_RX_OFF_LINK,
 	STATE_RADIO_IRQ_ON,
 	STATE_RADIO_IRQ_OFF,
+	STATE_RADIO_IRQ_ON_ISR,
+	STATE_RADIO_IRQ_OFF_ISR,
 };
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index fe7bce7..049433f 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1622,7 +1622,8 @@ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
 static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 			       enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_OFF);
+	int mask = (state == STATE_RADIO_IRQ_OFF) ||
+		   (state == STATE_RADIO_IRQ_OFF_ISR);
 	u32 reg;
 
 	/*
@@ -1739,7 +1740,9 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt61pci_toggle_rx(rt2x00dev, state);
 		break;
 	case STATE_RADIO_IRQ_ON:
+	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
+	case STATE_RADIO_IRQ_OFF_ISR:
 		rt61pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -2147,27 +2150,11 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
 	rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
-static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
+static irqreturn_t rt61pci_interrupt_thread(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg_mcu;
-	u32 reg;
-
-	/*
-	 * Get the interrupt sources & saved to local variable.
-	 * Write register value back to clear pending interrupts.
-	 */
-	rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
-	rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
-
-	rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-	rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
-	if (!reg && !reg_mcu)
-		return IRQ_NONE;
-
-	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-		return IRQ_HANDLED;
+	u32 reg = rt2x00dev->irqvalue[0];
+	u32 reg_mcu = rt2x00dev->irqvalue[1];
 
 	/*
 	 * Handle interrupts, walk through all bits
@@ -2206,9 +2193,45 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
 	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
 		rt2x00lib_beacondone(rt2x00dev);
 
+	/* Enable interrupts again. */
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+					      STATE_RADIO_IRQ_ON_ISR);
 	return IRQ_HANDLED;
 }
 
+
+static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
+{
+	struct rt2x00_dev *rt2x00dev = dev_instance;
+	u32 reg_mcu;
+	u32 reg;
+
+	/*
+	 * Get the interrupt sources & saved to local variable.
+	 * Write register value back to clear pending interrupts.
+	 */
+	rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg_mcu);
+	rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu);
+
+	rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+	rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+	if (!reg && !reg_mcu)
+		return IRQ_NONE;
+
+	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		return IRQ_HANDLED;
+
+	/* Store irqvalues for use in the interrupt thread. */
+	rt2x00dev->irqvalue[0] = reg;
+	rt2x00dev->irqvalue[1] = reg_mcu;
+
+	/* Disable interrupts, will be enabled again in the interrupt thread. */
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+					      STATE_RADIO_IRQ_OFF_ISR);
+	return IRQ_WAKE_THREAD;
+}
+
 /*
  * Device probe functions.
  */
@@ -2795,6 +2818,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
 	.irq_handler		= rt61pci_interrupt,
+	.irq_handler_thread	= rt61pci_interrupt_thread,
 	.probe_hw		= rt61pci_probe_hw,
 	.get_firmware_name	= rt61pci_get_firmware_name,
 	.check_firmware		= rt61pci_check_firmware,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index cad07b6..aa9de18 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1400,7 +1400,9 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt73usb_toggle_rx(rt2x00dev, state);
 		break;
 	case STATE_RADIO_IRQ_ON:
+	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
+	case STATE_RADIO_IRQ_OFF_ISR:
 		/* No support, but no error either */
 		break;
 	case STATE_DEEP_SLEEP:
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 07/17] rt2x00: Make rt2800_write_beacon only export to GPL
From: Ivo van Doorn @ 2010-07-11 10:26 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111225.47409.IvDoorn@gmail.com>

rt2800_write_beacon is the only function which uses
EXPORT_SYMBOL instead of EXPORT_SYMBOL_GPL. All symbols
in rt2x00 should however use the GPL restricted export.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800lib.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index bcf50fc..afad3e1 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -473,7 +473,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 	dev_kfree_skb_any(entry->skb);
 	entry->skb = NULL;
 }
-EXPORT_SYMBOL(rt2800_write_beacon);
+EXPORT_SYMBOL_GPL(rt2800_write_beacon);
 
 static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
 				       unsigned int beacon_base)
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 05/17] rt2x00: Fix vgc_level_reg handling
From: Ivo van Doorn @ 2010-07-11 10:25 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111224.48247.IvDoorn@gmail.com>

Currently vgc_level_reg and vgc_level are equal to eachother,
while the purpose of vgc_level_reg is the value last written
to the register and is remembered through link tuning resets.
The vgc_level is the currently active level, which is
reset during link tuning resets.

The usage of these variables depends on the drivers, some drivers
need both, while others need only one of the two.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2400pci.c  |    8 +++++---
 drivers/net/wireless/rt2x00/rt2500pci.c  |    8 +++-----
 drivers/net/wireless/rt2x00/rt2x00link.c |    8 ++++++++
 3 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index d5f1fab..25e9dcf 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -586,9 +586,11 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
 static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev,
 				     struct link_qual *qual, u8 vgc_level)
 {
-	rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
-	qual->vgc_level = vgc_level;
-	qual->vgc_level_reg = vgc_level;
+	if (qual->vgc_level_reg != vgc_level) {
+		rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
+		qual->vgc_level = vgc_level;
+		qual->vgc_level_reg = vgc_level;
+	}
 }
 
 static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 096d6db..faa804c 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -626,6 +626,7 @@ static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev,
 {
 	if (qual->vgc_level_reg != vgc_level) {
 		rt2500pci_bbp_write(rt2x00dev, 17, vgc_level);
+		qual->vgc_level = vgc_level;
 		qual->vgc_level_reg = vgc_level;
 	}
 }
@@ -700,13 +701,10 @@ dynamic_cca_tune:
 	 * R17 is inside the dynamic tuning range,
 	 * start tuning the link based on the false cca counter.
 	 */
-	if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40) {
+	if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40)
 		rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg);
-		qual->vgc_level = qual->vgc_level_reg;
-	} else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32) {
+	else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32)
 		rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg);
-		qual->vgc_level = qual->vgc_level_reg;
-	}
 }
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 14f1d51..9acfc5c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -302,6 +302,7 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev)
 void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
 {
 	struct link_qual *qual = &rt2x00dev->link.qual;
+	u8 vgc_level = qual->vgc_level_reg;
 
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return;
@@ -318,6 +319,13 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)
 	memset(qual, 0, sizeof(*qual));
 
 	/*
+	 * Restore the VGC level as stored in the registers,
+	 * the driver can use this to determine if the register
+	 * must be updated during reset or not.
+	 */
+	qual->vgc_level_reg = vgc_level;
+
+	/*
 	 * Reset the link tuner.
 	 */
 	rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual);
-- 
1.7.1.1


^ permalink raw reply related

* [PATCH 06/17] rt2x00: Implement watchdog monitoring
From: Ivo van Doorn @ 2010-07-11 10:25 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, users, Helmut Schaa
In-Reply-To: <201007111225.18986.IvDoorn@gmail.com>

Implement watchdog monitoring for USB devices (PCI support can
be added later). This will determine if URBs being uploaded to
the hardware are actually returning. Both rt2500usb and rt2800usb
have shown that URBs being uploaded can remain hanging without
being released by the hardware.
By using this watchdog, a queue can be reset when this occurs.
For rt2800usb it has been tested that the connection is preserved
even though this interruption.

Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2500usb.c   |    2 +
 drivers/net/wireless/rt2x00/rt2800usb.c   |    2 +
 drivers/net/wireless/rt2x00/rt2x00.h      |    7 ++++
 drivers/net/wireless/rt2x00/rt2x00dev.c   |   10 ++++++
 drivers/net/wireless/rt2x00/rt2x00lib.h   |   26 +++++++++++++--
 drivers/net/wireless/rt2x00/rt2x00link.c  |   38 ++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00queue.c |    4 ++
 drivers/net/wireless/rt2x00/rt2x00queue.h |   11 ++++++
 drivers/net/wireless/rt2x00/rt2x00usb.c   |   50 +++++++++++++++++++++++++++++
 drivers/net/wireless/rt2x00/rt2x00usb.h   |   10 ++++++
 drivers/net/wireless/rt2x00/rt73usb.c     |    2 +
 11 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 0b7888d..009323e 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1736,6 +1736,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 		__set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
 	}
+	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -1772,6 +1773,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
 	.rfkill_poll		= rt2500usb_rfkill_poll,
 	.link_stats		= rt2500usb_link_stats,
 	.reset_tuner		= rt2500usb_reset_tuner,
+	.watchdog		= rt2x00usb_watchdog,
 	.write_tx_desc		= rt2500usb_write_tx_desc,
 	.write_beacon		= rt2500usb_write_beacon,
 	.get_tx_data_len	= rt2500usb_get_tx_data_len,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index e4ab4db..5aa7563 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -633,6 +633,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	if (!modparam_nohwcrypt)
 		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -655,6 +656,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.link_stats		= rt2800_link_stats,
 	.reset_tuner		= rt2800_reset_tuner,
 	.link_tuner		= rt2800_link_tuner,
+	.watchdog		= rt2x00usb_watchdog,
 	.write_tx_desc		= rt2800usb_write_tx_desc,
 	.write_tx_data		= rt2800usb_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index bf5e3f3..97b6261 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -332,6 +332,11 @@ struct link {
 	 * Work structure for scheduling periodic link tuning.
 	 */
 	struct delayed_work work;
+
+	/*
+	 * Work structure for scheduling periodic watchdog monitoring.
+	 */
+	struct delayed_work watchdog_work;
 };
 
 /*
@@ -543,6 +548,7 @@ struct rt2x00lib_ops {
 			     struct link_qual *qual);
 	void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
 			    struct link_qual *qual, const u32 count);
+	void (*watchdog) (struct rt2x00_dev *rt2x00dev);
 
 	/*
 	 * TX control handlers
@@ -648,6 +654,7 @@ enum rt2x00_flags {
 	DRIVER_SUPPORT_CONTROL_FILTERS,
 	DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
 	DRIVER_SUPPORT_LINK_TUNING,
+	DRIVER_SUPPORT_WATCHDOG,
 
 	/*
 	 * Driver configuration
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 12ee7bd..0906e14 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -70,6 +70,11 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
 	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 
 	/*
+	 * Start watchdog monitoring.
+	 */
+	rt2x00link_start_watchdog(rt2x00dev);
+
+	/*
 	 * Start the TX queues.
 	 */
 	ieee80211_wake_queues(rt2x00dev->hw);
@@ -89,6 +94,11 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
 	rt2x00queue_stop_queues(rt2x00dev);
 
 	/*
+	 * Stop watchdog monitoring.
+	 */
+	rt2x00link_stop_watchdog(rt2x00dev);
+
+	/*
 	 * Disable RX.
 	 */
 	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index ed27de1..dc5c657 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -30,6 +30,7 @@
 /*
  * Interval defines
  */
+#define WATCHDOG_INTERVAL	round_jiffies_relative(HZ)
 #define LINK_TUNE_INTERVAL	round_jiffies_relative(HZ)
 
 /*
@@ -257,11 +258,30 @@ void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev);
 void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna);
 
 /**
- * rt2x00link_register - Initialize link tuning functionality
+ * rt2x00link_start_watchdog - Start periodic watchdog monitoring
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
  *
- * Initialize work structure and all link tuning related
- * parameters. This will not start the link tuning process itself.
+ * This start the watchdog periodic work, this work will
+ *be executed periodically until &rt2x00link_stop_watchdog has
+ * been called.
+ */
+void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_stop_watchdog - Stop periodic watchdog monitoring
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * After this function completed the watchdog monitoring will not
+ * be running until &rt2x00link_start_watchdog is called.
+ */
+void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00link_register - Initialize link tuning & watchdog functionality
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * Initialize work structure and all link tuning and watchdog related
+ * parameters. This will not start the periodic work itself.
  */
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev);
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 9acfc5c..666cef3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -407,7 +407,45 @@ static void rt2x00link_tuner(struct work_struct *work)
 					     &link->work, LINK_TUNE_INTERVAL);
 }
 
+void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+	struct link *link = &rt2x00dev->link;
+
+	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+	    !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
+		return;
+
+	ieee80211_queue_delayed_work(rt2x00dev->hw,
+				     &link->watchdog_work, WATCHDOG_INTERVAL);
+}
+
+void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+	cancel_delayed_work_sync(&rt2x00dev->link.watchdog_work);
+}
+
+static void rt2x00link_watchdog(struct work_struct *work)
+{
+	struct rt2x00_dev *rt2x00dev =
+	    container_of(work, struct rt2x00_dev, link.watchdog_work.work);
+	struct link *link = &rt2x00dev->link;
+
+	/*
+	 * When the radio is shutting down we should
+	 * immediately cease the watchdog monitoring.
+	 */
+	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		return;
+
+	rt2x00dev->ops->lib->watchdog(rt2x00dev);
+
+	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+		ieee80211_queue_delayed_work(rt2x00dev->hw,
+					     &link->watchdog_work, WATCHDOG_INTERVAL);
+}
+
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
 {
+	INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
 	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
 }
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 5097fe0..a3401d3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -688,9 +688,11 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
 
 	if (index == Q_INDEX) {
 		queue->length++;
+		queue->last_index = jiffies;
 	} else if (index == Q_INDEX_DONE) {
 		queue->length--;
 		queue->count++;
+		queue->last_index_done = jiffies;
 	}
 
 	spin_unlock_irqrestore(&queue->lock, irqflags);
@@ -704,6 +706,8 @@ static void rt2x00queue_reset(struct data_queue *queue)
 
 	queue->count = 0;
 	queue->length = 0;
+	queue->last_index = jiffies;
+	queue->last_index_done = jiffies;
 	memset(queue->index, 0, sizeof(queue->index));
 
 	spin_unlock_irqrestore(&queue->lock, irqflags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index bd54f55..191e777 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -446,6 +446,8 @@ struct data_queue {
 	enum data_queue_qid qid;
 
 	spinlock_t lock;
+	unsigned long last_index;
+	unsigned long last_index_done;
 	unsigned int count;
 	unsigned short limit;
 	unsigned short threshold;
@@ -599,6 +601,15 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)
 }
 
 /**
+ * rt2x00queue_timeout - Check if a timeout occured for this queue
+ * @queue: Queue to check.
+ */
+static inline int rt2x00queue_timeout(struct data_queue *queue)
+{
+	return time_after(queue->last_index, queue->last_index_done + (HZ / 10));
+}
+
+/**
  * _rt2x00_desc_read - Read a word from the hardware descriptor.
  * @desc: Base descriptor address
  * @word: Word index from where the descriptor should be read.
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index a22837c..ff3a366 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -292,6 +292,56 @@ void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);
 
+static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue)
+{
+	struct queue_entry_priv_usb *entry_priv;
+	unsigned short threshold = queue->threshold;
+
+	WARNING(queue->rt2x00dev, "TX queue %d timed out, invoke reset", queue->qid);
+
+	/*
+	 * Temporarily disable the TX queue, this will force mac80211
+	 * to use the other queues until this queue has been restored.
+	 *
+	 * Set the queue threshold to the queue limit. This prevents the
+	 * queue from being enabled during the txdone handler.
+	 */
+	queue->threshold = queue->limit;
+	ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
+
+	/*
+	 * Reset all currently uploaded TX frames.
+	 */
+	while (!rt2x00queue_empty(queue)) {
+		entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data;
+		usb_kill_urb(entry_priv->urb);
+
+		/*
+		 * We need a short delay here to wait for
+		 * the URB to be canceled and invoked the tx_done handler.
+		 */
+		udelay(200);
+	}
+
+	/*
+	 * The queue has been reset, and mac80211 is allowed to use the
+	 * queue again.
+	 */
+	queue->threshold = threshold;
+	ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
+}
+
+void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+
+	tx_queue_for_each(rt2x00dev, queue) {
+		if (rt2x00queue_timeout(queue))
+			rt2x00usb_watchdog_reset_tx(queue);
+	}
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
+
 /*
  * RX data handlers.
  */
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 2b7a188..d3d3ddc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -399,6 +399,16 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
 void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
 			      const enum data_queue_qid qid);
 
+/**
+ * rt2x00usb_watchdog - Watchdog for USB communication
+ * @rt2x00dev: Pointer to &struct rt2x00_dev
+ *
+ * Check the health of the USB communication and determine
+ * if timeouts have occured. If this is the case, this function
+ * will reset all communication to restore functionality again.
+ */
+void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev);
+
 /*
  * Device initialization handlers.
  */
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 9ea6a67..cad07b6 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2136,6 +2136,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	if (!modparam_nohwcrypt)
 		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -2251,6 +2252,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
 	.link_stats		= rt73usb_link_stats,
 	.reset_tuner		= rt73usb_reset_tuner,
 	.link_tuner		= rt73usb_link_tuner,
+	.watchdog		= rt2x00usb_watchdog,
 	.write_tx_desc		= rt73usb_write_tx_desc,
 	.write_beacon		= rt73usb_write_beacon,
 	.get_tx_data_len	= rt73usb_get_tx_data_len,
-- 
1.7.1.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox