symbolic names: lapic and ioapic
Example: nmi_watchdog=2 or nmi_watchdog=panic,lapic
+ netpoll.carrier_timeout=
+ [NET] Specifies amount of time (in seconds) that
+ netpoll should wait for a carrier. By default netpoll
+ waits 4 seconds.
+
no387 [BUGS=X86-32] Tells the kernel to use the 387 maths
emulation library even if a 387 maths coprocessor
is present.
oprofile.cpu_type= Force an oprofile cpu type
This might be useful if you have an older oprofile
userland or if you want common events.
- Format: { archperfmon }
- archperfmon: [X86] Force use of architectural
+ Format: { arch_perfmon }
+ arch_perfmon: [X86] Force use of architectural
perfmon on Intel CPUs instead of the
CPU specific event set.
order. If you could add yourselves to it in alphabetical order that would be
so much easier [Ed]
- P: Person
- M: Mail patches to
+ P: Person (obsolete)
+ M: Mail patches to: FullName <address@domain>
L: Mailing list that is relevant to this area
W: Web-page with status/info
T: SCM tree type and location. Type is one of: git, hg, quilt, stgit.
matches all files in and below net excluding net/ipv6/
3C505 NETWORK DRIVER
- P: Philip Blundell
S: Maintained
F: drivers/net/3c505*
3C59X NETWORK DRIVER
- P: Steffen Klassert
S: Maintained
F: Documentation/networking/vortex.txt
F: drivers/net/3c59x.c
3CR990 NETWORK DRIVER
- P: David Dillow
S: Maintained
F: drivers/net/typhoon*
3W-9XXX SATA-RAID CONTROLLER DRIVER
- P: Adam Radford
W: http://www.amcc.com
S: Supported
F: drivers/scsi/3w-9xxx*
3W-XXXX ATA-RAID CONTROLLER DRIVER
- P: Adam Radford
W: http://www.amcc.com
S: Supported
F: drivers/scsi/3w-xxxx*
53C700 AND 53C700-66 SCSI DRIVER
- P: James E.J. Bottomley
S: Maintained
F: drivers/scsi/53c700*
6PACK NETWORK DRIVER FOR AX.25
- P: Andreas Koensgen
S: Maintained
F: drivers/net/hamradio/6pack.c
8169 10/100/1000 GIGABIT ETHERNET DRIVER
- P: Francois Romieu
S: Maintained
F: drivers/net/r8169.c
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
- P: Alan Cox
W: http://serial.sourceforge.net
- S: Odd Fixes
+ S: Orphan
F: drivers/serial/8250*
F: include/linux/serial_8250.h
8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
- P: Paul Gortmaker
S: Maintained
F: drivers/net/*8390*
F: drivers/net/ax88796.c
9P FILE SYSTEM
- P: Eric Van Hensbergen
- P: Ron Minnich
- P: Latchesar Ionkov
W: http://swik.net/v9fs
T: git git://git.kernel.org/pub/scm/linux/kernel/ericvh/v9fs.git
F: fs/9p/
A2232 SERIAL BOARD DRIVER
- P: Enver Haase
S: Maintained
F: drivers/char/ser_a2232*
AACRAID SCSI RAID DRIVER
- P: Adaptec OEM Raid Solutions
W: http://www.adaptec.com/
S: Supported
F: drivers/scsi/aacraid/
ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
- P: Hans de Goede
S: Maintained
F: drivers/hwmon/abituguru.c
ABIT UGURU 3 HARDWARE MONITOR DRIVER
- P: Alistair John Strachan
S: Maintained
F: drivers/hwmon/abituguru3.c
ACENIC DRIVER
- P: Jes Sorensen
S: Maintained
F: drivers/net/acenic*
ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER
- P: Peter Feuerer
- W: http://piie.net/?section=acerhdf
- S: Maintained
- F: drivers/platform/x86/acerhdf.c
+ W: http://piie.net/?section=acerhdf
+ S: Maintained
+ F: drivers/platform/x86/acerhdf.c
ACER WMI LAPTOP EXTRAS
- P: Carlos Corbacho
W: http://code.google.com/p/aceracpi
S: Maintained
F: drivers/platform/x86/acer-wmi.c
ACPI
- P: Len Brown
W: http://www.lesswatts.org/projects/acpi/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
F: include/linux/acpi.h
ACPI BATTERY DRIVERS
- P: Alexey Starikovskiy
W: http://www.lesswatts.org/projects/acpi/
S: Supported
F: drivers/acpi/*sbs*
ACPI EC DRIVER
- P: Alexey Starikovskiy
W: http://www.lesswatts.org/projects/acpi/
S: Supported
F: drivers/acpi/ec.c
ACPI FAN DRIVER
- P: Zhang Rui
W: http://www.lesswatts.org/projects/acpi/
S: Supported
F: drivers/acpi/fan.c
ACPI PCI HOTPLUG DRIVER
- P: Kristen Carlson Accardi
S: Supported
F: drivers/pci/hotplug/acpi*
ACPI THERMAL DRIVER
- P: Zhang Rui
W: http://www.lesswatts.org/projects/acpi/
S: Supported
F: drivers/acpi/*thermal*
ACPI VIDEO DRIVER
- P: Zhang Rui
W: http://www.lesswatts.org/projects/acpi/
S: Supported
F: drivers/acpi/video.c
ACPI WMI DRIVER
- P: Carlos Corbacho
W: http://www.lesswatts.org/projects/acpi/
S: Maintained
F: drivers/platform/x86/wmi.c
AD1889 ALSA SOUND DRIVER
- P: Kyle McMartin
- P: Thibaut Varene
W: http://wiki.parisc-linux.org/AD1889
S: Maintained
F: sound/pci/ad1889.*
ADM1025 HARDWARE MONITOR DRIVER
- P: Jean Delvare
S: Maintained
F: Documentation/hwmon/adm1025
F: drivers/hwmon/adm1025.c
ADM1029 HARDWARE MONITOR DRIVER
- P: Corentin Labbe
S: Maintained
F: drivers/hwmon/adm1029.c
ADM8211 WIRELESS DRIVER
- P: Michael Wu
W: http://linuxwireless.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
F: drivers/net/wireless/adm8211.*
ADT746X FAN DRIVER
- P: Colin Leroy
S: Maintained
F: drivers/macintosh/therm_adt746x.c
ADVANSYS SCSI DRIVER
- P: Matthew Wilcox
S: Maintained
F: Documentation/scsi/advansys.txt
F: drivers/scsi/advansys.c
AEDSP16 DRIVER
- P: Riccardo Facchetti
S: Maintained
F: sound/oss/aedsp16.c
AFFS FILE SYSTEM
- P: Roman Zippel
S: Maintained
F: Documentation/filesystems/affs.txt
F: fs/affs/
AFS FILESYSTEM & AF_RXRPC SOCKET DOMAIN
- P: David Howells
S: Supported
F: fs/afs/
F: net/rxrpc/af_rxrpc.c
AGPGART DRIVER
- P: David Airlie
T: git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
S: Maintained
F: drivers/char/agp/
F: include/linux/agp*
AHA152X SCSI DRIVER
- P: Juergen E. Fischer
S: Maintained
F: drivers/scsi/aha152x*
F: drivers/scsi/pcmcia/aha152x*
AIC7XXX / AIC79XX SCSI DRIVER
- P: Hannes Reinecke
S: Maintained
F: drivers/scsi/aic7xxx/
F: drivers/scsi/aic7xxx_old/
AIO
- P: Benjamin LaHaise
S: Supported
F: fs/aio.c
F: include/linux/*aio*.h
ALCATEL SPEEDTOUCH USB DRIVER
- P: Duncan Sands
W: http://www.linux-usb.org/SpeedTouch/
S: Maintained
F: drivers/usb/atm/usbatm.c
ALCHEMY AU1XX0 MMC DRIVER
- P: Manuel Lauss
S: Maintained
F: drivers/mmc/host/au1xmmc.c
ALI1563 I2C DRIVER
- P: Rudolf Marek
S: Maintained
F: Documentation/i2c/busses/i2c-ali1563
F: drivers/i2c/busses/i2c-ali1563.c
ALPHA PORT
- P: Richard Henderson
S: Odd Fixes for 2.4; Maintained for 2.6.
- P: Ivan Kokshaysky
S: Maintained for 2.4; PCI support for 2.6.
F: arch/alpha/
AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
- P: Thomas Dahlmann
S: Supported
F: drivers/usb/gadget/amd5536udc.*
F: arch/x86/include/asm/geode.h
AMD IOMMU (AMD-VI)
- P: Joerg Roedel
T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git
S: Supported
F: arch/x86/include/asm/amd_iommu*.h
AMD MICROCODE UPDATE SUPPORT
- P: Andreas Herrmann
S: Supported
F: arch/x86/kernel/microcode_amd.c
AMS (Apple Motion Sensor) DRIVER
- P: Stelian Pop
- P: Michael Hanselmann
S: Supported
F: drivers/hwmon/ams/
AMSO1100 RNIC DRIVER
- P: Tom Tucker
- P: Steve Wise
S: Maintained
F: drivers/infiniband/hw/amso1100/
AOA (Apple Onboard Audio) ALSA DRIVER
- P: Johannes Berg
S: Maintained
F: sound/aoa/
APM DRIVER
- P: Stephen Rothwell
W: http://www.canb.auug.org.au/~sfr/
S: Supported
F: include/linux/apm_bios.h
APPLE BCM5974 MULTITOUCH DRIVER
- P: Henrik Rydberg
S: Maintained
F: drivers/input/mouse/bcm5974.c
APPLE SMC DRIVER
- P: Nicolas Boichat
S: Maintained
F: drivers/hwmon/applesmc.c
APPLETALK NETWORK LAYER
- P: Arnaldo Carvalho de Melo
S: Maintained
F: drivers/net/appletalk/
F: net/appletalk/
APPLETOUCH TOUCHPAD DRIVER
- P: Johannes Berg
S: Maintained
F: Documentation/input/appletouch.txt
F: drivers/input/mouse/appletouch.c
ARC FRAMEBUFFER DRIVER
- P: Jaya Kumar
S: Maintained
F: drivers/video/arcfb.c
F: drivers/video/fb_defio.c
ARM MFM AND FLOPPY DRIVERS
- P: Ian Molton
S: Maintained
F: arch/arm/lib/floppydma.S
F: arch/arm/include/asm/floppy.h
ARM PORT
- P: Russell King
W: http://www.arm.linux.org.uk/
S: Maintained
F: drivers/mmc/host/mmci.*
ARM/ADI ROADRUNNER MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
F: arch/arm/mach-ixp23xx/
F: arch/arm/mach-ixp23xx/include/mach/
ARM/ADS SPHERE MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/AFEB9260 MACHINE SUPPORT
- P: Sergey Lapin
S: Maintained
ARM/AJECO 1ARM MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/ATMEL AT91RM9200 ARM ARCHITECTURE
- P: Andrew Victor
W: http://maxim.org.za/at91_26.html
S: Maintained
ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
- P: Lennert Buytenhek
S: Maintained
ARM/CIRRUS LOGIC EDB9315A MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/CLKDEV SUPPORT
- P: Russell King
F: arch/arm/common/clkdev.c
F: arch/arm/include/asm/clkdev.h
ARM/COMPULAB CM-X270/EM-X270 and CM-X300 MACHINE SUPPORT
- P: Mike Rapoport
S: Maintained
ARM/CORGI MACHINE SUPPORT
- P: Richard Purdie
S: Maintained
ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
- P: Paulius Zaleckas
T: git git://gitorious.org/linux-gemini/mainline.git
S: Maintained
F: arch/arm/mach-gemini/
ARM/EBSA110 MACHINE SUPPORT
- P: Russell King
W: http://www.arm.linux.org.uk/
S: Maintained
F: drivers/net/arm/am79c961a.*
ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
- P: Daniel Ribeiro
- P: Stefan Schmidt
- P: Harald Welte
W: http://www.openezx.org/
S: Maintained
F: arch/arm/mach-pxa/ezx.c
ARM/FARADAY FA526 PORT
- P: Paulius Zaleckas
S: Maintained
F: arch/arm/mm/*-fa*
ARM/FOOTBRIDGE ARCHITECTURE
- P: Russell King
W: http://www.arm.linux.org.uk/
S: Maintained
F: arch/arm/mach-footbridge/
ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
- P: Sascha Hauer
S: Maintained
ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/GUMSTIX MACHINE SUPPORT
- P: Steve Sakoman
S: Maintained
ARM/H4700 (HP IPAQ HX4700) MACHINE SUPPORT
- P: Philipp Zabel
S: Maintained
F: arch/arm/mach-pxa/hx4700.c
F: arch/arm/mach-pxa/include/mach/hx4700.h
ARM/HP JORNADA 7XX MACHINE SUPPORT
- P: Kristoffer Ericson
W: www.jlime.com
S: Maintained
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
+ F: arch/arm/mach-sa1100/jornada720.c
+ F: arch/arm/mach-sa1100/include/mach/jornada720.h
ARM/INTEL IOP32X ARM ARCHITECTURE
- P: Lennert Buytenhek
- P: Dan Williams
S: Supported
ARM/INTEL IOP33X ARM ARCHITECTURE
- P: Dan Williams
S: Supported
ARM/INTEL IOP13XX ARM ARCHITECTURE
- P: Lennert Buytenhek
- P: Dan Williams
S: Supported
ARM/INTEL IQ81342EX MACHINE SUPPORT
- P: Lennert Buytenhek
- P: Dan Williams
S: Supported
ARM/INTEL IXP2000 ARM ARCHITECTURE
- P: Lennert Buytenhek
S: Maintained
ARM/INTEL IXDP2850 MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/INTEL IXP23XX ARM ARCHITECTURE
- P: Lennert Buytenhek
S: Maintained
ARM/INTEL XSC3 (MANZANO) ARM CORE
- P: Lennert Buytenhek
- P: Dan Williams
S: Supported
ARM/IP FABRICS DOUBLE ESPRESSO MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/LOGICPD PXA270 MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/MAGICIAN MACHINE SUPPORT
- P: Philipp Zabel
S: Maintained
ARM/MIOA701 MACHINE SUPPORT
- P: Robert Jarzmik
F: arch/arm/mach-pxa/mioa701.c
S: Maintained
ARM/NEC MOBILEPRO 900/c MACHINE SUPPORT
- P: Michael Petchkovsky
S: Maintained
ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
- P: Nelson Castillo
W: http://wiki.openmoko.org/wiki/Neo_FreeRunner
S: Supported
ARM/TOSA MACHINE SUPPORT
- P: Dmitry Eremin-Solenikov
- P: Dirk Opfer
S: Maintained
ARM/PALMTX,PALMT5,PALMLD,PALMTE2 SUPPORT
- P: Marek Vasut
W: http://hackndev.com
S: Maintained
ARM/PALM TREO 680 SUPPORT
- P: Tomas Cech
W: http://hackndev.com
S: Maintained
ARM/PALMZ72 SUPPORT
- P: Sergey Lapin
W: http://hackndev.com
S: Maintained
ARM/PLEB SUPPORT
- P: Peter Chubb
W: http://www.disy.cse.unsw.edu.au/Hardware/PLEB
S: Maintained
ARM/PT DIGITAL BOARD PORT
- P: Stefan Eletzhofer
W: http://www.arm.linux.org.uk/
S: Maintained
ARM/RADISYS ENP2611 MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/RISCPC ARCHITECTURE
- P: Russell King
W: http://www.arm.linux.org.uk/
S: Maintained
F: drivers/scsi/arm/
ARM/SHARK MACHINE SUPPORT
- P: Alexander Schulz
W: http://www.shark-linux.de/shark.html
S: Maintained
ARM/SAMSUNG ARM ARCHITECTURES
- P: Ben Dooks
W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/plat-s3c24xx/
ARM/S3C2410 ARM ARCHITECTURE
- P: Ben Dooks
W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/mach-s3c2410/
ARM/S3C2440 ARM ARCHITECTURE
- P: Ben Dooks
W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/mach-s3c2440/
ARM/S3C2442 ARM ARCHITECTURE
- P: Ben Dooks
W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/mach-s3c2442/
ARM/S3C2443 ARM ARCHITECTURE
- P: Ben Dooks
W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/mach-s3c2443/
ARM/S3C6400 ARM ARCHITECTURE
- P: Ben Dooks
W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/mach-s3c6400/
ARM/S3C6410 ARM ARCHITECTURE
- P: Ben Dooks
W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/mach-s3c6410/
ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/THECUS N2100 MACHINE SUPPORT
- P: Lennert Buytenhek
S: Maintained
ARM/NUVOTON W90X900 ARM ARCHITECTURE
- P: Wan ZongShun
W: http://www.mcuos.com
S: Maintained
ARM/VFP SUPPORT
- P: Russell King
W: http://www.arm.linux.org.uk/
S: Maintained
F: arch/arm/vfp/
- ARPD SUPPORT
- P: Jonathan Layes
- S: Maintained
- F: net/ipv4/arp.c
-
ASUS ACPI EXTRAS DRIVER
- P: Corentin Chary
- P: Karol Kozimor
W: http://acpi4asus.sf.net
S: Maintained
F: drivers/platform/x86/asus_acpi.c
ASUS ASB100 HARDWARE MONITOR DRIVER
- P: Mark M. Hoffman
S: Maintained
F: drivers/hwmon/asb100.c
ASUS LAPTOP EXTRAS DRIVER
- P: Corentin Chary
W: http://acpi4asus.sf.net
S: Maintained
F: drivers/platform/x86/asus-laptop.c
ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API
- P: Dan Williams
- P: Maciej Sosnowski
W: http://sourceforge.net/projects/xscaleiop
S: Supported
F: Documentation/crypto/async-tx-api.txt
F: include/linux/async_tx.h
ATA OVER ETHERNET (AOE) DRIVER
- P: Ed L. Cashin
W: http://www.coraid.com/support/linux
S: Supported
F: Documentation/aoe/
F: drivers/block/aoe/
ATHEROS ATH5K WIRELESS DRIVER
- P: Jiri Slaby
- P: Nick Kossifidis
- P: Luis R. Rodriguez
- P: Bob Copeland
S: Maintained
F: drivers/net/wireless/ath/ath5k/
ATHEROS ATH9K WIRELESS DRIVER
- P: Luis R. Rodriguez
- P: Jouni Malinen
- P: Sujith Manoharan
- P: Vasanthakumar Thiagarajan
- P: Senthil Balasubramanian
S: Supported
F: drivers/net/wireless/ath/ath9k/
ATHEROS AR9170 WIRELESS DRIVER
- P: Christian Lamparter
W: http://wireless.kernel.org/en/users/Drivers/ar9170
S: Maintained
F: drivers/net/wireless/ath/ar9170/
ATI_REMOTE2 DRIVER
- P: Ville Syrjala
S: Maintained
F: drivers/input/misc/ati_remote2.c
ATLX ETHERNET DRIVERS
- P: Jay Cliburn
- P: Chris Snook
- P: Jie Yang
W: http://sourceforge.net/projects/atl1
W: http://atl1.sourceforge.net
F: drivers/net/atlx/
ATM
- P: Chas Williams
W: http://linux-atm.sourceforge.net
F: include/linux/atm*
ATMEL AT91 MCI DRIVER
- P: Nicolas Ferre
W: http://www.atmel.com/products/AT91/
W: http://www.at91.com/
F: drivers/mmc/host/at91_mci.c
ATMEL AT91 / AT32 MCI DRIVER
- P: Nicolas Ferre
S: Maintained
F: drivers/mmc/host/atmel-mci.c
F: drivers/mmc/host/atmel-mci-regs.h
ATMEL AT91 / AT32 SERIAL DRIVER
- P: Haavard Skinnemoen
S: Supported
F: drivers/serial/atmel_serial.c
ATMEL LCDFB DRIVER
- P: Nicolas Ferre
S: Maintained
F: drivers/video/atmel_lcdfb.c
F: include/video/atmel_lcdc.h
ATMEL MACB ETHERNET DRIVER
- P: Haavard Skinnemoen
S: Supported
F: drivers/net/macb.*
ATMEL SPI DRIVER
- P: Haavard Skinnemoen
S: Supported
F: drivers/spi/atmel_spi.*
ATMEL USBA UDC DRIVER
- P: Haavard Skinnemoen
W: http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver
S: Supported
F: drivers/usb/gadget/atmel_usba_udc.*
ATMEL WIRELESS DRIVER
- P: Simon Kelley
W: http://www.thekelleys.org.uk/atmel
W: http://atmelwlandriver.sourceforge.net/
F: drivers/net/wireless/atmel*
AUDIT SUBSYSTEM
- P: Al Viro
- P: Eric Paris
W: http://people.redhat.com/sgrubb/audit/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git
F: kernel/audit*
AUXILIARY DISPLAY DRIVERS
- P: Miguel Ojeda Sandonis
W: http://miguelojeda.es/auxdisplay.htm
W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
S: Maintained
F: include/linux/cfag12864b.h
AVR32 ARCHITECTURE
- P: Haavard Skinnemoen
W: http://www.atmel.com/products/AVR32/
W: http://avr32linux.org/
W: http://avrfreaks.net/
F: arch/avr32/
AVR32/AT32AP MACHINE SUPPORT
- P: Haavard Skinnemoen
S: Supported
F: arch/avr32/mach-at32ap/
AX.25 NETWORK LAYER
- P: Ralf Baechle
W: http://www.linux-ax25.org/
S: Maintained
F: net/ax25/
B43 WIRELESS DRIVER
- P: Michael Buesch
- P: Stefano Brivio
W: http://linuxwireless.org/en/users/Drivers/b43
S: Maintained
F: drivers/net/wireless/b43/
B43LEGACY WIRELESS DRIVER
- P: Larry Finger
- P: Stefano Brivio
W: http://linuxwireless.org/en/users/Drivers/b43
S: Maintained
F: drivers/net/wireless/b43legacy/
BACKLIGHT CLASS/SUBSYSTEM
- P: Richard Purdie
S: Maintained
F: drivers/video/backlight/
F: include/linux/backlight.h
BAYCOM/HDLCDRV DRIVERS FOR AX.25
- P: Thomas Sailer
W: http://www.baycom.org/~tom/ham/ham.html
S: Maintained
F: drivers/net/hamradio/baycom*
BEFS FILE SYSTEM
- P: Sergey S. Kostyliov
S: Maintained
F: Documentation/filesystems/befs.txt
F: fs/befs/
BFS FILE SYSTEM
- P: Tigran A. Aivazian
S: Maintained
F: Documentation/filesystems/bfs.txt
F: fs/bfs/
F: include/linux/bfs_fs.h
BLACKFIN ARCHITECTURE
- P: Mike Frysinger
W: http://blackfin.uclinux.org
S: Supported
F: arch/blackfin/
BLACKFIN EMAC DRIVER
- P: Michael Hennerich
W: http://blackfin.uclinux.org
S: Supported
F: drivers/net/bfin_mac.*
BLACKFIN RTC DRIVER
- P: Mike Frysinger
W: http://blackfin.uclinux.org
S: Supported
F: drivers/rtc/rtc-bfin.c
BLACKFIN SERIAL DRIVER
- P: Sonic Zhang
W: http://blackfin.uclinux.org
S: Supported
F: drivers/serial/bfin_5xx.c
BLACKFIN WATCHDOG DRIVER
- P: Mike Frysinger
W: http://blackfin.uclinux.org
S: Supported
F: drivers/watchdog/bfin_wdt.c
BLACKFIN I2C TWI DRIVER
- P: Sonic Zhang
W: http://blackfin.uclinux.org/
S: Supported
F: drivers/i2c/busses/i2c-bfin-twi.c
BLOCK LAYER
- P: Jens Axboe
T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
S: Maintained
F: block/
BLOCK2MTD DRIVER
- P: Joern Engel
S: Maintained
F: drivers/mtd/devices/block2mtd.c
BLUETOOTH DRIVERS
- P: Marcel Holtmann
W: http://www.bluez.org/
S: Maintained
F: drivers/bluetooth/
BLUETOOTH SUBSYSTEM
- P: Marcel Holtmann
W: http://www.bluez.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git
F: include/net/bluetooth/
BONDING DRIVER
- P: Jay Vosburgh
W: http://sourceforge.net/projects/bonding/
S: Supported
F: include/linux/if_bonding.h
BROADCOM B44 10/100 ETHERNET DRIVER
- P: Gary Zambrano
S: Supported
F: drivers/net/b44.*
BROADCOM BNX2 GIGABIT ETHERNET DRIVER
- P: Michael Chan
S: Supported
F: drivers/net/bnx2.*
F: drivers/net/bnx2_*
BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
- P: Eilon Greenstein
S: Supported
F: drivers/net/bnx2x*
BROADCOM TG3 GIGABIT ETHERNET DRIVER
- P: Matt Carlson
- P: Michael Chan
S: Supported
F: drivers/net/tg3.*
BSG (block layer generic sg v4 driver)
- P: FUJITA Tomonori
S: Supported
F: block/bsg.c
F: include/linux/bsg.h
BT8XXGPIO DRIVER
- P: Michael Buesch
W: http://bu3sch.de/btgpio.php
S: Maintained
F: drivers/gpio/bt8xxgpio.c
BTRFS FILE SYSTEM
- P: Chris Mason
W: http://btrfs.wiki.kernel.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git
F: fs/btrfs/
BTTV VIDEO4LINUX DRIVER
- P: Mauro Carvalho Chehab
W: http://linuxtv.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
F: drivers/media/video/bt8xx/bttv*
CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS
- P: David Howells
S: Supported
F: Documentation/filesystems/caching/cachefiles.txt
F: fs/cachefiles/
CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
- P: Jonathan Corbet
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
F: drivers/media/video/cafe_ccic*
CALGARY x86-64 IOMMU
- P: Muli Ben-Yehuda
- P: Jon D. Mason
S: Maintained
F: arch/x86/kernel/pci-calgary_64.c
F: arch/x86/include/asm/tce.h
CAN NETWORK LAYER
- P: Urs Thuermann
- P: Oliver Hartkopp
W: http://developer.berlios.de/projects/socketcan/
S: Maintained
F: include/linux/can.h
CAN NETWORK DRIVERS
- P: Wolfgang Grandegger
W: http://developer.berlios.de/projects/socketcan/
S: Maintained
CELL BROADBAND ENGINE ARCHITECTURE
- P: Arnd Bergmann
W: http://www.ibm.com/developerworks/power/cell/
F: arch/powerpc/platforms/cell/
CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
- P: David Vrabel
S: Supported
F: Documentation/usb/WUSB-Design-overview.txt
F: include/linux/usb/wusb*
CFAG12864B LCD DRIVER
- P: Miguel Ojeda Sandonis
W: http://miguelojeda.es/auxdisplay.htm
W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
S: Maintained
F: include/linux/cfag12864b.h
CFAG12864BFB LCD FRAMEBUFFER DRIVER
- P: Miguel Ojeda Sandonis
W: http://miguelojeda.es/auxdisplay.htm
W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
S: Maintained
F: include/linux/cfag12864b.h
CFG80211 and NL80211
- P: Johannes Berg
S: Maintained
F: include/linux/nl80211.h
X: net/wireless/wext*
CHECKPATCH
- P: Andy Whitcroft
S: Supported
F: scripts/checkpatch.pl
CISCO 10G ETHERNET DRIVER
- P: Scott Feldman
- P: Joe Eykholt
S: Supported
F: drivers/net/enic/
CIRRUS LOGIC EP93XX ETHERNET DRIVER
- P: Lennert Buytenhek
S: Maintained
F: drivers/net/arm/ep93xx_eth.c
CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER
- P: Lennert Buytenhek
S: Maintained
F: drivers/usb/host/ohci-ep93xx.c
CIRRUS LOGIC CS4270 SOUND DRIVER
- P: Timur Tabi
S: Supported
F: sound/soc/codecs/cs4270*
- CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
- P: Cirrus Logic Corporation (kernel 2.2 driver)
- P: Nils Faerber (port to kernel 2.4)
- S: Maintained
- F: Documentation/input/cs461x.txt
- F: sound/pci/cs46xx/
-
CLK API
- P: Russell King
F: include/linux/clk.h
CISCO FCOE HBA DRIVER
- P: Abhijeet Joglekar
- P: Joe Eykholt
S: Supported
F: drivers/scsi/fnic/
CODA FILE SYSTEM
- P: Jan Harkes
W: http://www.coda.cs.cmu.edu/
F: include/linux/coda*.h
COMMON INTERNET FILE SYSTEM (CIFS)
- P: Steve French
W: http://linux-cifs.samba.org/
F: fs/cifs/
COMPACTPCI HOTPLUG CORE
- P: Scott Murray
- S: Supported
+ S: Maintained
F: drivers/pci/hotplug/cpci_hotplug*
COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
- P: Scott Murray
- S: Supported
+ S: Maintained
F: drivers/pci/hotplug/cpcihp_zt5550.*
COMPACTPCI HOTPLUG GENERIC DRIVER
- P: Scott Murray
- S: Supported
+ S: Maintained
F: drivers/pci/hotplug/cpcihp_generic.c
COMPAL LAPTOP SUPPORT
- P: Cezary Jackiewicz
S: Maintained
F: drivers/platform/x86/compal-laptop.c
COMPUTONE INTELLIPORT MULTIPORT CARD
- P: Michael H. Warfield
W: http://www.wittsend.com/computone.html
S: Maintained
F: Documentation/serial/computone.txt
F: drivers/char/ip2/
CONEXANT ACCESSRUNNER USB DRIVER
- P: Simon Arlott
W: http://accessrunner.sourceforge.net/
S: Maintained
F: drivers/usb/atm/cxacru.c
CONFIGFS
- P: Joel Becker
S: Supported
F: fs/configfs/
F: include/linux/configfs.h
CONNECTOR
- P: Evgeniy Polyakov
S: Maintained
F: drivers/connector/
CONTROL GROUPS (CGROUPS)
- P: Paul Menage
- P: Li Zefan
S: Maintained
F: include/linux/cgroup*
F: mm/*cgroup*
CORETEMP HARDWARE MONITORING DRIVER
- P: Rudolf Marek
S: Maintained
F: Documentation/hwmon/coretemp
F: drivers/hwmon/coretemp.c
COSA/SRP SYNC SERIAL DRIVER
- P: Jan "Yenya" Kasprzak
W: http://www.fi.muni.cz/~kas/cosa/
S: Maintained
F: drivers/net/wan/cosa*
CPMAC ETHERNET DRIVER
- P: Florian Fainelli
S: Maintained
F: drivers/net/cpmac.c
CPU FREQUENCY DRIVERS
- P: Dave Jones
W: http://www.codemonkey.org.uk/projects/cpufreq/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git
F: include/linux/cpufreq.h
CPUID/MSR DRIVER
- P: H. Peter Anvin
S: Maintained
F: arch/x86/kernel/cpuid.c
F: arch/x86/kernel/msr.c
CPUSETS
- P: Paul Menage
W: http://www.bullopensource.org/cpuset/
W: http://oss.sgi.com/projects/cpusets/
S: Supported
F: fs/cramfs/
CRIS PORT
- P: Mikael Starvik
- P: Jesper Nilsson
W: http://developer.axis.com
S: Maintained
F: arch/cris/
CRYPTO API
- P: Herbert Xu
- P: David S. Miller
T: git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
S: Maintained
F: include/crypto/
CRYPTOGRAPHIC RANDOM NUMBER GENERATOR
- P: Neil Horman
S: Maintained
CS5535 Audio ALSA driver
- P: Jaya Kumar
S: Maintained
F: sound/pci/cs5535audio/
CX18 VIDEO4LINUX DRIVER
- P: Hans Verkuil
- P: Andy Walls
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://linuxtv.org
+ W: http://www.ivtvdriver.org/index.php/Cx18
S: Maintained
F: Documentation/video4linux/cx18.txt
F: drivers/media/video/cx18/
CXGB3 ETHERNET DRIVER (CXGB3)
- P: Divy Le Ray
W: http://www.chelsio.com
S: Supported
F: drivers/net/cxgb3/
CXGB3 IWARP RNIC DRIVER (IW_CXGB3)
- P: Steve Wise
W: http://www.openfabrics.org
S: Supported
F: drivers/infiniband/hw/cxgb3/
CYBERPRO FB DRIVER
- P: Russell King
W: http://www.arm.linux.org.uk/
S: Maintained
F: drivers/video/cyber2000fb.*
CYCLADES 2X SYNC CARD DRIVER
- P: Arnaldo Carvalho de Melo
W: http://oops.ghostprotocols.net:81/blog
S: Maintained
F: drivers/net/wan/cycx*
F: drivers/net/wan/pc300*
DAMA SLAVE for AX.25
- P: Joerg Reuter
W: http://yaina.de/jreuter/
W: http://www.qsl.net/dl1bke/
F: net/ax25/sysctl_net_ax25.c
DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
- P: Tobias Ringstrom
S: Maintained
F: Documentation/networking/dmfe.txt
F: drivers/net/tulip/dmfe.c
DC390/AM53C974 SCSI driver
- P: Kurt Garloff
W: http://www.garloff.de/kurt/linux/dc390/
- P: Guennadi Liakhovetski
S: Maintained
F: drivers/scsi/tmscsim.*
DC395x SCSI driver
- P: Oliver Neukum
- P: Ali Akcaagac
- P: Jamie Lenehan
W: http://twibble.org/dist/dc395x/
L: http://lists.twibble.org/mailman/listinfo/dc395x/
F: drivers/scsi/dc395x.*
DCCP PROTOCOL
- P: Arnaldo Carvalho de Melo
W: http://linux-net.osdl.org/index.php/DCCP
S: Maintained
F: net/dccp/
DECnet NETWORK LAYER
- P: Christine Caulfield
W: http://linux-decnet.sourceforge.net
S: Maintained
F: net/decnet/
DEFXX FDDI NETWORK DRIVER
- P: Maciej W. Rozycki
S: Maintained
F: drivers/net/defxx.*
DELL LAPTOP DRIVER
- P: Matthew Garrett
S: Maintained
F: drivers/platform/x86/dell-laptop.c
DELL LAPTOP SMM DRIVER
- P: Massimo Dal Zotto
W: http://www.debian.org/~dz/i8k/
S: Maintained
F: drivers/char/i8k.c
F: include/linux/i8k.h
DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
- P: Doug Warzecha
S: Maintained
F: Documentation/dcdbas.txt
F: drivers/firmware/dcdbas.*
DELL WMI EXTRAS DRIVER
- P: Matthew Garrett
S: Maintained
DEVICE NUMBER REGISTRY
- P: Torben Mathiasen
W: http://lanana.org/docs/device-list/index.html
S: Maintained
F: include/linux/dm-*.h
DIGI INTL. EPCA DRIVER
- P: Digi International, Inc
W: http://www.digi.com
S: Orphan
F: drivers/char/digi*
DIRECTORY NOTIFICATION (DNOTIFY)
- P: Eric Paris
S: Maintained
F: Documentation/filesystems/dnotify.txt
F: fs/notify/dnotify/
F: include/linux/dnotify.h
DISK GEOMETRY AND PARTITION HANDLING
- P: Andries Brouwer
W: http://www.win.tue.nl/~aeb/linux/Large-Disk.html
W: http://www.win.tue.nl/~aeb/linux/zip/zip-1.html
W: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
S: Maintained
DISKQUOTA
- P: Jan Kara
S: Maintained
F: Documentation/filesystems/quota.txt
F: fs/quota/
F: include/linux/quota*.h
DISTRIBUTED LOCK MANAGER (DLM)
- P: Christine Caulfield
- P: David Teigland
W: http://sources.redhat.com/cluster/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm.git
F: fs/dlm/
DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
- P: Maciej Sosnowski
- P: Dan Williams
S: Supported
F: drivers/dma/
F: include/linux/dma*
DME1737 HARDWARE MONITOR DRIVER
- P: Juerg Haefliger
S: Maintained
F: Documentation/hwmon/dme1737
F: drivers/hwmon/dme1737.c
DOCBOOK FOR DOCUMENTATION
- P: Randy Dunlap
S: Maintained
DOCKING STATION DRIVER
- P: Shaohua Li
S: Supported
F: drivers/acpi/dock.c
DOCUMENTATION
- P: Randy Dunlap
S: Maintained
F: Documentation/
DOUBLETALK DRIVER
- P: James R. Van Zandt
S: Maintained
F: drivers/char/dtlk.c
F: include/linux/dtlk.h
DPT_I2O SCSI RAID DRIVER
- P: Adaptec OEM Raid Solutions
W: http://www.adaptec.com/
S: Maintained
F: drivers/scsi/dpt/
DRIVER CORE, KOBJECTS, AND SYSFS
- P: Greg Kroah-Hartman
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
S: Supported
F: Documentation/kobject.txt
F: lib/kobj*
DRM DRIVERS
- P: David Airlie
T: git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
S: Maintained
F: drivers/gpu/drm/
DSCC4 DRIVER
- P: Francois Romieu
S: Maintained
F: drivers/net/wan/dscc4.c
DZ DECSTATION DZ11 SERIAL DRIVER
- P: Maciej W. Rozycki
S: Maintained
F: drivers/serial/dz.*
EATA-DMA SCSI DRIVER
- P: Michael Neuffer
S: Maintained
F: drivers/scsi/eata*
EATA ISA/EISA/PCI SCSI DRIVER
- P: Dario Ballabio
S: Maintained
F: drivers/scsi/eata.c
EATA-PIO SCSI DRIVER
- P: Michael Neuffer
S: Maintained
F: drivers/scsi/eata_pio.*
EBTABLES
- P: Bart De Schuymer
W: http://ebtables.sourceforge.net/
F: net/bridge/netfilter/ebt*.c
ECRYPT FILE SYSTEM
- P: Tyler Hicks
- P: Dustin Kirkland
W: https://launchpad.net/ecryptfs
S: Supported
F: fs/ecryptfs/
EDAC-CORE
- P: Doug Thompson
W: bluesmoke.sourceforge.net
S: Supported
F: include/linux/edac.h
EDAC-AMD64
- P: Doug Thompson
- P: Borislav Petkov
W: bluesmoke.sourceforge.net
S: Supported
F: drivers/edac/amd64_edac*
EDAC-E752X
- P: Mark Gross
- P: Doug Thompson
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/e752x_edac.c
EDAC-E7XXX
- P: Doug Thompson
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/e7xxx_edac.c
EDAC-I82443BXGX
- P: Tim Small
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i82443bxgx_edac.c
EDAC-I3000
- P: Jason Uhlenkott
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i3000_edac.c
EDAC-I5000
- P: Doug Thompson
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i5000_edac.c
EDAC-I5400
- P: Mauro Carvalho Chehab
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i5400_edac.c
EDAC-I82975X
- P: Ranganathan Desikan
- P: Arvind R.
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i82975x_edac.c
EDAC-PASEMI
- P: Egor Martovetsky
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/pasemi_edac.c
EDAC-R82600
- P: Tim Small
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/r82600_edac.c
EEEPC LAPTOP EXTRAS DRIVER
- P: Corentin Chary
W: http://acpi4asus.sf.net
S: Maintained
F: fs/efs/
EHCA (IBM GX bus InfiniBand adapter) DRIVER
- P: Hoang-Nam Nguyen
- P: Christoph Raisch
S: Supported
F: drivers/infiniband/hw/ehca/
EMBEDDED LINUX
- P: Paul Gortmaker
- P: Matt Mackall
- P: David Woodhouse
S: Maintained
EMULEX LPFC FC SCSI DRIVER
- P: James Smart
W: http://sourceforge.net/projects/lpfcxxxx
S: Supported
F: drivers/scsi/lpfc/
ENE CB710 FLASH CARD READER DRIVER
- P: Michał Mirosław
S: Maintained
F: drivers/misc/cb710/
F: drivers/mmc/host/cb710-mmc.*
F: include/linux/cb710.h
EPSON 1355 FRAMEBUFFER DRIVER
- P: Christopher Hoover
- P: Christopher Hoover
S: Maintained
F: drivers/video/epson1355fb.c
EPSON S1D13XXX FRAMEBUFFER DRIVER
- P: Kristoffer Ericson
S: Maintained
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
F: drivers/video/s1d13xxxfb.c
F: include/video/s1d13xxxfb.h
ETHEREXPRESS-16 NETWORK DRIVER
- P: Philip Blundell
S: Maintained
F: drivers/net/eexpress.*
ETHERNET BRIDGE
- P: Stephen Hemminger
W: http://www.linux-foundation.org/en/Net:Bridge
S: Maintained
F: net/bridge/
ETHERTEAM 16I DRIVER
- P: Mika Kuoppala
S: Maintained
F: drivers/net/eth16i.c
F: include/linux/ext2*
EXT3 FILE SYSTEM
- P: Stephen Tweedie
- P: Andrew Morton
- P: Andreas Dilger
S: Maintained
F: Documentation/filesystems/ext3.txt
F: include/linux/ext3*
EXT4 FILE SYSTEM
- P: Theodore Ts'o
- P: Andreas Dilger
W: http://ext4.wiki.kernel.org
S: Maintained
F: fs/ext4/
F71805F HARDWARE MONITORING DRIVER
- P: Jean Delvare
S: Maintained
F: Documentation/hwmon/f71805f
F: drivers/hwmon/f71805f.c
FARSYNC SYNCHRONOUS DRIVER
- P: Kevin Curtis
W: http://www.farsite.co.uk/
S: Supported
F: drivers/net/wan/farsync.*
FAULT INJECTION SUPPORT
- P: Akinobu Mita
S: Supported
F: Documentation/fault-injection/
F: lib/fault-inject.c
FILE LOCKING (flock() and fcntl()/lockf())
- P: Matthew Wilcox
S: Maintained
F: include/linux/fcntl.h
F: fs/locks.c
FILESYSTEMS (VFS and infrastructure)
- P: Alexander Viro
S: Maintained
F: fs/*
FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
- P: Riku Voipio
S: Maintained
F: drivers/hwmon/f75375s.c
F: include/linux/f75375s.h
FIREWIRE SUBSYSTEM
- P: Kristian Hoegsberg
- P: Stefan Richter
W: http://www.linux1394.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
F: include/linux/firmware.h
FPU EMULATOR
- P: Bill Metzenthen
W: http://floatingpoint.sourceforge.net/emulator/index.html
S: Maintained
F: arch/x86/math-emu/
FRAME RELAY DLCI/FRAD (Sangoma drivers too)
- P: Mike McLagan
S: Maintained
F: drivers/net/wan/dlci.c
F: include/linux/fb.h
FREESCALE DMA DRIVER
- P: Li Yang
- P: Zhang Wei
S: Maintained
F: drivers/dma/fsldma.*
FREESCALE I2C CPM DRIVER
- P: Jochen Friedrich
S: Maintained
F: drivers/i2c/busses/i2c-cpm.c
FREESCALE IMX / MXC FRAMEBUFFER DRIVER
- P: Sascha Hauer
S: Maintained
F: drivers/video/imxfb.c
FREESCALE SOC FS_ENET DRIVER
- P: Pantelis Antoniou
- P: Vitaly Bordug
S: Maintained
F: include/linux/fs_enet_pd.h
FREESCALE QUICC ENGINE LIBRARY
- P: Timur Tabi
S: Supported
F: arch/powerpc/sysdev/qe_lib/
F: arch/powerpc/include/asm/*qe.h
FREESCALE HIGHSPEED USB DEVICE DRIVER
- P: Li Yang
S: Maintained
F: drivers/usb/gadget/fsl_usb2_udc.c
FREESCALE QUICC ENGINE UCC ETHERNET DRIVER
- P: Li Yang
S: Maintained
F: drivers/net/ucc_geth*
FREESCALE QUICC ENGINE UCC UART DRIVER
- P: Timur Tabi
S: Supported
F: drivers/serial/ucc_uart.c
FREESCALE SOC SOUND DRIVERS
- P: Timur Tabi
S: Supported
F: sound/soc/fsl/mpc8610_hpcd.c
FREEVXFS FILESYSTEM
- P: Christoph Hellwig
W: ftp://ftp.openlinux.org/pub/people/hch/vxfs
S: Maintained
F: fs/freevxfs/
FREEZER
- P: Pavel Machek
- P: Rafael J. Wysocki
S: Supported
F: Documentation/power/freezing-of-tasks.txt
F: kernel/freezer.c
FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS
- P: David Howells
S: Supported
F: Documentation/filesystems/caching/
F: include/linux/fscache*.h
FTRACE
- P: Steven Rostedt
S: Maintained
F: Documentation/trace/ftrace.txt
F: arch/*/*/*/ftrace.h
F: kernel/trace/
FUJITSU FR-V (FRV) PORT
- P: David Howells
S: Maintained
F: arch/frv/
FUJITSU LAPTOP EXTRAS
- P: Jonathan Woithe
S: Maintained
F: drivers/platform/x86/fujitsu-laptop.c
FUSE: FILESYSTEM IN USERSPACE
- P: Miklos Szeredi
W: http://fuse.sourceforge.net/
S: Maintained
F: include/linux/fuse.h
FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit)
- P: Rik Faith
S: Odd Fixes (e.g., new signatures)
F: drivers/scsi/fdomain.*
GDT SCSI DISK ARRAY CONTROLLER DRIVER
- P: Achim Leubner
W: http://www.icp-vortex.com/
S: Supported
F: drivers/scsi/gdt*
GENERIC GPIO I2C DRIVER
- P: Haavard Skinnemoen
S: Supported
F: drivers/i2c/busses/i2c-gpio.c
F: include/linux/i2c-gpio.h
GENERIC HDLC (WAN) DRIVERS
- P: Krzysztof Halasa
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
S: Maintained
F: drivers/net/wan/c101.c
F: drivers/net/wan/wanxl*
GENERIC INCLUDE/ASM HEADER FILES
- P: Arnd Bergmann
T: git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git
S: Maintained
F: include/asm-generic
GFS2 FILE SYSTEM
- P: Steven Whitehouse
W: http://sources.redhat.com/cluster/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes.git
F: include/linux/gfs2_ondisk.h
GIGASET ISDN DRIVERS
- P: Hansjoerg Lipp
- P: Tilman Schmidt
W: http://gigaset307x.sourceforge.net/
S: Maintained
F: include/linux/gigaset_dev.h
HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
- P: Frank Seidel
W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
S: Maintained
F: drivers/char/hvc_*
GSPCA FINEPIX SUBDRIVER
- P: Frank Zago
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
F: drivers/media/video/gspca/finepix.c
GSPCA M5602 SUBDRIVER
- P: Erik Andren
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
F: drivers/media/video/gspca/m5602/
GSPCA PAC207 SONIXB SUBDRIVER
- P: Hans de Goede
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
F: drivers/media/video/gspca/pac207.c
GSPCA T613 SUBDRIVER
- P: Leandro Costantino
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
F: drivers/media/video/gspca/t613.c
GSPCA USB WEBCAM DRIVER
- P: Jean-Francois Moine
W: http://moinejf.free.fr
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
F: include/linux/hw_random.h
HARMONY SOUND DRIVER
- P: Kyle McMartin
S: Maintained
F: sound/parisc/harmony.*
HAYES ESP SERIAL DRIVER
- P: Andrew J. Robinson
W: http://www.nyx.net/~arobinso
S: Maintained
F: Documentation/serial/hayes-esp.txt
F: drivers/char/esp.c
HEWLETT-PACKARD SMART2 RAID DRIVER
- P: Chirag Kantharia
S: Maintained
F: Documentation/blockdev/cpqarray.txt
F: drivers/block/cpqarray.*
HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss)
- P: Mike Miller
S: Supported
F: Documentation/blockdev/cciss.txt
F: include/linux/cciss_ioctl.h
HFS FILESYSTEM
- P: Roman Zippel
S: Maintained
F: Documentation/filesystems/hfs.txt
F: fs/hfs/
HGA FRAMEBUFFER DRIVER
- P: Ferenc Bakonyi
W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml
S: Maintained
F: drivers/video/hgafb.c
HIBERNATION (aka Software Suspend, aka swsusp)
- P: Pavel Machek
- P: Rafael J. Wysocki
S: Supported
F: arch/x86/power/
F: arch/*/include/asm/suspend*.h
HID CORE LAYER
- P: Jiri Kosina
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
S: Maintained
F: include/linux/hid*
HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS
- P: Thomas Gleixner
S: Maintained
F: Documentation/timers/
F: kernel/hrtimer.c
F: include/linux/hrtimer.h
HIGH-SPEED SCC DRIVER FOR AX.25
- P: Klaus Kudielka
W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/
S: Maintained
F: drivers/net/hamradio/scc.c
HIGHPOINT ROCKETRAID 3xxx RAID DRIVER
- P: HighPoint Linux Team
W: http://www.highpoint-tech.com
S: Supported
F: Documentation/scsi/hptiop.txt
F: drivers/scsi/hptiop.c
HIPPI
- P: Jes Sorensen
S: Maintained
F: include/linux/hippidevice.h
F: net/802/hippi.c
HOST AP DRIVER
- P: Jouni Malinen
W: http://hostap.epitest.fi/
F: drivers/net/wireless/hostap/
HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
- P: Carlos Corbacho
S: Odd Fixes
F: drivers/platform/x86/tc1100-wmi.c
HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
- P: Jaroslav Kysela
S: Maintained
F: drivers/net/hp100.*
HPET: High Precision Event Timers driver
- P: Clemens Ladisch
S: Maintained
F: Documentation/timers/hpet.txt
F: drivers/char/hpet.c
F: include/linux/hpet.h
HPET: i386
- P: Venkatesh Pallipadi (Venki)
S: Maintained
F: arch/x86/kernel/hpet.c
F: arch/x86/include/asm/hpet.h
HPET: x86_64
- P: Vojtech Pavlik
S: Maintained
HPET: ACPI
- P: Bob Picco
S: Maintained
F: drivers/char/hpet.c
HPFS FILESYSTEM
- P: Mikulas Patocka
W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
S: Maintained
F: fs/hpfs/
HSO 3G MODEM DRIVER
- P: Jan Dumon
W: http://www.pharscape.org
S: Maintained
F: drivers/net/usb/hso.c
HTCPEN TOUCHSCREEN DRIVER
- P: Pau Oliva Fora
S: Maintained
F: drivers/input/touchscreen/htcpen.c
HUGETLB FILESYSTEM
- P: William Irwin
S: Maintained
F: fs/hugetlbfs/
I2C/SMBUS STUB DRIVER
- P: Mark M. Hoffman
S: Maintained
F: drivers/i2c/busses/i2c-stub.c
I2C SUBSYSTEM
- P: Jean Delvare (PC drivers, core)
- P: Ben Dooks (embedded platforms)
W: http://i2c.wiki.kernel.org/
T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
F: include/linux/i2c-id.h
I2C-TINY-USB DRIVER
- P: Till Harbaum
W: http://www.harbaum.org/till/i2c_tiny_usb
S: Maintained
F: drivers/i2c/busses/i2c-tiny-usb.c
i386 BOOT CODE
- P: H. Peter Anvin
S: Maintained
F: arch/x86/boot/
i386 SETUP CODE / CPU ERRATA WORKAROUNDS
- P: H. Peter Anvin
T: git git://git.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-x86setup.git
S: Maintained
IA64 (Itanium) PLATFORM
- P: Tony Luck
- P: Fenghua Yu
W: http://www.ia64-linux.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git
F: arch/ia64/
IBM MCA SCSI SUBSYSTEM DRIVER
- P: Michael Lang
W: http://www.uni-mainz.de/~langm000/linux.html
S: Maintained
F: drivers/scsi/ibmmca.c
IBM Power Linux RAID adapter
- P: Brian King
S: Supported
F: drivers/scsi/ipr.*
IBM ServeRAID RAID DRIVER
P: Jack Hammer
- P: Dave Jeffery
W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html
S: Supported
F: drivers/scsi/ips.*
IDE SUBSYSTEM
- P: David S. Miller
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-2.6.git
S: Maintained
F: include/linux/ide.h
IDE/ATAPI DRIVERS
- P: Borislav Petkov
S: Maintained
F: Documentation/cdrom/ide-cd
F: drivers/ide/ide-cd*
IDLE-I7300
- P: Andy Henroid
S: Supported
F: drivers/idle/i7300_idle.c
IEEE 1394 SUBSYSTEM
- P: Ben Collins
- P: Stefan Richter
W: http://www.linux1394.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
F: drivers/ieee1394/
IEEE 1394 RAW I/O DRIVER
- P: Dan Dennedy
- P: Stefan Richter
S: Maintained
F: drivers/ieee1394/raw1394*
IEEE 802.15.4 SUBSYSTEM
- P: Dmitry Eremin-Solenikov
- P: Sergey Lapin
W: http://apps.sourceforge.net/trac/linux-zigbee
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git
F: drivers/ieee802154/
INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
- P: Mimi Zohar
S: Supported
F: security/integrity/ima/
F: drivers/video/imsttfb.c
INFINIBAND SUBSYSTEM
- P: Roland Dreier
- P: Sean Hefty
- P: Hal Rosenstock
W: http://www.openib.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
F: include/linux/if_infiniband.h
INOTIFY
- P: John McCutchan
- P: Robert Love
- P: Eric Paris
S: Maintained
F: Documentation/filesystems/inotify.txt
F: fs/notify/inotify/
F: include/linux/inotify.h
INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
- P: Dmitry Torokhov
T: git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
S: Maintained
F: drivers/input/
INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
- P: Sylvain Meyer
S: Maintained
F: Documentation/fb/intelfb.txt
F: drivers/video/intelfb/
INTEL 810/815 FRAMEBUFFER DRIVER
- P: Antonino Daplas
S: Maintained
F: drivers/video/i810/
INTEL MENLOW THERMAL DRIVER
- P: Sujith Thomas
W: http://www.lesswatts.org/projects/acpi/
S: Supported
F: drivers/platform/x86/intel_menlow.c
INTEL IA32 MICROCODE UPDATE SUPPORT
- P: Tigran Aivazian
S: Maintained
F: arch/x86/kernel/microcode_core.c
F: arch/x86/kernel/microcode_intel.c
INTEL I/OAT DMA DRIVER
- P: Maciej Sosnowski
S: Supported
F: drivers/dma/ioat*
INTEL IOMMU (VT-d)
- P: David Woodhouse
T: git git://git.infradead.org/iommu-2.6.git
S: Supported
F: include/linux/intel-iommu.h
INTEL IOP-ADMA DMA DRIVER
- P: Dan Williams
S: Supported
F: drivers/dma/iop-adma.c
INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT
- P: Krzysztof Halasa
S: Maintained
F: arch/arm/mach-ixp4xx/include/mach/qmgr.h
F: arch/arm/mach-ixp4xx/include/mach/npe.h
F: drivers/net/wan/ixp4xx_hss.c
INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
- P: Deepak Saxena
S: Maintained
F: drivers/char/hw_random/ixp4xx-rng.c
INTEL IXP2000 ETHERNET DRIVER
- P: Lennert Buytenhek
S: Maintained
F: drivers/net/ixp2000/
INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/ixgb/ixgbe)
- P: Jeff Kirsher
- P: Jesse Brandeburg
- P: Bruce Allan
- P: PJ Waskiewicz
- P: John Ronciak
W: http://e1000.sourceforge.net/
S: Supported
F: drivers/net/ixgbe/
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
- P: Zhu Yi
- P: James Ketrenos
- P: Reinette Chatre
W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
F: drivers/net/wireless/ipw2x00/ipw2100.*
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
- P: Zhu Yi
- P: James Ketrenos
- P: Reinette Chatre
W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
F: drivers/net/wireless/ipw2x00/ipw2200.*
INTEL WIRELESS WIMAX CONNECTION 2400
- P: Inaky Perez-Gonzalez
S: Supported
F: include/linux/wimax/i2400m.h
INTEL WIRELESS WIFI LINK (iwlwifi)
- P: Zhu Yi
- P: Reinette Chatre
W: http://intellinuxwireless.org
F: drivers/net/wireless/iwlwifi/
IOC3 ETHERNET DRIVER
- P: Ralf Baechle
S: Maintained
F: drivers/net/ioc3-eth.c
IOC3 SERIAL DRIVER
- P: Pat Gefre
S: Maintained
F: drivers/serial/ioc3_serial.c
IP MASQUERADING
- P: Juanjo Ciarlante
S: Maintained
F: net/ipv4/netfilter/ipt_MASQUERADE.c
IP1000A 10/100/1000 GIGABIT ETHERNET DRIVER
- P: Francois Romieu
- P: Sorbica Shieh
- P: Jesse Huang
S: Maintained
F: drivers/net/ipg.c
IPATH DRIVER
- P: Ralph Campbell
T: git git://git.qlogic.com/ipath-linux-2.6
S: Supported
F: drivers/infiniband/hw/ipath/
IPMI SUBSYSTEM
- P: Corey Minyard
W: http://openipmi.sourceforge.net/
S: Supported
F: include/linux/ipmi*
IPS SCSI RAID DRIVER
- P: Adaptec OEM Raid Solutions
W: http://www.adaptec.com/
S: Maintained
F: drivers/scsi/ips*
IPVS
- P: Wensong Zhang
- P: Simon Horman
- P: Julian Anastasov
S: Maintained
F: net/netfilter/ipvs/
IPWIRELESS DRIVER
- P: Jiri Kosina
- P: David Sterba
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git
F: drivers/char/pcmcia/ipwireless/
IPX NETWORK LAYER
- P: Arnaldo Carvalho de Melo
S: Maintained
F: include/linux/ipx.h
F: net/ipx/
IRDA SUBSYSTEM
- P: Samuel Ortiz
W: http://irda.sourceforge.net/
S: Maintained
F: net/irda/
ISAPNP
- P: Jaroslav Kysela
S: Maintained
F: Documentation/isapnp.txt
F: drivers/pnp/isapnp/
F: include/linux/isapnp.h
ISCSI
- P: Mike Christie
W: www.open-iscsi.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mnc/linux-2.6-iscsi.git
F: include/scsi/*iscsi*
ISDN SUBSYSTEM
- P: Karsten Keil
W: http://www.isdn4linux.de
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/isdn-2.6.git
F: include/linux/isdn/
ISDN SUBSYSTEM (Eicon active card driver)
- P: Armin Schindler
W: http://www.melware.de
S: Maintained
F: drivers/isdn/hardware/eicon/
IVTV VIDEO4LINUX DRIVER
- P: Hans Verkuil
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://www.ivtvdriver.org
F: include/linux/ivtv*
JFS FILESYSTEM
- P: Dave Kleikamp
W: http://jfs.sourceforge.net/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git
- S: Supported
+ S: Maintained
F: Documentation/filesystems/jfs.txt
F: fs/jfs/
JME NETWORK DRIVER
- P: Guo-Fu Tseng
S: Maintained
F: drivers/net/jme.*
JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
- P: David Woodhouse
W: http://www.linux-mtd.infradead.org/doc/jffs2.html
S: Maintained
F: include/linux/jffs2.h
JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
- P: Stephen Tweedie
- P: Andrew Morton
S: Maintained
F: fs/jbd*/
F: include/linux/jbd*.h
K8TEMP HARDWARE MONITORING DRIVER
- P: Rudolf Marek
S: Maintained
F: Documentation/hwmon/k8temp
F: drivers/hwmon/k8temp.c
KCONFIG
- P: Roman Zippel
S: Maintained
F: Documentation/kbuild/kconfig-language.txt
F: scripts/kconfig/
KDUMP
- P: Vivek Goyal
- P: Haren Myneni
W: http://lse.sourceforge.net/kdump/
S: Maintained
F: Documentation/kdump/
KERNEL AUTOMOUNTER (AUTOFS)
- P: H. Peter Anvin
S: Odd Fixes
F: fs/autofs/
KERNEL AUTOMOUNTER v4 (AUTOFS4)
- P: Ian Kent
S: Maintained
F: fs/autofs4/
KERNEL BUILD
- P: Sam Ravnborg
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-next.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes.git
F: scripts/Makefile.*
KERNEL JANITORS
- P: Several
W: http://www.kerneljanitors.org/
- S: Maintained
+ S: Odd fixes
KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
- P: J. Bruce Fields
- P: Neil Brown
W: http://nfs.sourceforge.net/
S: Supported
F: include/linux/sunrpc/
KERNEL VIRTUAL MACHINE (KVM)
- P: Avi Kivity
W: http://kvm.qumranet.com
S: Supported
F: virt/kvm/
KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V
- P: Joerg Roedel
W: http://kvm.qumranet.com
S: Supported
F: arch/x86/kvm/svm.c
KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
- P: Hollis Blanchard
W: http://kvm.qumranet.com
S: Supported
F: arch/powerpc/kvm/
KERNEL VIRTUAL MACHINE For Itanium (KVM/IA64)
- P: Xiantao Zhang
W: http://kvm.qumranet.com
S: Supported
F: arch/ia64/kvm/
KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
- P: Carsten Otte
- P: Christian Borntraeger
W: http://www.ibm.com/developerworks/linux/linux390/
F: arch/s390/kvm/
KEXEC
- P: Eric Biederman
W: http://ftp.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
S: Maintained
F: kernel/kexec.c
KGDB
- P: Jason Wessel
S: Maintained
F: Documentation/DocBook/kgdb.tmpl
F: kernel/kgdb.c
KMEMCHECK
- P: Vegard Nossum
P Pekka Enberg
S: Maintained
KMEMLEAK
- P: Catalin Marinas
S: Maintained
F: Documentation/kmemleak.txt
F: include/linux/kmemleak.h
F: mm/kmemleak-test.c
KMEMTRACE
- P: Eduard - Gabriel Munteanu
S: Maintained
F: Documentation/trace/kmemtrace.txt
F: include/linux/kmemtrace.h
F: kernel/trace/kmemtrace.c
KPROBES
- P: Ananth N Mavinakayanahalli
- P: Anil S Keshavamurthy
- P: David S. Miller
- P: Masami Hiramatsu
S: Maintained
F: Documentation/kprobes.txt
F: include/linux/kprobes.h
F: kernel/kprobes.c
KS0108 LCD CONTROLLER DRIVER
- P: Miguel Ojeda Sandonis
W: http://miguelojeda.es/auxdisplay.htm
W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
S: Maintained
F: net/lapb/
LASI 53c700 driver for PARISC
- P: James E.J. Bottomley
S: Maintained
F: Documentation/scsi/53c700.txt
F: drivers/scsi/53c700*
LED SUBSYSTEM
- P: Richard Purdie
S: Maintained
F: drivers/leds/
F: include/linux/leds.h
LEGO USB Tower driver
- P: Juergen Stuber
W: http://legousb.sourceforge.net/
S: Maintained
F: drivers/usb/misc/legousbtower.c
LGUEST
- P: Rusty Russell
W: http://lguest.ozlabs.org/
S: Maintained
F: arch/x86/include/asm/lguest*.h
LINUX FOR IBM pSERIES (RS/6000)
- P: Paul Mackerras
W: http://www.ibm.com/linux/ltc/projects/ppc
S: Supported
LINUX FOR POWERPC (32-BIT AND 64-BIT)
- P: Benjamin Herrenschmidt
- P: Paul Mackerras
W: http://www.penguinppc.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git
S: Supported
LINUX FOR POWER MACINTOSH
- P: Benjamin Herrenschmidt
W: http://www.penguinppc.org/
S: Maintained
LINUX FOR POWERPC EMBEDDED MPC5XXX
- P: Grant Likely
T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
LINUX FOR POWERPC EMBEDDED PPC4XX
- P: Josh Boyer
- P: Matt Porter
W: http://www.penguinppc.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git
S: Maintained
LINUX FOR POWERPC EMBEDDED XILINX VIRTEX
- P: Grant Likely
W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex
T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
LINUX FOR POWERPC EMBEDDED PPC8XX
- P: Vitaly Bordug
- P: Marcelo Tosatti
W: http://www.penguinppc.org/
S: Maintained
LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
- P: Kumar Gala
W: http://www.penguinppc.org/
S: Maintained
LINUX FOR POWERPC PA SEMI PWRFICIENT
- P: Olof Johansson
W: http://www.pasemi.com/
S: Supported
LINUX SECURITY MODULE (LSM) FRAMEWORK
- P: Chris Wright
T: git git://git.kernel.org/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git
S: Supported
LLC (802.2)
- P: Arnaldo Carvalho de Melo
S: Maintained
F: include/linux/llc.h
F: include/net/llc*
F: net/llc/
LIS3LV02D ACCELEROMETER DRIVER
- P: Eric Piel
S: Maintained
F: Documentation/hwmon/lis3lv02d
F: drivers/hwmon/lis3lv02d.*
LM83 HARDWARE MONITOR DRIVER
- P: Jean Delvare
S: Maintained
F: Documentation/hwmon/lm83
F: drivers/hwmon/lm83.c
LM90 HARDWARE MONITOR DRIVER
- P: Jean Delvare
S: Maintained
F: Documentation/hwmon/lm90
F: drivers/hwmon/lm90.c
LOCKDEP AND LOCKSTAT
- P: Peter Zijlstra
- P: Ingo Molnar
T: git git://git.kernel.org/pub/scm/linux/kernel/git/peterz/linux-2.6-lockdep.git
S: Maintained
F: Documentation/lockdep*.txt
F: kernel/lockdep*
LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)
- P: Richard Russon (FlatCap)
W: http://www.linux-ntfs.org/content/view/19/37/
S: Maintained
F: fs/partitions/ldm.*
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
- P: Eric Moore
F: drivers/message/fusion/
LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers
- P: Matthew Wilcox
S: Maintained
F: drivers/scsi/sym53c8xx_2/
LTP (Linux Test Project)
- P: Subrata Modak
- P: Mike Frysinger
W: http://ltp.sourceforge.net/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/ltp.git
S: Maintained
M32R ARCHITECTURE
- P: Hirokazu Takata
W: http://www.linux-m32r.org/
F: arch/m32r/
M68K ARCHITECTURE
- P: Geert Uytterhoeven
- P: Roman Zippel
W: http://www.linux-m68k.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git
F: drivers/zorro/
M68K ON APPLE MACINTOSH
- P: Joshua Thompson
W: http://www.mac.linux-m68k.org/
S: Maintained
F: arch/m68k/mac/
M68K ON HP9000/300
- P: Philip Blundell
W: http://www.tazenda.demon.co.uk/phil/linux-hp
S: Maintained
F: arch/m68k/hp300/
MAC80211
- P: Johannes Berg
W: http://linuxwireless.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
F: net/mac80211/
MAC80211 PID RATE CONTROL
- P: Stefano Brivio
- P: Mattias Nissler
W: http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
F: net/mac80211/rc80211_pid*
MACVLAN DRIVER
- P: Patrick McHardy
S: Maintained
F: drivers/net/macvlan.c
F: include/linux/if_macvlan.h
MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
- P: Michael Kerrisk
W: http://www.kernel.org/doc/man-pages
S: Maintained
MARVELL LIBERTAS WIRELESS DRIVER
- P: Dan Williams
S: Maintained
F: drivers/net/wireless/libertas/
MARVELL MV643XX ETHERNET DRIVER
- P: Lennert Buytenhek
S: Supported
F: drivers/net/mv643xx_eth.*
F: include/linux/mv643xx.h
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
- P: Nicolas Pitre
S: Maintained
MARVELL YUKON / SYSKONNECT DRIVER
- P: Mirko Lindner
- P: Ralph Roesler
W: http://www.syskonnect.com
S: Supported
MATROX FRAMEBUFFER DRIVER
- P: Petr Vandrovec
S: Maintained
F: drivers/video/matrox/matroxfb_*
F: include/linux/matroxfb.h
MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
- P: Hans J. Koch
S: Maintained
F: Documentation/hwmon/max6650
F: drivers/hwmon/max6650.c
MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
- P: Mauro Carvalho Chehab
P: LinuxTV.org Project
W: http://linuxtv.org
F: include/linux/videodev*.h
MEGARAID SCSI DRIVERS
- P: Neela Syam Kolli
W: http://megaraid.lsilogic.com
S: Maintained
F: mm/
MEMORY RESOURCE CONTROLLER
- P: Balbir Singh
- P: Pavel Emelyanov
- P: KAMEZAWA Hiroyuki
S: Maintained
F: mm/memcontrol.c
MEMORY TECHNOLOGY DEVICES (MTD)
- P: David Woodhouse
W: http://www.linux-mtd.infradead.org/
T: git git://git.infradead.org/mtd-2.6.git
F: include/mtd/
MICROBLAZE ARCHITECTURE
- P: Michal Simek
W: http://www.monstr.eu/fdt/
T: git git://git.monstr.eu/linux-2.6-microblaze.git
F: arch/microblaze/
MICROTEK X6 SCANNER
- P: Oliver Neukum
S: Maintained
F: drivers/usb/image/microtek.*
MIPS
- P: Ralf Baechle
W: http://www.linux-mips.org/
T: git git://git.linux-mips.org/pub/scm/linux.git
F: arch/mips/
MISCELLANEOUS MCA-SUPPORT
- P: James Bottomley
S: Maintained
F: Documentation/ia64/mca.txt
F: Documentation/mca.txt
F: include/linux/mca*
MODULE SUPPORT
- P: Rusty Russell
S: Maintained
F: include/linux/module.h
F: kernel/module.c
MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
- P: Stelian Pop
W: http://popies.net/meye/
S: Maintained
F: Documentation/video4linux/meye.txt
F: include/linux/meye.h
MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
- P: Pavel Pisa
S: Maintained
F: drivers/mmc/host/imxmmc.*
MOUSE AND MISC DEVICES [GENERAL]
- P: Alessandro Rubini
S: Maintained
F: drivers/input/mouse/
F: include/linux/gpio_mouse.h
MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
- P: Jiri Slaby
S: Maintained
F: Documentation/serial/moxa-smartio
F: drivers/char/mxser.*
MSI LAPTOP SUPPORT
- P: Lennart Poettering
W: https://tango.0pointer.de/mailman/listinfo/s270-linux
W: http://0pointer.de/lennart/tchibo.html
S: Maintained
F: drivers/platform/x86/msi-laptop.c
MULTIFUNCTION DEVICES (MFD)
- P: Samuel Ortiz
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git
S: Supported
F: drivers/mfd/
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
- P: Pierre Ossman
- S: Maintained
+ S: Orphan
F: drivers/mmc/
F: include/linux/mmc/
MULTIMEDIA CARD (MMC) ETC. OVER SPI
- P: David Brownell
S: Odd Fixes
F: drivers/mmc/host/mmc_spi.c
F: include/linux/spi/mmc_spi.h
MULTISOUND SOUND DRIVER
- P: Andrew Veliath
S: Maintained
F: Documentation/sound/oss/MultiSound
F: sound/oss/msnd*
MULTITECH MULTIPORT CARD (ISICOM)
- P: Jiri Slaby
S: Maintained
F: drivers/char/isicom.c
F: include/linux/isicom.h
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
- P: Felipe Balbi
T: git git://gitorious.org/musb/mainline.git
S: Maintained
F: drivers/usb/musb/
MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
- P: Andrew Gallatin
- P: Brice Goglin
W: http://www.myri.com/scs/download-Myri10GE.html
S: Supported
F: drivers/net/myri10ge/
NATSEMI ETHERNET DRIVER (DP8381x)
- P: Tim Hockin
S: Maintained
F: drivers/net/natsemi.c
NCP FILESYSTEM
- P: Petr Vandrovec
S: Maintained
F: fs/ncpfs/
NCR DUAL 700 SCSI DRIVER (MICROCHANNEL)
- P: James E.J. Bottomley
S: Maintained
F: drivers/scsi/NCR_D700.*
NETEFFECT IWARP RNIC DRIVER (IW_NES)
- P: Faisal Latif
- P: Chien Tung
W: http://www.neteffect.com
S: Supported
F: drivers/infiniband/hw/nes/
NETEM NETWORK EMULATOR
- P: Stephen Hemminger
S: Maintained
F: net/sched/sch_netem.c
NETERION (S2IO) 10GbE DRIVER (xframe/vxge)
- P: Ramkrishna Vepa
- P: Rastapur Santosh
- P: Sivakumar Subramani
- P: Sreenivasa Honnur
- P: Anil Murthy
W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
P: James Morris
P: Harald Welte
P: Jozsef Kadlecsik
- P: Patrick McHardy
F: net/netfilter/
NETLABEL
- P: Paul Moore
W: http://netlabel.sf.net
S: Supported
F: net/netlabel/
NETROM NETWORK LAYER
- P: Ralf Baechle
W: http://www.linux-ax25.org/
S: Maintained
F: net/netrom/
NETWORK BLOCK DEVICE (NBD)
- P: Paul Clements
S: Maintained
F: Documentation/blockdev/nbd.txt
F: drivers/block/nbd.c
F: include/linux/nbd.h
NETWORKING [GENERAL]
- P: David S. Miller
W: http://www.linuxfoundation.org/en/Net
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
S: Maintained
F: net/
F: include/net/
+ F: include/linux/in.h
+ F: include/linux/net.h
+ F: include/linux/netdevice.h
NETWORKING [IPv4/IPv6]
- P: David S. Miller
- P: Alexey Kuznetsov
- P: Pekka Savola (ipv6)
- P: James Morris
- P: Hideaki YOSHIFUJI
- P: Patrick McHardy
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
S: Maintained
F: include/net/ip*
NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK)
- P: Paul Moore
S: Maintained
NETWORKING [WIRELESS]
- P: John W. Linville
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
S: Odd Fixes
F: drivers/net/
+ F: include/linux/if_*
+ F: include/linux/*device.h
NETXEN (1/10) GbE SUPPORT
- P: Dhananjay Phadke
W: http://www.netxen.com
S: Supported
F: drivers/net/netxen/
NFS, SUNRPC, AND LOCKD CLIENTS
- P: Trond Myklebust
W: http://client.linux-nfs.org
T: git git://git.linux-nfs.org/pub/linux/nfs-2.6.git
F: include/linux/sunrpc/
NI5010 NETWORK DRIVER
- P: Jan-Pascal van Best
- P: Andreas Mohr
S: Maintained
F: drivers/net/ni5010.*
NILFS2 FILESYSTEM
- P: KONISHI Ryusuke
W: http://www.nilfs.org/en/
S: Supported
F: include/linux/nilfs2_fs.h
NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER
- P: YOKOTA Hiroshi
W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
S: Maintained
F: Documentation/scsi/NinjaSCSI.txt
F: drivers/scsi/pcmcia/nsp_*
NINJA SCSI-32Bi/UDE PCI/CARDBUS SCSI HOST ADAPTER DRIVER
- P: GOTO Masanori
- P: YOKOTA Hiroshi
W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
S: Maintained
F: Documentation/scsi/NinjaSCSI.txt
F: drivers/scsi/nsp32*
NTFS FILESYSTEM
- P: Anton Altaparmakov
W: http://www.linux-ntfs.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git
F: fs/ntfs/
NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
- P: Antonino Daplas
S: Maintained
F: drivers/video/riva/
F: drivers/video/nvidia/
OMAP SUPPORT
W: http://www.muru.com/linux/omap/
W: http://linux.omap.com/
F: arch/arm/*omap*
OMAP CLOCK FRAMEWORK SUPPORT
- P: Paul Walmsley
S: Maintained
F: arch/arm/*omap*/*clock*
OMAP POWER MANAGEMENT SUPPORT
- P: Kevin Hilman
S: Maintained
F: arch/arm/*omap*/*pm*
OMAP AUDIO SUPPORT
- P: Jarkko Nikula
S: Maintained
F: sound/soc/omap/
OMAP FRAMEBUFFER SUPPORT
- P: Imre Deak
S: Maintained
F: drivers/video/omap/
OMAP MMC SUPPORT
- P: Jarkko Lavinen
S: Maintained
F: drivers/mmc/host/*omap*
OMAP RANDOM NUMBER GENERATOR SUPPORT
- P: Deepak Saxena
S: Maintained
F: drivers/char/hw_random/omap-rng.c
OMAP USB SUPPORT
- P: Felipe Balbi
- P: David Brownell
S: Maintained
OMFS FILESYSTEM
- P: Bob Copeland
S: Maintained
F: Documentation/filesystems/omfs.txt
F: fs/omfs/
OMNIKEY CARDMAN 4000 DRIVER
- P: Harald Welte
S: Maintained
F: drivers/char/pcmcia/cm4000_cs.c
F: include/linux/cm4000_cs.h
OMNIKEY CARDMAN 4040 DRIVER
- P: Harald Welte
S: Maintained
F: drivers/char/pcmcia/cm4040_cs.*
OMNIVISION OV7670 SENSOR DRIVER
- P: Jonathan Corbet
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
F: drivers/media/video/ov7670.c
ONENAND FLASH DRIVER
- P: Kyungmin Park
S: Maintained
F: drivers/mtd/onenand/
F: include/linux/mtd/onenand*.h
ONSTREAM SCSI TAPE DRIVER
- P: Willem Riede
S: Maintained
F: drivers/scsi/st*
OPENCORES I2C BUS DRIVER
- P: Peter Korsgaard
S: Maintained
F: Documentation/i2c/busses/i2c-ocores
F: drivers/i2c/busses/i2c-ocores.c
OPROFILE
- P: Robert Richter
S: Maintained
F: arch/*/oprofile/
F: include/linux/oprofile.h
ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
- P: Mark Fasheh
- P: Joel Becker
W: http://oss.oracle.com/projects/ocfs2/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git
F: fs/ocfs2/
ORINOCO DRIVER
- P: Pavel Roskin
- P: David Gibson
S: Maintained
F: drivers/net/wireless/orinoco/
- OSD LIBRARY
- P: Boaz Harrosh
- P: Benny Halevy
+ OSD LIBRARY and FILESYSTEM
W: http://open-osd.org
T: git git://git.open-osd.org/open-osd.git
S: Maintained
+ F: drivers/scsi/osd/
+ F: drivers/include/scsi/osd_*
+ F: fs/exofs/
P54 WIRELESS DRIVER
- P: Michael Wu
W: http://prism54.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
F: drivers/net/wireless/p54/
PA SEMI ETHERNET DRIVER
- P: Olof Johansson
S: Maintained
F: drivers/net/pasemi_mac.*
PA SEMI SMBUS DRIVER
- P: Olof Johansson
S: Maintained
F: drivers/i2c/busses/i2c-pasemi.c
PANASONIC LAPTOP ACPI EXTRAS DRIVER
- P: Harald Welte
S: Maintained
F: drivers/platform/x86/panasonic-laptop.c
PANASONIC MN10300/AM33 PORT
- P: David Howells
- P: Koichi Yasutake
W: ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/
S: Maintained
F: include/linux/ppdev.h
PARAVIRT_OPS INTERFACE
- P: Jeremy Fitzhardinge
- P: Chris Wright
- P: Alok Kataria
- P: Rusty Russell
S: Supported
F: Documentation/ia64/paravirt_ops.txt
F: arch/*/include/asm/paravirt.h
PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
- P: Tim Waugh
W: http://www.torque.net/linux-pp.html
S: Maintained
F: drivers/block/paride/
PARISC ARCHITECTURE
- P: Kyle McMartin
- P: Helge Deller
W: http://www.parisc-linux.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
F: drivers/parisc/
PC87360 HARDWARE MONITORING DRIVER
- P: Jim Cromie
S: Maintained
F: Documentation/hwmon/pc87360
F: drivers/hwmon/pc87360.c
PC8736x GPIO DRIVER
- P: Jim Cromie
S: Maintained
F: drivers/char/pc8736x_gpio.c
PCA9532 LED DRIVER
- P: Riku Voipio
S: Maintained
F: drivers/leds/leds-pca9532.c
F: include/linux/leds-pca9532.h
PCI ERROR RECOVERY
- P: Linas Vepstas
S: Supported
F: Documentation/PCI/pci-error-recovery.txt
F: Documentation/powerpc/eeh-pci-error-recovery.txt
PCI SUBSYSTEM
- P: Jesse Barnes
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
S: Supported
F: include/linux/pci*
PCIE HOTPLUG DRIVER
- P: Kristen Carlson Accardi
S: Supported
F: drivers/pci/pcie/
F: include/pcmcia/
PCNET32 NETWORK DRIVER
- P: Don Fry
S: Maintained
F: drivers/net/pcnet32.c
PER-TASK DELAY ACCOUNTING
- P: Balbir Singh
S: Maintained
F: include/linux/delayacct.h
F: kernel/delayacct.c
PERFORMANCE COUNTER SUBSYSTEM
- P: Peter Zijlstra
- P: Paul Mackerras
- P: Ingo Molnar
S: Supported
PERSONALITY HANDLING
- P: Christoph Hellwig
S: Maintained
F: include/linux/personality.h
PHRAM MTD DRIVER
- P: Joern Engel
S: Maintained
F: drivers/mtd/devices/phram.c
PKTCDVD DRIVER
- P: Peter Osterlund
S: Maintained
F: drivers/block/pktcdvd.c
F: include/linux/pktcdvd.h
POSIX CLOCKS and TIMERS
- P: Thomas Gleixner
S: Supported
F: fs/timerfd.c
F: include/linux/timer*
F: kernel/*timer*
POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
- P: Anton Vorontsov
- P: David Woodhouse
T: git git://git.infradead.org/battery-2.6.git
S: Maintained
F: include/linux/power_supply.h
F: drivers/power/power_supply*
PNP SUPPORT
- P: Adam Belay
- P: Bjorn Helgaas
S: Maintained
F: drivers/pnp/
PNXxxxx I2C DRIVER
- P: Vitaly Wool
S: Maintained
F: drivers/i2c/busses/i2c-pnx.c
PPP PROTOCOL DRIVERS AND COMPRESSORS
- P: Paul Mackerras
S: Maintained
F: drivers/net/ppp_*
PPP OVER ATM (RFC 2364)
- P: Mitchell Blank Jr
S: Maintained
F: net/atm/pppoatm.c
F: include/linux/atmppp.h
PPP OVER ETHERNET
- P: Michal Ostrowski
S: Maintained
F: drivers/net/pppoe.c
F: drivers/net/pppox.c
PPP OVER L2TP
- P: James Chapman
S: Maintained
F: drivers/net/pppol2tp.c
F: include/linux/if_pppol2tp.h
PPS SUPPORT
- P: Rodolfo Giometti
W: http://wiki.enneenne.com/index.php/LinuxPPS_support
S: Maintained
+ F: Documentation/pps/
+ F: drivers/pps/
+ F: include/linux/pps*.h
PREEMPTIBLE KERNEL
- P: Robert Love
W: ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel
S: Supported
F: include/linux/preempt.h
PRISM54 WIRELESS DRIVER
- P: Luis R. Rodriguez
W: http://prism54.org
S: Maintained
F: drivers/net/wireless/prism54/
PROMISE DC4030 CACHING DISK CONTROLLER DRIVER
- P: Peter Denison
W: http://www.pnd-pc.demon.co.uk/promise/
S: Maintained
PROMISE SATA TX2/TX4 CONTROLLER LIBATA DRIVER
- P: Mikael Pettersson
S: Maintained
F: drivers/ata/sata_promise.*
PS3 NETWORK SUPPORT
- P: Geoff Levand
S: Supported
F: drivers/net/ps3_gelic_net.*
PS3 PLATFORM SUPPORT
- P: Geoff Levand
S: Supported
F: sound/ppc/snd_ps3*
PS3VRAM DRIVER
- P: Jim Paris
S: Maintained
PTRACE SUPPORT
- P: Roland McGrath
- P: Oleg Nesterov
S: Maintained
F: include/asm-generic/syscall.h
F: include/linux/ptrace.h
F: kernel/ptrace.c
PVRUSB2 VIDEO4LINUX DRIVER
- P: Mike Isely
W: http://www.isely.net/pvrusb2/
F: drivers/media/video/pvrusb2/
PXA2xx/PXA3xx SUPPORT
- P: Eric Miao
- P: Russell King
S: Maintained
F: arch/arm/mach-pxa/
F: sound/soc/pxa
PXA168 SUPPORT
- P: Eric Miao
- P: Jason Chagas
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
S: Maintained
PXA910 SUPPORT
- P: Eric Miao
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
S: Maintained
S: Orphan
PXA RTC DRIVER
- P: Robert Jarzmik
S: Maintained
QLOGIC QLA2XXX FC-SCSI DRIVER
- P: Andrew Vasquez
S: Supported
F: drivers/scsi/qla2xxx/
QLOGIC QLA3XXX NETWORK DRIVER
- P: Ron Mercer
S: Supported
F: drivers/net/qla3xxx.*
QLOGIC QLGE 10Gb ETHERNET DRIVER
- P: Ron Mercer
S: Supported
F: drivers/net/qlge/
QNX4 FILESYSTEM
- P: Anders Larsen
W: http://www.alarsen.net/linux/qnx4fs/
S: Maintained
F: fs/qnx4/
F: include/linux/qnxtypes.h
RADEON FRAMEBUFFER DISPLAY DRIVER
- P: Benjamin Herrenschmidt
S: Maintained
F: drivers/video/aty/radeon*
F: include/linux/radeonfb.h
RAGE128 FRAMEBUFFER DISPLAY DRIVER
- P: Paul Mackerras
S: Maintained
F: drivers/video/aty/aty128fb.c
F: drivers/net/wireless/rt2x00/
RAMDISK RAM BLOCK DEVICE DRIVER
- P: Nick Piggin
S: Maintained
F: Documentation/blockdev/ramdisk.txt
F: drivers/block/brd.c
RANDOM NUMBER DRIVER
- P: Matt Mackall
S: Maintained
F: drivers/char/random.c
RAPIDIO SUBSYSTEM
- P: Matt Porter
S: Maintained
F: drivers/rapidio/
RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
- P: Corey Thomas
S: Maintained
F: drivers/net/wireless/ray*
RCUTORTURE MODULE
- P: Josh Triplett
- P: Paul E. McKenney
S: Maintained
F: Documentation/RCU/torture.txt
F: kernel/rcutorture.c
RDC R-321X SoC
- P: Florian Fainelli
S: Maintained
RDC R6040 FAST ETHERNET DRIVER
- P: Florian Fainelli
S: Maintained
F: drivers/net/r6040.c
RDS - RELIABLE DATAGRAM SOCKETS
- P: Andy Grover
S: Supported
F: net/rds/
READ-COPY UPDATE (RCU)
- P: Dipankar Sarma
- P: Paul E. McKenney
W: http://www.rdrop.com/users/paulmck/rclock/
S: Supported
F: Documentation/RCU/rcu.txt
F: kernel/rcupdate.c
REAL TIME CLOCK DRIVER
- P: Paul Gortmaker
S: Maintained
F: Documentation/rtc.txt
F: drivers/rtc/
F: include/linux/rtc.h
REAL TIME CLOCK (RTC) SUBSYSTEM
- P: Alessandro Zummo
S: Maintained
F: Documentation/rtc.txt
F: fs/reiserfs/
RFKILL
- P: Johannes Berg
S: Maintained
F Documentation/rfkill.txt
F: drivers/char/rocket*
ROSE NETWORK LAYER
- P: Ralf Baechle
W: http://www.linux-ax25.org/
S: Maintained
F: net/rose/
RTL8180 WIRELESS DRIVER
- P: John W. Linville
W: http://linuxwireless.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Maintained
-F: drivers/net/wireless/rtl818*
+F: drivers/net/wireless/rtl818x/rtl8180*
RTL8187 WIRELESS DRIVER
- P: Herton Ronaldo Krzesinski
- P: Hin-Tak Leung
- P: Larry Finger
W: http://linuxwireless.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
F: drivers/net/wireless/rtl818x/rtl8187*
S3 SAVAGE FRAMEBUFFER DRIVER
- P: Antonino Daplas
S: Maintained
F: drivers/video/savage/
S390
- P: Martin Schwidefsky
- P: Heiko Carstens
W: http://www.ibm.com/developerworks/linux/linux390/
F: arch/s390/
S390 NETWORK DRIVERS
- P: Ursula Braun
- P: Frank Blaschka
W: http://www.ibm.com/developerworks/linux/linux390/
F: drivers/s390/net/
S390 ZCRYPT DRIVER
- P: Felix Beck
- P: Ralph Wuerthner
S: Supported
F: drivers/s390/crypto/
S390 ZFCP DRIVER
- P: Christof Schmitt
- P: Martin Peschke
W: http://www.ibm.com/developerworks/linux/linux390/
F: drivers/s390/scsi/zfcp_*
S390 IUCV NETWORK LAYER
- P: Ursula Braun
W: http://www.ibm.com/developerworks/linux/linux390/
F: net/iucv/
S3C24XX SD/MMC Driver
- P: Ben Dooks
S: Supported
F: drivers/mmc/host/s3cmci.*
SAA7146 VIDEO4LINUX-2 DRIVER
- P: Michael Hunold
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
W: http://www.mihu.de/linux/saa7146
F: include/media/*7146*
SC1200 WDT DRIVER
- P: Zwane Mwaikambo
S: Maintained
F: drivers/watchdog/sc1200wdt.c
SCHEDULER
- P: Ingo Molnar
- P: Peter Zijlstra
S: Maintained
F: kernel/sched*
F: include/linux/sched.h
SCSI CDROM DRIVER
- P: Jens Axboe
W: http://www.kernel.dk
S: Maintained
F: drivers/scsi/sr*
SCSI SG DRIVER
- P: Doug Gilbert
W: http://www.torque.net/sg
S: Maintained
F: include/scsi/sg.h
SCSI SUBSYSTEM
- P: James E.J. Bottomley
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git
F: include/scsi/
SCSI TAPE DRIVER
- P: Kai Mäkisara
S: Maintained
F: Documentation/scsi/st.txt
F: drivers/scsi/st*
SCTP PROTOCOL
- P: Vlad Yasevich
- P: Sridhar Samudrala
W: http://lksctp.sourceforge.net
S: Supported
F: net/sctp/
SCx200 CPU SUPPORT
- P: Jim Cromie
S: Odd Fixes
F: Documentation/i2c/busses/scx200_acb
F: arch/x86/kernel/scx200_32.c
F: include/linux/scx200.h
SCx200 GPIO DRIVER
- P: Jim Cromie
S: Maintained
F: drivers/char/scx200_gpio.c
F: include/linux/scx200_gpio.h
SCx200 HRT CLOCKSOURCE DRIVER
- P: Jim Cromie
S: Maintained
F: drivers/clocksource/scx200_hrt.c
SDRICOH_CS MMC/SD HOST CONTROLLER INTERFACE DRIVER
- P: Sascha Sommer
S: Maintained
F: drivers/mmc/host/sdricoh_cs.c
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
- P: Pierre Ossman
S: Maintained
SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
- P: Anton Vorontsov
S: Maintained
F: drivers/mmc/host/sdhci.*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
- P: Ben Dooks
S: Maintained
F: drivers/mmc/host/sdhci-s3c.c
SECURITY SUBSYSTEM
- P: James Morris
T: git git://www.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
W: http://security.wiki.kernel.org/
F: security/
SECURITY CONTACT
- P: Security Officers
S: Supported
SELINUX SECURITY MODULE
- P: Stephen Smalley
- P: James Morris
- P: Eric Paris
W: http://selinuxproject.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
F: security/selinux/
SENSABLE PHANTOM
- P: Jiri Slaby
S: Maintained
F: drivers/misc/phantom.c
F: include/linux/phantom.h
SERIAL ATA (SATA) SUBSYSTEM
- P: Jeff Garzik
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
S: Supported
F: include/linux/libata.h
SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER
- P: Sathya Perla
- P: Subbu Seetharaman
W: http://www.serverengines.com
S: Supported
SFC NETWORK DRIVER
P: Steve Hodgson
P: Ben Hutchings
- P: Robert Stonehouse
S: Supported
F: drivers/net/sfc/
SGI GRU DRIVER
- P: Jack Steiner
S: Maintained
F: drivers/misc/sgi-gru/
SGI SN-IA64 (Altix) SERIAL CONSOLE DRIVER
- P: Pat Gefre
S: Supported
F: Documentation/ia64/serial.txt
F: include/linux/ioc?.h
SGI VISUAL WORKSTATION 320 AND 540
- P: Andrey Panin
W: http://linux-visws.sf.net
S: Maintained for 2.6.
F: Documentation/sgi-visws.txt
SGI XP/XPC/XPNET DRIVER
- P: Robin Holt
S: Maintained
F: drivers/misc/sgi-xp/
SHARP LH SUPPORT (LH7952X & LH7A40X)
- P: Marc Singer
W: http://projects.buici.com/arm
S: Maintained
F: drivers/usb/host/ohci-lh7a40*
SHPC HOTPLUG DRIVER
- P: Kristen Carlson Accardi
S: Supported
F: drivers/pci/hotplug/shpchp*
SIMTEC EB110ATX (Chalice CATS)
P: Ben Dooks
- P: Vincent Sanders
W: http://www.simtec.co.uk/products/EB110ATX/
S: Supported
SIMTEC EB2410ITX (BAST)
P: Ben Dooks
- P: Vincent Sanders
W: http://www.simtec.co.uk/products/EB2410ITX/
S: Supported
F: arch/arm/mach-s3c2410/
F: drivers/*/*/*s3c2410*
SIS 190 ETHERNET DRIVER
- P: Francois Romieu
S: Maintained
F: drivers/net/sis190.c
SIS 900/7016 FAST ETHERNET DRIVER
- P: Daniele Venzano
W: http://www.brownhat.org/sis900.html
S: Maintained
F: drivers/net/sis900.*
SIS 96X I2C/SMBUS DRIVER
- P: Mark M. Hoffman
S: Maintained
F: Documentation/i2c/busses/i2c-sis96x
F: drivers/i2c/busses/i2c-sis96x.c
SIS FRAMEBUFFER DRIVER
- P: Thomas Winischhofer
W: http://www.winischhofer.net/linuxsisvga.shtml
S: Maintained
F: Documentation/fb/sisfb.txt
F: include/video/sisfb.h
SIS USB2VGA DRIVER
- P: Thomas Winischhofer
W: http://www.winischhofer.at/linuxsisusbvga.shtml
S: Maintained
F: drivers/usb/misc/sisusbvga/
SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
- P: Stephen Hemminger
S: Maintained
F: drivers/net/skge.*
F: drivers/net/sky2.*
SLAB ALLOCATOR
- P: Christoph Lameter
- P: Pekka Enberg
- P: Matt Mackall
S: Maintained
F: include/linux/sl?b*.h
F: mm/sl?b.c
SMC91x ETHERNET DRIVER
- P: Nicolas Pitre
S: Maintained
F: drivers/net/smc91x.*
SMSC47B397 HARDWARE MONITOR DRIVER
- P: Mark M. Hoffman
S: Maintained
F: Documentation/hwmon/smsc47b397
F: drivers/hwmon/smsc47b397.c
SMSC911x ETHERNET DRIVER
- P: Steve Glendinning
S: Supported
F: include/linux/smsc911x.h
F: drivers/net/smsc911x.*
SMSC9420 PCI ETHERNET DRIVER
- P: Steve Glendinning
S: Supported
F: drivers/net/smsc9420.*
SMX UIO Interface
- P: Ben Nizette
S: Maintained
F: drivers/uio/uio_smx.c
SN-IA64 (Itanium) SUB-PLATFORM
- P: Jes Sorensen
W: http://www.sgi.com/altix
F: arch/ia64/sn/
SOC-CAMERA V4L2 SUBSYSTEM
- P: Guennadi Liakhovetski
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
F: drivers/media/video/v4l2*
SOEKRIS NET48XX LED SUPPORT
- P: Chris Boot
S: Maintained
F: drivers/leds/leds-net48xx.c
SOFTWARE RAID (Multiple Disks) SUPPORT
- P: Neil Brown
S: Supported
F: drivers/md/
F: include/linux/raid/
SONIC NETWORK DRIVER
- P: Thomas Bogendoerfer
S: Maintained
F: drivers/net/sonic.*
SONICS SILICON BACKPLANE DRIVER (SSB)
- P: Michael Buesch
S: Maintained
F: drivers/ssb/
F: include/linux/ssb/
SONY VAIO CONTROL DEVICE DRIVER
- P: Mattia Dongili
W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers
S: Maintained
F: include/linux/sony-laptop.h
SONY MEMORYSTICK CARD SUPPORT
- P: Alex Dubov
W: http://tifmxx.berlios.de/
S: Maintained
F: drivers/memstick/host/tifm_ms.c
SOUND
- P: Jaroslav Kysela
- P: Takashi Iwai
W: http://www.alsa-project.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
F: sound/
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
- P: Liam Girdwood
- P: Mark Brown
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git
W: http://alsa-project.org/main/index.php/ASoC
F: include/sound/soc*
SPARC + UltraSPARC (sparc/sparc64)
- P: David S. Miller
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
F: arch/sparc/
SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
- P: Roger Wolff
S: Supported
F: Documentation/serial/specialix.txt
F: drivers/char/specialix*
SPI SUBSYSTEM
- P: David Brownell
S: Maintained
F: Documentation/spi/
F: include/linux/spi/
SPIDERNET NETWORK DRIVER for CELL
- P: Ishizaki Kou
- P: Jens Osterkamp
S: Supported
F: Documentation/networking/spider_net.txt
F: drivers/net/spider_net*
SPU FILE SYSTEM
- P: Jeremy Kerr
W: http://www.ibm.com/developerworks/power/cell/
F: arch/powerpc/platforms/cell/spufs/
SQUASHFS FILE SYSTEM
- P: Phillip Lougher
W: http://squashfs.org.uk
S: Maintained
F: fs/squashfs/
SRM (Alpha) environment access
- P: Jan-Benedict Glaw
S: Maintained
F: arch/alpha/kernel/srm_env.c
STABLE BRANCH
- P: Greg Kroah-Hartman
- P: Chris Wright
S: Maintained
STAGING SUBSYSTEM
- P: Greg Kroah-Hartman
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
S: Maintained
F: drivers/staging/
STARFIRE/DURALAN NETWORK DRIVER
- P: Ion Badulescu
S: Odd Fixes
F: drivers/net/starfire*
F: include/linux/if_strip.h
STRADIS MPEG-2 DECODER DRIVER
- P: Nathan Laredo
W: http://www.stradis.com/
S: Maintained
F: drivers/media/video/stradis.c
SUN3/3X
- P: Sam Creasey
W: http://sammy.net/sun3/
S: Maintained
F: arch/m68k/kernel/*sun3*
F: arch/m68k/include/asm/sun3*
SUPERH
- P: Paul Mundt
W: http://www.linux-sh.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git
F: drivers/sh/
SUSPEND TO RAM
- P: Len Brown
- P: Pavel Machek
- P: Rafael J. Wysocki
S: Supported
F: Documentation/power/
F: include/linux/pm.h
SVGA HANDLING
- P: Martin Mares
S: Maintained
F: Documentation/svga.txt
F: arch/x86/boot/video*
SYSV FILESYSTEM
- P: Christoph Hellwig
S: Maintained
F: Documentation/filesystems/sysv-fs.txt
F: fs/sysv/
F: include/linux/sysv_fs.h
TASKSTATS STATISTICS INTERFACE
- P: Balbir Singh
S: Maintained
F: Documentation/accounting/taskstats*
F: include/linux/taskstats*
F: kernel/taskstats.c
TC CLASSIFIER
- P: Jamal Hadi Salim
S: Maintained
F: include/linux/pkt_cls.h
F: net/sched/
TCP LOW PRIORITY MODULE
- P: Wong Hoi Sing, Edison
- P: Hung Hing Lun, Mike
W: http://tcp-lp-mod.sourceforge.net/
S: Maintained
F: net/ipv4/tcp_lp.c
TEHUTI ETHERNET DRIVER
- P: Alexander Indenbaum
- P: Andy Gospodarek
S: Supported
F: drivers/net/tehuti*
Telecom Clock Driver for MCPL0010
- P: Mark Gross
S: Supported
F: drivers/char/tlclk.c
TENSILICA XTENSA PORT (xtensa)
- P: Chris Zankel
S: Maintained
F: arch/xtensa/
THINKPAD ACPI EXTRAS DRIVER
- P: Henrique de Moraes Holschuh
W: http://ibm-acpi.sourceforge.net
W: http://thinkwiki.org/wiki/Ibm-acpi
F: drivers/platform/x86/thinkpad_acpi.c
TI FLASH MEDIA INTERFACE DRIVER
- P: Alex Dubov
S: Maintained
F: drivers/misc/tifm*
F: drivers/mmc/host/tifm_sd.c
F: include/linux/tifm.h
TI TWL4030 SERIES SOC CODEC DRIVER
- P: Peter Ujfalusi
S: Maintained
F: sound/soc/codecs/twl4030*
TIPC NETWORK LAYER
- P: Per Liden
- P: Jon Maloy
- P: Allan Stephens
W: http://tipc.sourceforge.net/
W: http://tipc.cslab.ericsson.net/
F: net/tipc/
TLAN NETWORK DRIVER
- P: Samuel Chessman
W: http://sourceforge.net/projects/tlan/
S: Maintained
F: drivers/net/tlan.*
TOMOYO SECURITY MODULE
- P: Kentaro Takeda
- P: Tetsuo Handa
F: drivers/platform/x86/toshiba_acpi.c
TOSHIBA SMM DRIVER
- P: Jonathan Buzzard
W: http://www.buzzard.org.uk/toshiba/
S: Maintained
F: include/linux/toshiba.h
TMIO MMC DRIVER
- P: Ian Molton
S: Maintained
F: drivers/mmc/host/tmio_mmc.*
TMPFS (SHMEM FILESYSTEM)
- P: Hugh Dickins
S: Maintained
F: include/linux/shmem_fs.h
F: mm/shmem.c
TPM DEVICE DRIVER
- P: Debora Velarde
- P: Rajiv Andrade
W: http://tpmdd.sourceforge.net
- P: Marcel Selhorst
W: http://www.sirrix.com
S: Maintained
F: drivers/char/tpm/
TRIVIAL PATCHES
- P: Jiri Kosina
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git
S: Maintained
+
+ TTY LAYER
+ S: Maintained
+ T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
F: drivers/char/tty_*
F: drivers/serial/serial_core.c
F: include/linux/serial_core.h
F: include/linux/serial.h
F: include/linux/tty.h
- TTY LAYER
- P: Alan Cox
- S: Maintained
- T: stgit http://zeniv.linux.org.uk/~alan/ttydev/
-
TULIP NETWORK DRIVERS
- P: Grant Grundler
- P: Kyle McMartin
S: Maintained
F: drivers/net/tulip/
TUN/TAP driver
- P: Maxim Krasnyansky
W: http://vtun.sourceforge.net/tun
S: Maintained
F: arch/um/os-Linux/drivers/
TURBOCHANNEL SUBSYSTEM
- P: Maciej W. Rozycki
S: Maintained
F: drivers/tc/
F: include/linux/tc.h
U14-34F SCSI DRIVER
- P: Dario Ballabio
S: Maintained
F: drivers/scsi/u14-34f.c
UBI FILE SYSTEM (UBIFS)
- P: Artem Bityutskiy
- P: Adrian Hunter
T: git git://git.infradead.org/ubifs-2.6.git
W: http://www.linux-mtd.infradead.org/doc/ubifs.html
F: fs/ubifs/
UCLINUX (AND M68KNOMMU)
- P: Greg Ungerer
W: http://www.uclinux.org/
S: Maintained
F: arch/m68knommu/
UCLINUX FOR RENESAS H8/300 (H8300)
- P: Yoshinori Sato
W: http://uclinux-h8.sourceforge.jp/
S: Supported
UDF FILESYSTEM
- P: Jan Kara
W: http://linux-udf.sourceforge.net
S: Maintained
F: Documentation/filesystems/udf.txt
F: fs/udf/
UFS FILESYSTEM
- P: Evgeniy Dushistov
S: Maintained
F: Documentation/filesystems/ufs.txt
F: fs/ufs/
ULTRA-WIDEBAND (UWB) SUBSYSTEM:
- P: David Vrabel
S: Supported
F: drivers/uwb/*
F: include/linux/uwb/
UNIFORM CDROM DRIVER
- P: Jens Axboe
W: http://www.kernel.dk
S: Maintained
F: Documentation/cdrom/
F: include/linux/cdrom.h
UNSORTED BLOCK IMAGES (UBI)
- P: Artem Bityutskiy
W: http://www.linux-mtd.infradead.org/
T: git git://git.infradead.org/ubi-2.6.git
F: include/mtd/ubi-user.h
USB ACM DRIVER
- P: Oliver Neukum
S: Maintained
F: Documentation/usb/acm.txt
F: drivers/usb/class/cdc-acm.*
USB BLOCK DRIVER (UB ub)
- P: Pete Zaitcev
S: Supported
F: drivers/block/ub.c
USB CDC ETHERNET DRIVER
- P: Greg Kroah-Hartman
S: Maintained
W: http://www.kroah.com/linux-usb/
F: include/linux/usb/cdc.h
USB CYPRESS C67X00 DRIVER
- P: Peter Korsgaard
S: Maintained
F: drivers/usb/c67x00/
USB DAVICOM DM9601 DRIVER
- P: Peter Korsgaard
W: http://www.linux-usb.org/usbnet
S: Maintained
F: drivers/net/usb/dm9601.c
USB DIAMOND RIO500 DRIVER
- P: Cesar Miquel
W: http://rio500.sourceforge.net
S: Maintained
F: drivers/usb/misc/rio500*
USB EHCI DRIVER
- P: David Brownell
S: Odd Fixes
F: Documentation/usb/ehci.txt
F: drivers/usb/host/ehci*
USB ET61X[12]51 DRIVER
- P: Luca Risolia
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
F: drivers/media/video/et61x251/
USB GADGET/PERIPHERAL SUBSYSTEM
- P: David Brownell
W: http://www.linux-usb.org/gadget
S: Maintained
F: include/linux/usb/gadget*
USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
- P: Jiri Kosina
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
S: Maintained
F: drivers/hid/usbhid/
USB ISP116X DRIVER
- P: Olav Kongas
S: Maintained
F: drivers/usb/host/isp116x*
F: include/linux/usb/isp116x.h
USB KAWASAKI LSI DRIVER
- P: Oliver Neukum
S: Maintained
F: drivers/usb/serial/kl5kusb105.*
USB MASS STORAGE DRIVER
- P: Matthew Dharm
S: Maintained
F: drivers/usb/storage/
USB OHCI DRIVER
- P: David Brownell
S: Odd Fixes
F: Documentation/usb/ohci.txt
F: drivers/usb/host/ohci*
USB OPTION-CARD DRIVER
- P: Matthias Urlichs
S: Maintained
F: drivers/usb/serial/option.c
USB OV511 DRIVER
- P: Mark McClelland
W: http://alpha.dyndns.org/ov511/
S: Maintained
F: drivers/media/video/ov511.*
USB PEGASUS DRIVER
- P: Petko Manolov
W: http://pegasus2.sourceforge.net/
F: drivers/net/usb/pegasus.*
USB PRINTER DRIVER (usblp)
- P: Pete Zaitcev
S: Supported
F: drivers/usb/class/usblp.c
USB RTL8150 DRIVER
- P: Petko Manolov
W: http://pegasus2.sourceforge.net/
F: drivers/net/usb/rtl8150.c
USB SE401 DRIVER
- P: Jeroen Vreeken
W: http://www.chello.nl/~j.vreeken/se401/
S: Maintained
F: drivers/media/video/se401.*
USB SERIAL BELKIN F5U103 DRIVER
- P: William Greathouse
S: Maintained
F: drivers/usb/serial/belkin_sa.*
USB SERIAL CYPRESS M8 DRIVER
- P: Lonnie Mendez
S: Maintained
W: http://geocities.com/i0xox0i
F: drivers/usb/serial/cypress_m8.*
USB SERIAL CYBERJACK DRIVER
- P: Matthias Bruestle and Harald Welte
W: http://www.reiner-sct.de/support/treiber_cyberjack.php
S: Maintained
F: drivers/usb/serial/cyberjack.c
USB SERIAL DIGI ACCELEPORT DRIVER
- P: Peter Berger and Al Borchers
S: Maintained
F: drivers/usb/serial/digi_acceleport.c
USB SERIAL DRIVER
- P: Greg Kroah-Hartman
S: Supported
F: Documentation/usb/usb-serial.txt
F: include/linux/usb/serial.h
USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
- P: Gary Brubaker
S: Maintained
F: drivers/usb/serial/empeg.c
USB SERIAL KEYSPAN DRIVER
- P: Greg Kroah-Hartman
W: http://www.kroah.com/linux/
S: Maintained
F: drivers/usb/serial/*keyspan*
USB SERIAL WHITEHEAT DRIVER
- P: Support Department
W: http://www.connecttech.com
S: Supported
F: drivers/usb/serial/whiteheat*
USB SMSC95XX ETHERNET DRIVER
- P: Steve Glendinning
S: Supported
F: drivers/net/usb/smsc95xx.*
USB SN9C1xx DRIVER
- P: Luca Risolia
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
F: drivers/media/video/sn9c102/
USB SUBSYSTEM
- P: Greg Kroah-Hartman
W: http://www.linux-usb.org
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
F: include/linux/usb/
USB UHCI DRIVER
- P: Alan Stern
S: Maintained
F: drivers/usb/host/uhci*
USB "USBNET" DRIVER FRAMEWORK
- P: David Brownell
W: http://www.linux-usb.org/usbnet
S: Maintained
F: include/linux/usb/usbnet.h
USB VIDEO CLASS
- P: Laurent Pinchart
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
F: drivers/media/video/uvc/
USB W996[87]CF DRIVER
- P: Luca Risolia
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
F: drivers/media/video/w996*
USB WIRELESS RNDIS DRIVER (rndis_wlan)
- P: Jussi Kivilinna
S: Maintained
F: drivers/net/wireless/rndis_wlan.c
USB XHCI DRIVER
- P: Sarah Sharp
S: Supported
USB ZC0301 DRIVER
- P: Luca Risolia
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
F: drivers/media/video/zc0301/
USB ZD1201 DRIVER
- P: Jeroen Vreeken
W: http://linux-lc100020.sourceforge.net
S: Maintained
F: drivers/net/wireless/zd1201.*
USB ZR364XX DRIVER
- P: Antoine Jacquet
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
F: drivers/media/video/zr364xx.c
USER-MODE LINUX (UML)
- P: Jeff Dike
W: http://user-mode-linux.sourceforge.net
F: fs/hppfs/
USERSPACE I/O (UIO)
- P: Hans J. Koch
- P: Greg Kroah-Hartman
S: Maintained
F: Documentation/DocBook/uio-howto.tmpl
F: drivers/uio/
F: include/linux/uio*.h
UTIL-LINUX-NG PACKAGE
- P: Karel Zak
W: http://kernel.org/~kzak/util-linux-ng/
T: git git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git
S: Maintained
UVESAFB DRIVER
- P: Michal Januszewski
W: http://dev.gentoo.org/~spock/projects/uvesafb/
S: Maintained
F: drivers/video/uvesafb.*
VFAT/FAT/MSDOS FILESYSTEM
- P: OGAWA Hirofumi
S: Maintained
F: Documentation/filesystems/vfat.txt
F: fs/fat/
VIA RHINE NETWORK DRIVER
- P: Roger Luethi
S: Maintained
F: drivers/net/via-rhine.c
VIAPRO SMBUS DRIVER
- P: Jean Delvare
S: Maintained
F: Documentation/i2c/busses/i2c-viapro
F: drivers/i2c/busses/i2c-viapro.c
VIA SD/MMC CARD CONTROLLER DRIVER
- P: Joseph Chan
- P: Harald Welte
S: Maintained
F: drivers/mmc/host/via-sdmmc.c
VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER
- P: Joseph Chan
- P: Scott Fang
S: Maintained
F: drivers/video/via/
VIA VELOCITY NETWORK DRIVER
- P: Francois Romieu
S: Maintained
F: drivers/net/via-velocity.*
VLAN (802.1Q)
- P: Patrick McHardy
S: Maintained
F: drivers/net/macvlan.c
F: net/8021q/
VLYNQ BUS
- P: Florian Fainelli
S: Maintained
F: drivers/vlynq/vlynq.c
F: include/linux/vlynq.h
VOLTAGE AND CURRENT REGULATOR FRAMEWORK
- P: Liam Girdwood
- P: Mark Brown
W: http://opensource.wolfsonmicro.com/node/15
W: http://www.slimlogic.co.uk/?p=48
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git
F: include/linux/regulator/
VT1211 HARDWARE MONITOR DRIVER
- P: Juerg Haefliger
S: Maintained
F: Documentation/hwmon/vt1211
F: drivers/hwmon/vt1211.c
VT8231 HARDWARE MONITOR DRIVER
- P: Roger Lucas
S: Maintained
F: drivers/hwmon/vt8231.c
W1 DALLAS'S 1-WIRE BUS
- P: Evgeniy Polyakov
S: Maintained
F: Documentation/w1/
F: drivers/w1/
W83791D HARDWARE MONITORING DRIVER
- P: Marc Hulsman
S: Maintained
F: Documentation/hwmon/w83791d
F: drivers/hwmon/w83791d.c
W83793 HARDWARE MONITORING DRIVER
- P: Rudolf Marek
S: Maintained
F: Documentation/hwmon/w83793
F: drivers/hwmon/w83793.c
W83L51xD SD/MMC CARD INTERFACE DRIVER
- P: Pierre Ossman
S: Maintained
F: drivers/mmc/host/wbsd.*
WATCHDOG DEVICE DRIVERS
- P: Wim Van Sebroeck
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog.git
S: Maintained
F: Documentation/watchdog/
F: include/linux/watchdog.h
WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS
- P: Jean Tourrilhes
W: http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
S: Maintained
F: drivers/net/wireless/wavelan*
WD7000 SCSI DRIVER
- P: Miroslav Zagorac
S: Maintained
F: drivers/scsi/wd7000.c
WIMAX STACK
- P: Inaky Perez-Gonzalez
S: Supported
W: http://linuxwimax.org
WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM
- P: David Vrabel
S: Maintained
F: include/linux/wlp.h
F: drivers/uwb/wlp/
WISTRON LAPTOP BUTTON DRIVER
- P: Miloslav Trmac
S: Maintained
F: drivers/input/misc/wistron_btns.c
+WL1251 WIRELESS DRIVER
+P: Kalle Valo
+W: http://wireless.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
+S: Maintained
+F: drivers/net/wireless/wl12xx/wl1251*
+
WL3501 WIRELESS PCMCIA CARD DRIVER
- P: Arnaldo Carvalho de Melo
W: http://oops.ghostprotocols.net:81/blog
S: Maintained
F: drivers/net/wireless/wl3501*
WM97XX TOUCHSCREEN DRIVERS
- P: Mark Brown
- P: Liam Girdwood
T: git git://opensource.wolfsonmicro.com/linux-2.6-touch
W: http://opensource.wolfsonmicro.com/node/7
F: include/linux/wm97xx.h
X.25 NETWORK LAYER
- P: Henner Eisen
S: Maintained
F: Documentation/networking/x25*
F: net/x25/
X86 ARCHITECTURE (32-BIT AND 64-BIT)
- P: Thomas Gleixner
- P: Ingo Molnar
- P: H. Peter Anvin
T: git git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
S: Maintained
F: arch/x86/
XEN HYPERVISOR INTERFACE
- P: Jeremy Fitzhardinge
- P: Chris Wright
S: Supported
XFS FILESYSTEM
P: Silicon Graphics Inc
- P: Felix Blyakher
W: http://oss.sgi.com/projects/xfs
F: fs/xfs/
XILINX SYSTEMACE DRIVER
- P: Grant Likely
W: http://www.secretlab.ca/
S: Maintained
F: drivers/block/xsysace.c
XILINX UARTLITE SERIAL DRIVER
- P: Peter Korsgaard
S: Maintained
F: drivers/serial/uartlite.c
YAM DRIVER FOR AX.25
- P: Jean-Paul Roubelat
S: Maintained
F: drivers/net/hamradio/yam*
F: include/linux/yam.h
YEALINK PHONE DRIVER
- P: Henk Vergonet
S: Maintained
F: Documentation/input/yealink.txt
F: drivers/input/misc/yealink.*
Z8530 DRIVER FOR AX.25
- P: Joerg Reuter
W: http://yaina.de/jreuter/
W: http://www.qsl.net/dl1bke/
F: drivers/net/hamradio/z8530.h
ZD1211RW WIRELESS DRIVER
- P: Daniel Drake
- P: Ulrich Kunitz
W: http://zd1211.ath.cx/wiki/DriverRewrite
F: drivers/media/video/zoran/
ZS DECSTATION Z85C30 SERIAL DRIVER
- P: Maciej W. Rozycki
S: Maintained
F: drivers/serial/zs.*
THE REST
- P: Linus Torvalds
T: git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
S: Buried alive in reporters
#include <linux/serial_8250.h>
#include <linux/ioport.h>
#include <linux/io.h>
- #include <linux/version.h>
#include <linux/vlynq.h>
#include <linux/leds.h>
#include <linux/string.h>
#include <linux/etherdevice.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
#include <asm/addrspace.h>
#include <asm/mach-ar7/ar7.h>
.width = 2,
};
+static struct fixed_phy_status fixed_phy_status __initdata = {
+ .link = 1,
+ .speed = 100,
+ .duplex = 1,
+};
+
static struct plat_cpmac_data cpmac_low_data = {
.reset_bit = 17,
.power_bit = 20,
.num_resources = 1,
};
- static u64 cpmac_dma_mask = DMA_32BIT_MASK;
+ static u64 cpmac_dma_mask = DMA_BIT_MASK(32);
static struct platform_device cpmac_low = {
.id = 0,
.name = "cpmac",
.dev = {
.dma_mask = &cpmac_dma_mask,
- .coherent_dma_mask = DMA_32BIT_MASK,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &cpmac_low_data,
},
.resource = cpmac_low_res,
.name = "cpmac",
.dev = {
.dma_mask = &cpmac_dma_mask,
- .coherent_dma_mask = DMA_32BIT_MASK,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &cpmac_high_data,
},
.resource = cpmac_high_res,
static int __init ar7_register_devices(void)
{
int res;
+ #ifdef CONFIG_SERIAL_8250
static struct uart_port uart_port[2];
memset(uart_port, 0, sizeof(struct uart_port) * 2);
if (res)
return res;
}
-
+ #endif /* CONFIG_SERIAL_8250 */
res = platform_device_register(&physmap_flash);
if (res)
return res;
}
if (ar7_has_high_cpmac()) {
+ res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status);
+ if (res && res != -ENODEV)
+ return res;
cpmac_get_mac(1, cpmac_high_data.dev_addr);
res = platform_device_register(&cpmac_high);
if (res)
cpmac_low_data.phy_mask = 0xffffffff;
}
+ res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
+ if (res && res != -ENODEV)
+ return res;
+
cpmac_get_mac(0, cpmac_low_data.dev_addr);
res = platform_device_register(&cpmac_low);
if (res)
PTR sys_connect
PTR sys_accept
PTR sys_sendto
- PTR sys_recvfrom
+ PTR compat_sys_recvfrom
PTR compat_sys_sendmsg /* 6045 */
PTR compat_sys_recvmsg
PTR sys_shutdown
PTR sys_pwritev
PTR compat_sys_rt_tgsigqueueinfo /* 5295 */
PTR sys_perf_counter_open
+ PTR sys_accept4
.size sysn32_call_table,.-sysn32_call_table
PTR sys_getsockname
PTR sys_getsockopt
PTR sys_listen
- PTR sys_recv /* 4175 */
- PTR sys_recvfrom
+ PTR compat_sys_recv /* 4175 */
+ PTR compat_sys_recvfrom
PTR compat_sys_recvmsg
PTR sys_send
PTR compat_sys_sendmsg
PTR compat_sys_pwritev
PTR compat_sys_rt_tgsigqueueinfo
PTR sys_perf_counter_open
+ PTR sys_accept4
.size sys_call_table,.-sys_call_table
skb->ip_summed = CHECKSUM_UNNECESSARY;
dev_dbg(xpnet, "passing skb to network layer\n"
- KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+ "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
"skb->end=0x%p skb->len=%d\n",
(void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
skb_end_pointer(skb), skb->len);
msg->buf_pa = xp_pa((void *)start_addr);
dev_dbg(xpnet, "sending XPC message to %d:%d\n"
- KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, "
+ "msg->buf_pa=0x%lx, msg->size=%u, "
"msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
msg->leadin_ignore, msg->tailout_ignore);
if (skb->data[0] == 0x33) {
dev_kfree_skb(skb);
- return 0; /* nothing needed to be done */
+ return NETDEV_TX_OK; /* nothing needed to be done */
}
/*
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
- return 0;
+ return NETDEV_TX_OK;
}
/*
CH_3C900B_FL,
CH_3C905_1,
CH_3C905_2,
+ CH_3C905B_TX,
CH_3C905B_1,
CH_3C905B_2,
PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
{"3c905 Boomerang 100baseT4",
PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
+ {"3C905B-TX Fast Etherlink XL PCI",
+ PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
{"3c905B Cyclone 100baseTx",
PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
{ 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL },
{ 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 },
{ 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 },
+ { 0x10B7, 0x9054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_TX },
{ 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 },
{ 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 },
iowrite8(0x00, ioaddr + TxStatus); /* Pop the status stack. */
}
}
- return 0;
+ return NETDEV_TX_OK;
}
static int
iowrite16(DownUnstall, ioaddr + EL3_CMD);
spin_unlock_irqrestore(&vp->lock, flags);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/* The interrupt handler does all of the Rx thread work and cleans up
&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
issue_and_wait(dev, DownStall);
for (i = 0; i < TX_RING_SIZE; i++) {
- pr_err(" %d: @%p length %8.8x status %8.8x\n", i,
- &vp->tx_ring[i],
+ unsigned int length;
+
#if DO_ZEROCOPY
- le32_to_cpu(vp->tx_ring[i].frag[0].length),
+ length = le32_to_cpu(vp->tx_ring[i].frag[0].length);
#else
- le32_to_cpu(vp->tx_ring[i].length),
+ length = le32_to_cpu(vp->tx_ring[i].length);
#endif
+ pr_err(" %d: @%p length %8.8x status %8.8x\n",
+ i, &vp->tx_ring[i], length,
le32_to_cpu(vp->tx_ring[i].status));
}
if (!stalled)
volatile struct lance_regs *ll = lp->ll;
volatile struct lance_init_block *ib = lp->init_block;
int entry, skblen;
- int status = 0;
+ int status = NETDEV_TX_OK;
unsigned long flags;
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
skblen = max_t(unsigned, skb->len, ETH_ZLEN);
local_irq_save(flags);
#ifdef DEBUG_DRIVER
/* dump the packet */
- {
- int i;
-
- for (i = 0; i < 64; i++) {
- if ((i % 16) == 0)
- printk("\n" KERN_DEBUG);
- printk ("%2.2x ", skb->data [i]);
- }
- printk("\n");
- }
+ print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE,
+ 16, 1, skb->data, 64, true);
#endif
entry = lp->tx_new & lp->tx_ring_mod_mask;
ib->btx_ring [entry].length = (-skblen) | 0xf000;
printk(KERN_DEBUG "phy registers:");
for (addr = 0; addr < 32; ++addr) {
if ((addr & 7) == 0)
- printk("\n" KERN_DEBUG);
- printk(" %.4x", bmac_mif_read(dev, addr));
+ printk(KERN_DEBUG);
+ printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr));
}
- printk("\n");
+ printk(KERN_CONT "\n");
+
if (bp->is_bmac_plus) {
unsigned int capable, ctrl;
struct bmac_data *bp = netdev_priv(dev);
skb_queue_tail(bp->queue, skb);
bmac_start(dev);
- return 0;
+ return NETDEV_TX_OK;
}
static void bmac_tx_timeout(unsigned long data)
#include "bnx2x_init_ops.h"
#include "bnx2x_dump.h"
-#define DRV_MODULE_VERSION "1.48.105-1"
-#define DRV_MODULE_RELDATE "2009/04/22"
+#define DRV_MODULE_VERSION "1.48.114-1"
+#define DRV_MODULE_RELDATE "2009/07/29"
#define BNX2X_BC_VER 0x040200
#include <linux/firmware.h>
mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104);
mark = ((mark + 0x3) & ~0x3);
- printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n" KERN_ERR, mark);
+ printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark);
+ printk(KERN_ERR PFX);
for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) {
for (word = 0; word < 8; word++)
data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH +
data[8] = 0x0;
printk(KERN_CONT "%s", (char *)data);
}
- printk("\n" KERN_ERR PFX "end of fw dump\n");
+ printk(KERN_ERR PFX "end of fw dump\n");
}
static void bnx2x_panic_dump(struct bnx2x *bp)
val, port, addr, (msix ? "MSI-X" : (msi ? "MSI" : "INTx")));
REG_WR(bp, addr, val);
+ /*
+ * Ensure that HC_CONFIG is written before leading/trailing edge config
+ */
+ mmiowb();
+ barrier();
if (CHIP_IS_E1H(bp)) {
/* init leading/trailing edge */
REG_WR(bp, HC_REG_TRAILING_EDGE_0 + port*8, val);
REG_WR(bp, HC_REG_LEADING_EDGE_0 + port*8, val);
}
+
+ /* Make sure that interrupts are indeed enabled from here on */
+ mmiowb();
}
static void bnx2x_int_disable(struct bnx2x *bp)
/* disable interrupt handling */
atomic_inc(&bp->intr_sem);
+ smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
+
if (disable_hw)
/* prevent the HW from sending interrupts */
bnx2x_int_disable(bp);
DP(BNX2X_MSG_OFF, "write 0x%08x to HC addr 0x%x\n",
(*(u32 *)&igu_ack), hc_addr);
REG_WR(bp, hc_addr, (*(u32 *)&igu_ack));
+
+ /* Make sure that ACK is written */
+ mmiowb();
+ barrier();
}
static inline u16 bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
bp->spq_prod_idx++;
}
+ /* Make sure that BD data is updated before writing the producer */
+ wmb();
+
REG_WR(bp, BAR_XSTRORM_INTMEM + XSTORM_SPQ_PROD_OFFSET(func),
bp->spq_prod_idx);
+ mmiowb();
+
spin_unlock_bh(&bp->spq_lock);
return 0;
}
}
}
+static inline void bnx2x_fan_failure(struct bnx2x *bp)
+{
+ int port = BP_PORT(bp);
+
+ /* mark the failure */
+ bp->link_params.ext_phy_config &= ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
+ bp->link_params.ext_phy_config |= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
+ SHMEM_WR(bp, dev_info.port_hw_config[port].external_phy_config,
+ bp->link_params.ext_phy_config);
+
+ /* log the failure */
+ printk(KERN_ERR PFX "Fan Failure on Network Controller %s has caused"
+ " the driver to shutdown the card to prevent permanent"
+ " damage. Please contact Dell Support for assistance\n",
+ bp->dev->name);
+}
static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
{
int port = BP_PORT(bp);
int reg_offset;
- u32 val;
+ u32 val, swap_val, swap_override;
reg_offset = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
BNX2X_ERR("SPIO5 hw attention\n");
+ /* Fan failure attention */
switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) {
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- /* Fan failure attention */
-
+ /* Low power mode is controlled by GPIO 2 */
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
/* The PHY reset is controlled by GPIO 1 */
bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
- /* Low power mode is controlled by GPIO 2 */
- bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ break;
+
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ /* The PHY reset is controlled by GPIO 1 */
+ /* fake the port number to cancel the swap done in
+ set_gpio() */
+ swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+ swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+ port = (swap_val && swap_override) ^ 1;
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
- /* mark the failure */
- bp->link_params.ext_phy_config &=
- ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
- bp->link_params.ext_phy_config |=
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE;
- SHMEM_WR(bp,
- dev_info.port_hw_config[port].
- external_phy_config,
- bp->link_params.ext_phy_config);
- /* log the failure */
- printk(KERN_ERR PFX "Fan Failure on Network"
- " Controller %s has caused the driver to"
- " shutdown the card to prevent permanent"
- " damage. Please contact Dell Support for"
- " assistance\n", bp->dev->name);
break;
default:
break;
}
+ bnx2x_fan_failure(bp);
}
if (attn & (AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 |
int mode = bp->rx_mode;
int mask = (1 << BP_L_ID(bp));
int func = BP_FUNC(bp);
+ int port = BP_PORT(bp);
int i;
+ /* All but management unicast packets should pass to the host as well */
+ u32 llh_mask =
+ NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_BRCST |
+ NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_MLCST |
+ NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_VLAN |
+ NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_NO_VLAN;
DP(NETIF_MSG_IFUP, "rx mode %d mask 0x%x\n", mode, mask);
tstorm_mac_filter.ucast_accept_all = mask;
tstorm_mac_filter.mcast_accept_all = mask;
tstorm_mac_filter.bcast_accept_all = mask;
+ /* pass management unicast packets as well */
+ llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
break;
default:
break;
}
+ REG_WR(bp,
+ (port ? NIG_REG_LLH1_BRB1_DRV_MASK : NIG_REG_LLH0_BRB1_DRV_MASK),
+ llh_mask);
+
for (i = 0; i < sizeof(struct tstorm_eth_mac_filter_config)/4; i++) {
REG_WR(bp, BAR_TSTRORM_INTMEM +
TSTORM_MAC_FILTER_CONFIG_OFFSET(func) + i * 4,
mmiowb();
bnx2x_int_enable(bp);
+
+ /* Check for SPIO5 */
+ bnx2x_attn_int_deasserted0(bp,
+ REG_RD(bp, MISC_REG_AEU_AFTER_INVERT_1_FUNC_0 + BP_PORT(bp)*4) &
+ AEU_INPUTS_ATTN_BITS_SPIO5);
}
/* end of nic init */
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, 0x1403);
}
+
+static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp)
+{
+ u32 val;
+ u8 port;
+ u8 is_required = 0;
+
+ val = SHMEM_RD(bp, dev_info.shared_hw_config.config2) &
+ SHARED_HW_CFG_FAN_FAILURE_MASK;
+
+ if (val == SHARED_HW_CFG_FAN_FAILURE_ENABLED)
+ is_required = 1;
+
+ /*
+ * The fan failure mechanism is usually related to the PHY type since
+ * the power consumption of the board is affected by the PHY. Currently,
+ * fan is required for most designs with SFX7101, BCM8727 and BCM8481.
+ */
+ else if (val == SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE)
+ for (port = PORT_0; port < PORT_MAX; port++) {
+ u32 phy_type =
+ SHMEM_RD(bp, dev_info.port_hw_config[port].
+ external_phy_config) &
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
+ is_required |=
+ ((phy_type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) ||
+ (phy_type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) ||
+ (phy_type ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481));
+ }
+
+ DP(NETIF_MSG_HW, "fan detection setting: %d\n", is_required);
+
+ if (is_required == 0)
+ return;
+
+ /* Fan failure is indicated by SPIO 5 */
+ bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
+ MISC_REGISTERS_SPIO_INPUT_HI_Z);
+
+ /* set to active low mode */
+ val = REG_RD(bp, MISC_REG_SPIO_INT);
+ val |= ((1 << MISC_REGISTERS_SPIO_5) <<
+ MISC_REGISTERS_SPIO_INT_OLD_SET_POS);
+ REG_WR(bp, MISC_REG_SPIO_INT, val);
+
+ /* enable interrupt to signal the IGU */
+ val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
+ val |= (1 << MISC_REGISTERS_SPIO_5);
+ REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
+}
+
static int bnx2x_init_common(struct bnx2x *bp)
{
u32 val, i;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
bp->port.need_hw_lock = 1;
break;
- case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
- /* Fan failure is indicated by SPIO 5 */
- bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
- MISC_REGISTERS_SPIO_INPUT_HI_Z);
-
- /* set to active low mode */
- val = REG_RD(bp, MISC_REG_SPIO_INT);
- val |= ((1 << MISC_REGISTERS_SPIO_5) <<
- MISC_REGISTERS_SPIO_INT_OLD_SET_POS);
- REG_WR(bp, MISC_REG_SPIO_INT, val);
-
- /* enable interrupt to signal the IGU */
- val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
- val |= (1 << MISC_REGISTERS_SPIO_5);
- REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
- break;
-
default:
break;
}
+ bnx2x_setup_fan_failure_detection(bp);
+
/* clear PXP2 attentions */
REG_RD(bp, PXP2_REG_PXP2_INT_STS_CLR_0);
break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
/* add SPIO 5 to group 0 */
- val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
+ {
+ u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
+ MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
+ val = REG_RD(bp, reg_addr);
val |= AEU_INPUTS_ATTN_BITS_SPIO5;
- REG_WR(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0, val);
+ REG_WR(bp, reg_addr, val);
+ }
break;
default:
}
/* send the MCP a request, block until there is a reply */
-static u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
+u32 bnx2x_fw_command(struct bnx2x *bp, u32 command)
{
int func = BP_FUNC(bp);
u32 seq = ++bp->fw_seq;
static void bnx2x_netif_start(struct bnx2x *bp)
{
- if (atomic_dec_and_test(&bp->intr_sem)) {
+ int intr_sem;
+
+ intr_sem = atomic_dec_and_test(&bp->intr_sem);
+ smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
+
+ if (intr_sem) {
if (netif_running(bp->dev)) {
bnx2x_napi_enable(bp);
bnx2x_int_enable(bp);
for (i = 0; i < MC_HASH_SIZE; i++)
REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+
+ REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
}
if (unload_mode == UNLOAD_NORMAL)
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
- else if (bp->flags & NO_WOL_FLAG) {
+ else if (bp->flags & NO_WOL_FLAG)
reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP;
- if (CHIP_IS_E1H(bp))
- REG_WR(bp, MISC_REG_E1HMF_MODE, 0);
- } else if (bp->wol) {
+ else if (bp->wol) {
u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
u8 *mac_addr = bp->dev->dev_addr;
u32 val;
#ifdef BNX2X_STOP_ON_ERROR
BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
" so reset not done to allow debug dump,\n"
- KERN_ERR " you will need to reboot when done\n");
+ " you will need to reboot when done\n");
return;
#endif
BNX2X_ERR("This driver needs bc_ver %X but found %X,"
" please upgrade BC\n", BNX2X_BC_VER, val);
}
+ bp->link_params.feature_config_flags |=
+ (val >= REQ_BC_VER_4_VRFY_OPT_MDL) ?
+ FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY : 0;
if (BP_E1HVN(bp) == 0) {
pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc);
SUPPORTED_Asym_Pause);
break;
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
+ BNX2X_DEV_INFO("ext_phy_type 0x%x (8727)\n",
+ ext_phy_type);
+
+ bp->port.supported |= (SUPPORTED_10000baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg |
+ SUPPORTED_FIBRE |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
BNX2X_DEV_INFO("ext_phy_type 0x%x (SFX7101)\n",
ext_phy_type);
bp->link_params.ext_phy_config =
SHMEM_RD(bp,
dev_info.port_hw_config[port].external_phy_config);
+ /* BCM8727_NOC => BCM8727 no over current */
+ if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) ==
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC) {
+ bp->link_params.ext_phy_config &=
+ ~PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK;
+ bp->link_params.ext_phy_config |=
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727;
+ bp->link_params.feature_config_flags |=
+ FEATURE_CONFIG_BCM8727_NOC;
+ }
+
bp->link_params.speed_cap_mask =
SHMEM_RD(bp,
dev_info.port_hw_config[port].speed_capability_mask);
bp->link_params.xgxs_config_tx[(i << 1) + 1] = (val & 0xffff);
}
- config = SHMEM_RD(bp, dev_info.port_feature_config[port].config);
- if (config & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_ENABLED)
- bp->link_params.feature_config_flags |=
- FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED;
- else
- bp->link_params.feature_config_flags &=
- ~FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED;
-
/* If the device is capable of WoL, set the default state according
* to the HW
*/
+ config = SHMEM_RD(bp, dev_info.port_feature_config[port].config);
bp->wol = (!(bp->flags & NO_WOL_FLAG) &&
(config & PORT_FEATURE_WOL_ENABLED));
bp->link_params.ext_phy_config,
bp->link_params.speed_cap_mask, bp->port.link_config);
- bp->link_params.switch_cfg = (bp->port.link_config &
- PORT_FEATURE_CONNECTED_SWITCH_MASK);
+ bp->link_params.switch_cfg |= (bp->port.link_config &
+ PORT_FEATURE_CONNECTED_SWITCH_MASK);
bnx2x_link_settings_supported(bp, bp->link_params.switch_cfg);
bnx2x_link_settings_requested(bp);
/* Disable interrupt handling until HW is initialized */
atomic_set(&bp->intr_sem, 1);
+ smp_wmb(); /* Ensure that bp->intr_sem update is SMP-safe */
mutex_init(&bp->port.phy_mutex);
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727:
cmd->port = PORT_FIBRE;
break;
{ XCM_REG_WU_DA_SET_TMR_CNT_FLG_CMD00, 4, 0x00000001 },
{ XCM_REG_WU_DA_CNT_CMD00, 4, 0x00000003 },
{ XCM_REG_GLB_DEL_ACK_MAX_CNT_0, 4, 0x000000ff },
- { NIG_REG_EGRESS_MNG0_FIFO, 20, 0xffffffff },
{ NIG_REG_LLH0_T_BIT, 4, 0x00000001 },
-/* 20 */ { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 },
- { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 },
+ { NIG_REG_EMAC0_IN_EN, 4, 0x00000001 },
+/* 20 */ { NIG_REG_BMAC0_IN_EN, 4, 0x00000001 },
{ NIG_REG_XCM0_OUT_EN, 4, 0x00000001 },
{ NIG_REG_BRB0_OUT_EN, 4, 0x00000001 },
{ NIG_REG_LLH0_XCM_MASK, 4, 0x00000007 },
{ NIG_REG_LLH0_DEST_MAC_0_0, 160, 0xffffffff },
{ NIG_REG_LLH0_DEST_IP_0_1, 160, 0xffffffff },
{ NIG_REG_LLH0_IPV4_IPV6_0, 160, 0x00000001 },
-/* 30 */ { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff },
- { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff },
+ { NIG_REG_LLH0_DEST_UDP_0, 160, 0x0000ffff },
+/* 30 */ { NIG_REG_LLH0_DEST_TCP_0, 160, 0x0000ffff },
{ NIG_REG_LLH0_VLAN_ID_0, 160, 0x00000fff },
{ NIG_REG_XGXS_SERDES0_MODE_SEL, 4, 0x00000001 },
{ NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 4, 0x00000001 },
etest->flags &= ~ETH_TEST_FL_OFFLINE;
if (etest->flags & ETH_TEST_FL_OFFLINE) {
+ int port = BP_PORT(bp);
+ u32 val;
u8 link_up;
+ /* save current value of input enable for TX port IF */
+ val = REG_RD(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4);
+ /* disable input for TX port IF */
+ REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0);
+
link_up = bp->link_vars.link_up;
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_DIAG);
etest->flags |= ETH_TEST_FL_FAILED;
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+
+ /* restore input for TX port IF */
+ REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, val);
+
bnx2x_nic_load(bp, LOAD_NORMAL);
/* wait until link state is restored */
bnx2x_wait_for_link(bp, link_up);
dev->features |= NETIF_F_HW_CSUM;
if (bp->flags & USING_DAC_FLAG)
dev->features |= NETIF_F_HIGHDMA;
+ dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
+ dev->features |= NETIF_F_TSO6;
#ifdef BCM_VLAN
dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX);
bp->flags |= (HW_VLAN_RX_FLAG | HW_VLAN_TX_FLAG);
+
+ dev->vlan_features |= NETIF_F_SG;
+ dev->vlan_features |= NETIF_F_HW_CSUM;
+ if (bp->flags & USING_DAC_FLAG)
+ dev->vlan_features |= NETIF_F_HIGHDMA;
+ dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
+ dev->vlan_features |= NETIF_F_TSO6;
#endif
- dev->features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
- dev->features |= NETIF_F_TSO6;
return 0;
netif_device_detach(dev);
+ if (state == pci_channel_io_perm_failure) {
+ rtnl_unlock();
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
if (netif_running(dev))
bnx2x_eeh_nic_unload(bp);
#ifndef MODULE
static int printed_version;
if (!printed_version++)
- printk (KERN_INFO "%s" KERN_INFO "%s",
- version, version2);
+ printk(KERN_INFO "%s%s", version, version2);
#endif
card_idx++;
unsigned long flags;
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
/* Caution: the write order is important here, set the field with the
"ownership" bit last. */
dev->name, (int)skb->len, entry, ctrl_word,
(int)inl(dev->base_addr + TxSTAT));
- return 0;
+ return NETDEV_TX_OK;
}
static void epic_tx_error(struct net_device *dev, struct epic_private *ep,
{
/* when a module, this is printed whether or not devices are found in probe */
#ifdef MODULE
- printk (KERN_INFO "%s" KERN_INFO "%s",
+ printk (KERN_INFO "%s%s",
version, version2);
#endif
unsigned long flags;
int i;
- printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
- " resetting...\n", dev->name, ioread32(ioaddr + ISR));
+ printk(KERN_WARNING
+ "%s: Transmit timed out, status %8.8x, resetting...\n",
+ dev->name, ioread32(ioaddr + ISR));
{
printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring);
for (i = 0; i < RX_RING_SIZE; i++)
- printk(" %8.8x", (unsigned int) np->rx_ring[i].status);
- printk("\n" KERN_DEBUG " Tx ring %p: ", np->tx_ring);
+ printk(KERN_CONT " %8.8x",
+ (unsigned int) np->rx_ring[i].status);
+ printk(KERN_CONT "\n");
+ printk(KERN_DEBUG " Tx ring %p: ", np->tx_ring);
for (i = 0; i < TX_RING_SIZE; i++)
- printk(" %4.4x", np->tx_ring[i].status);
- printk("\n");
+ printk(KERN_CONT " %4.4x", np->tx_ring[i].status);
+ printk(KERN_CONT "\n");
}
spin_lock_irqsave(&np->lock, flags);
dev->trans_start = jiffies;
spin_unlock_irqrestore(&np->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
{
struct fec_enet_private *fep = netdev_priv(dev);
struct bufdesc *bdp;
+ void *bufaddr;
unsigned short status;
unsigned long flags;
status &= ~BD_ENET_TX_STATS;
/* Set buffer length and buffer pointer */
- bdp->cbd_bufaddr = __pa(skb->data);
+ bufaddr = skb->data;
bdp->cbd_datlen = skb->len;
/*
* 4-byte boundaries. Use bounce buffers to copy data
* and get it aligned. Ugh.
*/
- if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
+ if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
unsigned int index;
index = bdp - fep->tx_bd_base;
memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
- bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
+ bufaddr = fep->tx_bounce[index];
}
/* Save skb pointer */
/* Push the data cache so the CPM does not get stale memory
* data.
*/
- bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+ bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
/* Send it on its way. Tell FEC it's ready, interrupt when done,
spin_unlock_irqrestore(&fep->hw_lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
static void
u32 tempval;
struct net_device *dev = NULL;
struct gfar_private *priv = NULL;
- DECLARE_MAC_BUF(mac);
int err = 0;
int len_devname;
struct gfar __iomem *regs = priv->regs;
int err = 0;
u32 rctrl = 0;
+ u32 tctrl = 0;
u32 attrs = 0;
gfar_write(®s->imask, IMASK_INIT_CLEAR);
rctrl |= RCTRL_PADDING(priv->padding);
}
+ /* keep vlan related bits if it's enabled */
+ if (priv->vlgrp) {
+ rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
+ tctrl |= TCTRL_VLINS;
+ }
+
/* Init rctrl based on our settings */
gfar_write(&priv->regs->rctrl, rctrl);
if (dev->features & NETIF_F_IP_CSUM)
- gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM);
+ tctrl |= TCTRL_INIT_CSUM;
+
+ gfar_write(&priv->regs->tctrl, tctrl);
/* Set the extraction length and index */
attrs = ATTRELI_EL(priv->rx_stash_size) |
/* Enable VLAN tag extraction */
tempval = gfar_read(&priv->regs->rctrl);
- tempval |= RCTRL_VLEX;
tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
gfar_write(&priv->regs->rctrl, tempval);
} else {
static const char version[] __devinitconst =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n"
/* IP_MF appears to be only defined in <netinet/ip.h>, however,
{
printk(KERN_DEBUG " Rx ring %p: ", hmp->rx_ring);
for (i = 0; i < RX_RING_SIZE; i++)
- printk(" %8.8x", le32_to_cpu(hmp->rx_ring[i].status_n_length));
- printk("\n"KERN_DEBUG" Tx ring %p: ", hmp->tx_ring);
+ printk(KERN_CONT " %8.8x",
+ le32_to_cpu(hmp->rx_ring[i].status_n_length));
+ printk(KERN_CONT "\n");
+ printk(KERN_DEBUG" Tx ring %p: ", hmp->tx_ring);
for (i = 0; i < TX_RING_SIZE; i++)
- printk(" %4.4x", le32_to_cpu(hmp->tx_ring[i].status_n_length));
- printk("\n");
+ printk(KERN_CONT " %4.4x",
+ le32_to_cpu(hmp->tx_ring[i].status_n_length));
+ printk(KERN_CONT "\n");
}
/* Reinit the hardware and make sure the Rx and Tx processes
printk(KERN_DEBUG "%s: Hamachi transmit frame #%d queued in slot %d.\n",
dev->name, hmp->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
/* The interrupt handler does all of the Rx thread work and cleans up
#ifdef __i386__
if (hamachi_debug > 2) {
- printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n",
+ printk(KERN_DEBUG " Tx ring at %8.8x:\n",
(int)hmp->tx_ring_dma);
for (i = 0; i < TX_RING_SIZE; i++)
- printk(" %c #%d desc. %8.8x %8.8x.\n",
+ printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x.\n",
readl(ioaddr + TxCurPtr) == (long)&hmp->tx_ring[i] ? '>' : ' ',
i, hmp->tx_ring[i].status_n_length, hmp->tx_ring[i].addr);
- printk("\n"KERN_DEBUG " Rx ring %8.8x:\n",
+ printk(KERN_DEBUG " Rx ring %8.8x:\n",
(int)hmp->rx_ring_dma);
for (i = 0; i < RX_RING_SIZE; i++) {
printk(KERN_DEBUG " %c #%d desc. %4.4x %8.8x\n",
u16 *addr = (u16 *)
hmp->rx_skbuff[i]->data;
int j;
-
+ printk(KERN_DEBUG "Addr: ");
for (j = 0; j < 0x50; j++)
printk(" %4.4x", addr[j]);
printk("\n");
static const char bc_drvname[] = "baycom_epp";
static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n"
- KERN_INFO "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
+ "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
if (skb->data[0] != 0) {
do_kiss_params(bc, skb->data, skb->len);
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
if (bc->skb)
return NETDEV_TX_LOCKED;
/* strip KISS byte */
if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) {
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
netif_stop_queue(dev);
bc->skb = skb;
- return 0;
+ return NETDEV_TX_OK;
}
/* --------------------------------------------------------------------- */
IRDA_DEBUG(0, "%s()\n", __func__ );
- for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) {
+ for (i=0; i < ARRAY_SIZE(dev_self) && io[i] < 2000; i++) {
if (w83977af_open(i, io[i], irq[i], dma[i]) == 0)
return 0;
}
w83977af_change_speed(self, speed);
dev->trans_start = jiffies;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} else
self->new_speed = speed;
}
/* Restore set register */
outb(set, iobase+SSR);
- return 0;
+ return NETDEV_TX_OK;
}
/*
u8 queue_index; /* needed for multiqueue queue management */
+ #define IXGBE_RING_RX_PS_ENABLED (u8)(1)
+ u8 flags; /* per ring feature flags */
u16 head;
u16 tail;
#define IXGBE_TX_CTXTDESC_ADV(R, i) \
(&(((struct ixgbe_adv_tx_context_desc *)((R).desc))[i]))
-#define IXGBE_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
-#define IXGBE_TX_DESC(R, i) IXGBE_GET_DESC(R, i, ixgbe_legacy_tx_desc)
-#define IXGBE_RX_DESC(R, i) IXGBE_GET_DESC(R, i, ixgbe_legacy_rx_desc)
-
#define IXGBE_MAX_JUMBO_FRAME_SIZE 16128
#ifdef IXGBE_FCOE
/* Use 3K as the baby jumbo frame size for FCoE */
static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data);
+ /**
+ * ixgbe_set_pcie_completion_timeout - set pci-e completion timeout
+ * @hw: pointer to the HW structure
+ *
+ * The defaults for 82598 should be in the range of 50us to 50ms,
+ * however the hardware default for these parts is 500us to 1ms which is less
+ * than the 10ms recommended by the pci-e spec. To address this we need to
+ * increase the value to either 10ms to 250ms for capability version 1 config,
+ * or 16ms to 55ms for version 2.
+ **/
+ void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
+ {
+ struct ixgbe_adapter *adapter = hw->back;
+ u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR);
+ u16 pcie_devctl2;
+
+ /* only take action if timeout value is defaulted to 0 */
+ if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK)
+ goto out;
+
+ /*
+ * if capababilities version is type 1 we can write the
+ * timeout of 10ms to 250ms through the GCR register
+ */
+ if (!(gcr & IXGBE_GCR_CAP_VER2)) {
+ gcr |= IXGBE_GCR_CMPL_TMOUT_10ms;
+ goto out;
+ }
+
+ /*
+ * for version 2 capabilities we need to write the config space
+ * directly in order to set the completion timeout value for
+ * 16ms to 55ms
+ */
+ pci_read_config_word(adapter->pdev,
+ IXGBE_PCI_DEVICE_CONTROL2, &pcie_devctl2);
+ pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms;
+ pci_write_config_word(adapter->pdev,
+ IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2);
+ out:
+ /* disable completion timeout resend */
+ gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND;
+ IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr);
+ }
+
/**
* ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count
* @hw: pointer to hardware structure
return ret_val;
}
+ /**
+ * ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx
+ * @hw: pointer to hardware structure
+ *
+ * Starts the hardware using the generic start_hw function.
+ * Then set pcie completion timeout
+ **/
+ s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw)
+ {
+ s32 ret_val = 0;
+
+ ret_val = ixgbe_start_hw_generic(hw);
+
+ /* set the completion timeout for interface */
+ if (ret_val == 0)
+ ixgbe_set_pcie_completion_timeout(hw);
+
+ return ret_val;
+ }
+
/**
* ixgbe_get_link_capabilities_82598 - Determines link capabilities
* @hw: pointer to hardware structure
media_type = ixgbe_media_type_fiber;
break;
case IXGBE_DEV_ID_82598AT:
+ case IXGBE_DEV_ID_82598AT2:
media_type = ixgbe_media_type_copper;
break;
default:
static struct ixgbe_mac_operations mac_ops_82598 = {
.init_hw = &ixgbe_init_hw_generic,
.reset_hw = &ixgbe_reset_hw_82598,
- .start_hw = &ixgbe_start_hw_generic,
+ .start_hw = &ixgbe_start_hw_82598,
.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic,
.get_media_type = &ixgbe_get_media_type_82598,
.get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82598,
static const char ixgbe_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Network Driver";
-#define DRV_VERSION "2.0.34-k2"
+#define DRV_VERSION "2.0.37-k2"
const char ixgbe_driver_version[] = DRV_VERSION;
static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation.";
board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT),
board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT2),
+ board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4),
board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT),
rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
if (!bi->page_dma &&
- (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)) {
+ (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) {
if (!bi->page) {
bi->page = alloc_page(GFP_ATOMIC);
if (!bi->page) {
}
/* Refresh the desc even if buffer_addrs didn't change because
* each write-back erases this info. */
- if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+ if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
} else {
break;
(*work_done)++;
- if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+ if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc));
len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
IXGBE_RXDADV_HDRBUFLEN_SHIFT;
rx_ring->stats.packets++;
rx_ring->stats.bytes += skb->len;
} else {
- if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+ if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
rx_buffer_info->skb = next_buffer->skb;
rx_buffer_info->dma = next_buffer->dma;
next_buffer->skb = skb;
#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
- static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index)
+ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *rx_ring)
{
- struct ixgbe_ring *rx_ring;
u32 srrctl;
- int queue0 = 0;
- unsigned long mask;
+ int index;
struct ixgbe_ring_feature *feature = adapter->ring_feature;
- if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
- if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
- int dcb_i = feature[RING_F_DCB].indices;
- if (dcb_i == 8)
- queue0 = index >> 4;
- else if (dcb_i == 4)
- queue0 = index >> 5;
- else
- dev_err(&adapter->pdev->dev, "Invalid DCB "
- "configuration\n");
- #ifdef IXGBE_FCOE
- if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
- struct ixgbe_ring_feature *f;
-
- rx_ring = &adapter->rx_ring[queue0];
- f = &adapter->ring_feature[RING_F_FCOE];
- if ((queue0 == 0) && (index > rx_ring->reg_idx))
- queue0 = f->mask + index -
- rx_ring->reg_idx - 1;
- }
- #endif /* IXGBE_FCOE */
- } else {
- queue0 = index;
- }
- } else {
+ index = rx_ring->reg_idx;
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+ unsigned long mask;
mask = (unsigned long) feature[RING_F_RSS].mask;
- queue0 = index & mask;
index = index & mask;
}
-
- rx_ring = &adapter->rx_ring[queue0];
-
srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(index));
srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
IXGBE_SRRCTL_BSIZEHDR_MASK;
- if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+ if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
#if (PAGE_SIZE / 2) > IXGBE_MAX_RXBUFFER
srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
#else
{
u64 rdba;
struct ixgbe_hw *hw = &adapter->hw;
+ struct ixgbe_ring *rx_ring;
struct net_device *netdev = adapter->netdev;
int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
int i, j;
/* Decide whether to use packet split mode or not */
adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
- #ifdef IXGBE_FCOE
- if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
- adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
- #endif /* IXGBE_FCOE */
-
/* Set the RX buffer length according to the mode */
if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
rx_buf_len = IXGBE_RX_HDR_SIZE;
* the Base and Length of the Rx Descriptor Ring
*/
for (i = 0; i < adapter->num_rx_queues; i++) {
- rdba = adapter->rx_ring[i].dma;
- j = adapter->rx_ring[i].reg_idx;
+ rx_ring = &adapter->rx_ring[i];
+ rdba = rx_ring->dma;
+ j = rx_ring->reg_idx;
IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_BIT_MASK(32)));
IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), rdlen);
IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
- adapter->rx_ring[i].head = IXGBE_RDH(j);
- adapter->rx_ring[i].tail = IXGBE_RDT(j);
- adapter->rx_ring[i].rx_buf_len = rx_buf_len;
+ rx_ring->head = IXGBE_RDH(j);
+ rx_ring->tail = IXGBE_RDT(j);
+ rx_ring->rx_buf_len = rx_buf_len;
+
+ if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)
+ rx_ring->flags |= IXGBE_RING_RX_PS_ENABLED;
#ifdef IXGBE_FCOE
if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
struct ixgbe_ring_feature *f;
f = &adapter->ring_feature[RING_F_FCOE];
- if ((rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE) &&
- (i >= f->mask) && (i < f->mask + f->indices))
- adapter->rx_ring[i].rx_buf_len =
- IXGBE_FCOE_JUMBO_FRAME_SIZE;
+ if ((i >= f->mask) && (i < f->mask + f->indices)) {
+ rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED;
+ if (rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE)
+ rx_ring->rx_buf_len =
+ IXGBE_FCOE_JUMBO_FRAME_SIZE;
+ }
}
#endif /* IXGBE_FCOE */
- ixgbe_configure_srrctl(adapter, j);
+ ixgbe_configure_srrctl(adapter, rx_ring);
}
if (hw->mac.type == ixgbe_mac_82598EB) {
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
/* Enable 82599 HW-RSC */
for (i = 0; i < adapter->num_rx_queues; i++) {
- j = adapter->rx_ring[i].reg_idx;
+ rx_ring = &adapter->rx_ring[i];
+ j = rx_ring->reg_idx;
rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
rscctrl |= IXGBE_RSCCTL_RSCEN;
/*
* total size of max desc * buf_len is not greater
* than 65535
*/
- if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+ if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
#if (MAX_SKB_FRAGS > 16)
rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
#elif (MAX_SKB_FRAGS > 8)
if (hw->mac.type == ixgbe_mac_82599EB) {
u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
- flow_rx = (mflcn & IXGBE_MFLCN_RFCE);
- flow_tx = (fccfg & IXGBE_FCCFG_TFCE_802_3X);
+ flow_rx = !!(mflcn & IXGBE_MFLCN_RFCE);
+ flow_tx = !!(fccfg & IXGBE_FCCFG_TFCE_802_3X);
} else {
u32 frctl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS);
- flow_rx = (frctl & IXGBE_FCTRL_RFCE);
- flow_tx = (rmcs & IXGBE_RMCS_TFCE_802_3X);
+ flow_rx = !!(frctl & IXGBE_FCTRL_RFCE);
+ flow_tx = !!(rmcs & IXGBE_RMCS_TFCE_802_3X);
}
printk(KERN_INFO "ixgbe: %s NIC Link is Up %s, "
return smp_processor_id();
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
- return 0; /* All traffic should default to class 0 */
+ return (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK) >> 13;
return skb_tx_hash(dev, skb);
}
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
#define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB
#define IXGBE_DEV_ID_82598AT 0x10C8
+#define IXGBE_DEV_ID_82598AT2 0x150B
#define IXGBE_DEV_ID_82598EB_CX4 0x10DD
#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
#define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1
#define IXGBE_ECC_STATUS_82599 0x110E0
#define IXGBE_BAR_CTRL_82599 0x110F4
+ /* PCI Express Control */
+ #define IXGBE_GCR_CMPL_TMOUT_MASK 0x0000F000
+ #define IXGBE_GCR_CMPL_TMOUT_10ms 0x00001000
+ #define IXGBE_GCR_CMPL_TMOUT_RESEND 0x00010000
+ #define IXGBE_GCR_CAP_VER2 0x00040000
+
/* Time Sync Registers */
#define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */
#define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */
/* PCI Bus Info */
#define IXGBE_PCI_LINK_STATUS 0xB2
+ #define IXGBE_PCI_DEVICE_CONTROL2 0xC8
#define IXGBE_PCI_LINK_WIDTH 0x3F0
#define IXGBE_PCI_LINK_WIDTH_1 0x10
#define IXGBE_PCI_LINK_WIDTH_2 0x20
#define IXGBE_PCI_LINK_SPEED_5000 0x2
#define IXGBE_PCI_HEADER_TYPE_REGISTER 0x0E
#define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80
+ #define IXGBE_PCI_DEVICE_CONTROL2_16ms 0x0005
/* Number of 100 microseconds we wait for PCI Express master disable */
#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
#define IXGBE_FDIR_INIT_DONE_POLL 10
#define IXGBE_FDIRCMD_CMD_POLL 10
-/* Transmit Descriptor - Legacy */
-struct ixgbe_legacy_tx_desc {
- u64 buffer_addr; /* Address of the descriptor's data buffer */
- union {
- __le32 data;
- struct {
- __le16 length; /* Data buffer length */
- u8 cso; /* Checksum offset */
- u8 cmd; /* Descriptor control */
- } flags;
- } lower;
- union {
- __le32 data;
- struct {
- u8 status; /* Descriptor status */
- u8 css; /* Checksum start */
- __le16 vlan;
- } fields;
- } upper;
-};
-
/* Transmit Descriptor - Advanced */
union ixgbe_adv_tx_desc {
struct {
} wb;
};
-/* Receive Descriptor - Legacy */
-struct ixgbe_legacy_rx_desc {
- __le64 buffer_addr; /* Address of the descriptor's data buffer */
- __le16 length; /* Length of data DMAed into data buffer */
- __le16 csum; /* Packet checksum */
- u8 status; /* Descriptor status */
- u8 errors; /* Descriptor Errors */
- __le16 vlan;
-};
-
/* Receive Descriptor - Advanced */
union ixgbe_adv_rx_desc {
struct {
#include "mlx4_en.h"
-static void *get_wqe(struct mlx4_en_rx_ring *ring, int n)
-{
- int offset = n << ring->srq.wqe_shift;
- return ring->buf + offset;
-}
-
-static void mlx4_en_srq_event(struct mlx4_srq *srq, enum mlx4_event type)
-{
- return;
-}
static int mlx4_en_get_frag_header(struct skb_frag_struct *frags, void **mac_hdr,
void **ip_hdr, void **tcpudp_hdr,
int possible_frags;
int i;
- /* Pre-link descriptor */
- rx_desc->next.next_wqe_index = cpu_to_be16((index + 1) & ring->size_mask);
-
/* Set size and memtype fields */
for (i = 0; i < priv->num_frags; i++) {
skb_frags[i].size = priv->frag_info[i].frag_size;
int err;
int tmp;
- /* Sanity check SRQ size before proceeding */
- if (size >= mdev->dev->caps.max_srq_wqes)
- return -EINVAL;
ring->prod = 0;
ring->cons = 0;
ring->size_mask = size - 1;
ring->stride = stride;
ring->log_stride = ffs(ring->stride) - 1;
- ring->buf_size = ring->size * ring->stride;
+ ring->buf_size = ring->size * ring->stride + TXBB_SIZE;
tmp = size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS *
sizeof(struct skb_frag_struct));
int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
{
- struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_wqe_srq_next_seg *next;
struct mlx4_en_rx_ring *ring;
int i;
int ring_ind;
int err;
int stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
DS_SIZE * priv->num_frags);
- int max_gs = (stride - sizeof(struct mlx4_wqe_srq_next_seg)) / DS_SIZE;
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
ring = &priv->rx_ring[ring_ind];
ring->cqn = priv->rx_cq[ring_ind].mcq.cqn;
ring->stride = stride;
+ if (ring->stride <= TXBB_SIZE)
+ ring->buf += TXBB_SIZE;
+
ring->log_stride = ffs(ring->stride) - 1;
ring->buf_size = ring->size * ring->stride;
ring = &priv->rx_ring[ring_ind];
mlx4_en_update_rx_prod_db(ring);
-
- /* Configure SRQ representing the ring */
- ring->srq.max = ring->actual_size;
- ring->srq.max_gs = max_gs;
- ring->srq.wqe_shift = ilog2(ring->stride);
-
- for (i = 0; i < ring->srq.max; ++i) {
- next = get_wqe(ring, i);
- next->next_wqe_index =
- cpu_to_be16((i + 1) & (ring->srq.max - 1));
- }
-
- err = mlx4_srq_alloc(mdev->dev, mdev->priv_pdn, &ring->wqres.mtt,
- ring->wqres.db.dma, &ring->srq);
- if (err){
- en_err(priv, "Failed to allocate srq\n");
- ring_ind--;
- goto err_srq;
- }
- ring->srq.event = mlx4_en_srq_event;
}
return 0;
-err_srq:
- while (ring_ind >= 0) {
- ring = &priv->rx_ring[ring_ind];
- mlx4_srq_free(mdev->dev, &ring->srq);
- ring_ind--;
- }
-
err_buffers:
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++)
mlx4_en_free_rx_buf(priv, &priv->rx_ring[ring_ind]);
kfree(ring->lro.lro_arr);
mlx4_en_unmap_buffer(&ring->wqres.buf);
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+ mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
vfree(ring->rx_info);
ring->rx_info = NULL;
}
void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring *ring)
{
- struct mlx4_en_dev *mdev = priv->mdev;
-
- mlx4_srq_free(mdev->dev, &ring->srq);
mlx4_en_free_rx_buf(priv, ring);
+ if (ring->stride <= TXBB_SIZE)
+ ring->buf -= TXBB_SIZE;
mlx4_en_destroy_allocator(priv, ring);
}
PCI_DMA_FROMDEVICE);
}
/* Adjust size of last fragment to match actual length */
- skb_frags_rx[nr - 1].size = length -
- priv->frag_info[nr - 1].frag_prefix_size;
+ if (nr > 0)
+ skb_frags_rx[nr - 1].size = length -
+ priv->frag_info[nr - 1].frag_prefix_size;
return nr;
fail:
/* RSS related functions */
-/* Calculate rss size and map each entry in rss table to rx ring */
-void mlx4_en_set_default_rss_map(struct mlx4_en_priv *priv,
- struct mlx4_en_rss_map *rss_map,
- int num_entries, int num_rings)
-{
- int i;
-
- rss_map->size = roundup_pow_of_two(num_entries);
- en_dbg(DRV, priv, "Setting default RSS map of %d entires\n",
- rss_map->size);
-
- for (i = 0; i < rss_map->size; i++) {
- rss_map->map[i] = i % num_rings;
- en_dbg(DRV, priv, "Entry %d ---> ring %d\n", i, rss_map->map[i]);
- }
-}
-
-static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv,
- int qpn, int srqn, int cqn,
+static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
+ struct mlx4_en_rx_ring *ring,
enum mlx4_qp_state *state,
struct mlx4_qp *qp)
{
qp->event = mlx4_en_sqp_event;
memset(context, 0, sizeof *context);
- mlx4_en_fill_qp_context(priv, 0, 0, 0, 0, qpn, cqn, srqn, context);
+ mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 0, 0,
+ qpn, ring->cqn, context);
+ context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
- err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, context, qp, state);
+ err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, context, qp, state);
if (err) {
mlx4_qp_remove(mdev->dev, qp);
mlx4_qp_free(mdev->dev, qp);
}
+ mlx4_en_update_rx_prod_db(ring);
out:
kfree(context);
return err;
void *ptr;
int rss_xor = mdev->profile.rss_xor;
u8 rss_mask = mdev->profile.rss_mask;
- int i, srqn, qpn, cqn;
+ int i, qpn;
int err = 0;
int good_qps = 0;
en_dbg(DRV, priv, "Configuring rss steering\n");
- err = mlx4_qp_reserve_range(mdev->dev, rss_map->size,
- rss_map->size, &rss_map->base_qpn);
+ err = mlx4_qp_reserve_range(mdev->dev, priv->rx_ring_num,
+ priv->rx_ring_num,
+ &rss_map->base_qpn);
if (err) {
- en_err(priv, "Failed reserving %d qps\n", rss_map->size);
+ en_err(priv, "Failed reserving %d qps\n", priv->rx_ring_num);
return err;
}
- for (i = 0; i < rss_map->size; i++) {
- cqn = priv->rx_ring[rss_map->map[i]].cqn;
- srqn = priv->rx_ring[rss_map->map[i]].srq.srqn;
+ for (i = 0; i < priv->rx_ring_num; i++) {
qpn = rss_map->base_qpn + i;
- err = mlx4_en_config_rss_qp(priv, qpn, srqn, cqn,
+ err = mlx4_en_config_rss_qp(priv, qpn, &priv->rx_ring[i],
&rss_map->state[i],
&rss_map->qps[i]);
if (err)
}
rss_map->indir_qp.event = mlx4_en_sqp_event;
mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
- priv->rx_ring[0].cqn, 0, &context);
+ priv->rx_ring[0].cqn, &context);
ptr = ((void *) &context) + 0x3c;
rss_context = (struct mlx4_en_rss_context *) ptr;
- rss_context->base_qpn = cpu_to_be32(ilog2(rss_map->size) << 24 |
+ rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
rss_context->hash_fn = rss_xor & 0x3;
mlx4_qp_remove(mdev->dev, &rss_map->qps[i]);
mlx4_qp_free(mdev->dev, &rss_map->qps[i]);
}
- mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, rss_map->size);
+ mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, priv->rx_ring_num);
return err;
}
mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
- for (i = 0; i < rss_map->size; i++) {
+ for (i = 0; i < priv->rx_ring_num; i++) {
mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->qps[i]);
mlx4_qp_remove(mdev->dev, &rss_map->qps[i]);
mlx4_qp_free(mdev->dev, &rss_map->qps[i]);
}
- mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, rss_map->size);
+ mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, priv->rx_ring_num);
}
int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring,
- int cq, int srqn)
+ int cq)
{
struct mlx4_en_dev *mdev = priv->mdev;
int err;
ring->doorbell_qpn = swab32(ring->qp.qpn << 8);
mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
- ring->cqn, srqn, &ring->context);
+ ring->cqn, &ring->context);
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
&ring->qp, &ring->qp_state);
pci_unmap_page(mdev->pdev,
(dma_addr_t) be64_to_cpu(data->addr),
frag->size, PCI_DMA_TODEVICE);
+ ++data;
}
}
/* Stamp the freed descriptor */
/* Poll CQ here */
mlx4_en_xmit_poll(priv, tx_ind);
- return 0;
+ return NETDEV_TX_OK;
tx_drop:
dev_kfree_skb_any(skb);
static const char version[] __devinitconst =
KERN_INFO DRV_NAME " dp8381x driver, version "
DRV_VERSION ", " DRV_RELDATE "\n"
- KERN_INFO " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n";
+ " 2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n";
MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver");
printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
dev->name, np->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
static void netdev_tx_done(struct net_device *dev)
#include <linux/if_vlan.h>
#include <net/ip.h>
#include <linux/ipv6.h>
+#include <linux/inetdevice.h>
MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver");
MODULE_LICENSE("GPL");
static int netxen_nic_close(struct net_device *netdev);
static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
static void netxen_tx_timeout(struct net_device *netdev);
-static void netxen_tx_timeout_task(struct work_struct *work);
+static void netxen_reset_task(struct work_struct *work);
static void netxen_watchdog(unsigned long);
static int netxen_nic_poll(struct napi_struct *napi, int budget);
#ifdef CONFIG_NET_POLL_CONTROLLER
struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
- return 1;
+ return -ENOMEM;
for (ring = 0; ring < adapter->max_sds_rings; ring++) {
sds_ring = &recv_ctx->sds_rings[ring];
}
}
- static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
+ static int nx_set_dma_mask(struct netxen_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
uint64_t mask, cmask;
adapter->pci_using_dac = 0;
mask = DMA_BIT_MASK(32);
- /*
- * Consistent DMA mask is set to 32 bit because it cannot be set to
- * 35 bits. For P3 also leave it at 32 bits for now. Only the rings
- * come off this pool.
- */
cmask = DMA_BIT_MASK(32);
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
#ifndef CONFIG_IA64
- if (revision_id >= NX_P3_B0)
- mask = DMA_BIT_MASK(39);
- else if (revision_id == NX_P2_C1)
mask = DMA_BIT_MASK(35);
#endif
+ } else {
+ mask = DMA_BIT_MASK(39);
+ cmask = mask;
+ }
+
if (pci_set_dma_mask(pdev, mask) == 0 &&
pci_set_consistent_dma_mask(pdev, cmask) == 0) {
adapter->pci_using_dac = 1;
nx_update_dma_mask(struct netxen_adapter *adapter)
{
int change, shift, err;
- uint64_t mask, old_mask;
+ uint64_t mask, old_mask, old_cmask;
struct pci_dev *pdev = adapter->pdev;
change = 0;
shift = NXRD32(adapter, CRB_DMA_SHIFT);
- if (shift >= 32)
+ if (shift > 32)
return 0;
if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && (shift > 9))
if (change) {
old_mask = pdev->dma_mask;
- mask = (1ULL<<(32+shift)) - 1;
+ old_cmask = pdev->dev.coherent_dma_mask;
+
+ mask = DMA_BIT_MASK(32+shift);
err = pci_set_dma_mask(pdev, mask);
if (err)
- return pci_set_dma_mask(pdev, old_mask);
+ goto err_out;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+
+ err = pci_set_consistent_dma_mask(pdev, mask);
+ if (err)
+ goto err_out;
+ }
+ dev_info(&pdev->dev, "using %d-bit dma mask\n", 32+shift);
}
return 0;
+
+ err_out:
+ pci_set_dma_mask(pdev, old_mask);
+ pci_set_consistent_dma_mask(pdev, old_cmask);
+ return err;
}
-static void netxen_check_options(struct netxen_adapter *adapter)
+static void
+netxen_check_options(struct netxen_adapter *adapter)
{
- if (adapter->ahw.port_type == NETXEN_NIC_XGBE)
- adapter->num_rxd = MAX_RCV_DESCRIPTORS_10G;
- else if (adapter->ahw.port_type == NETXEN_NIC_GBE)
- adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G;
+ if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
+ } else if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
+ adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
+ adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
+ }
adapter->msix_supported = 0;
if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
}
}
- adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST;
- adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS;
- adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
+ adapter->num_txd = MAX_CMD_DESCRIPTORS;
- return;
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
+ adapter->max_rds_rings = 3;
+ } else {
+ adapter->num_lro_rxd = 0;
+ adapter->max_rds_rings = 2;
+ }
}
static int
}
- err = netxen_initialize_adapter_offload(adapter);
+ err = netxen_init_dummy_dma(adapter);
if (err)
return err;
/* Handshake with the card before we register the devices. */
err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
if (err) {
- netxen_free_adapter_offload(adapter);
+ netxen_free_dummy_dma(adapter);
return err;
}
+ nx_update_dma_mask(adapter);
+
+ netxen_nic_get_firmware_info(adapter);
+
return 0;
}
}
}
+static void
+netxen_nic_init_coalesce_defaults(struct netxen_adapter *adapter)
+{
+ adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
+ adapter->coal.normal.data.rx_time_us =
+ NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
+ adapter->coal.normal.data.rx_packets =
+ NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
+ adapter->coal.normal.data.tx_time_us =
+ NETXEN_DEFAULT_INTR_COALESCE_TX_TIME_US;
+ adapter->coal.normal.data.tx_packets =
+ NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS;
+}
+
static int
netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
{
if (adapter->max_sds_rings > 1)
netxen_config_rss(adapter, 1);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_config_intr_coalesce(adapter);
+
netxen_napi_enable(adapter);
if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)
struct nx_host_rds_ring *rds_ring;
struct nx_host_tx_ring *tx_ring;
+ if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
+ return 0;
+
err = netxen_init_firmware(adapter);
if (err != 0) {
printk(KERN_ERR "Failed to init firmware\n");
return -EIO;
}
- if (adapter->fw_major < 4)
- adapter->max_rds_rings = 3;
- else
- adapter->max_rds_rings = 2;
-
err = netxen_alloc_sw_resources(adapter);
if (err) {
printk(KERN_ERR "%s: Error in setting sw resources\n",
goto err_out_free_sw;
}
- if (adapter->fw_major < 4) {
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
tx_ring = adapter->tx_ring;
tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum];
tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum];
goto err_out_free_rxbuf;
}
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_nic_init_coalesce_defaults(adapter);
+
adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
return 0;
static void
netxen_nic_detach(struct netxen_adapter *adapter)
{
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return;
+
netxen_free_hw_resources(adapter);
netxen_release_rx_buffers(adapter);
netxen_nic_free_irq(adapter);
adapter->is_up = 0;
}
+int
+netxen_nic_reset_context(struct netxen_adapter *adapter)
+{
+ int err = 0;
+ struct net_device *netdev = adapter->netdev;
+
+ if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
+
+ if (netif_running(netdev))
+ netxen_nic_down(adapter, netdev);
+
+ netxen_nic_detach(adapter);
+
+ err = netxen_nic_attach(adapter);
+ if (err)
+ goto done;
+
+ if (netif_running(netdev))
+ err = netxen_nic_up(adapter, netdev);
+ }
+done:
+ return err;
+}
+
+static int
+netxen_setup_netdev(struct netxen_adapter *adapter,
+ struct net_device *netdev)
+{
+ int err = 0;
+ struct pci_dev *pdev = adapter->pdev;
+
+ adapter->rx_csum = 1;
+ adapter->mc_enabled = 0;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ adapter->max_mc_count = 38;
+ else
+ adapter->max_mc_count = 16;
+
+ netdev->netdev_ops = &netxen_netdev_ops;
+ netdev->watchdog_timeo = 2*HZ;
+
+ netxen_nic_change_mtu(netdev, netdev->mtu);
+
+ SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
+
+ netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+ netdev->features |= (NETIF_F_GRO);
+ netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
+ netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
+ }
+
+ if (adapter->pci_using_dac) {
+ netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
+
+ if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX)
+ netdev->features |= (NETIF_F_HW_VLAN_TX);
+
+ netdev->irq = adapter->msix_entries[0].vector;
+
+ err = netxen_napi_add(adapter, netdev);
+ if (err)
+ return err;
+
+ init_timer(&adapter->watchdog_timer);
+ adapter->watchdog_timer.function = &netxen_watchdog;
+ adapter->watchdog_timer.data = (unsigned long)adapter;
+ INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
+ INIT_WORK(&adapter->tx_timeout_task, netxen_reset_task);
+
+ if (netxen_read_mac_addr(adapter))
+ dev_warn(&pdev->dev, "failed to read mac addr\n");
+
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+
+ err = register_netdev(netdev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register net device\n");
+ return err;
+ }
+
+ return 0;
+}
+
static int __devinit
netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
netdev = alloc_etherdev(sizeof(struct netxen_adapter));
if(!netdev) {
- printk(KERN_ERR"%s: Failed to allocate memory for the "
- "device block.Check system memory resource"
- " usage.\n", netxen_nic_driver_name);
+ dev_err(&pdev->dev, "failed to allocate net_device\n");
+ err = -ENOMEM;
goto err_out_free_res;
}
revision_id = pdev->revision;
adapter->ahw.revision_id = revision_id;
- err = nx_set_dma_mask(adapter, revision_id);
+ err = nx_set_dma_mask(adapter);
if (err)
goto err_out_free_netdev;
/* This will be reset for mezz cards */
adapter->portnum = pci_func_id;
- adapter->rx_csum = 1;
- adapter->mc_enabled = 0;
- if (NX_IS_REVISION_P3(revision_id))
- adapter->max_mc_count = 38;
- else
- adapter->max_mc_count = 16;
-
- netdev->netdev_ops = &netxen_netdev_ops;
- netdev->watchdog_timeo = 2*HZ;
-
- netxen_nic_change_mtu(netdev, netdev->mtu);
- SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
-
- netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
- netdev->features |= (NETIF_F_GRO);
- netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
-
- if (NX_IS_REVISION_P3(revision_id)) {
- netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
- netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6);
- }
-
- if (adapter->pci_using_dac) {
- netdev->features |= NETIF_F_HIGHDMA;
- netdev->vlan_features |= NETIF_F_HIGHDMA;
- }
-
- if (netxen_nic_get_board_info(adapter) != 0) {
- printk("%s: Error getting board config info.\n",
- netxen_nic_driver_name);
- err = -EIO;
+ err = netxen_nic_get_board_info(adapter);
+ if (err) {
+ dev_err(&pdev->dev, "Error getting board config info.\n");
goto err_out_iounmap;
}
if (err)
goto err_out_iounmap;
- nx_update_dma_mask(adapter);
-
- netxen_nic_get_firmware_info(adapter);
-
/*
* See if the firmware gave us a virtual-physical port mapping.
*/
adapter->physical_port = adapter->portnum;
- if (adapter->fw_major < 4) {
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
i = NXRD32(adapter, CRB_V2P(adapter->portnum));
if (i != 0x55555555)
adapter->physical_port = i;
netxen_setup_intr(adapter);
- netdev->irq = adapter->msix_entries[0].vector;
-
- if (netxen_napi_add(adapter, netdev))
- goto err_out_disable_msi;
-
- init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &netxen_watchdog;
- adapter->watchdog_timer.data = (unsigned long)adapter;
- INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
- INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
-
- err = netxen_read_mac_addr(adapter);
+ err = netxen_setup_netdev(adapter, netdev);
if (err)
- dev_warn(&pdev->dev, "failed to read mac addr\n");
-
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
-
- if ((err = register_netdev(netdev))) {
- printk(KERN_ERR "%s: register_netdev failed port #%d"
- " aborting\n", netxen_nic_driver_name,
- adapter->portnum);
- err = -EIO;
goto err_out_disable_msi;
- }
pci_set_drvdata(pdev, adapter);
err_out_disable_msi:
netxen_teardown_intr(adapter);
- netxen_free_adapter_offload(adapter);
+ netxen_free_dummy_dma(adapter);
err_out_iounmap:
netxen_cleanup_pci_map(adapter);
unregister_netdev(netdev);
- if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
- netxen_nic_detach(adapter);
- }
+ netxen_nic_detach(adapter);
if (adapter->portnum == 0)
- netxen_free_adapter_offload(adapter);
+ netxen_free_dummy_dma(adapter);
netxen_teardown_intr(adapter);
netxen_free_sds_rings(&adapter->recv_ctx);
if (netif_running(netdev))
netxen_nic_down(adapter, netdev);
- if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
- netxen_nic_detach(adapter);
+ netxen_nic_detach(adapter);
pci_save_state(pdev);
if (adapter->driver_mismatch)
return -EIO;
- if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
- err = netxen_nic_attach(adapter);
- if (err)
- return err;
- }
+ err = netxen_nic_attach(adapter);
+ if (err)
+ return err;
err = netxen_nic_up(adapter, netdev);
if (err)
return 0;
}
-static bool netxen_tso_check(struct net_device *netdev,
- struct cmd_desc_type0 *desc, struct sk_buff *skb)
+static void
+netxen_tso_check(struct net_device *netdev,
+ struct nx_host_tx_ring *tx_ring,
+ struct cmd_desc_type0 *first_desc,
+ struct sk_buff *skb)
{
- bool tso = false;
u8 opcode = TX_ETHER_PKT;
__be16 protocol = skb->protocol;
- u16 flags = 0;
+ u16 flags = 0, vid = 0;
+ u32 producer;
+ int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0;
+ struct cmd_desc_type0 *hwdesc;
+ struct vlan_ethhdr *vh;
if (protocol == cpu_to_be16(ETH_P_8021Q)) {
- struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data;
+
+ vh = (struct vlan_ethhdr *)skb->data;
protocol = vh->h_vlan_encapsulated_proto;
flags = FLAGS_VLAN_TAGGED;
+
+ } else if (vlan_tx_tag_present(skb)) {
+
+ flags = FLAGS_VLAN_OOB;
+ vid = vlan_tx_tag_get(skb);
+ netxen_set_tx_vlan_tci(first_desc, vid);
+ vlan_oob = 1;
}
if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
skb_shinfo(skb)->gso_size > 0) {
- desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
- desc->total_hdr_length =
- skb_transport_offset(skb) + tcp_hdrlen(skb);
+ hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+
+ first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+ first_desc->total_hdr_length = hdr_len;
+ if (vlan_oob) {
+ first_desc->total_hdr_length += VLAN_HLEN;
+ first_desc->tcp_hdr_offset = VLAN_HLEN;
+ first_desc->ip_hdr_offset = VLAN_HLEN;
+ /* Only in case of TSO on vlan device */
+ flags |= FLAGS_VLAN_TAGGED;
+ }
opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ?
TX_TCP_LSO6 : TX_TCP_LSO;
- tso = true;
+ tso = 1;
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
u8 l4proto;
opcode = TX_UDPV6_PKT;
}
}
- desc->tcp_hdr_offset = skb_transport_offset(skb);
- desc->ip_hdr_offset = skb_network_offset(skb);
- netxen_set_tx_flags_opcode(desc, flags, opcode);
- return tso;
+
+ first_desc->tcp_hdr_offset += skb_transport_offset(skb);
+ first_desc->ip_hdr_offset += skb_network_offset(skb);
+ netxen_set_tx_flags_opcode(first_desc, flags, opcode);
+
+ if (!tso)
+ return;
+
+ /* For LSO, we need to copy the MAC/IP/TCP headers into
+ * the descriptor ring
+ */
+ producer = tx_ring->producer;
+ copied = 0;
+ offset = 2;
+
+ if (vlan_oob) {
+ /* Create a TSO vlan header template for firmware */
+
+ hwdesc = &tx_ring->desc_head[producer];
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+ copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
+ hdr_len + VLAN_HLEN);
+
+ vh = (struct vlan_ethhdr *)((char *)hwdesc + 2);
+ skb_copy_from_linear_data(skb, vh, 12);
+ vh->h_vlan_proto = htons(ETH_P_8021Q);
+ vh->h_vlan_TCI = htons(vid);
+ skb_copy_from_linear_data_offset(skb, 12,
+ (char *)vh + 16, copy_len - 16);
+
+ copied = copy_len - VLAN_HLEN;
+ offset = 0;
+
+ producer = get_next_index(producer, tx_ring->num_desc);
+ }
+
+ while (copied < hdr_len) {
+
+ copy_len = min((int)sizeof(struct cmd_desc_type0) - offset,
+ (hdr_len - copied));
+
+ hwdesc = &tx_ring->desc_head[producer];
+ tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+ skb_copy_from_linear_data_offset(skb, copied,
+ (char *)hwdesc + offset, copy_len);
+
+ copied += copy_len;
+ offset = 0;
+
+ producer = get_next_index(producer, tx_ring->num_desc);
+ }
+
+ tx_ring->producer = producer;
+ barrier();
}
static void
static inline void
netxen_clear_cmddesc(u64 *desc)
{
- int i;
- for (i = 0; i < 8; i++)
- desc[i] = 0ULL;
+ desc[0] = 0ULL;
+ desc[2] = 0ULL;
}
static int
{
struct netxen_adapter *adapter = netdev_priv(netdev);
struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
- unsigned int first_seg_len = skb->len - skb->data_len;
+ struct skb_frag_struct *frag;
struct netxen_cmd_buffer *pbuf;
struct netxen_skb_frag *buffrag;
- struct cmd_desc_type0 *hwdesc;
- struct pci_dev *pdev = adapter->pdev;
+ struct cmd_desc_type0 *hwdesc, *first_desc;
+ struct pci_dev *pdev;
dma_addr_t temp_dma;
int i, k;
+ unsigned long offset;
u32 producer;
- int frag_count, no_of_desc;
+ int len, frag_count, no_of_desc;
u32 num_txd = tx_ring->num_desc;
- bool is_tso = false;
frag_count = skb_shinfo(skb)->nr_frags + 1;
producer = tx_ring->producer;
- hwdesc = &tx_ring->desc_head[producer];
- netxen_clear_cmddesc((u64 *)hwdesc);
- pbuf = &tx_ring->cmd_buf_arr[producer];
+ pdev = adapter->pdev;
+ len = skb->len - skb->data_len;
- is_tso = netxen_tso_check(netdev, hwdesc, skb);
+ temp_dma = pci_map_single(pdev, skb->data, len, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(pdev, temp_dma))
+ goto drop_packet;
+ pbuf = &tx_ring->cmd_buf_arr[producer];
pbuf->skb = skb;
pbuf->frag_count = frag_count;
- buffrag = &pbuf->frag_array[0];
- temp_dma = pci_map_single(pdev, skb->data, first_seg_len,
- PCI_DMA_TODEVICE);
- if (pci_dma_mapping_error(pdev, temp_dma))
- goto drop_packet;
+ buffrag = &pbuf->frag_array[0];
buffrag->dma = temp_dma;
- buffrag->length = first_seg_len;
+ buffrag->length = len;
+
+ first_desc = hwdesc = &tx_ring->desc_head[producer];
+ netxen_clear_cmddesc((u64 *)hwdesc);
netxen_set_tx_frags_len(hwdesc, frag_count, skb->len);
netxen_set_tx_port(hwdesc, adapter->portnum);
- hwdesc->buffer_length[0] = cpu_to_le16(first_seg_len);
- hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
+ hwdesc->buffer_length[0] = cpu_to_le16(len);
+ hwdesc->addr_buffer1 = cpu_to_le64(temp_dma);
for (i = 1, k = 1; i < frag_count; i++, k++) {
- struct skb_frag_struct *frag;
- int len, temp_len;
- unsigned long offset;
/* move to next desc. if there is a need */
if ((i & 0x3) == 0) {
pbuf = &tx_ring->cmd_buf_arr[producer];
pbuf->skb = NULL;
}
+ buffrag = &pbuf->frag_array[i];
frag = &skb_shinfo(skb)->frags[i - 1];
len = frag->size;
offset = frag->page_offset;
- temp_len = len;
temp_dma = pci_map_page(pdev, frag->page, offset,
len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(pdev, temp_dma)) {
goto drop_packet;
}
- buffrag++;
buffrag->dma = temp_dma;
- buffrag->length = temp_len;
+ buffrag->length = len;
- hwdesc->buffer_length[k] = cpu_to_le16(temp_len);
+ hwdesc->buffer_length[k] = cpu_to_le16(len);
switch (k) {
case 0:
hwdesc->addr_buffer1 = cpu_to_le64(temp_dma);
hwdesc->addr_buffer4 = cpu_to_le64(temp_dma);
break;
}
- frag++;
- }
- producer = get_next_index(producer, num_txd);
-
- /* For LSO, we need to copy the MAC/IP/TCP headers into
- * the descriptor ring
- */
- if (is_tso) {
- int hdr_len, first_hdr_len, more_hdr;
- hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
- if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) {
- first_hdr_len = sizeof(struct cmd_desc_type0) - 2;
- more_hdr = 1;
- } else {
- first_hdr_len = hdr_len;
- more_hdr = 0;
- }
- /* copy the MAC/IP/TCP headers to the cmd descriptor list */
- hwdesc = &tx_ring->desc_head[producer];
- pbuf = &tx_ring->cmd_buf_arr[producer];
- pbuf->skb = NULL;
-
- /* copy the first 64 bytes */
- memcpy(((void *)hwdesc) + 2,
- (void *)(skb->data), first_hdr_len);
- producer = get_next_index(producer, num_txd);
-
- if (more_hdr) {
- hwdesc = &tx_ring->desc_head[producer];
- pbuf = &tx_ring->cmd_buf_arr[producer];
- pbuf->skb = NULL;
- /* copy the next 64 bytes - should be enough except
- * for pathological case
- */
- skb_copy_from_linear_data_offset(skb, first_hdr_len,
- hwdesc,
- (hdr_len -
- first_hdr_len));
- producer = get_next_index(producer, num_txd);
- }
}
+ tx_ring->producer = get_next_index(producer, num_txd);
- tx_ring->producer = producer;
- adapter->stats.txbytes += skb->len;
+ netxen_tso_check(netdev, tx_ring, first_desc, skb);
netxen_nic_update_cmd_producer(adapter, tx_ring);
+ adapter->stats.txbytes += skb->len;
adapter->stats.xmitcalled++;
return NETDEV_TX_OK;
{
struct netxen_adapter *adapter = (struct netxen_adapter *)
netdev_priv(netdev);
+
+ dev_err(&netdev->dev, "transmit timeout, resetting.\n");
+
SCHEDULE_WORK(&adapter->tx_timeout_task);
}
-static void netxen_tx_timeout_task(struct work_struct *work)
+static void netxen_reset_task(struct work_struct *work)
{
struct netxen_adapter *adapter =
container_of(work, struct netxen_adapter, tx_timeout_task);
if (!netif_running(adapter->netdev))
return;
- printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
- netxen_nic_driver_name, adapter->netdev->name);
-
netxen_napi_disable(adapter);
adapter->netdev->trans_start = jiffies;
}
/* clear interrupt */
- if (adapter->fw_major < 4)
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
netxen_nic_disable_int(sds_ring);
adapter->pci_write_immediate(adapter,
}
#endif
+#ifdef CONFIG_INET
+
+#define is_netxen_netdev(dev) (dev->netdev_ops == &netxen_netdev_ops)
+
+static int
+netxen_destip_supported(struct netxen_adapter *adapter)
+{
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ return 0;
+
+ if (adapter->ahw.cut_through)
+ return 0;
+
+ return 1;
+}
+
+static int netxen_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct netxen_adapter *adapter;
+ struct net_device *dev = (struct net_device *)ptr;
+ struct in_device *indev;
+
+recheck:
+ if (dev == NULL)
+ goto done;
+
+ if (dev->priv_flags & IFF_802_1Q_VLAN) {
+ dev = vlan_dev_real_dev(dev);
+ goto recheck;
+ }
+
+ if (!is_netxen_netdev(dev))
+ goto done;
+
+ adapter = netdev_priv(dev);
+
+ if (!adapter || !netxen_destip_supported(adapter))
+ goto done;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ goto done;
+
+ indev = in_dev_get(dev);
+ if (!indev)
+ goto done;
+
+ for_ifa(indev) {
+ switch (event) {
+ case NETDEV_UP:
+ netxen_config_ipaddr(adapter,
+ ifa->ifa_address, NX_IP_UP);
+ break;
+ case NETDEV_DOWN:
+ netxen_config_ipaddr(adapter,
+ ifa->ifa_address, NX_IP_DOWN);
+ break;
+ default:
+ break;
+ }
+ } endfor_ifa(indev);
+
+ in_dev_put(indev);
+done:
+ return NOTIFY_DONE;
+}
+
+static int
+netxen_inetaddr_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct netxen_adapter *adapter;
+ struct net_device *dev;
+
+ struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+
+ dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
+
+recheck:
+ if (dev == NULL || !netif_running(dev))
+ goto done;
+
+ if (dev->priv_flags & IFF_802_1Q_VLAN) {
+ dev = vlan_dev_real_dev(dev);
+ goto recheck;
+ }
+
+ if (!is_netxen_netdev(dev))
+ goto done;
+
+ adapter = netdev_priv(dev);
+
+ if (!adapter || !netxen_destip_supported(adapter))
+ goto done;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ goto done;
+
+ switch (event) {
+ case NETDEV_UP:
+ netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP);
+ break;
+ case NETDEV_DOWN:
+ netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN);
+ break;
+ default:
+ break;
+ }
+
+done:
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block netxen_netdev_cb = {
+ .notifier_call = netxen_netdev_event,
+};
+
+static struct notifier_block netxen_inetaddr_cb = {
+ .notifier_call = netxen_inetaddr_event,
+};
+#endif
+
static struct pci_driver netxen_driver = {
.name = netxen_nic_driver_name,
.id_table = netxen_pci_tbl,
#endif
};
-/* Driver Registration on NetXen card */
-
static int __init netxen_init_module(void)
{
printk(KERN_INFO "%s\n", netxen_nic_driver_string);
if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL)
return -ENOMEM;
+#ifdef CONFIG_INET
+ register_netdevice_notifier(&netxen_netdev_cb);
+ register_inetaddr_notifier(&netxen_inetaddr_cb);
+#endif
+
return pci_register_driver(&netxen_driver);
}
static void __exit netxen_exit_module(void)
{
pci_unregister_driver(&netxen_driver);
+
+#ifdef CONFIG_INET
+ unregister_inetaddr_notifier(&netxen_inetaddr_cb);
+ unregister_netdevice_notifier(&netxen_netdev_cb);
+#endif
destroy_workqueue(netxen_workq);
}
static char version[] __devinitdata =
KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n"
- KERN_INFO " Support available from http://foo.com/bar/baz.html\n";
+ " Support available from http://foo.com/bar/baz.html\n";
/* define to 1 to enable PIO instead of MMIO */
#undef USE_IO_OPS
DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n",
dev->name, skb->data, skb->len, entry);
- return 0;
+ return NETDEV_TX_OK;
}
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
} /* mace_start_xmit */
/* ----------------------------------------------------------------------------
ladrf[byte] |= (1 << (hashcode & 7));
#ifdef PCMCIA_DEBUG
- if (pc_debug > 2) {
- printk(KERN_DEBUG " adr =");
- for (i = 0; i < 6; i++)
- printk(" %02X", adr[i]);
- printk("\n" KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63]"
- " =", hashcode);
- for (i = 0; i < 8; i++)
- printk(" %02X", ladrf[i]);
- printk("\n");
+ if (pc_debug > 2)
+ printk(KERN_DEBUG " adr =%pM\n", adr);
+ printk(KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63] =", hashcode);
+ for (i = 0; i < 8; i++)
+ printk(KERN_CONT " %02X", ladrf[i]);
+ printk(KERN_CONT "\n");
}
#endif
} /* BuildLAF */
&new_ring_dma_addr);
if (new_tx_ring == NULL) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR
+ printk(KERN_ERR
"%s: Consistent memory allocation failed.\n",
dev->name);
return;
GFP_ATOMIC);
if (!new_dma_addr_list) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR
+ printk(KERN_ERR
"%s: Memory allocation failed.\n", dev->name);
goto free_new_tx_ring;
}
GFP_ATOMIC);
if (!new_skb_list) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR
+ printk(KERN_ERR
"%s: Memory allocation failed.\n", dev->name);
goto free_new_lists;
}
&new_ring_dma_addr);
if (new_rx_ring == NULL) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR
+ printk(KERN_ERR
"%s: Consistent memory allocation failed.\n",
dev->name);
return;
GFP_ATOMIC);
if (!new_dma_addr_list) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR
+ printk(KERN_ERR
"%s: Memory allocation failed.\n", dev->name);
goto free_new_rx_ring;
}
GFP_ATOMIC);
if (!new_skb_list) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR
+ printk(KERN_ERR
"%s: Memory allocation failed.\n", dev->name);
goto free_new_lists;
}
if (pcnet32_dwio_read_csr(ioaddr, 0) == 4
&& pcnet32_dwio_check(ioaddr)) {
a = &pcnet32_dwio;
- } else
+ } else {
+ if (pcnet32_debug & NETIF_MSG_PROBE)
+ printk(KERN_ERR PFX "No access methods\n");
goto err_release_region;
+ }
}
chip_version =
ret = -ENOMEM;
goto err_release_region;
}
- SET_NETDEV_DEV(dev, &pdev->dev);
+
+ if (pdev)
+ SET_NETDEV_DEV(dev, &pdev->dev);
if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr);
/* Version 0x2623 and 0x2624 */
if (((chip_version + 1) & 0xfffe) == 0x2624) {
i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */
- printk("\n" KERN_INFO " tx_start_pt(0x%04x):", i);
+ printk(KERN_INFO " tx_start_pt(0x%04x):", i);
switch (i >> 10) {
case 0:
- printk(" 20 bytes,");
+ printk(KERN_CONT " 20 bytes,");
break;
case 1:
- printk(" 64 bytes,");
+ printk(KERN_CONT " 64 bytes,");
break;
case 2:
- printk(" 128 bytes,");
+ printk(KERN_CONT " 128 bytes,");
break;
case 3:
- printk("~220 bytes,");
+ printk(KERN_CONT "~220 bytes,");
break;
}
i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */
- printk(" BCR18(%x):", i & 0xffff);
+ printk(KERN_CONT " BCR18(%x):", i & 0xffff);
if (i & (1 << 5))
- printk("BurstWrEn ");
+ printk(KERN_CONT "BurstWrEn ");
if (i & (1 << 6))
- printk("BurstRdEn ");
+ printk(KERN_CONT "BurstRdEn ");
if (i & (1 << 7))
- printk("DWordIO ");
+ printk(KERN_CONT "DWordIO ");
if (i & (1 << 11))
- printk("NoUFlow ");
+ printk(KERN_CONT "NoUFlow ");
i = a->read_bcr(ioaddr, 25);
- printk("\n" KERN_INFO " SRAMSIZE=0x%04x,", i << 8);
+ printk(KERN_INFO " SRAMSIZE=0x%04x,", i << 8);
i = a->read_bcr(ioaddr, 26);
- printk(" SRAM_BND=0x%04x,", i << 8);
+ printk(KERN_CONT " SRAM_BND=0x%04x,", i << 8);
i = a->read_bcr(ioaddr, 27);
if (i & (1 << 14))
- printk("LowLatRx");
+ printk(KERN_CONT "LowLatRx");
}
}
spin_lock_init(&lp->lock);
- SET_NETDEV_DEV(dev, &pdev->dev);
lp->name = chipname;
lp->shared_irq = shared;
lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */
lp->chip_version = chip_version;
lp->msg_enable = pcnet32_debug;
if ((cards_found >= MAX_UNITS)
- || (options[cards_found] > sizeof(options_mapping)))
+ || (options[cards_found] >= sizeof(options_mapping)))
lp->options = PCNET32_PORT_ASEL;
else
lp->options = options_mapping[options[cards_found]];
((cards_found >= MAX_UNITS) || full_duplex[cards_found]))
lp->options |= PCNET32_PORT_FD;
- if (!a) {
- if (pcnet32_debug & NETIF_MSG_PROBE)
- printk(KERN_ERR PFX "No access methods\n");
- ret = -ENODEV;
- goto err_free_consistent;
- }
lp->a = *a;
/* prior to register_netdev, dev->name is not yet correct */
return 0;
- err_free_ring:
+ err_free_ring:
pcnet32_free_ring(dev);
- err_free_consistent:
pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block),
lp->init_block, lp->init_dma_addr);
- err_free_netdev:
+ err_free_netdev:
free_netdev(dev);
- err_release_region:
+ err_release_region:
release_region(ioaddr, PCNET32_TOTAL_SIZE);
return ret;
}
&lp->tx_ring_dma_addr);
if (lp->tx_ring == NULL) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR PFX
+ printk(KERN_ERR PFX
"%s: Consistent memory allocation failed.\n",
name);
return -ENOMEM;
&lp->rx_ring_dma_addr);
if (lp->rx_ring == NULL) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR PFX
+ printk(KERN_ERR PFX
"%s: Consistent memory allocation failed.\n",
name);
return -ENOMEM;
GFP_ATOMIC);
if (!lp->tx_dma_addr) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR PFX
+ printk(KERN_ERR PFX
"%s: Memory allocation failed.\n", name);
return -ENOMEM;
}
GFP_ATOMIC);
if (!lp->rx_dma_addr) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR PFX
+ printk(KERN_ERR PFX
"%s: Memory allocation failed.\n", name);
return -ENOMEM;
}
GFP_ATOMIC);
if (!lp->tx_skbuff) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR PFX
+ printk(KERN_ERR PFX
"%s: Memory allocation failed.\n", name);
return -ENOMEM;
}
GFP_ATOMIC);
if (!lp->rx_skbuff) {
if (netif_msg_drv(lp))
- printk("\n" KERN_ERR PFX
+ printk(KERN_ERR PFX
"%s: Memory allocation failed.\n", name);
return -ENOMEM;
}
static int pcnet32_open(struct net_device *dev)
{
struct pcnet32_private *lp = netdev_priv(dev);
+ struct pci_dev *pdev = lp->pci_dev;
unsigned long ioaddr = dev->base_addr;
u16 val;
int i;
lp->a.write_csr(ioaddr, 124, val);
/* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */
- if (lp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_AT &&
- (lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
- lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) {
+ if (pdev && pdev->subsystem_vendor == PCI_VENDOR_ID_AT &&
+ (pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
+ pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) {
if (lp->options & PCNET32_PORT_ASEL) {
lp->options = PCNET32_PORT_FD | PCNET32_PORT_100;
if (netif_msg_link(lp))
netif_stop_queue(dev);
}
spin_unlock_irqrestore(&lp->lock, flags);
- return 0;
+ return NETDEV_TX_OK;
}
/* The PCNET32 interrupt handler. */
netif_stop_queue(dev);
skb_queue_tail(&ppp->file.xq, skb);
ppp_xmit_process(ppp);
- return 0;
+ return NETDEV_TX_OK;
outf:
kfree_skb(skb);
++dev->stats.tx_dropped;
- return 0;
+ return NETDEV_TX_OK;
}
static int
/* create a fragment for each channel */
bits = B;
- while (nfree > 0 && len > 0) {
+ while (len > 0) {
list = list->next;
if (list == &ppp->channels) {
i = 0;
*otherwise divide it according to the speed
*of the channel we are going to transmit on
*/
- if (pch->speed == 0) {
- flen = totlen/nfree ;
- if (nbigger > 0) {
- flen++;
- nbigger--;
- }
- } else {
- flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) /
- ((totspeed*totfree)/pch->speed)) - hdrlen;
- if (nbigger > 0) {
- flen += ((totfree - nzero)*pch->speed)/totspeed;
- nbigger -= ((totfree - nzero)*pch->speed)/
+ if (nfree > 0) {
+ if (pch->speed == 0) {
+ flen = totlen/nfree ;
+ if (nbigger > 0) {
+ flen++;
+ nbigger--;
+ }
+ } else {
+ flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) /
+ ((totspeed*totfree)/pch->speed)) - hdrlen;
+ if (nbigger > 0) {
+ flen += ((totfree - nzero)*pch->speed)/totspeed;
+ nbigger -= ((totfree - nzero)*pch->speed)/
totspeed;
+ }
}
+ nfree--;
}
- nfree--;
/*
*check if we are on the last channel or
*we exceded the lenght of the data to
*fragment
*/
- if ((nfree == 0) || (flen > len))
+ if ((nfree <= 0) || (flen > len))
flen = len;
/*
*it is not worth to tx on slow channels:
continue;
}
- mtu = pch->chan->mtu + 2 - hdrlen;
+ mtu = pch->chan->mtu - hdrlen;
if (mtu < 4)
mtu = 4;
if (flen > mtu)
sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL);
#endif
+ sky2->restarting = 0;
+
err = sky2_rx_start(sky2);
if (err)
goto err_out;
sky2_set_multicast(dev);
+ /* wake queue incase we are restarting */
+ netif_wake_queue(dev);
+
if (netif_msg_ifup(sky2))
printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
return 0;
/* Number of list elements available for next tx */
static inline int tx_avail(const struct sky2_port *sky2)
{
+ if (unlikely(sky2->restarting))
+ return 0;
return sky2->tx_pending - tx_dist(sky2->tx_cons, sky2->tx_prod);
}
if (netif_msg_ifdown(sky2))
printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
+ /* explicitly shut off tx incase we're restarting */
+ sky2->restarting = 1;
+ netif_tx_disable(dev);
+
/* Force flow control off */
sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
{
struct sky2_port *sky2 = netdev_priv(dev);
- if (netif_running(dev)) {
+ if (likely(netif_running(dev) && !sky2->restarting)) {
netif_tx_lock(dev);
sky2_tx_complete(sky2, last);
netif_tx_unlock(dev);
seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n",
sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)),
- last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));
sky2_read32(hw, B0_Y2_SP_LISR);
spin_lock_init(&sky2->phy_lock);
sky2->tx_pending = TX_DEF_PENDING;
sky2->rx_pending = RX_DEF_PENDING;
+ sky2->restarting = 0;
hw->dev[port] = dev;
/* These identify the driver base version and may not be removed. */
static const char version[] __devinitconst =
KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <
[email protected]>\n"
- KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
+ " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
"%s: Transmit frame #%d queued in slot %d.\n",
dev->name, np->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
/* Reset hardware tx and free all of tx buffers */
#ifdef __i386__
if (netif_msg_hw(np)) {
- printk("\n"KERN_DEBUG" Tx ring at %8.8x:\n",
+ printk(KERN_DEBUG " Tx ring at %8.8x:\n",
(int)(np->tx_ring_dma));
for (i = 0; i < TX_RING_SIZE; i++)
- printk(" #%d desc. %4.4x %8.8x %8.8x.\n",
+ printk(KERN_DEBUG " #%d desc. %4.4x %8.8x %8.8x.\n",
i, np->tx_ring[i].status, np->tx_ring[i].frag[0].addr,
np->tx_ring[i].frag[0].length);
- printk("\n"KERN_DEBUG " Rx ring %8.8x:\n",
+ printk(KERN_DEBUG " Rx ring %8.8x:\n",
(int)(np->rx_ring_dma));
for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) {
printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n",
dw32(TxPoll, NormalTxPoll);
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
/* Set or clear the multicast filter for this adaptor.
macmode &= ~FullDuplex;
if (netif_msg_link(de)) {
- printk(KERN_INFO "%s: set link %s\n"
- KERN_INFO "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
- KERN_INFO "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",
+ printk(KERN_INFO
+ "%s: set link %s\n"
+ "%s: mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
+ "%s: set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",
de->dev->name, media_name[media],
de->dev->name, dr32(MacMode), dr32(SIAStatus),
dr32(CSR13), dr32(CSR14), dr32(CSR15),
(unsigned int)tp->rx_ring[i].buffer2,
buf[0], buf[1], buf[2]);
for (j = 0; buf[j] != 0xee && j < 1600; j++)
- if (j < 100) printk(" %2.2x", buf[j]);
- printk(" j=%d.\n", j);
+ if (j < 100)
+ printk(KERN_CONT " %2.2x", buf[j]);
+ printk(KERN_CONT " j=%d.\n", j);
}
printk(KERN_DEBUG " Rx ring %8.8x: ", (int)tp->rx_ring);
for (i = 0; i < RX_RING_SIZE; i++)
- printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
- printk("\n" KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring);
+ printk(KERN_CONT " %8.8x",
+ (unsigned int)tp->rx_ring[i].status);
+ printk(KERN_DEBUG " Tx ring %8.8x: ", (int)tp->tx_ring);
for (i = 0; i < TX_RING_SIZE; i++)
- printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
- printk("\n");
+ printk(KERN_CONT " %8.8x", (unsigned int)tp->tx_ring[i].status);
+ printk(KERN_CONT "\n");
}
#endif
dev->trans_start = jiffies;
- return 0;
+ return NETDEV_TX_OK;
}
static void tulip_clean_tx_ring(struct tulip_private *tp)
static const char version[] __initconst =
KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) "
- KERN_INFO " http://www.scyld.com/network/drivers.html\n";
+ " http://www.scyld.com/network/drivers.html\n";
MODULE_DESCRIPTION("Winbond W89c840 Ethernet driver");
printk(KERN_DEBUG " Rx ring %p: ", np->rx_ring);
for (i = 0; i < RX_RING_SIZE; i++)
printk(" %8.8x", (unsigned int)np->rx_ring[i].status);
- printk("\n"KERN_DEBUG" Tx ring %p: ", np->tx_ring);
+ printk(KERN_DEBUG" Tx ring %p: ", np->tx_ring);
for (i = 0; i < TX_RING_SIZE; i++)
printk(" %8.8x", np->tx_ring[i].status);
printk("\n");
printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
dev->name, np->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
static void netdev_tx_done(struct net_device *dev)
printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x.\n",
i, np->tx_ring[i].length,
np->tx_ring[i].status, np->tx_ring[i].buffer1);
- printk("\n"KERN_DEBUG " Rx ring %8.8x:\n",
+ printk(KERN_DEBUG " Rx ring %8.8x:\n",
(int)np->rx_ring);
for (i = 0; i < RX_RING_SIZE; i++) {
printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n",
if (tun->flags & TUN_FASYNC)
kill_fasync(&tun->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&tun->socket.wait);
- return 0;
+ return NETDEV_TX_OK;
drop:
dev->stats.tx_dropped++;
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static void tun_net_mclist(struct net_device *dev)
case VIRTIO_NET_HDR_GSO_TCPV6:
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
break;
+ case VIRTIO_NET_HDR_GSO_UDP:
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+ break;
default:
tun->dev->stats.rx_frame_errors++;
kfree_skb(skb);
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
else if (sinfo->gso_type & SKB_GSO_TCPV6)
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+ else if (sinfo->gso_type & SKB_GSO_UDP)
+ gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
else
BUG();
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
goto err_free_sk;
}
- err = -EINVAL;
err = register_netdevice(tun->dev);
if (err < 0)
goto err_free_sk;
return err;
}
- static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
+ static int tun_get_iff(struct net *net, struct tun_struct *tun,
+ struct ifreq *ifr)
{
- struct tun_struct *tun = tun_get(file);
-
- if (!tun)
- return -EBADFD;
-
DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
strcpy(ifr->ifr_name, tun->dev->name);
ifr->ifr_flags = tun_flags(tun);
- tun_put(tun);
return 0;
}
old_features = dev->features;
/* Unset features, set them as we chew on the arg. */
features = (old_features & ~(NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST
- |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6));
+ |NETIF_F_TSO_ECN|NETIF_F_TSO|NETIF_F_TSO6
+ |NETIF_F_UFO));
if (arg & TUN_F_CSUM) {
features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
features |= NETIF_F_TSO6;
arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
}
+
+ if (arg & TUN_F_UFO) {
+ features |= NETIF_F_UFO;
+ arg &= ~TUN_F_UFO;
+ }
}
/* This gives the user a way to test for new features in future by
return 0;
}
- static int tun_chr_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ static long tun_chr_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
struct tun_file *tfile = file->private_data;
struct tun_struct *tun;
(unsigned int __user*)argp);
}
+ rtnl_lock();
+
tun = __tun_get(tfile);
if (cmd == TUNSETIFF && !tun) {
- int err;
-
ifr.ifr_name[IFNAMSIZ-1] = '\0';
- rtnl_lock();
- err = tun_set_iff(tfile->net, file, &ifr);
- rtnl_unlock();
+ ret = tun_set_iff(tfile->net, file, &ifr);
- if (err)
- return err;
+ if (ret)
+ goto unlock;
if (copy_to_user(argp, &ifr, sizeof(ifr)))
- return -EFAULT;
- return 0;
+ ret = -EFAULT;
+ goto unlock;
}
-
+ ret = -EBADFD;
if (!tun)
- return -EBADFD;
+ goto unlock;
DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
ret = 0;
switch (cmd) {
case TUNGETIFF:
- ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr);
+ ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
if (ret)
break;
case TUNSETLINK:
/* Only allow setting the type when the interface is down */
- rtnl_lock();
if (tun->dev->flags & IFF_UP) {
DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
tun->dev->name);
DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
ret = 0;
}
- rtnl_unlock();
break;
#ifdef TUN_DEBUG
break;
#endif
case TUNSETOFFLOAD:
- rtnl_lock();
ret = set_offload(tun->dev, arg);
- rtnl_unlock();
break;
case TUNSETTXFILTER:
ret = -EINVAL;
if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
break;
- rtnl_lock();
ret = update_filter(&tun->txflt, (void __user *)arg);
- rtnl_unlock();
break;
case SIOCGIFHWADDR:
DBG(KERN_DEBUG "%s: set hw address: %pM\n",
tun->dev->name, ifr.ifr_hwaddr.sa_data);
- rtnl_lock();
ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
- rtnl_unlock();
break;
case TUNGETSNDBUF:
break;
};
- tun_put(tun);
+ unlock:
+ rtnl_unlock();
+ if (tun)
+ tun_put(tun);
return ret;
}
.write = do_sync_write,
.aio_write = tun_chr_aio_write,
.poll = tun_chr_poll,
- .ioctl = tun_chr_ioctl,
+ .unlocked_ioctl = tun_chr_ioctl,
.open = tun_chr_open,
.release = tun_chr_close,
.fasync = tun_chr_fasync
}
if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs)
- printk( KERN_WARNING " WARNING: The PCI BIOS assigned "
- "this PCI card to IRQ %d, which is unlikely "
- "to work!.\n"
- KERN_WARNING " You should use the PCI BIOS "
- "setup to assign a valid IRQ line.\n",
+ printk( KERN_WARNING
+ " WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
+ " You should use the PCI BIOS setup to assign a valid IRQ line.\n",
pci_irq_line );
/* avoiding re-enable dual adapters */
prepare_to_send( skb, p );
spin_unlock( &nl->lock );
netif_start_queue( dev );
- return 0;
+ return NETDEV_TX_OK;
}
}
prepare_to_send( skb, dev );
spin_unlock( &nl->lock );
- return 0;
+ return NETDEV_TX_OK;
}
#endif /* CONFIG_SBNI_MULTILINE */
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+static int modparam_ht;
+module_param_named(ht, modparam_ht, bool, S_IRUGO);
+MODULE_PARM_DESC(ht, "enable MPDU aggregation.");
+
#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \
.bitrate = (_bitrate), \
.flags = (_flags), \
.cap = IEEE80211_HT_CAP_MAX_AMSDU | \
IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
IEEE80211_HT_CAP_SGI_40 | \
+ IEEE80211_HT_CAP_GRN_FLD | \
IEEE80211_HT_CAP_DSSSCCK40 | \
IEEE80211_HT_CAP_SM_PS, \
.ampdu_factor = 3, \
.ampdu_density = 6, \
.mcs = { \
- .rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, }, \
+ .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \
+ .rx_highest = cpu_to_le16(300), \
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
}, \
}
};
static void ar9170_tx(struct ar9170 *ar);
+static bool ar9170_tx_ampdu(struct ar9170 *ar);
-#ifdef AR9170_QUEUE_DEBUG
+static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr)
+{
+ return le16_to_cpu(hdr->seq_ctrl) >> 4;
+}
+
+static inline u16 ar9170_get_seq(struct sk_buff *skb)
+{
+ struct ar9170_tx_control *txc = (void *) skb->data;
+ return ar9170_get_seq_h((void *) txc->frame_data);
+}
+
+static inline u16 ar9170_get_tid(struct sk_buff *skb)
+{
+ struct ar9170_tx_control *txc = (void *) skb->data;
+ struct ieee80211_hdr *hdr = (void *) txc->frame_data;
+
+ return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
+}
+
+#define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff)
+#define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb)))
+
+#if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG)
static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
{
struct ar9170_tx_control *txc = (void *) skb->data;
struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
struct ieee80211_hdr *hdr = (void *) txc->frame_data;
- printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x "
+ printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d "
"mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
- ieee80211_get_DA(hdr), arinfo->flags,
+ ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr),
le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
jiffies_to_msecs(arinfo->timeout - jiffies));
}
"mismatch %d != %d\n", skb_queue_len(queue), i);
printk(KERN_DEBUG "---[ end ]---\n");
}
+#endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */
+#ifdef AR9170_QUEUE_DEBUG
static void ar9170_dump_txqueue(struct ar9170 *ar,
struct sk_buff_head *queue)
{
__ar9170_dump_txqueue(ar, queue);
spin_unlock_irqrestore(&queue->lock, flags);
}
+#endif /* AR9170_QUEUE_DEBUG */
+#ifdef AR9170_QUEUE_STOP_DEBUG
static void __ar9170_dump_txstats(struct ar9170 *ar)
{
int i;
wiphy_name(ar->hw->wiphy));
for (i = 0; i < __AR9170_NUM_TXQ; i++)
- printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d\n",
- wiphy_name(ar->hw->wiphy), i, ar->tx_stats[i].limit,
- ar->tx_stats[i].len, skb_queue_len(&ar->tx_status[i]));
+ printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d "
+ " stopped:%d\n", wiphy_name(ar->hw->wiphy), i,
+ ar->tx_stats[i].limit, ar->tx_stats[i].len,
+ skb_queue_len(&ar->tx_status[i]),
+ ieee80211_queue_stopped(ar->hw, i));
}
+#endif /* AR9170_QUEUE_STOP_DEBUG */
-static void ar9170_dump_txstats(struct ar9170 *ar)
+#ifdef AR9170_TXAGG_DEBUG
+static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar)
{
unsigned long flags;
- spin_lock_irqsave(&ar->tx_stats_lock, flags);
- __ar9170_dump_txstats(ar);
- spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
+ spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags);
+ printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n",
+ wiphy_name(ar->hw->wiphy));
+ __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu);
+ spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags);
}
-#endif /* AR9170_QUEUE_DEBUG */
+
+#endif /* AR9170_TXAGG_DEBUG */
/* caller must guarantee exclusive access for _bin_ queue. */
static void ar9170_recycle_expired(struct ar9170 *ar,
ieee80211_tx_status_irqsafe(ar->hw, skb);
}
+static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar)
+{
+ struct sk_buff_head success;
+ struct sk_buff *skb;
+ unsigned int i;
+ unsigned long queue_bitmap = 0;
+
+ skb_queue_head_init(&success);
+
+ while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS)
+ __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu));
+
+ ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success);
+
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n",
+ wiphy_name(ar->hw->wiphy), skb_queue_len(&success));
+ __ar9170_dump_txqueue(ar, &success);
+#endif /* AR9170_TXAGG_DEBUG */
+
+ while ((skb = __skb_dequeue(&success))) {
+ struct ieee80211_tx_info *txinfo;
+
+ queue_bitmap |= BIT(skb_get_queue_mapping(skb));
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ ieee80211_tx_info_clear_status(txinfo);
+
+ txinfo->flags |= IEEE80211_TX_STAT_ACK;
+ txinfo->status.rates[0].count = 1;
+
+ skb_pull(skb, sizeof(struct ar9170_tx_control));
+ ieee80211_tx_status_irqsafe(ar->hw, skb);
+ }
+
+ for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) {
+#ifdef AR9170_QUEUE_STOP_DEBUG
+ printk(KERN_DEBUG "%s: wake queue %d\n",
+ wiphy_name(ar->hw->wiphy), i);
+ __ar9170_dump_txstats(ar);
+#endif /* AR9170_QUEUE_STOP_DEBUG */
+ ieee80211_wake_queue(ar->hw, i);
+ }
+
+ if (queue_bitmap)
+ ar9170_tx(ar);
+}
+
+static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+ struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
+
+ arinfo->timeout = jiffies +
+ msecs_to_jiffies(AR9170_BA_TIMEOUT);
+
+ skb_queue_tail(&ar->tx_status_ampdu, skb);
+ ar9170_tx_fake_ampdu_status(ar);
+ ar->tx_ampdu_pending--;
+
+ if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending)
+ ar9170_tx_ampdu(ar);
+}
+
void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) {
- dev_kfree_skb_any(skb);
+ ar9170_tx_ampdu_callback(ar, skb);
} else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) {
arinfo->timeout = jiffies +
msecs_to_jiffies(AR9170_TX_TIMEOUT);
return NULL;
}
+static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r)
+{
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *txinfo;
+
+ while (count) {
+ skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r);
+ if (!skb)
+ break;
+
+ txinfo = IEEE80211_SKB_CB(skb);
+ ieee80211_tx_info_clear_status(txinfo);
+
+ /* FIXME: maybe more ? */
+ txinfo->status.rates[0].count = 1;
+
+ skb_pull(skb, sizeof(struct ar9170_tx_control));
+ ieee80211_tx_status_irqsafe(ar->hw, skb);
+ count--;
+ }
+
+#ifdef AR9170_TXAGG_DEBUG
+ if (count) {
+ printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more "
+ "suitable frames left in tx_status queue.\n",
+ wiphy_name(ar->hw->wiphy), count);
+
+ ar9170_dump_tx_status_ampdu(ar);
+ }
+#endif /* AR9170_TXAGG_DEBUG */
+}
+
/*
* This worker tries to keeps an maintain tx_status queues.
* So we can guarantee that incoming tx_status reports are
resched = true;
}
- if (resched)
- queue_delayed_work(ar->hw->workqueue,
- &ar->tx_janitor,
- msecs_to_jiffies(AR9170_JANITOR_DELAY));
+ ar9170_tx_fake_ampdu_status(ar);
+
+ if (!resched)
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw,
+ &ar->tx_janitor,
+ msecs_to_jiffies(AR9170_JANITOR_DELAY));
}
void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
* pre-TBTT event
*/
if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
- queue_work(ar->hw->workqueue, &ar->beacon_work);
+ ieee80211_queue_work(ar->hw, &ar->beacon_work);
break;
case 0xc2:
break;
case 0xc4:
+ /* BlockACK bitmap */
+ break;
+
case 0xc5:
/* BlockACK events */
+ ar9170_handle_block_ack(ar,
+ le16_to_cpu(cmd->ba_fail_cnt.failed),
+ le16_to_cpu(cmd->ba_fail_cnt.rate));
+ ar9170_tx_fake_ampdu_status(ar);
break;
case 0xc6:
ar9170_rx_phy_status(ar, phy, &status);
skb = ar9170_rx_copy_data(buf, mpdu_len);
- if (likely(skb))
- ieee80211_rx_irqsafe(ar->hw, skb, &status);
+ if (likely(skb)) {
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx_irqsafe(ar->hw, skb);
+ }
}
void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */
AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */
+ /* set sane AMPDU defaults */
+ ar->global_ampdu_density = 6;
+ ar->global_ampdu_factor = 3;
+
ar->bad_hw_nagger = jiffies;
err = ar->open(ar);
if (IS_STARTED(ar))
ar->state = AR9170_IDLE;
- flush_workqueue(ar->hw->workqueue);
-
cancel_delayed_work_sync(&ar->tx_janitor);
+#ifdef CONFIG_AR9170_LEDS
+ cancel_delayed_work_sync(&ar->led_work);
+#endif
cancel_work_sync(&ar->filter_config_work);
cancel_work_sync(&ar->beacon_work);
+
mutex_lock(&ar->mutex);
if (IS_ACCEPTING_CMD(ar)) {
skb_queue_purge(&ar->tx_pending[i]);
skb_queue_purge(&ar->tx_status[i]);
}
+ skb_queue_purge(&ar->tx_status_ampdu);
+
mutex_unlock(&ar->mutex);
}
+static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct ar9170_tx_control *txc = (void *) skb->data;
+
+ txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU);
+}
+
+static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst,
+ struct sk_buff *src)
+{
+ struct ar9170_tx_control *dst_txc, *src_txc;
+ struct ieee80211_tx_info *dst_info, *src_info;
+ struct ar9170_tx_info *dst_arinfo, *src_arinfo;
+
+ src_txc = (void *) src->data;
+ src_info = IEEE80211_SKB_CB(src);
+ src_arinfo = (void *) src_info->rate_driver_data;
+
+ dst_txc = (void *) dst->data;
+ dst_info = IEEE80211_SKB_CB(dst);
+ dst_arinfo = (void *) dst_info->rate_driver_data;
+
+ dst_txc->phy_control = src_txc->phy_control;
+
+ /* same MCS for the whole aggregate */
+ memcpy(dst_info->driver_rates, src_info->driver_rates,
+ sizeof(dst_info->driver_rates));
+}
+
static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK;
+
goto out;
}
txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT);
}
+static bool ar9170_tx_ampdu(struct ar9170 *ar)
+{
+ struct sk_buff_head agg;
+ struct ar9170_sta_tid *tid_info = NULL, *tmp;
+ struct sk_buff *skb, *first = NULL;
+ unsigned long flags, f2;
+ unsigned int i = 0;
+ u16 seq, queue, tmpssn;
+ bool run = false;
+
+ skb_queue_head_init(&agg);
+
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ if (list_empty(&ar->tx_ampdu_list)) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: aggregation list is empty.\n",
+ wiphy_name(ar->hw->wiphy));
+#endif /* AR9170_TXAGG_DEBUG */
+ goto out_unlock;
+ }
+
+ list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) {
+ if (tid_info->state != AR9170_TID_STATE_COMPLETE) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: dangling aggregation entry!\n",
+ wiphy_name(ar->hw->wiphy));
+#endif /* AR9170_TXAGG_DEBUG */
+ continue;
+ }
+
+ if (++i > 64) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: enough frames aggregated.\n",
+ wiphy_name(ar->hw->wiphy));
+#endif /* AR9170_TXAGG_DEBUG */
+ break;
+ }
+
+ queue = TID_TO_WME_AC(tid_info->tid);
+
+ if (skb_queue_len(&ar->tx_pending[queue]) >=
+ AR9170_NUM_TX_AGG_MAX) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: queue %d full.\n",
+ wiphy_name(ar->hw->wiphy), queue);
+#endif /* AR9170_TXAGG_DEBUG */
+ continue;
+ }
+
+ list_del_init(&tid_info->list);
+
+ spin_lock_irqsave(&tid_info->queue.lock, f2);
+ tmpssn = seq = tid_info->ssn;
+ first = skb_peek(&tid_info->queue);
+
+ if (likely(first))
+ tmpssn = ar9170_get_seq(first);
+
+ if (unlikely(tmpssn != seq)) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.",
+ wiphy_name(ar->hw->wiphy), seq, tmpssn);
+#endif /* AR9170_TXAGG_DEBUG */
+ tid_info->ssn = tmpssn;
+ }
+
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with "
+ "%d queued frames.\n", wiphy_name(ar->hw->wiphy),
+ tid_info->tid, tid_info->ssn,
+ skb_queue_len(&tid_info->queue));
+ __ar9170_dump_txqueue(ar, &tid_info->queue);
+#endif /* AR9170_TXAGG_DEBUG */
+
+ while ((skb = skb_peek(&tid_info->queue))) {
+ if (unlikely(ar9170_get_seq(skb) != seq))
+ break;
+
+ __skb_unlink(skb, &tid_info->queue);
+ tid_info->ssn = seq = GET_NEXT_SEQ(seq);
+
+ if (unlikely(skb_get_queue_mapping(skb) != queue)) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d "
+ "!match.\n", wiphy_name(ar->hw->wiphy),
+ tid_info->tid,
+ TID_TO_WME_AC(tid_info->tid),
+ skb_get_queue_mapping(skb));
+#endif /* AR9170_TXAGG_DEBUG */
+ dev_kfree_skb_any(skb);
+ continue;
+ }
+
+ if (unlikely(first == skb)) {
+ ar9170_tx_prepare_phy(ar, skb);
+ __skb_queue_tail(&agg, skb);
+ first = skb;
+ } else {
+ ar9170_tx_copy_phy(ar, skb, first);
+ __skb_queue_tail(&agg, skb);
+ }
+
+ if (unlikely(skb_queue_len(&agg) ==
+ AR9170_NUM_TX_AGG_MAX))
+ break;
+ }
+
+ if (skb_queue_empty(&tid_info->queue))
+ tid_info->active = false;
+ else
+ list_add_tail(&tid_info->list,
+ &ar->tx_ampdu_list);
+
+ spin_unlock_irqrestore(&tid_info->queue.lock, f2);
+
+ if (unlikely(skb_queue_empty(&agg))) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: queued empty list!\n",
+ wiphy_name(ar->hw->wiphy));
+#endif /* AR9170_TXAGG_DEBUG */
+ continue;
+ }
+
+ /*
+ * tell the FW/HW that this is the last frame,
+ * that way it will wait for the immediate block ack.
+ */
+ if (likely(skb_peek_tail(&agg)))
+ ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg));
+
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n",
+ wiphy_name(ar->hw->wiphy));
+ __ar9170_dump_txqueue(ar, &agg);
+#endif /* AR9170_TXAGG_DEBUG */
+
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+
+ spin_lock_irqsave(&ar->tx_pending[queue].lock, flags);
+ skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]);
+ spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags);
+ run = true;
+
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ }
+
+out_unlock:
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ __skb_queue_purge(&agg);
+
+ return run;
+}
+
static void ar9170_tx(struct ar9170 *ar)
{
struct sk_buff *skb;
printk(KERN_DEBUG "%s: queue %d full\n",
wiphy_name(ar->hw->wiphy), i);
- __ar9170_dump_txstats(ar);
- printk(KERN_DEBUG "stuck frames: ===> \n");
+ printk(KERN_DEBUG "%s: stuck frames: ===> \n",
+ wiphy_name(ar->hw->wiphy));
ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
ar9170_dump_txqueue(ar, &ar->tx_status[i]);
#endif /* AR9170_QUEUE_DEBUG */
+
+#ifdef AR9170_QUEUE_STOP_DEBUG
+ printk(KERN_DEBUG "%s: stop queue %d\n",
+ wiphy_name(ar->hw->wiphy), i);
+ __ar9170_dump_txstats(ar);
+#endif /* AR9170_QUEUE_STOP_DEBUG */
ieee80211_stop_queue(ar->hw, i);
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
continue;
"remaining slots:%d, needed:%d\n",
wiphy_name(ar->hw->wiphy), i, remaining_space,
frames);
-
- ar9170_dump_txstats(ar);
#endif /* AR9170_QUEUE_DEBUG */
frames = remaining_space;
}
arinfo->timeout = jiffies +
msecs_to_jiffies(AR9170_TX_TIMEOUT);
+ if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
+ ar->tx_ampdu_pending++;
+
#ifdef AR9170_QUEUE_DEBUG
printk(KERN_DEBUG "%s: send frame q:%d =>\n",
wiphy_name(ar->hw->wiphy), i);
err = ar->tx(ar, skb);
if (unlikely(err)) {
+ if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
+ ar->tx_ampdu_pending--;
+
frames_failed++;
dev_kfree_skb_any(skb);
} else {
if (unlikely(frames_failed)) {
#ifdef AR9170_QUEUE_DEBUG
- printk(KERN_DEBUG "%s: frames failed =>\n",
+ printk(KERN_DEBUG "%s: frames failed %d =>\n",
wiphy_name(ar->hw->wiphy), frames_failed);
#endif /* AR9170_QUEUE_DEBUG */
spin_lock_irqsave(&ar->tx_stats_lock, flags);
ar->tx_stats[i].len -= frames_failed;
ar->tx_stats[i].count -= frames_failed;
+#ifdef AR9170_QUEUE_STOP_DEBUG
+ printk(KERN_DEBUG "%s: wake queue %d\n",
+ wiphy_name(ar->hw->wiphy), i);
+ __ar9170_dump_txstats(ar);
+#endif /* AR9170_QUEUE_STOP_DEBUG */
ieee80211_wake_queue(ar->hw, i);
spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
}
}
- if (schedule_garbagecollector)
- queue_delayed_work(ar->hw->workqueue,
- &ar->tx_janitor,
- msecs_to_jiffies(AR9170_JANITOR_DELAY));
+ if (!schedule_garbagecollector)
+ return;
+
+ ieee80211_queue_delayed_work(ar->hw,
+ &ar->tx_janitor,
+ msecs_to_jiffies(AR9170_JANITOR_DELAY));
+}
+
+static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *txinfo;
+ struct ar9170_sta_info *sta_info;
+ struct ar9170_sta_tid *agg;
+ struct sk_buff *iter;
+ unsigned long flags, f2;
+ unsigned int max;
+ u16 tid, seq, qseq;
+ bool run = false, queue = false;
+
+ tid = ar9170_get_tid(skb);
+ seq = ar9170_get_seq(skb);
+ txinfo = IEEE80211_SKB_CB(skb);
+ sta_info = (void *) txinfo->control.sta->drv_priv;
+ agg = &sta_info->agg[tid];
+ max = sta_info->ampdu_max_len;
+
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+
+ if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: BlockACK session not fully initialized "
+ "for ESS:%pM tid:%d state:%d.\n",
+ wiphy_name(ar->hw->wiphy), agg->addr, agg->tid,
+ agg->state);
+#endif /* AR9170_TXAGG_DEBUG */
+ goto err_unlock;
+ }
+
+ if (!agg->active) {
+ agg->active = true;
+ agg->ssn = seq;
+ queue = true;
+ }
+
+ /* check if seq is within the BA window */
+ if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) {
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not "
+ "fit into BA window (%d - %d)\n",
+ wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn,
+ (agg->ssn + max) & 0xfff);
+#endif /* AR9170_TXAGG_DEBUG */
+ goto err_unlock;
+ }
+
+ spin_lock_irqsave(&agg->queue.lock, f2);
+
+ skb_queue_reverse_walk(&agg->queue, iter) {
+ qseq = ar9170_get_seq(iter);
+
+ if (GET_NEXT_SEQ(qseq) == seq) {
+ __skb_queue_after(&agg->queue, iter, skb);
+ goto queued;
+ }
+ }
+
+ __skb_queue_head(&agg->queue, skb);
+
+queued:
+ spin_unlock_irqrestore(&agg->queue.lock, f2);
+
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_DEBUG "%s: new aggregate %p queued.\n",
+ wiphy_name(ar->hw->wiphy), skb);
+ __ar9170_dump_txqueue(ar, &agg->queue);
+#endif /* AR9170_TXAGG_DEBUG */
+
+ if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX)
+ run = true;
+
+ if (queue)
+ list_add_tail(&agg->list, &ar->tx_ampdu_list);
+
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ return run;
+
+err_unlock:
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ dev_kfree_skb_irq(skb);
+ return false;
}
int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
info = IEEE80211_SKB_CB(skb);
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
- /* drop frame, we do not allow TX A-MPDU aggregation yet. */
- goto err_free;
+ bool run = ar9170_tx_ampdu_queue(ar, skb);
+
+ if (run || !ar->tx_ampdu_pending)
+ ar9170_tx_ampdu(ar);
} else {
unsigned int queue = skb_get_queue_mapping(skb);
}
if (likely(IS_STARTED(ar)))
- queue_work(ar->hw->workqueue, &ar->filter_config_work);
+ ieee80211_queue_work(ar->hw, &ar->filter_config_work);
}
static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta)
{
+ struct ar9170 *ar = hw->priv;
+ struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
+ unsigned int i;
+
+ switch (cmd) {
+ case STA_NOTIFY_ADD:
+ memset(sta_info, 0, sizeof(*sta_info));
+
+ if (!sta->ht_cap.ht_supported)
+ break;
+
+ if (sta->ht_cap.ampdu_density > ar->global_ampdu_density)
+ ar->global_ampdu_density = sta->ht_cap.ampdu_density;
+
+ if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor)
+ ar->global_ampdu_factor = sta->ht_cap.ampdu_factor;
+
+ for (i = 0; i < AR9170_NUM_TID; i++) {
+ sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN;
+ sta_info->agg[i].active = false;
+ sta_info->agg[i].ssn = 0;
+ sta_info->agg[i].retry = 0;
+ sta_info->agg[i].tid = i;
+ INIT_LIST_HEAD(&sta_info->agg[i].list);
+ skb_queue_head_init(&sta_info->agg[i].queue);
+ }
+
+ sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
+ break;
+
+ case STA_NOTIFY_REMOVE:
+ if (!sta->ht_cap.ht_supported)
+ break;
+
+ for (i = 0; i < AR9170_NUM_TID; i++) {
+ sta_info->agg[i].state = AR9170_TID_STATE_INVALID;
+ skb_queue_purge(&sta_info->agg[i].queue);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ if (IS_STARTED(ar) && ar->filter_changed)
+ ieee80211_queue_work(ar->hw, &ar->filter_config_work);
}
static int ar9170_get_stats(struct ieee80211_hw *hw,
int ret;
mutex_lock(&ar->mutex);
- if ((param) && !(queue > __AR9170_NUM_TXQ)) {
+ if (queue < __AR9170_NUM_TXQ) {
memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
param, sizeof(*param));
ret = ar9170_set_qos(ar);
- } else
+ } else {
ret = -EINVAL;
+ }
mutex_unlock(&ar->mutex);
return ret;
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
+ struct ar9170 *ar = hw->priv;
+ struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
+ struct ar9170_sta_tid *tid_info = &sta_info->agg[tid];
+ unsigned long flags;
+
+ if (!modparam_ht)
+ return -EOPNOTSUPP;
+
switch (action) {
+ case IEEE80211_AMPDU_TX_START:
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ if (tid_info->state != AR9170_TID_STATE_SHUTDOWN ||
+ !list_empty(&tid_info->list)) {
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] "
+ "is in a very bad state!\n",
+ wiphy_name(hw->wiphy), sta->addr, tid);
+#endif /* AR9170_TXAGG_DEBUG */
+ return -EBUSY;
+ }
+
+ *ssn = tid_info->ssn;
+ tid_info->state = AR9170_TID_STATE_PROGRESS;
+ tid_info->active = false;
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+ break;
+
+ case IEEE80211_AMPDU_TX_STOP:
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ tid_info->state = AR9170_TID_STATE_SHUTDOWN;
+ list_del_init(&tid_info->list);
+ tid_info->active = false;
+ skb_queue_purge(&tid_info->queue);
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+ break;
+
+ case IEEE80211_AMPDU_TX_OPERATIONAL:
+#ifdef AR9170_TXAGG_DEBUG
+ printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n",
+ wiphy_name(hw->wiphy), sta->addr, tid);
+#endif /* AR9170_TXAGG_DEBUG */
+ spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
+ sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE;
+ spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
+ break;
+
case IEEE80211_AMPDU_RX_START:
case IEEE80211_AMPDU_RX_STOP:
- /*
- * Something goes wrong -- RX locks up
- * after a while of receiving aggregated
- * frames -- not enabling for now.
- */
- return -EOPNOTSUPP;
+ /* Handled by firmware */
+ break;
+
default:
return -EOPNOTSUPP;
}
+
+ return 0;
}
static const struct ieee80211_ops ar9170_ops = {
mutex_init(&ar->mutex);
spin_lock_init(&ar->cmdlock);
spin_lock_init(&ar->tx_stats_lock);
+ spin_lock_init(&ar->tx_ampdu_list_lock);
+ skb_queue_head_init(&ar->tx_status_ampdu);
for (i = 0; i < __AR9170_NUM_TXQ; i++) {
skb_queue_head_init(&ar->tx_status[i]);
skb_queue_head_init(&ar->tx_pending[i]);
INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor);
+ INIT_LIST_HEAD(&ar->tx_ampdu_list);
/* all hw supports 2.4 GHz, so set channel to 1 by default */
ar->channel = &ar9170_2ghz_chantable[0];
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
+ if (modparam_ht) {
+ ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
+ } else {
+ ar9170_band_2GHz.ht_cap.ht_supported = false;
+ ar9170_band_5GHz.ht_cap.ht_supported = false;
+ }
+
ar->hw->queues = __AR9170_NUM_TXQ;
ar->hw->extra_tx_headroom = 8;
ar->hw->sta_data_size = sizeof(struct ar9170_sta_info);
{
#define RW 8 /* number of words to read at once */
#define RB (sizeof(u32) * RW)
- DECLARE_MAC_BUF(mbuf);
u8 *eeprom = (void *)&ar->eeprom;
u8 *addr = ar->eeprom.mac_address;
__le32 offsets[RW];
+ unsigned int rx_streams, tx_streams, tx_params = 0;
int i, j, err, bands = 0;
BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz;
bands++;
}
+
+ rx_streams = hweight8(ar->eeprom.rx_mask);
+ tx_streams = hweight8(ar->eeprom.tx_mask);
+
+ if (rx_streams != tx_streams)
+ tx_params = IEEE80211_HT_MCS_TX_RX_DIFF;
+
+ if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS)
+ tx_params = (tx_streams - 1) <<
+ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+
+ ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params;
+ ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params;
+
/*
* I measured this, a bandswitch takes roughly
* 135 ms and a frequency switch about 80.
err = request_firmware(&aru->init_values, "ar9170-1.fw",
&aru->udev->dev);
+ if (err) {
+ dev_err(&aru->udev->dev, "file with init values not found.\n");
+ return err;
+ }
err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev);
if (err) {
release_firmware(aru->init_values);
- dev_err(&aru->udev->dev, "file with init values not found.\n");
+ dev_err(&aru->udev->dev, "firmware file not found.\n");
return err;
}
aru->req_one_stage_fw = ar9170_requires_one_stage(id);
usb_set_intfdata(intf, aru);
- SET_IEEE80211_DEV(ar->hw, &udev->dev);
+ SET_IEEE80211_DEV(ar->hw, &intf->dev);
init_usb_anchor(&aru->rx_submitted);
init_usb_anchor(&aru->tx_pending);
};
u8 channel;
- while (channel_index < IPW_SCAN_CHANNELS) {
+ while (channel_index < IPW_SCAN_CHANNELS - 1) {
channel =
priv->speed_scan[priv->speed_scan_pos];
if (channel == 0) {
struct ipw_priv *priv =
container_of(work, struct ipw_priv, qos_activate);
- if (priv == NULL)
- return;
-
mutex_lock(&priv->mutex);
if (priv->status & STATUS_ASSOCIATED)
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0},
{PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0},
- {PCI_VENDOR_ID_INTEL, 0x104f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {PCI_VENDOR_ID_INTEL, 0x4220, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */
- {PCI_VENDOR_ID_INTEL, 0x4221, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* BG */
- {PCI_VENDOR_ID_INTEL, 0x4223, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
- {PCI_VENDOR_ID_INTEL, 0x4224, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* ABG */
+ {PCI_VDEVICE(INTEL, 0x104f), 0},
+ {PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */
+ {PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */
+ {PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */
+ {PCI_VDEVICE(INTEL, 0x4224), 0}, /* ABG */
/* required last entry */
{0,}
IWL_RATE_##pp##M_INDEX, \
IWL_RATE_##np##M_INDEX }
+u32 iwl_debug_level;
+EXPORT_SYMBOL(iwl_debug_level);
+
static irqreturn_t iwl_isr(int irq, void *data);
/*
geo_ch->flags |= IEEE80211_CHAN_DISABLED;
}
- /* Save flags for reg domain usage */
- geo_ch->orig_flags = geo_ch->flags;
-
IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
ch->channel, geo_ch->center_freq,
is_channel_a_band(ch) ? "5.2" : "2.4",
if (!sta_ht_inf->ht_supported)
return 0;
}
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (priv->disable_ht40)
+ return 0;
+#endif
return iwl_is_channel_extension(priv, priv->band,
le16_to_cpu(priv->staging_rxon.channel),
iwl_ht_conf->extension_chan_offset);
}
EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
+static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
+{
+ u16 new_val = 0;
+ u16 beacon_factor = 0;
+
+ beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val;
+ new_val = beacon_val / beacon_factor;
+
+ if (!new_val)
+ new_val = max_beacon_val;
+
+ return new_val;
+}
+
+void iwl_setup_rxon_timing(struct iwl_priv *priv)
+{
+ u64 tsf;
+ s32 interval_tm, rem;
+ unsigned long flags;
+ struct ieee80211_conf *conf = NULL;
+ u16 beacon_int;
+
+ conf = ieee80211_get_hw_conf(priv->hw);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
+ priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
+
+ if (priv->iw_mode == NL80211_IFTYPE_STATION) {
+ beacon_int = priv->beacon_int;
+ priv->rxon_timing.atim_window = 0;
+ } else {
+ beacon_int = priv->vif->bss_conf.beacon_int;
+
+ /* TODO: we need to get atim_window from upper stack
+ * for now we set to 0 */
+ priv->rxon_timing.atim_window = 0;
+ }
+
+ beacon_int = iwl_adjust_beacon_interval(beacon_int,
+ priv->hw_params.max_beacon_itrvl * 1024);
+ priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
+
+ tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
+ interval_tm = beacon_int * 1024;
+ rem = do_div(tsf, interval_tm);
+ priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ IWL_DEBUG_ASSOC(priv,
+ "beacon interval %d beacon timer %d beacon tim %d\n",
+ le16_to_cpu(priv->rxon_timing.beacon_interval),
+ le32_to_cpu(priv->rxon_timing.beacon_init_val),
+ le16_to_cpu(priv->rxon_timing.atim_window));
+}
+EXPORT_SYMBOL(iwl_setup_rxon_timing);
+
void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
{
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK;
}
}
-EXPORT_SYMBOL(iwl_set_flags_for_band);
/*
* initialize rxon structure with default values from eeprom
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
- iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+ iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n",
IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
-#endif
+static const char *desc_lookup_text[] = {
+ "OK",
+ "FAIL",
+ "BAD_PARAM",
+ "BAD_CHECKSUM",
+ "NMI_INTERRUPT_WDG",
+ "SYSASSERT",
+ "FATAL_ERROR",
+ "BAD_COMMAND",
+ "HW_ERROR_TUNE_LOCK",
+ "HW_ERROR_TEMPERATURE",
+ "ILLEGAL_CHAN_FREQ",
+ "VCC_NOT_STABLE",
+ "FH_ERROR",
+ "NMI_INTERRUPT_HOST",
+ "NMI_INTERRUPT_ACTION_PT",
+ "NMI_INTERRUPT_UNKNOWN",
+ "UCODE_VERSION_MISMATCH",
+ "HW_ERROR_ABS_LOCK",
+ "HW_ERROR_CAL_LOCK_FAIL",
+ "NMI_INTERRUPT_INST_ACTION_PT",
+ "NMI_INTERRUPT_DATA_ACTION_PT",
+ "NMI_TRM_HW_ER",
+ "NMI_INTERRUPT_TRM",
+ "NMI_INTERRUPT_BREAK_POINT"
+ "DEBUG_0",
+ "DEBUG_1",
+ "DEBUG_2",
+ "DEBUG_3",
+ "UNKNOWN"
+};
+
+static const char *desc_lookup(int i)
+{
+ int max = ARRAY_SIZE(desc_lookup_text) - 1;
+
+ if (i < 0 || i > max)
+ i = max;
+
+ return desc_lookup_text[i];
+}
+
+#define ERROR_START_OFFSET (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+
+static void iwl_dump_nic_error_log(struct iwl_priv *priv)
+{
+ u32 data2, line;
+ u32 desc, time, count, base, data1;
+ u32 blink1, blink2, ilink1, ilink2;
+
+ switch (priv->ucode_type) {
+ case UCODE_RT:
+ base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+ break;
+ case UCODE_INIT:
+ base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+ break;
+ default:
+ IWL_ERR(priv, "uCode image not available\n");
+ return;
+ }
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
+ return;
+ }
+
+ count = iwl_read_targ_mem(priv, base);
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+ IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+ priv->status, count);
+ }
+
+ desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+ blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
+ blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
+ ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
+ ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
+ data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
+ data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
+ line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
+ time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
+
+ IWL_ERR(priv, "Desc Time "
+ "data1 data2 line\n");
+ IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
+ desc_lookup(desc), desc, time, data1, data2, line);
+ IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
+ IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
+ ilink1, ilink2);
+
+}
+
+#define EVENT_START_OFFSET (4 * sizeof(u32))
+
+/**
+ * iwl_print_event_log - Dump error event log to syslog
+ *
+ */
+static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode)
+{
+ u32 i;
+ u32 base; /* SRAM byte address of event log header */
+ u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+ u32 ptr; /* SRAM byte address of log data */
+ u32 ev, time, data; /* event log data */
+
+ if (num_events == 0)
+ return;
+ switch (priv->ucode_type) {
+ case UCODE_RT:
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+ break;
+ case UCODE_INIT:
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ break;
+ default:
+ IWL_ERR(priv, "uCode image not available\n");
+ return;
+ }
+
+ if (mode == 0)
+ event_size = 2 * sizeof(u32);
+ else
+ event_size = 3 * sizeof(u32);
+
+ ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+ /* "time" is actually "data" for mode 0 (no timestamp).
+ * place event id # at far right for easier visual parsing. */
+ for (i = 0; i < num_events; i++) {
+ ev = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ time = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ if (mode == 0) {
+ /* data, ev */
+ IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
+ } else {
+ data = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
+ time, data, ev);
+ }
+ }
+}
+
+void iwl_dump_nic_event_log(struct iwl_priv *priv)
+{
+ u32 base; /* SRAM byte address of event log header */
+ u32 capacity; /* event log capacity in # entries */
+ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
+ u32 num_wraps; /* # times uCode wrapped to top of log */
+ u32 next_entry; /* index of next entry to be written by uCode */
+ u32 size; /* # entries that we'll print */
+
+ switch (priv->ucode_type) {
+ case UCODE_RT:
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+ break;
+ case UCODE_INIT:
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ break;
+ default:
+ IWL_ERR(priv, "uCode image not available\n");
+ return;
+ }
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
+ return;
+ }
+
+ /* event log header */
+ capacity = iwl_read_targ_mem(priv, base);
+ mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
+ num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
+ next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+ size = num_wraps ? capacity : next_entry;
+
+ /* bail out if nothing in log */
+ if (size == 0) {
+ IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+ return;
+ }
+
+ IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
+ size, num_wraps);
+
+ /* if uCode has wrapped back to top of log, start at the oldest entry,
+ * i.e the next one that uCode would fill. */
+ if (num_wraps)
+ iwl_print_event_log(priv, next_entry,
+ capacity - next_entry, mode);
+ /* (then/else) start at top of log */
+ iwl_print_event_log(priv, 0, next_entry, mode);
+
+}
+#endif
/**
* iwl_irq_handle_error - called for HW or SW error interrupt from card
*/
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & IWL_DL_FW_ERRORS) {
+ if (iwl_debug_level & IWL_DL_FW_ERRORS) {
iwl_dump_nic_error_log(priv);
iwl_dump_nic_event_log(priv);
iwl_print_rx_config_cmd(priv);
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM |
IEEE80211_HW_AMPDU_AGGREGATION |
- IEEE80211_HW_SPECTRUM_MGMT;
+ IEEE80211_HW_SPECTRUM_MGMT |
+ IEEE80211_HW_SUPPORTS_PS;
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
hw->wiphy->custom_regulatory = true;
+ /* Firmware does not support this */
+ hw->wiphy->disable_beacon_hints = true;
+
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
/* we create the 802.11 header and a zero-length SSID element */
hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
int iwl_set_hw_params(struct iwl_priv *priv)
{
- priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto;
priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
if (priv->cfg->mod_params->amsdu_size_8K)
priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
+ priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
+
if (priv->cfg->mod_params->disable_11n)
priv->cfg->sku &= ~IWL_SKU_N;
}
EXPORT_SYMBOL(iwl_uninit_drv);
-
-void iwl_disable_interrupts(struct iwl_priv *priv)
-{
- clear_bit(STATUS_INT_ENABLED, &priv->status);
-
- /* disable interrupts from uCode/NIC to host */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
- /* acknowledge/clear/reset any interrupts still pending
- * from uCode or flow handler (Rx/Tx DMA) */
- iwl_write32(priv, CSR_INT, 0xffffffff);
- iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
- IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
-}
-EXPORT_SYMBOL(iwl_disable_interrupts);
-
-void iwl_enable_interrupts(struct iwl_priv *priv)
-{
- IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
- set_bit(STATUS_INT_ENABLED, &priv->status);
- iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
-}
-EXPORT_SYMBOL(iwl_enable_interrupts);
-
-
#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
/* Free dram table */
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & (IWL_DL_ISR)) {
+ if (iwl_debug_level & (IWL_DL_ISR)) {
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
"fh 0x%08x\n", inta, inta_mask, inta_fh);
u32 stat_flags = 0;
struct iwl_host_cmd cmd = {
.id = REPLY_STATISTICS_CMD,
- .meta.flags = flags,
+ .flags = flags,
.len = sizeof(stat_flags),
.data = (u8 *) &stat_flags,
};
EXPORT_SYMBOL(iwl_verify_ucode);
-static const char *desc_lookup_text[] = {
- "OK",
- "FAIL",
- "BAD_PARAM",
- "BAD_CHECKSUM",
- "NMI_INTERRUPT_WDG",
- "SYSASSERT",
- "FATAL_ERROR",
- "BAD_COMMAND",
- "HW_ERROR_TUNE_LOCK",
- "HW_ERROR_TEMPERATURE",
- "ILLEGAL_CHAN_FREQ",
- "VCC_NOT_STABLE",
- "FH_ERROR",
- "NMI_INTERRUPT_HOST",
- "NMI_INTERRUPT_ACTION_PT",
- "NMI_INTERRUPT_UNKNOWN",
- "UCODE_VERSION_MISMATCH",
- "HW_ERROR_ABS_LOCK",
- "HW_ERROR_CAL_LOCK_FAIL",
- "NMI_INTERRUPT_INST_ACTION_PT",
- "NMI_INTERRUPT_DATA_ACTION_PT",
- "NMI_TRM_HW_ER",
- "NMI_INTERRUPT_TRM",
- "NMI_INTERRUPT_BREAK_POINT"
- "DEBUG_0",
- "DEBUG_1",
- "DEBUG_2",
- "DEBUG_3",
- "UNKNOWN"
-};
-
-static const char *desc_lookup(int i)
-{
- int max = ARRAY_SIZE(desc_lookup_text) - 1;
-
- if (i < 0 || i > max)
- i = max;
-
- return desc_lookup_text[i];
-}
-
-#define ERROR_START_OFFSET (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-
-void iwl_dump_nic_error_log(struct iwl_priv *priv)
-{
- u32 data2, line;
- u32 desc, time, count, base, data1;
- u32 blink1, blink2, ilink1, ilink2;
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
- return;
- }
-
- count = iwl_read_targ_mem(priv, base);
-
- if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
- IWL_ERR(priv, "Start IWL Error Log Dump:\n");
- IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
- priv->status, count);
- }
-
- desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
- blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
- blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
- ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
- ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
- data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
- data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
- line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
- time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
-
- IWL_ERR(priv, "Desc Time "
- "data1 data2 line\n");
- IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
- desc_lookup(desc), desc, time, data1, data2, line);
- IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
- IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
- ilink1, ilink2);
-
-}
-EXPORT_SYMBOL(iwl_dump_nic_error_log);
-
-#define EVENT_START_OFFSET (4 * sizeof(u32))
-
-/**
- * iwl_print_event_log - Dump error event log to syslog
- *
- */
-static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
-
- if (num_events == 0)
- return;
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- time = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- if (mode == 0) {
- /* data, ev */
- IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
- } else {
- data = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- }
- }
-}
-
-void iwl_dump_nic_event_log(struct iwl_priv *priv)
-{
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
- return;
- }
-
- /* event log header */
- capacity = iwl_read_targ_mem(priv, base);
- mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return;
- }
-
- IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
- size, num_wraps);
-
- /* if uCode has wrapped back to top of log, start at the oldest entry,
- * i.e the next one that uCode would fill. */
- if (num_wraps)
- iwl_print_event_log(priv, next_entry,
- capacity - next_entry, mode);
- /* (then/else) start at top of log */
- iwl_print_event_log(priv, 0, next_entry, mode);
-
-}
-EXPORT_SYMBOL(iwl_dump_nic_event_log);
-
void iwl_rf_kill_ct_config(struct iwl_priv *priv)
{
struct iwl_ct_kill_config cmd;
+ struct iwl_ct_kill_throttling_config adv_cmd;
unsigned long flags;
int ret = 0;
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
spin_unlock_irqrestore(&priv->lock, flags);
+ priv->power_data.ct_kill_toggle = false;
+
+ switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+ case CSR_HW_REV_TYPE_1000:
+ case CSR_HW_REV_TYPE_6x00:
+ case CSR_HW_REV_TYPE_6x50:
+ adv_cmd.critical_temperature_enter =
+ cpu_to_le32(priv->hw_params.ct_kill_threshold);
+ adv_cmd.critical_temperature_exit =
+ cpu_to_le32(priv->hw_params.ct_kill_exit_threshold);
+
+ ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+ sizeof(adv_cmd), &adv_cmd);
+ break;
+ default:
+ cmd.critical_temperature_R =
+ cpu_to_le32(priv->hw_params.ct_kill_threshold);
- cmd.critical_temperature_R =
- cpu_to_le32(priv->hw_params.ct_kill_threshold);
-
+ ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+ sizeof(cmd), &cmd);
+ break;
+ }
ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
sizeof(cmd), &cmd);
if (ret)
.id = REPLY_CARD_STATE_CMD,
.len = sizeof(u32),
.data = &flags,
- .meta.flags = meta_flag,
+ .flags = meta_flag,
};
return iwl_send_cmd(priv, &cmd);
}
-EXPORT_SYMBOL(iwl_send_card_state);
void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
"notification for %s:\n",
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
- iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+ iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
}
EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
{
memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
}
-EXPORT_SYMBOL(iwl_clear_isr_stats);
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
#define DEBUGFS_ADD_FILE(name, parent) do { \
dbgfs->dbgfs_##parent##_files.file_##name = \
- debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \
+ debugfs_create_file(#name, S_IWUSR | S_IRUSR, \
+ dbgfs->dir_##parent, priv, \
&iwl_dbgfs_##name##_ops); \
if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \
goto err; \
#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
dbgfs->dbgfs_##parent##_files.file_##name = \
- debugfs_create_bool(#name, 0644, dbgfs->dir_##parent, ptr); \
+ debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
+ dbgfs->dir_##parent, ptr); \
if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
|| !dbgfs->dbgfs_##parent##_files.file_##name) \
goto err; \
#define DEBUGFS_ADD_X32(name, parent, ptr) do { \
dbgfs->dbgfs_##parent##_files.file_##name = \
- debugfs_create_x32(#name, 0444, dbgfs->dir_##parent, ptr); \
+ debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \
if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
|| !dbgfs->dbgfs_##parent##_files.file_##name) \
goto err; \
return -ENODATA;
}
+ ptr = priv->eeprom;
+ if (!ptr) {
+ IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
+ return -ENOMEM;
+ }
+
/* 4 characters for byte 0xYY */
buf = kzalloc(buf_size, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
-
- ptr = priv->eeprom;
- if (!ptr) {
- IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
- return -ENOMEM;
- }
pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n",
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
? "OTP" : "EEPROM");
return count;
}
+static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0, i;
+ char buf[256];
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ for (i = 0; i < AC_NUM; i++) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "\tcw_min\tcw_max\taifsn\ttxop\n");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "AC[%d]\t%u\t%u\t%u\t%u\n", i,
+ priv->qos_data.def_qos_parm.ac[i].cw_min,
+ priv->qos_data.def_qos_parm.ac[i].cw_max,
+ priv->qos_data.def_qos_parm.ac[i].aifsn,
+ priv->qos_data.def_qos_parm.ac[i].edca_txop);
+ }
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+
+#ifdef CONFIG_IWLWIFI_LEDS
+static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ int pos = 0;
+ char buf[256];
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "allow blinking: %s\n",
+ (priv->allow_blinking) ? "True" : "False");
+ if (priv->allow_blinking) {
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Led blinking rate: %u\n",
+ priv->last_blink_rate);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Last blink time: %lu\n",
+ priv->last_blink_time);
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+#endif
+
+static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ struct iwl_tt_mgmt *tt = &priv->power_data.tt;
+ struct iwl_tt_restriction *restriction;
+ char buf[100];
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Thermal Throttling Mode: %s\n",
+ (priv->power_data.adv_tt)
+ ? "Advance" : "Legacy");
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Thermal Throttling State: %d\n",
+ tt->state);
+ if (priv->power_data.adv_tt) {
+ restriction = tt->restriction + tt->state;
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Tx mode: %d\n",
+ restriction->tx_stream);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Rx mode: %d\n",
+ restriction->rx_stream);
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "HT mode: %d\n",
+ restriction->is_ht);
+ }
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = file->private_data;
+ char buf[8];
+ int buf_size;
+ int ht40;
+
+ memset(buf, 0, sizeof(buf));
+ buf_size = min(count, sizeof(buf) - 1);
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ if (sscanf(buf, "%d", &ht40) != 1)
+ return -EFAULT;
+ if (!iwl_is_associated(priv))
+ priv->disable_ht40 = ht40 ? true : false;
+ else {
+ IWL_ERR(priv, "Sta associated with AP - "
+ "Change to 40MHz channel support is not allowed\n");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ char buf[100];
+ int pos = 0;
+ const size_t bufsz = sizeof(buf);
+ ssize_t ret;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "11n 40MHz Mode: %s\n",
+ priv->disable_ht40 ? "Disabled" : "Enabled");
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ return ret;
+}
DEBUGFS_READ_WRITE_FILE_OPS(sram);
DEBUGFS_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(channels);
DEBUGFS_READ_FILE_OPS(status);
DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
+DEBUGFS_READ_FILE_OPS(qos);
+#ifdef CONFIG_IWLWIFI_LEDS
+DEBUGFS_READ_FILE_OPS(led);
+#endif
+DEBUGFS_READ_FILE_OPS(thermal_throttling);
+DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
/*
* Create the debugfs files and directories
DEBUGFS_ADD_FILE(channels, data);
DEBUGFS_ADD_FILE(status, data);
DEBUGFS_ADD_FILE(interrupt, data);
+ DEBUGFS_ADD_FILE(qos, data);
+#ifdef CONFIG_IWLWIFI_LEDS
+ DEBUGFS_ADD_FILE(led, data);
+#endif
+ DEBUGFS_ADD_FILE(thermal_throttling, data);
+ DEBUGFS_ADD_FILE(disable_ht40, data);
DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
&priv->disable_chain_noise_cal);
- DEBUGFS_ADD_BOOL(disable_tx_power, rf, &priv->disable_tx_power_cal);
+ if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
+ ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
+ DEBUGFS_ADD_BOOL(disable_tx_power, rf,
+ &priv->disable_tx_power_cal);
return 0;
err:
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos);
+#ifdef CONFIG_IWLWIFI_LEDS
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led);
+#endif
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
DEBUGFS_REMOVE(priv->dbgfs->dir_data);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
- DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
+ if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
+ ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power);
DEBUGFS_REMOVE(priv->dbgfs->dir_rf);
DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
kfree(priv->dbgfs);
/* module parameters */
struct iwl_mod_params iwl3945_mod_params = {
- .num_of_queues = IWL39_MAX_NUM_QUEUES,
+ .num_of_queues = IWL39_NUM_QUEUES, /* Not used */
.sw_crypto = 1,
.restart_fw = 1,
/* the rest are 0 by default */
priv->shared_phys);
}
-#define MAX_UCODE_BEACON_INTERVAL 1024
-#define INTEL_CONN_LISTEN_INTERVAL cpu_to_le16(0xA)
-
-static __le16 iwl3945_adjust_beacon_interval(u16 beacon_val)
-{
- u16 new_val = 0;
- u16 beacon_factor = 0;
-
- beacon_factor =
- (beacon_val + MAX_UCODE_BEACON_INTERVAL)
- / MAX_UCODE_BEACON_INTERVAL;
- new_val = beacon_val / beacon_factor;
-
- return cpu_to_le16(new_val);
-}
-
-static void iwl3945_setup_rxon_timing(struct iwl_priv *priv)
-{
- u64 interval_tm_unit;
- u64 tsf, result;
- unsigned long flags;
- struct ieee80211_conf *conf = NULL;
- u16 beacon_int = 0;
-
- conf = ieee80211_get_hw_conf(priv->hw);
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
- priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
-
- tsf = priv->timestamp;
-
- beacon_int = priv->beacon_int;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (priv->iw_mode == NL80211_IFTYPE_STATION) {
- if (beacon_int == 0) {
- priv->rxon_timing.beacon_interval = cpu_to_le16(100);
- priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
- } else {
- priv->rxon_timing.beacon_interval =
- cpu_to_le16(beacon_int);
- priv->rxon_timing.beacon_interval =
- iwl3945_adjust_beacon_interval(
- le16_to_cpu(priv->rxon_timing.beacon_interval));
- }
-
- priv->rxon_timing.atim_window = 0;
- } else {
- priv->rxon_timing.beacon_interval =
- iwl3945_adjust_beacon_interval(
- priv->vif->bss_conf.beacon_int);
- /* TODO: we need to get atim_window from upper stack
- * for now we set to 0 */
- priv->rxon_timing.atim_window = 0;
- }
-
- interval_tm_unit =
- (le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
- result = do_div(tsf, interval_tm_unit);
- priv->rxon_timing.beacon_init_val =
- cpu_to_le32((u32) ((u64) interval_tm_unit - result));
-
- IWL_DEBUG_ASSOC(priv,
- "beacon interval %d beacon timer %d beacon tim %d\n",
- le16_to_cpu(priv->rxon_timing.beacon_interval),
- le32_to_cpu(priv->rxon_timing.beacon_init_val),
- le16_to_cpu(priv->rxon_timing.atim_window));
-}
-
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
struct ieee80211_tx_info *info,
- struct iwl_cmd *cmd,
+ struct iwl_device_cmd *cmd,
struct sk_buff *skb_frag,
int sta_id)
{
* handle build REPLY_TX command notification.
*/
static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
+ struct iwl_device_cmd *cmd,
struct ieee80211_tx_info *info,
struct ieee80211_hdr *hdr, u8 std_id)
{
struct iwl3945_tx_cmd *tx;
struct iwl_tx_queue *txq = NULL;
struct iwl_queue *q = NULL;
- struct iwl_cmd *out_cmd = NULL;
+ struct iwl_device_cmd *out_cmd;
+ struct iwl_cmd_meta *out_meta;
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
int txq_id = skb_get_queue_mapping(skb);
/* Init first empty entry in queue's array of Tx/cmd buffers */
out_cmd = txq->cmd[idx];
+ out_meta = &txq->meta[idx];
tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
memset(tx, 0, sizeof(*tx));
IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
le16_to_cpu(out_cmd->hdr.sequence));
IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags));
- iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
- iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
+ iwl_print_hex_dump(IWL_DL_TX, tx, sizeof(*tx));
+ iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx->hdr,
ieee80211_hdrlen(fc));
/*
len, PCI_DMA_TODEVICE);
/* we do not map meta data ... so we can safely access address to
* provide to unmap command*/
- pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
- pci_unmap_len_set(&out_cmd->meta, len, len);
+ pci_unmap_addr_set(out_meta, mapping, txcmd_phys);
+ pci_unmap_len_set(out_meta, len, len);
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
struct iwl_host_cmd cmd = {
.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
.data = (void *)&spectrum,
- .meta.flags = CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
};
u32 add_time = le64_to_cpu(params->start_time);
int rc;
if (rc)
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl_rx_packet *)cmd.reply_skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
rc = -EIO;
break;
}
- dev_kfree_skb_any(cmd.meta.u.skb);
+ dev_kfree_skb_any(cmd.reply_skb);
return rc;
}
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
unsigned long status = priv->status;
- IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
+ IWL_WARN(priv, "Card state received: HW:%s SW:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
(flags & SW_CARD_DISABLED) ? "Kill" : "On");
iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & IWL_DL_ISR) {
+ if (iwl_debug_level & IWL_DL_ISR) {
/* just for debug */
inta_mask = iwl_read32(priv, CSR_INT_MASK);
IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
/* Now service all interrupt bits discovered above. */
if (inta & CSR_INT_BIT_HW_ERR) {
- IWL_ERR(priv, "Microcode HW error detected. Restarting.\n");
+ IWL_ERR(priv, "Hardware error detected. Restarting.\n");
/* Tell the device to stop sending interrupts */
iwl_disable_interrupts(priv);
}
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & (IWL_DL_ISR)) {
+ if (iwl_debug_level & (IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_SCD) {
IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
iwl_enable_interrupts(priv);
#ifdef CONFIG_IWLWIFI_DEBUG
- if (priv->debug_level & (IWL_DL_ISR)) {
+ if (iwl_debug_level & (IWL_DL_ISR)) {
inta = iwl_read32(priv, CSR_INT);
inta_mask = iwl_read32(priv, CSR_INT_MASK);
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
u8 is_active, u8 n_probes,
struct iwl3945_scan_channel *scan_ch)
{
- const struct ieee80211_channel *channels = NULL;
+ struct ieee80211_channel *chan;
const struct ieee80211_supported_band *sband;
const struct iwl_channel_info *ch_info;
u16 passive_dwell = 0;
if (!sband)
return 0;
- channels = sband->channels;
-
active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
passive_dwell = iwl_get_passive_dwell_time(priv, band);
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
- for (i = 0, added = 0; i < sband->n_channels; i++) {
- if (channels[i].flags & IEEE80211_CHAN_DISABLED)
+ for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+ chan = priv->scan_request->channels[i];
+
+ if (chan->band != band)
continue;
- scan_ch->channel = channels[i].hw_value;
+ scan_ch->channel = chan->hw_value;
ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
if (!is_channel_valid(ch_info)) {
* and use long active_dwell time.
*/
if (!is_active || is_channel_passive(ch_info) ||
- (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
+ (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
scan_ch->type = 0; /* passive */
if (IWL_UCODE_API(priv->ucode_ver) == 1)
scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
*/
static int iwl3945_read_ucode(struct iwl_priv *priv)
{
- struct iwl_ucode *ucode;
+ const struct iwl_ucode_header *ucode;
int ret = -EINVAL, index;
const struct firmware *ucode_raw;
/* firmware file name contains uCode/driver compatibility version */
goto error;
/* Make sure that we got at least our header! */
- if (ucode_raw->size < sizeof(*ucode)) {
+ if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
IWL_ERR(priv, "File size way too small!\n");
ret = -EINVAL;
goto err_release;
}
/* Data from ucode file: header followed by uCode images */
- ucode = (void *)ucode_raw->data;
+ ucode = (struct iwl_ucode_header *)ucode_raw->data;
priv->ucode_ver = le32_to_cpu(ucode->ver);
api_ver = IWL_UCODE_API(priv->ucode_ver);
- inst_size = le32_to_cpu(ucode->inst_size);
- data_size = le32_to_cpu(ucode->data_size);
- init_size = le32_to_cpu(ucode->init_size);
- init_data_size = le32_to_cpu(ucode->init_data_size);
- boot_size = le32_to_cpu(ucode->boot_size);
+ inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
+ data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
+ init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
+ init_data_size =
+ priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
+ boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
+ src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
/* api_ver should match the api version forming part of the
* firmware filename ... but we don't check for that and only rely
/* Verify size of file vs. image size info in file's header */
- if (ucode_raw->size < sizeof(*ucode) +
+ if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) +
inst_size + data_size + init_size +
init_data_size + boot_size) {
- IWL_DEBUG_INFO(priv, "uCode file size %zd too small\n",
- ucode_raw->size);
+ IWL_DEBUG_INFO(priv,
+ "uCode file size %zd does not match expected size\n",
+ ucode_raw->size);
ret = -EINVAL;
goto err_release;
}
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
- src = &ucode->data[0];
- len = priv->ucode_code.len;
+ len = inst_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) uCode instr len %zd\n", len);
memcpy(priv->ucode_code.v_addr, src, len);
+ src += len;
+
IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
* NOTE: Copy into backup buffer will be done in iwl3945_up() */
- src = &ucode->data[inst_size];
- len = priv->ucode_data.len;
+ len = data_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) uCode data len %zd\n", len);
memcpy(priv->ucode_data.v_addr, src, len);
memcpy(priv->ucode_data_backup.v_addr, src, len);
+ src += len;
/* Initialization instructions (3rd block) */
if (init_size) {
- src = &ucode->data[inst_size + data_size];
- len = priv->ucode_init.len;
+ len = init_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) init instr len %zd\n", len);
memcpy(priv->ucode_init.v_addr, src, len);
+ src += len;
}
/* Initialization data (4th block) */
if (init_data_size) {
- src = &ucode->data[inst_size + data_size + init_size];
- len = priv->ucode_init_data.len;
+ len = init_data_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) init data len %zd\n", len);
memcpy(priv->ucode_init_data.v_addr, src, len);
+ src += len;
}
/* Bootstrap instructions (5th block) */
- src = &ucode->data[inst_size + data_size + init_size + init_data_size];
- len = priv->ucode_boot.len;
+ len = boot_size;
IWL_DEBUG_INFO(priv,
"Copying (but not loading) boot instr len %zd\n", len);
memcpy(priv->ucode_boot.v_addr, src, len);
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = sizeof(struct iwl3945_scan_cmd),
- .meta.flags = CMD_SIZE_HUGE,
+ .flags = CMD_SIZE_HUGE,
};
int rc = 0;
struct iwl3945_scan_cmd *scan;
iwlcore_commit_rxon(priv);
memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl3945_setup_rxon_timing(priv);
+ iwl_setup_rxon_timing(priv);
rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing), &priv->rxon_timing);
if (rc)
/* RXON Timing */
memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl3945_setup_rxon_timing(priv);
+ iwl_setup_rxon_timing(priv);
rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing),
&priv->rxon_timing);
* used for controlling the debug level.
*
* See the level definitions in iwl for details.
+ *
+ * FIXME This file can be deprecated as the module parameter is
+ * writable and users can thus also change the debug level
+ * using the /sys/module/iwl3945/parameters/debug file.
*/
static ssize_t show_debug_level(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
-
- return sprintf(buf, "0x%08X\n", priv->debug_level);
+ return sprintf(buf, "0x%08X\n", iwl_debug_level);
}
static ssize_t store_debug_level(struct device *d,
struct device_attribute *attr,
if (ret)
IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
else
- priv->debug_level = val;
+ iwl_debug_level = val;
return strnlen(buf, count);
}
hw->wiphy->custom_regulatory = true;
+ /* Firmware does not support this */
+ hw->wiphy->disable_beacon_hints = true;
+
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
/* we create the 802.11 header and a zero-length SSID element */
hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
priv = hw->priv;
SET_IEEE80211_DEV(hw, &pdev->dev);
- if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) ||
- (iwl3945_mod_params.num_of_queues < IWL39_MIN_NUM_QUEUES)) {
- IWL_ERR(priv,
- "invalid queues_num, should be between %d and %d\n",
- IWL39_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
- err = -EINVAL;
- goto out_ieee80211_free_hw;
- }
-
/*
* Disabling hardware scan means that mac80211 will perform scans
* "the hard way", rather than using device's scan.
priv->inta_mask = CSR_INI_SET_MASK;
#ifdef CONFIG_IWLWIFI_DEBUG
- priv->debug_level = iwl3945_mod_params.debug;
atomic_set(&priv->restrict_refcnt, 0);
#endif
module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444);
MODULE_PARM_DESC(swcrypto,
"using software crypto (default 1 [software])\n");
-module_param_named(debug, iwl3945_mod_params.debug, uint, 0444);
+#ifdef CONFIG_IWLWIFI_DEBUG
+module_param_named(debug, iwl_debug_level, uint, 0644);
MODULE_PARM_DESC(debug, "debug output mask");
+#endif
module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444);
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
-
-module_param_named(queues_num, iwl3945_mod_params.num_of_queues, int, 0444);
-MODULE_PARM_DESC(queues_num, "number of hw queues.");
-
module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444);
MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");
int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
bool resp)
{
+ struct iwm_umac_wifi_if *hdr = (struct iwm_umac_wifi_if *)payload;
struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
struct iwm_umac_cmd umac_cmd;
+ int ret;
+ u8 oid = hdr->oid;
umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER;
umac_cmd.resp = resp;
- return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
- payload, payload_size);
+ ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
+ payload, payload_size);
+
+ if (resp) {
+ ret = wait_event_interruptible_timeout(iwm->wifi_ntfy_queue,
+ test_and_clear_bit(oid, &iwm->wifi_ntfy[0]),
+ 3 * HZ);
+
+ return ret ? 0 : -EBUSY;
+ }
+
+ return ret;
}
static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
{4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
{3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
{5, 5, 0, COEX_CALIBRATION_FLAGS},
- {4, 4, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
+ {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
{5, 4, 0, COEX_CONNECTION_ESTAB_FLAGS},
{4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS},
{4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
if (IS_ERR(eeprom_rxiq)) {
IWM_ERR(iwm, "Couldn't access EEPROM RX IQ entry\n");
+ kfree(rxiq);
return PTR_ERR(eeprom_rxiq);
}
return ret;
}
-int iwm_send_umac_config(struct iwm_priv *iwm,
- __le32 reset_flags)
+int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags)
{
int ret;
if (ret < 0)
return ret;
+ ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
+ CFG_WIRELESS_MODE,
+ iwm->conf.wireless_mode);
+ if (ret < 0)
+ return ret;
+
ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
CFG_COEX_MODE, iwm->conf.coexist_mode);
if (ret < 0)
return ret;
ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
- CFG_PM_CTRL_FLAGS, 0x30001);
+ CFG_PM_CTRL_FLAGS, 0x1);
if (ret < 0)
return ret;
target_cmd.eop = 1;
ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
- if (ret < 0)
+ if (ret < 0) {
IWM_ERR(iwm, "Couldn't send READ command\n");
+ return ret;
+ }
/* When succeding, the send_target routine returns the seq number */
seq_num = ret;
kfree(cmd);
- return ret;
+ return 0;
}
int iwm_read_mac(struct iwm_priv *iwm, u8 *mac)
ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR),
mac_align, sizeof(mac_align));
- if (ret < 0)
+ if (ret)
return ret;
if (is_valid_ether_addr(mac_align))
return 0;
}
-int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
-{
- struct iwm_umac_tx_key_id tx_key_id;
-
- if (!iwm->default_key || !iwm->default_key->in_use)
- return -EINVAL;
-
- tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
- tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
- sizeof(struct iwm_umac_wifi_if));
-
- tx_key_id.key_idx = key_idx;
-
- return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
-}
-
static int iwm_check_profile(struct iwm_priv *iwm)
{
if (!iwm->umac_profile_active)
return 0;
}
-int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
- struct iwm_key *key)
+int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
{
+ struct iwm_umac_tx_key_id tx_key_id;
int ret;
+
+ ret = iwm_check_profile(iwm);
+ if (ret < 0)
+ return ret;
+
+ /* UMAC only allows to set default key for WEP and auth type is
+ * NOT 802.1X or RSNA. */
+ if ((iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
+ iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104) ||
+ iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_8021X ||
+ iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_RSNA_PSK)
+ return 0;
+
+ tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
+ tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
+ sizeof(struct iwm_umac_wifi_if));
+
+ tx_key_id.key_idx = key_idx;
+
+ return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
+}
+
+int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key)
+{
+ int ret = 0;
u8 cmd[64], *sta_addr, *key_data, key_len;
s8 key_idx;
u16 cmd_size = 0;
struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd;
struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd;
- if (set_tx_key)
- iwm->default_key = key;
-
- /*
- * We check if our current profile is valid.
- * If not, we dont push the key, we just cache them,
- * so that with the next siwsessid call, the keys
- * will be actually pushed.
- */
if (!remove) {
ret = iwm_check_profile(iwm);
if (ret < 0)
key_idx = key->hdr.key_idx;
if (!remove) {
- IWM_DBG_WEXT(iwm, DBG, "key_idx:%d set tx key:%d\n",
- key_idx, set_tx_key);
+ u8 auth_type = iwm->umac_profile->sec.auth_type;
+
+ IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx);
IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len);
IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n",
key_hdr->mac, key_hdr->key_idx, key_hdr->multicast);
iwm->umac_profile->sec.auth_type,
iwm->umac_profile->sec.flags);
- switch (key->alg) {
- case UMAC_CIPHER_TYPE_WEP_40:
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_WEP40:
wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY;
wep40->hdr.buf_size =
cpu_to_le16(sizeof(struct iwm_umac_key_wep40) -
memcpy(&wep40->key_hdr, key_hdr,
sizeof(struct iwm_umac_key_hdr));
memcpy(wep40->key, key_data, key_len);
- wep40->static_key = 1;
+ wep40->static_key =
+ !!((auth_type != UMAC_AUTH_TYPE_8021X) &&
+ (auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
cmd_size = sizeof(struct iwm_umac_key_wep40);
break;
- case UMAC_CIPHER_TYPE_WEP_104:
+ case WLAN_CIPHER_SUITE_WEP104:
wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY;
wep104->hdr.buf_size =
cpu_to_le16(sizeof(struct iwm_umac_key_wep104) -
memcpy(&wep104->key_hdr, key_hdr,
sizeof(struct iwm_umac_key_hdr));
memcpy(wep104->key, key_data, key_len);
- wep104->static_key = 1;
+ wep104->static_key =
+ !!((auth_type != UMAC_AUTH_TYPE_8021X) &&
+ (auth_type != UMAC_AUTH_TYPE_RSNA_PSK));
cmd_size = sizeof(struct iwm_umac_key_wep104);
break;
- case UMAC_CIPHER_TYPE_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP:
key_hdr->key_idx++;
ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY;
ccmp->hdr.buf_size =
memcpy(ccmp->key, key_data, key_len);
- if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- memcpy(ccmp->iv_count, key->rx_seq, 6);
+ if (key->seq_len)
+ memcpy(ccmp->iv_count, key->seq, key->seq_len);
cmd_size = sizeof(struct iwm_umac_key_ccmp);
break;
- case UMAC_CIPHER_TYPE_TKIP:
+ case WLAN_CIPHER_SUITE_TKIP:
key_hdr->key_idx++;
tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY;
tkip->hdr.buf_size =
key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE,
IWM_TKIP_MIC_SIZE);
- if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- memcpy(ccmp->iv_count, key->rx_seq, 6);
+ if (key->seq_len)
+ memcpy(ccmp->iv_count, key->seq, key->seq_len);
cmd_size = sizeof(struct iwm_umac_key_tkip);
break;
return -ENOTSUPP;
}
- if ((key->alg == UMAC_CIPHER_TYPE_CCMP) ||
- (key->alg == UMAC_CIPHER_TYPE_TKIP))
+ if ((key->cipher == WLAN_CIPHER_SUITE_TKIP) ||
+ (key->cipher == WLAN_CIPHER_SUITE_CCMP))
/*
* UGLY_UGLY_UGLY
* Copied HACK from the MWG driver.
schedule_timeout_interruptible(usecs_to_jiffies(300));
ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1);
- if (ret < 0)
- goto err;
-
- /*
- * We need a default key only if it is set and
- * if we're doing WEP.
- */
- if (iwm->default_key == key &&
- ((key->alg == UMAC_CIPHER_TYPE_WEP_40) ||
- (key->alg == UMAC_CIPHER_TYPE_WEP_104))) {
- ret = iwm_set_tx_key(iwm, key_idx);
- if (ret < 0)
- goto err;
- }
} else {
struct iwm_umac_key_remove key_remove;
+ IWM_DBG_WEXT(iwm, ERR, "Removing key_idx:%d\n", key_idx);
+
key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY;
key_remove.hdr.buf_size =
cpu_to_le16(sizeof(struct iwm_umac_key_remove) -
ret = iwm_send_wifi_if_cmd(iwm, &key_remove,
sizeof(struct iwm_umac_key_remove),
1);
- if (ret < 0)
+ if (ret)
return ret;
- iwm->keys[key_idx].in_use = 0;
+ iwm->keys[key_idx].key_len = 0;
}
- return 0;
-
- err:
- kfree(key);
return ret;
}
int iwm_send_mlme_profile(struct iwm_priv *iwm)
{
- int ret, i;
+ int ret;
struct iwm_umac_profile profile;
memcpy(&profile, iwm->umac_profile, sizeof(profile));
sizeof(struct iwm_umac_wifi_if));
ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1);
- if (ret < 0) {
+ if (ret) {
IWM_ERR(iwm, "Send profile command failed\n");
return ret;
}
- /* Wait for the profile to be active */
- ret = wait_event_interruptible_timeout(iwm->mlme_queue,
- iwm->umac_profile_active == 1,
- 3 * HZ);
- if (!ret)
- return -EBUSY;
-
-
- for (i = 0; i < IWM_NUM_KEYS; i++)
- if (iwm->keys[i].in_use) {
- int default_key = 0;
- struct iwm_key *key = &iwm->keys[i];
-
- if (key == iwm->default_key)
- default_key = 1;
-
- /* Wait for the profile before sending the keys */
- wait_event_interruptible_timeout(iwm->mlme_queue,
- (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) ||
- test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)),
- 3 * HZ);
-
- ret = iwm_set_key(iwm, 0, default_key, key);
- if (ret < 0)
- return ret;
- }
-
return 0;
}
int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
{
- int ret;
struct iwm_umac_invalidate_profile invalid;
+ int ret;
invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE;
invalid.hdr.buf_size =
invalid.reason = WLAN_REASON_UNSPECIFIED;
ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1);
- if (ret < 0)
+ if (ret)
return ret;
ret = wait_event_interruptible_timeout(iwm->mlme_queue,
- (iwm->umac_profile_active == 0),
- 2 * HZ);
- if (!ret)
- return -EBUSY;
+ (iwm->umac_profile_active == 0), 2 * HZ);
- return 0;
+ return ret ? 0 : -EBUSY;
}
int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags)
}
ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0);
- if (ret < 0) {
+ if (ret) {
IWM_ERR(iwm, "Couldn't send scan request\n");
return ret;
}
/* Copyright (C) 2006, Red Hat, Inc. */
#include <linux/types.h>
- #include <linux/kernel.h>
#include <linux/etherdevice.h>
#include <linux/ieee80211.h>
#include <linux/if_arp.h>
u16 *rates_size)
{
u8 *card_rates = lbs_bg_rates;
+ size_t num_card_rates = sizeof(lbs_bg_rates);
int ret = 0, i, j;
- u8 tmp[(ARRAY_SIZE(lbs_bg_rates) - 1) * (*rates_size - 1)];
+ u8 tmp[30];
size_t tmp_size = 0;
/* For each rate in card_rates that exists in rate1, copy to tmp */
- for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && card_rates[i]; i++) {
- for (j = 0; j < *rates_size && rates[j]; j++) {
+ for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
+ for (j = 0; rates[j] && (j < *rates_size); j++) {
if (rates[j] == card_rates[i])
tmp[tmp_size++] = card_rates[i];
}
}
lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
- lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates,
- ARRAY_SIZE(lbs_bg_rates));
+ lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
lbs_pr_alert("Previously set fixed data rate %#x isn't "
"compatible with the network.\n", priv->cur_rate);
ret = -1;
+ goto done;
}
+ ret = 0;
+
done:
memset(rates, 0, *rates_size);
*rates_size = min_t(int, tmp_size, *rates_size);
{
struct cmd_ds_802_11_authenticate cmd;
int ret = -1;
- DECLARE_MAC_BUF(mac);
lbs_deb_enter(LBS_DEB_JOIN);
cmd.authtype = iw_auth_to_ieee_auth(auth);
- lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
- print_mac(mac, bssid), cmd.authtype);
+ lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype);
ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
rates = (struct mrvl_ie_rates_param_set *) pos;
rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
memcpy(&rates->rates, &bss->rates, MAX_RATES);
- tmplen = min_t(u16, ARRAY_SIZE(rates->rates), MAX_RATES);
+ tmplen = MAX_RATES;
if (get_common_rates(priv, rates->rates, &tmplen)) {
ret = -1;
goto done;
/* Firmware v9+ indicate authentication suites as a TLV */
if (priv->fwrelease >= 0x09000000) {
- DECLARE_MAC_BUF(mac);
-
auth = (struct mrvl_ie_auth_type *) pos;
auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
auth->header.len = cpu_to_le16(2);
auth->auth = cpu_to_le16(tmpauth);
pos += sizeof(auth->header) + 2;
- lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
- print_mac(mac, bss->bssid), priv->secinfo.auth_mode);
+ lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n",
+ bss->bssid, priv->secinfo.auth_mode);
}
/* WPA/WPA2 IEs */
/* Copy Data rates from the rates recorded in scan response */
memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
- ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), MAX_RATES);
+ ratesize = min_t(u16, sizeof(cmd.bss.rates), MAX_RATES);
memcpy(cmd.bss.rates, bss->rates, ratesize);
if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
if (ret)
goto out;
+ memcpy(&priv->wpa_unicast_key, &assoc_req->wpa_unicast_key,
+ sizeof(struct enc_key));
+
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
assoc_req->flags = flags;
+
+ memcpy(&priv->wpa_mcast_key, &assoc_req->wpa_mcast_key,
+ sizeof(struct enc_key));
}
out:
*/
};
- #define MWL8K_VIF(_vif) (struct mwl8k_vif *)(&((_vif)->drv_priv))
+ #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
static const struct ieee80211_channel mwl8k_channels[] = {
{ .center_freq = 2412, .hw_value = 1, },
rmb();
skb = rxq->rx_skb[rxq->rx_head];
+ if (skb == NULL)
+ break;
rxq->rx_skb[rxq->rx_head] = NULL;
rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS;
status.flag = 0;
status.band = IEEE80211_BAND_2GHZ;
status.freq = ieee80211_channel_to_frequency(rx_desc->channel);
- ieee80211_rx_irqsafe(hw, skb, &status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx_irqsafe(hw, skb);
processed++;
}
timeout = wait_for_completion_timeout(&cmd_wait,
msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS));
+ pci_unmap_single(priv->pdev, dma_addr, dma_size,
+ PCI_DMA_BIDIRECTIONAL);
+
result = &cmd->result;
if (!timeout) {
spin_lock_irq(&priv->fw_lock);
*result);
}
- pci_unmap_single(priv->pdev, dma_addr, dma_size,
- PCI_DMA_BIDIRECTIONAL);
return rc;
}
memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma);
- cmd->num_tx_queues = MWL8K_TX_QUEUES;
+ cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES);
for (i = 0; i < MWL8K_TX_QUEUES; i++)
cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma);
- cmd->num_tx_desc_per_queue = MWL8K_TX_DESCS;
- cmd->total_rx_desc = MWL8K_RX_DESCS;
+ cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
+ cmd->total_rx_desc = cpu_to_le32(MWL8K_RX_DESCS);
rc = mwl8k_post_cmd(hw, &cmd->header);
if (!rc) {
SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
- priv->fw_rev = cmd->fw_rev;
+ priv->fw_rev = le32_to_cpu(cmd->fw_rev);
priv->hw_rev = cmd->hw_rev;
priv->region_code = le16_to_cpu(cmd->region_code);
}
struct mwl8k_cmd_update_sta_db *cmd;
struct peer_capability_info *peer_info;
struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
- DECLARE_MAC_BUF(mac);
int rc;
__u8 count, *rates;
struct dev_addr_list *mclist = worker->mclist;
struct mwl8k_priv *priv = hw->priv;
- struct mwl8k_vif *mv_vif;
int rc = 0;
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
rc = mwl8k_cmd_set_pre_scan(hw);
else {
- mv_vif = MWL8K_VIF(priv->vif);
- rc = mwl8k_cmd_set_post_scan(hw, mv_vif->bssid);
+ u8 *bssid;
+
+ bssid = "\x00\x00\x00\x00\x00\x00";
+ if (priv->vif != NULL)
+ bssid = MWL8K_VIF(priv->vif)->bssid;
+
+ rc = mwl8k_cmd_set_post_scan(hw, bssid);
}
}
{
struct ieee80211_hw *hw;
struct mwl8k_priv *priv;
- DECLARE_MAC_BUF(mac);
int rc;
int i;
u8 *fw;
MWL8K_DESC);
printk(KERN_INFO "%s: Driver Ver:%s Firmware Ver:%u.%u.%u.%u\n",
priv->name, MWL8K_VERSION, fw[3], fw[2], fw[1], fw[0]);
- printk(KERN_INFO "%s: MAC Address: %s\n", priv->name,
- print_mac(mac, hw->wiphy->perm_addr));
+ printk(KERN_INFO "%s: MAC Address: %pM\n", priv->name,
+ hw->wiphy->perm_addr);
return 0;
ieee80211_stop_queues(hw);
+ ieee80211_unregister_hw(hw);
+
/* Remove tx reclaim tasklet */
tasklet_kill(&priv->tx_reclaim_task);
for (i = 0; i < MWL8K_TX_QUEUES; i++)
mwl8k_txq_reclaim(hw, i, 1);
- ieee80211_unregister_hw(hw);
-
for (i = 0; i < MWL8K_TX_QUEUES; i++)
mwl8k_txq_deinit(hw, i);
if (length < ETH_ZLEN) {
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
length = ETH_ZLEN;
}
switch (ray_hw_xmit(skb->data, length, dev, DATA_TYPE)) {
default:
dev->trans_start = jiffies;
dev_kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
- return 0;
+ return NETDEV_TX_OK;
} /* ray_dev_start_xmit */
/*===========================================================================*/
struct pcmcia_device *link = local->finder;
struct status __iomem *p = local->sram + STATUS_BASE;
- if (local == (ray_dev_t *) NULL)
- return (iw_stats *) NULL;
-
local->wstats.status = local->card_status;
#ifdef WIRELESS_SPY
if ((local->spy_data.spy_number > 0)
#ifdef PCMCIA_DEBUG
if (pc_debug > 3) {
- int i;
- printk(KERN_DEBUG "skb->data before untranslate");
- for (i = 0; i < 64; i++)
- printk("%02x ", skb->data[i]);
- printk("\n" KERN_DEBUG
+ print_hex_dump(KERN_DEBUG, "skb->data before untranslate: ",
+ DUMP_PREFIX_NONE, 16, 1,
+ skb->data, 64, true);
+ printk(KERN_DEBUG
"type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n",
ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl,
psnap->org[0], psnap->org[1], psnap->org[2]);
* able to detect collisions, therefore in theory we don't really
* need to pad. Jean II */
if (skb_padto(skb, ETH_ZLEN))
- return 0;
+ return NETDEV_TX_OK;
wv_packet_write(dev, skb->data, skb->len);
#ifdef DEBUG_TX_TRACE
printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name);
#endif
- return(0);
+ return NETDEV_TX_OK;
}
/********************** HARDWARE CONFIGURATION **********************/
cfblk.rcvstop = TRUE; /* Enable Receive Stop Register */
#ifdef DEBUG_I82593_SHOW
- {
- u_char *c = (u_char *) &cfblk;
- int i;
- printk(KERN_DEBUG "wavelan_cs: config block:");
- for(i = 0; i < sizeof(struct i82593_conf_block); i++,c++)
- {
- if((i % 16) == 0) printk("\n" KERN_DEBUG);
- printk("%02x ", *c);
- }
- printk("\n");
- }
+ print_hex_dump(KERN_DEBUG, "wavelan_cs: config block: ", DUMP_PREFIX_NONE,
+ 16, 1, &cfblk, sizeof(struct i82593_conf_block), false);
#endif
/* Copy the config block to the i82593 */
/* These identify the driver base version and may not be removed. */
static const char version[] __devinitconst =
KERN_INFO DRV_NAME ".c:v1.05 1/09/2001 Written by Donald Becker <
[email protected]>\n"
- KERN_INFO " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n";
+ " (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n";
MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver");
int i;
printk(KERN_WARNING " Rx ring %p: ", yp->rx_ring);
for (i = 0; i < RX_RING_SIZE; i++)
- printk(" %8.8x", yp->rx_ring[i].result_status);
- printk("\n"KERN_WARNING" Tx ring %p: ", yp->tx_ring);
+ printk(KERN_CONT " %8.8x",
+ yp->rx_ring[i].result_status);
+ printk(KERN_CONT "\n");
+ printk(KERN_WARNING" Tx ring %p: ", yp->tx_ring);
for (i = 0; i < TX_RING_SIZE; i++)
- printk(" %4.4x /%8.8x", yp->tx_status[i].tx_errs,
- yp->tx_ring[i].result_status);
- printk("\n");
+ printk(KERN_CONT " %4.4x /%8.8x",
+ yp->tx_status[i].tx_errs,
+ yp->tx_ring[i].result_status);
+ printk(KERN_CONT "\n");
}
/* If the hardware is found to hang regularly, we will update the code
if (skb_padto(skb, len)) {
yp->tx_skbuff[entry] = NULL;
netif_wake_queue(dev);
- return 0;
+ return NETDEV_TX_OK;
}
}
}
printk(KERN_DEBUG "%s: Yellowfin transmit frame #%d queued in slot %d.\n",
dev->name, yp->cur_tx, entry);
}
- return 0;
+ return NETDEV_TX_OK;
}
/* The interrupt handler does all of the Rx thread work and cleans up
#if defined(__i386__)
if (yellowfin_debug > 2) {
- printk("\n"KERN_DEBUG" Tx ring at %8.8llx:\n",
+ printk(KERN_DEBUG" Tx ring at %8.8llx:\n",
(unsigned long long)yp->tx_ring_dma);
for (i = 0; i < TX_RING_SIZE*2; i++)
- printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n",
+ printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n",
ioread32(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ',
i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr,
yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status);
printk(KERN_DEBUG " Tx status %p:\n", yp->tx_status);
for (i = 0; i < TX_RING_SIZE; i++)
- printk(" #%d status %4.4x %4.4x %4.4x %4.4x.\n",
+ printk(KERN_DEBUG " #%d status %4.4x %4.4x %4.4x %4.4x.\n",
i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs,
yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused);
- printk("\n"KERN_DEBUG " Rx ring %8.8llx:\n",
+ printk(KERN_DEBUG " Rx ring %8.8llx:\n",
(unsigned long long)yp->rx_ring_dma);
for (i = 0; i < RX_RING_SIZE; i++) {
printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n",
stlc45xx_debug(DEBUG_RX, "rx data 0x%p %d B", skb->data, skb->len);
stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len);
- ieee80211_rx(stlc->hw, skb, &status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx(stlc->hw, skb);
return 0;
}
stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
}
- static int stlc45xx_op_config_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_if_conf *conf)
- {
- struct stlc45xx *stlc = hw->priv;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- mutex_lock(&stlc->mutex);
-
- memcpy(stlc->bssid, conf->bssid, ETH_ALEN);
- stlc45xx_tx_setup(stlc);
-
- mutex_unlock(&stlc->mutex);
-
- return 0;
- }
-
static int stlc45xx_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct stlc45xx *stlc = hw->priv;
{
struct stlc45xx *stlc = hw->priv;
+ stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
+ mutex_lock(&stlc->mutex);
+
+ memcpy(stlc->bssid, info->bssid, ETH_ALEN);
+ stlc45xx_tx_setup(stlc);
+
+ mutex_unlock(&stlc->mutex);
+
if (changed & BSS_CHANGED_ASSOC) {
stlc->associated = info->assoc;
if (info->assoc)
.add_interface = stlc45xx_op_add_interface,
.remove_interface = stlc45xx_op_remove_interface,
.config = stlc45xx_op_config,
- .config_interface = stlc45xx_op_config_interface,
.configure_filter = stlc45xx_op_configure_filter,
.tx = stlc45xx_op_tx,
.bss_info_changed = stlc45xx_op_bss_info_changed,
* @ssids: SSIDs to scan for (active scan only)
* @n_ssids: number of SSIDs
* @channels: channels to scan on.
- * @n_channels: number of channels for each band
+ * @n_channels: total number of channels to scan
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
* @wiphy: the wiphy this was for
- * @ifidx: the interface index
+ * @dev: the interface
*/
struct cfg80211_scan_request {
struct cfg80211_ssid *ssids;
/* internal */
struct wiphy *wiphy;
- int ifidx;
+ struct net_device *dev;
+ bool aborted;
};
/**
* is no guarantee that these are well-formed!)
* @len_information_elements: total length of the information elements
* @signal: signal strength value (type depends on the wiphy's signal_type)
- * @hold: BSS should not expire
* @free_priv: function pointer to free private data
* @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
*/
u8 priv[0] __attribute__((__aligned__(sizeof(void *))));
};
+/**
+ * ieee80211_bss_get_ie - find IE with given ID
+ * @bss: the bss to search
+ * @ie: the IE ID
+ * Returns %NULL if not found.
+ */
+const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
+
+
+/**
+ * struct cfg80211_crypto_settings - Crypto settings
+ * @wpa_versions: indicates which, if any, WPA versions are enabled
+ * (from enum nl80211_wpa_versions)
+ * @cipher_group: group key cipher suite (or 0 if unset)
+ * @n_ciphers_pairwise: number of AP supported unicast ciphers
+ * @ciphers_pairwise: unicast key cipher suites
+ * @n_akm_suites: number of AKM suites
+ * @akm_suites: AKM suites
+ * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
+ * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
+ * required to assume that the port is unauthorized until authorized by
+ * user space. Otherwise, port is marked authorized by default.
+ */
+struct cfg80211_crypto_settings {
+ u32 wpa_versions;
+ u32 cipher_group;
+ int n_ciphers_pairwise;
+ u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES];
+ int n_akm_suites;
+ u32 akm_suites[NL80211_MAX_NR_AKM_SUITES];
+ bool control_port;
+};
+
/**
* struct cfg80211_auth_request - Authentication request data
*
* This structure provides information needed to complete IEEE 802.11
* authentication.
- * NOTE: This structure will likely change when more code from mac80211 is
- * moved into cfg80211 so that non-mac80211 drivers can benefit from it, too.
- * Before using this in a driver that does not use mac80211, it would be better
- * to check the status of that work and better yet, volunteer to work on it.
- *
- * @chan: The channel to use or %NULL if not specified (auto-select based on
- * scan results)
- * @peer_addr: The address of the peer STA (AP BSSID in infrastructure case);
- * this field is required to be present; if the driver wants to help with
- * BSS selection, it should use (yet to be added) MLME event to allow user
- * space SME to be notified of roaming candidate, so that the SME can then
- * use the authentication request with the recommended BSSID and whatever
- * other data may be needed for authentication/association
- * @ssid: SSID or %NULL if not yet available
- * @ssid_len: Length of ssid in octets
+ *
+ * @bss: The BSS to authenticate with.
* @auth_type: Authentication type (algorithm)
* @ie: Extra IEs to add to Authentication frame or %NULL
* @ie_len: Length of ie buffer in octets
+ * @key_len: length of WEP key for shared key authentication
+ * @key_idx: index of WEP key for shared key authentication
+ * @key: WEP key for shared key authentication
*/
struct cfg80211_auth_request {
- struct ieee80211_channel *chan;
- u8 *peer_addr;
- const u8 *ssid;
- size_t ssid_len;
- enum nl80211_auth_type auth_type;
+ struct cfg80211_bss *bss;
const u8 *ie;
size_t ie_len;
+ enum nl80211_auth_type auth_type;
+ const u8 *key;
+ u8 key_len, key_idx;
};
/**
*
* This structure provides information needed to complete IEEE 802.11
* (re)association.
- * NOTE: This structure will likely change when more code from mac80211 is
- * moved into cfg80211 so that non-mac80211 drivers can benefit from it, too.
- * Before using this in a driver that does not use mac80211, it would be better
- * to check the status of that work and better yet, volunteer to work on it.
- *
- * @chan: The channel to use or %NULL if not specified (auto-select based on
- * scan results)
- * @peer_addr: The address of the peer STA (AP BSSID); this field is required
- * to be present and the STA must be in State 2 (authenticated) with the
- * peer STA
- * @ssid: SSID
- * @ssid_len: Length of ssid in octets
+ * @bss: The BSS to associate with.
* @ie: Extra IEs to add to (Re)Association Request frame or %NULL
* @ie_len: Length of ie buffer in octets
* @use_mfp: Use management frame protection (IEEE 802.11w) in this association
- * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
- * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
- * required to assume that the port is unauthorized until authorized by
- * user space. Otherwise, port is marked authorized by default.
+ * @crypto: crypto settings
+ * @prev_bssid: previous BSSID, if not %NULL use reassociate frame
*/
struct cfg80211_assoc_request {
- struct ieee80211_channel *chan;
- u8 *peer_addr;
- const u8 *ssid;
- size_t ssid_len;
- const u8 *ie;
+ struct cfg80211_bss *bss;
+ const u8 *ie, *prev_bssid;
size_t ie_len;
+ struct cfg80211_crypto_settings crypto;
bool use_mfp;
- bool control_port;
};
/**
* This structure provides information needed to complete IEEE 802.11
* deauthentication.
*
- * @peer_addr: The address of the peer STA (AP BSSID); this field is required
- * to be present and the STA must be authenticated with the peer STA
+ * @bss: the BSS to deauthenticate from
* @ie: Extra IEs to add to Deauthentication frame or %NULL
* @ie_len: Length of ie buffer in octets
+ * @reason_code: The reason code for the deauthentication
*/
struct cfg80211_deauth_request {
- u8 *peer_addr;
- u16 reason_code;
+ struct cfg80211_bss *bss;
const u8 *ie;
size_t ie_len;
+ u16 reason_code;
};
/**
* This structure provides information needed to complete IEEE 802.11
* disassocation.
*
- * @peer_addr: The address of the peer STA (AP BSSID); this field is required
- * to be present and the STA must be associated with the peer STA
+ * @bss: the BSS to disassociate from
* @ie: Extra IEs to add to Disassociation frame or %NULL
* @ie_len: Length of ie buffer in octets
+ * @reason_code: The reason code for the disassociation
*/
struct cfg80211_disassoc_request {
- u8 *peer_addr;
- u16 reason_code;
+ struct cfg80211_bss *bss;
const u8 *ie;
size_t ie_len;
+ u16 reason_code;
};
/**
* @ie: information element(s) to include in the beacon
* @ie_len: length of that
* @beacon_interval: beacon interval to use
+ * @privacy: this is a protected network, keys will be configured
+ * after joining
*/
struct cfg80211_ibss_params {
u8 *ssid;
u8 ssid_len, ie_len;
u16 beacon_interval;
bool channel_fixed;
+ bool privacy;
+};
+
+/**
+ * struct cfg80211_connect_params - Connection parameters
+ *
+ * This structure provides information needed to complete IEEE 802.11
+ * authentication and association.
+ *
+ * @channel: The channel to use or %NULL if not specified (auto-select based
+ * on scan results)
+ * @bssid: The AP BSSID or %NULL if not specified (auto-select based on scan
+ * results)
+ * @ssid: SSID
+ * @ssid_len: Length of ssid in octets
+ * @auth_type: Authentication type (algorithm)
+ * @assoc_ie: IEs for association request
+ * @assoc_ie_len: Length of assoc_ie in octets
+ * @privacy: indicates whether privacy-enabled APs should be used
+ * @crypto: crypto settings
+ * @key_len: length of WEP key for shared key authentication
+ * @key_idx: index of WEP key for shared key authentication
+ * @key: WEP key for shared key authentication
+ */
+struct cfg80211_connect_params {
+ struct ieee80211_channel *channel;
+ u8 *bssid;
+ u8 *ssid;
+ size_t ssid_len;
+ enum nl80211_auth_type auth_type;
+ u8 *ie;
+ size_t ie_len;
+ bool privacy;
+ struct cfg80211_crypto_settings crypto;
+ const u8 *key;
+ u8 key_len, key_idx;
};
/**
TX_POWER_FIXED,
};
+/*
+ * cfg80211_bitrate_mask - masks for bitrate control
+ */
+struct cfg80211_bitrate_mask {
+/*
+ * As discussed in Berlin, this struct really
+ * should look like this:
+
+ struct {
+ u32 legacy;
+ u8 mcs[IEEE80211_HT_MCS_MASK_LEN];
+ } control[IEEE80211_NUM_BANDS];
+
+ * Since we can always fix in-kernel users, let's keep
+ * it simpler for now:
+ */
+ u32 fixed; /* fixed bitrate, 0 == not fixed */
+ u32 maxrate; /* in kbps, 0 == no limit */
+};
+
/**
* struct cfg80211_ops - backend description for wireless configuration
*
* @resume: wiphy device needs to be resumed
*
* @add_virtual_intf: create a new virtual interface with the given name,
- * must set the struct wireless_dev's iftype.
+ * must set the struct wireless_dev's iftype. Beware: You must create
+ * the new netdev in the wiphy's network namespace!
*
* @del_virtual_intf: remove the virtual interface determined by ifindex.
*
* @deauth: Request to deauthenticate from the specified peer
* @disassoc: Request to disassociate from the specified peer
*
+ * @connect: Connect to the ESS with the specified parameters. When connected,
+ * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
+ * If the connection fails for some reason, call cfg80211_connect_result()
+ * with the status from the AP.
+ * @disconnect: Disconnect from the BSS/ESS.
+ *
* @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
* cfg80211_ibss_joined(), also call that function when changing BSSID due
* to a merge.
*
* @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
* functions to adjust rfkill hw state
+ *
+ * @testmode_cmd: run a test mode command
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy);
int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params);
- int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex);
- int (*change_virtual_intf)(struct wiphy *wiphy, int ifindex,
+ int (*del_virtual_intf)(struct wiphy *wiphy, struct net_device *dev);
+ int (*change_virtual_intf)(struct wiphy *wiphy,
+ struct net_device *dev,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params);
int (*assoc)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_assoc_request *req);
int (*deauth)(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_deauth_request *req);
+ struct cfg80211_deauth_request *req,
+ void *cookie);
int (*disassoc)(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_disassoc_request *req);
+ struct cfg80211_disassoc_request *req,
+ void *cookie);
+
+ int (*connect)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_connect_params *sme);
+ int (*disconnect)(struct wiphy *wiphy, struct net_device *dev,
+ u16 reason_code);
int (*join_ibss)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_ibss_params *params);
enum tx_power_setting type, int dbm);
int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
+ int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *addr);
+
void (*rfkill_poll)(struct wiphy *wiphy);
+
+#ifdef CONFIG_NL80211_TESTMODE
+ int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len);
+#endif
+
+ int (*set_bitrate_mask)(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ const struct cfg80211_bitrate_mask *mask);
+
+ /* some temporary stuff to finish wext */
+ int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
+ bool enabled, int timeout);
};
/*
* channels at a later time. This can be used for devices which do not
* have calibration information gauranteed for frequencies or settings
* outside of its regulatory domain.
+ * @disable_beacon_hints: enable this if your driver needs to ensure that
+ * passive scan flags and beaconing flags may not be lifted by cfg80211
+ * due to regulatory beacon hints. For more information on beacon
+ * hints read the documenation for regulatory_hint_found_beacon()
* @reg_notifier: the driver's regulatory notification callback
* @regd: the driver's regulatory domain, if one was requested via
* the regulatory_hint() API. This can be used by the driver
* @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
* -1 = fragmentation disabled, only odd values >= 256 used
* @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
+ * @net: the network namespace this wiphy currently lives in
+ * @netnsok: if set to false, do not allow changing the netns of this
+ * wiphy at all
*/
struct wiphy {
/* assign these fields before you register the wiphy */
bool custom_regulatory;
bool strict_regulatory;
+ bool disable_beacon_hints;
+ bool netnsok;
+
enum cfg80211_signal_type signal_type;
int bss_priv_size;
/* dir in debugfs: ieee80211/<wiphyname> */
struct dentry *debugfsdir;
+#ifdef CONFIG_NET_NS
+ /* the network namespace this phy lives in currently */
+ struct net *_net;
+#endif
+
char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
};
+#ifdef CONFIG_NET_NS
+static inline struct net *wiphy_net(struct wiphy *wiphy)
+{
+ return wiphy->_net;
+}
+
+static inline void wiphy_net_set(struct wiphy *wiphy, struct net *net)
+{
+ wiphy->_net = net;
+}
+#else
+static inline struct net *wiphy_net(struct wiphy *wiphy)
+{
+ return &init_net;
+}
+
+static inline void wiphy_net_set(struct wiphy *wiphy, struct net *net)
+{
+}
+#endif
+
/**
* wiphy_priv - return priv from wiphy
*
return &wiphy->priv;
}
+/**
+ * priv_to_wiphy - return the wiphy containing the priv
+ *
+ * @priv: a pointer previously returned by wiphy_priv
+ */
+static inline struct wiphy *priv_to_wiphy(void *priv)
+{
+ BUG_ON(!priv);
+ return container_of(priv, struct wiphy, priv);
+}
+
/**
* set_wiphy_dev - set device pointer for wiphy
*
*/
extern void wiphy_free(struct wiphy *wiphy);
+/* internal structs */
+struct cfg80211_conn;
+struct cfg80211_internal_bss;
+struct cfg80211_cached_keys;
+
+#define MAX_AUTH_BSSES 4
+
/**
* struct wireless_dev - wireless per-netdev state
*
struct wiphy *wiphy;
enum nl80211_iftype iftype;
- /* private to the generic wireless code */
+ /* the remainder of this struct should be private to cfg80211 */
struct list_head list;
struct net_device *netdev;
- /* currently used for IBSS - might be rearranged in the future */
- struct cfg80211_bss *current_bss;
- u8 bssid[ETH_ALEN];
+ struct mutex mtx;
+
+ /* currently used for IBSS and SME - might be rearranged later */
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len;
+ enum {
+ CFG80211_SME_IDLE,
+ CFG80211_SME_CONNECTING,
+ CFG80211_SME_CONNECTED,
+ } sme_state;
+ struct cfg80211_conn *conn;
+ struct cfg80211_cached_keys *connect_keys;
+
+ struct list_head event_list;
+ spinlock_t event_lock;
+
+ struct cfg80211_internal_bss *authtry_bsses[MAX_AUTH_BSSES];
+ struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
+ struct cfg80211_internal_bss *current_bss; /* associated / joined */
#ifdef CONFIG_WIRELESS_EXT
/* wext data */
struct {
struct cfg80211_ibss_params ibss;
+ struct cfg80211_connect_params connect;
+ struct cfg80211_cached_keys *keys;
+ u8 *ie;
+ size_t ie_len;
u8 bssid[ETH_ALEN];
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
s8 default_key, default_mgmt_key;
+ bool ps;
+ int ps_timeout;
} wext;
#endif
};
*/
extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
-/**
- * regulatory_hint_11d - hints a country IE as a regulatory domain
- * @wiphy: the wireless device giving the hint (used only for reporting
- * conflicts)
- * @country_ie: pointer to the country IE
- * @country_ie_len: length of the country IE
- *
- * We will intersect the rd with the what CRDA tells us should apply
- * for the alpha2 this country IE belongs to, this prevents APs from
- * sending us incorrect or outdated information against a country.
- */
-extern void regulatory_hint_11d(struct wiphy *wiphy,
- u8 *country_ie,
- u8 country_ie_len);
/**
* wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
* @wiphy: the wireless device we want to process the regulatory domain on
int cfg80211_wext_giwrange(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *data, char *extra);
-int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra);
-int cfg80211_ibss_wext_giwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra);
-int cfg80211_ibss_wext_siwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid);
-int cfg80211_ibss_wext_giwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid);
-int cfg80211_ibss_wext_siwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra);
-int cfg80211_ibss_wext_giwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra);
+int cfg80211_wext_siwgenie(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+int cfg80211_wext_siwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra);
+int cfg80211_wext_giwauth(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra);
-struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy,
- struct iw_freq *freq);
+int cfg80211_wext_siwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_wext_giwfreq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *freq, char *extra);
+int cfg80211_wext_siwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+int cfg80211_wext_giwessid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *ssid);
+int cfg80211_wext_siwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra);
+int cfg80211_wext_giwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra);
int cfg80211_wext_siwrts(struct net_device *dev,
struct iw_request_info *info,
int cfg80211_wext_giwtxpower(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *data, char *keybuf);
+struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev);
+
+int cfg80211_wext_siwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra);
+int cfg80211_wext_giwpower(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrq, char *extra);
+
+int cfg80211_wext_siwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
+int cfg80211_wext_giwap(struct net_device *dev,
+ struct iw_request_info *info,
+ struct sockaddr *ap_addr, char *extra);
/*
* callbacks for asynchronous cfg80211 methods, notification
* This function is called whenever an authentication has been processed in
* station mode. The driver is required to call either this function or
* cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
- * call.
+ * call. This function may sleep.
*/
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
* cfg80211_send_auth_timeout - notification of timed out authentication
* @dev: network device
* @addr: The MAC address of the device with which the authentication timed out
+ *
+ * This function may sleep.
*/
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
* This function is called whenever a (re)association response has been
* processed in station mode. The driver is required to call either this
* function or cfg80211_send_assoc_timeout() to indicate the result of
- * cfg80211_ops::assoc() call.
+ * cfg80211_ops::assoc() call. This function may sleep.
*/
void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len);
* cfg80211_send_assoc_timeout - notification of timed out association
* @dev: network device
* @addr: The MAC address of the device with which the association timed out
+ *
+ * This function may sleep.
*/
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
* @dev: network device
* @buf: deauthentication frame (header + body)
* @len: length of the frame data
+ * @cookie: cookie from ->deauth if called within that callback,
+ * %NULL otherwise
*
* This function is called whenever deauthentication has been processed in
* station mode. This includes both received deauthentication frames and
- * locally generated ones.
+ * locally generated ones. This function may sleep.
*/
-void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
+void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len,
+ void *cookie);
/**
* cfg80211_send_disassoc - notification of processed disassociation
* @dev: network device
* @buf: disassociation response frame (header + body)
* @len: length of the frame data
+ * @cookie: cookie from ->disassoc if called within that callback,
+ * %NULL otherwise
*
* This function is called whenever disassociation has been processed in
* station mode. This includes both received disassociation frames and locally
- * generated ones.
- */
-void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);
-
-/**
- * cfg80211_hold_bss - exclude bss from expiration
- * @bss: bss which should not expire
- *
- * In a case when the BSS is not updated but it shouldn't expire this
- * function can be used to mark the BSS to be excluded from expiration.
+ * generated ones. This function may sleep.
*/
-void cfg80211_hold_bss(struct cfg80211_bss *bss);
-
-/**
- * cfg80211_unhold_bss - remove expiration exception from the BSS
- * @bss: bss which can expire again
- *
- * This function marks the BSS to be expirable again.
- */
-void cfg80211_unhold_bss(struct cfg80211_bss *bss);
+void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len,
+ void *cookie);
/**
* cfg80211_michael_mic_failure - notification of Michael MIC failure (TKIP)
* @key_type: The key type that the received frame used
* @key_id: Key identifier (0..3)
* @tsc: The TSC value of the frame that generated the MIC failure (6 octets)
+ * @gfp: allocation flags
*
* This function is called whenever the local MAC detects a MIC failure in a
* received frame. This matches with MLME-MICHAELMICFAILURE.indication()
*/
void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
enum nl80211_key_type key_type, int key_id,
- const u8 *tsc);
+ const u8 *tsc, gfp_t gfp);
/**
* cfg80211_ibss_joined - notify cfg80211 that device joined an IBSS
*/
void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
+#ifdef CONFIG_NL80211_TESTMODE
+/**
+ * cfg80211_testmode_alloc_reply_skb - allocate testmode reply
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ * be put into the skb
+ *
+ * This function allocates and pre-fills an skb for a reply to
+ * the testmode command. Since it is intended for a reply, calling
+ * it outside of the @testmode_cmd operation is invalid.
+ *
+ * The returned skb (or %NULL if any errors happen) is pre-filled
+ * with the wiphy index and set up in a way that any data that is
+ * put into the skb (with skb_put(), nla_put() or similar) will end
+ * up being within the %NL80211_ATTR_TESTDATA attribute, so all that
+ * needs to be done with the skb is adding data for the corresponding
+ * userspace tool which can then read that data out of the testdata
+ * attribute. You must not modify the skb in any other way.
+ *
+ * When done, call cfg80211_testmode_reply() with the skb and return
+ * its error code as the result of the @testmode_cmd operation.
+ */
+struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
+ int approxlen);
+
+/**
+ * cfg80211_testmode_reply - send the reply skb
+ * @skb: The skb, must have been allocated with
+ * cfg80211_testmode_alloc_reply_skb()
+ *
+ * Returns an error code or 0 on success, since calling this
+ * function will usually be the last thing before returning
+ * from the @testmode_cmd you should return the error code.
+ * Note that this function consumes the skb regardless of the
+ * return value.
+ */
+int cfg80211_testmode_reply(struct sk_buff *skb);
+
+/**
+ * cfg80211_testmode_alloc_event_skb - allocate testmode event
+ * @wiphy: the wiphy
+ * @approxlen: an upper bound of the length of the data that will
+ * be put into the skb
+ * @gfp: allocation flags
+ *
+ * This function allocates and pre-fills an skb for an event on the
+ * testmode multicast group.
+ *
+ * The returned skb (or %NULL if any errors happen) is set up in the
+ * same way as with cfg80211_testmode_alloc_reply_skb() but prepared
+ * for an event. As there, you should simply add data to it that will
+ * then end up in the %NL80211_ATTR_TESTDATA attribute. Again, you must
+ * not modify the skb in any other way.
+ *
+ * When done filling the skb, call cfg80211_testmode_event() with the
+ * skb to send the event.
+ */
+struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
+ int approxlen, gfp_t gfp);
+
+/**
+ * cfg80211_testmode_event - send the event
+ * @skb: The skb, must have been allocated with
+ * cfg80211_testmode_alloc_event_skb()
+ * @gfp: allocation flags
+ *
+ * This function sends the given @skb, which must have been allocated
+ * by cfg80211_testmode_alloc_event_skb(), as an event. It always
+ * consumes it.
+ */
+void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp);
+
+#define CFG80211_TESTMODE_CMD(cmd) .testmode_cmd = (cmd),
+#else
+#define CFG80211_TESTMODE_CMD(cmd)
+#endif
+
+/**
+ * cfg80211_connect_result - notify cfg80211 of connection result
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the AP
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @status: status code, 0 for successful connection, use
+ * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
+ * the real status code for failures.
+ * @gfp: allocation flags
+ *
+ * It should be called by the underlying driver whenever connect() has
+ * succeeded.
+ */
+void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len,
+ u16 status, gfp_t gfp);
+
+/**
+ * cfg80211_roamed - notify cfg80211 of roaming
+ *
+ * @dev: network device
+ * @bssid: the BSSID of the new AP
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @gfp: allocation flags
+ *
+ * It should be called by the underlying driver whenever it roamed
+ * from one AP to another while connected.
+ */
+void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
+
+/**
+ * cfg80211_disconnected - notify cfg80211 that connection was dropped
+ *
+ * @dev: network device
+ * @ie: information elements of the deauth/disassoc frame (may be %NULL)
+ * @ie_len: length of IEs
+ * @reason: reason code for the disconnection, set it to 0 if unknown
+ * @gfp: allocation flags
+ *
+ * After it calls this function, the driver should enter an idle state
+ * and not try to connect to any AP any more.
+ */
+void cfg80211_disconnected(struct net_device *dev, u16 reason,
+ u8 *ie, size_t ie_len, gfp_t gfp);
+
+
#endif /* __NET_CFG80211_H */
ARPHRD_PHONET_PIPE, ARPHRD_IEEE802154, ARPHRD_IEEE802154_PHY,
ARPHRD_VOID, ARPHRD_NONE};
-static const char *netdev_lock_name[] =
+static const char *const netdev_lock_name[] =
{"_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25",
"_xmit_PRONET", "_xmit_CHAOS", "_xmit_IEEE802", "_xmit_ARCNET",
"_xmit_APPLETLK", "_xmit_DLCI", "_xmit_ATM", "_xmit_METRICOM",
skb_dst_drop(skb);
rc = ops->ndo_start_xmit(skb, dev);
- if (rc == 0)
+ if (rc == NETDEV_TX_OK)
txq_trans_update(txq);
/*
* TODO: if skb_orphan() was called by
skb->next = nskb->next;
nskb->next = NULL;
rc = ops->ndo_start_xmit(nskb, dev);
- if (unlikely(rc)) {
+ if (unlikely(rc != NETDEV_TX_OK)) {
nskb->next = skb->next;
skb->next = nskb;
return rc;
out_kfree_skb:
kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
static u32 skb_tx_hashrnd;
return netdev_get_tx_queue(dev, queue_index);
}
+static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
+ struct net_device *dev,
+ struct netdev_queue *txq)
+{
+ spinlock_t *root_lock = qdisc_lock(q);
+ int rc;
+
+ spin_lock(root_lock);
+ if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {
+ kfree_skb(skb);
+ rc = NET_XMIT_DROP;
+ } else if ((q->flags & TCQ_F_CAN_BYPASS) && !qdisc_qlen(q) &&
+ !test_and_set_bit(__QDISC_STATE_RUNNING, &q->state)) {
+ /*
+ * This is a work-conserving queue; there are no old skbs
+ * waiting to be sent out; and the qdisc is not running -
+ * xmit the skb directly.
+ */
+ __qdisc_update_bstats(q, skb->len);
+ if (sch_direct_xmit(skb, q, dev, txq, root_lock))
+ __qdisc_run(q);
+ else
+ clear_bit(__QDISC_STATE_RUNNING, &q->state);
+
+ rc = NET_XMIT_SUCCESS;
+ } else {
+ rc = qdisc_enqueue_root(skb, q);
+ qdisc_run(q);
+ }
+ spin_unlock(root_lock);
+
+ return rc;
+}
+
/**
* dev_queue_xmit - transmit a buffer
* @skb: buffer to transmit
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
#endif
if (q->enqueue) {
- spinlock_t *root_lock = qdisc_lock(q);
-
- spin_lock(root_lock);
-
- if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED, &q->state))) {
- kfree_skb(skb);
- rc = NET_XMIT_DROP;
- } else {
- rc = qdisc_enqueue_root(skb, q);
- qdisc_run(q);
- }
- spin_unlock(root_lock);
-
+ rc = __dev_xmit_skb(skb, q, dev, txq);
goto out;
}
ASSERT_RTNL();
+ netif_addr_lock_bh(dev);
err = __hw_addr_del(&dev->uc, addr, dev->addr_len,
NETDEV_HW_ADDR_T_UNICAST);
if (!err)
__dev_set_rx_mode(dev);
+ netif_addr_unlock_bh(dev);
return err;
}
EXPORT_SYMBOL(dev_unicast_delete);
ASSERT_RTNL();
+ netif_addr_lock_bh(dev);
err = __hw_addr_add(&dev->uc, addr, dev->addr_len,
NETDEV_HW_ADDR_T_UNICAST);
if (!err)
__dev_set_rx_mode(dev);
+ netif_addr_unlock_bh(dev);
return err;
}
EXPORT_SYMBOL(dev_unicast_add);
}
return err;
}
+EXPORT_SYMBOL_GPL(__dev_addr_sync);
void __dev_addr_unsync(struct dev_addr_list **to, int *to_count,
struct dev_addr_list **from, int *from_count)
da = next;
}
}
+EXPORT_SYMBOL_GPL(__dev_addr_unsync);
/**
* dev_unicast_sync - Synchronize device's unicast list to another device
* @from: source device
*
* Add newly added addresses to the destination device and release
- * addresses that have no users left.
+ * addresses that have no users left. The source device must be
+ * locked by netif_tx_lock_bh.
*
* This function is intended to be called from the dev->set_rx_mode
* function of layered software devices.
{
int err = 0;
- ASSERT_RTNL();
-
if (to->addr_len != from->addr_len)
return -EINVAL;
+ netif_addr_lock_bh(to);
err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
if (!err)
__dev_set_rx_mode(to);
+ netif_addr_unlock_bh(to);
return err;
}
EXPORT_SYMBOL(dev_unicast_sync);
*/
void dev_unicast_unsync(struct net_device *to, struct net_device *from)
{
- ASSERT_RTNL();
-
if (to->addr_len != from->addr_len)
return;
+ netif_addr_lock_bh(from);
+ netif_addr_lock(to);
__hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
__dev_set_rx_mode(to);
+ netif_addr_unlock(to);
+ netif_addr_unlock_bh(from);
}
EXPORT_SYMBOL(dev_unicast_unsync);
static void dev_unicast_flush(struct net_device *dev)
{
- /* rtnl_mutex must be held here */
-
+ netif_addr_lock_bh(dev);
__hw_addr_flush(&dev->uc);
+ netif_addr_unlock_bh(dev);
}
static void dev_unicast_init(struct net_device *dev)
{
- /* rtnl_mutex must be held here */
-
__hw_addr_init(&dev->uc);
}
out:
return err;
}
+EXPORT_SYMBOL_GPL(dev_change_net_namespace);
static int dev_cpu_callback(struct notifier_block *nfb,
unsigned long action,
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/idr.h>
+#include <linux/rculist.h>
+#include <linux/nsproxy.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
rv = setup_net(net);
if (rv == 0) {
rtnl_lock();
- list_add_tail(&net->list, &net_namespace_list);
+ list_add_tail_rcu(&net->list, &net_namespace_list);
rtnl_unlock();
}
mutex_unlock(&net_mutex);
/* Don't let anyone else find us. */
rtnl_lock();
- list_del(&net->list);
+ list_del_rcu(&net->list);
rtnl_unlock();
+ /*
+ * Another CPU might be rcu-iterating the list, wait for it.
+ * This needs to be before calling the exit() notifiers, so
+ * the rcu_barrier() below isn't sufficient alone.
+ */
+ synchronize_rcu();
+
/* Run all of the network namespace exit methods */
list_for_each_entry_reverse(ops, &pernet_list, list) {
if (ops->exit)
}
#endif
+struct net *get_net_ns_by_pid(pid_t pid)
+{
+ struct task_struct *tsk;
+ struct net *net;
+
+ /* Lookup the network namespace */
+ net = ERR_PTR(-ESRCH);
+ rcu_read_lock();
+ tsk = find_task_by_vpid(pid);
+ if (tsk) {
+ struct nsproxy *nsproxy;
+ nsproxy = task_nsproxy(tsk);
+ if (nsproxy)
+ net = get_net(nsproxy->net_ns);
+ }
+ rcu_read_unlock();
+ return net;
+}
+EXPORT_SYMBOL_GPL(get_net_ns_by_pid);
+
static int __init net_ns_init(void)
{
struct net_generic *ng;
panic("Could not setup the initial network namespace");
rtnl_lock();
- list_add_tail(&init_net.list, &net_namespace_list);
+ list_add_tail_rcu(&init_net.list, &net_namespace_list);
rtnl_unlock();
mutex_unlock(&net_mutex);
*/
ng->len = id;
- memcpy(&ng->ptr, &old_ng->ptr, old_ng->len);
+ memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
rcu_assign_pointer(net->gen, ng);
call_rcu(&old_ng->rcu, net_generic_release);
const char *dccp_packet_name(const int type)
{
- static const char *dccp_packet_names[] = {
+ static const char *const dccp_packet_names[] = {
[DCCP_PKT_REQUEST] = "REQUEST",
[DCCP_PKT_RESPONSE] = "RESPONSE",
[DCCP_PKT_DATA] = "DATA",
const char *dccp_state_name(const int state)
{
- static char *dccp_state_names[] = {
+ static const char *const dccp_state_names[] = {
[DCCP_OPEN] = "OPEN",
[DCCP_REQUESTING] = "REQUESTING",
[DCCP_PARTOPEN] = "PARTOPEN",
(dccp_hashinfo.ehash_size - 1))
dccp_hashinfo.ehash_size--;
dccp_hashinfo.ehash = (struct inet_ehash_bucket *)
- __get_free_pages(GFP_ATOMIC, ehash_order);
+ __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, ehash_order);
} while (!dccp_hashinfo.ehash && --ehash_order > 0);
if (!dccp_hashinfo.ehash) {
bhash_order > 0)
continue;
dccp_hashinfo.bhash = (struct inet_bind_hashbucket *)
- __get_free_pages(GFP_ATOMIC, bhash_order);
+ __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, bhash_order);
} while (!dccp_hashinfo.bhash && --bhash_order >= 0);
if (!dccp_hashinfo.bhash) {
kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
dccp_ackvec_exit();
dccp_sysctl_exit();
+ percpu_counter_destroy(&dccp_orphan_count);
}
module_init(dccp_init);
if (peer)
return -EOPNOTSUPP;
+ memset(sec, 0, sizeof(*sec));
mutex_lock(&econet_mutex);
sk = sock->sk;
skb->protocol = htons(ETH_P_IP);
skb_pull(skb, sizeof(struct ec_framehdr));
netif_rx(skb);
- return 0;
+ return NET_RX_SUCCESS;
}
sk = ec_listening_socket(hdr->port, hdr->src_stn, hdr->src_net);
hdr->port))
goto drop;
- return 0;
+ return NET_RX_SUCCESS;
drop:
kfree_skb(skb);
#include <net/tcp_states.h>
#include <net/route.h>
-#include <net/ieee802154/af_ieee802154.h>
-#include <net/ieee802154/netdevice.h>
+#include <net/af_ieee802154.h>
+#include <net/ieee802154_netdev.h>
#include "af802154.h"
unsigned int cmd)
{
struct ifreq ifr;
- int ret = -EINVAL;
+ int ret = -ENOIOCTLCMD;
struct net_device *dev;
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
dev_load(sock_net(sk), ifr.ifr_name);
dev = dev_get_by_name(sock_net(sk), ifr.ifr_name);
- if (dev->type == ARPHRD_IEEE802154 ||
- dev->type == ARPHRD_IEEE802154_PHY)
+
+ if ((dev->type == ARPHRD_IEEE802154 ||
+ dev->type == ARPHRD_IEEE802154_PHY) &&
+ dev->netdev_ops->ndo_do_ioctl)
ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd);
if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
#include <linux/if_arp.h>
#include <linux/list.h>
#include <net/sock.h>
-#include <net/ieee802154/af_ieee802154.h>
-#include <net/ieee802154/mac_def.h>
-#include <net/ieee802154/netdevice.h>
+#include <net/af_ieee802154.h>
+#include <net/ieee802154.h>
+#include <net/ieee802154_netdev.h>
#include <asm/ioctls.h>
return ret;
}
+ static int dgram_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+ {
+ return -EOPNOTSUPP;
+ }
+
+ static int dgram_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user optlen)
+ {
+ return -EOPNOTSUPP;
+ }
+
struct proto ieee802154_dgram_prot = {
.name = "IEEE-802.15.4-MAC",
.owner = THIS_MODULE,
.connect = dgram_connect,
.disconnect = dgram_disconnect,
.ioctl = dgram_ioctl,
+ .getsockopt = dgram_getsockopt,
+ .setsockopt = dgram_setsockopt,
};
#include <linux/if_arp.h>
#include <linux/list.h>
#include <net/sock.h>
-#include <net/ieee802154/af_ieee802154.h>
+#include <net/af_ieee802154.h>
#include "af802154.h"
read_unlock(&raw_lock);
}
+ static int raw_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen)
+ {
+ return -EOPNOTSUPP;
+ }
+
+ static int raw_setsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user optlen)
+ {
+ return -EOPNOTSUPP;
+ }
+
struct proto ieee802154_raw_prot = {
.name = "IEEE-802.15.4-RAW",
.owner = THIS_MODULE,
.unhash = raw_unhash,
.connect = raw_connect,
.disconnect = raw_disconnect,
+ .getsockopt = raw_getsockopt,
+ .setsockopt = raw_setsockopt,
};
*/
static const struct ieee80211_regdomain *country_ie_regdomain;
+/*
+ * Protects static reg.c components:
+ * - cfg80211_world_regdom
+ * - cfg80211_regdom
+ * - country_ie_regdomain
+ * - last_request
+ */
+DEFINE_MUTEX(reg_mutex);
+#define assert_reg_lock() WARN_ON(!mutex_is_locked(®_mutex))
+
/* Used to queue up regulatory hints */
static LIST_HEAD(reg_requests_list);
static spinlock_t reg_requests_lock;
static const struct ieee80211_regdomain *cfg80211_world_regdom =
&world_regdom;
-#ifdef CONFIG_WIRELESS_OLD_REGULATORY
-static char *ieee80211_regdom = "US";
-#else
static char *ieee80211_regdom = "00";
-#endif
module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
- list_for_each_entry(drv, &cfg80211_drv_list, list)
- wiphy_update_regulatory(&drv->wiphy, initiator);
+ list_for_each_entry(rdev, &cfg80211_rdev_list, list)
+ wiphy_update_regulatory(&rdev->wiphy, initiator);
}
static void handle_reg_beacon(struct wiphy *wiphy,
chan->beacon_found = true;
+ if (wiphy->disable_beacon_hints)
+ return;
+
chan_before.center_freq = chan->center_freq;
chan_before.flags = chan->flags;
- if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
- !(chan->orig_flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
+ if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) {
chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
channel_changed = true;
}
- if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
- !(chan->orig_flags & IEEE80211_CHAN_NO_IBSS)) {
+ if (chan->flags & IEEE80211_CHAN_NO_IBSS) {
chan->flags &= ~IEEE80211_CHAN_NO_IBSS;
channel_changed = true;
}
struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan;
- assert_cfg80211_lock();
+ assert_reg_lock();
sband = wiphy->bands[band];
BUG_ON(chan_idx >= sband->n_channels);
enum ieee80211_band band;
unsigned int bands_set = 0;
- mutex_lock(&cfg80211_mutex);
+ mutex_lock(®_mutex);
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (!wiphy->bands[band])
continue;
handle_band_custom(wiphy, band, regd);
bands_set++;
}
- mutex_unlock(&cfg80211_mutex);
+ mutex_unlock(®_mutex);
/*
* no point in calling this if it won't have any effect
* Returns zero if all went fine, %-EALREADY if a regulatory domain had
* already been set or other standard error codes.
*
- * Caller must hold &cfg80211_mutex
+ * Caller must hold &cfg80211_mutex and ®_mutex
*/
static int __regulatory_hint(struct wiphy *wiphy,
struct regulatory_request *pending_request)
BUG_ON(!reg_request->alpha2);
mutex_lock(&cfg80211_mutex);
+ mutex_lock(®_mutex);
if (wiphy_idx_valid(reg_request->wiphy_idx))
wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx);
if (r == -EALREADY && wiphy && wiphy->strict_regulatory)
wiphy_update_regulatory(wiphy, reg_request->initiator);
out:
+ mutex_unlock(®_mutex);
mutex_unlock(&cfg80211_mutex);
}
/* Processes beacon hints -- this has nothing to do with country IEs */
static void reg_process_pending_beacon_hints(void)
{
- struct cfg80211_registered_device *drv;
+ struct cfg80211_registered_device *rdev;
struct reg_beacon *pending_beacon, *tmp;
+ /*
+ * No need to hold the reg_mutex here as we just touch wiphys
+ * and do not read or access regulatory variables.
+ */
mutex_lock(&cfg80211_mutex);
/* This goes through the _pending_ beacon list */
list_del_init(&pending_beacon->list);
/* Applies the beacon hint to current wiphys */
- list_for_each_entry(drv, &cfg80211_drv_list, list)
- wiphy_update_new_beacon(&drv->wiphy, pending_beacon);
+ list_for_each_entry(rdev, &cfg80211_rdev_list, list)
+ wiphy_update_new_beacon(&rdev->wiphy, pending_beacon);
/* Remembers the beacon hint for new wiphys or reg changes */
list_add_tail(&pending_beacon->list, ®_beacon_list);
}
EXPORT_SYMBOL(regulatory_hint);
+/* Caller must hold reg_mutex */
static bool reg_same_country_ie_hint(struct wiphy *wiphy,
u32 country_ie_checksum)
{
struct wiphy *request_wiphy;
- assert_cfg80211_lock();
+ assert_reg_lock();
if (unlikely(last_request->initiator !=
NL80211_REGDOM_SET_BY_COUNTRY_IE))
return false;
}
+/*
+ * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
+ * therefore cannot iterate over the rdev list here.
+ */
void regulatory_hint_11d(struct wiphy *wiphy,
u8 *country_ie,
u8 country_ie_len)
enum environment_cap env = ENVIRON_ANY;
struct regulatory_request *request;
- mutex_lock(&cfg80211_mutex);
+ mutex_lock(®_mutex);
- if (unlikely(!last_request)) {
- mutex_unlock(&cfg80211_mutex);
- return;
- }
+ if (unlikely(!last_request))
+ goto out;
/* IE len must be evenly divisible by 2 */
if (country_ie_len & 0x01)
env = ENVIRON_OUTDOOR;
/*
- * We will run this for *every* beacon processed for the BSSID, so
- * we optimize an early check to exit out early if we don't have to
- * do anything
+ * We will run this only upon a successful connection on cfg80211.
+ * We leave conflict resolution to the workqueue, where can hold
+ * cfg80211_mutex.
*/
if (likely(last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE &&
- wiphy_idx_valid(last_request->wiphy_idx))) {
- struct cfg80211_registered_device *drv_last_ie;
-
- drv_last_ie =
- cfg80211_drv_by_wiphy_idx(last_request->wiphy_idx);
-
- /*
- * Lets keep this simple -- we trust the first AP
- * after we intersect with CRDA
- */
- if (likely(&drv_last_ie->wiphy == wiphy)) {
- /*
- * Ignore IEs coming in on this wiphy with
- * the same alpha2 and environment cap
- */
- if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
- alpha2) &&
- env == drv_last_ie->env)) {
- goto out;
- }
- /*
- * the wiphy moved on to another BSSID or the AP
- * was reconfigured. XXX: We need to deal with the
- * case where the user suspends and goes to goes
- * to another country, and then gets IEs from an
- * AP with different settings
- */
- goto out;
- } else {
- /*
- * Ignore IEs coming in on two separate wiphys with
- * the same alpha2 and environment cap
- */
- if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2,
- alpha2) &&
- env == drv_last_ie->env)) {
- goto out;
- }
- /* We could potentially intersect though */
- goto out;
- }
- }
+ wiphy_idx_valid(last_request->wiphy_idx)))
+ goto out;
rd = country_ie_2_rd(country_ie, country_ie_len, &checksum);
if (!rd)
request->country_ie_checksum = checksum;
request->country_ie_env = env;
- mutex_unlock(&cfg80211_mutex);
+ mutex_unlock(®_mutex);
queue_regulatory_request(request);
free_rd_out:
kfree(rd);
out:
- mutex_unlock(&cfg80211_mutex);
+ mutex_unlock(®_mutex);
}
-EXPORT_SYMBOL(regulatory_hint_11d);
static bool freq_is_chan_12_13_14(u16 freq)
{
if (last_request->initiator ==
NL80211_REGDOM_SET_BY_COUNTRY_IE) {
- struct cfg80211_registered_device *drv;
- drv = cfg80211_drv_by_wiphy_idx(
+ struct cfg80211_registered_device *rdev;
+ rdev = cfg80211_rdev_by_wiphy_idx(
last_request->wiphy_idx);
- if (drv) {
+ if (rdev) {
printk(KERN_INFO "cfg80211: Current regulatory "
"domain updated by AP to: %c%c\n",
- drv->country_ie_alpha2[0],
- drv->country_ie_alpha2[1]);
+ rdev->country_ie_alpha2[0],
+ rdev->country_ie_alpha2[1]);
} else
printk(KERN_INFO "cfg80211: Current regulatory "
"domain intersected: \n");
static int __set_regdom(const struct ieee80211_regdomain *rd)
{
const struct ieee80211_regdomain *intersected_rd = NULL;
- struct cfg80211_registered_device *drv = NULL;
+ struct cfg80211_registered_device *rdev = NULL;
struct wiphy *request_wiphy;
/* Some basic sanity checks first */
if (!intersected_rd)
return -EINVAL;
- drv = wiphy_to_dev(request_wiphy);
+ rdev = wiphy_to_dev(request_wiphy);
- drv->country_ie_alpha2[0] = rd->alpha2[0];
- drv->country_ie_alpha2[1] = rd->alpha2[1];
- drv->env = last_request->country_ie_env;
+ rdev->country_ie_alpha2[0] = rd->alpha2[0];
+ rdev->country_ie_alpha2[1] = rd->alpha2[1];
+ rdev->env = last_request->country_ie_env;
BUG_ON(intersected_rd == rd);
assert_cfg80211_lock();
+ mutex_lock(®_mutex);
+
/* Note that this doesn't update the wiphys, this is done below */
r = __set_regdom(rd);
if (r) {
kfree(rd);
+ mutex_unlock(®_mutex);
return r;
}
nl80211_send_reg_change_event(last_request);
+ mutex_unlock(®_mutex);
+
return r;
}
assert_cfg80211_lock();
+ mutex_lock(®_mutex);
+
kfree(wiphy->regd);
if (last_request)
request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
if (!request_wiphy || request_wiphy != wiphy)
- return;
+ goto out;
last_request->wiphy_idx = WIPHY_IDX_STALE;
last_request->country_ie_env = ENVIRON_ANY;
+out:
+ mutex_unlock(®_mutex);
}
int regulatory_init(void)
printk(KERN_INFO "cfg80211: Using static regulatory domain info\n");
print_regdomain_info(cfg80211_regdomain);
- /*
- * The old code still requests for a new regdomain and if
- * you have CRDA you get it updated, otherwise you get
- * stuck with the static values. Since "EU" is not a valid
- * ISO / IEC 3166 alpha2 code we can't expect userpace to
- * give us a regulatory domain for it. We need last_request
- * iniitalized though so lets just send a request which we
- * know will be ignored... this crap will be removed once
- * OLD_REG dies.
- */
- err = regulatory_hint_core(ieee80211_regdom);
#else
cfg80211_regdomain = cfg80211_world_regdom;
- err = regulatory_hint_core(ieee80211_regdom);
#endif
+ /* We always try to get an update for the static regdomain */
+ err = regulatory_hint_core(cfg80211_regdomain->alpha2);
if (err) {
if (err == -ENOMEM)
return err;
#endif
}
+ /*
+ * Finally, if the user set the module parameter treat it
+ * as a user hint.
+ */
+ if (!is_world_regdom(ieee80211_regdom))
+ regulatory_hint_user(ieee80211_regdom);
+
return 0;
}
cancel_work_sync(®_work);
mutex_lock(&cfg80211_mutex);
+ mutex_lock(®_mutex);
reset_regdomains();
}
spin_unlock(®_requests_lock);
+ mutex_unlock(®_mutex);
mutex_unlock(&cfg80211_mutex);
}
* non-radar 5 GHz channels.
*
* Drivers do not need to call this, cfg80211 will do it for after a scan
- * on a newly found BSS.
+ * on a newly found BSS. If you cannot make use of this feature you can
+ * set the wiphy->disable_beacon_hints to true.
*/
int regulatory_hint_found_beacon(struct wiphy *wiphy,
struct ieee80211_channel *beacon_chan,
gfp_t gfp);
+/**
+ * regulatory_hint_11d - hints a country IE as a regulatory domain
+ * @wiphy: the wireless device giving the hint (used only for reporting
+ * conflicts)
+ * @country_ie: pointer to the country IE
+ * @country_ie_len: length of the country IE
+ *
+ * We will intersect the rd with the what CRDA tells us should apply
+ * for the alpha2 this country IE belongs to, this prevents APs from
+ * sending us incorrect or outdated information against a country.
+ */
+void regulatory_hint_11d(struct wiphy *wiphy,
+ u8 *country_ie,
+ u8 country_ie_len);
+
#endif /* __NET_WIRELESS_REG_H */
#include <net/iw_handler.h>
#include "core.h"
#include "nl80211.h"
+#include "wext-compat.h"
-#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
+#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
-void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
+void __cfg80211_scan_done(struct work_struct *wk)
{
+ struct cfg80211_registered_device *rdev;
+ struct cfg80211_scan_request *request;
struct net_device *dev;
#ifdef CONFIG_WIRELESS_EXT
union iwreq_data wrqu;
#endif
- dev = dev_get_by_index(&init_net, request->ifidx);
- if (!dev)
- goto out;
+ rdev = container_of(wk, struct cfg80211_registered_device,
+ scan_done_wk);
- WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
+ mutex_lock(&rdev->mtx);
+ request = rdev->scan_req;
+
+ dev = request->dev;
- if (aborted)
+ /*
+ * This must be before sending the other events!
+ * Otherwise, wpa_supplicant gets completely confused with
+ * wext events.
+ */
+ cfg80211_sme_scan_done(dev);
+
+ if (request->aborted)
nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev);
else
nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
#ifdef CONFIG_WIRELESS_EXT
- if (!aborted) {
+ if (!request->aborted) {
memset(&wrqu, 0, sizeof(wrqu));
wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
dev_put(dev);
- out:
+ cfg80211_unlock_rdev(rdev);
wiphy_to_dev(request->wiphy)->scan_req = NULL;
kfree(request);
}
+
+void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
+{
+ WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
+
+ request->aborted = aborted;
+ schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk);
+}
EXPORT_SYMBOL(cfg80211_scan_done);
static void bss_release(struct kref *ref)
if (bss->ies_allocated)
kfree(bss->pub.information_elements);
+ BUG_ON(atomic_read(&bss->hold));
+
kfree(bss);
}
bool expired = false;
list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) {
- if (bss->hold ||
- !time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
+ if (atomic_read(&bss->hold))
+ continue;
+ if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
continue;
list_del(&bss->list);
rb_erase(&bss->rbn, &dev->bss_tree);
if (!ie1 && !ie2)
return 0;
- if (!ie1)
+ if (!ie1 || !ie2)
return -1;
r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1]));
ie = find_ie(WLAN_EID_MESH_CONFIG,
a->information_elements,
a->len_information_elements);
+ if (!ie)
+ return false;
if (ie[1] != IEEE80211_MESH_CONFIG_LEN)
return false;
}
EXPORT_SYMBOL(cfg80211_unlink_bss);
-void cfg80211_hold_bss(struct cfg80211_bss *pub)
-{
- struct cfg80211_internal_bss *bss;
-
- if (!pub)
- return;
-
- bss = container_of(pub, struct cfg80211_internal_bss, pub);
- bss->hold = true;
-}
-EXPORT_SYMBOL(cfg80211_hold_bss);
-
-void cfg80211_unhold_bss(struct cfg80211_bss *pub)
-{
- struct cfg80211_internal_bss *bss;
-
- if (!pub)
- return;
-
- bss = container_of(pub, struct cfg80211_internal_bss, pub);
- bss->hold = false;
-}
-EXPORT_SYMBOL(cfg80211_unhold_bss);
-
#ifdef CONFIG_WIRELESS_EXT
int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info,
if (!netif_running(dev))
return -ENETDOWN;
- rdev = cfg80211_get_dev_from_ifindex(dev->ifindex);
+ rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
}
creq->wiphy = wiphy;
- creq->ifidx = dev->ifindex;
+ creq->dev = dev;
creq->ssids = (void *)(creq + 1);
creq->channels = (void *)(creq->ssids + 1);
creq->n_channels = n_channels;
if (err) {
rdev->scan_req = NULL;
kfree(creq);
+ } else {
+ nl80211_send_scan_start(rdev, dev);
+ dev_hold(dev);
}
out:
- cfg80211_put_dev(rdev);
+ cfg80211_unlock_rdev(rdev);
return err;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
if (!netif_running(dev))
return -ENETDOWN;
- rdev = cfg80211_get_dev_from_ifindex(dev->ifindex);
+ rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
}
out:
- cfg80211_put_dev(rdev);
+ cfg80211_unlock_rdev(rdev);
return res;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);