From 1e31785cb936146cc18ec58e38d5740531877501 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Wed, 26 Dec 2007 22:46:05 +0100 Subject: [PATCH] --- yaml --- r: 103228 b: refs/heads/master c: 1087f4f4af302e6e2fa40dd741f306444d90bece h: refs/heads/master v: v3 --- [refs] | 2 +- .../feature-removal-schedule.txt | 12 - trunk/Documentation/networking/ip-sysctl.txt | 21 +- trunk/Documentation/networking/s2io.txt | 6 +- trunk/Documentation/rfkill.txt | 547 +--- trunk/MAINTAINERS | 4 + trunk/drivers/connector/connector.c | 40 - trunk/drivers/net/3c59x.c | 5 +- trunk/drivers/net/b44.c | 140 +- trunk/drivers/net/e100.c | 2 - trunk/drivers/net/e1000/e1000_ethtool.c | 2 +- trunk/drivers/net/e1000e/netdev.c | 3 +- trunk/drivers/net/hamradio/dmascc.c | 2 + trunk/drivers/net/igb/igb_main.c | 3 +- trunk/drivers/net/ipg.c | 16 +- trunk/drivers/net/ixgbe/ixgbe_main.c | 3 +- trunk/drivers/net/netxen/netxen_nic_main.c | 18 +- trunk/drivers/net/niu.c | 158 - trunk/drivers/net/pcmcia/axnet_cs.c | 2 - trunk/drivers/net/pcmcia/pcnet_cs.c | 3 - trunk/drivers/net/pppoe.c | 2 +- trunk/drivers/net/ps3_gelic_wireless.c | 30 +- trunk/drivers/net/qla3xxx.c | 2 - trunk/drivers/net/r6040.c | 2 +- trunk/drivers/net/r8169.c | 6 +- trunk/drivers/net/s2io.c | 35 +- trunk/drivers/net/s2io.h | 4 + trunk/drivers/net/tc35815.c | 4 +- trunk/drivers/net/tun.c | 150 +- trunk/drivers/net/wan/x25_asy.c | 3 - trunk/drivers/net/wireless/Kconfig | 24 + trunk/drivers/net/wireless/Makefile | 1 + trunk/drivers/net/wireless/adm8211.c | 9 +- trunk/drivers/net/wireless/airo.c | 84 +- trunk/drivers/net/wireless/ath5k/Kconfig | 3 - trunk/drivers/net/wireless/ath5k/base.c | 263 +- trunk/drivers/net/wireless/ath5k/base.h | 32 +- trunk/drivers/net/wireless/ath5k/hw.c | 4 +- trunk/drivers/net/wireless/atmel.c | 24 +- trunk/drivers/net/wireless/b43/b43.h | 2 - trunk/drivers/net/wireless/b43/debugfs.c | 359 +-- trunk/drivers/net/wireless/b43/debugfs.h | 23 +- trunk/drivers/net/wireless/b43/dma.c | 65 +- trunk/drivers/net/wireless/b43/leds.c | 3 - trunk/drivers/net/wireless/b43/main.c | 98 +- trunk/drivers/net/wireless/b43/main.h | 4 - trunk/drivers/net/wireless/b43/pio.c | 2 +- trunk/drivers/net/wireless/b43/rfkill.c | 7 +- trunk/drivers/net/wireless/b43/xmit.c | 17 +- trunk/drivers/net/wireless/b43legacy/dma.c | 65 +- trunk/drivers/net/wireless/b43legacy/main.c | 6 +- trunk/drivers/net/wireless/b43legacy/rfkill.c | 8 +- trunk/drivers/net/wireless/b43legacy/xmit.c | 16 +- trunk/drivers/net/wireless/hostap/hostap.h | 3 +- trunk/drivers/net/wireless/hostap/hostap_ap.c | 32 +- .../net/wireless/hostap/hostap_ioctl.c | 58 +- trunk/drivers/net/wireless/iwlwifi/Kconfig | 2 +- .../drivers/net/wireless/iwlwifi/iwl-rfkill.c | 18 +- trunk/drivers/net/wireless/iwlwifi/iwl-scan.c | 33 +- .../net/wireless/iwlwifi/iwl3945-base.c | 33 +- trunk/drivers/net/wireless/libertas/scan.c | 36 +- trunk/drivers/net/wireless/mac80211_hwsim.c | 7 +- trunk/drivers/net/wireless/orinoco.c | 30 +- .../drivers/net/wireless/prism54/isl_ioctl.c | 49 +- .../drivers/net/wireless/prism54/islpci_eth.c | 2 +- trunk/drivers/net/wireless/rndis_wlan.c | 32 +- trunk/drivers/net/wireless/rt2x00/rt2400pci.c | 17 +- trunk/drivers/net/wireless/rt2x00/rt2500pci.c | 14 +- trunk/drivers/net/wireless/rt2x00/rt2500usb.c | 40 +- trunk/drivers/net/wireless/rt2x00/rt2x00.h | 60 +- trunk/drivers/net/wireless/rt2x00/rt2x00dev.c | 138 +- trunk/drivers/net/wireless/rt2x00/rt2x00lib.h | 51 +- trunk/drivers/net/wireless/rt2x00/rt2x00mac.c | 4 +- trunk/drivers/net/wireless/rt2x00/rt2x00pci.c | 126 +- trunk/drivers/net/wireless/rt2x00/rt2x00pci.h | 12 + .../drivers/net/wireless/rt2x00/rt2x00queue.c | 141 +- .../drivers/net/wireless/rt2x00/rt2x00queue.h | 35 +- .../net/wireless/rt2x00/rt2x00rfkill.c | 7 +- trunk/drivers/net/wireless/rt2x00/rt2x00usb.c | 103 +- trunk/drivers/net/wireless/rt2x00/rt2x00usb.h | 6 - trunk/drivers/net/wireless/rt2x00/rt61pci.c | 23 +- trunk/drivers/net/wireless/rt2x00/rt73usb.c | 44 +- trunk/drivers/net/wireless/strip.c | 2804 +++++++++++++++++ trunk/drivers/net/wireless/wl3501_cs.c | 10 +- trunk/drivers/net/wireless/zd1201.c | 21 +- trunk/drivers/net/wireless/zd1211rw/zd_mac.c | 22 +- trunk/drivers/ssb/Kconfig | 2 +- trunk/drivers/ssb/main.c | 75 +- trunk/fs/compat_ioctl.c | 113 +- trunk/include/linux/ethtool.h | 33 - trunk/include/linux/ieee80211.h | 64 +- trunk/include/linux/if_tun.h | 10 - trunk/include/linux/igmp.h | 1 + trunk/include/linux/inet_lro.h | 6 +- trunk/include/linux/ipv6.h | 4 - trunk/include/linux/mroute.h | 28 +- trunk/include/linux/mroute6.h | 35 +- trunk/include/linux/netdevice.h | 4 - trunk/include/linux/nl80211.h | 5 +- trunk/include/linux/rfkill.h | 46 +- trunk/include/linux/ssb/ssb.h | 143 +- trunk/include/linux/wireless.h | 28 - trunk/include/net/fib_rules.h | 2 +- trunk/include/net/ipv6.h | 6 - trunk/include/net/iw_handler.h | 151 +- trunk/include/net/mac80211.h | 14 +- trunk/include/net/net_namespace.h | 11 - trunk/include/net/netns/ipv4.h | 4 - trunk/include/net/route.h | 2 +- trunk/include/net/wext.h | 7 - trunk/net/core/dev.c | 6 +- trunk/net/core/ethtool.c | 37 - trunk/net/core/fib_rules.c | 2 +- trunk/net/core/net_namespace.c | 3 - trunk/net/core/skbuff.c | 17 +- trunk/net/decnet/dn_rules.c | 2 +- trunk/net/ieee80211/ieee80211_wx.c | 48 +- trunk/net/ipv4/af_inet.c | 5 +- trunk/net/ipv4/arp.c | 2 +- trunk/net/ipv4/devinet.c | 8 +- trunk/net/ipv4/fib_frontend.c | 17 +- trunk/net/ipv4/fib_hash.c | 6 +- trunk/net/ipv4/fib_rules.c | 4 +- trunk/net/ipv4/fib_trie.c | 6 +- trunk/net/ipv4/inet_fragment.c | 16 +- trunk/net/ipv4/inet_lro.c | 3 +- trunk/net/ipv4/ip_fragment.c | 2 - trunk/net/ipv4/ipmr.c | 28 +- trunk/net/ipv4/route.c | 255 +- trunk/net/ipv4/sysctl_net_ipv4.c | 3 +- trunk/net/ipv4/tcp.c | 9 +- trunk/net/ipv4/tcp_input.c | 46 +- trunk/net/ipv4/tcp_ipv4.c | 6 +- trunk/net/ipv4/tcp_output.c | 7 +- trunk/net/ipv4/tcp_timer.c | 15 +- trunk/net/ipv6/addrconf.c | 53 - trunk/net/ipv6/af_inet6.c | 11 +- trunk/net/ipv6/icmp.c | 3 +- trunk/net/ipv6/ip6_input.c | 12 +- trunk/net/ipv6/ip6_output.c | 10 +- trunk/net/ipv6/ip6mr.c | 38 +- trunk/net/ipv6/ipv6_sockglue.c | 11 +- trunk/net/ipv6/netfilter/ip6table_mangle.c | 2 +- trunk/net/ipv6/netfilter/nf_conntrack_reasm.c | 3 +- trunk/net/ipv6/reassembly.c | 2 - trunk/net/ipv6/route.c | 28 +- trunk/net/ipv6/tcp_ipv6.c | 6 +- trunk/net/mac80211/Kconfig | 2 +- trunk/net/mac80211/ieee80211_i.h | 14 +- trunk/net/mac80211/key.c | 9 - trunk/net/mac80211/key.h | 37 +- trunk/net/mac80211/main.c | 2 +- trunk/net/mac80211/mlme.c | 207 +- trunk/net/mac80211/rx.c | 7 +- trunk/net/mac80211/sta_info.c | 1 - trunk/net/mac80211/sta_info.h | 40 +- trunk/net/mac80211/tkip.c | 30 +- trunk/net/mac80211/tx.c | 204 +- trunk/net/mac80211/wep.c | 39 +- trunk/net/mac80211/wext.c | 50 +- trunk/net/mac80211/wpa.c | 20 +- trunk/net/netlabel/netlabel_unlabeled.c | 2 +- trunk/net/netlink/attr.c | 7 +- trunk/net/rfkill/rfkill-input.c | 98 +- trunk/net/rfkill/rfkill-input.h | 1 - trunk/net/rfkill/rfkill.c | 304 +- trunk/net/sched/Kconfig | 11 + trunk/net/sched/sch_generic.c | 2 +- trunk/net/sctp/socket.c | 16 +- trunk/net/socket.c | 10 - trunk/net/unix/af_unix.c | 52 +- trunk/net/wireless/wext.c | 582 ++-- 172 files changed, 4971 insertions(+), 4661 deletions(-) create mode 100644 trunk/drivers/net/wireless/strip.c diff --git a/[refs] b/[refs] index 6e282b2e5bf0..32d019e3ded6 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 32cb5b4e035e3d7b52f1e9de87920645a00e5234 +refs/heads/master: 1087f4f4af302e6e2fa40dd741f306444d90bece diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 5378511a5f9f..5b3f31faed56 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -312,15 +312,3 @@ When: 2.6.26 Why: Implementation became generic; users should now include linux/semaphore.h instead. Who: Matthew Wilcox - ---------------------------- - -What: SCTP_GET_PEER_ADDRS_NUM_OLD, SCTP_GET_PEER_ADDRS_OLD, - SCTP_GET_LOCAL_ADDRS_NUM_OLD, SCTP_GET_LOCAL_ADDRS_OLD -When: June 2009 -Why: A newer version of the options have been introduced in 2005 that - removes the limitions of the old API. The sctp library has been - converted to use these new options at the same time. Any user - space app that directly uses the old options should convert to using - the new options. -Who: Vlad Yasevich diff --git a/trunk/Documentation/networking/ip-sysctl.txt b/trunk/Documentation/networking/ip-sysctl.txt index 72f6d52e52e6..17a6e46fbd43 100644 --- a/trunk/Documentation/networking/ip-sysctl.txt +++ b/trunk/Documentation/networking/ip-sysctl.txt @@ -548,9 +548,8 @@ icmp_echo_ignore_broadcasts - BOOLEAN icmp_ratelimit - INTEGER Limit the maximal rates for sending ICMP packets whose type matches icmp_ratemask (see below) to specific targets. - 0 to disable any limiting, - otherwise the minimal space between responses in milliseconds. - Default: 1000 + 0 to disable any limiting, otherwise the maximal rate in jiffies(1) + Default: 100 icmp_ratemask - INTEGER Mask made of ICMP types for which rates are being limited. @@ -1025,23 +1024,11 @@ max_addresses - INTEGER autoconfigured addresses. Default: 16 -disable_ipv6 - BOOLEAN - Disable IPv6 operation. - Default: FALSE (enable IPv6 operation) - -accept_dad - INTEGER - Whether to accept DAD (Duplicate Address Detection). - 0: Disable DAD - 1: Enable DAD (default) - 2: Enable DAD, and disable IPv6 operation if MAC-based duplicate - link-local address has been found. - icmp/*: ratelimit - INTEGER Limit the maximal rates for sending ICMPv6 packets. - 0 to disable any limiting, - otherwise the minimal space between responses in milliseconds. - Default: 1000 + 0 to disable any limiting, otherwise the maximal rate in jiffies(1) + Default: 100 IPv6 Update by: diff --git a/trunk/Documentation/networking/s2io.txt b/trunk/Documentation/networking/s2io.txt index 1e28e2ddb90a..4bde53e85f3f 100644 --- a/trunk/Documentation/networking/s2io.txt +++ b/trunk/Documentation/networking/s2io.txt @@ -83,9 +83,9 @@ Valid range: Limited by memory on system Default: 30 e. intr_type -Specifies interrupt type. Possible values 0(INTA), 2(MSI-X) -Valid values: 0, 2 -Default: 2 +Specifies interrupt type. Possible values 1(INTA), 2(MSI), 3(MSI-X) +Valid range: 1-3 +Default: 1 5. Performance suggestions General: diff --git a/trunk/Documentation/rfkill.txt b/trunk/Documentation/rfkill.txt index 0843ed0163a5..a83ff23cd68c 100644 --- a/trunk/Documentation/rfkill.txt +++ b/trunk/Documentation/rfkill.txt @@ -1,528 +1,89 @@ rfkill - RF switch subsystem support ==================================== -1 Introduction -2 Implementation details -3 Kernel driver guidelines -3.1 wireless device drivers -3.2 platform/switch drivers -3.3 input device drivers -4 Kernel API -5 Userspace support - - -1. Introduction: - -The rfkill switch subsystem exists to add a generic interface to circuitry that -can enable or disable the signal output of a wireless *transmitter* of any -type. By far, the most common use is to disable radio-frequency transmitters. - -Note that disabling the signal output means that the the transmitter is to be -made to not emit any energy when "blocked". rfkill is not about blocking data -transmissions, it is about blocking energy emission. - -The rfkill subsystem offers support for keys and switches often found on -laptops to enable wireless devices like WiFi and Bluetooth, so that these keys -and switches actually perform an action in all wireless devices of a given type -attached to the system. - -The buttons to enable and disable the wireless transmitters are important in -situations where the user is for example using his laptop on a location where -radio-frequency transmitters _must_ be disabled (e.g. airplanes). - -Because of this requirement, userspace support for the keys should not be made -mandatory. Because userspace might want to perform some additional smarter -tasks when the key is pressed, rfkill provides userspace the possibility to -take over the task to handle the key events. - -=============================================================================== -2: Implementation details - -The rfkill subsystem is composed of various components: the rfkill class, the -rfkill-input module (an input layer handler), and some specific input layer -events. - -The rfkill class provides kernel drivers with an interface that allows them to -know when they should enable or disable a wireless network device transmitter. -This is enabled by the CONFIG_RFKILL Kconfig option. - -The rfkill class support makes sure userspace will be notified of all state -changes on rfkill devices through uevents. It provides a notification chain -for interested parties in the kernel to also get notified of rfkill state -changes in other drivers. It creates several sysfs entries which can be used -by userspace. See section "Userspace support". - -The rfkill-input module provides the kernel with the ability to implement a -basic response when the user presses a key or button (or toggles a switch) -related to rfkill functionality. It is an in-kernel implementation of default -policy of reacting to rfkill-related input events and neither mandatory nor -required for wireless drivers to operate. It is enabled by the -CONFIG_RFKILL_INPUT Kconfig option. - -rfkill-input is a rfkill-related events input layer handler. This handler will -listen to all rfkill key events and will change the rfkill state of the -wireless devices accordingly. With this option enabled userspace could either -do nothing or simply perform monitoring tasks. - -The rfkill-input module also provides EPO (emergency power-off) functionality -for all wireless transmitters. This function cannot be overridden, and it is -always active. rfkill EPO is related to *_RFKILL_ALL input layer events. - - -Important terms for the rfkill subsystem: - -In order to avoid confusion, we avoid the term "switch" in rfkill when it is -referring to an electronic control circuit that enables or disables a -transmitter. We reserve it for the physical device a human manipulates -(which is an input device, by the way): - -rfkill switch: - - A physical device a human manipulates. Its state can be perceived by - the kernel either directly (through a GPIO pin, ACPI GPE) or by its - effect on a rfkill line of a wireless device. - -rfkill controller: - - A hardware circuit that controls the state of a rfkill line, which a - kernel driver can interact with *to modify* that state (i.e. it has - either write-only or read/write access). - -rfkill line: - - An input channel (hardware or software) of a wireless device, which - causes a wireless transmitter to stop emitting energy (BLOCK) when it - is active. Point of view is extremely important here: rfkill lines are - always seen from the PoV of a wireless device (and its driver). - -soft rfkill line/software rfkill line: - - A rfkill line the wireless device driver can directly change the state - of. Related to rfkill_state RFKILL_STATE_SOFT_BLOCKED. - -hard rfkill line/hardware rfkill line: - - A rfkill line that works fully in hardware or firmware, and that cannot - be overridden by the kernel driver. The hardware device or the - firmware just exports its status to the driver, but it is read-only. - Related to rfkill_state RFKILL_STATE_HARD_BLOCKED. - -The enum rfkill_state describes the rfkill state of a transmitter: - -When a rfkill line or rfkill controller is in the RFKILL_STATE_UNBLOCKED state, -the wireless transmitter (radio TX circuit for example) is *enabled*. When the -it is in the RFKILL_STATE_SOFT_BLOCKED or RFKILL_STATE_HARD_BLOCKED, the -wireless transmitter is to be *blocked* from operating. - -RFKILL_STATE_SOFT_BLOCKED indicates that a call to toggle_radio() can change -that state. RFKILL_STATE_HARD_BLOCKED indicates that a call to toggle_radio() -will not be able to change the state and will return with a suitable error if -attempts are made to set the state to RFKILL_STATE_UNBLOCKED. - -RFKILL_STATE_HARD_BLOCKED is used by drivers to signal that the device is -locked in the BLOCKED state by a hardwire rfkill line (typically an input pin -that, when active, forces the transmitter to be disabled) which the driver -CANNOT override. - -Full rfkill functionality requires two different subsystems to cooperate: the -input layer and the rfkill class. The input layer issues *commands* to the -entire system requesting that devices registered to the rfkill class change -state. The way this interaction happens is not complex, but it is not obvious -either: - -Kernel Input layer: - - * Generates KEY_WWAN, KEY_WLAN, KEY_BLUETOOTH, SW_RFKILL_ALL, and - other such events when the user presses certain keys, buttons, or - toggles certain physical switches. - - THE INPUT LAYER IS NEVER USED TO PROPAGATE STATUS, NOTIFICATIONS OR THE - KIND OF STUFF AN ON-SCREEN-DISPLAY APPLICATION WOULD REPORT. It is - used to issue *commands* for the system to change behaviour, and these - commands may or may not be carried out by some kernel driver or - userspace application. It follows that doing user feedback based only - on input events is broken, as there is no guarantee that an input event - will be acted upon. - - Most wireless communication device drivers implementing rfkill - functionality MUST NOT generate these events, and have no reason to - register themselves with the input layer. Doing otherwise is a common - misconception. There is an API to propagate rfkill status change - information, and it is NOT the input layer. - -rfkill class: - - * Calls a hook in a driver to effectively change the wireless - transmitter state; - * Keeps track of the wireless transmitter state (with help from - the driver); - * Generates userspace notifications (uevents) and a call to a - notification chain (kernel) when there is a wireless transmitter - state change; - * Connects a wireless communications driver with the common rfkill - control system, which, for example, allows actions such as - "switch all bluetooth devices offline" to be carried out by - userspace or by rfkill-input. - - THE RFKILL CLASS NEVER ISSUES INPUT EVENTS. THE RFKILL CLASS DOES - NOT LISTEN TO INPUT EVENTS. NO DRIVER USING THE RFKILL CLASS SHALL - EVER LISTEN TO, OR ACT ON RFKILL INPUT EVENTS. Doing otherwise is - a layering violation. - - Most wireless data communication drivers in the kernel have just to - implement the rfkill class API to work properly. Interfacing to the - input layer is not often required (and is very often a *bug*) on - wireless drivers. - - Platform drivers often have to attach to the input layer to *issue* - (but never to listen to) rfkill events for rfkill switches, and also to - the rfkill class to export a control interface for the platform rfkill - controllers to the rfkill subsystem. This does NOT mean the rfkill - switch is attached to a rfkill class (doing so is almost always wrong). - It just means the same kernel module is the driver for different - devices (rfkill switches and rfkill controllers). - - -Userspace input handlers (uevents) or kernel input handlers (rfkill-input): - - * Implements the policy of what should happen when one of the input - layer events related to rfkill operation is received. - * Uses the sysfs interface (userspace) or private rfkill API calls - to tell the devices registered with the rfkill class to change - their state (i.e. translates the input layer event into real - action). - * rfkill-input implements EPO by handling EV_SW SW_RFKILL_ALL 0 - (power off all transmitters) in a special way: it ignores any - overrides and local state cache and forces all transmitters to the - RFKILL_STATE_SOFT_BLOCKED state (including those which are already - supposed to be BLOCKED). Note that the opposite event (power on all - transmitters) is handled normally. - -Userspace uevent handler or kernel platform-specific drivers hooked to the -rfkill notifier chain: - - * Taps into the rfkill notifier chain or to KOBJ_CHANGE uevents, - in order to know when a device that is registered with the rfkill - class changes state; - * Issues feedback notifications to the user; - * In the rare platforms where this is required, synthesizes an input - event to command all *OTHER* rfkill devices to also change their - statues when a specific rfkill device changes state. - +1 Implementation details +2 Driver support +3 Userspace support =============================================================================== -3: Kernel driver guidelines - -Remember: point-of-view is everything for a driver that connects to the rfkill -subsystem. All the details below must be measured/perceived from the point of -view of the specific driver being modified. - -The first thing one needs to know is whether his driver should be talking to -the rfkill class or to the input layer. In rare cases (platform drivers), it -could happen that you need to do both, as platform drivers often handle a -variety of devices in the same driver. - -Do not mistake input devices for rfkill controllers. The only type of "rfkill -switch" device that is to be registered with the rfkill class are those -directly controlling the circuits that cause a wireless transmitter to stop -working (or the software equivalent of them), i.e. what we call a rfkill -controller. Every other kind of "rfkill switch" is just an input device and -MUST NOT be registered with the rfkill class. - -A driver should register a device with the rfkill class when ALL of the -following conditions are met (they define a rfkill controller): - -1. The device is/controls a data communications wireless transmitter; - -2. The kernel can interact with the hardware/firmware to CHANGE the wireless - transmitter state (block/unblock TX operation); - -3. The transmitter can be made to not emit any energy when "blocked": - rfkill is not about blocking data transmissions, it is about blocking - energy emission; - -A driver should register a device with the input subsystem to issue -rfkill-related events (KEY_WLAN, KEY_BLUETOOTH, KEY_WWAN, KEY_WIMAX, -SW_RFKILL_ALL, etc) when ALL of the folowing conditions are met: - -1. It is directly related to some physical device the user interacts with, to - command the O.S./firmware/hardware to enable/disable a data communications - wireless transmitter. +1: Implementation details - Examples of the physical device are: buttons, keys and switches the user - will press/touch/slide/switch to enable or disable the wireless - communication device. +The rfkill switch subsystem offers support for keys often found on laptops +to enable wireless devices like WiFi and Bluetooth. -2. It is NOT slaved to another device, i.e. there is no other device that - issues rfkill-related input events in preference to this one. +This is done by providing the user 3 possibilities: + 1 - The rfkill system handles all events; userspace is not aware of events. + 2 - The rfkill system handles all events; userspace is informed about the events. + 3 - The rfkill system does not handle events; userspace handles all events. - Please refer to the corner cases and examples section for more details. - -When in doubt, do not issue input events. For drivers that should generate -input events in some platforms, but not in others (e.g. b43), the best solution -is to NEVER generate input events in the first place. That work should be -deferred to a platform-specific kernel module (which will know when to generate -events through the rfkill notifier chain) or to userspace. This avoids the -usual maintenance problems with DMI whitelisting. - - -Corner cases and examples: -==================================== - -1. If the device is an input device that, because of hardware or firmware, -causes wireless transmitters to be blocked regardless of the kernel's will, it -is still just an input device, and NOT to be registered with the rfkill class. - -2. If the wireless transmitter switch control is read-only, it is an input -device and not to be registered with the rfkill class (and maybe not to be made -an input layer event source either, see below). - -3. If there is some other device driver *closer* to the actual hardware the -user interacted with (the button/switch/key) to issue an input event, THAT is -the device driver that should be issuing input events. - -E.g: - [RFKILL slider switch] -- [GPIO hardware] -- [WLAN card rf-kill input] - (platform driver) (wireless card driver) - -The user is closer to the RFKILL slide switch plaform driver, so the driver -which must issue input events is the platform driver looking at the GPIO -hardware, and NEVER the wireless card driver (which is just a slave). It is -very likely that there are other leaves than just the WLAN card rf-kill input -(e.g. a bluetooth card, etc)... - -On the other hand, some embedded devices do this: +The buttons to enable and disable the wireless radios are important in +situations where the user is for example using his laptop on a location where +wireless radios _must_ be disabled (e.g. airplanes). +Because of this requirement, userspace support for the keys should not be +made mandatory. Because userspace might want to perform some additional smarter +tasks when the key is pressed, rfkill still provides userspace the possibility +to take over the task to handle the key events. - [RFKILL slider switch] -- [WLAN card rf-kill input] - (wireless card driver) +The system inside the kernel has been split into 2 separate sections: + 1 - RFKILL + 2 - RFKILL_INPUT -In this situation, the wireless card driver *could* register itself as an input -device and issue rf-kill related input events... but in order to AVOID the need -for DMI whitelisting, the wireless card driver does NOT do it. Userspace (HAL) -or a platform driver (that exists only on these embedded devices) will do the -dirty job of issuing the input events. +The first option enables rfkill support and will make sure userspace will +be notified of any events through the input device. It also creates several +sysfs entries which can be used by userspace. See section "Userspace support". +The second option provides an rfkill input handler. This handler will +listen to all rfkill key events and will toggle the radio accordingly. +With this option enabled userspace could either do nothing or simply +perform monitoring tasks. -COMMON MISTAKES in kernel drivers, related to rfkill: ==================================== +2: Driver support -1. NEVER confuse input device keys and buttons with input device switches. - - 1a. Switches are always set or reset. They report the current state - (on position or off position). - - 1b. Keys and buttons are either in the pressed or not-pressed state, and - that's it. A "button" that latches down when you press it, and - unlatches when you press it again is in fact a switch as far as input - devices go. - -Add the SW_* events you need for switches, do NOT try to emulate a button using -KEY_* events just because there is no such SW_* event yet. Do NOT try to use, -for example, KEY_BLUETOOTH when you should be using SW_BLUETOOTH instead. - -2. Input device switches (sources of EV_SW events) DO store their current state -(so you *must* initialize it by issuing a gratuitous input layer event on -driver start-up and also when resuming from sleep), and that state CAN be -queried from userspace through IOCTLs. There is no sysfs interface for this, -but that doesn't mean you should break things trying to hook it to the rfkill -class to get a sysfs interface :-) - -3. Do not issue *_RFKILL_ALL events by default, unless you are sure it is the -correct event for your switch/button. These events are emergency power-off -events when they are trying to turn the transmitters off. An example of an -input device which SHOULD generate *_RFKILL_ALL events is the wireless-kill -switch in a laptop which is NOT a hotkey, but a real switch that kills radios -in hardware, even if the O.S. has gone to lunch. An example of an input device -which SHOULD NOT generate *_RFKILL_ALL events by default, is any sort of hot -key that does nothing by itself, as well as any hot key that is type-specific -(e.g. the one for WLAN). - - -3.1 Guidelines for wireless device drivers ------------------------------------------- - -1. Each independent transmitter in a wireless device (usually there is only one -transmitter per device) should have a SINGLE rfkill class attached to it. - -2. If the device does not have any sort of hardware assistance to allow the -driver to rfkill the device, the driver should emulate it by taking all actions -required to silence the transmitter. - -3. If it is impossible to silence the transmitter (i.e. it still emits energy, -even if it is just in brief pulses, when there is no data to transmit and there -is no hardware support to turn it off) do NOT lie to the users. Do not attach -it to a rfkill class. The rfkill subsystem does not deal with data -transmission, it deals with energy emission. If the transmitter is emitting -energy, it is not blocked in rfkill terms. - -4. It doesn't matter if the device has multiple rfkill input lines affecting -the same transmitter, their combined state is to be exported as a single state -per transmitter (see rule 1). - -This rule exists because users of the rfkill subsystem expect to get (and set, -when possible) the overall transmitter rfkill state, not of a particular rfkill -line. - -Example of a WLAN wireless driver connected to the rfkill subsystem: --------------------------------------------------------------------- - -A certain WLAN card has one input pin that causes it to block the transmitter -and makes the status of that input pin available (only for reading!) to the -kernel driver. This is a hard rfkill input line (it cannot be overridden by -the kernel driver). - -The card also has one PCI register that, if manipulated by the driver, causes -it to block the transmitter. This is a soft rfkill input line. - -It has also a thermal protection circuitry that shuts down its transmitter if -the card overheats, and makes the status of that protection available (only for -reading!) to the kernel driver. This is also a hard rfkill input line. - -If either one of these rfkill lines are active, the transmitter is blocked by -the hardware and forced offline. - -The driver should allocate and attach to its struct device *ONE* instance of -the rfkill class (there is only one transmitter). +To build a driver with rfkill subsystem support, the driver should +depend on the Kconfig symbol RFKILL; it should _not_ depend on +RKFILL_INPUT. -It can implement the get_state() hook, and return RFKILL_STATE_HARD_BLOCKED if -either one of its two hard rfkill input lines are active. If the two hard -rfkill lines are inactive, it must return RFKILL_STATE_SOFT_BLOCKED if its soft -rfkill input line is active. Only if none of the rfkill input lines are -active, will it return RFKILL_STATE_UNBLOCKED. +Unless key events trigger an interrupt to which the driver listens, polling +will be required to determine the key state changes. For this the input +layer providers the input-polldev handler. -If it doesn't implement the get_state() hook, it must make sure that its calls -to rfkill_force_state() are enough to keep the status always up-to-date, and it -must do a rfkill_force_state() on resume from sleep. +A driver should implement a few steps to correctly make use of the +rfkill subsystem. First for non-polling drivers: -Every time the driver gets a notification from the card that one of its rfkill -lines changed state (polling might be needed on badly designed cards that don't -generate interrupts for such events), it recomputes the rfkill state as per -above, and calls rfkill_force_state() to update it. - -The driver should implement the toggle_radio() hook, that: - -1. Returns an error if one of the hardware rfkill lines are active, and the -caller asked for RFKILL_STATE_UNBLOCKED. - -2. Activates the soft rfkill line if the caller asked for state -RFKILL_STATE_SOFT_BLOCKED. It should do this even if one of the hard rfkill -lines are active, effectively double-blocking the transmitter. - -3. Deactivates the soft rfkill line if none of the hardware rfkill lines are -active and the caller asked for RFKILL_STATE_UNBLOCKED. - -=============================================================================== -4: Kernel API - -To build a driver with rfkill subsystem support, the driver should depend on -(or select) the Kconfig symbol RFKILL; it should _not_ depend on RKFILL_INPUT. - -The hardware the driver talks to may be write-only (where the current state -of the hardware is unknown), or read-write (where the hardware can be queried -about its current state). - -The rfkill class will call the get_state hook of a device every time it needs -to know the *real* current state of the hardware. This can happen often. - -Some hardware provides events when its status changes. In these cases, it is -best for the driver to not provide a get_state hook, and instead register the -rfkill class *already* with the correct status, and keep it updated using -rfkill_force_state() when it gets an event from the hardware. - -There is no provision for a statically-allocated rfkill struct. You must -use rfkill_allocate() to allocate one. - -You should: - rfkill_allocate() - - modify rfkill fields (flags, name) - - modify state to the current hardware state (THIS IS THE ONLY TIME - YOU CAN ACCESS state DIRECTLY) + - input_allocate_device() - rfkill_register() + - input_register_device() -The only way to set a device to the RFKILL_STATE_HARD_BLOCKED state is through -a suitable return of get_state() or through rfkill_force_state(). - -When a device is in the RFKILL_STATE_HARD_BLOCKED state, the only way to switch -it to a different state is through a suitable return of get_state() or through -rfkill_force_state(). - -If toggle_radio() is called to set a device to state RFKILL_STATE_SOFT_BLOCKED -when that device is already at the RFKILL_STATE_HARD_BLOCKED state, it should -not return an error. Instead, it should try to double-block the transmitter, -so that its state will change from RFKILL_STATE_HARD_BLOCKED to -RFKILL_STATE_SOFT_BLOCKED should the hardware blocking cease. +For polling drivers: -Please refer to the source for more documentation. - -=============================================================================== -5: Userspace support - -rfkill devices issue uevents (with an action of "change"), with the following -environment variables set: - -RFKILL_NAME -RFKILL_STATE -RFKILL_TYPE - -The ABI for these variables is defined by the sysfs attributes. It is best -to take a quick look at the source to make sure of the possible values. - -It is expected that HAL will trap those, and bridge them to DBUS, etc. These -events CAN and SHOULD be used to give feedback to the user about the rfkill -status of the system. - -Input devices may issue events that are related to rfkill. These are the -various KEY_* events and SW_* events supported by rfkill-input.c. - -******IMPORTANT****** -When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL -SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it -has set to true the user_claim attribute for that particular switch. This rule -is *absolute*; do NOT violate it. -******IMPORTANT****** + - rfkill_allocate() + - input_allocate_polled_device() + - rfkill_register() + - input_register_polled_device() -Userspace must not assume it is the only source of control for rfkill switches. -Their state CAN and WILL change due to firmware actions, direct user actions, -and the rfkill-input EPO override for *_RFKILL_ALL. +When a key event has been detected, the correct event should be +sent over the input device which has been registered by the driver. -When rfkill-input is not active, userspace must initiate a rfkill status -change by writing to the "state" attribute in order for anything to happen. +==================================== +3: Userspace support -Take particular care to implement EV_SW SW_RFKILL_ALL properly. When that -switch is set to OFF, *every* rfkill device *MUST* be immediately put into the -RFKILL_STATE_SOFT_BLOCKED state, no questions asked. +For each key an input device will be created which will send out the correct +key event when the rfkill key has been pressed. The following sysfs entries will be created: name: Name assigned by driver to this key (interface or driver name). type: Name of the key type ("wlan", "bluetooth", etc). - state: Current state of the transmitter - 0: RFKILL_STATE_SOFT_BLOCKED - transmitter is forced off, but one can override it - by a write to the state attribute; - 1: RFKILL_STATE_UNBLOCKED - transmiter is NOT forced off, and may operate if - all other conditions for such operation are met - (such as interface is up and configured, etc); - 2: RFKILL_STATE_HARD_BLOCKED - transmitter is forced off by something outside of - the driver's control. One cannot set a device to - this state through writes to the state attribute; + state: Current state of the key. 1: On, 0: Off. claim: 1: Userspace handles events, 0: Kernel handles events Both the "state" and "claim" entries are also writable. For the "state" entry -this means that when 1 or 0 is written, the device rfkill state (if not yet in -the requested state), will be will be toggled accordingly. - +this means that when 1 or 0 is written all radios, not yet in the requested +state, will be will be toggled accordingly. For the "claim" entry writing 1 to it means that the kernel no longer handles key events even though RFKILL_INPUT input was enabled. When "claim" has been set to 0, userspace should make sure that it listens for the input events or -check the sysfs "state" entry regularly to correctly perform the required tasks -when the rkfill key is pressed. - -A note about input devices and EV_SW events: - -In order to know the current state of an input device switch (like -SW_RFKILL_ALL), you will need to use an IOCTL. That information is not -available through sysfs in a generic way at this time, and it is not available -through the rfkill class AT ALL. +check the sysfs "state" entry regularly to correctly perform the required +tasks when the rkfill key is pressed. diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 5ae19d502e0b..d0ea6ec2552f 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -3854,6 +3854,10 @@ P: Ion Badulescu M: ionut@cs.columbia.edu S: Maintained +STARMODE RADIO IP (STRIP) PROTOCOL DRIVER +W: http://mosquitonet.Stanford.EDU/strip.html +S: Unsupported ? + STRADIS MPEG-2 DECODER DRIVER P: Nathan Laredo M: laredo@gnu.org diff --git a/trunk/drivers/connector/connector.c b/trunk/drivers/connector/connector.c index bf4830082a13..85e2ba7fcfba 100644 --- a/trunk/drivers/connector/connector.c +++ b/trunk/drivers/connector/connector.c @@ -27,8 +27,6 @@ #include #include #include -#include -#include #include @@ -405,40 +403,6 @@ static void cn_callback(void *data) mutex_unlock(¬ify_lock); } -static int cn_proc_show(struct seq_file *m, void *v) -{ - struct cn_queue_dev *dev = cdev.cbdev; - struct cn_callback_entry *cbq; - - seq_printf(m, "Name ID\n"); - - spin_lock_bh(&dev->queue_lock); - - list_for_each_entry(cbq, &dev->queue_list, callback_entry) { - seq_printf(m, "%-15s %u:%u\n", - cbq->id.name, - cbq->id.id.idx, - cbq->id.id.val); - } - - spin_unlock_bh(&dev->queue_lock); - - return 0; -} - -static int cn_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, cn_proc_show, NULL); -} - -static const struct file_operations cn_file_ops = { - .owner = THIS_MODULE, - .open = cn_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release -}; - static int __devinit cn_init(void) { struct cn_dev *dev = &cdev; @@ -470,8 +434,6 @@ static int __devinit cn_init(void) return -EINVAL; } - proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops); - return 0; } @@ -481,8 +443,6 @@ static void __devexit cn_fini(void) cn_already_initialized = 0; - proc_net_remove(&init_net, "connector"); - cn_del_callback(&dev->id); cn_queue_free_dev(dev->cbdev); netlink_kernel_release(dev->nls); diff --git a/trunk/drivers/net/3c59x.c b/trunk/drivers/net/3c59x.c index aabad8ce7458..2edda8cc7f99 100644 --- a/trunk/drivers/net/3c59x.c +++ b/trunk/drivers/net/3c59x.c @@ -1768,10 +1768,9 @@ vortex_timer(unsigned long data) case XCVR_MII: case XCVR_NWAY: { ok = 1; - /* Interrupts are already disabled */ - spin_lock(&vp->lock); + spin_lock_bh(&vp->lock); vortex_check_media(dev, 0); - spin_unlock(&vp->lock); + spin_unlock_bh(&vp->lock); } break; default: /* Other media types handled by Tx timeouts. */ diff --git a/trunk/drivers/net/b44.c b/trunk/drivers/net/b44.c index c3bda5ce67c4..59dce6aa0865 100644 --- a/trunk/drivers/net/b44.c +++ b/trunk/drivers/net/b44.c @@ -148,9 +148,9 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev, unsigned long offset, enum dma_data_direction dir) { - ssb_dma_sync_single_range_for_device(sdev, dma_base, - offset & dma_desc_align_mask, - dma_desc_sync_size, dir); + dma_sync_single_range_for_device(sdev->dma_dev, dma_base, + offset & dma_desc_align_mask, + dma_desc_sync_size, dir); } static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, @@ -158,9 +158,9 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev, unsigned long offset, enum dma_data_direction dir) { - ssb_dma_sync_single_range_for_cpu(sdev, dma_base, - offset & dma_desc_align_mask, - dma_desc_sync_size, dir); + dma_sync_single_range_for_cpu(sdev->dma_dev, dma_base, + offset & dma_desc_align_mask, + dma_desc_sync_size, dir); } static inline unsigned long br32(const struct b44 *bp, unsigned long reg) @@ -613,10 +613,10 @@ static void b44_tx(struct b44 *bp) BUG_ON(skb == NULL); - ssb_dma_unmap_single(bp->sdev, - rp->mapping, - skb->len, - DMA_TO_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, + rp->mapping, + skb->len, + DMA_TO_DEVICE); rp->skb = NULL; dev_kfree_skb_irq(skb); } @@ -653,29 +653,29 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) if (skb == NULL) return -ENOMEM; - mapping = ssb_dma_map_single(bp->sdev, skb->data, - RX_PKT_BUF_SZ, - DMA_FROM_DEVICE); + mapping = dma_map_single(bp->sdev->dma_dev, skb->data, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); /* Hardware bug work-around, the chip is unable to do PCI DMA to/from anything above 1GB :-( */ - if (ssb_dma_mapping_error(bp->sdev, mapping) || + if (dma_mapping_error(mapping) || mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) { /* Sigh... */ - if (!ssb_dma_mapping_error(bp->sdev, mapping)) - ssb_dma_unmap_single(bp->sdev, mapping, - RX_PKT_BUF_SZ, DMA_FROM_DEVICE); + if (!dma_mapping_error(mapping)) + dma_unmap_single(bp->sdev->dma_dev, mapping, + RX_PKT_BUF_SZ, DMA_FROM_DEVICE); dev_kfree_skb_any(skb); skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA); if (skb == NULL) return -ENOMEM; - mapping = ssb_dma_map_single(bp->sdev, skb->data, - RX_PKT_BUF_SZ, - DMA_FROM_DEVICE); - if (ssb_dma_mapping_error(bp->sdev, mapping) || + mapping = dma_map_single(bp->sdev->dma_dev, skb->data, + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); + if (dma_mapping_error(mapping) || mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) { - if (!ssb_dma_mapping_error(bp->sdev, mapping)) - ssb_dma_unmap_single(bp->sdev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); + if (!dma_mapping_error(mapping)) + dma_unmap_single(bp->sdev->dma_dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE); dev_kfree_skb_any(skb); return -ENOMEM; } @@ -750,9 +750,9 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) dest_idx * sizeof(dest_desc), DMA_BIDIRECTIONAL); - ssb_dma_sync_single_for_device(bp->sdev, le32_to_cpu(src_desc->addr), - RX_PKT_BUF_SZ, - DMA_FROM_DEVICE); + dma_sync_single_for_device(bp->sdev->dma_dev, le32_to_cpu(src_desc->addr), + RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); } static int b44_rx(struct b44 *bp, int budget) @@ -772,7 +772,7 @@ static int b44_rx(struct b44 *bp, int budget) struct rx_header *rh; u16 len; - ssb_dma_sync_single_for_cpu(bp->sdev, map, + dma_sync_single_for_cpu(bp->sdev->dma_dev, map, RX_PKT_BUF_SZ, DMA_FROM_DEVICE); rh = (struct rx_header *) skb->data; @@ -806,8 +806,8 @@ static int b44_rx(struct b44 *bp, int budget) skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); if (skb_size < 0) goto drop_it; - ssb_dma_unmap_single(bp->sdev, map, - skb_size, DMA_FROM_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, map, + skb_size, DMA_FROM_DEVICE); /* Leave out rx_header */ skb_put(skb, len + RX_PKT_OFFSET); skb_pull(skb, RX_PKT_OFFSET); @@ -966,25 +966,25 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) goto err_out; } - mapping = ssb_dma_map_single(bp->sdev, skb->data, len, DMA_TO_DEVICE); - if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_30BIT_MASK) { + mapping = dma_map_single(bp->sdev->dma_dev, skb->data, len, DMA_TO_DEVICE); + if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { struct sk_buff *bounce_skb; /* Chip can't handle DMA to/from >1GB, use bounce buffer */ - if (!ssb_dma_mapping_error(bp->sdev, mapping)) - ssb_dma_unmap_single(bp->sdev, mapping, len, - DMA_TO_DEVICE); + if (!dma_mapping_error(mapping)) + dma_unmap_single(bp->sdev->dma_dev, mapping, len, + DMA_TO_DEVICE); bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA); if (!bounce_skb) goto err_out; - mapping = ssb_dma_map_single(bp->sdev, bounce_skb->data, - len, DMA_TO_DEVICE); - if (ssb_dma_mapping_error(bp->sdev, mapping) || mapping + len > DMA_30BIT_MASK) { - if (!ssb_dma_mapping_error(bp->sdev, mapping)) - ssb_dma_unmap_single(bp->sdev, mapping, - len, DMA_TO_DEVICE); + mapping = dma_map_single(bp->sdev->dma_dev, bounce_skb->data, + len, DMA_TO_DEVICE); + if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) { + if (!dma_mapping_error(mapping)) + dma_unmap_single(bp->sdev->dma_dev, mapping, + len, DMA_TO_DEVICE); dev_kfree_skb_any(bounce_skb); goto err_out; } @@ -1082,8 +1082,8 @@ static void b44_free_rings(struct b44 *bp) if (rp->skb == NULL) continue; - ssb_dma_unmap_single(bp->sdev, rp->mapping, RX_PKT_BUF_SZ, - DMA_FROM_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, rp->mapping, RX_PKT_BUF_SZ, + DMA_FROM_DEVICE); dev_kfree_skb_any(rp->skb); rp->skb = NULL; } @@ -1094,8 +1094,8 @@ static void b44_free_rings(struct b44 *bp) if (rp->skb == NULL) continue; - ssb_dma_unmap_single(bp->sdev, rp->mapping, rp->skb->len, - DMA_TO_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, rp->mapping, rp->skb->len, + DMA_TO_DEVICE); dev_kfree_skb_any(rp->skb); rp->skb = NULL; } @@ -1117,14 +1117,14 @@ static void b44_init_rings(struct b44 *bp) memset(bp->tx_ring, 0, B44_TX_RING_BYTES); if (bp->flags & B44_FLAG_RX_RING_HACK) - ssb_dma_sync_single_for_device(bp->sdev, bp->rx_ring_dma, - DMA_TABLE_BYTES, - DMA_BIDIRECTIONAL); + dma_sync_single_for_device(bp->sdev->dma_dev, bp->rx_ring_dma, + DMA_TABLE_BYTES, + DMA_BIDIRECTIONAL); if (bp->flags & B44_FLAG_TX_RING_HACK) - ssb_dma_sync_single_for_device(bp->sdev, bp->tx_ring_dma, - DMA_TABLE_BYTES, - DMA_TO_DEVICE); + dma_sync_single_for_device(bp->sdev->dma_dev, bp->tx_ring_dma, + DMA_TABLE_BYTES, + DMA_TO_DEVICE); for (i = 0; i < bp->rx_pending; i++) { if (b44_alloc_rx_skb(bp, -1, i) < 0) @@ -1144,27 +1144,25 @@ static void b44_free_consistent(struct b44 *bp) bp->tx_buffers = NULL; if (bp->rx_ring) { if (bp->flags & B44_FLAG_RX_RING_HACK) { - ssb_dma_unmap_single(bp->sdev, bp->rx_ring_dma, - DMA_TABLE_BYTES, - DMA_BIDIRECTIONAL); + dma_unmap_single(bp->sdev->dma_dev, bp->rx_ring_dma, + DMA_TABLE_BYTES, + DMA_BIDIRECTIONAL); kfree(bp->rx_ring); } else - ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES, - bp->rx_ring, bp->rx_ring_dma, - GFP_KERNEL); + dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES, + bp->rx_ring, bp->rx_ring_dma); bp->rx_ring = NULL; bp->flags &= ~B44_FLAG_RX_RING_HACK; } if (bp->tx_ring) { if (bp->flags & B44_FLAG_TX_RING_HACK) { - ssb_dma_unmap_single(bp->sdev, bp->tx_ring_dma, - DMA_TABLE_BYTES, - DMA_TO_DEVICE); + dma_unmap_single(bp->sdev->dma_dev, bp->tx_ring_dma, + DMA_TABLE_BYTES, + DMA_TO_DEVICE); kfree(bp->tx_ring); } else - ssb_dma_free_consistent(bp->sdev, DMA_TABLE_BYTES, - bp->tx_ring, bp->tx_ring_dma, - GFP_KERNEL); + dma_free_coherent(bp->sdev->dma_dev, DMA_TABLE_BYTES, + bp->tx_ring, bp->tx_ring_dma); bp->tx_ring = NULL; bp->flags &= ~B44_FLAG_TX_RING_HACK; } @@ -1189,7 +1187,7 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) goto out_err; size = DMA_TABLE_BYTES; - bp->rx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->rx_ring_dma, gfp); + bp->rx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, &bp->rx_ring_dma, gfp); if (!bp->rx_ring) { /* Allocation may have failed due to pci_alloc_consistent insisting on use of GFP_DMA, which is more restrictive @@ -1201,11 +1199,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) if (!rx_ring) goto out_err; - rx_ring_dma = ssb_dma_map_single(bp->sdev, rx_ring, - DMA_TABLE_BYTES, - DMA_BIDIRECTIONAL); + rx_ring_dma = dma_map_single(bp->sdev->dma_dev, rx_ring, + DMA_TABLE_BYTES, + DMA_BIDIRECTIONAL); - if (ssb_dma_mapping_error(bp->sdev, rx_ring_dma) || + if (dma_mapping_error(rx_ring_dma) || rx_ring_dma + size > DMA_30BIT_MASK) { kfree(rx_ring); goto out_err; @@ -1216,9 +1214,9 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) bp->flags |= B44_FLAG_RX_RING_HACK; } - bp->tx_ring = ssb_dma_alloc_consistent(bp->sdev, size, &bp->tx_ring_dma, gfp); + bp->tx_ring = dma_alloc_coherent(bp->sdev->dma_dev, size, &bp->tx_ring_dma, gfp); if (!bp->tx_ring) { - /* Allocation may have failed due to ssb_dma_alloc_consistent + /* Allocation may have failed due to dma_alloc_coherent insisting on use of GFP_DMA, which is more restrictive than necessary... */ struct dma_desc *tx_ring; @@ -1228,11 +1226,11 @@ static int b44_alloc_consistent(struct b44 *bp, gfp_t gfp) if (!tx_ring) goto out_err; - tx_ring_dma = ssb_dma_map_single(bp->sdev, tx_ring, + tx_ring_dma = dma_map_single(bp->sdev->dma_dev, tx_ring, DMA_TABLE_BYTES, DMA_TO_DEVICE); - if (ssb_dma_mapping_error(bp->sdev, tx_ring_dma) || + if (dma_mapping_error(tx_ring_dma) || tx_ring_dma + size > DMA_30BIT_MASK) { kfree(tx_ring); goto out_err; diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c index 1037b1332312..f3cba5e24ec5 100644 --- a/trunk/drivers/net/e100.c +++ b/trunk/drivers/net/e100.c @@ -1803,8 +1803,6 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) if (rx->prev->skb) { struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; put_unaligned_le32(rx->dma_addr, &prev_rfd->link); - pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); } return 0; diff --git a/trunk/drivers/net/e1000/e1000_ethtool.c b/trunk/drivers/net/e1000/e1000_ethtool.c index a3f6a9c72ec8..701531e72e7b 100644 --- a/trunk/drivers/net/e1000/e1000_ethtool.c +++ b/trunk/drivers/net/e1000/e1000_ethtool.c @@ -347,7 +347,7 @@ e1000_set_tso(struct net_device *netdev, u32 data) else netdev->features &= ~NETIF_F_TSO; - if (data && (adapter->hw.mac_type > e1000_82547_rev_2)) + if (data) netdev->features |= NETIF_F_TSO6; else netdev->features &= ~NETIF_F_TSO6; diff --git a/trunk/drivers/net/e1000e/netdev.c b/trunk/drivers/net/e1000e/netdev.c index acdd616c96f6..22f2fc906354 100644 --- a/trunk/drivers/net/e1000e/netdev.c +++ b/trunk/drivers/net/e1000e/netdev.c @@ -2535,8 +2535,7 @@ void e1000e_down(struct e1000_adapter *adapter) adapter->link_speed = 0; adapter->link_duplex = 0; - if (!pci_channel_offline(adapter->pdev)) - e1000e_reset(adapter); + e1000e_reset(adapter); e1000_clean_tx_ring(adapter); e1000_clean_rx_ring(adapter); diff --git a/trunk/drivers/net/hamradio/dmascc.c b/trunk/drivers/net/hamradio/dmascc.c index e8cfadefa4b6..0b94833e23f7 100644 --- a/trunk/drivers/net/hamradio/dmascc.c +++ b/trunk/drivers/net/hamradio/dmascc.c @@ -1077,6 +1077,8 @@ static inline void rx_off(struct scc_priv *priv) static void start_timer(struct scc_priv *priv, int t, int r15) { + unsigned long flags; + outb(priv->tmr_mode, priv->tmr_ctrl); if (t == 0) { tm_isr(priv); diff --git a/trunk/drivers/net/igb/igb_main.c b/trunk/drivers/net/igb/igb_main.c index 171d1fc1fbf8..e13b8db67b7c 100644 --- a/trunk/drivers/net/igb/igb_main.c +++ b/trunk/drivers/net/igb/igb_main.c @@ -718,8 +718,7 @@ void igb_down(struct igb_adapter *adapter) adapter->link_speed = 0; adapter->link_duplex = 0; - if (!pci_channel_offline(adapter->pdev)) - igb_reset(adapter); + igb_reset(adapter); igb_clean_all_tx_rings(adapter); igb_clean_all_rx_rings(adapter); } diff --git a/trunk/drivers/net/ipg.c b/trunk/drivers/net/ipg.c index 2c03f4e2ccc4..679a0826780e 100644 --- a/trunk/drivers/net/ipg.c +++ b/trunk/drivers/net/ipg.c @@ -1271,7 +1271,7 @@ static void ipg_nic_rx_with_end(struct net_device *dev, framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN; - endframelen = framelen - jumbo->current_size; + endframeLen = framelen - jumbo->current_size; /* if (framelen > IPG_RXFRAG_SIZE) framelen=IPG_RXFRAG_SIZE; @@ -1279,8 +1279,8 @@ static void ipg_nic_rx_with_end(struct net_device *dev, if (framelen > IPG_RXSUPPORT_SIZE) dev_kfree_skb_irq(jumbo->skb); else { - memcpy(skb_put(jumbo->skb, endframelen), - skb->data, endframelen); + memcpy(skb_put(jumbo->skb, endframeLen), + skb->data, endframeLen); jumbo->skb->protocol = eth_type_trans(jumbo->skb, dev); @@ -1352,16 +1352,16 @@ static int ipg_nic_rx(struct net_device *dev) switch (ipg_nic_rx_check_frame_type(dev)) { case FRAME_WITH_START_WITH_END: - ipg_nic_rx_with_start_and_end(dev, sp, rxfd, entry); + ipg_nic_rx_with_start_and_end(dev, tp, rxfd, entry); break; case FRAME_WITH_START: - ipg_nic_rx_with_start(dev, sp, rxfd, entry); + ipg_nic_rx_with_start(dev, tp, rxfd, entry); break; case FRAME_WITH_END: - ipg_nic_rx_with_end(dev, sp, rxfd, entry); + ipg_nic_rx_with_end(dev, tp, rxfd, entry); break; case FRAME_NO_START_NO_END: - ipg_nic_rx_no_start_no_end(dev, sp, rxfd, entry); + ipg_nic_rx_no_start_no_end(dev, tp, rxfd, entry); break; } } @@ -1808,7 +1808,7 @@ static int ipg_nic_open(struct net_device *dev) /* initialize JUMBO Frame control variable */ sp->jumbo.found_start = 0; sp->jumbo.current_size = 0; - sp->jumbo.skb = NULL; + sp->jumbo.skb = 0; dev->mtu = IPG_TXFRAG_SIZE; #endif diff --git a/trunk/drivers/net/ixgbe/ixgbe_main.c b/trunk/drivers/net/ixgbe/ixgbe_main.c index b37d618d8e2a..f429c9a4754f 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ixgbe/ixgbe_main.c @@ -2023,8 +2023,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) netif_carrier_off(netdev); netif_stop_queue(netdev); - if (!pci_channel_offline(adapter->pdev)) - ixgbe_reset(adapter); + ixgbe_reset(adapter); ixgbe_clean_all_tx_rings(adapter); ixgbe_clean_all_rx_rings(adapter); diff --git a/trunk/drivers/net/netxen/netxen_nic_main.c b/trunk/drivers/net/netxen/netxen_nic_main.c index 63cd67b931e7..6797ed069f1f 100644 --- a/trunk/drivers/net/netxen/netxen_nic_main.c +++ b/trunk/drivers/net/netxen/netxen_nic_main.c @@ -71,18 +71,14 @@ static irqreturn_t netxen_intr(int irq, void *data); static irqreturn_t netxen_msi_intr(int irq, void *data); /* PCI Device ID Table */ -#define ENTRY(device) \ - {PCI_DEVICE(0x4040, (device)), \ - .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} - static struct pci_device_id netxen_pci_tbl[] __devinitdata = { - ENTRY(0x0001), - ENTRY(0x0002), - ENTRY(0x0003), - ENTRY(0x0004), - ENTRY(0x0005), - ENTRY(0x0024), - ENTRY(0x0025), + {PCI_DEVICE(0x4040, 0x0001), PCI_DEVICE_CLASS(0x020000, ~0)}, + {PCI_DEVICE(0x4040, 0x0002), PCI_DEVICE_CLASS(0x020000, ~0)}, + {PCI_DEVICE(0x4040, 0x0003), PCI_DEVICE_CLASS(0x020000, ~0)}, + {PCI_DEVICE(0x4040, 0x0004), PCI_DEVICE_CLASS(0x020000, ~0)}, + {PCI_DEVICE(0x4040, 0x0005), PCI_DEVICE_CLASS(0x020000, ~0)}, + {PCI_DEVICE(0x4040, 0x0024), PCI_DEVICE_CLASS(0x020000, ~0)}, + {PCI_DEVICE(0x4040, 0x0025), PCI_DEVICE_CLASS(0x020000, ~0)}, {0,} }; diff --git a/trunk/drivers/net/niu.c b/trunk/drivers/net/niu.c index de2a8a30199d..918f802fe089 100644 --- a/trunk/drivers/net/niu.c +++ b/trunk/drivers/net/niu.c @@ -6385,162 +6385,6 @@ static int niu_get_eeprom(struct net_device *dev, return 0; } -static int niu_ethflow_to_class(int flow_type, u64 *class) -{ - switch (flow_type) { - case TCP_V4_FLOW: - *class = CLASS_CODE_TCP_IPV4; - break; - case UDP_V4_FLOW: - *class = CLASS_CODE_UDP_IPV4; - break; - case AH_ESP_V4_FLOW: - *class = CLASS_CODE_AH_ESP_IPV4; - break; - case SCTP_V4_FLOW: - *class = CLASS_CODE_SCTP_IPV4; - break; - case TCP_V6_FLOW: - *class = CLASS_CODE_TCP_IPV6; - break; - case UDP_V6_FLOW: - *class = CLASS_CODE_UDP_IPV6; - break; - case AH_ESP_V6_FLOW: - *class = CLASS_CODE_AH_ESP_IPV6; - break; - case SCTP_V6_FLOW: - *class = CLASS_CODE_SCTP_IPV6; - break; - default: - return -1; - } - - return 1; -} - -static u64 niu_flowkey_to_ethflow(u64 flow_key) -{ - u64 ethflow = 0; - - if (flow_key & FLOW_KEY_PORT) - ethflow |= RXH_DEV_PORT; - if (flow_key & FLOW_KEY_L2DA) - ethflow |= RXH_L2DA; - if (flow_key & FLOW_KEY_VLAN) - ethflow |= RXH_VLAN; - if (flow_key & FLOW_KEY_IPSA) - ethflow |= RXH_IP_SRC; - if (flow_key & FLOW_KEY_IPDA) - ethflow |= RXH_IP_DST; - if (flow_key & FLOW_KEY_PROTO) - ethflow |= RXH_L3_PROTO; - if (flow_key & (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_0_SHIFT)) - ethflow |= RXH_L4_B_0_1; - if (flow_key & (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_1_SHIFT)) - ethflow |= RXH_L4_B_2_3; - - return ethflow; - -} - -static int niu_ethflow_to_flowkey(u64 ethflow, u64 *flow_key) -{ - u64 key = 0; - - if (ethflow & RXH_DEV_PORT) - key |= FLOW_KEY_PORT; - if (ethflow & RXH_L2DA) - key |= FLOW_KEY_L2DA; - if (ethflow & RXH_VLAN) - key |= FLOW_KEY_VLAN; - if (ethflow & RXH_IP_SRC) - key |= FLOW_KEY_IPSA; - if (ethflow & RXH_IP_DST) - key |= FLOW_KEY_IPDA; - if (ethflow & RXH_L3_PROTO) - key |= FLOW_KEY_PROTO; - if (ethflow & RXH_L4_B_0_1) - key |= (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_0_SHIFT); - if (ethflow & RXH_L4_B_2_3) - key |= (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_1_SHIFT); - - *flow_key = key; - - return 1; - -} - -static int niu_get_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd) -{ - struct niu *np = netdev_priv(dev); - u64 class; - - cmd->data = 0; - - if (!niu_ethflow_to_class(cmd->flow_type, &class)) - return -EINVAL; - - if (np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] & - TCAM_KEY_DISC) - cmd->data = RXH_DISCARD; - else - - cmd->data = niu_flowkey_to_ethflow(np->parent->flow_key[class - - CLASS_CODE_USER_PROG1]); - return 0; -} - -static int niu_set_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd) -{ - struct niu *np = netdev_priv(dev); - u64 class; - u64 flow_key = 0; - unsigned long flags; - - if (!niu_ethflow_to_class(cmd->flow_type, &class)) - return -EINVAL; - - if (class < CLASS_CODE_USER_PROG1 || - class > CLASS_CODE_SCTP_IPV6) - return -EINVAL; - - if (cmd->data & RXH_DISCARD) { - niu_lock_parent(np, flags); - flow_key = np->parent->tcam_key[class - - CLASS_CODE_USER_PROG1]; - flow_key |= TCAM_KEY_DISC; - nw64(TCAM_KEY(class - CLASS_CODE_USER_PROG1), flow_key); - np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] = flow_key; - niu_unlock_parent(np, flags); - return 0; - } else { - /* Discard was set before, but is not set now */ - if (np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] & - TCAM_KEY_DISC) { - niu_lock_parent(np, flags); - flow_key = np->parent->tcam_key[class - - CLASS_CODE_USER_PROG1]; - flow_key &= ~TCAM_KEY_DISC; - nw64(TCAM_KEY(class - CLASS_CODE_USER_PROG1), - flow_key); - np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] = - flow_key; - niu_unlock_parent(np, flags); - } - } - - if (!niu_ethflow_to_flowkey(cmd->data, &flow_key)) - return -EINVAL; - - niu_lock_parent(np, flags); - nw64(FLOW_KEY(class - CLASS_CODE_USER_PROG1), flow_key); - np->parent->flow_key[class - CLASS_CODE_USER_PROG1] = flow_key; - niu_unlock_parent(np, flags); - - return 0; -} - static const struct { const char string[ETH_GSTRING_LEN]; } niu_xmac_stat_keys[] = { @@ -6771,8 +6615,6 @@ static const struct ethtool_ops niu_ethtool_ops = { .get_stats_count = niu_get_stats_count, .get_ethtool_stats = niu_get_ethtool_stats, .phys_id = niu_phys_id, - .get_rxhash = niu_get_hash_opts, - .set_rxhash = niu_set_hash_opts, }; static int niu_ldg_assign_ldn(struct niu *np, struct niu_parent *parent, diff --git a/trunk/drivers/net/pcmcia/axnet_cs.c b/trunk/drivers/net/pcmcia/axnet_cs.c index 3f682d49a4e6..d7018ff9e171 100644 --- a/trunk/drivers/net/pcmcia/axnet_cs.c +++ b/trunk/drivers/net/pcmcia/axnet_cs.c @@ -525,14 +525,12 @@ static int axnet_open(struct net_device *dev) int ret; axnet_dev_t *info = PRIV(dev); struct pcmcia_device *link = info->p_dev; - unsigned int nic_base = dev->base_addr; DEBUG(2, "axnet_open('%s')\n", dev->name); if (!pcmcia_dev_present(link)) return -ENODEV; - outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev); if (ret) return ret; diff --git a/trunk/drivers/net/pcmcia/pcnet_cs.c b/trunk/drivers/net/pcmcia/pcnet_cs.c index 2d4c4ad89b8d..fd8158a86f64 100644 --- a/trunk/drivers/net/pcmcia/pcnet_cs.c +++ b/trunk/drivers/net/pcmcia/pcnet_cs.c @@ -969,7 +969,6 @@ static int pcnet_open(struct net_device *dev) int ret; pcnet_dev_t *info = PRIV(dev); struct pcmcia_device *link = info->p_dev; - unsigned int nic_base = dev->base_addr; DEBUG(2, "pcnet_open('%s')\n", dev->name); @@ -977,8 +976,6 @@ static int pcnet_open(struct net_device *dev) return -ENODEV; set_misc_reg(dev); - - outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev); if (ret) return ret; diff --git a/trunk/drivers/net/pppoe.c b/trunk/drivers/net/pppoe.c index fc6f4b8c64b3..bafb69b6f7cb 100644 --- a/trunk/drivers/net/pppoe.c +++ b/trunk/drivers/net/pppoe.c @@ -942,7 +942,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, m->msg_namelen = 0; if (skb) { - total_len = min_t(size_t, total_len, skb->len); + total_len = min(total_len, skb->len); error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); if (error == 0) error = total_len; diff --git a/trunk/drivers/net/ps3_gelic_wireless.c b/trunk/drivers/net/ps3_gelic_wireless.c index 6b2dee0cf3a9..aa963ac1e37b 100644 --- a/trunk/drivers/net/ps3_gelic_wireless.c +++ b/trunk/drivers/net/ps3_gelic_wireless.c @@ -571,7 +571,6 @@ static void gelic_wl_parse_ie(u8 *data, size_t len, * independent format */ static char *gelic_wl_translate_scan(struct net_device *netdev, - struct iw_request_info *info, char *ev, char *stop, struct gelic_wl_scan_info *network) @@ -589,26 +588,26 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, &scan->bssid[2], ETH_ALEN); - ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_ADDR_LEN); + ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_ADDR_LEN); /* ESSID */ iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; iwe.u.data.length = strnlen(scan->essid, 32); - ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); + ev = iwe_stream_add_point(ev, stop, &iwe, scan->essid); /* FREQUENCY */ iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = be16_to_cpu(scan->channel); iwe.u.freq.e = 0; /* table value in MHz */ iwe.u.freq.i = 0; - ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_FREQ_LEN); + ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_FREQ_LEN); /* RATES */ iwe.cmd = SIOCGIWRATE; iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; /* to stuff multiple values in one event */ - tmp = ev + iwe_stream_lcp_len(info); + tmp = ev + IW_EV_LCP_LEN; /* put them in ascendant order (older is first) */ i = 0; j = 0; @@ -621,16 +620,16 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, else rate = scan->rate[i++] & 0x7f; iwe.u.bitrate.value = rate * 500000; /* 500kbps unit */ - tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, + tmp = iwe_stream_add_value(ev, tmp, stop, &iwe, IW_EV_PARAM_LEN); } while (j < network->rate_ext_len) { iwe.u.bitrate.value = (scan->ext_rate[j++] & 0x7f) * 500000; - tmp = iwe_stream_add_value(info, ev, tmp, stop, &iwe, + tmp = iwe_stream_add_value(ev, tmp, stop, &iwe, IW_EV_PARAM_LEN); } /* Check if we added any rate */ - if (iwe_stream_lcp_len(info) < (tmp - ev)) + if (IW_EV_LCP_LEN < (tmp - ev)) ev = tmp; /* ENCODE */ @@ -640,7 +639,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - ev = iwe_stream_add_point(info, ev, stop, &iwe, scan->essid); + ev = iwe_stream_add_point(ev, stop, &iwe, scan->essid); /* MODE */ iwe.cmd = SIOCGIWMODE; @@ -650,7 +649,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; - ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_UINT_LEN); + ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_UINT_LEN); } /* QUAL */ @@ -660,7 +659,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, iwe.u.qual.level = be16_to_cpu(scan->rssi); iwe.u.qual.qual = be16_to_cpu(scan->rssi); iwe.u.qual.noise = 0; - ev = iwe_stream_add_event(info, ev, stop, &iwe, IW_EV_QUAL_LEN); + ev = iwe_stream_add_event(ev, stop, &iwe, IW_EV_QUAL_LEN); /* RSN */ memset(&iwe, 0, sizeof(iwe)); @@ -670,7 +669,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, if (len) { iwe.cmd = IWEVGENIE; iwe.u.data.length = len; - ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); + ev = iwe_stream_add_point(ev, stop, &iwe, buf); } } else { /* this scan info has IE data */ @@ -685,7 +684,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, memcpy(buf, ie_info.wpa.data, ie_info.wpa.len); iwe.cmd = IWEVGENIE; iwe.u.data.length = ie_info.wpa.len; - ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); + ev = iwe_stream_add_point(ev, stop, &iwe, buf); } if (ie_info.rsn.len && (ie_info.rsn.len <= sizeof(buf))) { @@ -693,7 +692,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev, memcpy(buf, ie_info.rsn.data, ie_info.rsn.len); iwe.cmd = IWEVGENIE; iwe.u.data.length = ie_info.rsn.len; - ev = iwe_stream_add_point(info, ev, stop, &iwe, buf); + ev = iwe_stream_add_point(ev, stop, &iwe, buf); } } @@ -738,8 +737,7 @@ static int gelic_wl_get_scan(struct net_device *netdev, if (wl->scan_age == 0 || time_after(scan_info->last_scanned + wl->scan_age, this_time)) - ev = gelic_wl_translate_scan(netdev, info, - ev, stop, + ev = gelic_wl_translate_scan(netdev, ev, stop, scan_info); else pr_debug("%s:entry too old\n", __func__); diff --git a/trunk/drivers/net/qla3xxx.c b/trunk/drivers/net/qla3xxx.c index e7d48a352beb..5f608780c3e8 100644 --- a/trunk/drivers/net/qla3xxx.c +++ b/trunk/drivers/net/qla3xxx.c @@ -3701,9 +3701,7 @@ static int ql_cycle_adapter(struct ql3_adapter *qdev, int reset) printk(KERN_ERR PFX "%s: Driver up/down cycle failed, " "closing device\n",qdev->ndev->name); - rtnl_lock(); dev_close(qdev->ndev); - rtnl_unlock(); return -1; } return 0; diff --git a/trunk/drivers/net/r6040.c b/trunk/drivers/net/r6040.c index 504a48ff73c8..858b191517b3 100644 --- a/trunk/drivers/net/r6040.c +++ b/trunk/drivers/net/r6040.c @@ -273,7 +273,7 @@ static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring, dma_addr_t mapping = desc_dma; while (size-- > 0) { - mapping += sizeof(*desc); + mapping += sizeof(sizeof(*desc)); desc->ndesc = cpu_to_le32(mapping); desc->vndescp = desc + 1; desc++; diff --git a/trunk/drivers/net/r8169.c b/trunk/drivers/net/r8169.c index 657242504621..9086e819d742 100644 --- a/trunk/drivers/net/r8169.c +++ b/trunk/drivers/net/r8169.c @@ -3098,8 +3098,10 @@ static void rtl_set_rx_mode(struct net_device *dev) (tp->mac_version == RTL_GIGA_MAC_VER_15) || (tp->mac_version == RTL_GIGA_MAC_VER_16) || (tp->mac_version == RTL_GIGA_MAC_VER_17)) { - mc_filter[0] = 0xffffffff; - mc_filter[1] = 0xffffffff; + u32 data = mc_filter[0]; + + mc_filter[0] = swab32(mc_filter[1]); + mc_filter[1] = swab32(data); } RTL_W32(MAR0 + 0, mc_filter[0]); diff --git a/trunk/drivers/net/s2io.c b/trunk/drivers/net/s2io.c index e7a3dbec674c..5694e894fc7a 100644 --- a/trunk/drivers/net/s2io.c +++ b/trunk/drivers/net/s2io.c @@ -2625,7 +2625,9 @@ static int fill_rx_buffers(struct ring_info *ring) rxdp1->Buffer0_ptr = pci_map_single (ring->pdev, skb->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); - if(pci_dma_mapping_error(rxdp1->Buffer0_ptr)) + if( (rxdp1->Buffer0_ptr == 0) || + (rxdp1->Buffer0_ptr == + DMA_ERROR_CODE)) goto pci_map_failed; rxdp->Control_2 = @@ -2655,7 +2657,6 @@ static int fill_rx_buffers(struct ring_info *ring) skb->data = (void *) (unsigned long)tmp; skb_reset_tail_pointer(skb); - /* AK: check is wrong. 0 can be valid dma address */ if (!(rxdp3->Buffer0_ptr)) rxdp3->Buffer0_ptr = pci_map_single(ring->pdev, ba->ba_0, @@ -2664,7 +2665,8 @@ static int fill_rx_buffers(struct ring_info *ring) pci_dma_sync_single_for_device(ring->pdev, (dma_addr_t) rxdp3->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(rxdp3->Buffer0_ptr)) + if( (rxdp3->Buffer0_ptr == 0) || + (rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) goto pci_map_failed; rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); @@ -2679,17 +2681,18 @@ static int fill_rx_buffers(struct ring_info *ring) (ring->pdev, skb->data, ring->mtu + 4, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(rxdp3->Buffer2_ptr)) + if( (rxdp3->Buffer2_ptr == 0) || + (rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) goto pci_map_failed; - /* AK: check is wrong */ if (!rxdp3->Buffer1_ptr) rxdp3->Buffer1_ptr = pci_map_single(ring->pdev, ba->ba_1, BUF1_LEN, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(rxdp3->Buffer1_ptr)) { + if( (rxdp3->Buffer1_ptr == 0) || + (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { pci_unmap_single (ring->pdev, (dma_addr_t)(unsigned long) @@ -4261,14 +4264,16 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Buffer_Pointer = pci_map_single(sp->pdev, fifo->ufo_in_band_v, sizeof(u64), PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(txdp->Buffer_Pointer)) + if((txdp->Buffer_Pointer == 0) || + (txdp->Buffer_Pointer == DMA_ERROR_CODE)) goto pci_map_failed; txdp++; } txdp->Buffer_Pointer = pci_map_single (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(txdp->Buffer_Pointer)) + if((txdp->Buffer_Pointer == 0) || + (txdp->Buffer_Pointer == DMA_ERROR_CODE)) goto pci_map_failed; txdp->Host_Control = (unsigned long) skb; @@ -6879,8 +6884,10 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, pci_map_single( sp->pdev, (*skb)->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(rxdp1->Buffer0_ptr)) + if( (rxdp1->Buffer0_ptr == 0) || + (rxdp1->Buffer0_ptr == DMA_ERROR_CODE)) { goto memalloc_failed; + } rxdp->Host_Control = (unsigned long) (*skb); } } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) { @@ -6906,12 +6913,15 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, pci_map_single(sp->pdev, (*skb)->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(rxdp3->Buffer2_ptr)) + if( (rxdp3->Buffer2_ptr == 0) || + (rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) { goto memalloc_failed; + } rxdp3->Buffer0_ptr = *temp0 = pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(rxdp3->Buffer0_ptr)) { + if( (rxdp3->Buffer0_ptr == 0) || + (rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) { pci_unmap_single (sp->pdev, (dma_addr_t)rxdp3->Buffer2_ptr, dev->mtu + 4, PCI_DMA_FROMDEVICE); @@ -6923,7 +6933,8 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, rxdp3->Buffer1_ptr = *temp1 = pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(rxdp3->Buffer1_ptr)) { + if( (rxdp3->Buffer1_ptr == 0) || + (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { pci_unmap_single (sp->pdev, (dma_addr_t)rxdp3->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); diff --git a/trunk/drivers/net/s2io.h b/trunk/drivers/net/s2io.h index 483b17c34ae8..d0a84ba887a5 100644 --- a/trunk/drivers/net/s2io.h +++ b/trunk/drivers/net/s2io.h @@ -75,6 +75,10 @@ static int debug_level = ERR_DBG; /* DEBUG message print. */ #define DBG_PRINT(dbg_level, args...) if(!(debug_levellock); - netif_carrier_off(dev); /* schedule a link state check */ phy_start(lp->phy_dev); @@ -1736,6 +1735,7 @@ tc35815_rx(struct net_device *dev) skb = lp->rx_skbs[cur_bd].skb; prefetch(skb->data); lp->rx_skbs[cur_bd].skb = NULL; + lp->fbl_count--; pci_unmap_single(lp->pci_dev, lp->rx_skbs[cur_bd].skb_dma, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); @@ -1791,7 +1791,6 @@ tc35815_rx(struct net_device *dev) #ifdef TC35815_USE_PACKEDBUFFER while (lp->fbl_curid != id) #else - lp->fbl_count--; while (lp->fbl_count < RX_BUF_NUM) #endif { @@ -2454,7 +2453,6 @@ static int tc35815_resume(struct pci_dev *pdev) return 0; pci_set_power_state(pdev, PCI_D0); tc35815_restart(dev); - netif_carrier_off(dev); if (lp->phy_dev) phy_start(lp->phy_dev); netif_device_attach(dev); diff --git a/trunk/drivers/net/tun.c b/trunk/drivers/net/tun.c index aa4ee4439f04..7ab94c825b57 100644 --- a/trunk/drivers/net/tun.c +++ b/trunk/drivers/net/tun.c @@ -63,7 +63,6 @@ #include #include #include -#include #include #include @@ -284,7 +283,6 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) }; struct sk_buff *skb; size_t len = count, align = 0; - struct virtio_net_hdr gso = { 0 }; if (!(tun->flags & TUN_NO_PI)) { if ((len -= sizeof(pi)) > count) @@ -294,17 +292,6 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, return -EFAULT; } - if (tun->flags & TUN_VNET_HDR) { - if ((len -= sizeof(gso)) > count) - return -EINVAL; - - if (memcpy_fromiovec((void *)&gso, iv, sizeof(gso))) - return -EFAULT; - - if (gso.hdr_len > len) - return -EINVAL; - } - if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { align = NET_IP_ALIGN; if (unlikely(len < ETH_HLEN)) @@ -324,16 +311,6 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, return -EFAULT; } - if (gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { - if (!skb_partial_csum_set(skb, gso.csum_start, - gso.csum_offset)) { - tun->dev->stats.rx_frame_errors++; - kfree_skb(skb); - return -EINVAL; - } - } else if (tun->flags & TUN_NOCHECKSUM) - skb->ip_summed = CHECKSUM_UNNECESSARY; - switch (tun->flags & TUN_TYPE_MASK) { case TUN_TUN_DEV: if (tun->flags & TUN_NO_PI) { @@ -360,35 +337,8 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, break; }; - if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { - pr_debug("GSO!\n"); - switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { - case VIRTIO_NET_HDR_GSO_TCPV4: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; - break; - case VIRTIO_NET_HDR_GSO_TCPV6: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; - break; - default: - tun->dev->stats.rx_frame_errors++; - kfree_skb(skb); - return -EINVAL; - } - - if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN) - skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; - - skb_shinfo(skb)->gso_size = gso.gso_size; - if (skb_shinfo(skb)->gso_size == 0) { - tun->dev->stats.rx_frame_errors++; - kfree_skb(skb); - return -EINVAL; - } - - /* Header must be checked, and gso_segs computed. */ - skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; - skb_shinfo(skb)->gso_segs = 0; - } + if (tun->flags & TUN_NOCHECKSUM) + skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx_ni(skb); tun->dev->last_rx = jiffies; @@ -434,39 +384,6 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun, total += sizeof(pi); } - if (tun->flags & TUN_VNET_HDR) { - struct virtio_net_hdr gso = { 0 }; /* no info leak */ - if ((len -= sizeof(gso)) < 0) - return -EINVAL; - - if (skb_is_gso(skb)) { - struct skb_shared_info *sinfo = skb_shinfo(skb); - - /* This is a hint as to how much should be linear. */ - gso.hdr_len = skb_headlen(skb); - gso.gso_size = sinfo->gso_size; - if (sinfo->gso_type & SKB_GSO_TCPV4) - 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 - BUG(); - if (sinfo->gso_type & SKB_GSO_TCP_ECN) - gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN; - } else - gso.gso_type = VIRTIO_NET_HDR_GSO_NONE; - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - gso.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; - gso.csum_start = skb->csum_start - skb_headroom(skb); - gso.csum_offset = skb->csum_offset; - } /* else everything is zero */ - - if (unlikely(memcpy_toiovec(iv, (void *)&gso, sizeof(gso)))) - return -EFAULT; - total += sizeof(gso); - } - len = min_t(int, skb->len, len); skb_copy_datagram_iovec(skb, 0, iv, len); @@ -681,11 +598,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) else tun->flags &= ~TUN_ONE_QUEUE; - if (ifr->ifr_flags & IFF_VNET_HDR) - tun->flags |= TUN_VNET_HDR; - else - tun->flags &= ~TUN_VNET_HDR; - file->private_data = tun; tun->attached = 1; get_net(dev_net(tun->dev)); @@ -699,46 +611,6 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) return err; } -/* This is like a cut-down ethtool ops, except done via tun fd so no - * privs required. */ -static int set_offload(struct net_device *dev, unsigned long arg) -{ - unsigned int old_features, features; - - 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)); - - if (arg & TUN_F_CSUM) { - features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST; - arg &= ~TUN_F_CSUM; - - if (arg & (TUN_F_TSO4|TUN_F_TSO6)) { - if (arg & TUN_F_TSO_ECN) { - features |= NETIF_F_TSO_ECN; - arg &= ~TUN_F_TSO_ECN; - } - if (arg & TUN_F_TSO4) - features |= NETIF_F_TSO; - if (arg & TUN_F_TSO6) - features |= NETIF_F_TSO6; - arg &= ~(TUN_F_TSO4|TUN_F_TSO6); - } - } - - /* This gives the user a way to test for new features in future by - * trying to set them. */ - if (arg) - return -EINVAL; - - dev->features = features; - if (old_features != dev->features) - netdev_features_change(dev); - - return 0; -} - static int tun_chr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -768,15 +640,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, return 0; } - if (cmd == TUNGETFEATURES) { - /* Currently this just means: "what IFF flags are valid?". - * This is needed because we never checked for invalid flags on - * TUNSETIFF. */ - return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | - IFF_VNET_HDR, - (unsigned int __user*)argp); - } - if (!tun) return -EBADFD; @@ -844,15 +707,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, break; #endif - case TUNSETOFFLOAD: - { - int ret; - rtnl_lock(); - ret = set_offload(tun->dev, arg); - rtnl_unlock(); - return ret; - } - case SIOCGIFFLAGS: ifr.ifr_flags = tun->if_flags; if (copy_to_user( argp, &ifr, sizeof ifr)) diff --git a/trunk/drivers/net/wan/x25_asy.c b/trunk/drivers/net/wan/x25_asy.c index 069f8bb0a99f..249e18053d5f 100644 --- a/trunk/drivers/net/wan/x25_asy.c +++ b/trunk/drivers/net/wan/x25_asy.c @@ -32,7 +32,6 @@ #include #include #include -#include #include "x25_asy.h" #include @@ -602,10 +601,8 @@ static void x25_asy_close_tty(struct tty_struct *tty) if (!sl || sl->magic != X25_ASY_MAGIC) return; - rtnl_lock(); if (sl->dev->flags & IFF_UP) dev_close(sl->dev); - rtnl_unlock(); tty->disc_data = NULL; sl->tty = NULL; diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig index 865f2980c273..22e1e9a1fb73 100644 --- a/trunk/drivers/net/wireless/Kconfig +++ b/trunk/drivers/net/wireless/Kconfig @@ -14,6 +14,30 @@ config WLAN_PRE80211 This option does not affect the kernel build, it only lets you choose drivers. +config STRIP + tristate "STRIP (Metricom starmode radio IP)" + depends on INET && WLAN_PRE80211 + select WIRELESS_EXT + ---help--- + Say Y if you have a Metricom radio and intend to use Starmode Radio + IP. STRIP is a radio protocol developed for the MosquitoNet project + (on the WWW at ) to send Internet + traffic using Metricom radios. Metricom radios are small, battery + powered, 100kbit/sec packet radio transceivers, about the size and + weight of a cellular telephone. (You may also have heard them called + "Metricom modems" but we avoid the term "modem" because it misleads + many people into thinking that you can plug a Metricom modem into a + phone line and use it as a modem.) + + You can use STRIP on any Linux machine with a serial port, although + it is obviously most useful for people with laptop computers. If you + think you might get a Metricom radio in the future, there is no harm + in saying Y to STRIP now, except that it makes the kernel a bit + bigger. + + To compile this as a module, choose M here: the module will be + called strip. + config ARLAN tristate "Aironet Arlan 655 & IC2200 DS support" depends on ISA && !64BIT && WLAN_PRE80211 diff --git a/trunk/drivers/net/wireless/Makefile b/trunk/drivers/net/wireless/Makefile index 2668934abbff..54a4f6f1db67 100644 --- a/trunk/drivers/net/wireless/Makefile +++ b/trunk/drivers/net/wireless/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_IPW2100) += ipw2100.o obj-$(CONFIG_IPW2200) += ipw2200.o +obj-$(CONFIG_STRIP) += strip.o obj-$(CONFIG_ARLAN) += arlan.o arlan-objs := arlan-main.o arlan-proc.o diff --git a/trunk/drivers/net/wireless/adm8211.c b/trunk/drivers/net/wireless/adm8211.c index 3333d4596b8d..0ba55ba93958 100644 --- a/trunk/drivers/net/wireless/adm8211.c +++ b/trunk/drivers/net/wireless/adm8211.c @@ -1685,6 +1685,7 @@ static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb, static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) { struct adm8211_tx_hdr *txhdr; + u16 fc; size_t payload_len, hdrlen; int plcp, dur, len, plcp_signal, short_preamble; struct ieee80211_hdr *hdr; @@ -1695,7 +1696,8 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) plcp_signal = txrate->bitrate; hdr = (struct ieee80211_hdr *)skb->data; - hdrlen = ieee80211_hdrlen(hdr->frame_control); + fc = le16_to_cpu(hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED; + hdrlen = ieee80211_get_hdrlen(fc); memcpy(skb->cb, skb->data, hdrlen); hdr = (struct ieee80211_hdr *)skb->cb; skb_pull(skb, hdrlen); @@ -1709,6 +1711,8 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) txhdr->frame_control = hdr->frame_control; len = hdrlen + payload_len + FCS_LEN; + if (fc & IEEE80211_FCTL_PROTECTED) + len += 8; txhdr->frag = cpu_to_le16(0x0FFF); adm8211_calc_durations(&dur, &plcp, payload_len, @@ -1726,6 +1730,9 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS); + if (fc & IEEE80211_FCTL_PROTECTED) + txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_WEP_ENGINE); + txhdr->retry_limit = info->control.retry_limit; adm8211_tx_raw(dev, skb, plcp_signal, hdrlen); diff --git a/trunk/drivers/net/wireless/airo.c b/trunk/drivers/net/wireless/airo.c index b5cd850a4a59..e30f8b79ea89 100644 --- a/trunk/drivers/net/wireless/airo.c +++ b/trunk/drivers/net/wireless/airo.c @@ -85,10 +85,10 @@ static struct pci_driver airo_driver = { /* Include Wireless Extension definition and check version - Jean II */ #include -#define WIRELESS_SPY /* enable iwspy support */ -#include /* New driver API */ +#define WIRELESS_SPY // enable iwspy support +#include // New driver API -#define CISCO_EXT /* enable Cisco extensions */ +#define CISCO_EXT // enable Cisco extensions #ifdef CISCO_EXT #include #endif @@ -281,7 +281,7 @@ MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc"); /* This is a kind of sloppy hack to get this information to OUT4500 and IN4500. I would be extremely interested in the situation where this doesn't work though!!! */ -static int do8bitIO /* = 0 */; +static int do8bitIO = 0; /* Return codes */ #define SUCCESS 0 @@ -398,8 +398,8 @@ static int do8bitIO /* = 0 */; #define MAXTXQ 64 /* BAP selectors */ -#define BAP0 0 /* Used for receiving packets */ -#define BAP1 2 /* Used for xmiting packets and working with RIDS */ +#define BAP0 0 // Used for receiving packets +#define BAP1 2 // Used for xmiting packets and working with RIDS /* Flags */ #define COMMAND_BUSY 0x8000 @@ -5522,13 +5522,11 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) Cmd cmd; Resp rsp; - if (!ai->APList) - ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL); - if (!ai->APList) + if ((ai->APList == NULL) && + (ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL)) == NULL) return -ENOMEM; - if (!ai->SSID) - ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL); - if (!ai->SSID) + if ((ai->SSID == NULL) && + (ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL)) == NULL) return -ENOMEM; readAPListRid(ai, ai->APList); readSsidRid(ai, ai->SSID); @@ -5539,7 +5537,7 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) disable_MAC(ai, 0); netif_device_detach(dev); ai->power = state; - cmd.cmd = HOSTSLEEP; + cmd.cmd=HOSTSLEEP; issuecommand(ai, &cmd, &rsp); pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); @@ -5569,7 +5567,7 @@ static int airo_pci_resume(struct pci_dev *pdev) msleep(100); } - set_bit(FLAG_COMMIT, &ai->flags); + set_bit (FLAG_COMMIT, &ai->flags); disable_MAC(ai, 0); msleep(200); if (ai->SSID) { @@ -5596,6 +5594,9 @@ static int airo_pci_resume(struct pci_dev *pdev) static int __init airo_init_module( void ) { int i; +#if 0 + int have_isa_dev = 0; +#endif airo_entry = create_proc_entry("driver/aironet", S_IFDIR | airo_perm, @@ -5606,11 +5607,15 @@ static int __init airo_init_module( void ) airo_entry->gid = proc_gid; } - for (i = 0; i < 4 && io[i] && irq[i]; i++) { + for( i = 0; i < 4 && io[i] && irq[i]; i++ ) { airo_print_info("", "Trying to configure ISA adapter at irq=%d " "io=0x%x", irq[i], io[i] ); if (init_airo_card( irq[i], io[i], 0, NULL )) +#if 0 + have_isa_dev = 1; +#else /* do nothing */ ; +#endif } #ifdef CONFIG_PCI @@ -5656,7 +5661,7 @@ static void __exit airo_cleanup_module( void ) static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi) { - if (!rssi_rid) + if( !rssi_rid ) return 0; return (0x100 - rssi_rid[rssi].rssidBm); @@ -5666,10 +5671,10 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm) { int i; - if (!rssi_rid) + if( !rssi_rid ) return 0; - for (i = 0; i < 256; i++) + for( i = 0; i < 256; i++ ) if (rssi_rid[i].rssidBm == dbm) return rssi_rid[i].rssipct; @@ -7151,7 +7156,6 @@ static int airo_set_scan(struct net_device *dev, * format that the Wireless Tools will understand - Jean II */ static inline char *airo_translate_scan(struct net_device *dev, - struct iw_request_info *info, char *current_ev, char *end_buf, BSSListRid *bss) @@ -7168,8 +7172,7 @@ static inline char *airo_translate_scan(struct net_device *dev, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_ADDR_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); /* Other entries will be displayed in the order we give them */ @@ -7179,8 +7182,7 @@ static inline char *airo_translate_scan(struct net_device *dev, iwe.u.data.length = 32; iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); /* Add mode */ iwe.cmd = SIOCGIWMODE; @@ -7190,8 +7192,7 @@ static inline char *airo_translate_scan(struct net_device *dev, iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); } /* Add frequency */ @@ -7202,8 +7203,7 @@ static inline char *airo_translate_scan(struct net_device *dev, */ iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000; iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_FREQ_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); dBm = le16_to_cpu(bss->dBm); @@ -7223,8 +7223,7 @@ static inline char *airo_translate_scan(struct net_device *dev, | IW_QUAL_DBM; } iwe.u.qual.noise = ai->wstats.qual.noise; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_QUAL_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); /* Add encryption capability */ iwe.cmd = SIOCGIWENCODE; @@ -7233,12 +7232,11 @@ static inline char *airo_translate_scan(struct net_device *dev, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid); /* Rate : stuffing multiple values in a single event require a bit * more of magic - Jean II */ - current_val = current_ev + iwe_stream_lcp_len(info); + current_val = current_ev + IW_EV_LCP_LEN; iwe.cmd = SIOCGIWRATE; /* Those two flags are ignored... */ @@ -7251,12 +7249,10 @@ static inline char *airo_translate_scan(struct net_device *dev, /* Bit rate given in 500 kb/s units (+ 0x80) */ iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000); /* Add new value to event */ - current_val = iwe_stream_add_value(info, current_ev, - current_val, end_buf, - &iwe, IW_EV_PARAM_LEN); + current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } /* Check if we added any event */ - if ((current_val - current_ev) > iwe_stream_lcp_len(info)) + if((current_val - current_ev) > IW_EV_LCP_LEN) current_ev = current_val; /* Beacon interval */ @@ -7265,8 +7261,7 @@ static inline char *airo_translate_scan(struct net_device *dev, iwe.cmd = IWEVCUSTOM; sprintf(buf, "bcn_int=%d", bss->beaconInterval); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, buf); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); kfree(buf); } @@ -7300,10 +7295,8 @@ static inline char *airo_translate_scan(struct net_device *dev, iwe.cmd = IWEVGENIE; iwe.u.data.length = min(info_element->len + 2, MAX_WPA_IE_LEN); - current_ev = iwe_stream_add_point( - info, current_ev, - end_buf, &iwe, - (char *) info_element); + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, (char *) info_element); } break; @@ -7311,9 +7304,8 @@ static inline char *airo_translate_scan(struct net_device *dev, iwe.cmd = IWEVGENIE; iwe.u.data.length = min(info_element->len + 2, MAX_WPA_IE_LEN); - current_ev = iwe_stream_add_point( - info, current_ev, end_buf, - &iwe, (char *) info_element); + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, (char *) info_element); break; default: @@ -7352,7 +7344,7 @@ static int airo_get_scan(struct net_device *dev, list_for_each_entry (net, &ai->network_list, list) { /* Translate to WE format this entry */ - current_ev = airo_translate_scan(dev, info, current_ev, + current_ev = airo_translate_scan(dev, current_ev, extra + dwrq->length, &net->bss); diff --git a/trunk/drivers/net/wireless/ath5k/Kconfig b/trunk/drivers/net/wireless/ath5k/Kconfig index 75383a5df992..f1f2aea2eab4 100644 --- a/trunk/drivers/net/wireless/ath5k/Kconfig +++ b/trunk/drivers/net/wireless/ath5k/Kconfig @@ -1,9 +1,6 @@ config ATH5K tristate "Atheros 5xxx wireless cards support" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL - select MAC80211_LEDS - select LEDS_CLASS - select NEW_LEDS ---help--- This module adds support for wireless adapters based on Atheros 5xxx chipset. diff --git a/trunk/drivers/net/wireless/ath5k/base.c b/trunk/drivers/net/wireless/ath5k/base.c index a43e9b25169b..85045afc1ba7 100644 --- a/trunk/drivers/net/wireless/ath5k/base.c +++ b/trunk/drivers/net/wireless/ath5k/base.c @@ -58,6 +58,11 @@ #include "reg.h" #include "debug.h" +enum { + ATH_LED_TX, + ATH_LED_RX, +}; + static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ @@ -304,10 +309,13 @@ static void ath5k_tasklet_reset(unsigned long data); static void ath5k_calibrate(unsigned long data); /* LED functions */ -static int ath5k_init_leds(struct ath5k_softc *sc); -static void ath5k_led_enable(struct ath5k_softc *sc); -static void ath5k_led_off(struct ath5k_softc *sc); -static void ath5k_unregister_leds(struct ath5k_softc *sc); +static void ath5k_led_off(unsigned long data); +static void ath5k_led_blink(struct ath5k_softc *sc, + unsigned int on, + unsigned int off); +static void ath5k_led_event(struct ath5k_softc *sc, + int event); + /* * Module init/exit functions @@ -588,7 +596,8 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath5k_softc *sc = hw->priv; - ath5k_led_off(sc); + if (test_bit(ATH_STAT_LEDSOFT, sc->status)) + ath5k_hw_set_gpio(sc->ah, sc->led_pin, 1); ath5k_stop_hw(sc); pci_save_state(pdev); @@ -623,7 +632,10 @@ ath5k_pci_resume(struct pci_dev *pdev) pci_write_config_byte(pdev, 0x41, 0); ath5k_init(sc); - ath5k_led_enable(sc); + if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { + ath5k_hw_set_gpio_output(ah, sc->led_pin); + ath5k_hw_set_gpio(ah, sc->led_pin, 0); + } /* * Reset the key cache since some parts do not @@ -730,6 +742,27 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); + setup_timer(&sc->led_tim, ath5k_led_off, (unsigned long)sc); + + sc->led_on = 0; /* low true */ + /* + * Auto-enable soft led processing for IBM cards and for + * 5211 minipci cards. + */ + if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM || + pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { + __set_bit(ATH_STAT_LEDSOFT, sc->status); + sc->led_pin = 0; + } + /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ + if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { + __set_bit(ATH_STAT_LEDSOFT, sc->status); + sc->led_pin = 0; + } + if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { + ath5k_hw_set_gpio_output(ah, sc->led_pin); + ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on); + } ath5k_hw_get_lladdr(ah, mac); SET_IEEE80211_PERM_ADDR(hw, mac); @@ -743,8 +776,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) goto err_queues; } - ath5k_init_leds(sc); - return 0; err_queues: ath5k_txq_release(sc); @@ -778,7 +809,6 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) ath5k_desc_free(sc, pdev); ath5k_txq_release(sc); ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); - ath5k_unregister_leds(sc); /* * NB: can't reclaim these until after ieee80211_ifdetach @@ -1030,9 +1060,65 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) return 0; } +/* + * TODO: CLEAN THIS !!! + */ static void ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) { + if (unlikely(test_bit(ATH_STAT_LEDSOFT, sc->status))) { + /* from Atheros NDIS driver, w/ permission */ + static const struct { + u16 rate; /* tx/rx 802.11 rate */ + u16 timeOn; /* LED on time (ms) */ + u16 timeOff; /* LED off time (ms) */ + } blinkrates[] = { + { 108, 40, 10 }, + { 96, 44, 11 }, + { 72, 50, 13 }, + { 48, 57, 14 }, + { 36, 67, 16 }, + { 24, 80, 20 }, + { 22, 100, 25 }, + { 18, 133, 34 }, + { 12, 160, 40 }, + { 10, 200, 50 }, + { 6, 240, 58 }, + { 4, 267, 66 }, + { 2, 400, 100 }, + { 0, 500, 130 } + }; + const struct ath5k_rate_table *rt = + ath5k_hw_get_rate_table(sc->ah, mode); + unsigned int i, j; + + BUG_ON(rt == NULL); + + memset(sc->hwmap, 0, sizeof(sc->hwmap)); + for (i = 0; i < 32; i++) { + u8 ix = rt->rate_code_to_index[i]; + if (ix == 0xff) { + sc->hwmap[i].ledon = msecs_to_jiffies(500); + sc->hwmap[i].ledoff = msecs_to_jiffies(130); + continue; + } + sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD; + /* receive frames include FCS */ + sc->hwmap[i].rxflags = sc->hwmap[i].txflags | + IEEE80211_RADIOTAP_F_FCS; + /* setup blink rate table to avoid per-packet lookup */ + for (j = 0; j < ARRAY_SIZE(blinkrates) - 1; j++) + if (blinkrates[j].rate == /* XXX why 7f? */ + (rt->rates[ix].dot11_rate&0x7f)) + break; + + sc->hwmap[i].ledon = msecs_to_jiffies(blinkrates[j]. + timeOn); + sc->hwmap[i].ledoff = msecs_to_jiffies(blinkrates[j]. + timeOff); + } + } + sc->curmode = mode; if (mode == AR5K_MODE_11A) { @@ -1605,9 +1691,9 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, /* Apparently when a default key is used to decrypt the packet the hw does not set the index used to decrypt. In such cases get the index from the packet. */ - if (ieee80211_has_protected(hdr->frame_control) && - !(rs->rs_status & AR5K_RXERR_DECRYPT) && - skb->len >= hlen + 4) { + if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) && + !(rs->rs_status & AR5K_RXERR_DECRYPT) && + skb->len >= hlen + 4) { keyix = skb->data[hlen + 3] >> 6; if (test_bit(keyix, sc->keymap)) @@ -1626,7 +1712,10 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, u32 hw_tu; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - if (ieee80211_is_beacon(mgmt->frame_control) && + if ((le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_FTYPE) == + IEEE80211_FTYPE_MGMT && + (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) == + IEEE80211_STYPE_BEACON && le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { /* @@ -1814,6 +1903,8 @@ ath5k_tasklet_rx(unsigned long data) ath5k_check_ibss_tsf(sc, skb, &rxs); __ieee80211_rx(sc->hw, skb, &rxs); + sc->led_rxrate = rs.rs_rate; + ath5k_led_event(sc, ATH_LED_RX); next: list_move_tail(&bf->list, &sc->rxbuf); } while (ath5k_rxbuf_setup(sc, bf) == 0); @@ -1894,9 +1985,13 @@ ath5k_tasklet_tx(unsigned long data) struct ath5k_softc *sc = (void *)data; ath5k_tx_processq(sc, sc->txq); + + ath5k_led_event(sc, ATH_LED_TX); } + + /*****************\ * Beacon handling * \*****************/ @@ -2271,7 +2366,11 @@ ath5k_stop_locked(struct ath5k_softc *sc) ieee80211_stop_queues(sc->hw); if (!test_bit(ATH_STAT_INVALID, sc->status)) { - ath5k_led_off(sc); + if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { + del_timer_sync(&sc->led_tim); + ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on); + __clear_bit(ATH_STAT_LEDBLINKING, sc->status); + } ath5k_hw_set_intr(ah, 0); } ath5k_txq_cleanup(sc); @@ -2467,124 +2566,55 @@ ath5k_calibrate(unsigned long data) \***************/ static void -ath5k_led_enable(struct ath5k_softc *sc) +ath5k_led_off(unsigned long data) { - if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { - ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); - ath5k_led_off(sc); + struct ath5k_softc *sc = (void *)data; + + if (test_bit(ATH_STAT_LEDENDBLINK, sc->status)) + __clear_bit(ATH_STAT_LEDBLINKING, sc->status); + else { + __set_bit(ATH_STAT_LEDENDBLINK, sc->status); + ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); + mod_timer(&sc->led_tim, jiffies + sc->led_off); } } +/* + * Blink the LED according to the specified on/off times. + */ static void -ath5k_led_on(struct ath5k_softc *sc) +ath5k_led_blink(struct ath5k_softc *sc, unsigned int on, + unsigned int off) { - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - return; + ATH5K_DBG(sc, ATH5K_DEBUG_LED, "on %u off %u\n", on, off); ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); + __set_bit(ATH_STAT_LEDBLINKING, sc->status); + __clear_bit(ATH_STAT_LEDENDBLINK, sc->status); + sc->led_off = off; + mod_timer(&sc->led_tim, jiffies + on); } static void -ath5k_led_off(struct ath5k_softc *sc) +ath5k_led_event(struct ath5k_softc *sc, int event) { - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) + if (likely(!test_bit(ATH_STAT_LEDSOFT, sc->status))) return; - ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); -} - -static void -ath5k_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct ath5k_led *led = container_of(led_dev, struct ath5k_led, - led_dev); - - if (brightness == LED_OFF) - ath5k_led_off(led->sc); - else - ath5k_led_on(led->sc); -} - -static int -ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, - const char *name, char *trigger) -{ - int err; - - led->sc = sc; - strncpy(led->name, name, sizeof(led->name)); - led->led_dev.name = led->name; - led->led_dev.default_trigger = trigger; - led->led_dev.brightness_set = ath5k_led_brightness_set; - - err = led_classdev_register(&sc->pdev->dev, &led->led_dev); - if (err) - { - ATH5K_WARN(sc, "could not register LED %s\n", name); - led->sc = NULL; + if (unlikely(test_bit(ATH_STAT_LEDBLINKING, sc->status))) + return; /* don't interrupt active blink */ + switch (event) { + case ATH_LED_TX: + ath5k_led_blink(sc, sc->hwmap[sc->led_txrate].ledon, + sc->hwmap[sc->led_txrate].ledoff); + break; + case ATH_LED_RX: + ath5k_led_blink(sc, sc->hwmap[sc->led_rxrate].ledon, + sc->hwmap[sc->led_rxrate].ledoff); + break; } - return err; -} - -static void -ath5k_unregister_led(struct ath5k_led *led) -{ - if (!led->sc) - return; - led_classdev_unregister(&led->led_dev); - ath5k_led_off(led->sc); - led->sc = NULL; } -static void -ath5k_unregister_leds(struct ath5k_softc *sc) -{ - ath5k_unregister_led(&sc->rx_led); - ath5k_unregister_led(&sc->tx_led); -} -static int -ath5k_init_leds(struct ath5k_softc *sc) -{ - int ret = 0; - struct ieee80211_hw *hw = sc->hw; - struct pci_dev *pdev = sc->pdev; - char name[ATH5K_LED_MAX_NAME_LEN + 1]; - - sc->led_on = 0; /* active low */ - - /* - * Auto-enable soft led processing for IBM cards and for - * 5211 minipci cards. - */ - if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM || - pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = 0; - } - /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */ - if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = 1; - } - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - goto out; - - ath5k_led_enable(sc); - - snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->rx_led, name, - ieee80211_get_rx_led_name(hw)); - if (ret) - goto out; - - snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->tx_led, name, - ieee80211_get_tx_led_name(hw)); -out: - return ret; -} - /********************\ * Mac80211 functions * @@ -2595,6 +2625,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ath5k_softc *sc = hw->priv; struct ath5k_buf *bf; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); unsigned long flags; int hdrlen; int pad; @@ -2620,6 +2651,8 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) memmove(skb->data, skb->data+pad, hdrlen); } + sc->led_txrate = ieee80211_get_tx_rate(hw, info)->hw_value; + spin_lock_irqsave(&sc->txbuflock, flags); if (list_empty(&sc->txbuf)) { ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); diff --git a/trunk/drivers/net/wireless/ath5k/base.h b/trunk/drivers/net/wireless/ath5k/base.h index 47f414b09e67..bb4b26d523ab 100644 --- a/trunk/drivers/net/wireless/ath5k/base.h +++ b/trunk/drivers/net/wireless/ath5k/base.h @@ -45,7 +45,6 @@ #include #include #include -#include #include "ath5k.h" #include "debug.h" @@ -80,19 +79,6 @@ struct ath5k_txq { bool setup; }; -#define ATH5K_LED_MAX_NAME_LEN 31 - -/* - * State for LED triggers - */ -struct ath5k_led -{ - char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */ - struct ath5k_softc *sc; /* driver state */ - struct led_classdev led_dev; /* led classdev */ -}; - - #if CHAN_DEBUG #define ATH_CHAN_MAX (26+26+26+200+200) #else @@ -132,11 +118,13 @@ struct ath5k_softc { size_t desc_len; /* size of TX/RX descriptors */ u16 cachelsz; /* cache line size */ - DECLARE_BITMAP(status, 4); + DECLARE_BITMAP(status, 6); #define ATH_STAT_INVALID 0 /* disable hardware accesses */ #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ #define ATH_STAT_PROMISC 2 -#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ +#define ATH_STAT_LEDBLINKING 3 /* LED blink operation active */ +#define ATH_STAT_LEDENDBLINK 4 /* finish LED blink operation */ +#define ATH_STAT_LEDSOFT 5 /* enable LED gpio status */ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ unsigned int curmode; /* current phy mode */ @@ -144,6 +132,13 @@ struct ath5k_softc { struct ieee80211_vif *vif; + struct { + u8 rxflags; /* radiotap rx flags */ + u8 txflags; /* radiotap tx flags */ + u16 ledon; /* softled on time */ + u16 ledoff; /* softled off time */ + } hwmap[32]; /* h/w rate ix mappings */ + enum ath5k_int imask; /* interrupt mask copy */ DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ @@ -153,6 +148,9 @@ struct ath5k_softc { unsigned int led_pin, /* GPIO pin for driving LED */ led_on, /* pin setting for LED on */ led_off; /* off time for current blink */ + struct timer_list led_tim; /* led off timer */ + u8 led_rxrate; /* current rx rate for LED */ + u8 led_txrate; /* current tx rate for LED */ struct tasklet_struct restq; /* reset tasklet */ @@ -161,7 +159,6 @@ struct ath5k_softc { spinlock_t rxbuflock; u32 *rxlink; /* link ptr in last RX desc */ struct tasklet_struct rxtq; /* rx intr tasklet */ - struct ath5k_led rx_led; /* rx led */ struct list_head txbuf; /* transmit buffer */ spinlock_t txbuflock; @@ -170,7 +167,6 @@ struct ath5k_softc { struct ath5k_txq *txq; /* beacon and tx*/ struct tasklet_struct txtq; /* tx intr tasklet */ - struct ath5k_led tx_led; /* tx led */ struct ath5k_buf *bbuf; /* beacon buffer */ unsigned int bhalq, /* SW q for outgoing beacons */ diff --git a/trunk/drivers/net/wireless/ath5k/hw.c b/trunk/drivers/net/wireless/ath5k/hw.c index c6d12c53bda4..77990b56860b 100644 --- a/trunk/drivers/net/wireless/ath5k/hw.c +++ b/trunk/drivers/net/wireless/ath5k/hw.c @@ -31,14 +31,14 @@ #include "base.h" #include "debug.h" -/* Rate tables */ +/*Rate tables*/ static const struct ath5k_rate_table ath5k_rt_11a = AR5K_RATES_11A; static const struct ath5k_rate_table ath5k_rt_11b = AR5K_RATES_11B; static const struct ath5k_rate_table ath5k_rt_11g = AR5K_RATES_11G; static const struct ath5k_rate_table ath5k_rt_turbo = AR5K_RATES_TURBO; static const struct ath5k_rate_table ath5k_rt_xr = AR5K_RATES_XR; -/* Prototypes */ +/*Prototypes*/ static int ath5k_hw_nic_reset(struct ath5k_hw *, u32); static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool); static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, diff --git a/trunk/drivers/net/wireless/atmel.c b/trunk/drivers/net/wireless/atmel.c index 28b6ff3eaa37..7bb2646ae0ef 100644 --- a/trunk/drivers/net/wireless/atmel.c +++ b/trunk/drivers/net/wireless/atmel.c @@ -2310,40 +2310,30 @@ static int atmel_get_scan(struct net_device *dev, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6); - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_ADDR_LEN); + current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN); iwe.u.data.length = priv->BSSinfo[i].SSIDsize; if (iwe.u.data.length > 32) iwe.u.data.length = 32; iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, priv->BSSinfo[i].SSID); + current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, priv->BSSinfo[i].SSID); iwe.cmd = SIOCGIWMODE; iwe.u.mode = priv->BSSinfo[i].BSStype; - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_UINT_LEN); + current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN); iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = priv->BSSinfo[i].channel; iwe.u.freq.e = 0; - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_FREQ_LEN); + current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN); /* Add quality statistics */ iwe.cmd = IWEVQUAL; iwe.u.qual.level = priv->BSSinfo[i].RSSI; iwe.u.qual.qual = iwe.u.qual.level; /* iwe.u.qual.noise = SOMETHING */ - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_QUAL_LEN); + current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA , &iwe, IW_EV_QUAL_LEN); iwe.cmd = SIOCGIWENCODE; @@ -2352,9 +2342,7 @@ static int atmel_get_scan(struct net_device *dev, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, NULL); + current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL); } /* Length of data */ diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index edcdfa366452..532365f5ecef 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -441,8 +441,6 @@ enum { #define B43_FWPANIC_DIE 0 /* Firmware died. Don't auto-restart it. */ #define B43_FWPANIC_RESTART 1 /* Firmware died. Schedule a controller reset. */ -/* The firmware register that contains the watchdog counter. */ -#define B43_WATCHDOG_REG 1 /* Device specific rate values. * The actual values defined here are (rate_in_mbps * 2). diff --git a/trunk/drivers/net/wireless/b43/debugfs.c b/trunk/drivers/net/wireless/b43/debugfs.c index 29851bc1101f..210e2789c1c3 100644 --- a/trunk/drivers/net/wireless/b43/debugfs.c +++ b/trunk/drivers/net/wireless/b43/debugfs.c @@ -74,327 +74,70 @@ struct b43_dfs_file * fops_to_dfs_file(struct b43_wldev *dev, } while (0) -/* The biggest address values for SHM access from the debugfs files. */ -#define B43_MAX_SHM_ROUTING 4 -#define B43_MAX_SHM_ADDR 0xFFFF - -static ssize_t shm16read__read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) +/* wl->irq_lock is locked */ +static ssize_t tsf_read_file(struct b43_wldev *dev, + char *buf, size_t bufsize) { ssize_t count = 0; - unsigned int routing, addr; - u16 val; - - routing = dev->dfsentry->shm16read_routing_next; - addr = dev->dfsentry->shm16read_addr_next; - if ((routing > B43_MAX_SHM_ROUTING) || - (addr > B43_MAX_SHM_ADDR)) - return -EDESTADDRREQ; + u64 tsf; - val = b43_shm_read16(dev, routing, addr); - fappend("0x%04X\n", val); + b43_tsf_read(dev, &tsf); + fappend("0x%08x%08x\n", + (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), + (unsigned int)(tsf & 0xFFFFFFFFULL)); return count; } -static int shm16read__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int routing, addr; - int res; - - res = sscanf(buf, "0x%X 0x%X", &routing, &addr); - if (res != 2) - return -EINVAL; - if (routing > B43_MAX_SHM_ROUTING) - return -EADDRNOTAVAIL; - if (addr > B43_MAX_SHM_ADDR) - return -EADDRNOTAVAIL; - if (routing == B43_SHM_SHARED) { - if ((addr % 2) != 0) - return -EADDRNOTAVAIL; - } - - dev->dfsentry->shm16read_routing_next = routing; - dev->dfsentry->shm16read_addr_next = addr; - - return 0; -} - -static int shm16write__write_file(struct b43_wldev *dev, - const char *buf, size_t count) +/* wl->irq_lock is locked */ +static int tsf_write_file(struct b43_wldev *dev, + const char *buf, size_t count) { - unsigned int routing, addr, mask, set; - u16 val; - int res; - unsigned long flags; + u64 tsf; - res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", - &routing, &addr, &mask, &set); - if (res != 4) + if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1) return -EINVAL; - if (routing > B43_MAX_SHM_ROUTING) - return -EADDRNOTAVAIL; - if (addr > B43_MAX_SHM_ADDR) - return -EADDRNOTAVAIL; - if (routing == B43_SHM_SHARED) { - if ((addr % 2) != 0) - return -EADDRNOTAVAIL; - } - if ((mask > 0xFFFF) || (set > 0xFFFF)) - return -E2BIG; - - spin_lock_irqsave(&dev->wl->shm_lock, flags); - if (mask == 0) - val = 0; - else - val = __b43_shm_read16(dev, routing, addr); - val &= mask; - val |= set; - __b43_shm_write16(dev, routing, addr, val); - spin_unlock_irqrestore(&dev->wl->shm_lock, flags); + b43_tsf_write(dev, tsf); return 0; } -static ssize_t shm32read__read_file(struct b43_wldev *dev, +/* wl->irq_lock is locked */ +static ssize_t ucode_regs_read_file(struct b43_wldev *dev, char *buf, size_t bufsize) { ssize_t count = 0; - unsigned int routing, addr; - u32 val; - - routing = dev->dfsentry->shm32read_routing_next; - addr = dev->dfsentry->shm32read_addr_next; - if ((routing > B43_MAX_SHM_ROUTING) || - (addr > B43_MAX_SHM_ADDR)) - return -EDESTADDRREQ; - - val = b43_shm_read32(dev, routing, addr); - fappend("0x%08X\n", val); - - return count; -} - -static int shm32read__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int routing, addr; - int res; - - res = sscanf(buf, "0x%X 0x%X", &routing, &addr); - if (res != 2) - return -EINVAL; - if (routing > B43_MAX_SHM_ROUTING) - return -EADDRNOTAVAIL; - if (addr > B43_MAX_SHM_ADDR) - return -EADDRNOTAVAIL; - if (routing == B43_SHM_SHARED) { - if ((addr % 2) != 0) - return -EADDRNOTAVAIL; - } - - dev->dfsentry->shm32read_routing_next = routing; - dev->dfsentry->shm32read_addr_next = addr; - - return 0; -} - -static int shm32write__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int routing, addr, mask, set; - u32 val; - int res; - unsigned long flags; + int i; - res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", - &routing, &addr, &mask, &set); - if (res != 4) - return -EINVAL; - if (routing > B43_MAX_SHM_ROUTING) - return -EADDRNOTAVAIL; - if (addr > B43_MAX_SHM_ADDR) - return -EADDRNOTAVAIL; - if (routing == B43_SHM_SHARED) { - if ((addr % 2) != 0) - return -EADDRNOTAVAIL; + for (i = 0; i < 64; i++) { + fappend("r%d = 0x%04x\n", i, + b43_shm_read16(dev, B43_SHM_SCRATCH, i)); } - if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF)) - return -E2BIG; - - spin_lock_irqsave(&dev->wl->shm_lock, flags); - if (mask == 0) - val = 0; - else - val = __b43_shm_read32(dev, routing, addr); - val &= mask; - val |= set; - __b43_shm_write32(dev, routing, addr, val); - spin_unlock_irqrestore(&dev->wl->shm_lock, flags); - - return 0; -} - -/* The biggest MMIO address that we allow access to from the debugfs files. */ -#define B43_MAX_MMIO_ACCESS (0xF00 - 1) - -static ssize_t mmio16read__read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - unsigned int addr; - u16 val; - - addr = dev->dfsentry->mmio16read_next; - if (addr > B43_MAX_MMIO_ACCESS) - return -EDESTADDRREQ; - - val = b43_read16(dev, addr); - fappend("0x%04X\n", val); - - return count; -} - -static int mmio16read__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int addr; - int res; - - res = sscanf(buf, "0x%X", &addr); - if (res != 1) - return -EINVAL; - if (addr > B43_MAX_MMIO_ACCESS) - return -EADDRNOTAVAIL; - if ((addr % 2) != 0) - return -EINVAL; - - dev->dfsentry->mmio16read_next = addr; - - return 0; -} - -static int mmio16write__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int addr, mask, set; - int res; - u16 val; - - res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set); - if (res != 3) - return -EINVAL; - if (addr > B43_MAX_MMIO_ACCESS) - return -EADDRNOTAVAIL; - if ((mask > 0xFFFF) || (set > 0xFFFF)) - return -E2BIG; - if ((addr % 2) != 0) - return -EINVAL; - - if (mask == 0) - val = 0; - else - val = b43_read16(dev, addr); - val &= mask; - val |= set; - b43_write16(dev, addr, val); - - return 0; -} - -static ssize_t mmio32read__read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - unsigned int addr; - u32 val; - - addr = dev->dfsentry->mmio32read_next; - if (addr > B43_MAX_MMIO_ACCESS) - return -EDESTADDRREQ; - - val = b43_read32(dev, addr); - fappend("0x%08X\n", val); return count; } -static int mmio32read__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int addr; - int res; - - res = sscanf(buf, "0x%X", &addr); - if (res != 1) - return -EINVAL; - if (addr > B43_MAX_MMIO_ACCESS) - return -EADDRNOTAVAIL; - if ((addr % 4) != 0) - return -EINVAL; - - dev->dfsentry->mmio32read_next = addr; - - return 0; -} - -static int mmio32write__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int addr, mask, set; - int res; - u32 val; - - res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set); - if (res != 3) - return -EINVAL; - if (addr > B43_MAX_MMIO_ACCESS) - return -EADDRNOTAVAIL; - if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF)) - return -E2BIG; - if ((addr % 4) != 0) - return -EINVAL; - - if (mask == 0) - val = 0; - else - val = b43_read32(dev, addr); - val &= mask; - val |= set; - b43_write32(dev, addr, val); - - return 0; -} - /* wl->irq_lock is locked */ -static ssize_t tsf_read_file(struct b43_wldev *dev, +static ssize_t shm_read_file(struct b43_wldev *dev, char *buf, size_t bufsize) { ssize_t count = 0; - u64 tsf; + int i; + u16 tmp; + __le16 *le16buf = (__le16 *)buf; - b43_tsf_read(dev, &tsf); - fappend("0x%08x%08x\n", - (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), - (unsigned int)(tsf & 0xFFFFFFFFULL)); + for (i = 0; i < 0x1000; i++) { + if (bufsize < sizeof(tmp)) + break; + tmp = b43_shm_read16(dev, B43_SHM_SHARED, 2 * i); + le16buf[i] = cpu_to_le16(tmp); + count += sizeof(tmp); + bufsize -= sizeof(tmp); + } return count; } -/* wl->irq_lock is locked */ -static int tsf_write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - u64 tsf; - - if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1) - return -EINVAL; - b43_tsf_write(dev, tsf); - - return 0; -} - static ssize_t txstat_read_file(struct b43_wldev *dev, char *buf, size_t bufsize) { @@ -753,15 +496,9 @@ static ssize_t b43_debugfs_write(struct file *file, .take_irqlock = _take_irqlock, \ } -B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file, 1); -B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file, 1); -B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file, 1); -B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file, 1); -B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1); -B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); -B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); -B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); +B43_DEBUGFS_FOPS(ucode_regs, ucode_regs_read_file, NULL, 1); +B43_DEBUGFS_FOPS(shm, shm_read_file, NULL, 1); B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0); B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); @@ -801,7 +538,6 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); add_dyn_dbg("debug_lo", B43_DBG_LO, 0); - add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); #undef add_dyn_dbg } @@ -848,13 +584,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev) return; } - e->mmio16read_next = 0xFFFF; /* invalid address */ - e->mmio32read_next = 0xFFFF; /* invalid address */ - e->shm16read_routing_next = 0xFFFFFFFF; /* invalid routing */ - e->shm16read_addr_next = 0xFFFFFFFF; /* invalid address */ - e->shm32read_routing_next = 0xFFFFFFFF; /* invalid routing */ - e->shm32read_addr_next = 0xFFFFFFFF; /* invalid address */ - #define ADD_FILE(name, mode) \ do { \ struct dentry *d; \ @@ -867,15 +596,9 @@ void b43_debugfs_add_device(struct b43_wldev *dev) } while (0) - ADD_FILE(shm16read, 0600); - ADD_FILE(shm16write, 0200); - ADD_FILE(shm32read, 0600); - ADD_FILE(shm32write, 0200); - ADD_FILE(mmio16read, 0600); - ADD_FILE(mmio16write, 0200); - ADD_FILE(mmio32read, 0600); - ADD_FILE(mmio32write, 0200); ADD_FILE(tsf, 0600); + ADD_FILE(ucode_regs, 0400); + ADD_FILE(shm, 0400); ADD_FILE(txstat, 0400); ADD_FILE(txpower_g, 0600); ADD_FILE(restart, 0200); @@ -897,15 +620,9 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) return; b43_remove_dynamic_debug(dev); - debugfs_remove(e->file_shm16read.dentry); - debugfs_remove(e->file_shm16write.dentry); - debugfs_remove(e->file_shm32read.dentry); - debugfs_remove(e->file_shm32write.dentry); - debugfs_remove(e->file_mmio16read.dentry); - debugfs_remove(e->file_mmio16write.dentry); - debugfs_remove(e->file_mmio32read.dentry); - debugfs_remove(e->file_mmio32write.dentry); debugfs_remove(e->file_tsf.dentry); + debugfs_remove(e->file_ucode_regs.dentry); + debugfs_remove(e->file_shm.dentry); debugfs_remove(e->file_txstat.dentry); debugfs_remove(e->file_txpower_g.dentry); debugfs_remove(e->file_restart.dentry); diff --git a/trunk/drivers/net/wireless/b43/debugfs.h b/trunk/drivers/net/wireless/b43/debugfs.h index 22ffd02ba554..c75cff4151d9 100644 --- a/trunk/drivers/net/wireless/b43/debugfs.h +++ b/trunk/drivers/net/wireless/b43/debugfs.h @@ -11,7 +11,6 @@ enum b43_dyndbg { /* Dynamic debugging features */ B43_DBG_PWORK_FAST, B43_DBG_PWORK_STOP, B43_DBG_LO, - B43_DBG_FIRMWARE, __B43_NR_DYNDBG, }; @@ -37,15 +36,9 @@ struct b43_dfsentry { struct b43_wldev *dev; struct dentry *subdir; - struct b43_dfs_file file_shm16read; - struct b43_dfs_file file_shm16write; - struct b43_dfs_file file_shm32read; - struct b43_dfs_file file_shm32write; - struct b43_dfs_file file_mmio16read; - struct b43_dfs_file file_mmio16write; - struct b43_dfs_file file_mmio32read; - struct b43_dfs_file file_mmio32write; struct b43_dfs_file file_tsf; + struct b43_dfs_file file_ucode_regs; + struct b43_dfs_file file_shm; struct b43_dfs_file file_txstat; struct b43_dfs_file file_txpower_g; struct b43_dfs_file file_restart; @@ -53,18 +46,6 @@ struct b43_dfsentry { struct b43_txstatus_log txstatlog; - /* The cached address for the next mmio16read file read */ - u16 mmio16read_next; - /* The cached address for the next mmio32read file read */ - u16 mmio32read_next; - - /* The cached address for the next shm16read file read */ - u32 shm16read_routing_next; - u32 shm16read_addr_next; - /* The cached address for the next shm32read file read */ - u32 shm32read_routing_next; - u32 shm32read_addr_next; - /* Enabled/Disabled list for the dynamic debugging features. */ u32 dyn_debug[__B43_NR_DYNDBG]; /* Dentries for the dynamic debugging entries. */ diff --git a/trunk/drivers/net/wireless/b43/dma.c b/trunk/drivers/net/wireless/b43/dma.c index 098f886976f6..8a09a1db08db 100644 --- a/trunk/drivers/net/wireless/b43/dma.c +++ b/trunk/drivers/net/wireless/b43/dma.c @@ -328,11 +328,11 @@ static inline dma_addr_t dmaaddr; if (tx) { - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, DMA_TO_DEVICE); + dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + buf, len, DMA_TO_DEVICE); } else { - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, DMA_FROM_DEVICE); + dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + buf, len, DMA_FROM_DEVICE); } return dmaaddr; @@ -343,11 +343,11 @@ static inline dma_addr_t addr, size_t len, int tx) { if (tx) { - ssb_dma_unmap_single(ring->dev->dev, - addr, len, DMA_TO_DEVICE); + dma_unmap_single(ring->dev->dev->dma_dev, + addr, len, DMA_TO_DEVICE); } else { - ssb_dma_unmap_single(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); + dma_unmap_single(ring->dev->dev->dma_dev, + addr, len, DMA_FROM_DEVICE); } } @@ -356,8 +356,8 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - ssb_dma_sync_single_for_cpu(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(ring->dev->dev->dma_dev, + addr, len, DMA_FROM_DEVICE); } static inline @@ -365,8 +365,8 @@ static inline dma_addr_t addr, size_t len) { B43_WARN_ON(ring->tx); - ssb_dma_sync_single_for_device(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); + dma_sync_single_for_device(ring->dev->dev->dma_dev, + addr, len, DMA_FROM_DEVICE); } static inline @@ -381,6 +381,7 @@ static inline static int alloc_ringmemory(struct b43_dmaring *ring) { + struct device *dma_dev = ring->dev->dev->dma_dev; gfp_t flags = GFP_KERNEL; /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K @@ -391,14 +392,11 @@ static int alloc_ringmemory(struct b43_dmaring *ring) * For unknown reasons - possibly a hardware error - the BCM4311 rev * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, * which accounts for the GFP_DMA flag below. - * - * The flags here must match the flags in free_ringmemory below! */ if (ring->type == B43_DMA_64BIT) flags |= GFP_DMA; - ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, - B43_DMA_RINGMEMSIZE, - &(ring->dmabase), flags); + ring->descbase = dma_alloc_coherent(dma_dev, B43_DMA_RINGMEMSIZE, + &(ring->dmabase), flags); if (!ring->descbase) { b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); return -ENOMEM; @@ -410,13 +408,10 @@ static int alloc_ringmemory(struct b43_dmaring *ring) static void free_ringmemory(struct b43_dmaring *ring) { - gfp_t flags = GFP_KERNEL; - - if (ring->type == B43_DMA_64BIT) - flags |= GFP_DMA; + struct device *dma_dev = ring->dev->dev->dma_dev; - ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, - ring->descbase, ring->dmabase, flags); + dma_free_coherent(dma_dev, B43_DMA_RINGMEMSIZE, + ring->descbase, ring->dmabase); } /* Reset the RX DMA channel */ @@ -523,7 +518,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, dma_addr_t addr, size_t buffersize, bool dma_to_device) { - if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) + if (unlikely(dma_mapping_error(addr))) return 1; switch (ring->type) { @@ -849,10 +844,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, goto err_kfree_meta; /* test for ability to dma to txhdr_cache */ - dma_test = ssb_dma_map_single(dev->dev, - ring->txhdr_cache, - b43_txhdr_size(dev), - DMA_TO_DEVICE); + dma_test = dma_map_single(dev->dev->dma_dev, + ring->txhdr_cache, + b43_txhdr_size(dev), + DMA_TO_DEVICE); if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev), 1)) { @@ -864,10 +859,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, if (!ring->txhdr_cache) goto err_kfree_meta; - dma_test = ssb_dma_map_single(dev->dev, - ring->txhdr_cache, - b43_txhdr_size(dev), - DMA_TO_DEVICE); + dma_test = dma_map_single(dev->dev->dma_dev, + ring->txhdr_cache, + b43_txhdr_size(dev), + DMA_TO_DEVICE); if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev), 1)) { @@ -878,9 +873,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, } } - ssb_dma_unmap_single(dev->dev, - dma_test, b43_txhdr_size(dev), - DMA_TO_DEVICE); + dma_unmap_single(dev->dev->dma_dev, + dma_test, b43_txhdr_size(dev), + DMA_TO_DEVICE); } err = alloc_ringmemory(ring); diff --git a/trunk/drivers/net/wireless/b43/leds.c b/trunk/drivers/net/wireless/b43/leds.c index 76f4c7bad8b8..36a9c42df835 100644 --- a/trunk/drivers/net/wireless/b43/leds.c +++ b/trunk/drivers/net/wireless/b43/leds.c @@ -72,9 +72,6 @@ static void b43_led_brightness_set(struct led_classdev *led_dev, struct b43_wldev *dev = led->dev; bool radio_enabled; - if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) - return; - /* Checking the radio-enabled status here is slightly racy, * but we want to avoid the locking overhead and we don't care * whether the LED has the wrong state for a second. */ diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index 9d2eb273b726..7bca8e981512 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -373,10 +373,13 @@ static inline void b43_shm_control_word(struct b43_wldev *dev, b43_write32(dev, B43_MMIO_SHM_CONTROL, control); } -u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) +u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) { + struct b43_wl *wl = dev->wl; + unsigned long flags; u32 ret; + spin_lock_irqsave(&wl->shm_lock, flags); if (routing == B43_SHM_SHARED) { B43_WARN_ON(offset & 0x0001); if (offset & 0x0003) { @@ -394,26 +397,18 @@ u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) b43_shm_control_word(dev, routing, offset); ret = b43_read32(dev, B43_MMIO_SHM_DATA); out: - return ret; -} - -u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) -{ - struct b43_wl *wl = dev->wl; - unsigned long flags; - u32 ret; - - spin_lock_irqsave(&wl->shm_lock, flags); - ret = __b43_shm_read32(dev, routing, offset); spin_unlock_irqrestore(&wl->shm_lock, flags); return ret; } -u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset) +u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset) { + struct b43_wl *wl = dev->wl; + unsigned long flags; u16 ret; + spin_lock_irqsave(&wl->shm_lock, flags); if (routing == B43_SHM_SHARED) { B43_WARN_ON(offset & 0x0001); if (offset & 0x0003) { @@ -428,24 +423,17 @@ u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset) b43_shm_control_word(dev, routing, offset); ret = b43_read16(dev, B43_MMIO_SHM_DATA); out: + spin_unlock_irqrestore(&wl->shm_lock, flags); + return ret; } -u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset) +void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) { struct b43_wl *wl = dev->wl; unsigned long flags; - u16 ret; spin_lock_irqsave(&wl->shm_lock, flags); - ret = __b43_shm_read16(dev, routing, offset); - spin_unlock_irqrestore(&wl->shm_lock, flags); - - return ret; -} - -void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) -{ if (routing == B43_SHM_SHARED) { B43_WARN_ON(offset & 0x0001); if (offset & 0x0003) { @@ -455,47 +443,35 @@ void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value (value >> 16) & 0xffff); b43_shm_control_word(dev, routing, (offset >> 2) + 1); b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff); - return; + goto out; } offset >>= 2; } b43_shm_control_word(dev, routing, offset); b43_write32(dev, B43_MMIO_SHM_DATA, value); +out: + spin_unlock_irqrestore(&wl->shm_lock, flags); } -void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) +void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) { struct b43_wl *wl = dev->wl; unsigned long flags; spin_lock_irqsave(&wl->shm_lock, flags); - __b43_shm_write32(dev, routing, offset, value); - spin_unlock_irqrestore(&wl->shm_lock, flags); -} - -void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) -{ if (routing == B43_SHM_SHARED) { B43_WARN_ON(offset & 0x0001); if (offset & 0x0003) { /* Unaligned access */ b43_shm_control_word(dev, routing, offset >> 2); b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value); - return; + goto out; } offset >>= 2; } b43_shm_control_word(dev, routing, offset); b43_write16(dev, B43_MMIO_SHM_DATA, value); -} - -void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) -{ - struct b43_wl *wl = dev->wl; - unsigned long flags; - - spin_lock_irqsave(&wl->shm_lock, flags); - __b43_shm_write16(dev, routing, offset, value); +out: spin_unlock_irqrestore(&wl->shm_lock, flags); } @@ -2487,19 +2463,6 @@ static void b43_gpio_cleanup(struct b43_wldev *dev) /* http://bcm-specs.sipsolutions.net/EnableMac */ void b43_mac_enable(struct b43_wldev *dev) { - if (b43_debug(dev, B43_DBG_FIRMWARE)) { - u16 fwstate; - - fwstate = b43_shm_read16(dev, B43_SHM_SHARED, - B43_SHM_SH_UCODESTAT); - if ((fwstate != B43_SHM_SH_UCODESTAT_SUSP) && - (fwstate != B43_SHM_SH_UCODESTAT_SLEEP)) { - b43err(dev->wl, "b43_mac_enable(): The firmware " - "should be suspended, but current state is %u\n", - fwstate); - } - } - dev->mac_suspended--; B43_WARN_ON(dev->mac_suspended < 0); if (dev->mac_suspended == 0) { @@ -2820,21 +2783,6 @@ static void b43_periodic_every30sec(struct b43_wldev *dev) static void b43_periodic_every15sec(struct b43_wldev *dev) { struct b43_phy *phy = &dev->phy; - u16 wdr; - - if (dev->fw.opensource) { - /* Check if the firmware is still alive. - * It will reset the watchdog counter to 0 in its idle loop. */ - wdr = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_WATCHDOG_REG); - if (unlikely(wdr)) { - b43err(dev->wl, "Firmware watchdog: The firmware died!\n"); - b43_controller_restart(dev, "Firmware watchdog"); - return; - } else { - b43_shm_write16(dev, B43_SHM_SCRATCH, - B43_WATCHDOG_REG, 1); - } - } if (phy->type == B43_PHYTYPE_G) { //TODO: update_aci_moving_average @@ -3028,11 +2976,12 @@ static int b43_op_tx(struct ieee80211_hw *hw, if (unlikely(skb->len < 2 + 2 + 6)) { /* Too short, this can't be a valid frame. */ - goto drop_packet; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } B43_WARN_ON(skb_shinfo(skb)->nr_frags); if (unlikely(!dev)) - goto drop_packet; + return NETDEV_TX_BUSY; /* Transmissions on seperate queues can run concurrently. */ read_lock_irqsave(&wl->tx_lock, flags); @@ -3048,12 +2997,7 @@ static int b43_op_tx(struct ieee80211_hw *hw, read_unlock_irqrestore(&wl->tx_lock, flags); if (unlikely(err)) - goto drop_packet; - return NETDEV_TX_OK; - -drop_packet: - /* We can not transmit this packet. Drop it. */ - dev_kfree_skb_any(skb); + return NETDEV_TX_BUSY; return NETDEV_TX_OK; } diff --git a/trunk/drivers/net/wireless/b43/main.h b/trunk/drivers/net/wireless/b43/main.h index f871a252cb55..dad23c42b422 100644 --- a/trunk/drivers/net/wireless/b43/main.h +++ b/trunk/drivers/net/wireless/b43/main.h @@ -95,13 +95,9 @@ void b43_tsf_read(struct b43_wldev *dev, u64 * tsf); void b43_tsf_write(struct b43_wldev *dev, u64 tsf); u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset); -u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset); u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); -u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); -void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); -void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); u64 b43_hf_read(struct b43_wldev *dev); void b43_hf_write(struct b43_wldev *dev, u64 value); diff --git a/trunk/drivers/net/wireless/b43/pio.c b/trunk/drivers/net/wireless/b43/pio.c index 401591267592..8b1555d95f1c 100644 --- a/trunk/drivers/net/wireless/b43/pio.c +++ b/trunk/drivers/net/wireless/b43/pio.c @@ -586,7 +586,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, spin_lock(&q->lock); /* IRQs are already disabled. */ - info = IEEE80211_SKB_CB(pack->skb); + info = (void *)pack->skb; memset(&info->status, 0, sizeof(info->status)); b43_fill_txstatus_report(info, status); diff --git a/trunk/drivers/net/wireless/b43/rfkill.c b/trunk/drivers/net/wireless/b43/rfkill.c index 4cca203992e8..11f53cb1139e 100644 --- a/trunk/drivers/net/wireless/b43/rfkill.c +++ b/trunk/drivers/net/wireless/b43/rfkill.c @@ -88,7 +88,7 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) goto out_unlock; err = 0; switch (state) { - case RFKILL_STATE_UNBLOCKED: + case RFKILL_STATE_ON: if (!dev->radio_hw_enable) { /* No luck. We can't toggle the hardware RF-kill * button from software. */ @@ -98,13 +98,10 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) if (!dev->phy.radio_on) b43_radio_turn_on(dev); break; - case RFKILL_STATE_SOFT_BLOCKED: + case RFKILL_STATE_OFF: if (dev->phy.radio_on) b43_radio_turn_off(dev, 0); break; - default: - b43warn(wl, "Received unexpected rfkill state %d.\n", state); - break; } out_unlock: mutex_unlock(&wl->mutex); diff --git a/trunk/drivers/net/wireless/b43/xmit.c b/trunk/drivers/net/wireless/b43/xmit.c index bf6f6c1ed4cf..f9e1cff2aecb 100644 --- a/trunk/drivers/net/wireless/b43/xmit.c +++ b/trunk/drivers/net/wireless/b43/xmit.c @@ -193,7 +193,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, const struct ieee80211_hdr *wlhdr = (const struct ieee80211_hdr *)fragment_data; int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)); - __le16 fctl = wlhdr->frame_control; + u16 fctl = le16_to_cpu(wlhdr->frame_control); struct ieee80211_rate *fbrate; u8 rate, rate_fb; int rate_ofdm, rate_fb_ofdm; @@ -259,7 +259,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, B43_TXH_MAC_KEYIDX; mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & B43_TXH_MAC_KEYALG; - wlhdr_len = ieee80211_hdrlen(fctl); + wlhdr_len = ieee80211_get_hdrlen(fctl); iv_len = min((size_t) info->control.iv_len, ARRAY_SIZE(txhdr->iv)); memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); @@ -317,7 +317,8 @@ int b43_generate_txhdr(struct b43_wldev *dev, /* MAC control */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43_TXH_MAC_ACK; - if (!ieee80211_is_pspoll(fctl)) + if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && + ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL))) mac_ctl |= B43_TXH_MAC_HWSEQ; if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) mac_ctl |= B43_TXH_MAC_STMSDU; @@ -508,7 +509,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) struct b43_plcp_hdr6 *plcp; struct ieee80211_hdr *wlhdr; const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; - __le16 fctl; + u16 fctl; u16 phystat0, phystat3, chanstat, mactime; u32 macstat; u16 chanid; @@ -548,7 +549,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) goto drop; } wlhdr = (struct ieee80211_hdr *)(skb->data); - fctl = wlhdr->frame_control; + fctl = le16_to_cpu(wlhdr->frame_control); if (macstat & B43_RX_MAC_DEC) { unsigned int keyidx; @@ -563,7 +564,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) B43_WARN_ON(keyidx >= dev->max_nr_keys); if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { - wlhdr_len = ieee80211_hdrlen(fctl); + wlhdr_len = ieee80211_get_hdrlen(fctl); if (unlikely(skb->len < (wlhdr_len + 3))) { b43dbg(dev->wl, "RX: Packet size underrun (3)\n"); @@ -603,7 +604,9 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) * of timestamp, i.e. about 65 milliseconds after the PHY received * the first symbol. */ - if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { + if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) + == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) || + dev->wl->radiotap_enabled) { u16 low_mactime_now; b43_tsf_read(dev, &status.mactime); diff --git a/trunk/drivers/net/wireless/b43legacy/dma.c b/trunk/drivers/net/wireless/b43legacy/dma.c index eb0243a22691..33cc256c5baf 100644 --- a/trunk/drivers/net/wireless/b43legacy/dma.c +++ b/trunk/drivers/net/wireless/b43legacy/dma.c @@ -393,13 +393,13 @@ dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring, dma_addr_t dmaaddr; if (tx) - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, - DMA_TO_DEVICE); + dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + buf, len, + DMA_TO_DEVICE); else - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, - DMA_FROM_DEVICE); + dmaaddr = dma_map_single(ring->dev->dev->dma_dev, + buf, len, + DMA_FROM_DEVICE); return dmaaddr; } @@ -411,13 +411,13 @@ void unmap_descbuffer(struct b43legacy_dmaring *ring, int tx) { if (tx) - ssb_dma_unmap_single(ring->dev->dev, - addr, len, - DMA_TO_DEVICE); + dma_unmap_single(ring->dev->dev->dma_dev, + addr, len, + DMA_TO_DEVICE); else - ssb_dma_unmap_single(ring->dev->dev, - addr, len, - DMA_FROM_DEVICE); + dma_unmap_single(ring->dev->dev->dma_dev, + addr, len, + DMA_FROM_DEVICE); } static inline @@ -427,8 +427,8 @@ void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring, { B43legacy_WARN_ON(ring->tx); - ssb_dma_sync_single_for_cpu(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); + dma_sync_single_for_cpu(ring->dev->dev->dma_dev, + addr, len, DMA_FROM_DEVICE); } static inline @@ -438,8 +438,8 @@ void sync_descbuffer_for_device(struct b43legacy_dmaring *ring, { B43legacy_WARN_ON(ring->tx); - ssb_dma_sync_single_for_device(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); + dma_sync_single_for_device(ring->dev->dev->dma_dev, + addr, len, DMA_FROM_DEVICE); } static inline @@ -458,11 +458,10 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring, static int alloc_ringmemory(struct b43legacy_dmaring *ring) { - /* GFP flags must match the flags in free_ringmemory()! */ - ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, - B43legacy_DMA_RINGMEMSIZE, - &(ring->dmabase), - GFP_KERNEL); + struct device *dma_dev = ring->dev->dev->dma_dev; + + ring->descbase = dma_alloc_coherent(dma_dev, B43legacy_DMA_RINGMEMSIZE, + &(ring->dmabase), GFP_KERNEL); if (!ring->descbase) { b43legacyerr(ring->dev->wl, "DMA ringmemory allocation" " failed\n"); @@ -475,8 +474,10 @@ static int alloc_ringmemory(struct b43legacy_dmaring *ring) static void free_ringmemory(struct b43legacy_dmaring *ring) { - ssb_dma_free_consistent(ring->dev->dev, B43legacy_DMA_RINGMEMSIZE, - ring->descbase, ring->dmabase, GFP_KERNEL); + struct device *dma_dev = ring->dev->dev->dma_dev; + + dma_free_coherent(dma_dev, B43legacy_DMA_RINGMEMSIZE, + ring->descbase, ring->dmabase); } /* Reset the RX DMA channel */ @@ -588,7 +589,7 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, size_t buffersize, bool dma_to_device) { - if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) + if (unlikely(dma_mapping_error(addr))) return 1; switch (ring->type) { @@ -875,7 +876,6 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, if (!ring) goto out; ring->type = type; - ring->dev = dev; nr_slots = B43legacy_RXRING_SLOTS; if (for_tx) @@ -893,9 +893,9 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, goto err_kfree_meta; /* test for ability to dma to txhdr_cache */ - dma_test = ssb_dma_map_single(dev->dev, ring->txhdr_cache, - sizeof(struct b43legacy_txhdr_fw3), - DMA_TO_DEVICE); + dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache, + sizeof(struct b43legacy_txhdr_fw3), + DMA_TO_DEVICE); if (b43legacy_dma_mapping_error(ring, dma_test, sizeof(struct b43legacy_txhdr_fw3), 1)) { @@ -907,7 +907,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, if (!ring->txhdr_cache) goto err_kfree_meta; - dma_test = ssb_dma_map_single(dev->dev, + dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache, sizeof(struct b43legacy_txhdr_fw3), DMA_TO_DEVICE); @@ -917,11 +917,12 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, goto err_kfree_txhdr_cache; } - ssb_dma_unmap_single(dev->dev, dma_test, - sizeof(struct b43legacy_txhdr_fw3), - DMA_TO_DEVICE); + dma_unmap_single(dev->dev->dma_dev, + dma_test, sizeof(struct b43legacy_txhdr_fw3), + DMA_TO_DEVICE); } + ring->dev = dev; ring->nr_slots = nr_slots; ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index); ring->index = controller_index; diff --git a/trunk/drivers/net/wireless/b43legacy/main.c b/trunk/drivers/net/wireless/b43legacy/main.c index 069157eea05c..5f533b93ad5d 100644 --- a/trunk/drivers/net/wireless/b43legacy/main.c +++ b/trunk/drivers/net/wireless/b43legacy/main.c @@ -2377,10 +2377,8 @@ static int b43legacy_op_tx(struct ieee80211_hw *hw, } else err = b43legacy_dma_tx(dev, skb); out: - if (unlikely(err)) { - /* Drop the packet. */ - dev_kfree_skb_any(skb); - } + if (unlikely(err)) + return NETDEV_TX_BUSY; return NETDEV_TX_OK; } diff --git a/trunk/drivers/net/wireless/b43legacy/rfkill.c b/trunk/drivers/net/wireless/b43legacy/rfkill.c index 8935a302b220..d178dfbb1c9f 100644 --- a/trunk/drivers/net/wireless/b43legacy/rfkill.c +++ b/trunk/drivers/net/wireless/b43legacy/rfkill.c @@ -90,7 +90,7 @@ static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state) goto out_unlock; err = 0; switch (state) { - case RFKILL_STATE_UNBLOCKED: + case RFKILL_STATE_ON: if (!dev->radio_hw_enable) { /* No luck. We can't toggle the hardware RF-kill * button from software. */ @@ -100,14 +100,10 @@ static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state) if (!dev->phy.radio_on) b43legacy_radio_turn_on(dev); break; - case RFKILL_STATE_SOFT_BLOCKED: + case RFKILL_STATE_OFF: if (dev->phy.radio_on) b43legacy_radio_turn_off(dev, 0); break; - default: - b43legacywarn(wl, "Received unexpected rfkill state %d.\n", - state); - break; } out_unlock: diff --git a/trunk/drivers/net/wireless/b43legacy/xmit.c b/trunk/drivers/net/wireless/b43legacy/xmit.c index a3540787eb50..82dc04d59446 100644 --- a/trunk/drivers/net/wireless/b43legacy/xmit.c +++ b/trunk/drivers/net/wireless/b43legacy/xmit.c @@ -442,7 +442,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev, struct b43legacy_plcp_hdr6 *plcp; struct ieee80211_hdr *wlhdr; const struct b43legacy_rxhdr_fw3 *rxhdr = _rxhdr; - __le16 fctl; + u16 fctl; u16 phystat0; u16 phystat3; u16 chanstat; @@ -480,7 +480,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev, goto drop; } wlhdr = (struct ieee80211_hdr *)(skb->data); - fctl = wlhdr->frame_control; + fctl = le16_to_cpu(wlhdr->frame_control); if ((macstat & B43legacy_RX_MAC_DEC) && !(macstat & B43legacy_RX_MAC_DECERR)) { @@ -499,11 +499,11 @@ void b43legacy_rx(struct b43legacy_wldev *dev, if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) { /* Remove PROTECTED flag to mark it as decrypted. */ - B43legacy_WARN_ON(!ieee80211_has_protected(fctl)); - fctl &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED); - wlhdr->frame_control = fctl; + B43legacy_WARN_ON(!(fctl & IEEE80211_FCTL_PROTECTED)); + fctl &= ~IEEE80211_FCTL_PROTECTED; + wlhdr->frame_control = cpu_to_le16(fctl); - wlhdr_len = ieee80211_hdrlen(fctl); + wlhdr_len = ieee80211_get_hdrlen(fctl); if (unlikely(skb->len < (wlhdr_len + 3))) { b43legacydbg(dev->wl, "RX: Packet size" " underrun3\n"); @@ -556,7 +556,9 @@ void b43legacy_rx(struct b43legacy_wldev *dev, * of timestamp, i.e. about 65 milliseconds after the PHY received * the first symbol. */ - if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { + if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) + == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) || + dev->wl->radiotap_enabled) { u16 low_mactime_now; b43legacy_tsf_read(dev, &status.mactime); diff --git a/trunk/drivers/net/wireless/hostap/hostap.h b/trunk/drivers/net/wireless/hostap/hostap.h index 3a386a636cca..547ba84dc797 100644 --- a/trunk/drivers/net/wireless/hostap/hostap.h +++ b/trunk/drivers/net/wireless/hostap/hostap.h @@ -67,8 +67,7 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], struct iw_quality qual[], int buf_size, int aplist); -int prism2_ap_translate_scan(struct net_device *dev, - struct iw_request_info *info, char *buffer); +int prism2_ap_translate_scan(struct net_device *dev, char *buffer); int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param); diff --git a/trunk/drivers/net/wireless/hostap/hostap_ap.c b/trunk/drivers/net/wireless/hostap/hostap_ap.c index 06b23df8f69b..0acd9589c48c 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_ap.c +++ b/trunk/drivers/net/wireless/hostap/hostap_ap.c @@ -2420,8 +2420,7 @@ int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], /* Translate our list of Access Points & Stations to a card independant * format that the Wireless Tools will understand - Jean II */ -int prism2_ap_translate_scan(struct net_device *dev, - struct iw_request_info *info, char *buffer) +int prism2_ap_translate_scan(struct net_device *dev, char *buffer) { struct hostap_interface *iface; local_info_t *local; @@ -2450,8 +2449,8 @@ int prism2_ap_translate_scan(struct net_device *dev, iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, sta->addr, ETH_ALEN); iwe.len = IW_EV_ADDR_LEN; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_ADDR_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, + IW_EV_ADDR_LEN); /* Use the mode to indicate if it's a station or * an Access Point */ @@ -2462,8 +2461,8 @@ int prism2_ap_translate_scan(struct net_device *dev, else iwe.u.mode = IW_MODE_INFRA; iwe.len = IW_EV_UINT_LEN; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, + IW_EV_UINT_LEN); /* Some quality */ memset(&iwe, 0, sizeof(iwe)); @@ -2478,8 +2477,8 @@ int prism2_ap_translate_scan(struct net_device *dev, iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); iwe.u.qual.updated = sta->last_rx_updated; iwe.len = IW_EV_QUAL_LEN; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_QUAL_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, + IW_EV_QUAL_LEN); #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT if (sta->ap) { @@ -2487,8 +2486,8 @@ int prism2_ap_translate_scan(struct net_device *dev, iwe.cmd = SIOCGIWESSID; iwe.u.data.length = sta->u.ap.ssid_len; iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, sta->u.ap.ssid); memset(&iwe, 0, sizeof(iwe)); @@ -2498,9 +2497,10 @@ int prism2_ap_translate_scan(struct net_device *dev, IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; else iwe.u.data.flags = IW_ENCODE_DISABLED; - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, - sta->u.ap.ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, + sta->u.ap.ssid + /* 0 byte memcpy */); if (sta->u.ap.channel > 0 && sta->u.ap.channel <= FREQ_COUNT) { @@ -2510,7 +2510,7 @@ int prism2_ap_translate_scan(struct net_device *dev, * 100000; iwe.u.freq.e = 1; current_ev = iwe_stream_add_event( - info, current_ev, end_buf, &iwe, + current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); } @@ -2519,8 +2519,8 @@ int prism2_ap_translate_scan(struct net_device *dev, sprintf(buf, "beacon_interval=%d", sta->listen_interval); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, buf); + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, buf); } #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ diff --git a/trunk/drivers/net/wireless/hostap/hostap_ioctl.c b/trunk/drivers/net/wireless/hostap/hostap_ioctl.c index ed52d98317cd..0ca0bfeb0ada 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/trunk/drivers/net/wireless/hostap/hostap_ioctl.c @@ -1793,7 +1793,6 @@ static int prism2_ioctl_siwscan(struct net_device *dev, #ifndef PRISM2_NO_STATION_MODES static char * __prism2_translate_scan(local_info_t *local, - struct iw_request_info *info, struct hfa384x_hostscan_result *scan, struct hostap_bss_info *bss, char *current_ev, char *end_buf) @@ -1824,7 +1823,7 @@ static char * __prism2_translate_scan(local_info_t *local, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); /* Other entries will be displayed in the order we give them */ @@ -1833,8 +1832,7 @@ static char * __prism2_translate_scan(local_info_t *local, iwe.cmd = SIOCGIWESSID; iwe.u.data.length = ssid_len; iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ssid); memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWMODE; @@ -1849,8 +1847,8 @@ static char * __prism2_translate_scan(local_info_t *local, iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, + IW_EV_UINT_LEN); } memset(&iwe, 0, sizeof(iwe)); @@ -1866,8 +1864,8 @@ static char * __prism2_translate_scan(local_info_t *local, if (chan > 0) { iwe.u.freq.m = freq_list[chan - 1] * 100000; iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_FREQ_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, + IW_EV_FREQ_LEN); } if (scan) { @@ -1886,8 +1884,8 @@ static char * __prism2_translate_scan(local_info_t *local, | IW_QUAL_NOISE_UPDATED | IW_QUAL_QUAL_INVALID | IW_QUAL_DBM; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_QUAL_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, + IW_EV_QUAL_LEN); } memset(&iwe, 0, sizeof(iwe)); @@ -1897,13 +1895,13 @@ static char * __prism2_translate_scan(local_info_t *local, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, ""); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ""); /* TODO: add SuppRates into BSS table */ if (scan) { memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWRATE; - current_val = current_ev + iwe_stream_lcp_len(info); + current_val = current_ev + IW_EV_LCP_LEN; pos = scan->sup_rates; for (i = 0; i < sizeof(scan->sup_rates); i++) { if (pos[i] == 0) @@ -1911,11 +1909,11 @@ static char * __prism2_translate_scan(local_info_t *local, /* Bit rate given in 500 kb/s units (+ 0x80) */ iwe.u.bitrate.value = ((pos[i] & 0x7f) * 500000); current_val = iwe_stream_add_value( - info, current_ev, current_val, end_buf, &iwe, + current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } /* Check if we added any event */ - if ((current_val - current_ev) > iwe_stream_lcp_len(info)) + if ((current_val - current_ev) > IW_EV_LCP_LEN) current_ev = current_val; } @@ -1926,15 +1924,15 @@ static char * __prism2_translate_scan(local_info_t *local, iwe.cmd = IWEVCUSTOM; sprintf(buf, "bcn_int=%d", le16_to_cpu(scan->beacon_interval)); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, buf); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, + buf); memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVCUSTOM; sprintf(buf, "resp_rate=%d", le16_to_cpu(scan->rate)); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, buf); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, + buf); if (local->last_scan_type == PRISM2_HOSTSCAN && (capabilities & WLAN_CAPABILITY_IBSS)) { @@ -1942,8 +1940,8 @@ static char * __prism2_translate_scan(local_info_t *local, iwe.cmd = IWEVCUSTOM; sprintf(buf, "atim=%d", le16_to_cpu(scan->atim)); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, buf); + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, buf); } } kfree(buf); @@ -1952,16 +1950,16 @@ static char * __prism2_translate_scan(local_info_t *local, memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVGENIE; iwe.u.data.length = bss->wpa_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->wpa_ie); + current_ev = iwe_stream_add_point( + current_ev, end_buf, &iwe, bss->wpa_ie); } if (bss && bss->rsn_ie_len > 0 && bss->rsn_ie_len <= MAX_WPA_IE_LEN) { memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVGENIE; iwe.u.data.length = bss->rsn_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->rsn_ie); + current_ev = iwe_stream_add_point( + current_ev, end_buf, &iwe, bss->rsn_ie); } return current_ev; @@ -1971,7 +1969,6 @@ static char * __prism2_translate_scan(local_info_t *local, /* Translate scan data returned from the card to a card independant * format that the Wireless Tools will understand - Jean II */ static inline int prism2_translate_scan(local_info_t *local, - struct iw_request_info *info, char *buffer, int buflen) { struct hfa384x_hostscan_result *scan; @@ -2002,14 +1999,13 @@ static inline int prism2_translate_scan(local_info_t *local, if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) { bss->included = 1; current_ev = __prism2_translate_scan( - local, info, scan, bss, current_ev, - end_buf); + local, scan, bss, current_ev, end_buf); found++; } } if (!found) { current_ev = __prism2_translate_scan( - local, info, scan, NULL, current_ev, end_buf); + local, scan, NULL, current_ev, end_buf); } /* Check if there is space for one more entry */ if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { @@ -2027,7 +2023,7 @@ static inline int prism2_translate_scan(local_info_t *local, bss = list_entry(ptr, struct hostap_bss_info, list); if (bss->included) continue; - current_ev = __prism2_translate_scan(local, info, NULL, bss, + current_ev = __prism2_translate_scan(local, NULL, bss, current_ev, end_buf); /* Check if there is space for one more entry */ if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { @@ -2074,7 +2070,7 @@ static inline int prism2_ioctl_giwscan_sta(struct net_device *dev, } local->scan_timestamp = 0; - res = prism2_translate_scan(local, info, extra, data->length); + res = prism2_translate_scan(local, extra, data->length); if (res >= 0) { data->length = res; @@ -2107,7 +2103,7 @@ static int prism2_ioctl_giwscan(struct net_device *dev, * Jean II */ /* Translate to WE format */ - res = prism2_ap_translate_scan(dev, info, extra); + res = prism2_ap_translate_scan(dev, extra); if (res >= 0) { printk(KERN_DEBUG "Scan result translation succeeded " "(length=%d)\n", res); diff --git a/trunk/drivers/net/wireless/iwlwifi/Kconfig b/trunk/drivers/net/wireless/iwlwifi/Kconfig index d7ea32f39694..a382c0078923 100644 --- a/trunk/drivers/net/wireless/iwlwifi/Kconfig +++ b/trunk/drivers/net/wireless/iwlwifi/Kconfig @@ -8,7 +8,7 @@ config IWLCORE select MAC80211_LEDS if IWLWIFI_LEDS select LEDS_CLASS if IWLWIFI_LEDS select RFKILL if IWLWIFI_RFKILL - select RFKILL_INPUT if (IWLWIFI_RFKILL && INPUT) + select RFKILL_INPUT if IWLWIFI_RFKILL config IWLWIFI_LEDS bool diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c index ffefbb487e12..5f098747cf95 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -54,20 +54,17 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) mutex_lock(&priv->mutex); switch (state) { - case RFKILL_STATE_UNBLOCKED: + case RFKILL_STATE_ON: iwl_radio_kill_sw_enable_radio(priv); /* if HW rf-kill is set dont allow ON state */ if (iwl_is_rfkill(priv)) err = -EBUSY; break; - case RFKILL_STATE_SOFT_BLOCKED: + case RFKILL_STATE_OFF: iwl_radio_kill_sw_disable_radio(priv); if (!iwl_is_rfkill(priv)) err = -EBUSY; break; - default: - IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); - break; } mutex_unlock(&priv->mutex); @@ -98,7 +95,6 @@ int iwl_rfkill_init(struct iwl_priv *priv) priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; priv->rfkill_mngr.rfkill->dev.class->resume = NULL; -#if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) priv->rfkill_mngr.input_dev = input_allocate_device(); if (!priv->rfkill_mngr.input_dev) { IWL_ERROR("Unable to allocate rfkill input device.\n"); @@ -113,7 +109,6 @@ int iwl_rfkill_init(struct iwl_priv *priv) priv->rfkill_mngr.input_dev->dev.parent = device; priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); -#endif ret = rfkill_register(priv->rfkill_mngr.rfkill); if (ret) { @@ -121,13 +116,11 @@ int iwl_rfkill_init(struct iwl_priv *priv) goto free_input_dev; } -#if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) ret = input_register_device(priv->rfkill_mngr.input_dev); if (ret) { IWL_ERROR("Unable to register rfkill input device: %d\n", ret); goto unregister_rfkill; } -#endif IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); return ret; @@ -137,10 +130,8 @@ int iwl_rfkill_init(struct iwl_priv *priv) priv->rfkill_mngr.rfkill = NULL; free_input_dev: -#if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) input_free_device(priv->rfkill_mngr.input_dev); priv->rfkill_mngr.input_dev = NULL; -#endif freed_rfkill: if (priv->rfkill_mngr.rfkill != NULL) @@ -156,16 +147,13 @@ EXPORT_SYMBOL(iwl_rfkill_init); void iwl_rfkill_unregister(struct iwl_priv *priv) { -#if defined(CONFIG_RFKILL_INPUT) || defined(CONFIG_RFKILL_INPUT_MODULE) if (priv->rfkill_mngr.input_dev) input_unregister_device(priv->rfkill_mngr.input_dev); - input_free_device(priv->rfkill_mngr.input_dev); - priv->rfkill_mngr.input_dev = NULL; -#endif if (priv->rfkill_mngr.rfkill) rfkill_unregister(priv->rfkill_mngr.rfkill); + priv->rfkill_mngr.input_dev = NULL; priv->rfkill_mngr.rfkill = NULL; } EXPORT_SYMBOL(iwl_rfkill_unregister); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c index 5b420b43af5c..5ca181f7125d 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -276,18 +276,13 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, cancel_delayed_work(&priv->scan_check); IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", - (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? - "2.4" : "5.2", + (priv->scan_bands == 2) ? "2.4" : "5.2", jiffies_to_msecs(elapsed_jiffies (priv->scan_pass_start, jiffies))); - /* Remove this scanned band from the list of pending - * bands to scan, band G precedes A in order of scanning - * as seen in iwl_bg_request_scan */ - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) - priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); - else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) - priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ); + /* Remove this scanned band from the list + * of pending bands to scan */ + priv->scan_bands--; /* If a request to abort was given, or the scan did not succeed * then we reset the scan state machine and terminate, @@ -297,7 +292,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, clear_bit(STATUS_SCAN_ABORTING, &priv->status); } else { /* If there are more bands on this scan pass reschedule */ - if (priv->scan_bands) + if (priv->scan_bands > 0) goto reschedule; } @@ -394,7 +389,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", + IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", scan_ch->channel); continue; } @@ -470,10 +465,7 @@ int iwl_scan_initiate(struct iwl_priv *priv) } IWL_DEBUG_INFO("Starting scan...\n"); - if (priv->cfg->sku & IWL_SKU_G) - priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); - if (priv->cfg->sku & IWL_SKU_A) - priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); + priv->scan_bands = 2; set_bit(STATUS_SCANNING, &priv->status); priv->scan_start = jiffies; priv->scan_pass_start = priv->scan_start; @@ -811,7 +803,8 @@ static void iwl_bg_request_scan(struct work_struct *data) scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { + switch (priv->scan_bands) { + case 2: band = IEEE80211_BAND_2GHZ; scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; tx_ant = iwl_scan_tx_ant(priv, band); @@ -825,7 +818,9 @@ static void iwl_bg_request_scan(struct work_struct *data) tx_ant | RATE_MCS_CCK_MSK); scan->good_CRC_th = 0; - } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { + break; + + case 1: band = IEEE80211_BAND_5GHZ; tx_ant = iwl_scan_tx_ant(priv, band); scan->tx_cmd.rate_n_flags = @@ -838,7 +833,9 @@ static void iwl_bg_request_scan(struct work_struct *data) * MIMO is not used here, but value is required */ if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) rx_chain = 0x6; - } else { + + break; + default: IWL_WARNING("Invalid scan band count\n"); goto done; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c index 92d1b2e312d4..47cf4b997f50 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2217,10 +2217,7 @@ static int iwl3945_scan_initiate(struct iwl3945_priv *priv) } IWL_DEBUG_INFO("Starting scan...\n"); - if (priv->cfg->sku & IWL_SKU_G) - priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); - if (priv->cfg->sku & IWL_SKU_A) - priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); + priv->scan_bands = 2; set_bit(STATUS_SCANNING, &priv->status); priv->scan_start = jiffies; priv->scan_pass_start = priv->scan_start; @@ -3345,18 +3342,13 @@ static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv, cancel_delayed_work(&priv->scan_check); IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", - (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? - "2.4" : "5.2", + (priv->scan_bands == 2) ? "2.4" : "5.2", jiffies_to_msecs(elapsed_jiffies (priv->scan_pass_start, jiffies))); - /* Remove this scanned band from the list of pending - * bands to scan, band G precedes A in order of scanning - * as seen in iwl3945_bg_request_scan */ - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) - priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); - else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) - priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ); + /* Remove this scanned band from the list + * of pending bands to scan */ + priv->scan_bands--; /* If a request to abort was given, or the scan did not succeed * then we reset the scan state machine and terminate, @@ -4969,7 +4961,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", + IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", scan_ch->channel); continue; } @@ -6324,16 +6316,21 @@ static void iwl3945_bg_request_scan(struct work_struct *data) /* flags + rate selection */ - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { + switch (priv->scan_bands) { + case 2: scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; scan->tx_cmd.rate = IWL_RATE_1M_PLCP; scan->good_CRC_th = 0; band = IEEE80211_BAND_2GHZ; - } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { + break; + + case 1: scan->tx_cmd.rate = IWL_RATE_6M_PLCP; scan->good_CRC_th = IWL_GOOD_CRC_TH; band = IEEE80211_BAND_5GHZ; - } else { + break; + + default: IWL_WARNING("Invalid scan band count\n"); goto done; } @@ -6773,7 +6770,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ch_info = iwl3945_get_channel_info(priv, conf->channel->band, conf->channel->hw_value); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this band.\n", + IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n", conf->channel->hw_value, conf->channel->band); IWL_DEBUG_MAC80211("leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); diff --git a/trunk/drivers/net/wireless/libertas/scan.c b/trunk/drivers/net/wireless/libertas/scan.c index 343ed38f772d..d448c9702a0f 100644 --- a/trunk/drivers/net/wireless/libertas/scan.c +++ b/trunk/drivers/net/wireless/libertas/scan.c @@ -776,9 +776,8 @@ int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, #define MAX_CUSTOM_LEN 64 static inline char *lbs_translate_scan(struct lbs_private *priv, - struct iw_request_info *info, - char *start, char *stop, - struct bss_descriptor *bss) + char *start, char *stop, + struct bss_descriptor *bss) { struct chan_freq_power *cfp; char *current_val; /* For rates */ @@ -802,24 +801,24 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN); /* SSID */ iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); - start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); + start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); /* Mode */ iwe.cmd = SIOCGIWMODE; iwe.u.mode = bss->mode; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN); /* Frequency */ iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = (long)cfp->freq * 100000; iwe.u.freq.e = 1; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN); /* Add quality statistics */ iwe.cmd = IWEVQUAL; @@ -853,7 +852,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; iwe.u.qual.level = CAL_RSSI(snr, nf); } - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); /* Add encryption capability */ iwe.cmd = SIOCGIWENCODE; @@ -863,9 +862,9 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, iwe.u.data.flags = IW_ENCODE_DISABLED; } iwe.u.data.length = 0; - start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); + start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); - current_val = start + iwe_stream_lcp_len(info); + current_val = start + IW_EV_LCP_LEN; iwe.cmd = SIOCGIWRATE; iwe.u.bitrate.fixed = 0; @@ -875,19 +874,19 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) { /* Bit rate given in 500 kb/s units */ iwe.u.bitrate.value = bss->rates[j] * 500000; - current_val = iwe_stream_add_value(info, start, current_val, - stop, &iwe, IW_EV_PARAM_LEN); + current_val = iwe_stream_add_value(start, current_val, + stop, &iwe, IW_EV_PARAM_LEN); } if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate && !lbs_ssid_cmp(priv->curbssparams.ssid, priv->curbssparams.ssid_len, bss->ssid, bss->ssid_len)) { iwe.u.bitrate.value = 22 * 500000; - current_val = iwe_stream_add_value(info, start, current_val, + current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN); } /* Check if we added any event */ - if ((current_val - start) > iwe_stream_lcp_len(info)) + if((current_val - start) > IW_EV_LCP_LEN) start = current_val; memset(&iwe, 0, sizeof(iwe)); @@ -896,7 +895,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, memcpy(buf, bss->wpa_ie, bss->wpa_ie_len); iwe.cmd = IWEVGENIE; iwe.u.data.length = bss->wpa_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); + start = iwe_stream_add_point(start, stop, &iwe, buf); } memset(&iwe, 0, sizeof(iwe)); @@ -905,7 +904,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, memcpy(buf, bss->rsn_ie, bss->rsn_ie_len); iwe.cmd = IWEVGENIE; iwe.u.data.length = bss->rsn_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); + start = iwe_stream_add_point(start, stop, &iwe, buf); } if (bss->mesh) { @@ -916,8 +915,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc"); iwe.u.data.length = p - custom; if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, - &iwe, custom); + start = iwe_stream_add_point(start, stop, &iwe, custom); } out: @@ -1038,7 +1036,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, } /* Translate to WE format this entry */ - next_ev = lbs_translate_scan(priv, info, ev, stop, iter_bss); + next_ev = lbs_translate_scan(priv, ev, stop, iter_bss); if (next_ev == NULL) continue; ev = next_ev; diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index 5d30c57e3969..8da352ae6825 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -430,16 +430,15 @@ static int __init init_mac80211_hwsim(void) hwsim_radios[i] = hw; data = hw->priv; - data->dev = device_create_drvdata(hwsim_class, NULL, 0, hw, - "hwsim%d", i); + data->dev = device_create(hwsim_class, NULL, 0, "hwsim%d", i); if (IS_ERR(data->dev)) { - printk(KERN_DEBUG - "mac80211_hwsim: device_create_drvdata " + printk(KERN_DEBUG "mac80211_hwsim: device_create " "failed (%ld)\n", PTR_ERR(data->dev)); err = -ENOMEM; goto failed; } data->dev->driver = &mac80211_hwsim_driver; + dev_set_drvdata(data->dev, hw); SET_IEEE80211_DEV(hw, data->dev); addr[3] = i >> 8; diff --git a/trunk/drivers/net/wireless/orinoco.c b/trunk/drivers/net/wireless/orinoco.c index b047306bf386..6d13a0d15a0c 100644 --- a/trunk/drivers/net/wireless/orinoco.c +++ b/trunk/drivers/net/wireless/orinoco.c @@ -4046,7 +4046,6 @@ static int orinoco_ioctl_setscan(struct net_device *dev, * format that the Wireless Tools will understand - Jean II * Return message length or -errno for fatal errors */ static inline char *orinoco_translate_scan(struct net_device *dev, - struct iw_request_info *info, char *current_ev, char *end_buf, union hermes_scan_info *bss, @@ -4063,8 +4062,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_ADDR_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); /* Other entries will be displayed in the order we give them */ @@ -4074,8 +4072,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, iwe.u.data.length = 32; iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->a.essid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->a.essid); /* Add mode */ iwe.cmd = SIOCGIWMODE; @@ -4085,8 +4082,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN); } channel = bss->s.channel; @@ -4095,7 +4091,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = channel_frequency[channel-1] * 100000; iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); } @@ -4110,8 +4106,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise; else iwe.u.qual.qual = 0; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_QUAL_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); /* Add encryption capability */ iwe.cmd = SIOCGIWENCODE; @@ -4120,8 +4115,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->a.essid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->a.essid); /* Add EXTRA: Age to display seconds since last beacon/probe response * for given network. */ @@ -4132,12 +4126,11 @@ static inline char *orinoco_translate_scan(struct net_device *dev, jiffies_to_msecs(jiffies - last_scanned)); iwe.u.data.length = p - custom; if (iwe.u.data.length) - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, custom); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, custom); /* Bit rate is not available in Lucent/Agere firmwares */ if (priv->firmware_type != FIRMWARE_TYPE_AGERE) { - char *current_val = current_ev + iwe_stream_lcp_len(info); + char *current_val = current_ev + IW_EV_LCP_LEN; int i; int step; @@ -4156,13 +4149,12 @@ static inline char *orinoco_translate_scan(struct net_device *dev, break; /* Bit rate given in 500 kb/s units (+ 0x80) */ iwe.u.bitrate.value = ((bss->p.rates[i] & 0x7f) * 500000); - current_val = iwe_stream_add_value(info, current_ev, - current_val, + current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } /* Check if we added any event */ - if ((current_val - current_ev) > iwe_stream_lcp_len(info)) + if ((current_val - current_ev) > IW_EV_LCP_LEN) current_ev = current_val; } @@ -4198,7 +4190,7 @@ static int orinoco_ioctl_getscan(struct net_device *dev, list_for_each_entry(bss, &priv->bss_list, list) { /* Translate to WE format this entry */ - current_ev = orinoco_translate_scan(dev, info, current_ev, + current_ev = orinoco_translate_scan(dev, current_ev, extra + srq->length, &bss->bss, bss->last_scanned); diff --git a/trunk/drivers/net/wireless/prism54/isl_ioctl.c b/trunk/drivers/net/wireless/prism54/isl_ioctl.c index 97fa14e0a479..5b375b289036 100644 --- a/trunk/drivers/net/wireless/prism54/isl_ioctl.c +++ b/trunk/drivers/net/wireless/prism54/isl_ioctl.c @@ -571,9 +571,8 @@ prism54_set_scan(struct net_device *dev, struct iw_request_info *info, */ static char * -prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, - char *current_ev, char *end_buf, struct obj_bss *bss, - char noise) +prism54_translate_bss(struct net_device *ndev, char *current_ev, + char *end_buf, struct obj_bss *bss, char noise) { struct iw_event iwe; /* Temporary buffer */ short cap; @@ -585,8 +584,8 @@ prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); iwe.u.ap_addr.sa_family = ARPHRD_ETHER; iwe.cmd = SIOCGIWAP; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_ADDR_LEN); + current_ev = + iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); /* The following entries will be displayed in the same order we give them */ @@ -594,7 +593,7 @@ prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, iwe.u.data.length = bss->ssid.length; iwe.u.data.flags = 1; iwe.cmd = SIOCGIWESSID; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid.octets); /* Capabilities */ @@ -611,8 +610,9 @@ prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, iwe.u.mode = IW_MODE_ADHOC; iwe.cmd = SIOCGIWMODE; if (iwe.u.mode) - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); + current_ev = + iwe_stream_add_event(current_ev, end_buf, &iwe, + IW_EV_UINT_LEN); /* Encryption capability */ if (cap & CAP_CRYPT) @@ -621,15 +621,14 @@ prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; iwe.cmd = SIOCGIWENCODE; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, NULL); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, NULL); /* Add frequency. (short) bss->channel is the frequency in MHz */ iwe.u.freq.m = bss->channel; iwe.u.freq.e = 6; iwe.cmd = SIOCGIWFREQ; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_FREQ_LEN); + current_ev = + iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); /* Add quality statistics */ iwe.u.qual.level = bss->rssi; @@ -637,20 +636,20 @@ prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, /* do a simple SNR for quality */ iwe.u.qual.qual = bss->rssi - noise; iwe.cmd = IWEVQUAL; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_QUAL_LEN); + current_ev = + iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); /* Add WPA/RSN Information Element, if any */ wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie); if (wpa_ie_len > 0) { iwe.cmd = IWEVGENIE; iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN); - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, wpa_ie); + current_ev = iwe_stream_add_point(current_ev, end_buf, + &iwe, wpa_ie); } /* Do the bitrates */ { - char *current_val = current_ev + iwe_stream_lcp_len(info); + char * current_val = current_ev + IW_EV_LCP_LEN; int i; int mask; @@ -663,14 +662,14 @@ prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, for(i = 0; i < sizeof(scan_rate_list); i++) { if(bss->rates & mask) { iwe.u.bitrate.value = (scan_rate_list[i] * 500000); - current_val = iwe_stream_add_value( - info, current_ev, current_val, - end_buf, &iwe, IW_EV_PARAM_LEN); + current_val = iwe_stream_add_value(current_ev, current_val, + end_buf, &iwe, + IW_EV_PARAM_LEN); } mask <<= 1; } /* Check if we added any event */ - if ((current_val - current_ev) > iwe_stream_lcp_len(info)) + if ((current_val - current_ev) > IW_EV_LCP_LEN) current_ev = current_val; } @@ -711,7 +710,7 @@ prism54_get_scan(struct net_device *ndev, struct iw_request_info *info, /* ok now, scan the list and translate its info */ for (i = 0; i < (int) bsslist->nr; i++) { - current_ev = prism54_translate_bss(ndev, info, current_ev, + current_ev = prism54_translate_bss(ndev, current_ev, extra + dwrq->length, &(bsslist->bsslist[i]), noise); @@ -2705,7 +2704,6 @@ prism2_ioctl_scan_req(struct net_device *ndev, struct prism2_hostapd_param *param) { islpci_private *priv = netdev_priv(ndev); - struct iw_request_info info; int i, rvalue; struct obj_bsslist *bsslist; u32 noise = 0; @@ -2729,12 +2727,9 @@ prism2_ioctl_scan_req(struct net_device *ndev, rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); bsslist = r.ptr; - info.cmd = PRISM54_HOSTAPD; - info.flags = 0; - /* ok now, scan the list and translate its info */ for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) - current_ev = prism54_translate_bss(ndev, &info, current_ev, + current_ev = prism54_translate_bss(ndev, current_ev, extra + IW_SCAN_MAX_DATA, &(bsslist->bsslist[i]), noise); diff --git a/trunk/drivers/net/wireless/prism54/islpci_eth.c b/trunk/drivers/net/wireless/prism54/islpci_eth.c index e43bae97ed8f..762e85bef55d 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_eth.c +++ b/trunk/drivers/net/wireless/prism54/islpci_eth.c @@ -290,7 +290,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb) avs->version = cpu_to_be32(P80211CAPTURE_VERSION); avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header)); - avs->mactime = cpu_to_be64(clock); + avs->mactime = cpu_to_be64(le64_to_cpu(clock)); avs->hosttime = cpu_to_be64(jiffies); avs->phytype = cpu_to_be32(6); /*OFDM: 6 for (g), 8 for (a) */ avs->channel = cpu_to_be32(channel_of_freq(freq)); diff --git a/trunk/drivers/net/wireless/rndis_wlan.c b/trunk/drivers/net/wireless/rndis_wlan.c index 00e965b9da75..f001f2afd05e 100644 --- a/trunk/drivers/net/wireless/rndis_wlan.c +++ b/trunk/drivers/net/wireless/rndis_wlan.c @@ -1648,9 +1648,7 @@ static int rndis_iw_set_scan(struct net_device *dev, static char *rndis_translate_scan(struct net_device *dev, - struct iw_request_info *info, char *cev, - char *end_buf, - struct ndis_80211_bssid_ex *bssid) + char *cev, char *end_buf, struct ndis_80211_bssid_ex *bssid) { #ifdef DEBUG struct usbnet *usbdev = dev->priv; @@ -1669,14 +1667,14 @@ static char *rndis_translate_scan(struct net_device *dev, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN); - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_ADDR_LEN); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length), bssid->ssid.essid); iwe.cmd = SIOCGIWESSID; iwe.u.essid.length = le32_to_cpu(bssid->ssid.length); iwe.u.essid.flags = 1; - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, bssid->ssid.essid); + cev = iwe_stream_add_point(cev, end_buf, &iwe, bssid->ssid.essid); devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra)); iwe.cmd = SIOCGIWMODE; @@ -1692,12 +1690,12 @@ static char *rndis_translate_scan(struct net_device *dev, iwe.u.mode = IW_MODE_AUTO; break; } - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_UINT_LEN); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config)); iwe.cmd = SIOCGIWFREQ; dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq); - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_FREQ_LEN); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi)); iwe.cmd = IWEVQUAL; @@ -1706,7 +1704,7 @@ static char *rndis_translate_scan(struct net_device *dev, iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; - cev = iwe_stream_add_event(info, cev, end_buf, &iwe, IW_EV_QUAL_LEN); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy)); iwe.cmd = SIOCGIWENCODE; @@ -1716,10 +1714,10 @@ static char *rndis_translate_scan(struct net_device *dev, else iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL); + cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); devdbg(usbdev, "RATES:"); - current_val = cev + iwe_stream_lcp_len(info); + current_val = cev + IW_EV_LCP_LEN; iwe.cmd = SIOCGIWRATE; for (i = 0; i < sizeof(bssid->rates); i++) { if (bssid->rates[i] & 0x7f) { @@ -1727,13 +1725,13 @@ static char *rndis_translate_scan(struct net_device *dev, ((bssid->rates[i] & 0x7f) * 500000); devdbg(usbdev, " %d", iwe.u.bitrate.value); - current_val = iwe_stream_add_value(info, cev, + current_val = iwe_stream_add_value(cev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } } - if ((current_val - cev) > iwe_stream_lcp_len(info)) + if ((current_val - cev) > IW_EV_LCP_LEN) cev = current_val; beacon = le32_to_cpu(bssid->config.beacon_period); @@ -1741,14 +1739,14 @@ static char *rndis_translate_scan(struct net_device *dev, iwe.cmd = IWEVCUSTOM; snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon); iwe.u.data.length = strlen(sbuf); - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf); + cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf); atim = le32_to_cpu(bssid->config.atim_window); devdbg(usbdev, "ATIM %d", atim); iwe.cmd = IWEVCUSTOM; snprintf(sbuf, sizeof(sbuf), "atim=%u", atim); iwe.u.data.length = strlen(sbuf); - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, sbuf); + cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf); ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies)); ie_len = min(bssid_len - (int)sizeof(*bssid), @@ -1762,7 +1760,7 @@ static char *rndis_translate_scan(struct net_device *dev, (ie->id == MFIE_TYPE_RSN) ? 2 : 1); iwe.cmd = IWEVGENIE; iwe.u.data.length = min(ie->len + 2, MAX_WPA_IE_LEN); - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, + cev = iwe_stream_add_point(cev, end_buf, &iwe, (u8 *)ie); } @@ -1805,8 +1803,8 @@ static int rndis_iw_get_scan(struct net_device *dev, devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count); while (count && ((void *)bssid + bssid_len) <= (buf + len)) { - cev = rndis_translate_scan(dev, info, cev, - extra + IW_SCAN_MAX_DATA, bssid); + cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA, + bssid); bssid = (void *)bssid + bssid_len; bssid_len = le32_to_cpu(bssid->length); count--; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c index b3dffcfed835..bb3d83560d02 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2400pci.c @@ -632,15 +632,15 @@ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); u32 word; rt2x00_desc_read(entry_priv->desc, 2, &word); - rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len); + rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, + entry->queue->data_size); rt2x00_desc_write(entry_priv->desc, 2, word); rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry_priv->data_dma); rt2x00_desc_write(entry_priv->desc, 1, word); rt2x00_desc_read(entry_priv->desc, 0, &word); @@ -1012,7 +1012,7 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Start writing the descriptor words. */ rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry_priv->data_dma); rt2x00_desc_write(entry_priv->desc, 1, word); rt2x00_desc_read(txd, 2, &word); @@ -1154,7 +1154,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, } txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00lib_txdone(entry, &txdesc); + rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } } @@ -1366,7 +1366,7 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) IEEE80211_HW_SIGNAL_DBM; rt2x00dev->hw->extra_tx_headroom = 0; - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); + SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); @@ -1412,10 +1412,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) rt2400pci_probe_hw_mode(rt2x00dev); /* - * This device requires the atim queue and DMA-mapped skbs. + * This device requires the atim queue */ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1527,7 +1526,7 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) * Write entire beacon with descriptor to register, * and kick the beacon generator. */ - rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); + memcpy(entry_priv->data, skb->data, skb->len); rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c index 0423c251c78e..3c956b91c4e3 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500pci.c @@ -727,11 +727,10 @@ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); u32 word; rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry_priv->data_dma); rt2x00_desc_write(entry_priv->desc, 1, word); rt2x00_desc_read(entry_priv->desc, 0, &word); @@ -1172,7 +1171,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Start writing the descriptor words. */ rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry_priv->data_dma); rt2x00_desc_write(entry_priv->desc, 1, word); rt2x00_desc_read(txd, 2, &word); @@ -1312,7 +1311,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, } txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00lib_txdone(entry, &txdesc); + rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } } @@ -1689,7 +1688,7 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->extra_tx_headroom = 0; - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); + SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); @@ -1753,10 +1752,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) rt2500pci_probe_hw_mode(rt2x00dev); /* - * This device requires the atim queue and DMA-mapped skbs. + * This device requires the atim queue */ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1844,7 +1842,7 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) * Write entire beacon with descriptor to register, * and kick the beacon generator. */ - rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb); + memcpy(entry_priv->data, skb->data, skb->len); rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c index 0dd1cb537b92..9851cefaabf3 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2500usb.c @@ -138,8 +138,11 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - goto exit_fail; + if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { + ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); + mutex_unlock(&rt2x00dev->usb_cache_mutex); + return; + } /* * Write the data into the BBP. @@ -152,13 +155,6 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); mutex_unlock(&rt2x00dev->usb_cache_mutex); - - return; - -exit_fail: - mutex_unlock(&rt2x00dev->usb_cache_mutex); - - ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); } static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -172,8 +168,10 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - goto exit_fail; + if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { + ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); + return; + } /* * Write the request into the BBP. @@ -188,21 +186,17 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - goto exit_fail; + if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { + ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); + *value = 0xff; + mutex_unlock(&rt2x00dev->usb_cache_mutex); + return; + } rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); mutex_unlock(&rt2x00dev->usb_cache_mutex); - - return; - -exit_fail: - mutex_unlock(&rt2x00dev->usb_cache_mutex); - - ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); - *value = 0xff; } static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, @@ -1594,7 +1588,7 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); + SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); @@ -1678,7 +1672,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); struct queue_entry_priv_usb_bcn *bcn_priv; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00.h b/trunk/drivers/net/wireless/rt2x00/rt2x00.h index 6842464dcf3e..0da8f972a1b2 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00.h @@ -44,7 +44,7 @@ /* * Module information. */ -#define DRV_VERSION "2.1.8" +#define DRV_VERSION "2.1.7" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* @@ -110,6 +110,33 @@ #define SHORT_DIFS ( SHORT_PIFS + SHORT_SLOT_TIME ) #define EIFS ( SIFS + (8 * (IEEE80211_HEADER + ACK_SIZE)) ) +/* + * IEEE802.11 header defines + */ +static inline int is_rts_frame(u16 fc) +{ + return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)); +} + +static inline int is_cts_frame(u16 fc) +{ + return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS)); +} + +static inline int is_probe_resp(u16 fc) +{ + return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)); +} + +static inline int is_beacon(u16 fc) +{ + return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)); +} + /* * Chipset identification * The chipset on the device is composed of a RT and RF chip. @@ -601,7 +628,6 @@ enum rt2x00_flags { DRIVER_REQUIRE_BEACON_GUARD, DRIVER_REQUIRE_ATIM_QUEUE, DRIVER_REQUIRE_SCHEDULED, - DRIVER_REQUIRE_DMA, /* * Driver configuration @@ -626,7 +652,11 @@ struct rt2x00_dev { * When accessing this variable, the rt2x00dev_{pci,usb} * macro's should be used for correct typecasting. */ - struct device *dev; + void *dev; +#define rt2x00dev_pci(__dev) ( (struct pci_dev *)(__dev)->dev ) +#define rt2x00dev_usb(__dev) ( (struct usb_interface *)(__dev)->dev ) +#define rt2x00dev_usb_dev(__dev)\ + ( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) ) /* * Callback functions. @@ -788,7 +818,6 @@ struct rt2x00_dev { /* * Scheduled work. */ - struct workqueue_struct *workqueue; struct work_struct intf_work; struct work_struct filter_work; @@ -901,11 +930,10 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) } /** - * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to map. + * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes. + * @queue: The queue for which the skb will be applicable. */ -void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); +struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue); /** * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input @@ -956,14 +984,26 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, enum queue_index index); +/** + * rt2x00queue_index_inc - Index incrementation function + * @queue: Queue (&struct data_queue) to perform the action on. + * @index: Index type (&enum queue_index) to perform the action on. + * + * This function will increase the requested index on the queue, + * it will grab the appropriate locks and handle queue overflow events by + * resetting the index to the start of the queue. + */ +void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); + + /* * Interrupt context handlers. */ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc); -void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry); +void rt2x00lib_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc); /* * mac80211 handlers. diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index ae8ab71fe474..9ea677320daa 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -74,7 +74,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) rt2x00lib_reset_link_tuner(rt2x00dev); - queue_delayed_work(rt2x00dev->workqueue, + queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, LINK_TUNE_INTERVAL); } @@ -137,6 +137,14 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) return; + /* + * Stop all scheduled work. + */ + if (work_pending(&rt2x00dev->intf_work)) + cancel_work_sync(&rt2x00dev->intf_work); + if (work_pending(&rt2x00dev->filter_work)) + cancel_work_sync(&rt2x00dev->filter_work); + /* * Stop the TX queues. */ @@ -392,8 +400,8 @@ static void rt2x00lib_link_tuner(struct work_struct *work) * Increase tuner counter, and reschedule the next link tuner run. */ rt2x00dev->link.count++; - queue_delayed_work(rt2x00dev->workqueue, - &rt2x00dev->link.work, LINK_TUNE_INTERVAL); + queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, + LINK_TUNE_INTERVAL); } static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) @@ -426,15 +434,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, spin_unlock(&intf->lock); - /* - * It is possible the radio was disabled while the work had been - * scheduled. If that happens we should return here immediately, - * note that in the spinlock protected area above the delayed_flags - * have been cleared correctly. - */ - if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - if (delayed_flags & DELAYED_UPDATE_BEACON) { skb = ieee80211_beacon_get(rt2x00dev->hw, vif); if (skb && @@ -443,7 +442,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, } if (delayed_flags & DELAYED_CONFIG_ERP) - rt2x00lib_config_erp(rt2x00dev, intf, &conf); + rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf); if (delayed_flags & DELAYED_LED_ASSOC) rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); @@ -469,19 +468,12 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work) static void rt2x00lib_beacondone_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct rt2x00_dev *rt2x00dev = data; struct rt2x00_intf *intf = vif_to_intf(vif); if (vif->type != IEEE80211_IF_TYPE_AP && vif->type != IEEE80211_IF_TYPE_IBSS) return; - /* - * Clean up the beacon skb. - */ - rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb); - intf->beacon->skb = NULL; - spin_lock(&intf->lock); intf->delayed_flags |= DELAYED_UPDATE_BEACON; spin_unlock(&intf->lock); @@ -496,7 +488,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) rt2x00lib_beacondone_iter, rt2x00dev); - queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -505,12 +497,6 @@ void rt2x00lib_txdone(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); - - /* - * Unmap the skb. - */ - rt2x00queue_unmap_skb(rt2x00dev, entry->skb); /* * Send frame to debugfs immediately, after this call is completed @@ -559,77 +545,39 @@ void rt2x00lib_txdone(struct queue_entry *entry, ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); else dev_kfree_skb_irq(entry->skb); - - /* - * Make this entry available for reuse. - */ entry->skb = NULL; - entry->flags = 0; - - rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry); - - __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); - - /* - * If the data queue was below the threshold before the txdone - * handler we must make sure the packet queue in the mac80211 stack - * is reenabled when the txdone handler has finished. - */ - if (!rt2x00queue_threshold(entry->queue)) - ieee80211_wake_queue(rt2x00dev->hw, qid); } EXPORT_SYMBOL_GPL(rt2x00lib_txdone); -void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry) +void rt2x00lib_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - struct rxdone_entry_desc rxdesc; - struct sk_buff *skb; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; + unsigned int header_size = ieee80211_get_hdrlen_from_skb(entry->skb); struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; const struct rt2x00_rate *rate; - unsigned int header_size; unsigned int align; unsigned int i; int idx = -1; - - /* - * Allocate a new sk_buffer. If no new buffer available, drop the - * received frame and reuse the existing buffer. - */ - skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry); - if (!skb) - return; - - /* - * Unmap the skb. - */ - rt2x00queue_unmap_skb(rt2x00dev, entry->skb); - - /* - * Extract the RXD details. - */ - memset(&rxdesc, 0, sizeof(rxdesc)); - rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); + u16 fc; /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. */ - header_size = ieee80211_get_hdrlen_from_skb(entry->skb); align = ((unsigned long)(entry->skb->data + header_size)) & 3; if (align) { skb_push(entry->skb, align); /* Move entire frame in 1 command */ memmove(entry->skb->data, entry->skb->data + align, - rxdesc.size); + rxdesc->size); } /* Update data pointers, trim buffer to correct size */ - skb_trim(entry->skb, rxdesc.size); + skb_trim(entry->skb, rxdesc->size); /* * Update RX statistics. @@ -638,10 +586,10 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, for (i = 0; i < sband->n_bitrates; i++) { rate = rt2x00_get_rate(sband->bitrates[i].hw_value); - if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && - (rate->plcp == rxdesc.signal)) || - (!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && - (rate->bitrate == rxdesc.signal))) { + if (((rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) && + (rate->plcp == rxdesc->signal)) || + (!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) && + (rate->bitrate == rxdesc->signal))) { idx = i; break; } @@ -649,8 +597,8 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, if (idx < 0) { WARNING(rt2x00dev, "Frame received with unrecognized signal," - "signal=0x%.2x, plcp=%d.\n", rxdesc.signal, - !!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP)); + "signal=0x%.2x, plcp=%d.\n", rxdesc->signal, + !!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP)); idx = 0; } @@ -658,17 +606,17 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, * Only update link status if this is a beacon frame carrying our bssid. */ hdr = (struct ieee80211_hdr *)entry->skb->data; - if (ieee80211_is_beacon(hdr->frame_control) && - (rxdesc.dev_flags & RXDONE_MY_BSS)) - rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi); + fc = le16_to_cpu(hdr->frame_control); + if (is_beacon(fc) && (rxdesc->dev_flags & RXDONE_MY_BSS)) + rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi); rt2x00dev->link.qual.rx_success++; rx_status->rate_idx = idx; rx_status->qual = - rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); - rx_status->signal = rxdesc.rssi; - rx_status->flag = rxdesc.flags; + rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi); + rx_status->signal = rxdesc->rssi; + rx_status->flag = rxdesc->flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; /* @@ -677,16 +625,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, */ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); - - /* - * Replace the skb with the freshly allocated one. - */ - entry->skb = skb; - entry->flags = 0; - - rt2x00dev->ops->lib->init_rxentry(rt2x00dev, entry); - - rt2x00queue_index_inc(entry->queue, Q_INDEX); + entry->skb = NULL; } EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); @@ -1064,10 +1003,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Initialize configuration work. */ - rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib"); - if (!rt2x00dev->workqueue) - goto exit; - INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); @@ -1127,13 +1062,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) rt2x00rfkill_free(rt2x00dev); rt2x00leds_unregister(rt2x00dev); - /* - * Stop all queued work. Note that most tasks will already be halted - * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize(). - */ - flush_workqueue(rt2x00dev->workqueue); - destroy_workqueue(rt2x00dev->workqueue); - /* * Free ieee80211_hw memory. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h b/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h index 1d1f0749375e..558f45bf27e3 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -98,57 +98,10 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, const int force_config); -/** - * DOC: Queue handlers - */ - -/** - * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @queue: The queue for which the skb will be applicable. - */ -struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry); - -/** - * rt2x00queue_unmap_skb - Unmap a skb from DMA. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to unmap. - */ -void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); - -/** - * rt2x00queue_free_skb - free a skb - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to free. - */ -void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); - -/** - * rt2x00queue_free_skb - free a skb - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to free. - */ -void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); - -/** - * rt2x00queue_write_tx_frame - Write TX frame to hardware - * @queue: Queue over which the frame should be send - * @skb: The skb to send +/* + * Queue handlers. */ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); - -/** - * rt2x00queue_index_inc - Index incrementation function - * @queue: Queue (&struct data_queue) to perform the action on. - * @index: Index type (&enum queue_index) to perform the action on. - * - * This function will increase the requested index on the queue, - * it will grab the appropriate locks and handle queue overflow events by - * resetting the index to the start of the queue. - */ -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); - void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev); void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev); int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c index 1253da89295b..c90992f613fe 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -431,7 +431,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); else - queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work); + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); } EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); @@ -512,7 +512,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); if (delayed) { intf->delayed_flags |= delayed; - queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); } spin_unlock(&intf->lock); } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c index adf2876ed8ab..8d6ad18d3890 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -60,8 +60,12 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry) * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(entry->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->desc = entry_priv->desc; skbdesc->desc_len = entry->queue->desc_size; + skbdesc->entry = entry; + + memcpy(entry_priv->data, entry->skb->data, entry->skb->len); return 0; } @@ -76,6 +80,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) struct queue_entry *entry; struct queue_entry_priv_pci *entry_priv; struct skb_frame_desc *skbdesc; + struct rxdone_entry_desc rxdesc; u32 word; while (1) { @@ -86,27 +91,110 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) break; + memset(&rxdesc, 0, sizeof(rxdesc)); + rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); + /* - * Fill in desc fields of the skb descriptor + * Allocate the sk_buffer and copy all data into it. + */ + entry->skb = rt2x00queue_alloc_rxskb(queue); + if (!entry->skb) + return; + + memcpy(entry->skb->data, entry_priv->data, rxdesc.size); + skb_trim(entry->skb, rxdesc.size); + + /* + * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(entry->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = entry->queue->desc_size; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; /* * Send the frame to rt2x00lib for further processing. */ - rt2x00lib_rxdone(rt2x00dev, entry); + rt2x00lib_rxdone(entry, &rxdesc); + + if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) { + rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1); + rt2x00_desc_write(entry_priv->desc, 0, word); + } + + rt2x00queue_index_inc(queue, Q_INDEX); } } EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); +void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, + struct txdone_entry_desc *txdesc) +{ + struct queue_entry_priv_pci *entry_priv = entry->priv_data; + enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); + u32 word; + + rt2x00lib_txdone(entry, txdesc); + + /* + * Make this entry available for reuse. + */ + entry->flags = 0; + + rt2x00_desc_read(entry_priv->desc, 0, &word); + rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0); + rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0); + rt2x00_desc_write(entry_priv->desc, 0, word); + + __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); + + /* + * If the data queue was below the threshold before the txdone + * handler we must make sure the packet queue in the mac80211 stack + * is reenabled when the txdone handler has finished. + */ + if (!rt2x00queue_threshold(entry->queue)) + ieee80211_wake_queue(rt2x00dev->hw, qid); + +} +EXPORT_SYMBOL_GPL(rt2x00pci_txdone); + /* * Device initialization handlers. */ +#define desc_size(__queue) \ +({ \ + ((__queue)->limit * (__queue)->desc_size);\ +}) + +#define data_size(__queue) \ +({ \ + ((__queue)->limit * (__queue)->data_size);\ +}) + +#define dma_size(__queue) \ +({ \ + data_size(__queue) + desc_size(__queue);\ +}) + +#define desc_offset(__queue, __base, __i) \ +({ \ + (__base) + data_size(__queue) + \ + ((__i) * (__queue)->desc_size); \ +}) + +#define data_offset(__queue, __base, __i) \ +({ \ + (__base) + \ + ((__i) * (__queue)->data_size); \ +}) + static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, struct data_queue *queue) { + struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); struct queue_entry_priv_pci *entry_priv; void *addr; dma_addr_t dma; @@ -115,21 +203,21 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, /* * Allocate DMA memory for descriptor and buffer. */ - addr = dma_alloc_coherent(rt2x00dev->dev, - queue->limit * queue->desc_size, - &dma, GFP_KERNEL | GFP_DMA); + addr = pci_alloc_consistent(pci_dev, dma_size(queue), &dma); if (!addr) return -ENOMEM; - memset(addr, 0, queue->limit * queue->desc_size); + memset(addr, 0, dma_size(queue)); /* * Initialize all queue entries to contain valid addresses. */ for (i = 0; i < queue->limit; i++) { entry_priv = queue->entries[i].priv_data; - entry_priv->desc = addr + i * queue->desc_size; - entry_priv->desc_dma = dma + i * queue->desc_size; + entry_priv->desc = desc_offset(queue, addr, i); + entry_priv->desc_dma = desc_offset(queue, dma, i); + entry_priv->data = data_offset(queue, addr, i); + entry_priv->data_dma = data_offset(queue, dma, i); } return 0; @@ -138,19 +226,19 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, struct data_queue *queue) { + struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); struct queue_entry_priv_pci *entry_priv = queue->entries[0].priv_data; - if (entry_priv->desc) - dma_free_coherent(rt2x00dev->dev, - queue->limit * queue->desc_size, - entry_priv->desc, entry_priv->desc_dma); - entry_priv->desc = NULL; + if (entry_priv->data) + pci_free_consistent(pci_dev, dma_size(queue), + entry_priv->data, entry_priv->data_dma); + entry_priv->data = NULL; } int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) { - struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev); + struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); struct data_queue *queue; int status; @@ -191,7 +279,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) /* * Free irq line. */ - free_irq(to_pci_dev(rt2x00dev->dev)->irq, rt2x00dev); + free_irq(rt2x00dev_pci(rt2x00dev)->irq, rt2x00dev); /* * Free DMA @@ -220,7 +308,7 @@ static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev) { - struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev); + struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); @@ -269,7 +357,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) if (pci_set_mwi(pci_dev)) ERROR_PROBE("MWI not available.\n"); - if (dma_set_mask(&pci_dev->dev, DMA_32BIT_MASK)) { + if (pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) { ERROR_PROBE("PCI DMA not supported.\n"); retval = -EIO; goto exit_disable_device; @@ -285,7 +373,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) pci_set_drvdata(pci_dev, hw); rt2x00dev = hw->priv; - rt2x00dev->dev = &pci_dev->dev; + rt2x00dev->dev = pci_dev; rt2x00dev->ops = ops; rt2x00dev->hw = hw; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h index 50c6df4f81db..87c4a0cd78db 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -107,6 +107,9 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry); struct queue_entry_priv_pci { __le32 *desc; dma_addr_t desc_dma; + + void *data; + dma_addr_t data_dma; }; /** @@ -115,6 +118,15 @@ struct queue_entry_priv_pci { */ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); +/** + * rt2x00pci_txdone - Handle TX done events + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @entry: Entry which has completed the transmission of a frame. + * @desc: TX done descriptor + */ +void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, + struct txdone_entry_desc *desc); + /* * Device initialization handlers. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c index 8e86611791f0..7b52039b01a6 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -25,30 +25,34 @@ #include #include -#include #include "rt2x00.h" #include "rt2x00lib.h" -struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry) +struct sk_buff *rt2x00queue_alloc_rxskb(struct data_queue *queue) { + struct sk_buff *skb; unsigned int frame_size; unsigned int reserved_size; - struct sk_buff *skb; - struct skb_frame_desc *skbdesc; /* * The frame size includes descriptor size, because the * hardware directly receive the frame into the skbuffer. */ - frame_size = entry->queue->data_size + entry->queue->desc_size; + frame_size = queue->data_size + queue->desc_size; /* - * Reserve a few bytes extra headroom to allow drivers some moving - * space (e.g. for alignment), while keeping the skb aligned. + * For the allocation we should keep a few things in mind: + * 1) 4byte alignment of 802.11 payload + * + * For (1) we need at most 4 bytes to guarentee the correct + * alignment. We are going to optimize the fact that the chance + * that the 802.11 header_size % 4 == 2 is much bigger then + * anything else. However since we need to move the frame up + * to 3 bytes to the front, which means we need to preallocate + * 6 bytes. */ - reserved_size = 8; + reserved_size = 6; /* * Allocate skbuffer. @@ -60,56 +64,9 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, skb_reserve(skb, reserved_size); skb_put(skb, frame_size); - /* - * Populate skbdesc. - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->entry = entry; - - if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) { - skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, - skb->data, - skb->len, - DMA_FROM_DEVICE); - skbdesc->flags |= SKBDESC_DMA_MAPPED_RX; - } - return skb; } - -void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - - skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len, - DMA_TO_DEVICE); - skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; -} -EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); - -void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - - if (skbdesc->flags & SKBDESC_DMA_MAPPED_RX) { - dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, - DMA_FROM_DEVICE); - skbdesc->flags &= ~SKBDESC_DMA_MAPPED_RX; - } - - if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { - dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, - DMA_TO_DEVICE); - skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; - } -} - -void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) -{ - rt2x00queue_unmap_skb(rt2x00dev, skb); - dev_kfree_skb_any(skb); -} +EXPORT_SYMBOL_GPL(rt2x00queue_alloc_rxskb); void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc) @@ -123,6 +80,7 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, unsigned int data_length; unsigned int duration; unsigned int residual; + u16 frame_control; memset(txdesc, 0, sizeof(*txdesc)); @@ -137,6 +95,11 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, /* Data length should be extended with 4 bytes for CRC */ data_length = entry->skb->len + 4; + /* + * Read required fields from ieee80211 header. + */ + frame_control = le16_to_cpu(hdr->frame_control); + /* * Check whether this frame is to be acked. */ @@ -146,10 +109,9 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, /* * Check if this is a RTS/CTS frame */ - if (ieee80211_is_rts(hdr->frame_control) || - ieee80211_is_cts(hdr->frame_control)) { + if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) { __set_bit(ENTRY_TXD_BURST, &txdesc->flags); - if (ieee80211_is_rts(hdr->frame_control)) + if (is_rts_frame(frame_control)) __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags); else __set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags); @@ -177,8 +139,7 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * Beacons and probe responses require the tsf timestamp * to be inserted into the frame. */ - if (ieee80211_is_beacon(hdr->frame_control) || - ieee80211_is_probe_resp(hdr->frame_control)) + if (txdesc->queue == QID_BEACON || is_probe_resp(frame_control)) __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); /* @@ -275,7 +236,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) { struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); struct txentry_desc txdesc; - struct skb_frame_desc *skbdesc; if (unlikely(rt2x00queue_full(queue))) return -EINVAL; @@ -296,21 +256,11 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) entry->skb = skb; rt2x00queue_create_tx_descriptor(entry, &txdesc); - /* - * skb->cb array is now ours and we are free to use it. - */ - skbdesc = get_skb_frame_desc(entry->skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->entry = entry; - if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); return -EIO; } - if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) - rt2x00queue_map_txskb(queue->rt2x00dev, skb); - __set_bit(ENTRY_DATA_PENDING, &entry->flags); rt2x00queue_index_inc(queue, Q_INDEX); @@ -386,6 +336,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) spin_unlock_irqrestore(&queue->lock, irqflags); } +EXPORT_SYMBOL_GPL(rt2x00queue_index_inc); static void rt2x00queue_reset(struct data_queue *queue) { @@ -475,41 +426,12 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, return 0; } -static void rt2x00queue_free_skbs(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) -{ - unsigned int i; - - if (!queue->entries) - return; - - for (i = 0; i < queue->limit; i++) { - if (queue->entries[i].skb) - rt2x00queue_free_skb(rt2x00dev, queue->entries[i].skb); - } -} - -static int rt2x00queue_alloc_rxskbs(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) -{ - unsigned int i; - struct sk_buff *skb; - - for (i = 0; i < queue->limit; i++) { - skb = rt2x00queue_alloc_rxskb(rt2x00dev, &queue->entries[i]); - if (!skb) - return -ENOMEM; - queue->entries[i].skb = skb; - } - - return 0; -} - int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; int status; + status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); if (status) goto exit; @@ -524,14 +446,11 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) if (status) goto exit; - if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) { - status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], - rt2x00dev->ops->atim); - if (status) - goto exit; - } + if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) + return 0; - status = rt2x00queue_alloc_rxskbs(rt2x00dev, rt2x00dev->rx); + status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], + rt2x00dev->ops->atim); if (status) goto exit; @@ -549,8 +468,6 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; - rt2x00queue_free_skbs(rt2x00dev, rt2x00dev->rx); - queue_for_each(rt2x00dev, queue) { kfree(queue->entries); queue->entries = NULL; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h index 5dd9cca3c62c..fcf52520b016 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -42,18 +42,15 @@ /** * DOC: Number of entries per queue * - * Under normal load without fragmentation 12 entries are sufficient - * without the queue being filled up to the maximum. When using fragmentation - * and the queue threshold code we need to add some additional margins to - * make sure the queue will never (or only under extreme load) fill up - * completely. - * Since we don't use preallocated DMA having a large number of queue entries - * will have only minimal impact on the memory requirements for the queue. + * After research it was concluded that 12 entries in a RX and TX + * queue would be sufficient. Although this is almost one third of + * the amount the legacy driver allocated, the queues aren't getting + * filled to the maximum even when working with the maximum rate. */ -#define RX_ENTRIES 24 -#define TX_ENTRIES 24 +#define RX_ENTRIES 12 +#define TX_ENTRIES 12 #define BEACON_ENTRIES 1 -#define ATIM_ENTRIES 8 +#define ATIM_ENTRIES 1 /** * enum data_queue_qid: Queue identification @@ -85,13 +82,10 @@ enum data_queue_qid { /** * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc * - * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX - * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX */ -enum skb_frame_desc_flags { - SKBDESC_DMA_MAPPED_RX = (1 << 0), - SKBDESC_DMA_MAPPED_TX = (1 << 1), -}; +//enum skb_frame_desc_flags { +// TEMPORARILY EMPTY +//}; /** * struct skb_frame_desc: Descriptor information for the skb buffer @@ -100,20 +94,19 @@ enum skb_frame_desc_flags { * this structure should not exceed the size of that array (40 bytes). * * @flags: Frame flags, see &enum skb_frame_desc_flags. - * @desc_len: Length of the frame descriptor. + * @data: Pointer to data part of frame (Start of ieee80211 header). * @desc: Pointer to descriptor part of the frame. * Note that this pointer could point to something outside * of the scope of the skb->data pointer. - * @skb_dma: (PCI-only) the DMA address associated with the sk buffer. + * @data_len: Length of the frame data. + * @desc_len: Length of the frame descriptor. * @entry: The entry to which this sk buffer belongs. */ struct skb_frame_desc { unsigned int flags; - unsigned int desc_len; void *desc; - - dma_addr_t skb_dma; + unsigned int desc_len; struct queue_entry *entry; }; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/trunk/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 207281cfa8b7..fcef9885ab5e 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -45,17 +45,14 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags)) return 0; - if (state == RFKILL_STATE_UNBLOCKED) { + if (state == RFKILL_STATE_ON) { INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n"); __clear_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags); retval = rt2x00lib_enable_radio(rt2x00dev); - } else if (state == RFKILL_STATE_SOFT_BLOCKED) { + } else if (state == RFKILL_STATE_OFF) { INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n"); __set_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags); rt2x00lib_disable_radio(rt2x00dev); - } else { - WARNING(rt2x00dev, "Received unexpected rfkill state %d.\n", - state); } return retval; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c index 83862e7f7aec..3080969ae5b3 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -40,7 +40,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, void *buffer, const u16 buffer_length, const int timeout) { - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); int status; unsigned int i; unsigned int pipe = @@ -130,9 +130,10 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct txdone_entry_desc txdesc; + enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || - !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* @@ -156,12 +157,26 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) txdesc.retry = 0; rt2x00lib_txdone(entry, &txdesc); + + /* + * Make this entry available for reuse. + */ + entry->flags = 0; + rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); + + /* + * If the data queue was below the threshold before the txdone + * handler we must make sure the packet queue in the mac80211 stack + * is reenabled when the txdone handler has finished. + */ + if (!rt2x00queue_threshold(entry->queue)) + ieee80211_wake_queue(rt2x00dev->hw, qid); } int rt2x00usb_write_tx_data(struct queue_entry *entry) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); struct queue_entry_priv_usb *entry_priv = entry->priv_data; struct skb_frame_desc *skbdesc; u32 length; @@ -176,8 +191,10 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry) * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(entry->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->desc = entry->skb->data; skbdesc->desc_len = entry->queue->desc_size; + skbdesc->entry = entry; /* * USB devices cannot blindly pass the skb->len as the @@ -247,11 +264,13 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) { struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + struct sk_buff *skb; + struct skb_frame_desc *skbdesc; + struct rxdone_entry_desc rxdesc; u8 rxd[32]; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || - !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* @@ -259,22 +278,50 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * to be actually valid, or if the urb is signaling * a problem. */ - if (urb->actual_length < entry->queue->desc_size || urb->status) { - __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - usb_submit_urb(urb, GFP_ATOMIC); - return; - } + if (urb->actual_length < entry->queue->desc_size || urb->status) + goto skip_entry; /* - * Fill in desc fields of the skb descriptor + * Fill in skb descriptor */ + skbdesc = get_skb_frame_desc(entry->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->entry = entry; skbdesc->desc = rxd; skbdesc->desc_len = entry->queue->desc_size; + memset(&rxdesc, 0, sizeof(rxdesc)); + rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); + + /* + * Allocate a new sk buffer to replace the current one. + * If allocation fails, we should drop the current frame + * so we can recycle the existing sk buffer for the new frame. + */ + skb = rt2x00queue_alloc_rxskb(entry->queue); + if (!skb) + goto skip_entry; + /* * Send the frame to rt2x00lib for further processing. */ - rt2x00lib_rxdone(rt2x00dev, entry); + rt2x00lib_rxdone(entry, &rxdesc); + + /* + * Replace current entry's skb with the newly allocated one, + * and reinitialize the urb. + */ + entry->skb = skb; + urb->transfer_buffer = entry->skb->data; + urb->transfer_buffer_length = entry->skb->len; + +skip_entry: + if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) { + __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + usb_submit_urb(urb, GFP_ATOMIC); + } + + rt2x00queue_index_inc(entry->queue, Q_INDEX); } /* @@ -284,7 +331,6 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) { struct queue_entry_priv_usb *entry_priv; struct queue_entry_priv_usb_bcn *bcn_priv; - struct data_queue *queue; unsigned int i; rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, @@ -293,11 +339,9 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Cancel all queues. */ - queue_for_each(rt2x00dev, queue) { - for (i = 0; i < queue->limit; i++) { - entry_priv = queue->entries[i].priv_data; - usb_kill_urb(entry_priv->urb); - } + for (i = 0; i < rt2x00dev->rx->limit; i++) { + entry_priv = rt2x00dev->rx->entries[i].priv_data; + usb_kill_urb(entry_priv->urb); } /* @@ -320,7 +364,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); struct queue_entry_priv_usb *entry_priv = entry->priv_data; usb_fill_bulk_urb(entry_priv->urb, usb_dev, @@ -387,6 +431,8 @@ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, entry_priv = queue->entries[i].priv_data; usb_kill_urb(entry_priv->urb); usb_free_urb(entry_priv->urb); + if (queue->entries[i].skb) + kfree_skb(queue->entries[i].skb); } /* @@ -408,7 +454,10 @@ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; - int status; + struct sk_buff *skb; + unsigned int entry_size; + unsigned int i; + int uninitialized_var(status); /* * Allocate DMA @@ -419,6 +468,18 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) goto exit; } + /* + * For the RX queue, skb's should be allocated. + */ + entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size; + for (i = 0; i < rt2x00dev->rx->limit; i++) { + skb = rt2x00queue_alloc_rxskb(rt2x00dev->rx); + if (!skb) + goto exit; + + rt2x00dev->rx->entries[i].skb = skb; + } + return 0; exit: @@ -497,7 +558,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, usb_set_intfdata(usb_intf, hw); rt2x00dev = hw->priv; - rt2x00dev->dev = &usb_intf->dev; + rt2x00dev->dev = usb_intf; rt2x00dev->ops = ops; rt2x00dev->hw = hw; mutex_init(&rt2x00dev->usb_cache_mutex); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h index aad794adf52c..b1187c812e7f 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -26,12 +26,6 @@ #ifndef RT2X00USB_H #define RT2X00USB_H -#define to_usb_device_intf(d) \ -({ \ - struct usb_interface *intf = to_usb_interface(d); \ - interface_to_usbdev(intf); \ -}) - /* * This variable should be used with the * usb_driver structure initialization. diff --git a/trunk/drivers/net/wireless/rt2x00/rt61pci.c b/trunk/drivers/net/wireless/rt2x00/rt61pci.c index bbf1048f6400..5b7267ece1b9 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt61pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt61pci.c @@ -1030,12 +1030,11 @@ static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); u32 word; rt2x00_desc_read(entry_priv->desc, 5, &word); rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, - skbdesc->skb_dma); + entry_priv->data_dma); rt2x00_desc_write(entry_priv->desc, 5, word); rt2x00_desc_read(entry_priv->desc, 0, &word); @@ -1523,6 +1522,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; __le32 *txd = skbdesc->desc; u32 word; @@ -1557,7 +1557,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 6, &word); rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, - skbdesc->skb_dma); + entry_priv->data_dma); rt2x00_desc_write(txd, 6, word); if (skbdesc->desc_len > TXINFO_SIZE) { @@ -1767,7 +1767,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) __set_bit(TXDONE_UNKNOWN, &txdesc.flags); txdesc.retry = 0; - rt2x00lib_txdone(entry_done, &txdesc); + rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc); entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); } @@ -1787,7 +1787,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) } txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); - rt2x00lib_txdone(entry, &txdesc); + rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } } @@ -1973,7 +1973,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * To determine the RT chip we have to read the * PCI header of the device. */ - pci_read_config_word(to_pci_dev(rt2x00dev->dev), + pci_read_config_word(rt2x00dev_pci(rt2x00dev), PCI_CONFIG_HEADER_DEVICE, &device); value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); @@ -2239,7 +2239,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) IEEE80211_HW_SIGNAL_DBM; rt2x00dev->hw->extra_tx_headroom = 0; - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); + SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); @@ -2302,10 +2302,9 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) rt61pci_probe_hw_mode(rt2x00dev); /* - * This device requires firmware and DMA mapped skbs. + * This device requires firmware. */ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); /* * Set the rssi offset. @@ -2403,12 +2402,6 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) skb->data, skb->len); rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON); - /* - * Clean up beacon skb. - */ - dev_kfree_skb_any(skb); - intf->beacon->skb = NULL; - return 0; } diff --git a/trunk/drivers/net/wireless/rt2x00/rt73usb.c b/trunk/drivers/net/wireless/rt2x00/rt73usb.c index 3ef318e098e7..fceefd730ab8 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt73usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt73usb.c @@ -134,8 +134,11 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - goto exit_fail; + if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { + ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); + mutex_unlock(&rt2x00dev->usb_cache_mutex); + return; + } /* * Write the data into the BBP. @@ -148,13 +151,6 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); mutex_unlock(&rt2x00dev->usb_cache_mutex); - - return; - -exit_fail: - mutex_unlock(&rt2x00dev->usb_cache_mutex); - - ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); } static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -168,8 +164,11 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - goto exit_fail; + if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { + ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); + mutex_unlock(&rt2x00dev->usb_cache_mutex); + return; + } /* * Write the request into the BBP. @@ -185,19 +184,14 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) - goto exit_fail; + if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { + ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); + *value = 0xff; + return; + } *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); mutex_unlock(&rt2x00dev->usb_cache_mutex); - - return; - -exit_fail: - mutex_unlock(&rt2x00dev->usb_cache_mutex); - - ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); - *value = 0xff; } static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, @@ -1827,7 +1821,7 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) IEEE80211_HW_SIGNAL_DBM; rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); + SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); @@ -2007,12 +2001,6 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) REGISTER_TIMEOUT32(skb->len)); rt73usb_kick_tx_queue(rt2x00dev, QID_BEACON); - /* - * Clean up the beacon skb. - */ - dev_kfree_skb(skb); - intf->beacon->skb = NULL; - return 0; } diff --git a/trunk/drivers/net/wireless/strip.c b/trunk/drivers/net/wireless/strip.c new file mode 100644 index 000000000000..883af891ebfb --- /dev/null +++ b/trunk/drivers/net/wireless/strip.c @@ -0,0 +1,2804 @@ +/* + * Copyright 1996 The Board of Trustees of The Leland Stanford + * Junior University. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. Stanford University + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + * + * strip.c This module implements Starmode Radio IP (STRIP) + * for kernel-based devices like TTY. It interfaces between a + * raw TTY, and the kernel's INET protocol layers (via DDI). + * + * Version: @(#)strip.c 1.3 July 1997 + * + * Author: Stuart Cheshire + * + * Fixes: v0.9 12th Feb 1996 (SC) + * New byte stuffing (2+6 run-length encoding) + * New watchdog timer task + * New Protocol key (SIP0) + * + * v0.9.1 3rd March 1996 (SC) + * Changed to dynamic device allocation -- no more compile + * time (or boot time) limit on the number of STRIP devices. + * + * v0.9.2 13th March 1996 (SC) + * Uses arp cache lookups (but doesn't send arp packets yet) + * + * v0.9.3 17th April 1996 (SC) + * Fixed bug where STR_ERROR flag was getting set unneccessarily + * (causing otherwise good packets to be unneccessarily dropped) + * + * v0.9.4 27th April 1996 (SC) + * First attempt at using "&COMMAND" Starmode AT commands + * + * v0.9.5 29th May 1996 (SC) + * First attempt at sending (unicast) ARP packets + * + * v0.9.6 5th June 1996 (Elliot) + * Put "message level" tags in every "printk" statement + * + * v0.9.7 13th June 1996 (laik) + * Added support for the /proc fs + * + * v0.9.8 July 1996 (Mema) + * Added packet logging + * + * v1.0 November 1996 (SC) + * Fixed (severe) memory leaks in the /proc fs code + * Fixed race conditions in the logging code + * + * v1.1 January 1997 (SC) + * Deleted packet logging (use tcpdump instead) + * Added support for Metricom Firmware v204 features + * (like message checksums) + * + * v1.2 January 1997 (SC) + * Put portables list back in + * + * v1.3 July 1997 (SC) + * Made STRIP driver set the radio's baud rate automatically. + * It is no longer necessarily to manually set the radio's + * rate permanently to 115200 -- the driver handles setting + * the rate automatically. + */ + +#ifdef MODULE +static const char StripVersion[] = "1.3A-STUART.CHESHIRE-MODULAR"; +#else +static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; +#endif + +#define TICKLE_TIMERS 0 +#define EXT_COUNTERS 1 + + +/************************************************************************/ +/* Header files */ + +#include +#include +#include +#include +#include +#include + +# include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/************************************************************************/ +/* Useful structures and definitions */ + +/* + * A MetricomKey identifies the protocol being carried inside a Metricom + * Starmode packet. + */ + +typedef union { + __u8 c[4]; + __u32 l; +} MetricomKey; + +/* + * An IP address can be viewed as four bytes in memory (which is what it is) or as + * a single 32-bit long (which is convenient for assignment, equality testing etc.) + */ + +typedef union { + __u8 b[4]; + __u32 l; +} IPaddr; + +/* + * A MetricomAddressString is used to hold a printable representation of + * a Metricom address. + */ + +typedef struct { + __u8 c[24]; +} MetricomAddressString; + +/* Encapsulation can expand packet of size x to 65/64x + 1 + * Sent packet looks like "*
*" + * 1 1 1-18 1 4 ? 1 + * eg. *0000-1234*SIP0 + * We allow 31 bytes for the stars, the key, the address and the s + */ +#define STRIP_ENCAP_SIZE(X) (32 + (X)*65L/64L) + +/* + * A STRIP_Header is never really sent over the radio, but making a dummy + * header for internal use within the kernel that looks like an Ethernet + * header makes certain other software happier. For example, tcpdump + * already understands Ethernet headers. + */ + +typedef struct { + MetricomAddress dst_addr; /* Destination address, e.g. "0000-1234" */ + MetricomAddress src_addr; /* Source address, e.g. "0000-5678" */ + unsigned short protocol; /* The protocol type, using Ethernet codes */ +} STRIP_Header; + +typedef struct { + char c[60]; +} MetricomNode; + +#define NODE_TABLE_SIZE 32 +typedef struct { + struct timeval timestamp; + int num_nodes; + MetricomNode node[NODE_TABLE_SIZE]; +} MetricomNodeTable; + +enum { FALSE = 0, TRUE = 1 }; + +/* + * Holds the radio's firmware version. + */ +typedef struct { + char c[50]; +} FirmwareVersion; + +/* + * Holds the radio's serial number. + */ +typedef struct { + char c[18]; +} SerialNumber; + +/* + * Holds the radio's battery voltage. + */ +typedef struct { + char c[11]; +} BatteryVoltage; + +typedef struct { + char c[8]; +} char8; + +enum { + NoStructure = 0, /* Really old firmware */ + StructuredMessages = 1, /* Parsable AT response msgs */ + ChecksummedMessages = 2 /* Parsable AT response msgs with checksums */ +}; + +struct strip { + int magic; + /* + * These are pointers to the malloc()ed frame buffers. + */ + + unsigned char *rx_buff; /* buffer for received IP packet */ + unsigned char *sx_buff; /* buffer for received serial data */ + int sx_count; /* received serial data counter */ + int sx_size; /* Serial buffer size */ + unsigned char *tx_buff; /* transmitter buffer */ + unsigned char *tx_head; /* pointer to next byte to XMIT */ + int tx_left; /* bytes left in XMIT queue */ + int tx_size; /* Serial buffer size */ + + /* + * STRIP interface statistics. + */ + + unsigned long rx_packets; /* inbound frames counter */ + unsigned long tx_packets; /* outbound frames counter */ + unsigned long rx_errors; /* Parity, etc. errors */ + unsigned long tx_errors; /* Planned stuff */ + unsigned long rx_dropped; /* No memory for skb */ + unsigned long tx_dropped; /* When MTU change */ + unsigned long rx_over_errors; /* Frame bigger then STRIP buf. */ + + unsigned long pps_timer; /* Timer to determine pps */ + unsigned long rx_pps_count; /* Counter to determine pps */ + unsigned long tx_pps_count; /* Counter to determine pps */ + unsigned long sx_pps_count; /* Counter to determine pps */ + unsigned long rx_average_pps; /* rx packets per second * 8 */ + unsigned long tx_average_pps; /* tx packets per second * 8 */ + unsigned long sx_average_pps; /* sent packets per second * 8 */ + +#ifdef EXT_COUNTERS + unsigned long rx_bytes; /* total received bytes */ + unsigned long tx_bytes; /* total received bytes */ + unsigned long rx_rbytes; /* bytes thru radio i/f */ + unsigned long tx_rbytes; /* bytes thru radio i/f */ + unsigned long rx_sbytes; /* tot bytes thru serial i/f */ + unsigned long tx_sbytes; /* tot bytes thru serial i/f */ + unsigned long rx_ebytes; /* tot stat/err bytes */ + unsigned long tx_ebytes; /* tot stat/err bytes */ +#endif + + /* + * Internal variables. + */ + + struct list_head list; /* Linked list of devices */ + + int discard; /* Set if serial error */ + int working; /* Is radio working correctly? */ + int firmware_level; /* Message structuring level */ + int next_command; /* Next periodic command */ + unsigned int user_baud; /* The user-selected baud rate */ + int mtu; /* Our mtu (to spot changes!) */ + long watchdog_doprobe; /* Next time to test the radio */ + long watchdog_doreset; /* Time to do next reset */ + long gratuitous_arp; /* Time to send next ARP refresh */ + long arp_interval; /* Next ARP interval */ + struct timer_list idle_timer; /* For periodic wakeup calls */ + MetricomAddress true_dev_addr; /* True address of radio */ + int manual_dev_addr; /* Hack: See note below */ + + FirmwareVersion firmware_version; /* The radio's firmware version */ + SerialNumber serial_number; /* The radio's serial number */ + BatteryVoltage battery_voltage; /* The radio's battery voltage */ + + /* + * Other useful structures. + */ + + struct tty_struct *tty; /* ptr to TTY structure */ + struct net_device *dev; /* Our device structure */ + + /* + * Neighbour radio records + */ + + MetricomNodeTable portables; + MetricomNodeTable poletops; +}; + +/* + * Note: manual_dev_addr hack + * + * It is not possible to change the hardware address of a Metricom radio, + * or to send packets with a user-specified hardware source address, thus + * trying to manually set a hardware source address is a questionable + * thing to do. However, if the user *does* manually set the hardware + * source address of a STRIP interface, then the kernel will believe it, + * and use it in certain places. For example, the hardware address listed + * by ifconfig will be the manual address, not the true one. + * (Both addresses are listed in /proc/net/strip.) + * Also, ARP packets will be sent out giving the user-specified address as + * the source address, not the real address. This is dangerous, because + * it means you won't receive any replies -- the ARP replies will go to + * the specified address, which will be some other radio. The case where + * this is useful is when that other radio is also connected to the same + * machine. This allows you to connect a pair of radios to one machine, + * and to use one exclusively for inbound traffic, and the other + * exclusively for outbound traffic. Pretty neat, huh? + * + * Here's the full procedure to set this up: + * + * 1. "slattach" two interfaces, e.g. st0 for outgoing packets, + * and st1 for incoming packets + * + * 2. "ifconfig" st0 (outbound radio) to have the hardware address + * which is the real hardware address of st1 (inbound radio). + * Now when it sends out packets, it will masquerade as st1, and + * replies will be sent to that radio, which is exactly what we want. + * + * 3. Set the route table entry ("route add default ..." or + * "route add -net ...", as appropriate) to send packets via the st0 + * interface (outbound radio). Do not add any route which sends packets + * out via the st1 interface -- that radio is for inbound traffic only. + * + * 4. "ifconfig" st1 (inbound radio) to have hardware address zero. + * This tells the STRIP driver to "shut down" that interface and not + * send any packets through it. In particular, it stops sending the + * periodic gratuitous ARP packets that a STRIP interface normally sends. + * Also, when packets arrive on that interface, it will search the + * interface list to see if there is another interface who's manual + * hardware address matches its own real address (i.e. st0 in this + * example) and if so it will transfer ownership of the skbuff to + * that interface, so that it looks to the kernel as if the packet + * arrived on that interface. This is necessary because when the + * kernel sends an ARP packet on st0, it expects to get a reply on + * st0, and if it sees the reply come from st1 then it will ignore + * it (to be accurate, it puts the entry in the ARP table, but + * labelled in such a way that st0 can't use it). + * + * Thanks to Petros Maniatis for coming up with the idea of splitting + * inbound and outbound traffic between two interfaces, which turned + * out to be really easy to implement, even if it is a bit of a hack. + * + * Having set a manual address on an interface, you can restore it + * to automatic operation (where the address is automatically kept + * consistent with the real address of the radio) by setting a manual + * address of all ones, e.g. "ifconfig st0 hw strip FFFFFFFFFFFF" + * This 'turns off' manual override mode for the device address. + * + * Note: The IEEE 802 headers reported in tcpdump will show the *real* + * radio addresses the packets were sent and received from, so that you + * can see what is really going on with packets, and which interfaces + * they are really going through. + */ + + +/************************************************************************/ +/* Constants */ + +/* + * CommandString1 works on all radios + * Other CommandStrings are only used with firmware that provides structured responses. + * + * ats319=1 Enables Info message for node additions and deletions + * ats319=2 Enables Info message for a new best node + * ats319=4 Enables checksums + * ats319=8 Enables ACK messages + */ + +static const int MaxCommandStringLength = 32; +static const int CompatibilityCommand = 1; + +static const char CommandString0[] = "*&COMMAND*ATS319=7"; /* Turn on checksums & info messages */ +static const char CommandString1[] = "*&COMMAND*ATS305?"; /* Query radio name */ +static const char CommandString2[] = "*&COMMAND*ATS325?"; /* Query battery voltage */ +static const char CommandString3[] = "*&COMMAND*ATS300?"; /* Query version information */ +static const char CommandString4[] = "*&COMMAND*ATS311?"; /* Query poletop list */ +static const char CommandString5[] = "*&COMMAND*AT~LA"; /* Query portables list */ +typedef struct { + const char *string; + long length; +} StringDescriptor; + +static const StringDescriptor CommandString[] = { + {CommandString0, sizeof(CommandString0) - 1}, + {CommandString1, sizeof(CommandString1) - 1}, + {CommandString2, sizeof(CommandString2) - 1}, + {CommandString3, sizeof(CommandString3) - 1}, + {CommandString4, sizeof(CommandString4) - 1}, + {CommandString5, sizeof(CommandString5) - 1} +}; + +#define GOT_ALL_RADIO_INFO(S) \ + ((S)->firmware_version.c[0] && \ + (S)->battery_voltage.c[0] && \ + memcmp(&(S)->true_dev_addr, zero_address.c, sizeof(zero_address))) + +static const char hextable[16] = "0123456789ABCDEF"; + +static const MetricomAddress zero_address; +static const MetricomAddress broadcast_address = + { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} }; + +static const MetricomKey SIP0Key = { "SIP0" }; +static const MetricomKey ARP0Key = { "ARP0" }; +static const MetricomKey ATR_Key = { "ATR " }; +static const MetricomKey ACK_Key = { "ACK_" }; +static const MetricomKey INF_Key = { "INF_" }; +static const MetricomKey ERR_Key = { "ERR_" }; + +static const long MaxARPInterval = 60 * HZ; /* One minute */ + +/* + * Maximum Starmode packet length is 1183 bytes. Allowing 4 bytes for + * protocol key, 4 bytes for checksum, one byte for CR, and 65/64 expansion + * for STRIP encoding, that translates to a maximum payload MTU of 1155. + * Note: A standard NFS 1K data packet is a total of 0x480 (1152) bytes + * long, including IP header, UDP header, and NFS header. Setting the STRIP + * MTU to 1152 allows us to send default sized NFS packets without fragmentation. + */ +static const unsigned short MAX_SEND_MTU = 1152; +static const unsigned short MAX_RECV_MTU = 1500; /* Hoping for Ethernet sized packets in the future! */ +static const unsigned short DEFAULT_STRIP_MTU = 1152; +static const int STRIP_MAGIC = 0x5303; +static const long LongTime = 0x7FFFFFFF; + +/************************************************************************/ +/* Global variables */ + +static LIST_HEAD(strip_list); +static DEFINE_SPINLOCK(strip_lock); + +/************************************************************************/ +/* Macros */ + +/* Returns TRUE if text T begins with prefix P */ +#define has_prefix(T,L,P) (((L) >= sizeof(P)-1) && !strncmp((T), (P), sizeof(P)-1)) + +/* Returns TRUE if text T of length L is equal to string S */ +#define text_equal(T,L,S) (((L) == sizeof(S)-1) && !strncmp((T), (S), sizeof(S)-1)) + +#define READHEX(X) ((X)>='0' && (X)<='9' ? (X)-'0' : \ + (X)>='a' && (X)<='f' ? (X)-'a'+10 : \ + (X)>='A' && (X)<='F' ? (X)-'A'+10 : 0 ) + +#define READHEX16(X) ((__u16)(READHEX(X))) + +#define READDEC(X) ((X)>='0' && (X)<='9' ? (X)-'0' : 0) + +#define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)])) + +#define JIFFIE_TO_SEC(X) ((X) / HZ) + + +/************************************************************************/ +/* Utility routines */ + +static int arp_query(unsigned char *haddr, u32 paddr, + struct net_device *dev) +{ + struct neighbour *neighbor_entry; + int ret = 0; + + neighbor_entry = neigh_lookup(&arp_tbl, &paddr, dev); + + if (neighbor_entry != NULL) { + neighbor_entry->used = jiffies; + if (neighbor_entry->nud_state & NUD_VALID) { + memcpy(haddr, neighbor_entry->ha, dev->addr_len); + ret = 1; + } + neigh_release(neighbor_entry); + } + return ret; +} + +static void DumpData(char *msg, struct strip *strip_info, __u8 * ptr, + __u8 * end) +{ + static const int MAX_DumpData = 80; + __u8 pkt_text[MAX_DumpData], *p = pkt_text; + + *p++ = '\"'; + + while (ptr < end && p < &pkt_text[MAX_DumpData - 4]) { + if (*ptr == '\\') { + *p++ = '\\'; + *p++ = '\\'; + } else { + if (*ptr >= 32 && *ptr <= 126) { + *p++ = *ptr; + } else { + sprintf(p, "\\%02X", *ptr); + p += 3; + } + } + ptr++; + } + + if (ptr == end) + *p++ = '\"'; + *p++ = 0; + + printk(KERN_INFO "%s: %-13s%s\n", strip_info->dev->name, msg, pkt_text); +} + + +/************************************************************************/ +/* Byte stuffing/unstuffing routines */ + +/* Stuffing scheme: + * 00 Unused (reserved character) + * 01-3F Run of 2-64 different characters + * 40-7F Run of 1-64 different characters plus a single zero at the end + * 80-BF Run of 1-64 of the same character + * C0-FF Run of 1-64 zeroes (ASCII 0) + */ + +typedef enum { + Stuff_Diff = 0x00, + Stuff_DiffZero = 0x40, + Stuff_Same = 0x80, + Stuff_Zero = 0xC0, + Stuff_NoCode = 0xFF, /* Special code, meaning no code selected */ + + Stuff_CodeMask = 0xC0, + Stuff_CountMask = 0x3F, + Stuff_MaxCount = 0x3F, + Stuff_Magic = 0x0D /* The value we are eliminating */ +} StuffingCode; + +/* StuffData encodes the data starting at "src" for "length" bytes. + * It writes it to the buffer pointed to by "dst" (which must be at least + * as long as 1 + 65/64 of the input length). The output may be up to 1.6% + * larger than the input for pathological input, but will usually be smaller. + * StuffData returns the new value of the dst pointer as its result. + * "code_ptr_ptr" points to a "__u8 *" which is used to hold encoding state + * between calls, allowing an encoded packet to be incrementally built up + * from small parts. On the first call, the "__u8 *" pointed to should be + * initialized to NULL; between subsequent calls the calling routine should + * leave the value alone and simply pass it back unchanged so that the + * encoder can recover its current state. + */ + +#define StuffData_FinishBlock(X) \ +(*code_ptr = (X) ^ Stuff_Magic, code = Stuff_NoCode) + +static __u8 *StuffData(__u8 * src, __u32 length, __u8 * dst, + __u8 ** code_ptr_ptr) +{ + __u8 *end = src + length; + __u8 *code_ptr = *code_ptr_ptr; + __u8 code = Stuff_NoCode, count = 0; + + if (!length) + return (dst); + + if (code_ptr) { + /* + * Recover state from last call, if applicable + */ + code = (*code_ptr ^ Stuff_Magic) & Stuff_CodeMask; + count = (*code_ptr ^ Stuff_Magic) & Stuff_CountMask; + } + + while (src < end) { + switch (code) { + /* Stuff_NoCode: If no current code, select one */ + case Stuff_NoCode: + /* Record where we're going to put this code */ + code_ptr = dst++; + count = 0; /* Reset the count (zero means one instance) */ + /* Tentatively start a new block */ + if (*src == 0) { + code = Stuff_Zero; + src++; + } else { + code = Stuff_Same; + *dst++ = *src++ ^ Stuff_Magic; + } + /* Note: We optimistically assume run of same -- */ + /* which will be fixed later in Stuff_Same */ + /* if it turns out not to be true. */ + break; + + /* Stuff_Zero: We already have at least one zero encoded */ + case Stuff_Zero: + /* If another zero, count it, else finish this code block */ + if (*src == 0) { + count++; + src++; + } else { + StuffData_FinishBlock(Stuff_Zero + count); + } + break; + + /* Stuff_Same: We already have at least one byte encoded */ + case Stuff_Same: + /* If another one the same, count it */ + if ((*src ^ Stuff_Magic) == code_ptr[1]) { + count++; + src++; + break; + } + /* else, this byte does not match this block. */ + /* If we already have two or more bytes encoded, finish this code block */ + if (count) { + StuffData_FinishBlock(Stuff_Same + count); + break; + } + /* else, we only have one so far, so switch to Stuff_Diff code */ + code = Stuff_Diff; + /* and fall through to Stuff_Diff case below + * Note cunning cleverness here: case Stuff_Diff compares + * the current character with the previous two to see if it + * has a run of three the same. Won't this be an error if + * there aren't two previous characters stored to compare with? + * No. Because we know the current character is *not* the same + * as the previous one, the first test below will necessarily + * fail and the send half of the "if" won't be executed. + */ + + /* Stuff_Diff: We have at least two *different* bytes encoded */ + case Stuff_Diff: + /* If this is a zero, must encode a Stuff_DiffZero, and begin a new block */ + if (*src == 0) { + StuffData_FinishBlock(Stuff_DiffZero + + count); + } + /* else, if we have three in a row, it is worth starting a Stuff_Same block */ + else if ((*src ^ Stuff_Magic) == dst[-1] + && dst[-1] == dst[-2]) { + /* Back off the last two characters we encoded */ + code += count - 2; + /* Note: "Stuff_Diff + 0" is an illegal code */ + if (code == Stuff_Diff + 0) { + code = Stuff_Same + 0; + } + StuffData_FinishBlock(code); + code_ptr = dst - 2; + /* dst[-1] already holds the correct value */ + count = 2; /* 2 means three bytes encoded */ + code = Stuff_Same; + } + /* else, another different byte, so add it to the block */ + else { + *dst++ = *src ^ Stuff_Magic; + count++; + } + src++; /* Consume the byte */ + break; + } + if (count == Stuff_MaxCount) { + StuffData_FinishBlock(code + count); + } + } + if (code == Stuff_NoCode) { + *code_ptr_ptr = NULL; + } else { + *code_ptr_ptr = code_ptr; + StuffData_FinishBlock(code + count); + } + return (dst); +} + +/* + * UnStuffData decodes the data at "src", up to (but not including) "end". + * It writes the decoded data into the buffer pointed to by "dst", up to a + * maximum of "dst_length", and returns the new value of "src" so that a + * follow-on call can read more data, continuing from where the first left off. + * + * There are three types of results: + * 1. The source data runs out before extracting "dst_length" bytes: + * UnStuffData returns NULL to indicate failure. + * 2. The source data produces exactly "dst_length" bytes: + * UnStuffData returns new_src = end to indicate that all bytes were consumed. + * 3. "dst_length" bytes are extracted, with more remaining. + * UnStuffData returns new_src < end to indicate that there are more bytes + * to be read. + * + * Note: The decoding may be destructive, in that it may alter the source + * data in the process of decoding it (this is necessary to allow a follow-on + * call to resume correctly). + */ + +static __u8 *UnStuffData(__u8 * src, __u8 * end, __u8 * dst, + __u32 dst_length) +{ + __u8 *dst_end = dst + dst_length; + /* Sanity check */ + if (!src || !end || !dst || !dst_length) + return (NULL); + while (src < end && dst < dst_end) { + int count = (*src ^ Stuff_Magic) & Stuff_CountMask; + switch ((*src ^ Stuff_Magic) & Stuff_CodeMask) { + case Stuff_Diff: + if (src + 1 + count >= end) + return (NULL); + do { + *dst++ = *++src ^ Stuff_Magic; + } + while (--count >= 0 && dst < dst_end); + if (count < 0) + src += 1; + else { + if (count == 0) + *src = Stuff_Same ^ Stuff_Magic; + else + *src = + (Stuff_Diff + + count) ^ Stuff_Magic; + } + break; + case Stuff_DiffZero: + if (src + 1 + count >= end) + return (NULL); + do { + *dst++ = *++src ^ Stuff_Magic; + } + while (--count >= 0 && dst < dst_end); + if (count < 0) + *src = Stuff_Zero ^ Stuff_Magic; + else + *src = + (Stuff_DiffZero + count) ^ Stuff_Magic; + break; + case Stuff_Same: + if (src + 1 >= end) + return (NULL); + do { + *dst++ = src[1] ^ Stuff_Magic; + } + while (--count >= 0 && dst < dst_end); + if (count < 0) + src += 2; + else + *src = (Stuff_Same + count) ^ Stuff_Magic; + break; + case Stuff_Zero: + do { + *dst++ = 0; + } + while (--count >= 0 && dst < dst_end); + if (count < 0) + src += 1; + else + *src = (Stuff_Zero + count) ^ Stuff_Magic; + break; + } + } + if (dst < dst_end) + return (NULL); + else + return (src); +} + + +/************************************************************************/ +/* General routines for STRIP */ + +/* + * set_baud sets the baud rate to the rate defined by baudcode + */ +static void set_baud(struct tty_struct *tty, speed_t baudrate) +{ + struct ktermios old_termios; + + mutex_lock(&tty->termios_mutex); + old_termios =*(tty->termios); + tty_encode_baud_rate(tty, baudrate, baudrate); + tty->ops->set_termios(tty, &old_termios); + mutex_unlock(&tty->termios_mutex); +} + +/* + * Convert a string to a Metricom Address. + */ + +#define IS_RADIO_ADDRESS(p) ( \ + isdigit((p)[0]) && isdigit((p)[1]) && isdigit((p)[2]) && isdigit((p)[3]) && \ + (p)[4] == '-' && \ + isdigit((p)[5]) && isdigit((p)[6]) && isdigit((p)[7]) && isdigit((p)[8]) ) + +static int string_to_radio_address(MetricomAddress * addr, __u8 * p) +{ + if (!IS_RADIO_ADDRESS(p)) + return (1); + addr->c[0] = 0; + addr->c[1] = 0; + addr->c[2] = READHEX(p[0]) << 4 | READHEX(p[1]); + addr->c[3] = READHEX(p[2]) << 4 | READHEX(p[3]); + addr->c[4] = READHEX(p[5]) << 4 | READHEX(p[6]); + addr->c[5] = READHEX(p[7]) << 4 | READHEX(p[8]); + return (0); +} + +/* + * Convert a Metricom Address to a string. + */ + +static __u8 *radio_address_to_string(const MetricomAddress * addr, + MetricomAddressString * p) +{ + sprintf(p->c, "%02X%02X-%02X%02X", addr->c[2], addr->c[3], + addr->c[4], addr->c[5]); + return (p->c); +} + +/* + * Note: Must make sure sx_size is big enough to receive a stuffed + * MAX_RECV_MTU packet. Additionally, we also want to ensure that it's + * big enough to receive a large radio neighbour list (currently 4K). + */ + +static int allocate_buffers(struct strip *strip_info, int mtu) +{ + struct net_device *dev = strip_info->dev; + int sx_size = max_t(int, STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096); + int tx_size = STRIP_ENCAP_SIZE(mtu) + MaxCommandStringLength; + __u8 *r = kmalloc(MAX_RECV_MTU, GFP_ATOMIC); + __u8 *s = kmalloc(sx_size, GFP_ATOMIC); + __u8 *t = kmalloc(tx_size, GFP_ATOMIC); + if (r && s && t) { + strip_info->rx_buff = r; + strip_info->sx_buff = s; + strip_info->tx_buff = t; + strip_info->sx_size = sx_size; + strip_info->tx_size = tx_size; + strip_info->mtu = dev->mtu = mtu; + return (1); + } + kfree(r); + kfree(s); + kfree(t); + return (0); +} + +/* + * MTU has been changed by the IP layer. + * We could be in + * an upcall from the tty driver, or in an ip packet queue. + */ +static int strip_change_mtu(struct net_device *dev, int new_mtu) +{ + struct strip *strip_info = netdev_priv(dev); + int old_mtu = strip_info->mtu; + unsigned char *orbuff = strip_info->rx_buff; + unsigned char *osbuff = strip_info->sx_buff; + unsigned char *otbuff = strip_info->tx_buff; + + if (new_mtu > MAX_SEND_MTU) { + printk(KERN_ERR + "%s: MTU exceeds maximum allowable (%d), MTU change cancelled.\n", + strip_info->dev->name, MAX_SEND_MTU); + return -EINVAL; + } + + spin_lock_bh(&strip_lock); + if (!allocate_buffers(strip_info, new_mtu)) { + printk(KERN_ERR "%s: unable to grow strip buffers, MTU change cancelled.\n", + strip_info->dev->name); + spin_unlock_bh(&strip_lock); + return -ENOMEM; + } + + if (strip_info->sx_count) { + if (strip_info->sx_count <= strip_info->sx_size) + memcpy(strip_info->sx_buff, osbuff, + strip_info->sx_count); + else { + strip_info->discard = strip_info->sx_count; + strip_info->rx_over_errors++; + } + } + + if (strip_info->tx_left) { + if (strip_info->tx_left <= strip_info->tx_size) + memcpy(strip_info->tx_buff, strip_info->tx_head, + strip_info->tx_left); + else { + strip_info->tx_left = 0; + strip_info->tx_dropped++; + } + } + strip_info->tx_head = strip_info->tx_buff; + spin_unlock_bh(&strip_lock); + + printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n", + strip_info->dev->name, old_mtu, strip_info->mtu); + + kfree(orbuff); + kfree(osbuff); + kfree(otbuff); + return 0; +} + +static void strip_unlock(struct strip *strip_info) +{ + /* + * Set the timer to go off in one second. + */ + strip_info->idle_timer.expires = jiffies + 1 * HZ; + add_timer(&strip_info->idle_timer); + netif_wake_queue(strip_info->dev); +} + + + +/* + * If the time is in the near future, time_delta prints the number of + * seconds to go into the buffer and returns the address of the buffer. + * If the time is not in the near future, it returns the address of the + * string "Not scheduled" The buffer must be long enough to contain the + * ascii representation of the number plus 9 charactes for the " seconds" + * and the null character. + */ +#ifdef CONFIG_PROC_FS +static char *time_delta(char buffer[], long time) +{ + time -= jiffies; + if (time > LongTime / 2) + return ("Not scheduled"); + if (time < 0) + time = 0; /* Don't print negative times */ + sprintf(buffer, "%ld seconds", time / HZ); + return (buffer); +} + +/* get Nth element of the linked list */ +static struct strip *strip_get_idx(loff_t pos) +{ + struct strip *str; + int i = 0; + + list_for_each_entry_rcu(str, &strip_list, list) { + if (pos == i) + return str; + ++i; + } + return NULL; +} + +static void *strip_seq_start(struct seq_file *seq, loff_t *pos) +{ + rcu_read_lock(); + return *pos ? strip_get_idx(*pos - 1) : SEQ_START_TOKEN; +} + +static void *strip_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct list_head *l; + struct strip *s; + + ++*pos; + if (v == SEQ_START_TOKEN) + return strip_get_idx(1); + + s = v; + l = &s->list; + list_for_each_continue_rcu(l, &strip_list) { + return list_entry(l, struct strip, list); + } + return NULL; +} + +static void strip_seq_stop(struct seq_file *seq, void *v) +{ + rcu_read_unlock(); +} + +static void strip_seq_neighbours(struct seq_file *seq, + const MetricomNodeTable * table, + const char *title) +{ + /* We wrap this in a do/while loop, so if the table changes */ + /* while we're reading it, we just go around and try again. */ + struct timeval t; + + do { + int i; + t = table->timestamp; + if (table->num_nodes) + seq_printf(seq, "\n %s\n", title); + for (i = 0; i < table->num_nodes; i++) { + MetricomNode node; + + spin_lock_bh(&strip_lock); + node = table->node[i]; + spin_unlock_bh(&strip_lock); + seq_printf(seq, " %s\n", node.c); + } + } while (table->timestamp.tv_sec != t.tv_sec + || table->timestamp.tv_usec != t.tv_usec); +} + +/* + * This function prints radio status information via the seq_file + * interface. The interface takes care of buffer size and over + * run issues. + * + * The buffer in seq_file is PAGESIZE (4K) + * so this routine should never print more or it will get truncated. + * With the maximum of 32 portables and 32 poletops + * reported, the routine outputs 3107 bytes into the buffer. + */ +static void strip_seq_status_info(struct seq_file *seq, + const struct strip *strip_info) +{ + char temp[32]; + MetricomAddressString addr_string; + + /* First, we must copy all of our data to a safe place, */ + /* in case a serial interrupt comes in and changes it. */ + int tx_left = strip_info->tx_left; + unsigned long rx_average_pps = strip_info->rx_average_pps; + unsigned long tx_average_pps = strip_info->tx_average_pps; + unsigned long sx_average_pps = strip_info->sx_average_pps; + int working = strip_info->working; + int firmware_level = strip_info->firmware_level; + long watchdog_doprobe = strip_info->watchdog_doprobe; + long watchdog_doreset = strip_info->watchdog_doreset; + long gratuitous_arp = strip_info->gratuitous_arp; + long arp_interval = strip_info->arp_interval; + FirmwareVersion firmware_version = strip_info->firmware_version; + SerialNumber serial_number = strip_info->serial_number; + BatteryVoltage battery_voltage = strip_info->battery_voltage; + char *if_name = strip_info->dev->name; + MetricomAddress true_dev_addr = strip_info->true_dev_addr; + MetricomAddress dev_dev_addr = + *(MetricomAddress *) strip_info->dev->dev_addr; + int manual_dev_addr = strip_info->manual_dev_addr; +#ifdef EXT_COUNTERS + unsigned long rx_bytes = strip_info->rx_bytes; + unsigned long tx_bytes = strip_info->tx_bytes; + unsigned long rx_rbytes = strip_info->rx_rbytes; + unsigned long tx_rbytes = strip_info->tx_rbytes; + unsigned long rx_sbytes = strip_info->rx_sbytes; + unsigned long tx_sbytes = strip_info->tx_sbytes; + unsigned long rx_ebytes = strip_info->rx_ebytes; + unsigned long tx_ebytes = strip_info->tx_ebytes; +#endif + + seq_printf(seq, "\nInterface name\t\t%s\n", if_name); + seq_printf(seq, " Radio working:\t\t%s\n", working ? "Yes" : "No"); + radio_address_to_string(&true_dev_addr, &addr_string); + seq_printf(seq, " Radio address:\t\t%s\n", addr_string.c); + if (manual_dev_addr) { + radio_address_to_string(&dev_dev_addr, &addr_string); + seq_printf(seq, " Device address:\t%s\n", addr_string.c); + } + seq_printf(seq, " Firmware version:\t%s", !working ? "Unknown" : + !firmware_level ? "Should be upgraded" : + firmware_version.c); + if (firmware_level >= ChecksummedMessages) + seq_printf(seq, " (Checksums Enabled)"); + seq_printf(seq, "\n"); + seq_printf(seq, " Serial number:\t\t%s\n", serial_number.c); + seq_printf(seq, " Battery voltage:\t%s\n", battery_voltage.c); + seq_printf(seq, " Transmit queue (bytes):%d\n", tx_left); + seq_printf(seq, " Receive packet rate: %ld packets per second\n", + rx_average_pps / 8); + seq_printf(seq, " Transmit packet rate: %ld packets per second\n", + tx_average_pps / 8); + seq_printf(seq, " Sent packet rate: %ld packets per second\n", + sx_average_pps / 8); + seq_printf(seq, " Next watchdog probe:\t%s\n", + time_delta(temp, watchdog_doprobe)); + seq_printf(seq, " Next watchdog reset:\t%s\n", + time_delta(temp, watchdog_doreset)); + seq_printf(seq, " Next gratuitous ARP:\t"); + + if (!memcmp + (strip_info->dev->dev_addr, zero_address.c, + sizeof(zero_address))) + seq_printf(seq, "Disabled\n"); + else { + seq_printf(seq, "%s\n", time_delta(temp, gratuitous_arp)); + seq_printf(seq, " Next ARP interval:\t%ld seconds\n", + JIFFIE_TO_SEC(arp_interval)); + } + + if (working) { +#ifdef EXT_COUNTERS + seq_printf(seq, "\n"); + seq_printf(seq, + " Total bytes: \trx:\t%lu\ttx:\t%lu\n", + rx_bytes, tx_bytes); + seq_printf(seq, + " thru radio: \trx:\t%lu\ttx:\t%lu\n", + rx_rbytes, tx_rbytes); + seq_printf(seq, + " thru serial port: \trx:\t%lu\ttx:\t%lu\n", + rx_sbytes, tx_sbytes); + seq_printf(seq, + " Total stat/err bytes:\trx:\t%lu\ttx:\t%lu\n", + rx_ebytes, tx_ebytes); +#endif + strip_seq_neighbours(seq, &strip_info->poletops, + "Poletops:"); + strip_seq_neighbours(seq, &strip_info->portables, + "Portables:"); + } +} + +/* + * This function is exports status information from the STRIP driver through + * the /proc file system. + */ +static int strip_seq_show(struct seq_file *seq, void *v) +{ + if (v == SEQ_START_TOKEN) + seq_printf(seq, "strip_version: %s\n", StripVersion); + else + strip_seq_status_info(seq, (const struct strip *)v); + return 0; +} + + +static struct seq_operations strip_seq_ops = { + .start = strip_seq_start, + .next = strip_seq_next, + .stop = strip_seq_stop, + .show = strip_seq_show, +}; + +static int strip_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &strip_seq_ops); +} + +static const struct file_operations strip_seq_fops = { + .owner = THIS_MODULE, + .open = strip_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; +#endif + + + +/************************************************************************/ +/* Sending routines */ + +static void ResetRadio(struct strip *strip_info) +{ + struct tty_struct *tty = strip_info->tty; + static const char init[] = "ate0q1dt**starmode\r**"; + StringDescriptor s = { init, sizeof(init) - 1 }; + + /* + * If the radio isn't working anymore, + * we should clear the old status information. + */ + if (strip_info->working) { + printk(KERN_INFO "%s: No response: Resetting radio.\n", + strip_info->dev->name); + strip_info->firmware_version.c[0] = '\0'; + strip_info->serial_number.c[0] = '\0'; + strip_info->battery_voltage.c[0] = '\0'; + strip_info->portables.num_nodes = 0; + do_gettimeofday(&strip_info->portables.timestamp); + strip_info->poletops.num_nodes = 0; + do_gettimeofday(&strip_info->poletops.timestamp); + } + + strip_info->pps_timer = jiffies; + strip_info->rx_pps_count = 0; + strip_info->tx_pps_count = 0; + strip_info->sx_pps_count = 0; + strip_info->rx_average_pps = 0; + strip_info->tx_average_pps = 0; + strip_info->sx_average_pps = 0; + + /* Mark radio address as unknown */ + *(MetricomAddress *) & strip_info->true_dev_addr = zero_address; + if (!strip_info->manual_dev_addr) + *(MetricomAddress *) strip_info->dev->dev_addr = + zero_address; + strip_info->working = FALSE; + strip_info->firmware_level = NoStructure; + strip_info->next_command = CompatibilityCommand; + strip_info->watchdog_doprobe = jiffies + 10 * HZ; + strip_info->watchdog_doreset = jiffies + 1 * HZ; + + /* If the user has selected a baud rate above 38.4 see what magic we have to do */ + if (strip_info->user_baud > 38400) { + /* + * Subtle stuff: Pay attention :-) + * If the serial port is currently at the user's selected (>38.4) rate, + * then we temporarily switch to 19.2 and issue the ATS304 command + * to tell the radio to switch to the user's selected rate. + * If the serial port is not currently at that rate, that means we just + * issued the ATS304 command last time through, so this time we restore + * the user's selected rate and issue the normal starmode reset string. + */ + if (strip_info->user_baud == tty_get_baud_rate(tty)) { + static const char b0[] = "ate0q1s304=57600\r"; + static const char b1[] = "ate0q1s304=115200\r"; + static const StringDescriptor baudstring[2] = + { {b0, sizeof(b0) - 1} + , {b1, sizeof(b1) - 1} + }; + set_baud(tty, 19200); + if (strip_info->user_baud == 57600) + s = baudstring[0]; + else if (strip_info->user_baud == 115200) + s = baudstring[1]; + else + s = baudstring[1]; /* For now */ + } else + set_baud(tty, strip_info->user_baud); + } + + tty->ops->write(tty, s.string, s.length); +#ifdef EXT_COUNTERS + strip_info->tx_ebytes += s.length; +#endif +} + +/* + * Called by the driver when there's room for more data. If we have + * more packets to send, we send them here. + */ + +static void strip_write_some_more(struct tty_struct *tty) +{ + struct strip *strip_info = (struct strip *) tty->disc_data; + + /* First make sure we're connected. */ + if (!strip_info || strip_info->magic != STRIP_MAGIC || + !netif_running(strip_info->dev)) + return; + + if (strip_info->tx_left > 0) { + int num_written = + tty->ops->write(tty, strip_info->tx_head, + strip_info->tx_left); + strip_info->tx_left -= num_written; + strip_info->tx_head += num_written; +#ifdef EXT_COUNTERS + strip_info->tx_sbytes += num_written; +#endif + } else { /* Else start transmission of another packet */ + + tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + strip_unlock(strip_info); + } +} + +static __u8 *add_checksum(__u8 * buffer, __u8 * end) +{ + __u16 sum = 0; + __u8 *p = buffer; + while (p < end) + sum += *p++; + end[3] = hextable[sum & 0xF]; + sum >>= 4; + end[2] = hextable[sum & 0xF]; + sum >>= 4; + end[1] = hextable[sum & 0xF]; + sum >>= 4; + end[0] = hextable[sum & 0xF]; + return (end + 4); +} + +static unsigned char *strip_make_packet(unsigned char *buffer, + struct strip *strip_info, + struct sk_buff *skb) +{ + __u8 *ptr = buffer; + __u8 *stuffstate = NULL; + STRIP_Header *header = (STRIP_Header *) skb->data; + MetricomAddress haddr = header->dst_addr; + int len = skb->len - sizeof(STRIP_Header); + MetricomKey key; + + /*HexDump("strip_make_packet", strip_info, skb->data, skb->data + skb->len); */ + + if (header->protocol == htons(ETH_P_IP)) + key = SIP0Key; + else if (header->protocol == htons(ETH_P_ARP)) + key = ARP0Key; + else { + printk(KERN_ERR + "%s: strip_make_packet: Unknown packet type 0x%04X\n", + strip_info->dev->name, ntohs(header->protocol)); + return (NULL); + } + + if (len > strip_info->mtu) { + printk(KERN_ERR + "%s: Dropping oversized transmit packet: %d bytes\n", + strip_info->dev->name, len); + return (NULL); + } + + /* + * If we're sending to ourselves, discard the packet. + * (Metricom radios choke if they try to send a packet to their own address.) + */ + if (!memcmp(haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) { + printk(KERN_ERR "%s: Dropping packet addressed to self\n", + strip_info->dev->name); + return (NULL); + } + + /* + * If this is a broadcast packet, send it to our designated Metricom + * 'broadcast hub' radio (First byte of address being 0xFF means broadcast) + */ + if (haddr.c[0] == 0xFF) { + __be32 brd = 0; + struct in_device *in_dev; + + rcu_read_lock(); + in_dev = __in_dev_get_rcu(strip_info->dev); + if (in_dev == NULL) { + rcu_read_unlock(); + return NULL; + } + if (in_dev->ifa_list) + brd = in_dev->ifa_list->ifa_broadcast; + rcu_read_unlock(); + + /* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */ + if (!arp_query(haddr.c, brd, strip_info->dev)) { + printk(KERN_ERR + "%s: Unable to send packet (no broadcast hub configured)\n", + strip_info->dev->name); + return (NULL); + } + /* + * If we are the broadcast hub, don't bother sending to ourselves. + * (Metricom radios choke if they try to send a packet to their own address.) + */ + if (!memcmp + (haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) + return (NULL); + } + + *ptr++ = 0x0D; + *ptr++ = '*'; + *ptr++ = hextable[haddr.c[2] >> 4]; + *ptr++ = hextable[haddr.c[2] & 0xF]; + *ptr++ = hextable[haddr.c[3] >> 4]; + *ptr++ = hextable[haddr.c[3] & 0xF]; + *ptr++ = '-'; + *ptr++ = hextable[haddr.c[4] >> 4]; + *ptr++ = hextable[haddr.c[4] & 0xF]; + *ptr++ = hextable[haddr.c[5] >> 4]; + *ptr++ = hextable[haddr.c[5] & 0xF]; + *ptr++ = '*'; + *ptr++ = key.c[0]; + *ptr++ = key.c[1]; + *ptr++ = key.c[2]; + *ptr++ = key.c[3]; + + ptr = + StuffData(skb->data + sizeof(STRIP_Header), len, ptr, + &stuffstate); + + if (strip_info->firmware_level >= ChecksummedMessages) + ptr = add_checksum(buffer + 1, ptr); + + *ptr++ = 0x0D; + return (ptr); +} + +static void strip_send(struct strip *strip_info, struct sk_buff *skb) +{ + MetricomAddress haddr; + unsigned char *ptr = strip_info->tx_buff; + int doreset = (long) jiffies - strip_info->watchdog_doreset >= 0; + int doprobe = (long) jiffies - strip_info->watchdog_doprobe >= 0 + && !doreset; + __be32 addr, brd; + + /* + * 1. If we have a packet, encapsulate it and put it in the buffer + */ + if (skb) { + char *newptr = strip_make_packet(ptr, strip_info, skb); + strip_info->tx_pps_count++; + if (!newptr) + strip_info->tx_dropped++; + else { + ptr = newptr; + strip_info->sx_pps_count++; + strip_info->tx_packets++; /* Count another successful packet */ +#ifdef EXT_COUNTERS + strip_info->tx_bytes += skb->len; + strip_info->tx_rbytes += ptr - strip_info->tx_buff; +#endif + /*DumpData("Sending:", strip_info, strip_info->tx_buff, ptr); */ + /*HexDump("Sending", strip_info, strip_info->tx_buff, ptr); */ + } + } + + /* + * 2. If it is time for another tickle, tack it on, after the packet + */ + if (doprobe) { + StringDescriptor ts = CommandString[strip_info->next_command]; +#if TICKLE_TIMERS + { + struct timeval tv; + do_gettimeofday(&tv); + printk(KERN_INFO "**** Sending tickle string %d at %02d.%06d\n", + strip_info->next_command, tv.tv_sec % 100, + tv.tv_usec); + } +#endif + if (ptr == strip_info->tx_buff) + *ptr++ = 0x0D; + + *ptr++ = '*'; /* First send "**" to provoke an error message */ + *ptr++ = '*'; + + /* Then add the command */ + memcpy(ptr, ts.string, ts.length); + + /* Add a checksum ? */ + if (strip_info->firmware_level < ChecksummedMessages) + ptr += ts.length; + else + ptr = add_checksum(ptr, ptr + ts.length); + + *ptr++ = 0x0D; /* Terminate the command with a */ + + /* Cycle to next periodic command? */ + if (strip_info->firmware_level >= StructuredMessages) + if (++strip_info->next_command >= + ARRAY_SIZE(CommandString)) + strip_info->next_command = 0; +#ifdef EXT_COUNTERS + strip_info->tx_ebytes += ts.length; +#endif + strip_info->watchdog_doprobe = jiffies + 10 * HZ; + strip_info->watchdog_doreset = jiffies + 1 * HZ; + /*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev->name); */ + } + + /* + * 3. Set up the strip_info ready to send the data (if any). + */ + strip_info->tx_head = strip_info->tx_buff; + strip_info->tx_left = ptr - strip_info->tx_buff; + strip_info->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); + + /* + * 4. Debugging check to make sure we're not overflowing the buffer. + */ + if (strip_info->tx_size - strip_info->tx_left < 20) + printk(KERN_ERR "%s: Sending%5d bytes;%5d bytes free.\n", + strip_info->dev->name, strip_info->tx_left, + strip_info->tx_size - strip_info->tx_left); + + /* + * 5. If watchdog has expired, reset the radio. Note: if there's data waiting in + * the buffer, strip_write_some_more will send it after the reset has finished + */ + if (doreset) { + ResetRadio(strip_info); + return; + } + + if (1) { + struct in_device *in_dev; + + brd = addr = 0; + rcu_read_lock(); + in_dev = __in_dev_get_rcu(strip_info->dev); + if (in_dev) { + if (in_dev->ifa_list) { + brd = in_dev->ifa_list->ifa_broadcast; + addr = in_dev->ifa_list->ifa_local; + } + } + rcu_read_unlock(); + } + + + /* + * 6. If it is time for a periodic ARP, queue one up to be sent. + * We only do this if: + * 1. The radio is working + * 2. It's time to send another periodic ARP + * 3. We really know what our address is (and it is not manually set to zero) + * 4. We have a designated broadcast address configured + * If we queue up an ARP packet when we don't have a designated broadcast + * address configured, then the packet will just have to be discarded in + * strip_make_packet. This is not fatal, but it causes misleading information + * to be displayed in tcpdump. tcpdump will report that periodic APRs are + * being sent, when in fact they are not, because they are all being dropped + * in the strip_make_packet routine. + */ + if (strip_info->working + && (long) jiffies - strip_info->gratuitous_arp >= 0 + && memcmp(strip_info->dev->dev_addr, zero_address.c, + sizeof(zero_address)) + && arp_query(haddr.c, brd, strip_info->dev)) { + /*printk(KERN_INFO "%s: Sending gratuitous ARP with interval %ld\n", + strip_info->dev->name, strip_info->arp_interval / HZ); */ + strip_info->gratuitous_arp = + jiffies + strip_info->arp_interval; + strip_info->arp_interval *= 2; + if (strip_info->arp_interval > MaxARPInterval) + strip_info->arp_interval = MaxARPInterval; + if (addr) + arp_send(ARPOP_REPLY, ETH_P_ARP, addr, /* Target address of ARP packet is our address */ + strip_info->dev, /* Device to send packet on */ + addr, /* Source IP address this ARP packet comes from */ + NULL, /* Destination HW address is NULL (broadcast it) */ + strip_info->dev->dev_addr, /* Source HW address is our HW address */ + strip_info->dev->dev_addr); /* Target HW address is our HW address (redundant) */ + } + + /* + * 7. All ready. Start the transmission + */ + strip_write_some_more(strip_info->tty); +} + +/* Encapsulate a datagram and kick it into a TTY queue. */ +static int strip_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct strip *strip_info = netdev_priv(dev); + + if (!netif_running(dev)) { + printk(KERN_ERR "%s: xmit call when iface is down\n", + dev->name); + return (1); + } + + netif_stop_queue(dev); + + del_timer(&strip_info->idle_timer); + + + if (time_after(jiffies, strip_info->pps_timer + HZ)) { + unsigned long t = jiffies - strip_info->pps_timer; + unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t; + unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t; + unsigned long sx_pps_count = (strip_info->sx_pps_count * HZ * 8 + t / 2) / t; + + strip_info->pps_timer = jiffies; + strip_info->rx_pps_count = 0; + strip_info->tx_pps_count = 0; + strip_info->sx_pps_count = 0; + + strip_info->rx_average_pps = (strip_info->rx_average_pps + rx_pps_count + 1) / 2; + strip_info->tx_average_pps = (strip_info->tx_average_pps + tx_pps_count + 1) / 2; + strip_info->sx_average_pps = (strip_info->sx_average_pps + sx_pps_count + 1) / 2; + + if (rx_pps_count / 8 >= 10) + printk(KERN_INFO "%s: WARNING: Receiving %ld packets per second.\n", + strip_info->dev->name, rx_pps_count / 8); + if (tx_pps_count / 8 >= 10) + printk(KERN_INFO "%s: WARNING: Tx %ld packets per second.\n", + strip_info->dev->name, tx_pps_count / 8); + if (sx_pps_count / 8 >= 10) + printk(KERN_INFO "%s: WARNING: Sending %ld packets per second.\n", + strip_info->dev->name, sx_pps_count / 8); + } + + spin_lock_bh(&strip_lock); + + strip_send(strip_info, skb); + + spin_unlock_bh(&strip_lock); + + if (skb) + dev_kfree_skb(skb); + return 0; +} + +/* + * IdleTask periodically calls strip_xmit, so even when we have no IP packets + * to send for an extended period of time, the watchdog processing still gets + * done to ensure that the radio stays in Starmode + */ + +static void strip_IdleTask(unsigned long parameter) +{ + strip_xmit(NULL, (struct net_device *) parameter); +} + +/* + * Create the MAC header for an arbitrary protocol layer + * + * saddr!=NULL means use this specific address (n/a for Metricom) + * saddr==NULL means use default device source address + * daddr!=NULL means use this destination address + * daddr==NULL means leave destination address alone + * (e.g. unresolved arp -- kernel will call + * rebuild_header later to fill in the address) + */ + +static int strip_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned len) +{ + struct strip *strip_info = netdev_priv(dev); + STRIP_Header *header = (STRIP_Header *) skb_push(skb, sizeof(STRIP_Header)); + + /*printk(KERN_INFO "%s: strip_header 0x%04X %s\n", dev->name, type, + type == ETH_P_IP ? "IP" : type == ETH_P_ARP ? "ARP" : ""); */ + + header->src_addr = strip_info->true_dev_addr; + header->protocol = htons(type); + + /*HexDump("strip_header", netdev_priv(dev), skb->data, skb->data + skb->len); */ + + if (!daddr) + return (-dev->hard_header_len); + + header->dst_addr = *(MetricomAddress *) daddr; + return (dev->hard_header_len); +} + +/* + * Rebuild the MAC header. This is called after an ARP + * (or in future other address resolution) has completed on this + * sk_buff. We now let ARP fill in the other fields. + * I think this should return zero if packet is ready to send, + * or non-zero if it needs more time to do an address lookup + */ + +static int strip_rebuild_header(struct sk_buff *skb) +{ +#ifdef CONFIG_INET + STRIP_Header *header = (STRIP_Header *) skb->data; + + /* Arp find returns zero if if knows the address, */ + /* or if it doesn't know the address it sends an ARP packet and returns non-zero */ + return arp_find(header->dst_addr.c, skb) ? 1 : 0; +#else + return 0; +#endif +} + + +/************************************************************************/ +/* Receiving routines */ + +/* + * This function parses the response to the ATS300? command, + * extracting the radio version and serial number. + */ +static void get_radio_version(struct strip *strip_info, __u8 * ptr, __u8 * end) +{ + __u8 *p, *value_begin, *value_end; + int len; + + /* Determine the beginning of the second line of the payload */ + p = ptr; + while (p < end && *p != 10) + p++; + if (p >= end) + return; + p++; + value_begin = p; + + /* Determine the end of line */ + while (p < end && *p != 10) + p++; + if (p >= end) + return; + value_end = p; + p++; + + len = value_end - value_begin; + len = min_t(int, len, sizeof(FirmwareVersion) - 1); + if (strip_info->firmware_version.c[0] == 0) + printk(KERN_INFO "%s: Radio Firmware: %.*s\n", + strip_info->dev->name, len, value_begin); + sprintf(strip_info->firmware_version.c, "%.*s", len, value_begin); + + /* Look for the first colon */ + while (p < end && *p != ':') + p++; + if (p >= end) + return; + /* Skip over the space */ + p += 2; + len = sizeof(SerialNumber) - 1; + if (p + len <= end) { + sprintf(strip_info->serial_number.c, "%.*s", len, p); + } else { + printk(KERN_DEBUG + "STRIP: radio serial number shorter (%zd) than expected (%d)\n", + end - p, len); + } +} + +/* + * This function parses the response to the ATS325? command, + * extracting the radio battery voltage. + */ +static void get_radio_voltage(struct strip *strip_info, __u8 * ptr, __u8 * end) +{ + int len; + + len = sizeof(BatteryVoltage) - 1; + if (ptr + len <= end) { + sprintf(strip_info->battery_voltage.c, "%.*s", len, ptr); + } else { + printk(KERN_DEBUG + "STRIP: radio voltage string shorter (%zd) than expected (%d)\n", + end - ptr, len); + } +} + +/* + * This function parses the responses to the AT~LA and ATS311 commands, + * which list the radio's neighbours. + */ +static void get_radio_neighbours(MetricomNodeTable * table, __u8 * ptr, __u8 * end) +{ + table->num_nodes = 0; + while (ptr < end && table->num_nodes < NODE_TABLE_SIZE) { + MetricomNode *node = &table->node[table->num_nodes++]; + char *dst = node->c, *limit = dst + sizeof(*node) - 1; + while (ptr < end && *ptr <= 32) + ptr++; + while (ptr < end && dst < limit && *ptr != 10) + *dst++ = *ptr++; + *dst++ = 0; + while (ptr < end && ptr[-1] != 10) + ptr++; + } + do_gettimeofday(&table->timestamp); +} + +static int get_radio_address(struct strip *strip_info, __u8 * p) +{ + MetricomAddress addr; + + if (string_to_radio_address(&addr, p)) + return (1); + + /* See if our radio address has changed */ + if (memcmp(strip_info->true_dev_addr.c, addr.c, sizeof(addr))) { + MetricomAddressString addr_string; + radio_address_to_string(&addr, &addr_string); + printk(KERN_INFO "%s: Radio address = %s\n", + strip_info->dev->name, addr_string.c); + strip_info->true_dev_addr = addr; + if (!strip_info->manual_dev_addr) + *(MetricomAddress *) strip_info->dev->dev_addr = + addr; + /* Give the radio a few seconds to get its head straight, then send an arp */ + strip_info->gratuitous_arp = jiffies + 15 * HZ; + strip_info->arp_interval = 1 * HZ; + } + return (0); +} + +static int verify_checksum(struct strip *strip_info) +{ + __u8 *p = strip_info->sx_buff; + __u8 *end = strip_info->sx_buff + strip_info->sx_count - 4; + u_short sum = + (READHEX16(end[0]) << 12) | (READHEX16(end[1]) << 8) | + (READHEX16(end[2]) << 4) | (READHEX16(end[3])); + while (p < end) + sum -= *p++; + if (sum == 0 && strip_info->firmware_level == StructuredMessages) { + strip_info->firmware_level = ChecksummedMessages; + printk(KERN_INFO "%s: Radio provides message checksums\n", + strip_info->dev->name); + } + return (sum == 0); +} + +static void RecvErr(char *msg, struct strip *strip_info) +{ + __u8 *ptr = strip_info->sx_buff; + __u8 *end = strip_info->sx_buff + strip_info->sx_count; + DumpData(msg, strip_info, ptr, end); + strip_info->rx_errors++; +} + +static void RecvErr_Message(struct strip *strip_info, __u8 * sendername, + const __u8 * msg, u_long len) +{ + if (has_prefix(msg, len, "001")) { /* Not in StarMode! */ + RecvErr("Error Msg:", strip_info); + printk(KERN_INFO "%s: Radio %s is not in StarMode\n", + strip_info->dev->name, sendername); + } + + else if (has_prefix(msg, len, "002")) { /* Remap handle */ + /* We ignore "Remap handle" messages for now */ + } + + else if (has_prefix(msg, len, "003")) { /* Can't resolve name */ + RecvErr("Error Msg:", strip_info); + printk(KERN_INFO "%s: Destination radio name is unknown\n", + strip_info->dev->name); + } + + else if (has_prefix(msg, len, "004")) { /* Name too small or missing */ + strip_info->watchdog_doreset = jiffies + LongTime; +#if TICKLE_TIMERS + { + struct timeval tv; + do_gettimeofday(&tv); + printk(KERN_INFO + "**** Got ERR_004 response at %02d.%06d\n", + tv.tv_sec % 100, tv.tv_usec); + } +#endif + if (!strip_info->working) { + strip_info->working = TRUE; + printk(KERN_INFO "%s: Radio now in starmode\n", + strip_info->dev->name); + /* + * If the radio has just entered a working state, we should do our first + * probe ASAP, so that we find out our radio address etc. without delay. + */ + strip_info->watchdog_doprobe = jiffies; + } + if (strip_info->firmware_level == NoStructure && sendername) { + strip_info->firmware_level = StructuredMessages; + strip_info->next_command = 0; /* Try to enable checksums ASAP */ + printk(KERN_INFO + "%s: Radio provides structured messages\n", + strip_info->dev->name); + } + if (strip_info->firmware_level >= StructuredMessages) { + /* + * If this message has a valid checksum on the end, then the call to verify_checksum + * will elevate the firmware_level to ChecksummedMessages for us. (The actual return + * code from verify_checksum is ignored here.) + */ + verify_checksum(strip_info); + /* + * If the radio has structured messages but we don't yet have all our information about it, + * we should do probes without delay, until we have gathered all the information + */ + if (!GOT_ALL_RADIO_INFO(strip_info)) + strip_info->watchdog_doprobe = jiffies; + } + } + + else if (has_prefix(msg, len, "005")) /* Bad count specification */ + RecvErr("Error Msg:", strip_info); + + else if (has_prefix(msg, len, "006")) /* Header too big */ + RecvErr("Error Msg:", strip_info); + + else if (has_prefix(msg, len, "007")) { /* Body too big */ + RecvErr("Error Msg:", strip_info); + printk(KERN_ERR + "%s: Error! Packet size too big for radio.\n", + strip_info->dev->name); + } + + else if (has_prefix(msg, len, "008")) { /* Bad character in name */ + RecvErr("Error Msg:", strip_info); + printk(KERN_ERR + "%s: Radio name contains illegal character\n", + strip_info->dev->name); + } + + else if (has_prefix(msg, len, "009")) /* No count or line terminator */ + RecvErr("Error Msg:", strip_info); + + else if (has_prefix(msg, len, "010")) /* Invalid checksum */ + RecvErr("Error Msg:", strip_info); + + else if (has_prefix(msg, len, "011")) /* Checksum didn't match */ + RecvErr("Error Msg:", strip_info); + + else if (has_prefix(msg, len, "012")) /* Failed to transmit packet */ + RecvErr("Error Msg:", strip_info); + + else + RecvErr("Error Msg:", strip_info); +} + +static void process_AT_response(struct strip *strip_info, __u8 * ptr, + __u8 * end) +{ + u_long len; + __u8 *p = ptr; + while (p < end && p[-1] != 10) + p++; /* Skip past first newline character */ + /* Now ptr points to the AT command, and p points to the text of the response. */ + len = p - ptr; + +#if TICKLE_TIMERS + { + struct timeval tv; + do_gettimeofday(&tv); + printk(KERN_INFO "**** Got AT response %.7s at %02d.%06d\n", + ptr, tv.tv_sec % 100, tv.tv_usec); + } +#endif + + if (has_prefix(ptr, len, "ATS300?")) + get_radio_version(strip_info, p, end); + else if (has_prefix(ptr, len, "ATS305?")) + get_radio_address(strip_info, p); + else if (has_prefix(ptr, len, "ATS311?")) + get_radio_neighbours(&strip_info->poletops, p, end); + else if (has_prefix(ptr, len, "ATS319=7")) + verify_checksum(strip_info); + else if (has_prefix(ptr, len, "ATS325?")) + get_radio_voltage(strip_info, p, end); + else if (has_prefix(ptr, len, "AT~LA")) + get_radio_neighbours(&strip_info->portables, p, end); + else + RecvErr("Unknown AT Response:", strip_info); +} + +static void process_ACK(struct strip *strip_info, __u8 * ptr, __u8 * end) +{ + /* Currently we don't do anything with ACKs from the radio */ +} + +static void process_Info(struct strip *strip_info, __u8 * ptr, __u8 * end) +{ + if (ptr + 16 > end) + RecvErr("Bad Info Msg:", strip_info); +} + +static struct net_device *get_strip_dev(struct strip *strip_info) +{ + /* If our hardware address is *manually set* to zero, and we know our */ + /* real radio hardware address, try to find another strip device that has been */ + /* manually set to that address that we can 'transfer ownership' of this packet to */ + if (strip_info->manual_dev_addr && + !memcmp(strip_info->dev->dev_addr, zero_address.c, + sizeof(zero_address)) + && memcmp(&strip_info->true_dev_addr, zero_address.c, + sizeof(zero_address))) { + struct net_device *dev; + read_lock_bh(&dev_base_lock); + for_each_netdev(&init_net, dev) { + if (dev->type == strip_info->dev->type && + !memcmp(dev->dev_addr, + &strip_info->true_dev_addr, + sizeof(MetricomAddress))) { + printk(KERN_INFO + "%s: Transferred packet ownership to %s.\n", + strip_info->dev->name, dev->name); + read_unlock_bh(&dev_base_lock); + return (dev); + } + } + read_unlock_bh(&dev_base_lock); + } + return (strip_info->dev); +} + +/* + * Send one completely decapsulated datagram to the next layer. + */ + +static void deliver_packet(struct strip *strip_info, STRIP_Header * header, + __u16 packetlen) +{ + struct sk_buff *skb = dev_alloc_skb(sizeof(STRIP_Header) + packetlen); + if (!skb) { + printk(KERN_ERR "%s: memory squeeze, dropping packet.\n", + strip_info->dev->name); + strip_info->rx_dropped++; + } else { + memcpy(skb_put(skb, sizeof(STRIP_Header)), header, + sizeof(STRIP_Header)); + memcpy(skb_put(skb, packetlen), strip_info->rx_buff, + packetlen); + skb->dev = get_strip_dev(strip_info); + skb->protocol = header->protocol; + skb_reset_mac_header(skb); + + /* Having put a fake header on the front of the sk_buff for the */ + /* benefit of tools like tcpdump, skb_pull now 'consumes' that */ + /* fake header before we hand the packet up to the next layer. */ + skb_pull(skb, sizeof(STRIP_Header)); + + /* Finally, hand the packet up to the next layer (e.g. IP or ARP, etc.) */ + strip_info->rx_packets++; + strip_info->rx_pps_count++; +#ifdef EXT_COUNTERS + strip_info->rx_bytes += packetlen; +#endif + skb->dev->last_rx = jiffies; + netif_rx(skb); + } +} + +static void process_IP_packet(struct strip *strip_info, + STRIP_Header * header, __u8 * ptr, + __u8 * end) +{ + __u16 packetlen; + + /* Decode start of the IP packet header */ + ptr = UnStuffData(ptr, end, strip_info->rx_buff, 4); + if (!ptr) { + RecvErr("IP Packet too short", strip_info); + return; + } + + packetlen = ((__u16) strip_info->rx_buff[2] << 8) | strip_info->rx_buff[3]; + + if (packetlen > MAX_RECV_MTU) { + printk(KERN_INFO "%s: Dropping oversized received IP packet: %d bytes\n", + strip_info->dev->name, packetlen); + strip_info->rx_dropped++; + return; + } + + /*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev->name, packetlen); */ + + /* Decode remainder of the IP packet */ + ptr = + UnStuffData(ptr, end, strip_info->rx_buff + 4, packetlen - 4); + if (!ptr) { + RecvErr("IP Packet too short", strip_info); + return; + } + + if (ptr < end) { + RecvErr("IP Packet too long", strip_info); + return; + } + + header->protocol = htons(ETH_P_IP); + + deliver_packet(strip_info, header, packetlen); +} + +static void process_ARP_packet(struct strip *strip_info, + STRIP_Header * header, __u8 * ptr, + __u8 * end) +{ + __u16 packetlen; + struct arphdr *arphdr = (struct arphdr *) strip_info->rx_buff; + + /* Decode start of the ARP packet */ + ptr = UnStuffData(ptr, end, strip_info->rx_buff, 8); + if (!ptr) { + RecvErr("ARP Packet too short", strip_info); + return; + } + + packetlen = 8 + (arphdr->ar_hln + arphdr->ar_pln) * 2; + + if (packetlen > MAX_RECV_MTU) { + printk(KERN_INFO + "%s: Dropping oversized received ARP packet: %d bytes\n", + strip_info->dev->name, packetlen); + strip_info->rx_dropped++; + return; + } + + /*printk(KERN_INFO "%s: Got %d byte ARP %s\n", + strip_info->dev->name, packetlen, + ntohs(arphdr->ar_op) == ARPOP_REQUEST ? "request" : "reply"); */ + + /* Decode remainder of the ARP packet */ + ptr = + UnStuffData(ptr, end, strip_info->rx_buff + 8, packetlen - 8); + if (!ptr) { + RecvErr("ARP Packet too short", strip_info); + return; + } + + if (ptr < end) { + RecvErr("ARP Packet too long", strip_info); + return; + } + + header->protocol = htons(ETH_P_ARP); + + deliver_packet(strip_info, header, packetlen); +} + +/* + * process_text_message processes a -terminated block of data received + * from the radio that doesn't begin with a '*' character. All normal + * Starmode communication messages with the radio begin with a '*', + * so any text that does not indicates a serial port error, a radio that + * is in Hayes command mode instead of Starmode, or a radio with really + * old firmware that doesn't frame its Starmode responses properly. + */ +static void process_text_message(struct strip *strip_info) +{ + __u8 *msg = strip_info->sx_buff; + int len = strip_info->sx_count; + + /* Check for anything that looks like it might be our radio name */ + /* (This is here for backwards compatibility with old firmware) */ + if (len == 9 && get_radio_address(strip_info, msg) == 0) + return; + + if (text_equal(msg, len, "OK")) + return; /* Ignore 'OK' responses from prior commands */ + if (text_equal(msg, len, "ERROR")) + return; /* Ignore 'ERROR' messages */ + if (has_prefix(msg, len, "ate0q1")) + return; /* Ignore character echo back from the radio */ + + /* Catch other error messages */ + /* (This is here for backwards compatibility with old firmware) */ + if (has_prefix(msg, len, "ERR_")) { + RecvErr_Message(strip_info, NULL, &msg[4], len - 4); + return; + } + + RecvErr("No initial *", strip_info); +} + +/* + * process_message processes a -terminated block of data received + * from the radio. If the radio is not in Starmode or has old firmware, + * it may be a line of text in response to an AT command. Ideally, with + * a current radio that's properly in Starmode, all data received should + * be properly framed and checksummed radio message blocks, containing + * either a starmode packet, or a other communication from the radio + * firmware, like "INF_" Info messages and &COMMAND responses. + */ +static void process_message(struct strip *strip_info) +{ + STRIP_Header header = { zero_address, zero_address, 0 }; + __u8 *ptr = strip_info->sx_buff; + __u8 *end = strip_info->sx_buff + strip_info->sx_count; + __u8 sendername[32], *sptr = sendername; + MetricomKey key; + + /*HexDump("Receiving", strip_info, ptr, end); */ + + /* Check for start of address marker, and then skip over it */ + if (*ptr == '*') + ptr++; + else { + process_text_message(strip_info); + return; + } + + /* Copy out the return address */ + while (ptr < end && *ptr != '*' + && sptr < ARRAY_END(sendername) - 1) + *sptr++ = *ptr++; + *sptr = 0; /* Null terminate the sender name */ + + /* Check for end of address marker, and skip over it */ + if (ptr >= end || *ptr != '*') { + RecvErr("No second *", strip_info); + return; + } + ptr++; /* Skip the second '*' */ + + /* If the sender name is "&COMMAND", ignore this 'packet' */ + /* (This is here for backwards compatibility with old firmware) */ + if (!strcmp(sendername, "&COMMAND")) { + strip_info->firmware_level = NoStructure; + strip_info->next_command = CompatibilityCommand; + return; + } + + if (ptr + 4 > end) { + RecvErr("No proto key", strip_info); + return; + } + + /* Get the protocol key out of the buffer */ + key.c[0] = *ptr++; + key.c[1] = *ptr++; + key.c[2] = *ptr++; + key.c[3] = *ptr++; + + /* If we're using checksums, verify the checksum at the end of the packet */ + if (strip_info->firmware_level >= ChecksummedMessages) { + end -= 4; /* Chop the last four bytes off the packet (they're the checksum) */ + if (ptr > end) { + RecvErr("Missing Checksum", strip_info); + return; + } + if (!verify_checksum(strip_info)) { + RecvErr("Bad Checksum", strip_info); + return; + } + } + + /*printk(KERN_INFO "%s: Got packet from \"%s\".\n", strip_info->dev->name, sendername); */ + + /* + * Fill in (pseudo) source and destination addresses in the packet. + * We assume that the destination address was our address (the radio does not + * tell us this). If the radio supplies a source address, then we use it. + */ + header.dst_addr = strip_info->true_dev_addr; + string_to_radio_address(&header.src_addr, sendername); + +#ifdef EXT_COUNTERS + if (key.l == SIP0Key.l) { + strip_info->rx_rbytes += (end - ptr); + process_IP_packet(strip_info, &header, ptr, end); + } else if (key.l == ARP0Key.l) { + strip_info->rx_rbytes += (end - ptr); + process_ARP_packet(strip_info, &header, ptr, end); + } else if (key.l == ATR_Key.l) { + strip_info->rx_ebytes += (end - ptr); + process_AT_response(strip_info, ptr, end); + } else if (key.l == ACK_Key.l) { + strip_info->rx_ebytes += (end - ptr); + process_ACK(strip_info, ptr, end); + } else if (key.l == INF_Key.l) { + strip_info->rx_ebytes += (end - ptr); + process_Info(strip_info, ptr, end); + } else if (key.l == ERR_Key.l) { + strip_info->rx_ebytes += (end - ptr); + RecvErr_Message(strip_info, sendername, ptr, end - ptr); + } else + RecvErr("Unrecognized protocol key", strip_info); +#else + if (key.l == SIP0Key.l) + process_IP_packet(strip_info, &header, ptr, end); + else if (key.l == ARP0Key.l) + process_ARP_packet(strip_info, &header, ptr, end); + else if (key.l == ATR_Key.l) + process_AT_response(strip_info, ptr, end); + else if (key.l == ACK_Key.l) + process_ACK(strip_info, ptr, end); + else if (key.l == INF_Key.l) + process_Info(strip_info, ptr, end); + else if (key.l == ERR_Key.l) + RecvErr_Message(strip_info, sendername, ptr, end - ptr); + else + RecvErr("Unrecognized protocol key", strip_info); +#endif +} + +#define TTYERROR(X) ((X) == TTY_BREAK ? "Break" : \ + (X) == TTY_FRAME ? "Framing Error" : \ + (X) == TTY_PARITY ? "Parity Error" : \ + (X) == TTY_OVERRUN ? "Hardware Overrun" : "Unknown Error") + +/* + * Handle the 'receiver data ready' interrupt. + * This function is called by the 'tty_io' module in the kernel when + * a block of STRIP data has been received, which can now be decapsulated + * and sent on to some IP layer for further processing. + */ + +static void strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +{ + struct strip *strip_info = (struct strip *) tty->disc_data; + const unsigned char *end = cp + count; + + if (!strip_info || strip_info->magic != STRIP_MAGIC + || !netif_running(strip_info->dev)) + return; + + spin_lock_bh(&strip_lock); +#if 0 + { + struct timeval tv; + do_gettimeofday(&tv); + printk(KERN_INFO + "**** strip_receive_buf: %3d bytes at %02d.%06d\n", + count, tv.tv_sec % 100, tv.tv_usec); + } +#endif + +#ifdef EXT_COUNTERS + strip_info->rx_sbytes += count; +#endif + + /* Read the characters out of the buffer */ + while (cp < end) { + if (fp && *fp) + printk(KERN_INFO "%s: %s on serial port\n", + strip_info->dev->name, TTYERROR(*fp)); + if (fp && *fp++ && !strip_info->discard) { /* If there's a serial error, record it */ + /* If we have some characters in the buffer, discard them */ + strip_info->discard = strip_info->sx_count; + strip_info->rx_errors++; + } + + /* Leading control characters (CR, NL, Tab, etc.) are ignored */ + if (strip_info->sx_count > 0 || *cp >= ' ') { + if (*cp == 0x0D) { /* If end of packet, decide what to do with it */ + if (strip_info->sx_count > 3000) + printk(KERN_INFO + "%s: Cut a %d byte packet (%zd bytes remaining)%s\n", + strip_info->dev->name, + strip_info->sx_count, + end - cp - 1, + strip_info-> + discard ? " (discarded)" : + ""); + if (strip_info->sx_count > + strip_info->sx_size) { + strip_info->rx_over_errors++; + printk(KERN_INFO + "%s: sx_buff overflow (%d bytes total)\n", + strip_info->dev->name, + strip_info->sx_count); + } else if (strip_info->discard) + printk(KERN_INFO + "%s: Discarding bad packet (%d/%d)\n", + strip_info->dev->name, + strip_info->discard, + strip_info->sx_count); + else + process_message(strip_info); + strip_info->discard = 0; + strip_info->sx_count = 0; + } else { + /* Make sure we have space in the buffer */ + if (strip_info->sx_count < + strip_info->sx_size) + strip_info->sx_buff[strip_info-> + sx_count] = + *cp; + strip_info->sx_count++; + } + } + cp++; + } + spin_unlock_bh(&strip_lock); +} + + +/************************************************************************/ +/* General control routines */ + +static int set_mac_address(struct strip *strip_info, + MetricomAddress * addr) +{ + /* + * We're using a manually specified address if the address is set + * to anything other than all ones. Setting the address to all ones + * disables manual mode and goes back to automatic address determination + * (tracking the true address that the radio has). + */ + strip_info->manual_dev_addr = + memcmp(addr->c, broadcast_address.c, + sizeof(broadcast_address)); + if (strip_info->manual_dev_addr) + *(MetricomAddress *) strip_info->dev->dev_addr = *addr; + else + *(MetricomAddress *) strip_info->dev->dev_addr = + strip_info->true_dev_addr; + return 0; +} + +static int strip_set_mac_address(struct net_device *dev, void *addr) +{ + struct strip *strip_info = netdev_priv(dev); + struct sockaddr *sa = addr; + printk(KERN_INFO "%s: strip_set_dev_mac_address called\n", dev->name); + set_mac_address(strip_info, (MetricomAddress *) sa->sa_data); + return 0; +} + +static struct net_device_stats *strip_get_stats(struct net_device *dev) +{ + struct strip *strip_info = netdev_priv(dev); + static struct net_device_stats stats; + + memset(&stats, 0, sizeof(struct net_device_stats)); + + stats.rx_packets = strip_info->rx_packets; + stats.tx_packets = strip_info->tx_packets; + stats.rx_dropped = strip_info->rx_dropped; + stats.tx_dropped = strip_info->tx_dropped; + stats.tx_errors = strip_info->tx_errors; + stats.rx_errors = strip_info->rx_errors; + stats.rx_over_errors = strip_info->rx_over_errors; + return (&stats); +} + + +/************************************************************************/ +/* Opening and closing */ + +/* + * Here's the order things happen: + * When the user runs "slattach -p strip ..." + * 1. The TTY module calls strip_open;; + * 2. strip_open calls strip_alloc + * 3. strip_alloc calls register_netdev + * 4. register_netdev calls strip_dev_init + * 5. then strip_open finishes setting up the strip_info + * + * When the user runs "ifconfig st up address netmask ..." + * 6. strip_open_low gets called + * + * When the user runs "ifconfig st down" + * 7. strip_close_low gets called + * + * When the user kills the slattach process + * 8. strip_close gets called + * 9. strip_close calls dev_close + * 10. if the device is still up, then dev_close calls strip_close_low + * 11. strip_close calls strip_free + */ + +/* Open the low-level part of the STRIP channel. Easy! */ + +static int strip_open_low(struct net_device *dev) +{ + struct strip *strip_info = netdev_priv(dev); + + if (strip_info->tty == NULL) + return (-ENODEV); + + if (!allocate_buffers(strip_info, dev->mtu)) + return (-ENOMEM); + + strip_info->sx_count = 0; + strip_info->tx_left = 0; + + strip_info->discard = 0; + strip_info->working = FALSE; + strip_info->firmware_level = NoStructure; + strip_info->next_command = CompatibilityCommand; + strip_info->user_baud = tty_get_baud_rate(strip_info->tty); + + printk(KERN_INFO "%s: Initializing Radio.\n", + strip_info->dev->name); + ResetRadio(strip_info); + strip_info->idle_timer.expires = jiffies + 1 * HZ; + add_timer(&strip_info->idle_timer); + netif_wake_queue(dev); + return (0); +} + + +/* + * Close the low-level part of the STRIP channel. Easy! + */ + +static int strip_close_low(struct net_device *dev) +{ + struct strip *strip_info = netdev_priv(dev); + + if (strip_info->tty == NULL) + return -EBUSY; + strip_info->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP); + + netif_stop_queue(dev); + + /* + * Free all STRIP frame buffers. + */ + kfree(strip_info->rx_buff); + strip_info->rx_buff = NULL; + kfree(strip_info->sx_buff); + strip_info->sx_buff = NULL; + kfree(strip_info->tx_buff); + strip_info->tx_buff = NULL; + + del_timer(&strip_info->idle_timer); + return 0; +} + +static const struct header_ops strip_header_ops = { + .create = strip_header, + .rebuild = strip_rebuild_header, +}; + +/* + * This routine is called by DDI when the + * (dynamically assigned) device is registered + */ + +static void strip_dev_setup(struct net_device *dev) +{ + /* + * Finish setting up the DEVICE info. + */ + + dev->trans_start = 0; + dev->last_rx = 0; + dev->tx_queue_len = 30; /* Drop after 30 frames queued */ + + dev->flags = 0; + dev->mtu = DEFAULT_STRIP_MTU; + dev->type = ARPHRD_METRICOM; /* dtang */ + dev->hard_header_len = sizeof(STRIP_Header); + /* + * dev->priv Already holds a pointer to our struct strip + */ + + *(MetricomAddress *) & dev->broadcast = broadcast_address; + dev->dev_addr[0] = 0; + dev->addr_len = sizeof(MetricomAddress); + + /* + * Pointers to interface service routines. + */ + + dev->open = strip_open_low; + dev->stop = strip_close_low; + dev->hard_start_xmit = strip_xmit; + dev->header_ops = &strip_header_ops; + + dev->set_mac_address = strip_set_mac_address; + dev->get_stats = strip_get_stats; + dev->change_mtu = strip_change_mtu; +} + +/* + * Free a STRIP channel. + */ + +static void strip_free(struct strip *strip_info) +{ + spin_lock_bh(&strip_lock); + list_del_rcu(&strip_info->list); + spin_unlock_bh(&strip_lock); + + strip_info->magic = 0; + + free_netdev(strip_info->dev); +} + + +/* + * Allocate a new free STRIP channel + */ +static struct strip *strip_alloc(void) +{ + struct list_head *n; + struct net_device *dev; + struct strip *strip_info; + + dev = alloc_netdev(sizeof(struct strip), "st%d", + strip_dev_setup); + + if (!dev) + return NULL; /* If no more memory, return */ + + + strip_info = netdev_priv(dev); + strip_info->dev = dev; + + strip_info->magic = STRIP_MAGIC; + strip_info->tty = NULL; + + strip_info->gratuitous_arp = jiffies + LongTime; + strip_info->arp_interval = 0; + init_timer(&strip_info->idle_timer); + strip_info->idle_timer.data = (long) dev; + strip_info->idle_timer.function = strip_IdleTask; + + + spin_lock_bh(&strip_lock); + rescan: + /* + * Search the list to find where to put our new entry + * (and in the process decide what channel number it is + * going to be) + */ + list_for_each(n, &strip_list) { + struct strip *s = hlist_entry(n, struct strip, list); + + if (s->dev->base_addr == dev->base_addr) { + ++dev->base_addr; + goto rescan; + } + } + + sprintf(dev->name, "st%ld", dev->base_addr); + + list_add_tail_rcu(&strip_info->list, &strip_list); + spin_unlock_bh(&strip_lock); + + return strip_info; +} + +/* + * Open the high-level part of the STRIP channel. + * This function is called by the TTY module when the + * STRIP line discipline is called for. Because we are + * sure the tty line exists, we only have to link it to + * a free STRIP channel... + */ + +static int strip_open(struct tty_struct *tty) +{ + struct strip *strip_info = (struct strip *) tty->disc_data; + + /* + * First make sure we're not already connected. + */ + + if (strip_info && strip_info->magic == STRIP_MAGIC) + return -EEXIST; + + /* + * We need a write method. + */ + + if (tty->ops->write == NULL || tty->ops->set_termios == NULL) + return -EOPNOTSUPP; + + /* + * OK. Find a free STRIP channel to use. + */ + if ((strip_info = strip_alloc()) == NULL) + return -ENFILE; + + /* + * Register our newly created device so it can be ifconfig'd + * strip_dev_init() will be called as a side-effect + */ + + if (register_netdev(strip_info->dev) != 0) { + printk(KERN_ERR "strip: register_netdev() failed.\n"); + strip_free(strip_info); + return -ENFILE; + } + + strip_info->tty = tty; + tty->disc_data = strip_info; + tty->receive_room = 65536; + + tty_driver_flush_buffer(tty); + + /* + * Restore default settings + */ + + strip_info->dev->type = ARPHRD_METRICOM; /* dtang */ + + /* + * Set tty options + */ + + tty->termios->c_iflag |= IGNBRK | IGNPAR; /* Ignore breaks and parity errors. */ + tty->termios->c_cflag |= CLOCAL; /* Ignore modem control signals. */ + tty->termios->c_cflag &= ~HUPCL; /* Don't close on hup */ + + printk(KERN_INFO "STRIP: device \"%s\" activated\n", + strip_info->dev->name); + + /* + * Done. We have linked the TTY line to a channel. + */ + return (strip_info->dev->base_addr); +} + +/* + * Close down a STRIP channel. + * This means flushing out any pending queues, and then restoring the + * TTY line discipline to what it was before it got hooked to STRIP + * (which usually is TTY again). + */ + +static void strip_close(struct tty_struct *tty) +{ + struct strip *strip_info = (struct strip *) tty->disc_data; + + /* + * First make sure we're connected. + */ + + if (!strip_info || strip_info->magic != STRIP_MAGIC) + return; + + unregister_netdev(strip_info->dev); + + tty->disc_data = NULL; + strip_info->tty = NULL; + printk(KERN_INFO "STRIP: device \"%s\" closed down\n", + strip_info->dev->name); + strip_free(strip_info); + tty->disc_data = NULL; +} + + +/************************************************************************/ +/* Perform I/O control calls on an active STRIP channel. */ + +static int strip_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct strip *strip_info = (struct strip *) tty->disc_data; + + /* + * First make sure we're connected. + */ + + if (!strip_info || strip_info->magic != STRIP_MAGIC) + return -EINVAL; + + switch (cmd) { + case SIOCGIFNAME: + if(copy_to_user((void __user *) arg, strip_info->dev->name, strlen(strip_info->dev->name) + 1)) + return -EFAULT; + break; + case SIOCSIFHWADDR: + { + MetricomAddress addr; + //printk(KERN_INFO "%s: SIOCSIFHWADDR\n", strip_info->dev->name); + if(copy_from_user(&addr, (void __user *) arg, sizeof(MetricomAddress))) + return -EFAULT; + return set_mac_address(strip_info, &addr); + } + default: + return tty_mode_ioctl(tty, file, cmd, arg); + break; + } + return 0; +} + + +/************************************************************************/ +/* Initialization */ + +static struct tty_ldisc strip_ldisc = { + .magic = TTY_LDISC_MAGIC, + .name = "strip", + .owner = THIS_MODULE, + .open = strip_open, + .close = strip_close, + .ioctl = strip_ioctl, + .receive_buf = strip_receive_buf, + .write_wakeup = strip_write_some_more, +}; + +/* + * Initialize the STRIP driver. + * This routine is called at boot time, to bootstrap the multi-channel + * STRIP driver + */ + +static char signon[] __initdata = + KERN_INFO "STRIP: Version %s (unlimited channels)\n"; + +static int __init strip_init_driver(void) +{ + int status; + + printk(signon, StripVersion); + + + /* + * Fill in our line protocol discipline, and register it + */ + if ((status = tty_register_ldisc(N_STRIP, &strip_ldisc))) + printk(KERN_ERR "STRIP: can't register line discipline (err = %d)\n", + status); + + /* + * Register the status file with /proc + */ + proc_net_fops_create(&init_net, "strip", S_IFREG | S_IRUGO, &strip_seq_fops); + + return status; +} + +module_init(strip_init_driver); + +static const char signoff[] __exitdata = + KERN_INFO "STRIP: Module Unloaded\n"; + +static void __exit strip_exit_driver(void) +{ + int i; + struct list_head *p,*n; + + /* module ref count rules assure that all entries are unregistered */ + list_for_each_safe(p, n, &strip_list) { + struct strip *s = list_entry(p, struct strip, list); + strip_free(s); + } + + /* Unregister with the /proc/net file here. */ + proc_net_remove(&init_net, "strip"); + + if ((i = tty_unregister_ldisc(N_STRIP))) + printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i); + + printk(signoff); +} + +module_exit(strip_exit_driver); + +MODULE_AUTHOR("Stuart Cheshire "); +MODULE_DESCRIPTION("Starmode Radio IP (STRIP) Device Driver"); +MODULE_LICENSE("Dual BSD/GPL"); + +MODULE_SUPPORTED_DEVICE("Starmode Radio IP (STRIP) modem"); diff --git a/trunk/drivers/net/wireless/wl3501_cs.c b/trunk/drivers/net/wireless/wl3501_cs.c index 377141995e36..42a36b3f3ff7 100644 --- a/trunk/drivers/net/wireless/wl3501_cs.c +++ b/trunk/drivers/net/wireless/wl3501_cs.c @@ -1624,25 +1624,25 @@ static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(info, current_ev, + current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN); iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; iwe.u.data.length = this->bss_set[i].ssid.el.len; - current_ev = iwe_stream_add_point(info, current_ev, + current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, this->bss_set[i].ssid.essid); iwe.cmd = SIOCGIWMODE; iwe.u.mode = this->bss_set[i].bss_type; - current_ev = iwe_stream_add_event(info, current_ev, + current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_UINT_LEN); iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = this->bss_set[i].ds_pset.chan; iwe.u.freq.e = 0; - current_ev = iwe_stream_add_event(info, current_ev, + current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN); iwe.cmd = SIOCGIWENCODE; @@ -1651,7 +1651,7 @@ static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, + current_ev = iwe_stream_add_point(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, NULL); } diff --git a/trunk/drivers/net/wireless/zd1201.c b/trunk/drivers/net/wireless/zd1201.c index 07e4d1f73207..d5c0c66188ca 100644 --- a/trunk/drivers/net/wireless/zd1201.c +++ b/trunk/drivers/net/wireless/zd1201.c @@ -1152,36 +1152,32 @@ static int zd1201_get_scan(struct net_device *dev, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_ADDR_LEN); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); iwe.cmd = SIOCGIWESSID; iwe.u.data.length = zd->rxdata[i+16]; iwe.u.data.flags = 1; - cev = iwe_stream_add_point(info, cev, end_buf, - &iwe, zd->rxdata+i+18); + cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18); iwe.cmd = SIOCGIWMODE; if (zd->rxdata[i+14]&0x01) iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_UINT_LEN); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = zd->rxdata[i+0]; iwe.u.freq.e = 0; - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_FREQ_LEN); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); iwe.cmd = SIOCGIWRATE; iwe.u.bitrate.fixed = 0; iwe.u.bitrate.disabled = 0; for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_PARAM_LEN); + cev=iwe_stream_add_event(cev, end_buf, &iwe, + IW_EV_PARAM_LEN); } iwe.cmd = SIOCGIWENCODE; @@ -1190,15 +1186,14 @@ static int zd1201_get_scan(struct net_device *dev, iwe.u.data.flags = IW_ENCODE_ENABLED; else iwe.u.data.flags = IW_ENCODE_DISABLED; - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL); + cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); iwe.cmd = IWEVQUAL; iwe.u.qual.qual = zd->rxdata[i+4]; iwe.u.qual.noise= zd->rxdata[i+2]/10-100; iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; iwe.u.qual.updated = 7; - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_QUAL_LEN); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); } if (!enabled_save) diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c index 317c5e24f80c..6d86b365f150 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c @@ -376,6 +376,8 @@ static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length) static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, struct ieee80211_hdr *header, u32 flags) { + u16 fctl = le16_to_cpu(header->frame_control); + /* * CONTROL TODO: * - if backoff needed, enable bit 0 @@ -393,7 +395,8 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, cs->control |= ZD_CS_MULTICAST; /* PS-POLL */ - if (ieee80211_is_pspoll(header->frame_control)) + if ((fctl & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) == + (IEEE80211_FTYPE_CTL|IEEE80211_STYPE_PSPOLL)) cs->control |= ZD_CS_PS_POLL_FRAME; if (flags & IEEE80211_TX_CTL_USE_RTS_CTS) @@ -547,11 +550,13 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, struct ieee80211_rx_status *stats) { + u16 fc = le16_to_cpu(rx_hdr->frame_control); struct sk_buff *skb; struct sk_buff_head *q; unsigned long flags; - if (!ieee80211_is_ack(rx_hdr->frame_control)) + if ((fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) != + (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK)) return 0; q = &zd_hw_mac(hw)->ack_wait_queue; @@ -579,8 +584,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) const struct rx_status *status; struct sk_buff *skb; int bad_frame = 0; - __le16 fc; - int need_padding; + u16 fc; + bool is_qos, is_4addr, need_padding; int i; u8 rate; @@ -639,8 +644,13 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) && !mac->pass_ctrl) return 0; - fc = *(__le16 *)buffer; - need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc); + fc = le16_to_cpu(*((__le16 *) buffer)); + + is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && + (fc & IEEE80211_STYPE_QOS_DATA); + is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == + (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); + need_padding = is_qos ^ is_4addr; skb = dev_alloc_skb(length + (need_padding ? 2 : 0)); if (skb == NULL) diff --git a/trunk/drivers/ssb/Kconfig b/trunk/drivers/ssb/Kconfig index 307b1f62d949..cd845b8acd17 100644 --- a/trunk/drivers/ssb/Kconfig +++ b/trunk/drivers/ssb/Kconfig @@ -2,7 +2,7 @@ menu "Sonics Silicon Backplane" config SSB_POSSIBLE bool - depends on HAS_IOMEM && HAS_DMA + depends on HAS_IOMEM default y config SSB diff --git a/trunk/drivers/ssb/main.c b/trunk/drivers/ssb/main.c index d831a2beff39..d184f2aea78d 100644 --- a/trunk/drivers/ssb/main.c +++ b/trunk/drivers/ssb/main.c @@ -462,15 +462,18 @@ static int ssb_devices_register(struct ssb_bus *bus) #ifdef CONFIG_SSB_PCIHOST sdev->irq = bus->host_pci->irq; dev->parent = &bus->host_pci->dev; + sdev->dma_dev = &bus->host_pci->dev; #endif break; case SSB_BUSTYPE_PCMCIA: #ifdef CONFIG_SSB_PCMCIAHOST sdev->irq = bus->host_pcmcia->irq.AssignedIRQ; dev->parent = &bus->host_pcmcia->dev; + sdev->dma_dev = &bus->host_pcmcia->dev; #endif break; case SSB_BUSTYPE_SSB: + sdev->dma_dev = dev; break; } @@ -1153,81 +1156,35 @@ u32 ssb_dma_translation(struct ssb_device *dev) { switch (dev->bus->bustype) { case SSB_BUSTYPE_SSB: + case SSB_BUSTYPE_PCMCIA: return 0; case SSB_BUSTYPE_PCI: return SSB_PCI_DMA; - default: - __ssb_dma_not_implemented(dev); } return 0; } EXPORT_SYMBOL(ssb_dma_translation); -int ssb_dma_set_mask(struct ssb_device *dev, u64 mask) +int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask) { - int err; + struct device *dma_dev = ssb_dev->dma_dev; + int err = 0; - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - err = pci_set_dma_mask(dev->bus->host_pci, mask); +#ifdef CONFIG_SSB_PCIHOST + if (ssb_dev->bus->bustype == SSB_BUSTYPE_PCI) { + err = pci_set_dma_mask(ssb_dev->bus->host_pci, mask); if (err) return err; - err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask); + err = pci_set_consistent_dma_mask(ssb_dev->bus->host_pci, mask); return err; - case SSB_BUSTYPE_SSB: - return dma_set_mask(dev->dev, mask); - default: - __ssb_dma_not_implemented(dev); } - return -ENOSYS; -} -EXPORT_SYMBOL(ssb_dma_set_mask); - -void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp_flags) -{ - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - if (gfp_flags & GFP_DMA) { - /* Workaround: The PCI API does not support passing - * a GFP flag. */ - return dma_alloc_coherent(&dev->bus->host_pci->dev, - size, dma_handle, gfp_flags); - } - return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle); - case SSB_BUSTYPE_SSB: - return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags); - default: - __ssb_dma_not_implemented(dev); - } - return NULL; -} -EXPORT_SYMBOL(ssb_dma_alloc_consistent); +#endif + dma_dev->coherent_dma_mask = mask; + dma_dev->dma_mask = &dma_dev->coherent_dma_mask; -void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle, - gfp_t gfp_flags) -{ - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - if (gfp_flags & GFP_DMA) { - /* Workaround: The PCI API does not support passing - * a GFP flag. */ - dma_free_coherent(&dev->bus->host_pci->dev, - size, vaddr, dma_handle); - return; - } - pci_free_consistent(dev->bus->host_pci, size, - vaddr, dma_handle); - return; - case SSB_BUSTYPE_SSB: - dma_free_coherent(dev->dev, size, vaddr, dma_handle); - return; - default: - __ssb_dma_not_implemented(dev); - } + return err; } -EXPORT_SYMBOL(ssb_dma_free_consistent); +EXPORT_SYMBOL(ssb_dma_set_mask); int ssb_bus_may_powerdown(struct ssb_bus *bus) { diff --git a/trunk/fs/compat_ioctl.c b/trunk/fs/compat_ioctl.c index 05ec7eef8690..97dba0d92348 100644 --- a/trunk/fs/compat_ioctl.c +++ b/trunk/fs/compat_ioctl.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -1756,6 +1757,64 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, unsigned long a return sys_ioctl(fd, cmd, (unsigned long)tdata); } +struct compat_iw_point { + compat_caddr_t pointer; + __u16 length; + __u16 flags; +}; + +static int do_wireless_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct iwreq __user *iwr; + struct iwreq __user *iwr_u; + struct iw_point __user *iwp; + struct compat_iw_point __user *iwp_u; + compat_caddr_t pointer_u; + void __user *pointer; + __u16 length, flags; + int ret; + + iwr_u = compat_ptr(arg); + iwp_u = (struct compat_iw_point __user *) &iwr_u->u.data; + iwr = compat_alloc_user_space(sizeof(*iwr)); + if (iwr == NULL) + return -ENOMEM; + + iwp = &iwr->u.data; + + if (!access_ok(VERIFY_WRITE, iwr, sizeof(*iwr))) + return -EFAULT; + + if (__copy_in_user(&iwr->ifr_ifrn.ifrn_name[0], + &iwr_u->ifr_ifrn.ifrn_name[0], + sizeof(iwr->ifr_ifrn.ifrn_name))) + return -EFAULT; + + if (__get_user(pointer_u, &iwp_u->pointer) || + __get_user(length, &iwp_u->length) || + __get_user(flags, &iwp_u->flags)) + return -EFAULT; + + if (__put_user(compat_ptr(pointer_u), &iwp->pointer) || + __put_user(length, &iwp->length) || + __put_user(flags, &iwp->flags)) + return -EFAULT; + + ret = sys_ioctl(fd, cmd, (unsigned long) iwr); + + if (__get_user(pointer, &iwp->pointer) || + __get_user(length, &iwp->length) || + __get_user(flags, &iwp->flags)) + return -EFAULT; + + if (__put_user(ptr_to_compat(pointer), &iwp_u->pointer) || + __put_user(length, &iwp_u->length) || + __put_user(flags, &iwp_u->flags)) + return -EFAULT; + + return ret; +} + /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE * for some operations; this forces use of the newer bridge-utils that * use compatiable ioctls @@ -2436,6 +2495,36 @@ COMPATIBLE_IOCTL(I2C_TENBIT) COMPATIBLE_IOCTL(I2C_PEC) COMPATIBLE_IOCTL(I2C_RETRIES) COMPATIBLE_IOCTL(I2C_TIMEOUT) +/* wireless */ +COMPATIBLE_IOCTL(SIOCSIWCOMMIT) +COMPATIBLE_IOCTL(SIOCGIWNAME) +COMPATIBLE_IOCTL(SIOCSIWNWID) +COMPATIBLE_IOCTL(SIOCGIWNWID) +COMPATIBLE_IOCTL(SIOCSIWFREQ) +COMPATIBLE_IOCTL(SIOCGIWFREQ) +COMPATIBLE_IOCTL(SIOCSIWMODE) +COMPATIBLE_IOCTL(SIOCGIWMODE) +COMPATIBLE_IOCTL(SIOCSIWSENS) +COMPATIBLE_IOCTL(SIOCGIWSENS) +COMPATIBLE_IOCTL(SIOCSIWRANGE) +COMPATIBLE_IOCTL(SIOCSIWPRIV) +COMPATIBLE_IOCTL(SIOCSIWSTATS) +COMPATIBLE_IOCTL(SIOCSIWAP) +COMPATIBLE_IOCTL(SIOCGIWAP) +COMPATIBLE_IOCTL(SIOCSIWRATE) +COMPATIBLE_IOCTL(SIOCGIWRATE) +COMPATIBLE_IOCTL(SIOCSIWRTS) +COMPATIBLE_IOCTL(SIOCGIWRTS) +COMPATIBLE_IOCTL(SIOCSIWFRAG) +COMPATIBLE_IOCTL(SIOCGIWFRAG) +COMPATIBLE_IOCTL(SIOCSIWTXPOW) +COMPATIBLE_IOCTL(SIOCGIWTXPOW) +COMPATIBLE_IOCTL(SIOCSIWRETRY) +COMPATIBLE_IOCTL(SIOCGIWRETRY) +COMPATIBLE_IOCTL(SIOCSIWPOWER) +COMPATIBLE_IOCTL(SIOCGIWPOWER) +COMPATIBLE_IOCTL(SIOCSIWAUTH) +COMPATIBLE_IOCTL(SIOCGIWAUTH) /* hiddev */ COMPATIBLE_IOCTL(HIDIOCGVERSION) COMPATIBLE_IOCTL(HIDIOCAPPLICATION) @@ -2666,7 +2755,29 @@ COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) HANDLE_IOCTL(I2C_FUNCS, w_long) HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl) -/* bridge */ +/* wireless */ +HANDLE_IOCTL(SIOCGIWRANGE, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWPRIV, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWSTATS, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWSPY, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWSPY, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWTHRSPY, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWTHRSPY, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWMLME, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWAPLIST, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWSCAN, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWSCAN, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWESSID, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWESSID, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWNICKN, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWNICKN, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWENCODE, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWENCODE, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWGENIE, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWGENIE, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWENCODEEXT, do_wireless_ioctl) +HANDLE_IOCTL(SIOCGIWENCODEEXT, do_wireless_ioctl) +HANDLE_IOCTL(SIOCSIWPMKSA, do_wireless_ioctl) HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) HANDLE_IOCTL(SIOCGIFBR, old_bridge_ioctl) /* Not implemented in the native kernel */ diff --git a/trunk/include/linux/ethtool.h b/trunk/include/linux/ethtool.h index 8bb5e87df365..c8d216357865 100644 --- a/trunk/include/linux/ethtool.h +++ b/trunk/include/linux/ethtool.h @@ -272,12 +272,6 @@ enum ethtool_flags { ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ }; -struct ethtool_rxnfc { - __u32 cmd; - __u32 flow_type; - __u64 data; -}; - #ifdef __KERNEL__ struct net_device; @@ -402,8 +396,6 @@ struct ethtool_ops { /* the following hooks are obsolete */ int (*self_test_count)(struct net_device *);/* use get_sset_count */ int (*get_stats_count)(struct net_device *);/* use get_sset_count */ - int (*get_rxhash)(struct net_device *, struct ethtool_rxnfc *); - int (*set_rxhash)(struct net_device *, struct ethtool_rxnfc *); }; #endif /* __KERNEL__ */ @@ -450,9 +442,6 @@ struct ethtool_ops { #define ETHTOOL_GPFLAGS 0x00000027 /* Get driver-private flags bitmap */ #define ETHTOOL_SPFLAGS 0x00000028 /* Set driver-private flags bitmap */ -#define ETHTOOL_GRXFH 0x00000029 /* Get RX flow hash configuration */ -#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */ - /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET #define SPARC_ETH_SSET ETHTOOL_SSET @@ -539,26 +528,4 @@ struct ethtool_ops { #define WAKE_MAGIC (1 << 5) #define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ -/* L3-L4 network traffic flow types */ -#define TCP_V4_FLOW 0x01 -#define UDP_V4_FLOW 0x02 -#define SCTP_V4_FLOW 0x03 -#define AH_ESP_V4_FLOW 0x04 -#define TCP_V6_FLOW 0x05 -#define UDP_V6_FLOW 0x06 -#define SCTP_V6_FLOW 0x07 -#define AH_ESP_V6_FLOW 0x08 - -/* L3-L4 network traffic flow hash options */ -#define RXH_DEV_PORT (1 << 0) -#define RXH_L2DA (1 << 1) -#define RXH_VLAN (1 << 2) -#define RXH_L3_PROTO (1 << 3) -#define RXH_IP_SRC (1 << 4) -#define RXH_IP_DST (1 << 5) -#define RXH_L4_B_0_1 (1 << 6) /* src port in case of TCP/UDP/SCTP */ -#define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ -#define RXH_DISCARD (1 << 31) - - #endif /* _LINUX_ETHTOOL_H */ diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index cffd6d0094f9..2998e3b5f166 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -469,40 +469,6 @@ struct ieee80211s_hdr { u8 eaddr3[6]; } __attribute__ ((packed)); -/** - * struct ieee80211_quiet_ie - * - * This structure refers to "Quiet information element" - */ -struct ieee80211_quiet_ie { - u8 count; - u8 period; - __le16 duration; - __le16 offset; -} __attribute__ ((packed)); - -/** - * struct ieee80211_msrment_ie - * - * This structure refers to "Measurement Request/Report information element" - */ -struct ieee80211_msrment_ie { - u8 token; - u8 mode; - u8 type; - u8 request[0]; -} __attribute__ ((packed)); - -/** - * struct ieee80211_channel_sw_ie - * - * This structure refers to "Channel Switch Announcement information element" - */ -struct ieee80211_channel_sw_ie { - u8 mode; - u8 new_ch_num; - u8 count; -} __attribute__ ((packed)); struct ieee80211_mgmt { __le16 frame_control; @@ -578,15 +544,10 @@ struct ieee80211_mgmt { u8 action_code; u8 element_id; u8 length; - struct ieee80211_channel_sw_ie sw_elem; + u8 switch_mode; + u8 new_chan; + u8 switch_count; } __attribute__((packed)) chan_switch; - struct{ - u8 action_code; - u8 dialog_token; - u8 element_id; - u8 length; - struct ieee80211_msrment_ie msr_elem; - } __attribute__((packed)) measurement; struct{ u8 action_code; u8 dialog_token; @@ -739,21 +700,11 @@ struct ieee80211_ht_addt_info { #define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) #define WLAN_CAPABILITY_PBCC (1<<6) #define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) - /* 802.11h */ #define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) #define WLAN_CAPABILITY_QOS (1<<9) #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) #define WLAN_CAPABILITY_DSSS_OFDM (1<<13) -/* measurement */ -#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0) -#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1) -#define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2) - -#define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0 -#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1 -#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2 - /* 802.11g ERP information element */ #define WLAN_ERP_NON_ERP_PRESENT (1<<0) @@ -924,15 +875,6 @@ enum ieee80211_category { WLAN_CATEGORY_WMM = 17, }; -/* SPECTRUM_MGMT action code */ -enum ieee80211_spectrum_mgmt_actioncode { - WLAN_ACTION_SPCT_MSR_REQ = 0, - WLAN_ACTION_SPCT_MSR_RPRT = 1, - WLAN_ACTION_SPCT_TPC_REQ = 2, - WLAN_ACTION_SPCT_TPC_RPRT = 3, - WLAN_ACTION_SPCT_CHL_SWITCH = 4, -}; - /* BACK action code */ enum ieee80211_back_actioncode { WLAN_ACTION_ADDBA_REQ = 0, diff --git a/trunk/include/linux/if_tun.h b/trunk/include/linux/if_tun.h index 563fae542da6..18f31b6187a3 100644 --- a/trunk/include/linux/if_tun.h +++ b/trunk/include/linux/if_tun.h @@ -31,7 +31,6 @@ #define TUN_NO_PI 0x0040 #define TUN_ONE_QUEUE 0x0080 #define TUN_PERSIST 0x0100 -#define TUN_VNET_HDR 0x0200 /* Ioctl defines */ #define TUNSETNOCSUM _IOW('T', 200, int) @@ -41,21 +40,12 @@ #define TUNSETOWNER _IOW('T', 204, int) #define TUNSETLINK _IOW('T', 205, int) #define TUNSETGROUP _IOW('T', 206, int) -#define TUNGETFEATURES _IOR('T', 207, unsigned int) -#define TUNSETOFFLOAD _IOW('T', 208, unsigned int) /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 #define IFF_TAP 0x0002 #define IFF_NO_PI 0x1000 #define IFF_ONE_QUEUE 0x2000 -#define IFF_VNET_HDR 0x4000 - -/* Features for GSO (TUNSETOFFLOAD). */ -#define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ -#define TUN_F_TSO4 0x02 /* I can handle TSO for IPv4 packets */ -#define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */ -#define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ struct tun_pi { unsigned short flags; diff --git a/trunk/include/linux/igmp.h b/trunk/include/linux/igmp.h index 7bb3c095c15b..f5a1a0db2e8e 100644 --- a/trunk/include/linux/igmp.h +++ b/trunk/include/linux/igmp.h @@ -228,6 +228,7 @@ extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf, struct group_filter __user *optval, int __user *optlen); extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt, int dif); +extern void ip_mr_init(void); extern void ip_mc_init_dev(struct in_device *); extern void ip_mc_destroy_dev(struct in_device *); extern void ip_mc_up(struct in_device *); diff --git a/trunk/include/linux/inet_lro.h b/trunk/include/linux/inet_lro.h index c4335faebb63..80335b7d77c5 100644 --- a/trunk/include/linux/inet_lro.h +++ b/trunk/include/linux/inet_lro.h @@ -84,11 +84,7 @@ struct net_lro_mgr { from received packets and eth protocol is still ETH_P_8021Q */ - /* - * Set for generated SKBs that are not added to - * the frag list in fragmented mode - */ - u32 ip_summed; + u32 ip_summed; /* Set in non generated SKBs in page mode */ u32 ip_summed_aggr; /* Set in aggregated SKBs: CHECKSUM_UNNECESSARY * or CHECKSUM_NONE */ diff --git a/trunk/include/linux/ipv6.h b/trunk/include/linux/ipv6.h index 391ad0843a46..cde056e08181 100644 --- a/trunk/include/linux/ipv6.h +++ b/trunk/include/linux/ipv6.h @@ -163,8 +163,6 @@ struct ipv6_devconf { #ifdef CONFIG_IPV6_MROUTE __s32 mc_forwarding; #endif - __s32 disable_ipv6; - __s32 accept_dad; void *sysctl; }; @@ -196,8 +194,6 @@ enum { DEVCONF_OPTIMISTIC_DAD, DEVCONF_ACCEPT_SOURCE_ROUTE, DEVCONF_MC_FORWARDING, - DEVCONF_DISABLE_IPV6, - DEVCONF_ACCEPT_DAD, DEVCONF_MAX }; diff --git a/trunk/include/linux/mroute.h b/trunk/include/linux/mroute.h index 07112ee9293a..de4decfa1bfc 100644 --- a/trunk/include/linux/mroute.h +++ b/trunk/include/linux/mroute.h @@ -144,37 +144,11 @@ static inline int ip_mroute_opt(int opt) } #endif -#ifdef CONFIG_IP_MROUTE extern int ip_mroute_setsockopt(struct sock *, int, char __user *, int); extern int ip_mroute_getsockopt(struct sock *, int, char __user *, int __user *); extern int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg); -extern int ip_mr_init(void); -#else -static inline -int ip_mroute_setsockopt(struct sock *sock, - int optname, char __user *optval, int optlen) -{ - return -ENOPROTOOPT; -} - -static inline -int ip_mroute_getsockopt(struct sock *sock, - int optname, char __user *optval, int __user *optlen) -{ - return -ENOPROTOOPT; -} +extern void ip_mr_init(void); -static inline -int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) -{ - return -ENOIOCTLCMD; -} - -static inline int ip_mr_init(void) -{ - return 0; -} -#endif struct vif_device { diff --git a/trunk/include/linux/mroute6.h b/trunk/include/linux/mroute6.h index 5cf50473a10f..e7989593142b 100644 --- a/trunk/include/linux/mroute6.h +++ b/trunk/include/linux/mroute6.h @@ -131,44 +131,11 @@ static inline int ip6_mroute_opt(int opt) struct sock; -#ifdef CONFIG_IPV6_MROUTE extern int ip6_mroute_setsockopt(struct sock *, int, char __user *, int); extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *); extern int ip6_mr_input(struct sk_buff *skb); extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg); -extern int ip6_mr_init(void); -extern void ip6_mr_cleanup(void); -#else -static inline -int ip6_mroute_setsockopt(struct sock *sock, - int optname, char __user *optval, int optlen) -{ - return -ENOPROTOOPT; -} - -static inline -int ip6_mroute_getsockopt(struct sock *sock, - int optname, char __user *optval, int __user *optlen) -{ - return -ENOPROTOOPT; -} - -static inline -int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) -{ - return -ENOIOCTLCMD; -} - -static inline int ip6_mr_init(void) -{ - return 0; -} - -static inline void ip6_mr_cleanup(void) -{ - return; -} -#endif +extern void ip6_mr_init(void); struct mif_device { diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 56dadb528f67..1304ad2d7105 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -88,8 +88,6 @@ struct wireless_dev; #define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ #define NETDEV_TX_LOCKED -1 /* driver tx lock was already taken */ -#ifdef __KERNEL__ - /* * Compute the worst case header length according to the protocols * used. @@ -116,8 +114,6 @@ struct wireless_dev; #define MAX_HEADER (LL_MAX_HEADER + 48) #endif -#endif /* __KERNEL__ */ - struct net_device_subqueue { /* Give a control state for each queue. This struct may contain diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h index 2be7c63bc0f2..aa8411e2a160 100644 --- a/trunk/include/linux/nl80211.h +++ b/trunk/include/linux/nl80211.h @@ -241,10 +241,7 @@ enum nl80211_attrs { NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 }; -#define NL80211_MAX_SUPP_RATES 32 -#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 -#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 -#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 +#define NL80211_MAX_SUPP_RATES 32 /** * enum nl80211_iftype - (virtual) interface types diff --git a/trunk/include/linux/rfkill.h b/trunk/include/linux/rfkill.h index c5f6e54ec6ae..e3ab21d7fc7f 100644 --- a/trunk/include/linux/rfkill.h +++ b/trunk/include/linux/rfkill.h @@ -34,37 +34,26 @@ * RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. * RFKILL_TYPE_UWB: switch is on a ultra wideband device. * RFKILL_TYPE_WIMAX: switch is on a WiMAX device. - * RFKILL_TYPE_WWAN: switch is on a wireless WAN device. */ enum rfkill_type { RFKILL_TYPE_WLAN , RFKILL_TYPE_BLUETOOTH, RFKILL_TYPE_UWB, RFKILL_TYPE_WIMAX, - RFKILL_TYPE_WWAN, RFKILL_TYPE_MAX, }; enum rfkill_state { - RFKILL_STATE_SOFT_BLOCKED = 0, /* Radio output blocked */ - RFKILL_STATE_UNBLOCKED = 1, /* Radio output allowed */ - RFKILL_STATE_HARD_BLOCKED = 2, /* Output blocked, non-overrideable */ + RFKILL_STATE_OFF = 0, + RFKILL_STATE_ON = 1, }; -/* - * These are DEPRECATED, drivers using them should be verified to - * comply with the rfkill usage guidelines in Documentation/rfkill.txt - * and then converted to use the new names for rfkill_state - */ -#define RFKILL_STATE_OFF RFKILL_STATE_SOFT_BLOCKED -#define RFKILL_STATE_ON RFKILL_STATE_UNBLOCKED - /** * struct rfkill - rfkill control structure. * @name: Name of the switch. * @type: Radio type which the button controls, the value stored * here should be a value from enum rfkill_type. - * @state: State of the switch, "UNBLOCKED" means radio can operate. + * @state: State of the switch (on/off). * @user_claim_unsupported: Whether the hardware supports exclusive * RF-kill control by userspace. Set this before registering. * @user_claim: Set when the switch is controlled exlusively by userspace. @@ -72,12 +61,6 @@ enum rfkill_state { * @data: Pointer to the RF button drivers private data which will be * passed along when toggling radio state. * @toggle_radio(): Mandatory handler to control state of the radio. - * only RFKILL_STATE_SOFT_BLOCKED and RFKILL_STATE_UNBLOCKED are - * valid parameters. - * @get_state(): handler to read current radio state from hardware, - * may be called from atomic context, should return 0 on success. - * Either this handler OR judicious use of rfkill_force_state() is - * MANDATORY for any driver capable of RFKILL_STATE_HARD_BLOCKED. * @led_trigger: A LED trigger for this button's LED. * @dev: Device structure integrating the switch into device tree. * @node: Used to place switch into list of all switches known to the @@ -97,7 +80,6 @@ struct rfkill { void *data; int (*toggle_radio)(void *data, enum rfkill_state state); - int (*get_state)(void *data, enum rfkill_state *state); #ifdef CONFIG_RFKILL_LEDS struct led_trigger led_trigger; @@ -113,21 +95,6 @@ void rfkill_free(struct rfkill *rfkill); int rfkill_register(struct rfkill *rfkill); void rfkill_unregister(struct rfkill *rfkill); -int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state); - -/** - * rfkill_state_complement - return complementar state - * @state: state to return the complement of - * - * Returns RFKILL_STATE_SOFT_BLOCKED if @state is RFKILL_STATE_UNBLOCKED, - * returns RFKILL_STATE_UNBLOCKED otherwise. - */ -static inline enum rfkill_state rfkill_state_complement(enum rfkill_state state) -{ - return (state == RFKILL_STATE_UNBLOCKED) ? - RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; -} - /** * rfkill_get_led_name - Get the LED trigger name for the button's LED. * This function might return a NULL pointer if registering of the @@ -143,11 +110,4 @@ static inline char *rfkill_get_led_name(struct rfkill *rfkill) #endif } -/* rfkill notification chain */ -#define RFKILL_STATE_CHANGED 0x0001 /* state of a normal rfkill - switch has changed */ - -int register_rfkill_notifier(struct notifier_block *nb); -int unregister_rfkill_notifier(struct notifier_block *nb); - #endif /* RFKILL_H */ diff --git a/trunk/include/linux/ssb/ssb.h b/trunk/include/linux/ssb/ssb.h index 0fe5a0ded3ea..50dfd0dc4093 100644 --- a/trunk/include/linux/ssb/ssb.h +++ b/trunk/include/linux/ssb/ssb.h @@ -137,6 +137,9 @@ struct ssb_device { const struct ssb_bus_ops *ops; struct device *dev; + /* Pointer to the device that has to be used for + * any DMA related operation. */ + struct device *dma_dev; struct ssb_bus *bus; struct ssb_device_id id; @@ -396,151 +399,13 @@ static inline void ssb_block_write(struct ssb_device *dev, const void *buffer, #endif /* CONFIG_SSB_BLOCKIO */ -/* The SSB DMA API. Use this API for any DMA operation on the device. - * This API basically is a wrapper that calls the correct DMA API for - * the host device type the SSB device is attached to. */ - /* Translation (routing) bits that need to be ORed to DMA * addresses before they are given to a device. */ extern u32 ssb_dma_translation(struct ssb_device *dev); #define SSB_DMA_TRANSLATION_MASK 0xC0000000 #define SSB_DMA_TRANSLATION_SHIFT 30 -extern int ssb_dma_set_mask(struct ssb_device *dev, u64 mask); - -extern void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t gfp_flags); -extern void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle, - gfp_t gfp_flags); - -static inline void __cold __ssb_dma_not_implemented(struct ssb_device *dev) -{ -#ifdef CONFIG_SSB_DEBUG - printk(KERN_ERR "SSB: BUG! Calling DMA API for " - "unsupported bustype %d\n", dev->bus->bustype); -#endif /* DEBUG */ -} - -static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr) -{ - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - return pci_dma_mapping_error(addr); - case SSB_BUSTYPE_SSB: - return dma_mapping_error(addr); - default: - __ssb_dma_not_implemented(dev); - } - return -ENOSYS; -} - -static inline dma_addr_t ssb_dma_map_single(struct ssb_device *dev, void *p, - size_t size, enum dma_data_direction dir) -{ - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - return pci_map_single(dev->bus->host_pci, p, size, dir); - case SSB_BUSTYPE_SSB: - return dma_map_single(dev->dev, p, size, dir); - default: - __ssb_dma_not_implemented(dev); - } - return 0; -} - -static inline void ssb_dma_unmap_single(struct ssb_device *dev, dma_addr_t dma_addr, - size_t size, enum dma_data_direction dir) -{ - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - pci_unmap_single(dev->bus->host_pci, dma_addr, size, dir); - return; - case SSB_BUSTYPE_SSB: - dma_unmap_single(dev->dev, dma_addr, size, dir); - return; - default: - __ssb_dma_not_implemented(dev); - } -} - -static inline void ssb_dma_sync_single_for_cpu(struct ssb_device *dev, - dma_addr_t dma_addr, - size_t size, - enum dma_data_direction dir) -{ - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr, - size, dir); - return; - case SSB_BUSTYPE_SSB: - dma_sync_single_for_cpu(dev->dev, dma_addr, size, dir); - return; - default: - __ssb_dma_not_implemented(dev); - } -} - -static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev, - dma_addr_t dma_addr, - size_t size, - enum dma_data_direction dir) -{ - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr, - size, dir); - return; - case SSB_BUSTYPE_SSB: - dma_sync_single_for_device(dev->dev, dma_addr, size, dir); - return; - default: - __ssb_dma_not_implemented(dev); - } -} - -static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev, - dma_addr_t dma_addr, - unsigned long offset, - size_t size, - enum dma_data_direction dir) -{ - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - /* Just sync everything. That's all the PCI API can do. */ - pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr, - offset + size, dir); - return; - case SSB_BUSTYPE_SSB: - dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset, - size, dir); - return; - default: - __ssb_dma_not_implemented(dev); - } -} - -static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev, - dma_addr_t dma_addr, - unsigned long offset, - size_t size, - enum dma_data_direction dir) -{ - switch (dev->bus->bustype) { - case SSB_BUSTYPE_PCI: - /* Just sync everything. That's all the PCI API can do. */ - pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr, - offset + size, dir); - return; - case SSB_BUSTYPE_SSB: - dma_sync_single_range_for_device(dev->dev, dma_addr, offset, - size, dir); - return; - default: - __ssb_dma_not_implemented(dev); - } -} +extern int ssb_dma_set_mask(struct ssb_device *ssb_dev, u64 mask); #ifdef CONFIG_SSB_PCIHOST diff --git a/trunk/include/linux/wireless.h b/trunk/include/linux/wireless.h index d7958f9b52cb..4a95a0e5eeca 100644 --- a/trunk/include/linux/wireless.h +++ b/trunk/include/linux/wireless.h @@ -677,19 +677,6 @@ struct iw_point __u16 flags; /* Optional params */ }; -#ifdef __KERNEL__ -#ifdef CONFIG_COMPAT - -#include - -struct compat_iw_point { - compat_caddr_t pointer; - __u16 length; - __u16 flags; -}; -#endif -#endif - /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and @@ -1113,21 +1100,6 @@ struct iw_event #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ IW_EV_POINT_OFF) -#ifdef __KERNEL__ -#ifdef CONFIG_COMPAT -struct __compat_iw_event { - __u16 len; /* Real length of this stuff */ - __u16 cmd; /* Wireless IOCTL */ - compat_caddr_t pointer; -}; -#define IW_EV_COMPAT_LCP_LEN offsetof(struct __compat_iw_event, pointer) -#define IW_EV_COMPAT_POINT_OFF offsetof(struct compat_iw_point, length) -#define IW_EV_COMPAT_POINT_LEN \ - (IW_EV_COMPAT_LCP_LEN + sizeof(struct compat_iw_point) - \ - IW_EV_COMPAT_POINT_OFF) -#endif -#endif - /* Size of the Event prefix when packed in stream */ #define IW_EV_LCP_PK_LEN (4) /* Size of the various events when packed in stream */ diff --git a/trunk/include/net/fib_rules.h b/trunk/include/net/fib_rules.h index c2bb5cae6515..a5c6ccc5bb19 100644 --- a/trunk/include/net/fib_rules.h +++ b/trunk/include/net/fib_rules.h @@ -62,7 +62,7 @@ struct fib_rules_ops /* Called after modifications to the rules set, must flush * the route cache if one exists. */ - void (*flush_cache)(struct fib_rules_ops *ops); + void (*flush_cache)(void); int nlgroup; const struct nla_policy *policy; diff --git a/trunk/include/net/ipv6.h b/trunk/include/net/ipv6.h index c2222ee74d66..7f7db8d57934 100644 --- a/trunk/include/net/ipv6.h +++ b/trunk/include/net/ipv6.h @@ -365,12 +365,6 @@ static inline int ipv6_addr_any(const struct in6_addr *a) a->s6_addr32[2] | a->s6_addr32[3] ) == 0); } -static inline int ipv6_addr_loopback(const struct in6_addr *a) -{ - return ((a->s6_addr32[0] | a->s6_addr32[1] | - a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0); -} - static inline int ipv6_addr_v4mapped(const struct in6_addr *a) { return ((a->s6_addr32[0] | a->s6_addr32[1] | diff --git a/trunk/include/net/iw_handler.h b/trunk/include/net/iw_handler.h index 51b9a37de991..369d50e08b99 100644 --- a/trunk/include/net/iw_handler.h +++ b/trunk/include/net/iw_handler.h @@ -256,7 +256,7 @@ #define EIWCOMMIT EINPROGRESS /* Flags available in struct iw_request_info */ -#define IW_REQUEST_FLAG_COMPAT 0x0001 /* Compat ioctl call */ +#define IW_REQUEST_FLAG_NONE 0x0000 /* No flag so far */ /* Type of headers we know about (basically union iwreq_data) */ #define IW_HEADER_TYPE_NULL 0 /* Not available */ @@ -478,58 +478,105 @@ extern void wireless_spy_update(struct net_device * dev, * Function that are so simple that it's more efficient inlining them */ -static inline int iwe_stream_lcp_len(struct iw_request_info *info) +/*------------------------------------------------------------------*/ +/* + * Wrapper to add an Wireless Event to a stream of events. + */ +static inline char * +iwe_stream_add_event(char * stream, /* Stream of events */ + char * ends, /* End of stream */ + struct iw_event *iwe, /* Payload */ + int event_len) /* Real size of payload */ { -#ifdef CONFIG_COMPAT - if (info->flags & IW_REQUEST_FLAG_COMPAT) - return IW_EV_COMPAT_LCP_LEN; -#endif - return IW_EV_LCP_LEN; + /* Check if it's possible */ + if(likely((stream + event_len) < ends)) { + iwe->len = event_len; + /* Beware of alignement issues on 64 bits */ + memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); + memcpy(stream + IW_EV_LCP_LEN, + ((char *) iwe) + IW_EV_LCP_LEN, + event_len - IW_EV_LCP_LEN); + stream += event_len; + } + return stream; } -static inline int iwe_stream_point_len(struct iw_request_info *info) +/*------------------------------------------------------------------*/ +/* + * Wrapper to add an short Wireless Event containing a pointer to a + * stream of events. + */ +static inline char * +iwe_stream_add_point(char * stream, /* Stream of events */ + char * ends, /* End of stream */ + struct iw_event *iwe, /* Payload length + flags */ + char * extra) /* More payload */ { -#ifdef CONFIG_COMPAT - if (info->flags & IW_REQUEST_FLAG_COMPAT) - return IW_EV_COMPAT_POINT_LEN; -#endif - return IW_EV_POINT_LEN; + int event_len = IW_EV_POINT_LEN + iwe->u.data.length; + /* Check if it's possible */ + if(likely((stream + event_len) < ends)) { + iwe->len = event_len; + memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); + memcpy(stream + IW_EV_LCP_LEN, + ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF, + IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); + memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length); + stream += event_len; + } + return stream; } -static inline int iwe_stream_event_len_adjust(struct iw_request_info *info, - int event_len) +/*------------------------------------------------------------------*/ +/* + * Wrapper to add a value to a Wireless Event in a stream of events. + * Be careful, this one is tricky to use properly : + * At the first run, you need to have (value = event + IW_EV_LCP_LEN). + */ +static inline char * +iwe_stream_add_value(char * event, /* Event in the stream */ + char * value, /* Value in event */ + char * ends, /* End of stream */ + struct iw_event *iwe, /* Payload */ + int event_len) /* Real size of payload */ { -#ifdef CONFIG_COMPAT - if (info->flags & IW_REQUEST_FLAG_COMPAT) { - event_len -= IW_EV_LCP_LEN; - event_len += IW_EV_COMPAT_LCP_LEN; - } -#endif + /* Don't duplicate LCP */ + event_len -= IW_EV_LCP_LEN; - return event_len; + /* Check if it's possible */ + if(likely((value + event_len) < ends)) { + /* Add new value */ + memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len); + value += event_len; + /* Patch LCP */ + iwe->len = value - event; + memcpy(event, (char *) iwe, IW_EV_LCP_LEN); + } + return value; } /*------------------------------------------------------------------*/ /* * Wrapper to add an Wireless Event to a stream of events. + * Same as above, with explicit error check... */ static inline char * -iwe_stream_add_event(struct iw_request_info *info, char *stream, char *ends, - struct iw_event *iwe, int event_len) +iwe_stream_check_add_event(char * stream, /* Stream of events */ + char * ends, /* End of stream */ + struct iw_event *iwe, /* Payload */ + int event_len, /* Size of payload */ + int * perr) /* Error report */ { - int lcp_len = iwe_stream_lcp_len(info); - - event_len = iwe_stream_event_len_adjust(info, event_len); - - /* Check if it's possible */ + /* Check if it's possible, set error if not */ if(likely((stream + event_len) < ends)) { iwe->len = event_len; /* Beware of alignement issues on 64 bits */ memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); - memcpy(stream + lcp_len, &iwe->u, - event_len - lcp_len); + memcpy(stream + IW_EV_LCP_LEN, + ((char *) iwe) + IW_EV_LCP_LEN, + event_len - IW_EV_LCP_LEN); stream += event_len; - } + } else + *perr = -E2BIG; return stream; } @@ -537,25 +584,27 @@ iwe_stream_add_event(struct iw_request_info *info, char *stream, char *ends, /* * Wrapper to add an short Wireless Event containing a pointer to a * stream of events. + * Same as above, with explicit error check... */ static inline char * -iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends, - struct iw_event *iwe, char *extra) +iwe_stream_check_add_point(char * stream, /* Stream of events */ + char * ends, /* End of stream */ + struct iw_event *iwe, /* Payload length + flags */ + char * extra, /* More payload */ + int * perr) /* Error report */ { - int event_len = iwe_stream_point_len(info) + iwe->u.data.length; - int point_len = iwe_stream_point_len(info); - int lcp_len = iwe_stream_lcp_len(info); - + int event_len = IW_EV_POINT_LEN + iwe->u.data.length; /* Check if it's possible */ if(likely((stream + event_len) < ends)) { iwe->len = event_len; memcpy(stream, (char *) iwe, IW_EV_LCP_PK_LEN); - memcpy(stream + lcp_len, - ((char *) &iwe->u) + IW_EV_POINT_OFF, + memcpy(stream + IW_EV_LCP_LEN, + ((char *) iwe) + IW_EV_LCP_LEN + IW_EV_POINT_OFF, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); - memcpy(stream + point_len, extra, iwe->u.data.length); + memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length); stream += event_len; - } + } else + *perr = -E2BIG; return stream; } @@ -564,25 +613,29 @@ iwe_stream_add_point(struct iw_request_info *info, char *stream, char *ends, * Wrapper to add a value to a Wireless Event in a stream of events. * Be careful, this one is tricky to use properly : * At the first run, you need to have (value = event + IW_EV_LCP_LEN). + * Same as above, with explicit error check... */ static inline char * -iwe_stream_add_value(struct iw_request_info *info, char *event, char *value, - char *ends, struct iw_event *iwe, int event_len) +iwe_stream_check_add_value(char * event, /* Event in the stream */ + char * value, /* Value in event */ + char * ends, /* End of stream */ + struct iw_event *iwe, /* Payload */ + int event_len, /* Size of payload */ + int * perr) /* Error report */ { - int lcp_len = iwe_stream_lcp_len(info); - /* Don't duplicate LCP */ event_len -= IW_EV_LCP_LEN; /* Check if it's possible */ if(likely((value + event_len) < ends)) { /* Add new value */ - memcpy(value, &iwe->u, event_len); + memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len); value += event_len; /* Patch LCP */ iwe->len = value - event; - memcpy(event, (char *) iwe, lcp_len); - } + memcpy(event, (char *) iwe, IW_EV_LCP_LEN); + } else + *perr = -E2BIG; return value; } diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index 02c79e6b309e..7ab4ff6159a2 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -595,12 +595,7 @@ enum ieee80211_key_flags { * @flags: key flags, see &enum ieee80211_key_flags. * @keyidx: the key index (0-3) * @keylen: key material length - * @key: key material. For ALG_TKIP the key is encoded as a 256-bit (32 byte) - * data block: - * - Temporal Encryption Key (128 bits) - * - Temporal Authenticator Tx MIC Key (64 bits) - * - Temporal Authenticator Rx MIC Key (64 bits) - * + * @key: key material */ struct ieee80211_key_conf { enum ieee80211_key_alg alg; @@ -738,11 +733,8 @@ enum ieee80211_hw_flags { * @conf: &struct ieee80211_conf, device configuration, don't use. * * @workqueue: single threaded workqueue available for driver use, - * allocated by mac80211 on registration and flushed when an - * interface is removed. - * NOTICE: All work performed on this workqueue should NEVER - * acquire the RTNL lock (i.e. Don't use the function - * ieee80211_iterate_active_interfaces()) + * allocated by mac80211 on registration and flushed on + * unregistration. * * @priv: pointer to private area that was allocated for driver use * along with this structure. diff --git a/trunk/include/net/net_namespace.h b/trunk/include/net/net_namespace.h index f90443045c70..8df751b3be55 100644 --- a/trunk/include/net/net_namespace.h +++ b/trunk/include/net/net_namespace.h @@ -95,11 +95,6 @@ extern struct list_head net_namespace_list; #ifdef CONFIG_NET_NS extern void __put_net(struct net *net); -static inline int net_alive(struct net *net) -{ - return net && atomic_read(&net->count); -} - static inline struct net *get_net(struct net *net) { atomic_inc(&net->count); @@ -130,12 +125,6 @@ int net_eq(const struct net *net1, const struct net *net2) return net1 == net2; } #else - -static inline int net_alive(struct net *net) -{ - return 1; -} - static inline struct net *get_net(struct net *net) { return net; diff --git a/trunk/include/net/netns/ipv4.h b/trunk/include/net/netns/ipv4.h index a6ed83853dcc..6ef90b5fafb3 100644 --- a/trunk/include/net/netns/ipv4.h +++ b/trunk/include/net/netns/ipv4.h @@ -18,7 +18,6 @@ struct netns_ipv4 { struct ctl_table_header *forw_hdr; struct ctl_table_header *frags_hdr; struct ctl_table_header *ipv4_hdr; - struct ctl_table_header *route_hdr; #endif struct ipv4_devconf *devconf_all; struct ipv4_devconf *devconf_dflt; @@ -46,8 +45,5 @@ struct netns_ipv4 { int sysctl_icmp_ratelimit; int sysctl_icmp_ratemask; int sysctl_icmp_errors_use_inbound_ifaddr; - - struct timer_list rt_secret_timer; - atomic_t rt_genid; }; #endif diff --git a/trunk/include/net/route.h b/trunk/include/net/route.h index 3140cc500854..fc836ff824cc 100644 --- a/trunk/include/net/route.h +++ b/trunk/include/net/route.h @@ -111,7 +111,7 @@ struct in_device; extern int ip_rt_init(void); extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, __be32 src, struct net_device *dev); -extern void rt_cache_flush(struct net *net, int how); +extern void rt_cache_flush(int how); extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk, int flags); diff --git a/trunk/include/net/wext.h b/trunk/include/net/wext.h index 6d76a39a9c5b..80b31d826b7a 100644 --- a/trunk/include/net/wext.h +++ b/trunk/include/net/wext.h @@ -12,8 +12,6 @@ extern int wext_proc_init(struct net *net); extern void wext_proc_exit(struct net *net); extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, void __user *arg); -extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, - unsigned long arg); #else static inline int wext_proc_init(struct net *net) { @@ -28,11 +26,6 @@ static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned { return -EINVAL; } -static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, - unsigned long arg) -{ - return -EINVAL; -} #endif #endif /* __NET_WEXT_H */ diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 472676dd550e..f6944ecd5b2e 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -2107,10 +2107,6 @@ int netif_receive_skb(struct sk_buff *skb) rcu_read_lock(); - /* Don't receive packets in an exiting network namespace */ - if (!net_alive(dev_net(skb->dev))) - goto out; - #ifdef CONFIG_NET_CLS_ACT if (skb->tc_verd & TC_NCLS) { skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); @@ -3038,7 +3034,7 @@ EXPORT_SYMBOL(dev_unicast_delete); /** * dev_unicast_add - add a secondary unicast address * @dev: device - * @addr: address to add + * @addr: address to delete * @alen: length of @addr * * Add a secondary unicast address to the device or increase diff --git a/trunk/net/core/ethtool.c b/trunk/net/core/ethtool.c index 14ada537f895..0133b5ebd545 100644 --- a/trunk/net/core/ethtool.c +++ b/trunk/net/core/ethtool.c @@ -209,36 +209,6 @@ static int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) return 0; } -static int ethtool_set_rxhash(struct net_device *dev, void __user *useraddr) -{ - struct ethtool_rxnfc cmd; - - if (!dev->ethtool_ops->set_rxhash) - return -EOPNOTSUPP; - - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - - return dev->ethtool_ops->set_rxhash(dev, &cmd); -} - -static int ethtool_get_rxhash(struct net_device *dev, void __user *useraddr) -{ - struct ethtool_rxnfc info; - - if (!dev->ethtool_ops->get_rxhash) - return -EOPNOTSUPP; - - if (copy_from_user(&info, useraddr, sizeof(info))) - return -EFAULT; - - dev->ethtool_ops->get_rxhash(dev, &info); - - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; -} - static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) { struct ethtool_regs regs; @@ -856,7 +826,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_GGSO: case ETHTOOL_GFLAGS: case ETHTOOL_GPFLAGS: - case ETHTOOL_GRXFH: break; default: if (!capable(CAP_NET_ADMIN)) @@ -1008,12 +977,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) rc = ethtool_set_value(dev, useraddr, dev->ethtool_ops->set_priv_flags); break; - case ETHTOOL_GRXFH: - rc = ethtool_get_rxhash(dev, useraddr); - break; - case ETHTOOL_SRXFH: - rc = ethtool_set_rxhash(dev, useraddr); - break; default: rc = -EOPNOTSUPP; } diff --git a/trunk/net/core/fib_rules.c b/trunk/net/core/fib_rules.c index 1c2943a119f3..e3e9ab0f74e3 100644 --- a/trunk/net/core/fib_rules.c +++ b/trunk/net/core/fib_rules.c @@ -69,7 +69,7 @@ static void rules_ops_put(struct fib_rules_ops *ops) static void flush_route_cache(struct fib_rules_ops *ops) { if (ops->flush_cache) - ops->flush_cache(ops); + ops->flush_cache(); } int fib_rules_register(struct fib_rules_ops *ops) diff --git a/trunk/net/core/net_namespace.c b/trunk/net/core/net_namespace.c index 7c52fe277b62..72b4c184dd84 100644 --- a/trunk/net/core/net_namespace.c +++ b/trunk/net/core/net_namespace.c @@ -140,9 +140,6 @@ static void cleanup_net(struct work_struct *work) struct pernet_operations *ops; struct net *net; - /* Be very certain incoming network packets will not find us */ - rcu_barrier(); - net = container_of(work, struct net, work); mutex_lock(&net_mutex); diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 7c571560e9d2..2df012be973d 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -1290,14 +1290,12 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, { unsigned int nr_pages = spd->nr_pages; unsigned int poff, plen, len, toff, tlen; - int headlen, seg, error = 0; + int headlen, seg; toff = *offset; tlen = *total_len; - if (!tlen) { - error = 1; + if (!tlen) goto err; - } /* * if the offset is greater than the linear part, go directly to @@ -1339,8 +1337,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, * just jump directly to update and return, no point * in going over fragments when the output is full. */ - error = spd_fill_page(spd, virt_to_page(p), plen, poff, skb); - if (error) + if (spd_fill_page(spd, virt_to_page(p), plen, poff, skb)) goto done; tlen -= plen; @@ -1370,8 +1367,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, if (!plen) break; - error = spd_fill_page(spd, f->page, plen, poff, skb); - if (error) + if (spd_fill_page(spd, f->page, plen, poff, skb)) break; tlen -= plen; @@ -1384,10 +1380,7 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, return 0; } err: - /* update the offset to reflect the linear part skip, if any */ - if (!error) - *offset = toff; - return error; + return 1; } /* diff --git a/trunk/net/decnet/dn_rules.c b/trunk/net/decnet/dn_rules.c index 14fbca55e908..5b7539b7fe0c 100644 --- a/trunk/net/decnet/dn_rules.c +++ b/trunk/net/decnet/dn_rules.c @@ -229,7 +229,7 @@ static u32 dn_fib_rule_default_pref(struct fib_rules_ops *ops) return 0; } -static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops) +static void dn_fib_rule_flush_cache(void) { dn_rt_cache_flush(-1); } diff --git a/trunk/net/ieee80211/ieee80211_wx.c b/trunk/net/ieee80211/ieee80211_wx.c index 973832dd7faf..822606b615ca 100644 --- a/trunk/net/ieee80211/ieee80211_wx.c +++ b/trunk/net/ieee80211/ieee80211_wx.c @@ -43,9 +43,8 @@ static const char *ieee80211_modes[] = { #define MAX_CUSTOM_LEN 64 static char *ieee80211_translate_scan(struct ieee80211_device *ieee, - char *start, char *stop, - struct ieee80211_network *network, - struct iw_request_info *info) + char *start, char *stop, + struct ieee80211_network *network) { char custom[MAX_CUSTOM_LEN]; char *p; @@ -58,7 +57,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN); /* Remaining entries will be displayed in the order we provide them */ @@ -67,19 +66,17 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, iwe.u.data.flags = 1; if (network->flags & NETWORK_EMPTY_ESSID) { iwe.u.data.length = sizeof(""); - start = iwe_stream_add_point(info, start, stop, - &iwe, ""); + start = iwe_stream_add_point(start, stop, &iwe, ""); } else { iwe.u.data.length = min(network->ssid_len, (u8) 32); - start = iwe_stream_add_point(info, start, stop, - &iwe, network->ssid); + start = iwe_stream_add_point(start, stop, &iwe, network->ssid); } /* Add the protocol name */ iwe.cmd = SIOCGIWNAME; snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_CHAR_LEN); /* Add mode */ iwe.cmd = SIOCGIWMODE; @@ -89,8 +86,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, else iwe.u.mode = IW_MODE_ADHOC; - start = iwe_stream_add_event(info, start, stop, - &iwe, IW_EV_UINT_LEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN); } /* Add channel and frequency */ @@ -99,7 +95,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel); iwe.u.freq.e = 6; iwe.u.freq.i = 0; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN); /* Add encryption capability */ iwe.cmd = SIOCGIWENCODE; @@ -108,13 +104,12 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - start = iwe_stream_add_point(info, start, stop, - &iwe, network->ssid); + start = iwe_stream_add_point(start, stop, &iwe, network->ssid); /* Add basic and extended rates */ /* Rate : stuffing multiple values in a single event require a bit * more of magic - Jean II */ - current_val = start + iwe_stream_lcp_len(info); + current_val = start + IW_EV_LCP_LEN; iwe.cmd = SIOCGIWRATE; /* Those two flags are ignored... */ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; @@ -129,19 +124,17 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, /* Bit rate given in 500 kb/s units (+ 0x80) */ iwe.u.bitrate.value = ((rate & 0x7f) * 500000); /* Add new value to event */ - current_val = iwe_stream_add_value(info, start, current_val, - stop, &iwe, IW_EV_PARAM_LEN); + current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN); } for (; j < network->rates_ex_len; j++) { rate = network->rates_ex[j] & 0x7F; /* Bit rate given in 500 kb/s units (+ 0x80) */ iwe.u.bitrate.value = ((rate & 0x7f) * 500000); /* Add new value to event */ - current_val = iwe_stream_add_value(info, start, current_val, - stop, &iwe, IW_EV_PARAM_LEN); + current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN); } /* Check if we added any rate */ - if ((current_val - start) > iwe_stream_lcp_len(info)) + if((current_val - start) > IW_EV_LCP_LEN) start = current_val; /* Add quality statistics */ @@ -188,14 +181,14 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, iwe.u.qual.level = network->stats.signal; } - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); + start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN); iwe.cmd = IWEVCUSTOM; p = custom; iwe.u.data.length = p - custom; if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); + start = iwe_stream_add_point(start, stop, &iwe, custom); memset(&iwe, 0, sizeof(iwe)); if (network->wpa_ie_len) { @@ -203,7 +196,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, memcpy(buf, network->wpa_ie, network->wpa_ie_len); iwe.cmd = IWEVGENIE; iwe.u.data.length = network->wpa_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); + start = iwe_stream_add_point(start, stop, &iwe, buf); } memset(&iwe, 0, sizeof(iwe)); @@ -212,7 +205,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, memcpy(buf, network->rsn_ie, network->rsn_ie_len); iwe.cmd = IWEVGENIE; iwe.u.data.length = network->rsn_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); + start = iwe_stream_add_point(start, stop, &iwe, buf); } /* Add EXTRA: Age to display seconds since last beacon/probe response @@ -224,7 +217,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, jiffies_to_msecs(jiffies - network->last_scanned)); iwe.u.data.length = p - custom; if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); + start = iwe_stream_add_point(start, stop, &iwe, custom); /* Add spectrum management information */ iwe.cmd = -1; @@ -245,7 +238,7 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, if (iwe.cmd == IWEVCUSTOM) { iwe.u.data.length = p - custom; - start = iwe_stream_add_point(info, start, stop, &iwe, custom); + start = iwe_stream_add_point(start, stop, &iwe, custom); } return start; @@ -279,8 +272,7 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee, if (ieee->scan_age == 0 || time_after(network->last_scanned + ieee->scan_age, jiffies)) - ev = ieee80211_translate_scan(ieee, ev, stop, network, - info); + ev = ieee80211_translate_scan(ieee, ev, stop, network); else IEEE80211_DEBUG_SCAN("Not showing network '%s (" "%s)' due to age (%dms).\n", diff --git a/trunk/net/ipv4/af_inet.c b/trunk/net/ipv4/af_inet.c index dc411335c14f..42bd24b64b57 100644 --- a/trunk/net/ipv4/af_inet.c +++ b/trunk/net/ipv4/af_inet.c @@ -1479,15 +1479,14 @@ static int __init inet_init(void) * Initialise the multicast router */ #if defined(CONFIG_IP_MROUTE) - if (ip_mr_init()) - printk(KERN_CRIT "inet_init: Cannot init ipv4 mroute\n"); + ip_mr_init(); #endif /* * Initialise per-cpu ipv4 mibs */ if (init_ipv4_mibs()) - printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); + printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ; ipv4_proc_init(); diff --git a/trunk/net/ipv4/arp.c b/trunk/net/ipv4/arp.c index 29df75a6bcc7..20c515a1be28 100644 --- a/trunk/net/ipv4/arp.c +++ b/trunk/net/ipv4/arp.c @@ -1197,7 +1197,7 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event, vo switch (event) { case NETDEV_CHANGEADDR: neigh_changeaddr(&arp_tbl, dev); - rt_cache_flush(dev_net(dev), 0); + rt_cache_flush(0); break; default: break; diff --git a/trunk/net/ipv4/devinet.c b/trunk/net/ipv4/devinet.c index 2e667e2f90df..9de2514946ca 100644 --- a/trunk/net/ipv4/devinet.c +++ b/trunk/net/ipv4/devinet.c @@ -1348,7 +1348,7 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write, dev_disable_lro(idev->dev); } rtnl_unlock(); - rt_cache_flush(net, 0); + rt_cache_flush(0); } } @@ -1362,10 +1362,9 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write, int *valp = ctl->data; int val = *valp; int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); - struct net *net = ctl->extra2; if (write && *valp != val) - rt_cache_flush(net, 0); + rt_cache_flush(0); return ret; } @@ -1376,10 +1375,9 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen, { int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp, newval, newlen); - struct net *net = table->extra2; if (ret == 1) - rt_cache_flush(net, 0); + rt_cache_flush(0); return ret; } diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index 65c1503f8cc8..5ad01d63f83b 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -144,7 +144,7 @@ static void fib_flush(struct net *net) } if (flushed) - rt_cache_flush(net, -1); + rt_cache_flush(-1); } /* @@ -897,22 +897,21 @@ static void fib_disable_ip(struct net_device *dev, int force) { if (fib_sync_down_dev(dev, force)) fib_flush(dev_net(dev)); - rt_cache_flush(dev_net(dev), 0); + rt_cache_flush(0); arp_ifdown(dev); } static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr) { struct in_ifaddr *ifa = (struct in_ifaddr*)ptr; - struct net_device *dev = ifa->ifa_dev->dev; switch (event) { case NETDEV_UP: fib_add_ifaddr(ifa); #ifdef CONFIG_IP_ROUTE_MULTIPATH - fib_sync_up(dev); + fib_sync_up(ifa->ifa_dev->dev); #endif - rt_cache_flush(dev_net(dev), -1); + rt_cache_flush(-1); break; case NETDEV_DOWN: fib_del_ifaddr(ifa); @@ -920,9 +919,9 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, /* Last address was deleted from this interface. Disable IP. */ - fib_disable_ip(dev, 1); + fib_disable_ip(ifa->ifa_dev->dev, 1); } else { - rt_cache_flush(dev_net(dev), -1); + rt_cache_flush(-1); } break; } @@ -950,14 +949,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo #ifdef CONFIG_IP_ROUTE_MULTIPATH fib_sync_up(dev); #endif - rt_cache_flush(dev_net(dev), -1); + rt_cache_flush(-1); break; case NETDEV_DOWN: fib_disable_ip(dev, 0); break; case NETDEV_CHANGEMTU: case NETDEV_CHANGE: - rt_cache_flush(dev_net(dev), 0); + rt_cache_flush(0); break; } return NOTIFY_DONE; diff --git a/trunk/net/ipv4/fib_hash.c b/trunk/net/ipv4/fib_hash.c index c8cac6c7f881..eeec4bf982b8 100644 --- a/trunk/net/ipv4/fib_hash.c +++ b/trunk/net/ipv4/fib_hash.c @@ -472,7 +472,7 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) fib_release_info(fi_drop); if (state & FA_S_ACCESSED) - rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); + rt_cache_flush(-1); rtmsg_fib(RTM_NEWROUTE, key, fa, cfg->fc_dst_len, tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE); return 0; @@ -532,7 +532,7 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) if (new_f) fz->fz_nent++; - rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); + rt_cache_flush(-1); rtmsg_fib(RTM_NEWROUTE, key, new_fa, cfg->fc_dst_len, tb->tb_id, &cfg->fc_nlinfo, 0); @@ -614,7 +614,7 @@ static int fn_hash_delete(struct fib_table *tb, struct fib_config *cfg) write_unlock_bh(&fib_hash_lock); if (fa->fa_state & FA_S_ACCESSED) - rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); + rt_cache_flush(-1); fn_free_alias(fa, f); if (kill_fn) { fn_free_node(f); diff --git a/trunk/net/ipv4/fib_rules.c b/trunk/net/ipv4/fib_rules.c index 6080d7120821..1fb56876be54 100644 --- a/trunk/net/ipv4/fib_rules.c +++ b/trunk/net/ipv4/fib_rules.c @@ -258,9 +258,9 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule) + nla_total_size(4); /* flow */ } -static void fib4_rule_flush_cache(struct fib_rules_ops *ops) +static void fib4_rule_flush_cache(void) { - rt_cache_flush(ops->fro_net, -1); + rt_cache_flush(-1); } static struct fib_rules_ops fib4_rules_ops_template = { diff --git a/trunk/net/ipv4/fib_trie.c b/trunk/net/ipv4/fib_trie.c index d16ae4623be6..394db9c941a1 100644 --- a/trunk/net/ipv4/fib_trie.c +++ b/trunk/net/ipv4/fib_trie.c @@ -1271,7 +1271,7 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) fib_release_info(fi_drop); if (state & FA_S_ACCESSED) - rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); + rt_cache_flush(-1); rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE); @@ -1316,7 +1316,7 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) list_add_tail_rcu(&new_fa->fa_list, (fa ? &fa->fa_list : fa_head)); - rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); + rt_cache_flush(-1); rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, &cfg->fc_nlinfo, 0); succeeded: @@ -1664,7 +1664,7 @@ static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) trie_leaf_remove(t, l); if (fa->fa_state & FA_S_ACCESSED) - rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); + rt_cache_flush(-1); fib_release_info(fa->fa_info); alias_free_mem_rcu(fa); diff --git a/trunk/net/ipv4/inet_fragment.c b/trunk/net/ipv4/inet_fragment.c index 0546a0bc97ea..4ed429bd5951 100644 --- a/trunk/net/ipv4/inet_fragment.c +++ b/trunk/net/ipv4/inet_fragment.c @@ -192,21 +192,14 @@ EXPORT_SYMBOL(inet_frag_evictor); static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, struct inet_frag_queue *qp_in, struct inet_frags *f, - void *arg) + unsigned int hash, void *arg) { struct inet_frag_queue *qp; #ifdef CONFIG_SMP struct hlist_node *n; #endif - unsigned int hash; write_lock(&f->lock); - /* - * While we stayed w/o the lock other CPU could update - * the rnd seed, so we need to re-calculate the hash - * chain. Fortunatelly the qp_in can be used to get one. - */ - hash = f->hashfn(qp_in); #ifdef CONFIG_SMP /* With SMP race we have to recheck hash table, because * such entry could be created on other cpu, while we @@ -254,7 +247,7 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, } static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, - struct inet_frags *f, void *arg) + struct inet_frags *f, void *arg, unsigned int hash) { struct inet_frag_queue *q; @@ -262,7 +255,7 @@ static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, if (q == NULL) return NULL; - return inet_frag_intern(nf, q, f, arg); + return inet_frag_intern(nf, q, f, hash, arg); } struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, @@ -271,6 +264,7 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, struct inet_frag_queue *q; struct hlist_node *n; + read_lock(&f->lock); hlist_for_each_entry(q, n, &f->hash[hash], list) { if (q->net == nf && f->match(q, key)) { atomic_inc(&q->refcnt); @@ -280,6 +274,6 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, } read_unlock(&f->lock); - return inet_frag_create(nf, f, key); + return inet_frag_create(nf, f, key, hash); } EXPORT_SYMBOL(inet_frag_find); diff --git a/trunk/net/ipv4/inet_lro.c b/trunk/net/ipv4/inet_lro.c index cfd034a2b96e..4a4d49fca1f2 100644 --- a/trunk/net/ipv4/inet_lro.c +++ b/trunk/net/ipv4/inet_lro.c @@ -383,7 +383,8 @@ static int __lro_proc_skb(struct net_lro_mgr *lro_mgr, struct sk_buff *skb, out2: /* send aggregated SKBs to stack */ lro_flush(lro_mgr, lro_desc); -out: +out: /* Original SKB has to be posted to stack */ + skb->ip_summed = lro_mgr->ip_summed; return 1; } diff --git a/trunk/net/ipv4/ip_fragment.c b/trunk/net/ipv4/ip_fragment.c index fbd5804b5d83..91e321407313 100644 --- a/trunk/net/ipv4/ip_fragment.c +++ b/trunk/net/ipv4/ip_fragment.c @@ -227,8 +227,6 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user) arg.iph = iph; arg.user = user; - - read_lock(&ip4_frags.lock); hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); diff --git a/trunk/net/ipv4/ipmr.c b/trunk/net/ipv4/ipmr.c index 438fab9c62a0..300ab0c2919e 100644 --- a/trunk/net/ipv4/ipmr.c +++ b/trunk/net/ipv4/ipmr.c @@ -1878,36 +1878,16 @@ static struct net_protocol pim_protocol = { * Setup for IP multicast routing */ -int __init ip_mr_init(void) +void __init ip_mr_init(void) { - int err; - mrt_cachep = kmem_cache_create("ip_mrt_cache", sizeof(struct mfc_cache), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); - if (!mrt_cachep) - return -ENOMEM; - setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); - err = register_netdevice_notifier(&ip_mr_notifier); - if (err) - goto reg_notif_fail; + register_netdevice_notifier(&ip_mr_notifier); #ifdef CONFIG_PROC_FS - err = -ENOMEM; - if (!proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops)) - goto proc_vif_fail; - if (!proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops)) - goto proc_cache_fail; + proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops); + proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops); #endif - return 0; -reg_notif_fail: - kmem_cache_destroy(mrt_cachep); -#ifdef CONFIG_PROC_FS -proc_vif_fail: - unregister_netdevice_notifier(&ip_mr_notifier); -proc_cache_fail: - proc_net_remove(&init_net, "ip_mr_vif"); -#endif - return err; } diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 113cd2512ba7..fe3a02237286 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -132,6 +132,7 @@ static int ip_rt_secret_interval __read_mostly = 10 * 60 * HZ; static void rt_worker_func(struct work_struct *work); static DECLARE_DELAYED_WORK(expires_work, rt_worker_func); +static struct timer_list rt_secret_timer; /* * Interface to generic destination cache. @@ -250,25 +251,20 @@ static inline void rt_hash_lock_init(void) static struct rt_hash_bucket *rt_hash_table __read_mostly; static unsigned rt_hash_mask __read_mostly; static unsigned int rt_hash_log __read_mostly; +static atomic_t rt_genid __read_mostly; static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); #define RT_CACHE_STAT_INC(field) \ (__raw_get_cpu_var(rt_cache_stat).field++) -static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx, - int genid) +static inline unsigned int rt_hash(__be32 daddr, __be32 saddr, int idx) { return jhash_3words((__force u32)(__be32)(daddr), (__force u32)(__be32)(saddr), - idx, genid) + idx, atomic_read(&rt_genid)) & rt_hash_mask; } -static inline int rt_genid(struct net *net) -{ - return atomic_read(&net->ipv4.rt_genid); -} - #ifdef CONFIG_PROC_FS struct rt_cache_iter_state { struct seq_net_private p; @@ -338,7 +334,7 @@ static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos) struct rt_cache_iter_state *st = seq->private; if (*pos) return rt_cache_get_idx(seq, *pos - 1); - st->genid = rt_genid(seq_file_net(seq)); + st->genid = atomic_read(&rt_genid); return SEQ_START_TOKEN; } @@ -685,11 +681,6 @@ static inline int compare_netns(struct rtable *rt1, struct rtable *rt2) return dev_net(rt1->u.dst.dev) == dev_net(rt2->u.dst.dev); } -static inline int rt_is_expired(struct rtable *rth) -{ - return rth->rt_genid != rt_genid(dev_net(rth->u.dst.dev)); -} - /* * Perform a full scan of hash table and free all entries. * Can be called by a softirq or a process. @@ -699,7 +690,6 @@ static void rt_do_flush(int process_context) { unsigned int i; struct rtable *rth, *next; - struct rtable * tail; for (i = 0; i <= rt_hash_mask; i++) { if (process_context && need_resched()) @@ -709,39 +699,11 @@ static void rt_do_flush(int process_context) continue; spin_lock_bh(rt_hash_lock_addr(i)); -#ifdef CONFIG_NET_NS - { - struct rtable ** prev, * p; - - rth = rt_hash_table[i].chain; - - /* defer releasing the head of the list after spin_unlock */ - for (tail = rth; tail; tail = tail->u.dst.rt_next) - if (!rt_is_expired(tail)) - break; - if (rth != tail) - rt_hash_table[i].chain = tail; - - /* call rt_free on entries after the tail requiring flush */ - prev = &rt_hash_table[i].chain; - for (p = *prev; p; p = next) { - next = p->u.dst.rt_next; - if (!rt_is_expired(p)) { - prev = &p->u.dst.rt_next; - } else { - *prev = next; - rt_free(p); - } - } - } -#else rth = rt_hash_table[i].chain; rt_hash_table[i].chain = NULL; - tail = NULL; -#endif spin_unlock_bh(rt_hash_lock_addr(i)); - for (; rth != tail; rth = next) { + for (; rth; rth = next) { next = rth->u.dst.rt_next; rt_free(rth); } @@ -774,7 +736,7 @@ static void rt_check_expire(void) continue; spin_lock_bh(rt_hash_lock_addr(i)); while ((rth = *rthp) != NULL) { - if (rt_is_expired(rth)) { + if (rth->rt_genid != atomic_read(&rt_genid)) { *rthp = rth->u.dst.rt_next; rt_free(rth); continue; @@ -817,21 +779,21 @@ static void rt_worker_func(struct work_struct *work) * many times (2^24) without giving recent rt_genid. * Jenkins hash is strong enough that litle changes of rt_genid are OK. */ -static void rt_cache_invalidate(struct net *net) +static void rt_cache_invalidate(void) { unsigned char shuffle; get_random_bytes(&shuffle, sizeof(shuffle)); - atomic_add(shuffle + 1U, &net->ipv4.rt_genid); + atomic_add(shuffle + 1U, &rt_genid); } /* * delay < 0 : invalidate cache (fast : entries will be deleted later) * delay >= 0 : invalidate & flush cache (can be long) */ -void rt_cache_flush(struct net *net, int delay) +void rt_cache_flush(int delay) { - rt_cache_invalidate(net); + rt_cache_invalidate(); if (delay >= 0) rt_do_flush(!in_softirq()); } @@ -839,11 +801,10 @@ void rt_cache_flush(struct net *net, int delay) /* * We change rt_genid and let gc do the cleanup */ -static void rt_secret_rebuild(unsigned long __net) +static void rt_secret_rebuild(unsigned long dummy) { - struct net *net = (struct net *)__net; - rt_cache_invalidate(net); - mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval); + rt_cache_invalidate(); + mod_timer(&rt_secret_timer, jiffies + ip_rt_secret_interval); } /* @@ -919,7 +880,7 @@ static int rt_garbage_collect(struct dst_ops *ops) rthp = &rt_hash_table[k].chain; spin_lock_bh(rt_hash_lock_addr(k)); while ((rth = *rthp) != NULL) { - if (!rt_is_expired(rth) && + if (rth->rt_genid == atomic_read(&rt_genid) && !rt_may_expire(rth, tmo, expire)) { tmo >>= 1; rthp = &rth->u.dst.rt_next; @@ -1001,7 +962,7 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp) spin_lock_bh(rt_hash_lock_addr(hash)); while ((rth = *rthp) != NULL) { - if (rt_is_expired(rth)) { + if (rth->rt_genid != atomic_read(&rt_genid)) { *rthp = rth->u.dst.rt_next; rt_free(rth); continue; @@ -1177,7 +1138,7 @@ static void rt_del(unsigned hash, struct rtable *rt) spin_lock_bh(rt_hash_lock_addr(hash)); ip_rt_put(rt); while ((aux = *rthp) != NULL) { - if (aux == rt || rt_is_expired(aux)) { + if (aux == rt || (aux->rt_genid != atomic_read(&rt_genid))) { *rthp = aux->u.dst.rt_next; rt_free(aux); continue; @@ -1219,8 +1180,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, for (i = 0; i < 2; i++) { for (k = 0; k < 2; k++) { - unsigned hash = rt_hash(daddr, skeys[i], ikeys[k], - rt_genid(net)); + unsigned hash = rt_hash(daddr, skeys[i], ikeys[k]); rthp=&rt_hash_table[hash].chain; @@ -1232,7 +1192,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, rth->fl.fl4_src != skeys[i] || rth->fl.oif != ikeys[k] || rth->fl.iif != 0 || - rt_is_expired(rth) || + rth->rt_genid != atomic_read(&rt_genid) || !net_eq(dev_net(rth->u.dst.dev), net)) { rthp = &rth->u.dst.rt_next; continue; @@ -1271,7 +1231,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, rt->u.dst.neighbour = NULL; rt->u.dst.hh = NULL; rt->u.dst.xfrm = NULL; - rt->rt_genid = rt_genid(net); + rt->rt_genid = atomic_read(&rt_genid); rt->rt_flags |= RTCF_REDIRECTED; /* Gateway is different ... */ @@ -1335,8 +1295,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) } else if ((rt->rt_flags & RTCF_REDIRECTED) || rt->u.dst.expires) { unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src, - rt->fl.oif, - rt_genid(dev_net(dst->dev))); + rt->fl.oif); #if RT_CACHE_DEBUG >= 1 printk(KERN_DEBUG "ipv4_negative_advice: redirect to " NIPQUAD_FMT "/%02x dropped\n", @@ -1485,8 +1444,7 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, for (k = 0; k < 2; k++) { for (i = 0; i < 2; i++) { - unsigned hash = rt_hash(daddr, skeys[i], ikeys[k], - rt_genid(net)); + unsigned hash = rt_hash(daddr, skeys[i], ikeys[k]); rcu_read_lock(); for (rth = rcu_dereference(rt_hash_table[hash].chain); rth; @@ -1501,7 +1459,7 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, rth->fl.iif != 0 || dst_metric_locked(&rth->u.dst, RTAX_MTU) || !net_eq(dev_net(rth->u.dst.dev), net) || - !rt_is_expired(rth)) + rth->rt_genid != atomic_read(&rt_genid)) continue; if (new_mtu < 68 || new_mtu >= old_mtu) { @@ -1736,7 +1694,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->fl.oif = 0; rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; - rth->rt_genid = rt_genid(dev_net(dev)); + rth->rt_genid = atomic_read(&rt_genid); rth->rt_flags = RTCF_MULTICAST; rth->rt_type = RTN_MULTICAST; if (our) { @@ -1751,7 +1709,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, RT_CACHE_STAT_INC(in_slow_mc); in_dev_put(in_dev); - hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev))); + hash = rt_hash(daddr, saddr, dev->ifindex); return rt_intern_hash(hash, rth, &skb->rtable); e_nobufs: @@ -1877,7 +1835,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->u.dst.input = ip_forward; rth->u.dst.output = ip_output; - rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev)); + rth->rt_genid = atomic_read(&rt_genid); rt_set_nexthop(rth, res, itag); @@ -1912,8 +1870,7 @@ static int ip_mkroute_input(struct sk_buff *skb, return err; /* put it into the cache */ - hash = rt_hash(daddr, saddr, fl->iif, - rt_genid(dev_net(rth->u.dst.dev))); + hash = rt_hash(daddr, saddr, fl->iif); return rt_intern_hash(hash, rth, &skb->rtable); } @@ -2039,7 +1996,7 @@ out: return err; goto e_nobufs; rth->u.dst.output= ip_rt_bug; - rth->rt_genid = rt_genid(net); + rth->rt_genid = atomic_read(&rt_genid); atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; @@ -2069,7 +2026,7 @@ out: return err; rth->rt_flags &= ~RTCF_LOCAL; } rth->rt_type = res.type; - hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net)); + hash = rt_hash(daddr, saddr, fl.iif); err = rt_intern_hash(hash, rth, &skb->rtable); goto done; @@ -2120,7 +2077,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, net = dev_net(dev); tos &= IPTOS_RT_MASK; - hash = rt_hash(daddr, saddr, iif, rt_genid(net)); + hash = rt_hash(daddr, saddr, iif); rcu_read_lock(); for (rth = rcu_dereference(rt_hash_table[hash].chain); rth; @@ -2132,7 +2089,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr, (rth->fl.fl4_tos ^ tos)) == 0 && rth->fl.mark == skb->mark && net_eq(dev_net(rth->u.dst.dev), net) && - !rt_is_expired(rth)) { + rth->rt_genid == atomic_read(&rt_genid)) { dst_use(&rth->u.dst, jiffies); RT_CACHE_STAT_INC(in_hit); rcu_read_unlock(); @@ -2260,7 +2217,7 @@ static int __mkroute_output(struct rtable **result, rth->rt_spec_dst= fl->fl4_src; rth->u.dst.output=ip_output; - rth->rt_genid = rt_genid(dev_net(dev_out)); + rth->rt_genid = atomic_read(&rt_genid); RT_CACHE_STAT_INC(out_slow_tot); @@ -2309,8 +2266,7 @@ static int ip_mkroute_output(struct rtable **rp, int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags); unsigned hash; if (err == 0) { - hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif, - rt_genid(dev_net(dev_out))); + hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif); err = rt_intern_hash(hash, rth, rp); } @@ -2522,7 +2478,7 @@ int __ip_route_output_key(struct net *net, struct rtable **rp, unsigned hash; struct rtable *rth; - hash = rt_hash(flp->fl4_dst, flp->fl4_src, flp->oif, rt_genid(net)); + hash = rt_hash(flp->fl4_dst, flp->fl4_src, flp->oif); rcu_read_lock_bh(); for (rth = rcu_dereference(rt_hash_table[hash].chain); rth; @@ -2535,7 +2491,7 @@ int __ip_route_output_key(struct net *net, struct rtable **rp, !((rth->fl.fl4_tos ^ flp->fl4_tos) & (IPTOS_RT_MASK | RTO_ONLINK)) && net_eq(dev_net(rth->u.dst.dev), net) && - !rt_is_expired(rth)) { + rth->rt_genid == atomic_read(&rt_genid)) { dst_use(&rth->u.dst, jiffies); RT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); @@ -2566,7 +2522,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { }; -static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi *flp) +static int ipv4_dst_blackhole(struct rtable **rp, struct flowi *flp) { struct rtable *ort = *rp; struct rtable *rt = (struct rtable *) @@ -2590,7 +2546,7 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi rt->idev = ort->idev; if (rt->idev) in_dev_hold(rt->idev); - rt->rt_genid = rt_genid(net); + rt->rt_genid = atomic_read(&rt_genid); rt->rt_flags = ort->rt_flags; rt->rt_type = ort->rt_type; rt->rt_dst = ort->rt_dst; @@ -2626,7 +2582,7 @@ int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp, err = __xfrm_lookup((struct dst_entry **)rp, flp, sk, flags ? XFRM_LOOKUP_WAIT : 0); if (err == -EREMOTE) - err = ipv4_dst_blackhole(net, rp, flp); + err = ipv4_dst_blackhole(rp, flp); return err; } @@ -2845,7 +2801,7 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) rt = rcu_dereference(rt->u.dst.rt_next), idx++) { if (!net_eq(dev_net(rt->u.dst.dev), net) || idx < s_idx) continue; - if (rt_is_expired(rt)) + if (rt->rt_genid != atomic_read(&rt_genid)) continue; skb->dst = dst_clone(&rt->u.dst); if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid, @@ -2869,27 +2825,19 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) void ip_rt_multicast_event(struct in_device *in_dev) { - rt_cache_flush(dev_net(in_dev->dev), 0); + rt_cache_flush(0); } #ifdef CONFIG_SYSCTL +static int flush_delay; + static int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) { if (write) { - int flush_delay; - struct net *net; - static DEFINE_MUTEX(flush_mutex); - - mutex_lock(&flush_mutex); - ctl->data = &flush_delay; proc_dointvec(ctl, write, filp, buffer, lenp, ppos); - ctl->data = NULL; - mutex_unlock(&flush_mutex); - - net = (struct net *)ctl->extra1; - rt_cache_flush(net, flush_delay); + rt_cache_flush(flush_delay); return 0; } @@ -2905,17 +2853,24 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, size_t newlen) { int delay; - struct net *net; if (newlen != sizeof(int)) return -EINVAL; if (get_user(delay, (int __user *)newval)) return -EFAULT; - net = (struct net *)table->extra1; - rt_cache_flush(net, delay); + rt_cache_flush(delay); return 0; } ctl_table ipv4_route_table[] = { + { + .ctl_name = NET_IPV4_ROUTE_FLUSH, + .procname = "flush", + .data = &flush_delay, + .maxlen = sizeof(int), + .mode = 0200, + .proc_handler = &ipv4_sysctl_rtcache_flush, + .strategy = &ipv4_sysctl_rtcache_flush_strategy, + }, { .ctl_name = NET_IPV4_ROUTE_GC_THRESH, .procname = "gc_thresh", @@ -3054,97 +3009,8 @@ ctl_table ipv4_route_table[] = { }, { .ctl_name = 0 } }; - -static __net_initdata struct ctl_path ipv4_route_path[] = { - { .procname = "net", .ctl_name = CTL_NET, }, - { .procname = "ipv4", .ctl_name = NET_IPV4, }, - { .procname = "route", .ctl_name = NET_IPV4_ROUTE, }, - { }, -}; - - -static struct ctl_table ipv4_route_flush_table[] = { - { - .ctl_name = NET_IPV4_ROUTE_FLUSH, - .procname = "flush", - .maxlen = sizeof(int), - .mode = 0200, - .proc_handler = &ipv4_sysctl_rtcache_flush, - .strategy = &ipv4_sysctl_rtcache_flush_strategy, - }, - { .ctl_name = 0 }, -}; - -static __net_init int sysctl_route_net_init(struct net *net) -{ - struct ctl_table *tbl; - - tbl = ipv4_route_flush_table; - if (net != &init_net) { - tbl = kmemdup(tbl, sizeof(ipv4_route_flush_table), GFP_KERNEL); - if (tbl == NULL) - goto err_dup; - } - tbl[0].extra1 = net; - - net->ipv4.route_hdr = - register_net_sysctl_table(net, ipv4_route_path, tbl); - if (net->ipv4.route_hdr == NULL) - goto err_reg; - return 0; - -err_reg: - if (tbl != ipv4_route_flush_table) - kfree(tbl); -err_dup: - return -ENOMEM; -} - -static __net_exit void sysctl_route_net_exit(struct net *net) -{ - struct ctl_table *tbl; - - tbl = net->ipv4.route_hdr->ctl_table_arg; - unregister_net_sysctl_table(net->ipv4.route_hdr); - BUG_ON(tbl == ipv4_route_flush_table); - kfree(tbl); -} - -static __net_initdata struct pernet_operations sysctl_route_ops = { - .init = sysctl_route_net_init, - .exit = sysctl_route_net_exit, -}; #endif - -static __net_init int rt_secret_timer_init(struct net *net) -{ - atomic_set(&net->ipv4.rt_genid, - (int) ((num_physpages ^ (num_physpages>>8)) ^ - (jiffies ^ (jiffies >> 7)))); - - net->ipv4.rt_secret_timer.function = rt_secret_rebuild; - net->ipv4.rt_secret_timer.data = (unsigned long)net; - init_timer_deferrable(&net->ipv4.rt_secret_timer); - - net->ipv4.rt_secret_timer.expires = - jiffies + net_random() % ip_rt_secret_interval + - ip_rt_secret_interval; - add_timer(&net->ipv4.rt_secret_timer); - return 0; -} - -static __net_exit void rt_secret_timer_exit(struct net *net) -{ - del_timer_sync(&net->ipv4.rt_secret_timer); -} - -static __net_initdata struct pernet_operations rt_secret_timer_ops = { - .init = rt_secret_timer_init, - .exit = rt_secret_timer_exit, -}; - - #ifdef CONFIG_NET_CLS_ROUTE struct ip_rt_acct *ip_rt_acct __read_mostly; #endif /* CONFIG_NET_CLS_ROUTE */ @@ -3163,6 +3029,9 @@ int __init ip_rt_init(void) { int rc = 0; + atomic_set(&rt_genid, (int) ((num_physpages ^ (num_physpages>>8)) ^ + (jiffies ^ (jiffies >> 7)))); + #ifdef CONFIG_NET_CLS_ROUTE ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct)); if (!ip_rt_acct) @@ -3194,14 +3063,19 @@ int __init ip_rt_init(void) devinet_init(); ip_fib_init(); + rt_secret_timer.function = rt_secret_rebuild; + rt_secret_timer.data = 0; + init_timer_deferrable(&rt_secret_timer); + /* All the timers, started at system startup tend to synchronize. Perturb it a bit. */ schedule_delayed_work(&expires_work, net_random() % ip_rt_gc_interval + ip_rt_gc_interval); - if (register_pernet_subsys(&rt_secret_timer_ops)) - printk(KERN_ERR "Unable to setup rt_secret_timer\n"); + rt_secret_timer.expires = jiffies + net_random() % ip_rt_secret_interval + + ip_rt_secret_interval; + add_timer(&rt_secret_timer); if (ip_rt_proc_init()) printk(KERN_ERR "Unable to create route proc files\n"); @@ -3211,9 +3085,6 @@ int __init ip_rt_init(void) #endif rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL); -#ifdef CONFIG_SYSCTL - register_pernet_subsys(&sysctl_route_ops); -#endif return rc; } diff --git a/trunk/net/ipv4/sysctl_net_ipv4.c b/trunk/net/ipv4/sysctl_net_ipv4.c index 14ef202a2254..901607003205 100644 --- a/trunk/net/ipv4/sysctl_net_ipv4.c +++ b/trunk/net/ipv4/sysctl_net_ipv4.c @@ -793,8 +793,7 @@ static struct ctl_table ipv4_net_table[] = { .data = &init_net.ipv4.sysctl_icmp_ratelimit, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_ms_jiffies, - .strategy = &sysctl_ms_jiffies + .proc_handler = &proc_dointvec }, { .ctl_name = NET_IPV4_ICMP_RATEMASK, diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index c66ac83316e8..cf0850c068f5 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -258,8 +258,6 @@ #include #include #include -#include -#include #include #include #include @@ -2690,7 +2688,7 @@ __setup("thash_entries=", set_thash_entries); void __init tcp_init(void) { struct sk_buff *skb = NULL; - unsigned long nr_pages, limit; + unsigned long limit; int order, i, max_share; BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); @@ -2759,9 +2757,8 @@ void __init tcp_init(void) * is up to 1/2 at 256 MB, decreasing toward zero with the amount of * memory, with a floor of 128 pages. */ - nr_pages = totalram_pages - totalhigh_pages; - limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); - limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); + limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); + limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); limit = max(limit, 128UL); sysctl_tcp_mem[0] = limit / 4 * 3; sysctl_tcp_mem[1] = limit; diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index d6ea970a1513..de30e70ff256 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -947,21 +947,17 @@ static void tcp_update_reordering(struct sock *sk, const int metric, { struct tcp_sock *tp = tcp_sk(sk); if (metric > tp->reordering) { - int mib_idx; - tp->reordering = min(TCP_MAX_REORDERING, metric); /* This exciting event is worth to be remembered. 8) */ if (ts) - mib_idx = LINUX_MIB_TCPTSREORDER; + NET_INC_STATS_BH(LINUX_MIB_TCPTSREORDER); else if (tcp_is_reno(tp)) - mib_idx = LINUX_MIB_TCPRENOREORDER; + NET_INC_STATS_BH(LINUX_MIB_TCPRENOREORDER); else if (tcp_is_fack(tp)) - mib_idx = LINUX_MIB_TCPFACKREORDER; + NET_INC_STATS_BH(LINUX_MIB_TCPFACKREORDER); else - mib_idx = LINUX_MIB_TCPSACKREORDER; - - NET_INC_STATS_BH(mib_idx); + NET_INC_STATS_BH(LINUX_MIB_TCPSACKREORDER); #if FASTRETRANS_DEBUG > 1 printk(KERN_DEBUG "Disorder%d %d %u f%u s%u rr%d\n", tp->rx_opt.sack_ok, inet_csk(sk)->icsk_ca_state, @@ -1460,22 +1456,18 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, if (!tcp_is_sackblock_valid(tp, dup_sack, sp[used_sacks].start_seq, sp[used_sacks].end_seq)) { - int mib_idx; - if (dup_sack) { if (!tp->undo_marker) - mib_idx = LINUX_MIB_TCPDSACKIGNOREDNOUNDO; + NET_INC_STATS_BH(LINUX_MIB_TCPDSACKIGNOREDNOUNDO); else - mib_idx = LINUX_MIB_TCPDSACKIGNOREDOLD; + NET_INC_STATS_BH(LINUX_MIB_TCPDSACKIGNOREDOLD); } else { /* Don't count olds caused by ACK reordering */ if ((TCP_SKB_CB(ack_skb)->ack_seq != tp->snd_una) && !after(sp[used_sacks].end_seq, tp->snd_una)) continue; - mib_idx = LINUX_MIB_TCPSACKDISCARD; + NET_INC_STATS_BH(LINUX_MIB_TCPSACKDISCARD); } - - NET_INC_STATS_BH(mib_idx); if (i == 0) first_sack_index = -1; continue; @@ -2388,19 +2380,15 @@ static int tcp_try_undo_recovery(struct sock *sk) struct tcp_sock *tp = tcp_sk(sk); if (tcp_may_undo(tp)) { - int mib_idx; - /* Happy end! We did not retransmit anything * or our original transmission succeeded. */ DBGUNDO(sk, inet_csk(sk)->icsk_ca_state == TCP_CA_Loss ? "loss" : "retrans"); tcp_undo_cwr(sk, 1); if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss) - mib_idx = LINUX_MIB_TCPLOSSUNDO; + NET_INC_STATS_BH(LINUX_MIB_TCPLOSSUNDO); else - mib_idx = LINUX_MIB_TCPFULLUNDO; - - NET_INC_STATS_BH(mib_idx); + NET_INC_STATS_BH(LINUX_MIB_TCPFULLUNDO); tp->undo_marker = 0; } if (tp->snd_una == tp->high_seq && tcp_is_reno(tp)) { @@ -2572,7 +2560,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag) int is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && (tcp_fackets_out(tp) > tp->reordering)); - int fast_rexmit = 0, mib_idx; + int fast_rexmit = 0; if (WARN_ON(!tp->packets_out && tp->sacked_out)) tp->sacked_out = 0; @@ -2695,11 +2683,9 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag) /* Otherwise enter Recovery state */ if (tcp_is_reno(tp)) - mib_idx = LINUX_MIB_TCPRENORECOVERY; + NET_INC_STATS_BH(LINUX_MIB_TCPRENORECOVERY); else - mib_idx = LINUX_MIB_TCPSACKRECOVERY; - - NET_INC_STATS_BH(mib_idx); + NET_INC_STATS_BH(LINUX_MIB_TCPSACKRECOVERY); tp->high_seq = tp->snd_nxt; tp->prior_ssthresh = 0; @@ -3714,14 +3700,10 @@ static inline int tcp_sack_extend(struct tcp_sack_block *sp, u32 seq, static void tcp_dsack_set(struct tcp_sock *tp, u32 seq, u32 end_seq) { if (tcp_is_sack(tp) && sysctl_tcp_dsack) { - int mib_idx; - if (before(seq, tp->rcv_nxt)) - mib_idx = LINUX_MIB_TCPDSACKOLDSENT; + NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOLDSENT); else - mib_idx = LINUX_MIB_TCPDSACKOFOSENT; - - NET_INC_STATS_BH(mib_idx); + NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFOSENT); tp->rx_opt.dsack = 1; tp->duplicate_sack[0].start_seq = seq; diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index 4300bcf2ceaf..0db9b75c1fa2 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -2189,7 +2189,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) } seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " - "%08X %5d %8d %lu %d %p %lu %lu %u %u %d%n", + "%08X %5d %8d %lu %d %p %u %u %u %u %d%n", i, src, srcp, dest, destp, sk->sk_state, tp->write_seq - tp->snd_una, sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog : @@ -2201,8 +2201,8 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) icsk->icsk_probes_out, sock_i_ino(sk), atomic_read(&sk->sk_refcnt), sk, - jiffies_to_clock_t(icsk->icsk_rto), - jiffies_to_clock_t(icsk->icsk_ack.ato), + icsk->icsk_rto, + icsk->icsk_ack.ato, (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong, tp->snd_cwnd, tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh, diff --git a/trunk/net/ipv4/tcp_output.c b/trunk/net/ipv4/tcp_output.c index edef2afe905e..8f83ab432705 100644 --- a/trunk/net/ipv4/tcp_output.c +++ b/trunk/net/ipv4/tcp_output.c @@ -1985,17 +1985,14 @@ void tcp_xmit_retransmit_queue(struct sock *sk) if (sacked & TCPCB_LOST) { if (!(sacked & (TCPCB_SACKED_ACKED|TCPCB_SACKED_RETRANS))) { - int mib_idx; - if (tcp_retransmit_skb(sk, skb)) { tp->retransmit_skb_hint = NULL; return; } if (icsk->icsk_ca_state != TCP_CA_Loss) - mib_idx = LINUX_MIB_TCPFASTRETRANS; + NET_INC_STATS_BH(LINUX_MIB_TCPFASTRETRANS); else - mib_idx = LINUX_MIB_TCPSLOWSTARTRETRANS; - NET_INC_STATS_BH(mib_idx); + NET_INC_STATS_BH(LINUX_MIB_TCPSLOWSTARTRETRANS); if (skb == tcp_write_queue_head(sk)) inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, diff --git a/trunk/net/ipv4/tcp_timer.c b/trunk/net/ipv4/tcp_timer.c index 6a480d1fd8f6..3e358cbb1247 100644 --- a/trunk/net/ipv4/tcp_timer.c +++ b/trunk/net/ipv4/tcp_timer.c @@ -326,27 +326,24 @@ static void tcp_retransmit_timer(struct sock *sk) goto out; if (icsk->icsk_retransmits == 0) { - int mib_idx; - if (icsk->icsk_ca_state == TCP_CA_Disorder || icsk->icsk_ca_state == TCP_CA_Recovery) { if (tcp_is_sack(tp)) { if (icsk->icsk_ca_state == TCP_CA_Recovery) - mib_idx = LINUX_MIB_TCPSACKRECOVERYFAIL; + NET_INC_STATS_BH(LINUX_MIB_TCPSACKRECOVERYFAIL); else - mib_idx = LINUX_MIB_TCPSACKFAILURES; + NET_INC_STATS_BH(LINUX_MIB_TCPSACKFAILURES); } else { if (icsk->icsk_ca_state == TCP_CA_Recovery) - mib_idx = LINUX_MIB_TCPRENORECOVERYFAIL; + NET_INC_STATS_BH(LINUX_MIB_TCPRENORECOVERYFAIL); else - mib_idx = LINUX_MIB_TCPRENOFAILURES; + NET_INC_STATS_BH(LINUX_MIB_TCPRENOFAILURES); } } else if (icsk->icsk_ca_state == TCP_CA_Loss) { - mib_idx = LINUX_MIB_TCPLOSSFAILURES; + NET_INC_STATS_BH(LINUX_MIB_TCPLOSSFAILURES); } else { - mib_idx = LINUX_MIB_TCPTIMEOUTS; + NET_INC_STATS_BH(LINUX_MIB_TCPTIMEOUTS); } - NET_INC_STATS_BH(mib_idx); } if (tcp_use_frto(sk)) { diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 2ec73e62202c..84127d854cfc 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -119,7 +119,6 @@ static void ipv6_regen_rndid(unsigned long data); static int desync_factor = MAX_DESYNC_FACTOR * HZ; #endif -static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); static int ipv6_count_addresses(struct inet6_dev *idev); /* @@ -184,8 +183,6 @@ struct ipv6_devconf ipv6_devconf __read_mostly = { #endif .proxy_ndp = 0, .accept_source_route = 0, /* we do not accept RH0 by default. */ - .disable_ipv6 = 0, - .accept_dad = 1, }; static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { @@ -218,8 +215,6 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { #endif .proxy_ndp = 0, .accept_source_route = 0, /* we do not accept RH0 by default. */ - .disable_ipv6 = 0, - .accept_dad = 1, }; /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ @@ -383,9 +378,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) */ in6_dev_hold(ndev); - if (dev->flags & (IFF_NOARP | IFF_LOOPBACK)) - ndev->cnf.accept_dad = -1; - #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) { printk(KERN_INFO @@ -586,13 +578,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, struct rt6_info *rt; int hash; int err = 0; - int addr_type = ipv6_addr_type(addr); - - if (addr_type == IPV6_ADDR_ANY || - addr_type & IPV6_ADDR_MULTICAST || - (!(idev->dev->flags & IFF_LOOPBACK) && - addr_type & IPV6_ADDR_LOOPBACK)) - return ERR_PTR(-EADDRNOTAVAIL); rcu_read_lock_bh(); if (idev->dead) { @@ -1427,20 +1412,6 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp) void addrconf_dad_failure(struct inet6_ifaddr *ifp) { - struct inet6_dev *idev = ifp->idev; - if (idev->cnf.accept_dad > 1 && !idev->cnf.disable_ipv6) { - struct in6_addr addr; - - addr.s6_addr32[0] = htonl(0xfe800000); - addr.s6_addr32[1] = 0; - - if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) && - ipv6_addr_equal(&ifp->addr, &addr)) { - /* DAD failed for link-local based on MAC address */ - idev->cnf.disable_ipv6 = 1; - } - } - if (net_ratelimit()) printk(KERN_INFO "%s: duplicate address detected!\n", ifp->idev->dev->name); addrconf_dad_stop(ifp); @@ -2773,7 +2744,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) spin_lock_bh(&ifp->lock); if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || - idev->cnf.accept_dad < 1 || !(ifp->flags&IFA_F_TENTATIVE) || ifp->flags & IFA_F_NODAD) { ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC); @@ -2821,11 +2791,6 @@ static void addrconf_dad_timer(unsigned long data) read_unlock_bh(&idev->lock); goto out; } - if (idev->cnf.accept_dad > 1 && idev->cnf.disable_ipv6) { - read_unlock_bh(&idev->lock); - addrconf_dad_failure(ifp); - return; - } spin_lock_bh(&ifp->lock); if (ifp->probes == 0) { /* @@ -3685,8 +3650,6 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, #ifdef CONFIG_IPV6_MROUTE array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding; #endif - array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6; - array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad; } static inline size_t inet6_if_nlmsg_size(void) @@ -4245,22 +4208,6 @@ static struct addrconf_sysctl_table .proc_handler = &proc_dointvec, }, #endif - { - .ctl_name = CTL_UNNUMBERED, - .procname = "disable_ipv6", - .data = &ipv6_devconf.disable_ipv6, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "accept_dad", - .data = &ipv6_devconf.accept_dad, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, { .ctl_name = 0, /* sentinel */ } diff --git a/trunk/net/ipv6/af_inet6.c b/trunk/net/ipv6/af_inet6.c index 3d828bc4b1cf..3ce8d2f318c6 100644 --- a/trunk/net/ipv6/af_inet6.c +++ b/trunk/net/ipv6/af_inet6.c @@ -59,7 +59,9 @@ #include #include +#ifdef CONFIG_IPV6_MROUTE #include +#endif MODULE_AUTHOR("Cast of dozens"); MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); @@ -950,9 +952,9 @@ static int __init inet6_init(void) err = icmpv6_init(); if (err) goto icmp_fail; - err = ip6_mr_init(); - if (err) - goto ipmr_fail; +#ifdef CONFIG_IPV6_MROUTE + ip6_mr_init(); +#endif err = ndisc_init(); if (err) goto ndisc_fail; @@ -1055,8 +1057,6 @@ static int __init inet6_init(void) igmp_fail: ndisc_cleanup(); ndisc_fail: - ip6_mr_cleanup(); -ipmr_fail: icmpv6_cleanup(); icmp_fail: unregister_pernet_subsys(&inet6_net_ops); @@ -1111,7 +1111,6 @@ static void __exit inet6_exit(void) ipv6_netfilter_fini(); igmp6_cleanup(); ndisc_cleanup(); - ip6_mr_cleanup(); icmpv6_cleanup(); rawv6_exit(); diff --git a/trunk/net/ipv6/icmp.c b/trunk/net/ipv6/icmp.c index abedf95fdf2d..399d41f65437 100644 --- a/trunk/net/ipv6/icmp.c +++ b/trunk/net/ipv6/icmp.c @@ -954,8 +954,7 @@ ctl_table ipv6_icmp_table_template[] = { .data = &init_net.ipv6.sysctl.icmpv6_time, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_ms_jiffies, - .strategy = &sysctl_ms_jiffies + .proc_handler = &proc_dointvec }, { .ctl_name = 0 }, }; diff --git a/trunk/net/ipv6/ip6_input.c b/trunk/net/ipv6/ip6_input.c index ea81c614dde2..f77a6011c302 100644 --- a/trunk/net/ipv6/ip6_input.c +++ b/trunk/net/ipv6/ip6_input.c @@ -71,8 +71,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES); - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL || - !idev || unlikely(idev->cnf.disable_ipv6)) { + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); rcu_read_unlock(); goto out; @@ -101,15 +100,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (hdr->version != 6) goto err; - /* - * RFC4291 2.5.3 - * A packet received on an interface with a destination address - * of loopback must be dropped. - */ - if (!(dev->flags & IFF_LOOPBACK) && - ipv6_addr_loopback(&hdr->daddr)) - goto err; - skb->transport_header = skb->network_header + sizeof(*hdr); IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index 0981c1ef3057..fd7cd1bfe151 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -173,13 +173,6 @@ static inline int ip6_skb_dst_mtu(struct sk_buff *skb) int ip6_output(struct sk_buff *skb) { - struct inet6_dev *idev = ip6_dst_idev(skb->dst); - if (unlikely(idev->cnf.disable_ipv6)) { - IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); - kfree_skb(skb); - return 0; - } - if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || dst_allfrag(skb->dst)) return ip6_fragment(skb, ip6_output2); @@ -505,8 +498,7 @@ int ip6_forward(struct sk_buff *skb) int addrtype = ipv6_addr_type(&hdr->saddr); /* This check is security critical. */ - if (addrtype == IPV6_ADDR_ANY || - addrtype & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LOOPBACK)) + if (addrtype & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK)) goto error; if (addrtype & IPV6_ADDR_LINKLOCAL) { icmpv6_send(skb, ICMPV6_DEST_UNREACH, diff --git a/trunk/net/ipv6/ip6mr.c b/trunk/net/ipv6/ip6mr.c index cfac26d674ed..90e763073dc5 100644 --- a/trunk/net/ipv6/ip6mr.c +++ b/trunk/net/ipv6/ip6mr.c @@ -948,51 +948,23 @@ static struct notifier_block ip6_mr_notifier = { * Setup for IP multicast routing */ -int __init ip6_mr_init(void) +void __init ip6_mr_init(void) { - int err; - mrt_cachep = kmem_cache_create("ip6_mrt_cache", sizeof(struct mfc6_cache), 0, SLAB_HWCACHE_ALIGN, NULL); if (!mrt_cachep) - return -ENOMEM; + panic("cannot allocate ip6_mrt_cache"); setup_timer(&ipmr_expire_timer, ipmr_expire_process, 0); - err = register_netdevice_notifier(&ip6_mr_notifier); - if (err) - goto reg_notif_fail; -#ifdef CONFIG_PROC_FS - err = -ENOMEM; - if (!proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops)) - goto proc_vif_fail; - if (!proc_net_fops_create(&init_net, "ip6_mr_cache", - 0, &ip6mr_mfc_fops)) - goto proc_cache_fail; -#endif - return 0; -reg_notif_fail: - kmem_cache_destroy(mrt_cachep); + register_netdevice_notifier(&ip6_mr_notifier); #ifdef CONFIG_PROC_FS -proc_vif_fail: - unregister_netdevice_notifier(&ip6_mr_notifier); -proc_cache_fail: - proc_net_remove(&init_net, "ip6_mr_vif"); + proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops); + proc_net_fops_create(&init_net, "ip6_mr_cache", 0, &ip6mr_mfc_fops); #endif - return err; } -void ip6_mr_cleanup(void) -{ -#ifdef CONFIG_PROC_FS - proc_net_remove(&init_net, "ip6_mr_cache"); - proc_net_remove(&init_net, "ip6_mr_vif"); -#endif - unregister_netdevice_notifier(&ip6_mr_notifier); - del_timer(&ipmr_expire_timer); - kmem_cache_destroy(mrt_cachep); -} static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock) { diff --git a/trunk/net/ipv6/ipv6_sockglue.c b/trunk/net/ipv6/ipv6_sockglue.c index 030c0c956f9d..a9988841172a 100644 --- a/trunk/net/ipv6/ipv6_sockglue.c +++ b/trunk/net/ipv6/ipv6_sockglue.c @@ -343,21 +343,18 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, case IPV6_DSTOPTS: { struct ipv6_txoptions *opt; - - /* remove any sticky options header with a zero option - * length, per RFC3542. - */ if (optlen == 0) optval = NULL; - else if (optlen < sizeof(struct ipv6_opt_hdr) || - optlen & 0x7 || optlen > 8 * 255) - goto e_inval; /* hop-by-hop / destination options are privileged option */ retv = -EPERM; if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) break; + if (optlen < sizeof(struct ipv6_opt_hdr) || + optlen & 0x7 || optlen > 8 * 255) + goto e_inval; + opt = ipv6_renew_options(sk, np->opt, optname, (struct ipv6_opt_hdr __user *)optval, optlen); diff --git a/trunk/net/ipv6/netfilter/ip6table_mangle.c b/trunk/net/ipv6/netfilter/ip6table_mangle.c index f405cea21a8b..27a5e8b48d93 100644 --- a/trunk/net/ipv6/netfilter/ip6table_mangle.c +++ b/trunk/net/ipv6/netfilter/ip6table_mangle.c @@ -129,7 +129,7 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { .priority = NF_IP6_PRI_MANGLE, }, { - .hook = ip6t_route_hook, + .hook = ip6t_local_hook, .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_INET_LOCAL_IN, diff --git a/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c b/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c index cf20bc4fd60d..e65e26e210ee 100644 --- a/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -207,10 +207,9 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) arg.id = id; arg.src = src; arg.dst = dst; - - read_lock_bh(&nf_frags.lock); hash = ip6qhashfn(id, src, dst); + local_bh_disable(); q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); local_bh_enable(); if (q == NULL) diff --git a/trunk/net/ipv6/reassembly.c b/trunk/net/ipv6/reassembly.c index 6ab957ec2dd6..13509f906d89 100644 --- a/trunk/net/ipv6/reassembly.c +++ b/trunk/net/ipv6/reassembly.c @@ -245,8 +245,6 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, arg.id = id; arg.src = src; arg.dst = dst; - - read_lock(&ip6_frags.lock); hash = ip6qhashfn(id, src, dst); q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 5d6c166dfbb6..efe036aa3dd1 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -228,7 +228,7 @@ static __inline__ int rt6_check_expired(const struct rt6_info *rt) static inline int rt6_need_strict(struct in6_addr *daddr) { return (ipv6_addr_type(daddr) & - (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK)); + (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); } /* @@ -237,26 +237,21 @@ static inline int rt6_need_strict(struct in6_addr *daddr) static inline struct rt6_info *rt6_device_match(struct net *net, struct rt6_info *rt, - struct in6_addr *saddr, int oif, - int flags) + int strict) { struct rt6_info *local = NULL; struct rt6_info *sprt; - if (!oif && ipv6_addr_any(saddr)) - goto out; - - for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) { - struct net_device *dev = sprt->rt6i_dev; - - if (oif) { + if (oif) { + for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) { + struct net_device *dev = sprt->rt6i_dev; if (dev->ifindex == oif) return sprt; if (dev->flags & IFF_LOOPBACK) { if (sprt->rt6i_idev == NULL || sprt->rt6i_idev->dev->ifindex != oif) { - if (flags & RT6_LOOKUP_F_IFACE && oif) + if (strict && oif) continue; if (local && (!oif || local->rt6i_idev->dev->ifindex == oif)) @@ -264,21 +259,14 @@ static inline struct rt6_info *rt6_device_match(struct net *net, } local = sprt; } - } else { - if (ipv6_chk_addr(net, saddr, dev, - flags & RT6_LOOKUP_F_IFACE)) - return sprt; } - } - if (oif) { if (local) return local; - if (flags & RT6_LOOKUP_F_IFACE) + if (strict) return net->ipv6.ip6_null_entry; } -out: return rt; } @@ -551,7 +539,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net, fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); restart: rt = fn->leaf; - rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags); + rt = rt6_device_match(net, rt, fl->oif, flags); BACKTRACK(net, &fl->fl6_src); out: dst_use(&rt->u.dst, jiffies); diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index 30dbab7cc3cc..09be09cc1aa6 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -1946,7 +1946,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) seq_printf(seq, "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %lu %lu %u %u %d\n", + "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n", i, src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[2], src->s6_addr32[3], srcp, @@ -1962,8 +1962,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) icsk->icsk_probes_out, sock_i_ino(sp), atomic_read(&sp->sk_refcnt), sp, - jiffies_to_clock_t(icsk->icsk_rto), - jiffies_to_clock_t(icsk->icsk_ack.ato), + icsk->icsk_rto, + icsk->icsk_ack.ato, (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong, tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh ); diff --git a/trunk/net/mac80211/Kconfig b/trunk/net/mac80211/Kconfig index 0d3661d9b6a0..590e00b2766c 100644 --- a/trunk/net/mac80211/Kconfig +++ b/trunk/net/mac80211/Kconfig @@ -150,7 +150,7 @@ config MAC80211_LOWTX_FRAME_DUMP If unsure, say N and insert the debugging code you require into the driver you are debugging. -config MAC80211_TKIP_DEBUG +config TKIP_DEBUG bool "TKIP debugging" depends on MAC80211_DEBUG diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index af352c05c983..14fccf16b80f 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -24,7 +24,6 @@ #include #include #include -#include #include "key.h" #include "sta_info.h" @@ -791,10 +790,6 @@ struct ieee802_11_elems { u8 *preq; u8 *prep; u8 *perr; - u8 *ch_switch_elem; - u8 *country_elem; - u8 *pwr_constr_elem; - u8 *quiet_elem; /* first quite element */ /* length of them, respectively */ u8 ssid_len; @@ -819,11 +814,6 @@ struct ieee802_11_elems { u8 preq_len; u8 prep_len; u8 perr_len; - u8 ch_switch_elem_len; - u8 country_elem_len; - u8 pwr_constr_elem_len; - u8 quiet_elem_len; - u8 num_of_quiet_elem; /* can be more the one */ }; static inline struct ieee80211_local *hw_to_local( @@ -877,9 +867,7 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid); int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); void ieee80211_sta_req_auth(struct net_device *dev, struct ieee80211_if_sta *ifsta); -int ieee80211_sta_scan_results(struct net_device *dev, - struct iw_request_info *info, - char *buf, size_t len); +int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len); ieee80211_rx_result ieee80211_sta_rx_scan( struct net_device *dev, struct sk_buff *skb, struct ieee80211_rx_status *rx_status); diff --git a/trunk/net/mac80211/key.c b/trunk/net/mac80211/key.c index 6597c779e35a..d4893bd17754 100644 --- a/trunk/net/mac80211/key.c +++ b/trunk/net/mac80211/key.c @@ -387,15 +387,6 @@ void ieee80211_key_free(struct ieee80211_key *key) if (!key) return; - if (!key->sdata) { - /* The key has not been linked yet, simply free it - * and don't Oops */ - if (key->conf.alg == ALG_CCMP) - ieee80211_aes_key_free(key->u.ccmp.tfm); - kfree(key); - return; - } - spin_lock_irqsave(&key->sdata->local->key_lock, flags); __ieee80211_key_free(key); spin_unlock_irqrestore(&key->sdata->local->key_lock, flags); diff --git a/trunk/net/mac80211/key.h b/trunk/net/mac80211/key.h index 425816e0996c..a0f774aafa45 100644 --- a/trunk/net/mac80211/key.h +++ b/trunk/net/mac80211/key.h @@ -16,18 +16,31 @@ #include #include -#define WEP_IV_LEN 4 -#define WEP_ICV_LEN 4 -#define ALG_TKIP_KEY_LEN 32 -#define ALG_CCMP_KEY_LEN 16 -#define CCMP_HDR_LEN 8 -#define CCMP_MIC_LEN 8 -#define CCMP_TK_LEN 16 -#define CCMP_PN_LEN 6 -#define TKIP_IV_LEN 8 -#define TKIP_ICV_LEN 4 - -#define NUM_RX_DATA_QUEUES 17 +/* ALG_TKIP + * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block: + * Temporal Encryption Key (128 bits) + * Temporal Authenticator Tx MIC Key (64 bits) + * Temporal Authenticator Rx MIC Key (64 bits) + */ + +#define WEP_IV_LEN 4 +#define WEP_ICV_LEN 4 + +#define ALG_TKIP_KEY_LEN 32 +/* Starting offsets for each key */ +#define ALG_TKIP_TEMP_ENCR_KEY 0 +#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16 +#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24 +#define TKIP_IV_LEN 8 +#define TKIP_ICV_LEN 4 + +#define ALG_CCMP_KEY_LEN 16 +#define CCMP_HDR_LEN 8 +#define CCMP_MIC_LEN 8 +#define CCMP_TK_LEN 16 +#define CCMP_PN_LEN 6 + +#define NUM_RX_DATA_QUEUES 17 struct ieee80211_local; struct ieee80211_sub_if_data; diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index b661ee5bb824..5c5396edad32 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -1691,7 +1691,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) list_add_tail(&sdata->list, &local->interfaces); name = wiphy_dev(local->hw.wiphy)->driver->name; - local->hw.workqueue = create_freezeable_workqueue(name); + local->hw.workqueue = create_singlethread_workqueue(name); if (!local->hw.workqueue) { result = -ENOMEM; goto fail_workqueue; diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index 7b4d4d46843b..55659a730dc1 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -204,25 +204,6 @@ void ieee802_11_parse_elems(u8 *start, size_t len, elems->perr = pos; elems->perr_len = elen; break; - case WLAN_EID_CHANNEL_SWITCH: - elems->ch_switch_elem = pos; - elems->ch_switch_elem_len = elen; - break; - case WLAN_EID_QUIET: - if (!elems->quiet_elem) { - elems->quiet_elem = pos; - elems->quiet_elem_len = elen; - } - elems->num_of_quiet_elem++; - break; - case WLAN_EID_COUNTRY: - elems->country_elem = pos; - elems->country_elem_len = elen; - break; - case WLAN_EID_PWR_CONSTRAINT: - elems->pwr_constr_elem = pos; - elems->pwr_constr_elem_len = elen; - break; default: break; } @@ -1720,71 +1701,6 @@ void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr) } } -static void ieee80211_send_refuse_measurement_request(struct net_device *dev, - struct ieee80211_msrment_ie *request_ie, - const u8 *da, const u8 *bssid, - u8 dialog_token) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct sk_buff *skb; - struct ieee80211_mgmt *msr_report; - - skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + - sizeof(struct ieee80211_msrment_ie)); - - if (!skb) { - printk(KERN_ERR "%s: failed to allocate buffer for " - "measurement report frame\n", dev->name); - return; - } - - skb_reserve(skb, local->hw.extra_tx_headroom); - msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); - memset(msr_report, 0, 24); - memcpy(msr_report->da, da, ETH_ALEN); - memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN); - memcpy(msr_report->bssid, bssid, ETH_ALEN); - msr_report->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); - - skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); - msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; - msr_report->u.action.u.measurement.action_code = - WLAN_ACTION_SPCT_MSR_RPRT; - msr_report->u.action.u.measurement.dialog_token = dialog_token; - - msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; - msr_report->u.action.u.measurement.length = - sizeof(struct ieee80211_msrment_ie); - - memset(&msr_report->u.action.u.measurement.msr_elem, 0, - sizeof(struct ieee80211_msrment_ie)); - msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; - msr_report->u.action.u.measurement.msr_elem.mode |= - IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; - msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; - - ieee80211_sta_tx(dev, skb, 0); -} - -static void ieee80211_sta_process_measurement_req(struct net_device *dev, - struct ieee80211_mgmt *mgmt, - size_t len) -{ - /* - * Ignoring measurement request is spec violation. - * Mandatory measurements must be reported optional - * measurements might be refused or reported incapable - * For now just refuse - * TODO: Answer basic measurement as unmeasured - */ - ieee80211_send_refuse_measurement_request(dev, - &mgmt->u.action.u.measurement.msr_elem, - mgmt->sa, mgmt->bssid, - mgmt->u.action.u.measurement.dialog_token); -} - - static void ieee80211_rx_mgmt_auth(struct net_device *dev, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, @@ -1837,12 +1753,11 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, auth_transaction, status_code); if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { - /* - * IEEE 802.11 standard does not require authentication in IBSS + /* IEEE 802.11 standard does not require authentication in IBSS * networks and most implementations do not seem to use it. * However, try to reply to authentication attempts if someone * has actually implemented this. - */ + * TODO: Could implement shared key authentication. */ if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) { printk(KERN_DEBUG "%s: unexpected IBSS authentication " "frame (alg=%d transaction=%d)\n", @@ -3110,24 +3025,11 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev, struct ieee80211_rx_status *rx_status) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); if (len < IEEE80211_MIN_ACTION_SIZE) return; switch (mgmt->u.action.category) { - case WLAN_CATEGORY_SPECTRUM_MGMT: - if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) - break; - switch (mgmt->u.action.u.chan_switch.action_code) { - case WLAN_ACTION_SPCT_MSR_REQ: - if (len < (IEEE80211_MIN_ACTION_SIZE + - sizeof(mgmt->u.action.u.measurement))) - break; - ieee80211_sta_process_measurement_req(dev, mgmt, len); - break; - } - break; case WLAN_CATEGORY_BACK: switch (mgmt->u.action.u.addba_req.action_code) { case WLAN_ACTION_ADDBA_REQ: @@ -3271,32 +3173,33 @@ ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { struct ieee80211_mgmt *mgmt; - __le16 fc; + u16 fc; if (skb->len < 2) return RX_DROP_UNUSABLE; mgmt = (struct ieee80211_mgmt *) skb->data; - fc = mgmt->frame_control; + fc = le16_to_cpu(mgmt->frame_control); - if (ieee80211_is_ctl(fc)) + if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) return RX_CONTINUE; if (skb->len < 24) return RX_DROP_MONITOR; - if (ieee80211_is_probe_resp(fc)) { - ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); - dev_kfree_skb(skb); - return RX_QUEUED; - } - - if (ieee80211_is_beacon(fc)) { - ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); - dev_kfree_skb(skb); - return RX_QUEUED; + if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { + if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) { + ieee80211_rx_mgmt_probe_resp(dev, mgmt, + skb->len, rx_status); + dev_kfree_skb(skb); + return RX_QUEUED; + } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) { + ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, + rx_status); + dev_kfree_skb(skb); + return RX_QUEUED; + } } - return RX_CONTINUE; } @@ -3874,7 +3777,7 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, { struct sk_buff *skb; struct ieee80211_hdr *nullfunc; - __le16 fc; + u16 fc; skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); if (!skb) { @@ -3886,11 +3789,11 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); memset(nullfunc, 0, 24); - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); + fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_TODS; if (powersave) - fc |= cpu_to_le16(IEEE80211_FCTL_PM); - nullfunc->frame_control = fc; + fc |= IEEE80211_FCTL_PM; + nullfunc->frame_control = cpu_to_le16(fc); memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); @@ -4184,7 +4087,6 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) static char * ieee80211_sta_scan_result(struct net_device *dev, - struct iw_request_info *info, struct ieee80211_sta_bss *bss, char *current_ev, char *end_buf) { @@ -4199,7 +4101,7 @@ ieee80211_sta_scan_result(struct net_device *dev, iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN); memset(&iwe, 0, sizeof(iwe)); @@ -4207,13 +4109,13 @@ ieee80211_sta_scan_result(struct net_device *dev, if (bss_mesh_cfg(bss)) { iwe.u.data.length = bss_mesh_id_len(bss); iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss_mesh_id(bss)); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, + bss_mesh_id(bss)); } else { iwe.u.data.length = bss->ssid_len; iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ssid); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, + bss->ssid); } if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) @@ -4226,22 +4128,22 @@ ieee80211_sta_scan_result(struct net_device *dev, iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, + IW_EV_UINT_LEN); } memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); iwe.u.freq.e = 0; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); memset(&iwe, 0, sizeof(iwe)); iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = bss->freq; iwe.u.freq.e = 6; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVQUAL; @@ -4249,7 +4151,7 @@ ieee80211_sta_scan_result(struct net_device *dev, iwe.u.qual.level = bss->signal; iwe.u.qual.noise = bss->noise; iwe.u.qual.updated = local->wstats_flags; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, + current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN); memset(&iwe, 0, sizeof(iwe)); @@ -4259,36 +4161,35 @@ ieee80211_sta_scan_result(struct net_device *dev, else iwe.u.data.flags = IW_ENCODE_DISABLED; iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, ""); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ""); if (bss && bss->wpa_ie) { memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVGENIE; iwe.u.data.length = bss->wpa_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->wpa_ie); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, + bss->wpa_ie); } if (bss && bss->rsn_ie) { memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVGENIE; iwe.u.data.length = bss->rsn_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->rsn_ie); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, + bss->rsn_ie); } if (bss && bss->ht_ie) { memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVGENIE; iwe.u.data.length = bss->ht_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ht_ie); + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, + bss->ht_ie); } if (bss && bss->supp_rates_len > 0) { /* display all supported rates in readable format */ - char *p = current_ev + iwe_stream_lcp_len(info); + char *p = current_ev + IW_EV_LCP_LEN; int i; memset(&iwe, 0, sizeof(iwe)); @@ -4299,7 +4200,7 @@ ieee80211_sta_scan_result(struct net_device *dev, for (i = 0; i < bss->supp_rates_len; i++) { iwe.u.bitrate.value = ((bss->supp_rates[i] & 0x7f) * 500000); - p = iwe_stream_add_value(info, current_ev, p, + p = iwe_stream_add_value(current_ev, p, end_buf, &iwe, IW_EV_PARAM_LEN); } current_ev = p; @@ -4313,8 +4214,7 @@ ieee80211_sta_scan_result(struct net_device *dev, iwe.cmd = IWEVCUSTOM; sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); kfree(buf); } @@ -4329,36 +4229,31 @@ ieee80211_sta_scan_result(struct net_device *dev, iwe.cmd = IWEVCUSTOM; sprintf(buf, "Mesh network (version %d)", cfg[0]); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); sprintf(buf, "Path Selection Protocol ID: " "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], cfg[4]); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); sprintf(buf, "Path Selection Metric ID: " "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], cfg[8]); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); sprintf(buf, "Congestion Control Mode ID: " "0x%02X%02X%02X%02X", cfg[9], cfg[10], cfg[11], cfg[12]); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); sprintf(buf, "Channel Precedence: " "0x%02X%02X%02X%02X", cfg[13], cfg[14], cfg[15], cfg[16]); iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, + current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf); kfree(buf); } @@ -4368,9 +4263,7 @@ ieee80211_sta_scan_result(struct net_device *dev, } -int ieee80211_sta_scan_results(struct net_device *dev, - struct iw_request_info *info, - char *buf, size_t len) +int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); char *current_ev = buf; @@ -4383,8 +4276,8 @@ int ieee80211_sta_scan_results(struct net_device *dev, spin_unlock_bh(&local->sta_bss_lock); return -E2BIG; } - current_ev = ieee80211_sta_scan_result(dev, info, bss, - current_ev, end_buf); + current_ev = ieee80211_sta_scan_result(dev, bss, current_ev, + end_buf); } spin_unlock_bh(&local->sta_bss_lock); return current_ev - buf; diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index 8962d1355f04..c32a0bcd53b7 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -61,7 +61,7 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status, int present_fcs_len, int radiotap_len) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) return 1; @@ -2123,7 +2123,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, struct tid_ampdu_rx *tid_agg_rx; u16 sc; u16 mpdu_seq_num; - u8 ret = 0; + u8 ret = 0, *qc; int tid; sta = sta_info_get(local, hdr->addr2); @@ -2135,7 +2135,8 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, if (!ieee80211_is_data_qos(hdr->frame_control)) goto end_reorder; - tid = *ieee80211_get_qos_ctl(hdr) & QOS_CONTROL_TID_MASK; + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & QOS_CONTROL_TID_MASK; if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) goto end_reorder; diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index b3c733162fc1..c24770cb02c5 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -235,7 +235,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, return NULL; spin_lock_init(&sta->lock); - spin_lock_init(&sta->flaglock); memcpy(sta->addr, addr, ETH_ALEN); sta->local = local; diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index fd228c198e31..95753f860acf 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -164,7 +164,6 @@ struct sta_ampdu_mlme { * @aid: STA's unique AID (1..2007, 0 = not assigned yet), * only used in AP (and IBSS?) mode * @flags: STA flags, see &enum ieee80211_sta_info_flags - * @flaglock: spinlock for flags accesses * @ps_tx_buf: buffer of frames to transmit to this station * when it leaves power saving state * @tx_filtered: buffer of frames we already tried to transmit @@ -187,7 +186,6 @@ struct sta_info { struct rate_control_ref *rate_ctrl; void *rate_ctrl_priv; spinlock_t lock; - spinlock_t flaglock; struct ieee80211_ht_info ht_info; u64 supp_rates[IEEE80211_NUM_BANDS]; u8 addr[ETH_ALEN]; @@ -200,10 +198,7 @@ struct sta_info { */ u8 pin_status; - /* - * frequently updated, locked with own spinlock (flaglock), - * use the accessors defined below - */ + /* frequently updated information, locked with lock spinlock */ u32 flags; /* @@ -298,41 +293,34 @@ static inline enum plink_state sta_plink_state(struct sta_info *sta) static inline void set_sta_flags(struct sta_info *sta, const u32 flags) { - unsigned long irqfl; - - spin_lock_irqsave(&sta->flaglock, irqfl); + spin_lock_bh(&sta->lock); sta->flags |= flags; - spin_unlock_irqrestore(&sta->flaglock, irqfl); + spin_unlock_bh(&sta->lock); } static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) { - unsigned long irqfl; - - spin_lock_irqsave(&sta->flaglock, irqfl); + spin_lock_bh(&sta->lock); sta->flags &= ~flags; - spin_unlock_irqrestore(&sta->flaglock, irqfl); + spin_unlock_bh(&sta->lock); } static inline void set_and_clear_sta_flags(struct sta_info *sta, const u32 set, const u32 clear) { - unsigned long irqfl; - - spin_lock_irqsave(&sta->flaglock, irqfl); + spin_lock_bh(&sta->lock); sta->flags |= set; sta->flags &= ~clear; - spin_unlock_irqrestore(&sta->flaglock, irqfl); + spin_unlock_bh(&sta->lock); } static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) { u32 ret; - unsigned long irqfl; - spin_lock_irqsave(&sta->flaglock, irqfl); + spin_lock_bh(&sta->lock); ret = sta->flags & flags; - spin_unlock_irqrestore(&sta->flaglock, irqfl); + spin_unlock_bh(&sta->lock); return ret; } @@ -341,12 +329,11 @@ static inline u32 test_and_clear_sta_flags(struct sta_info *sta, const u32 flags) { u32 ret; - unsigned long irqfl; - spin_lock_irqsave(&sta->flaglock, irqfl); + spin_lock_bh(&sta->lock); ret = sta->flags & flags; sta->flags &= ~flags; - spin_unlock_irqrestore(&sta->flaglock, irqfl); + spin_unlock_bh(&sta->lock); return ret; } @@ -354,11 +341,10 @@ static inline u32 test_and_clear_sta_flags(struct sta_info *sta, static inline u32 get_sta_flags(struct sta_info *sta) { u32 ret; - unsigned long irqfl; - spin_lock_irqsave(&sta->flaglock, irqfl); + spin_lock_bh(&sta->lock); ret = sta->flags; - spin_unlock_irqrestore(&sta->flaglock, irqfl); + spin_unlock_bh(&sta->lock); return ret; } diff --git a/trunk/net/mac80211/tkip.c b/trunk/net/mac80211/tkip.c index 995f7af3d25e..e710243d82e2 100644 --- a/trunk/net/mac80211/tkip.c +++ b/trunk/net/mac80211/tkip.c @@ -164,10 +164,10 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, iv16 = data[2] | (data[0] << 8); iv32 = get_unaligned_le32(&data[4]); - tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; + tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; ctx = &key->u.tkip.tx; -#ifdef CONFIG_MAC80211_TKIP_DEBUG +#ifdef CONFIG_TKIP_DEBUG printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", iv16, iv32); @@ -177,7 +177,7 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " "fragmented packet\n"); } -#endif +#endif /* CONFIG_TKIP_DEBUG */ /* Update the p1k only when the iv16 in the packet wraps around, this * might occur after the wrap around of iv16 in the key in case of @@ -205,7 +205,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, { u8 rc4key[16]; struct tkip_ctx *ctx = &key->u.tkip.tx; - const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; + const u8 *tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; /* Calculate per-packet key */ if (ctx->iv16 == 0 || !ctx->initialized) @@ -231,7 +231,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, u32 iv16; u8 rc4key[16], keyid, *pos = payload; int res; - const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; + const u8 *tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; if (payload_len < 12) return -1; @@ -240,7 +240,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, keyid = pos[3]; iv32 = get_unaligned_le32(pos + 4); pos += 8; -#ifdef CONFIG_MAC80211_TKIP_DEBUG +#ifdef CONFIG_TKIP_DEBUG { int i; printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len); @@ -250,7 +250,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n", iv16, iv32); } -#endif +#endif /* CONFIG_TKIP_DEBUG */ if (!(keyid & (1 << 5))) return TKIP_DECRYPT_NO_EXT_IV; @@ -262,14 +262,14 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, (iv32 < key->u.tkip.rx[queue].iv32 || (iv32 == key->u.tkip.rx[queue].iv32 && iv16 <= key->u.tkip.rx[queue].iv16))) { -#ifdef CONFIG_MAC80211_TKIP_DEBUG +#ifdef CONFIG_TKIP_DEBUG DECLARE_MAC_BUF(mac); printk(KERN_DEBUG "TKIP replay detected for RX frame from " "%s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", print_mac(mac, ta), iv32, iv16, key->u.tkip.rx[queue].iv32, key->u.tkip.rx[queue].iv16); -#endif +#endif /* CONFIG_TKIP_DEBUG */ return TKIP_DECRYPT_REPLAY; } @@ -283,23 +283,23 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, key->u.tkip.rx[queue].iv32 != iv32) { /* IV16 wrapped around - perform TKIP phase 1 */ tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); -#ifdef CONFIG_MAC80211_TKIP_DEBUG +#ifdef CONFIG_TKIP_DEBUG { int i; - u8 key_offset = NL80211_TKIP_DATA_OFFSET_ENCR_KEY; DECLARE_MAC_BUF(mac); printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%s" " TK=", print_mac(mac, ta)); for (i = 0; i < 16; i++) printk("%02x ", - key->conf.key[key_offset + i]); + key->conf.key[ + ALG_TKIP_TEMP_ENCR_KEY + i]); printk("\n"); printk(KERN_DEBUG "TKIP decrypt: P1K="); for (i = 0; i < 5; i++) printk("%04x ", key->u.tkip.rx[queue].p1k[i]); printk("\n"); } -#endif +#endif /* CONFIG_TKIP_DEBUG */ if (key->local->ops->update_tkip_key && key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { u8 bcast[ETH_ALEN] = @@ -316,7 +316,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, } tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); -#ifdef CONFIG_MAC80211_TKIP_DEBUG +#ifdef CONFIG_TKIP_DEBUG { int i; printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key="); @@ -324,7 +324,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, printk("%02x ", rc4key[i]); printk("\n"); } -#endif +#endif /* CONFIG_TKIP_DEBUG */ res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12); done: diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index 52ab85c4341b..ce06e791bf43 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -52,8 +52,9 @@ static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdat static void ieee80211_dump_frame(const char *ifname, const char *title, const struct sk_buff *skb) { - const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - unsigned int hdrlen; + const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + u16 fc; + int hdrlen; DECLARE_MAC_BUF(mac); printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); @@ -62,12 +63,13 @@ static void ieee80211_dump_frame(const char *ifname, const char *title, return; } - hdrlen = ieee80211_hdrlen(hdr->frame_control); + fc = le16_to_cpu(hdr->frame_control); + hdrlen = ieee80211_get_hdrlen(fc); if (hdrlen > skb->len) hdrlen = skb->len; if (hdrlen >= 4) printk(" FC=0x%04x DUR=0x%04x", - le16_to_cpu(hdr->frame_control), le16_to_cpu(hdr->duration_id)); + fc, le16_to_cpu(hdr->duration_id)); if (hdrlen >= 10) printk(" A1=%s", print_mac(mac, hdr->addr1)); if (hdrlen >= 16) @@ -85,8 +87,8 @@ static inline void ieee80211_dump_frame(const char *ifname, const char *title, } #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ -static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, - int next_frag_len) +static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, + int next_frag_len) { int rate, mrate, erp, dur, i; struct ieee80211_rate *txrate; @@ -138,7 +140,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, /* data/mgmt */ if (0 /* FIX: data/mgmt during CFP */) - return cpu_to_le16(32768); + return 32768; if (group_addr) /* Group address as the destination - no ACK */ return 0; @@ -208,7 +210,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, tx->sdata->bss_conf.use_short_preamble); } - return cpu_to_le16(dur); + return dur; } static int inline is_ieee80211_device(struct net_device *dev, @@ -279,7 +281,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; - if (ieee80211_hdrlen(hdr->frame_control) >= 24) + if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24) ieee80211_include_sequence(tx->sdata, hdr); return TX_CONTINUE; @@ -540,7 +542,9 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) static ieee80211_tx_result ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; + u16 fc = le16_to_cpu(hdr->frame_control); + u16 dur; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_supported_band *sband; @@ -591,13 +595,21 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) /* Transmit data frames using short preambles if the driver supports * short preambles at the selected rate and short preambles are * available on the network at the current point in time. */ - if (ieee80211_is_data(hdr->frame_control) && + if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && tx->sdata->bss_conf.use_short_preamble && (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; } + /* Setup duration field for the first fragment of the frame. Duration + * for remaining fragments will be updated when they are being sent + * to low-level driver in ieee80211_tx(). */ + dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1), + (tx->flags & IEEE80211_TX_FRAGMENTED) ? + tx->extra_frag[0]->len : 0); + hdr->duration_id = cpu_to_le16(dur); + if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { struct ieee80211_rate *rate; @@ -635,7 +647,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) static ieee80211_tx_result ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; size_t hdrlen, per_fragm, num_fragm, payload_len, left; struct sk_buff **frags, *first, *frag; int i; @@ -658,7 +670,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) first = tx->skb; - hdrlen = ieee80211_hdrlen(hdr->frame_control); + hdrlen = ieee80211_get_hdrlen(tx->fc); payload_len = first->len - hdrlen; per_fragm = frag_threshold - hdrlen - FCS_LEN; num_fragm = DIV_ROUND_UP(payload_len, per_fragm); @@ -699,8 +711,6 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); copylen = left > per_fragm ? per_fragm : left; memcpy(skb_put(frag, copylen), pos, copylen); - memcpy(frag->cb, first->cb, sizeof(frag->cb)); - skb_copy_queue_mapping(frag, first); pos += copylen; left -= copylen; @@ -744,36 +754,6 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) return TX_DROP; } -static ieee80211_tx_result -ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; - int next_len, i; - int group_addr = is_multicast_ether_addr(hdr->addr1); - - if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) { - hdr->duration_id = ieee80211_duration(tx, group_addr, 0); - return TX_CONTINUE; - } - - hdr->duration_id = ieee80211_duration(tx, group_addr, - tx->extra_frag[0]->len); - - for (i = 0; i < tx->num_extra_frag; i++) { - if (i + 1 < tx->num_extra_frag) { - next_len = tx->extra_frag[i + 1]->len; - } else { - next_len = 0; - tx->rate_idx = tx->last_frag_rate_idx; - } - - hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; - hdr->duration_id = ieee80211_duration(tx, 0, next_len); - } - - return TX_CONTINUE; -} - static ieee80211_tx_result ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) { @@ -808,7 +788,6 @@ static ieee80211_tx_handler ieee80211_tx_handlers[] = ieee80211_tx_h_fragment, /* handlers after fragment must be aware of tx info fragmentation! */ ieee80211_tx_h_encrypt, - ieee80211_tx_h_calculate_duration, ieee80211_tx_h_stats, NULL }; @@ -1104,46 +1083,13 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, return IEEE80211_TX_OK; } -/* - * Invoke TX handlers, return 0 on success and non-zero if the - * frame was dropped or queued. - */ -static int invoke_tx_handlers(struct ieee80211_tx_data *tx) -{ - struct ieee80211_local *local = tx->local; - struct sk_buff *skb = tx->skb; - ieee80211_tx_handler *handler; - ieee80211_tx_result res = TX_DROP; - int i; - - for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) { - res = (*handler)(tx); - if (res != TX_CONTINUE) - break; - } - - if (unlikely(res == TX_DROP)) { - I802_DEBUG_INC(local->tx_handlers_drop); - dev_kfree_skb(skb); - for (i = 0; i < tx->num_extra_frag; i++) - if (tx->extra_frag[i]) - dev_kfree_skb(tx->extra_frag[i]); - kfree(tx->extra_frag); - return -1; - } else if (unlikely(res == TX_QUEUED)) { - I802_DEBUG_INC(local->tx_handlers_queued); - return -1; - } - - return 0; -} - static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct sta_info *sta; + ieee80211_tx_handler *handler; struct ieee80211_tx_data tx; - ieee80211_tx_result res_prepare; + ieee80211_tx_result res = TX_DROP, res_prepare; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); int ret, i; u16 queue; @@ -1172,8 +1118,44 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) tx.channel = local->hw.conf.channel; info->band = tx.channel->band; - if (invoke_tx_handlers(&tx)) - goto out; + for (handler = ieee80211_tx_handlers; *handler != NULL; + handler++) { + res = (*handler)(&tx); + if (res != TX_CONTINUE) + break; + } + + if (WARN_ON(tx.skb != skb)) + goto drop; + + if (unlikely(res == TX_DROP)) { + I802_DEBUG_INC(local->tx_handlers_drop); + goto drop; + } + + if (unlikely(res == TX_QUEUED)) { + I802_DEBUG_INC(local->tx_handlers_queued); + rcu_read_unlock(); + return 0; + } + + if (tx.extra_frag) { + for (i = 0; i < tx.num_extra_frag; i++) { + int next_len, dur; + struct ieee80211_hdr *hdr = + (struct ieee80211_hdr *) + tx.extra_frag[i]->data; + + if (i + 1 < tx.num_extra_frag) { + next_len = tx.extra_frag[i + 1]->len; + } else { + next_len = 0; + tx.rate_idx = tx.last_frag_rate_idx; + } + dur = ieee80211_duration(&tx, 0, next_len); + hdr->duration_id = cpu_to_le16(dur); + } + } retry: ret = __ieee80211_tx(local, skb, &tx); @@ -1216,7 +1198,6 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) store->last_frag_rate_ctrl_probe = !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG); } - out: rcu_read_unlock(); return 0; @@ -1398,8 +1379,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct ieee80211_tx_info *info; struct ieee80211_sub_if_data *sdata; int ret = 1, head_need; - u16 ethertype, hdrlen, meshhdrlen = 0; - __le16 fc; + u16 ethertype, hdrlen, meshhdrlen = 0, fc; struct ieee80211_hdr hdr; struct ieee80211s_hdr mesh_hdr; const u8 *encaps_data; @@ -1422,12 +1402,12 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, /* convert Ethernet header to proper 802.11 header (based on * operation mode) */ ethertype = (skb->data[12] << 8) | skb->data[13]; - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); + fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; switch (sdata->vif.type) { case IEEE80211_IF_TYPE_AP: case IEEE80211_IF_TYPE_VLAN: - fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); + fc |= IEEE80211_FCTL_FROMDS; /* DA BSSID SA */ memcpy(hdr.addr1, skb->data, ETH_ALEN); memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); @@ -1435,7 +1415,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, hdrlen = 24; break; case IEEE80211_IF_TYPE_WDS: - fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); + fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS; /* RA TA DA SA */ memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); @@ -1445,7 +1425,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, break; #ifdef CONFIG_MAC80211_MESH case IEEE80211_IF_TYPE_MESH_POINT: - fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); + fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS; /* RA TA DA SA */ if (is_multicast_ether_addr(skb->data)) memcpy(hdr.addr1, skb->data, ETH_ALEN); @@ -1475,7 +1455,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, break; #endif case IEEE80211_IF_TYPE_STA: - fc |= cpu_to_le16(IEEE80211_FCTL_TODS); + fc |= IEEE80211_FCTL_TODS; /* BSSID SA DA */ memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); @@ -1510,7 +1490,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, /* receiver and we are QoS enabled, use a QoS type frame */ if (sta_flags & WLAN_STA_WME && ieee80211_num_regular_queues(&local->hw) >= 4) { - fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); + fc |= IEEE80211_STYPE_QOS_DATA; hdrlen += 2; } @@ -1538,7 +1518,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } - hdr.frame_control = fc; + hdr.frame_control = cpu_to_le16(fc); hdr.duration_id = 0; hdr.seq_ctrl = 0; @@ -1607,7 +1587,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, h_pos += meshhdrlen; } - if (ieee80211_is_data_qos(fc)) { + if (fc & IEEE80211_STYPE_QOS_DATA) { __le16 *qos_control; qos_control = (__le16*) skb_push(skb, 2); @@ -1865,8 +1845,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); - mgmt->frame_control = - cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); + mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, + IEEE80211_STYPE_BEACON); memset(mgmt->da, 0xff, ETH_ALEN); memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); /* BSSID is left zeroed, wildcard value */ @@ -1934,9 +1914,10 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_rts *rts) { const struct ieee80211_hdr *hdr = frame; + u16 fctl; - rts->frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); + fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS; + rts->frame_control = cpu_to_le16(fctl); rts->duration = ieee80211_rts_duration(hw, vif, frame_len, frame_txctl); memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); @@ -1950,9 +1931,10 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_cts *cts) { const struct ieee80211_hdr *hdr = frame; + u16 fctl; - cts->frame_control = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); + fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS; + cts->frame_control = cpu_to_le16(fctl); cts->duration = ieee80211_ctstoself_duration(hw, vif, frame_len, frame_txctl); memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); @@ -1966,7 +1948,9 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_local *local = hw_to_local(hw); struct sk_buff *skb = NULL; struct sta_info *sta; + ieee80211_tx_handler *handler; struct ieee80211_tx_data tx; + ieee80211_tx_result res = TX_DROP; struct net_device *bdev; struct ieee80211_sub_if_data *sdata; struct ieee80211_if_ap *bss = NULL; @@ -2017,9 +2001,25 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, tx.channel = local->hw.conf.channel; info->band = tx.channel->band; - if (invoke_tx_handlers(&tx)) + for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) { + res = (*handler)(&tx); + if (res == TX_DROP || res == TX_QUEUED) + break; + } + + if (WARN_ON(tx.skb != skb)) + res = TX_DROP; + + if (res == TX_DROP) { + I802_DEBUG_INC(local->tx_handlers_drop); + dev_kfree_skb(skb); skb = NULL; - out: + } else if (res == TX_QUEUED) { + I802_DEBUG_INC(local->tx_handlers_queued); + skb = NULL; + } + +out: rcu_read_unlock(); return skb; diff --git a/trunk/net/mac80211/wep.c b/trunk/net/mac80211/wep.c index 35b664d00e23..e7b6344c900a 100644 --- a/trunk/net/mac80211/wep.c +++ b/trunk/net/mac80211/wep.c @@ -84,17 +84,20 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, struct sk_buff *skb, struct ieee80211_key *key) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - unsigned int hdrlen; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + u16 fc; + int hdrlen; u8 *newhdr; - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); + fc = le16_to_cpu(hdr->frame_control); + fc |= IEEE80211_FCTL_PROTECTED; + hdr->frame_control = cpu_to_le16(fc); if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN || skb_headroom(skb) < WEP_IV_LEN)) return NULL; - hdrlen = ieee80211_hdrlen(hdr->frame_control); + hdrlen = ieee80211_get_hdrlen(fc); newhdr = skb_push(skb, WEP_IV_LEN); memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); ieee80211_wep_get_iv(local, key, newhdr + hdrlen); @@ -106,10 +109,12 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, struct sk_buff *skb, struct ieee80211_key *key) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - unsigned int hdrlen; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + u16 fc; + int hdrlen; - hdrlen = ieee80211_hdrlen(hdr->frame_control); + fc = le16_to_cpu(hdr->frame_control); + hdrlen = ieee80211_get_hdrlen(fc); memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); skb_pull(skb, WEP_IV_LEN); } @@ -219,15 +224,17 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, u32 klen; u8 *rc4key; u8 keyidx; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - unsigned int hdrlen; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + u16 fc; + int hdrlen; size_t len; int ret = 0; - if (!ieee80211_has_protected(hdr->frame_control)) + fc = le16_to_cpu(hdr->frame_control); + if (!(fc & IEEE80211_FCTL_PROTECTED)) return -1; - hdrlen = ieee80211_hdrlen(hdr->frame_control); + hdrlen = ieee80211_get_hdrlen(fc); if (skb->len < 8 + hdrlen) return -1; @@ -274,15 +281,17 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - unsigned int hdrlen; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + u16 fc; + int hdrlen; u8 *ivpos; u32 iv; - if (!ieee80211_has_protected(hdr->frame_control)) + fc = le16_to_cpu(hdr->frame_control); + if (!(fc & IEEE80211_FCTL_PROTECTED)) return NULL; - hdrlen = ieee80211_hdrlen(hdr->frame_control); + hdrlen = ieee80211_get_hdrlen(fc); ivpos = skb->data + hdrlen; iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; diff --git a/trunk/net/mac80211/wext.c b/trunk/net/mac80211/wext.c index df0531c28141..5af3862e7191 100644 --- a/trunk/net/mac80211/wext.c +++ b/trunk/net/mac80211/wext.c @@ -135,39 +135,7 @@ static int ieee80211_ioctl_giwname(struct net_device *dev, struct iw_request_info *info, char *name, char *extra) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_supported_band *sband; - u8 is_ht = 0, is_a = 0, is_b = 0, is_g = 0; - - - sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ]; - if (sband) { - is_a = 1; - is_ht |= sband->ht_info.ht_supported; - } - - sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ]; - if (sband) { - int i; - /* Check for mandatory rates */ - for (i = 0; i < sband->n_bitrates; i++) { - if (sband->bitrates[i].bitrate == 10) - is_b = 1; - if (sband->bitrates[i].bitrate == 60) - is_g = 1; - } - is_ht |= sband->ht_info.ht_supported; - } - strcpy(name, "IEEE 802.11"); - if (is_a) - strcat(name, "a"); - if (is_b) - strcat(name, "b"); - if (is_g) - strcat(name, "g"); - if (is_ht) - strcat(name, "n"); return 0; } @@ -599,7 +567,7 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, if (local->sta_sw_scanning || local->sta_hw_scanning) return -EAGAIN; - res = ieee80211_sta_scan_results(dev, info, extra, data->length); + res = ieee80211_sta_scan_results(dev, extra, data->length); if (res >= 0) { data->length = res; return 0; @@ -753,9 +721,6 @@ static int ieee80211_ioctl_siwrts(struct net_device *dev, if (rts->disabled) local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - else if (!rts->fixed) - /* if the rts value is not fixed, then take default */ - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) return -EINVAL; else @@ -984,19 +949,6 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, erq->length = sdata->keys[idx]->conf.keylen; erq->flags |= IW_ENCODE_ENABLED; - if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - switch (ifsta->auth_alg) { - case WLAN_AUTH_OPEN: - case WLAN_AUTH_LEAP: - erq->flags |= IW_ENCODE_OPEN; - break; - case WLAN_AUTH_SHARED_KEY: - erq->flags |= IW_ENCODE_RESTRICTED; - break; - } - } - return 0; } diff --git a/trunk/net/mac80211/wpa.c b/trunk/net/mac80211/wpa.c index f809761fbfb5..345e10e9b313 100644 --- a/trunk/net/mac80211/wpa.c +++ b/trunk/net/mac80211/wpa.c @@ -49,7 +49,7 @@ static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da, ieee80211_tx_result ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) { - u8 *data, *sa, *da, *key, *mic, qos_tid, key_offset; + u8 *data, *sa, *da, *key, *mic, qos_tid; size_t data_len; u16 fc; struct sk_buff *skb = tx->skb; @@ -88,12 +88,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) #else authenticator = 1; #endif - /* At this point we know we're using ALG_TKIP. To get the MIC key - * we now will rely on the offset from the ieee80211_key_conf::key */ - key_offset = authenticator ? - NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY : - NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; - key = &tx->key->conf.key[key_offset]; + key = &tx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_TX_MIC_KEY : + ALG_TKIP_TEMP_AUTH_RX_MIC_KEY]; mic = skb_put(skb, MICHAEL_MIC_LEN); michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); @@ -104,7 +100,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) ieee80211_rx_result ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) { - u8 *data, *sa, *da, *key = NULL, qos_tid, key_offset; + u8 *data, *sa, *da, *key = NULL, qos_tid; size_t data_len; u16 fc; u8 mic[MICHAEL_MIC_LEN]; @@ -135,12 +131,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) #else authenticator = 1; #endif - /* At this point we know we're using ALG_TKIP. To get the MIC key - * we now will rely on the offset from the ieee80211_key_conf::key */ - key_offset = authenticator ? - NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : - NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; - key = &rx->key->conf.key[key_offset]; + key = &rx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_RX_MIC_KEY : + ALG_TKIP_TEMP_AUTH_TX_MIC_KEY]; michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { if (!(rx->flags & IEEE80211_RX_RA_MATCH)) diff --git a/trunk/net/netlabel/netlabel_unlabeled.c b/trunk/net/netlabel/netlabel_unlabeled.c index 52b2611a6eb6..0099da5b2591 100644 --- a/trunk/net/netlabel/netlabel_unlabeled.c +++ b/trunk/net/netlabel/netlabel_unlabeled.c @@ -1534,7 +1534,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, } } list_for_each_entry_rcu(addr6, &iface->addr6_list, list) { - if (!addr6->valid || iter_addr6++ < skip_addr6) + if (addr6->valid || iter_addr6++ < skip_addr6) continue; if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, iface, diff --git a/trunk/net/netlink/attr.c b/trunk/net/netlink/attr.c index 2d106cfe1d27..47bbf45ae5d7 100644 --- a/trunk/net/netlink/attr.c +++ b/trunk/net/netlink/attr.c @@ -132,7 +132,6 @@ int nla_validate(struct nlattr *head, int len, int maxtype, * @maxtype: maximum attribute type to be expected * @head: head of attribute stream * @len: length of attribute stream - * @policy: validation policy * * Parses a stream of attributes and stores a pointer to each attribute in * the tb array accessable via the attribute type. Attributes with a type @@ -195,7 +194,7 @@ struct nlattr *nla_find(struct nlattr *head, int len, int attrtype) /** * nla_strlcpy - Copy string attribute payload into a sized buffer * @dst: where to copy the string to - * @nla: attribute to copy the string from + * @src: attribute to copy the string from * @dstsize: size of destination buffer * * Copies at most dstsize - 1 bytes into the destination buffer. @@ -341,9 +340,9 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) } /** - * nla_reserve_nohdr - reserve room for attribute without header + * nla_reserve - reserve room for attribute without header * @skb: socket buffer to reserve room on - * @attrlen: length of attribute payload + * @len: length of attribute payload * * Reserves room for attribute payload without a header. * diff --git a/trunk/net/rfkill/rfkill-input.c b/trunk/net/rfkill/rfkill-input.c index 8aa822730145..e4b051dbed61 100644 --- a/trunk/net/rfkill/rfkill-input.c +++ b/trunk/net/rfkill/rfkill-input.c @@ -30,62 +30,39 @@ struct rfkill_task { spinlock_t lock; /* for accessing last and desired state */ unsigned long last; /* last schedule */ enum rfkill_state desired_state; /* on/off */ + enum rfkill_state current_state; /* on/off */ }; static void rfkill_task_handler(struct work_struct *work) { struct rfkill_task *task = container_of(work, struct rfkill_task, work); + enum rfkill_state state; mutex_lock(&task->mutex); - rfkill_switch_all(task->type, task->desired_state); + /* + * Use temp variable to fetch desired state to keep it + * consistent even if rfkill_schedule_toggle() runs in + * another thread or interrupts us. + */ + state = task->desired_state; - mutex_unlock(&task->mutex); -} - -static void rfkill_task_epo_handler(struct work_struct *work) -{ - rfkill_epo(); -} - -static DECLARE_WORK(epo_work, rfkill_task_epo_handler); - -static void rfkill_schedule_epo(void) -{ - schedule_work(&epo_work); -} - -static void rfkill_schedule_set(struct rfkill_task *task, - enum rfkill_state desired_state) -{ - unsigned long flags; - - if (unlikely(work_pending(&epo_work))) - return; - - spin_lock_irqsave(&task->lock, flags); - - if (time_after(jiffies, task->last + msecs_to_jiffies(200))) { - task->desired_state = desired_state; - task->last = jiffies; - schedule_work(&task->work); + if (state != task->current_state) { + rfkill_switch_all(task->type, state); + task->current_state = state; } - spin_unlock_irqrestore(&task->lock, flags); + mutex_unlock(&task->mutex); } static void rfkill_schedule_toggle(struct rfkill_task *task) { unsigned long flags; - if (unlikely(work_pending(&epo_work))) - return; - spin_lock_irqsave(&task->lock, flags); if (time_after(jiffies, task->last + msecs_to_jiffies(200))) { - task->desired_state = - rfkill_state_complement(task->desired_state); + task->desired_state = !task->desired_state; task->last = jiffies; schedule_work(&task->work); } @@ -93,26 +70,26 @@ static void rfkill_schedule_toggle(struct rfkill_task *task) spin_unlock_irqrestore(&task->lock, flags); } -#define DEFINE_RFKILL_TASK(n, t) \ - struct rfkill_task n = { \ - .work = __WORK_INITIALIZER(n.work, \ - rfkill_task_handler), \ - .type = t, \ - .mutex = __MUTEX_INITIALIZER(n.mutex), \ - .lock = __SPIN_LOCK_UNLOCKED(n.lock), \ - .desired_state = RFKILL_STATE_UNBLOCKED, \ +#define DEFINE_RFKILL_TASK(n, t) \ + struct rfkill_task n = { \ + .work = __WORK_INITIALIZER(n.work, \ + rfkill_task_handler), \ + .type = t, \ + .mutex = __MUTEX_INITIALIZER(n.mutex), \ + .lock = __SPIN_LOCK_UNLOCKED(n.lock), \ + .desired_state = RFKILL_STATE_ON, \ + .current_state = RFKILL_STATE_ON, \ } static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN); static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH); static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); -static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN); static void rfkill_event(struct input_handle *handle, unsigned int type, - unsigned int code, int data) + unsigned int code, int down) { - if (type == EV_KEY && data == 1) { + if (type == EV_KEY && down == 1) { switch (code) { case KEY_WLAN: rfkill_schedule_toggle(&rfkill_wlan); @@ -129,28 +106,6 @@ static void rfkill_event(struct input_handle *handle, unsigned int type, default: break; } - } else if (type == EV_SW) { - switch (code) { - case SW_RFKILL_ALL: - /* EVERY radio type. data != 0 means radios ON */ - /* handle EPO (emergency power off) through shortcut */ - if (data) { - rfkill_schedule_set(&rfkill_wwan, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_wimax, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_uwb, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_bt, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_wlan, - RFKILL_STATE_UNBLOCKED); - } else - rfkill_schedule_epo(); - break; - default: - break; - } } } @@ -213,11 +168,6 @@ static const struct input_device_id rfkill_ids[] = { .evbit = { BIT_MASK(EV_KEY) }, .keybit = { [BIT_WORD(KEY_WIMAX)] = BIT_MASK(KEY_WIMAX) }, }, - { - .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT, - .evbit = { BIT(EV_SW) }, - .swbit = { [BIT_WORD(SW_RFKILL_ALL)] = BIT_MASK(SW_RFKILL_ALL) }, - }, { } }; diff --git a/trunk/net/rfkill/rfkill-input.h b/trunk/net/rfkill/rfkill-input.h index f63d05045685..4dae5006fc77 100644 --- a/trunk/net/rfkill/rfkill-input.h +++ b/trunk/net/rfkill/rfkill-input.h @@ -12,6 +12,5 @@ #define __RFKILL_INPUT_H void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state); -void rfkill_epo(void); #endif /* __RFKILL_INPUT_H */ diff --git a/trunk/net/rfkill/rfkill.c b/trunk/net/rfkill/rfkill.c index ce0e23148cdd..4e10a95de832 100644 --- a/trunk/net/rfkill/rfkill.c +++ b/trunk/net/rfkill/rfkill.c @@ -39,56 +39,8 @@ MODULE_LICENSE("GPL"); static LIST_HEAD(rfkill_list); /* list of registered rf switches */ static DEFINE_MUTEX(rfkill_mutex); -static unsigned int rfkill_default_state = RFKILL_STATE_UNBLOCKED; -module_param_named(default_state, rfkill_default_state, uint, 0444); -MODULE_PARM_DESC(default_state, - "Default initial state for all radio types, 0 = radio off"); - static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX]; -static BLOCKING_NOTIFIER_HEAD(rfkill_notifier_list); - - -/** - * register_rfkill_notifier - Add notifier to rfkill notifier chain - * @nb: pointer to the new entry to add to the chain - * - * See blocking_notifier_chain_register() for return value and further - * observations. - * - * Adds a notifier to the rfkill notifier chain. The chain will be - * called with a pointer to the relevant rfkill structure as a parameter, - * refer to include/linux/rfkill.h for the possible events. - * - * Notifiers added to this chain are to always return NOTIFY_DONE. This - * chain is a blocking notifier chain: notifiers can sleep. - * - * Calls to this chain may have been done through a workqueue. One must - * assume unordered asynchronous behaviour, there is no way to know if - * actions related to the event that generated the notification have been - * carried out already. - */ -int register_rfkill_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&rfkill_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(register_rfkill_notifier); - -/** - * unregister_rfkill_notifier - remove notifier from rfkill notifier chain - * @nb: pointer to the entry to remove from the chain - * - * See blocking_notifier_chain_unregister() for return value and further - * observations. - * - * Removes a notifier from the rfkill notifier chain. - */ -int unregister_rfkill_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&rfkill_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(unregister_rfkill_notifier); - static void rfkill_led_trigger(struct rfkill *rfkill, enum rfkill_state state) @@ -98,99 +50,24 @@ static void rfkill_led_trigger(struct rfkill *rfkill, if (!led->name) return; - if (state != RFKILL_STATE_UNBLOCKED) + if (state == RFKILL_STATE_OFF) led_trigger_event(led, LED_OFF); else led_trigger_event(led, LED_FULL); #endif /* CONFIG_RFKILL_LEDS */ } -static void notify_rfkill_state_change(struct rfkill *rfkill) -{ - blocking_notifier_call_chain(&rfkill_notifier_list, - RFKILL_STATE_CHANGED, - rfkill); -} - -static void update_rfkill_state(struct rfkill *rfkill) -{ - enum rfkill_state newstate, oldstate; - - if (rfkill->get_state) { - mutex_lock(&rfkill->mutex); - if (!rfkill->get_state(rfkill->data, &newstate)) { - oldstate = rfkill->state; - rfkill->state = newstate; - if (oldstate != newstate) - notify_rfkill_state_change(rfkill); - } - mutex_unlock(&rfkill->mutex); - } -} - -/** - * rfkill_toggle_radio - wrapper for toggle_radio hook - * calls toggle_radio taking into account a lot of "small" - * details. - * @rfkill: the rfkill struct to use - * @force: calls toggle_radio even if cache says it is not needed, - * and also makes sure notifications of the state will be - * sent even if it didn't change - * @state: the new state to call toggle_radio() with - * - * This wrappen protects and enforces the API for toggle_radio - * calls. Note that @force cannot override a (possibly cached) - * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of - * RFKILL_STATE_HARD_BLOCKED implements either get_state() or - * rfkill_force_state(), so the cache either is bypassed or valid. - * - * Note that we do call toggle_radio for RFKILL_STATE_SOFT_BLOCKED - * even if the radio is in RFKILL_STATE_HARD_BLOCKED state, so as to - * give the driver a hint that it should double-BLOCK the transmitter. - * - * Caller must have aquired rfkill_mutex. - */ static int rfkill_toggle_radio(struct rfkill *rfkill, - enum rfkill_state state, - int force) + enum rfkill_state state) { int retval = 0; - enum rfkill_state oldstate, newstate; - - oldstate = rfkill->state; - if (rfkill->get_state && !force && - !rfkill->get_state(rfkill->data, &newstate)) - rfkill->state = newstate; - - switch (state) { - case RFKILL_STATE_HARD_BLOCKED: - /* typically happens when refreshing hardware state, - * such as on resume */ - state = RFKILL_STATE_SOFT_BLOCKED; - break; - case RFKILL_STATE_UNBLOCKED: - /* force can't override this, only rfkill_force_state() can */ - if (rfkill->state == RFKILL_STATE_HARD_BLOCKED) - return -EPERM; - break; - case RFKILL_STATE_SOFT_BLOCKED: - /* nothing to do, we want to give drivers the hint to double - * BLOCK even a transmitter that is already in state - * RFKILL_STATE_HARD_BLOCKED */ - break; - } - - if (force || state != rfkill->state) { + if (state != rfkill->state) { retval = rfkill->toggle_radio(rfkill->data, state); - /* never allow a HARD->SOFT downgrade! */ - if (!retval && rfkill->state != RFKILL_STATE_HARD_BLOCKED) + if (!retval) { rfkill->state = state; - } - - if (force || rfkill->state != oldstate) { - rfkill_led_trigger(rfkill, rfkill->state); - notify_rfkill_state_change(rfkill); + rfkill_led_trigger(rfkill, state); + } } return retval; @@ -205,6 +82,7 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, * a specific switch is claimed by userspace in which case it is * left alone. */ + void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) { struct rfkill *rfkill; @@ -215,66 +93,13 @@ void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) list_for_each_entry(rfkill, &rfkill_list, node) { if ((!rfkill->user_claim) && (rfkill->type == type)) - rfkill_toggle_radio(rfkill, state, 0); + rfkill_toggle_radio(rfkill, state); } mutex_unlock(&rfkill_mutex); } EXPORT_SYMBOL(rfkill_switch_all); -/** - * rfkill_epo - emergency power off all transmitters - * - * This kicks all rfkill devices to RFKILL_STATE_SOFT_BLOCKED, ignoring - * everything in its path but rfkill_mutex. - */ -void rfkill_epo(void) -{ - struct rfkill *rfkill; - - mutex_lock(&rfkill_mutex); - list_for_each_entry(rfkill, &rfkill_list, node) { - rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); - } - mutex_unlock(&rfkill_mutex); -} -EXPORT_SYMBOL_GPL(rfkill_epo); - -/** - * rfkill_force_state - Force the internal rfkill radio state - * @rfkill: pointer to the rfkill class to modify. - * @state: the current radio state the class should be forced to. - * - * This function updates the internal state of the radio cached - * by the rfkill class. It should be used when the driver gets - * a notification by the firmware/hardware of the current *real* - * state of the radio rfkill switch. - * - * It may not be called from an atomic context. - */ -int rfkill_force_state(struct rfkill *rfkill, enum rfkill_state state) -{ - enum rfkill_state oldstate; - - if (state != RFKILL_STATE_SOFT_BLOCKED && - state != RFKILL_STATE_UNBLOCKED && - state != RFKILL_STATE_HARD_BLOCKED) - return -EINVAL; - - mutex_lock(&rfkill->mutex); - - oldstate = rfkill->state; - rfkill->state = state; - - if (state != oldstate) - notify_rfkill_state_change(rfkill); - - mutex_unlock(&rfkill->mutex); - - return 0; -} -EXPORT_SYMBOL(rfkill_force_state); - static ssize_t rfkill_name_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -284,31 +109,31 @@ static ssize_t rfkill_name_show(struct device *dev, return sprintf(buf, "%s\n", rfkill->name); } -static const char *rfkill_get_type_str(enum rfkill_type type) +static ssize_t rfkill_type_show(struct device *dev, + struct device_attribute *attr, + char *buf) { - switch (type) { + struct rfkill *rfkill = to_rfkill(dev); + const char *type; + + switch (rfkill->type) { case RFKILL_TYPE_WLAN: - return "wlan"; + type = "wlan"; + break; case RFKILL_TYPE_BLUETOOTH: - return "bluetooth"; + type = "bluetooth"; + break; case RFKILL_TYPE_UWB: - return "ultrawideband"; + type = "ultrawideband"; + break; case RFKILL_TYPE_WIMAX: - return "wimax"; - case RFKILL_TYPE_WWAN: - return "wwan"; + type = "wimax"; + break; default: BUG(); } -} - -static ssize_t rfkill_type_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct rfkill *rfkill = to_rfkill(dev); - return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type)); + return sprintf(buf, "%s\n", type); } static ssize_t rfkill_state_show(struct device *dev, @@ -317,7 +142,6 @@ static ssize_t rfkill_state_show(struct device *dev, { struct rfkill *rfkill = to_rfkill(dev); - update_rfkill_state(rfkill); return sprintf(buf, "%d\n", rfkill->state); } @@ -332,14 +156,10 @@ static ssize_t rfkill_state_store(struct device *dev, if (!capable(CAP_NET_ADMIN)) return -EPERM; - /* RFKILL_STATE_HARD_BLOCKED is illegal here... */ - if (state != RFKILL_STATE_UNBLOCKED && - state != RFKILL_STATE_SOFT_BLOCKED) - return -EINVAL; - if (mutex_lock_interruptible(&rfkill->mutex)) return -ERESTARTSYS; - error = rfkill_toggle_radio(rfkill, state, 0); + error = rfkill_toggle_radio(rfkill, + state ? RFKILL_STATE_ON : RFKILL_STATE_OFF); mutex_unlock(&rfkill->mutex); return error ? error : count; @@ -380,8 +200,7 @@ static ssize_t rfkill_claim_store(struct device *dev, if (rfkill->user_claim != claim) { if (!claim) rfkill_toggle_radio(rfkill, - rfkill_states[rfkill->type], - 0); + rfkill_states[rfkill->type]); rfkill->user_claim = claim; } @@ -414,12 +233,12 @@ static int rfkill_suspend(struct device *dev, pm_message_t state) if (dev->power.power_state.event != state.event) { if (state.event & PM_EVENT_SLEEP) { - /* Stop transmitter, keep state, no notifies */ - update_rfkill_state(rfkill); - mutex_lock(&rfkill->mutex); - rfkill->toggle_radio(rfkill->data, - RFKILL_STATE_SOFT_BLOCKED); + + if (rfkill->state == RFKILL_STATE_ON) + rfkill->toggle_radio(rfkill->data, + RFKILL_STATE_OFF); + mutex_unlock(&rfkill->mutex); } @@ -436,8 +255,8 @@ static int rfkill_resume(struct device *dev) if (dev->power.power_state.event != PM_EVENT_ON) { mutex_lock(&rfkill->mutex); - /* restore radio state AND notify everybody */ - rfkill_toggle_radio(rfkill, rfkill->state, 1); + if (rfkill->state == RFKILL_STATE_ON) + rfkill->toggle_radio(rfkill->data, RFKILL_STATE_ON); mutex_unlock(&rfkill->mutex); } @@ -450,51 +269,12 @@ static int rfkill_resume(struct device *dev) #define rfkill_resume NULL #endif -static int rfkill_blocking_uevent_notifier(struct notifier_block *nb, - unsigned long eventid, - void *data) -{ - struct rfkill *rfkill = (struct rfkill *)data; - - switch (eventid) { - case RFKILL_STATE_CHANGED: - kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); - break; - default: - break; - } - - return NOTIFY_DONE; -} - -static struct notifier_block rfkill_blocking_uevent_nb = { - .notifier_call = rfkill_blocking_uevent_notifier, - .priority = 0, -}; - -static int rfkill_dev_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct rfkill *rfkill = to_rfkill(dev); - int error; - - error = add_uevent_var(env, "RFKILL_NAME=%s", rfkill->name); - if (error) - return error; - error = add_uevent_var(env, "RFKILL_TYPE=%s", - rfkill_get_type_str(rfkill->type)); - if (error) - return error; - error = add_uevent_var(env, "RFKILL_STATE=%d", rfkill->state); - return error; -} - static struct class rfkill_class = { .name = "rfkill", .dev_release = rfkill_release, .dev_attrs = rfkill_dev_attrs, .suspend = rfkill_suspend, .resume = rfkill_resume, - .dev_uevent = rfkill_dev_uevent, }; static int rfkill_add_switch(struct rfkill *rfkill) @@ -503,7 +283,7 @@ static int rfkill_add_switch(struct rfkill *rfkill) mutex_lock(&rfkill_mutex); - error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); + error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]); if (!error) list_add_tail(&rfkill->node, &rfkill_list); @@ -516,7 +296,7 @@ static void rfkill_remove_switch(struct rfkill *rfkill) { mutex_lock(&rfkill_mutex); list_del_init(&rfkill->node); - rfkill_toggle_radio(rfkill, RFKILL_STATE_SOFT_BLOCKED, 1); + rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF); mutex_unlock(&rfkill_mutex); } @@ -632,7 +412,7 @@ int rfkill_register(struct rfkill *rfkill) EXPORT_SYMBOL(rfkill_register); /** - * rfkill_unregister - Unregister a rfkill structure. + * rfkill_unregister - Uegister a rfkill structure. * @rfkill: rfkill structure to be unregistered * * This function should be called by the network driver during device @@ -656,13 +436,8 @@ static int __init rfkill_init(void) int error; int i; - /* RFKILL_STATE_HARD_BLOCKED is illegal here... */ - if (rfkill_default_state != RFKILL_STATE_SOFT_BLOCKED && - rfkill_default_state != RFKILL_STATE_UNBLOCKED) - return -EINVAL; - for (i = 0; i < ARRAY_SIZE(rfkill_states); i++) - rfkill_states[i] = rfkill_default_state; + rfkill_states[i] = RFKILL_STATE_ON; error = class_register(&rfkill_class); if (error) { @@ -670,14 +445,11 @@ static int __init rfkill_init(void) return error; } - register_rfkill_notifier(&rfkill_blocking_uevent_nb); - return 0; } static void __exit rfkill_exit(void) { - unregister_rfkill_notifier(&rfkill_blocking_uevent_nb); class_unregister(&rfkill_class); } diff --git a/trunk/net/sched/Kconfig b/trunk/net/sched/Kconfig index 9437b27ff84d..82adfe6447d7 100644 --- a/trunk/net/sched/Kconfig +++ b/trunk/net/sched/Kconfig @@ -106,6 +106,17 @@ config NET_SCH_PRIO To compile this code as a module, choose M here: the module will be called sch_prio. +config NET_SCH_RR + tristate "Multi Band Round Robin Queuing (RR)" + select NET_SCH_PRIO + ---help--- + Say Y here if you want to use an n-band round robin packet + scheduler. + + The module uses sch_prio for its framework and is aliased as + sch_rr, so it will load sch_prio, although it is referred + to using sch_rr. + config NET_SCH_RED tristate "Random Early Detection (RED)" ---help--- diff --git a/trunk/net/sched/sch_generic.c b/trunk/net/sched/sch_generic.c index 13afa7214392..d355e5e47fe3 100644 --- a/trunk/net/sched/sch_generic.c +++ b/trunk/net/sched/sch_generic.c @@ -468,7 +468,7 @@ struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops) return sch; errout: - return ERR_PTR(err); + return ERR_PTR(-err); } struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops, diff --git a/trunk/net/sctp/socket.c b/trunk/net/sctp/socket.c index df5572c39f0c..f98650cc48d8 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -4223,8 +4223,6 @@ static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len, if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) return -EFAULT; - printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_NUM_OLD " - "socket option deprecated\n"); /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, id); if (!asoc) @@ -4264,9 +4262,6 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len, if (getaddrs.addr_num <= 0) return -EINVAL; - printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_OLD " - "socket option deprecated\n"); - /* For UDP-style sockets, id specifies the association to query. */ asoc = sctp_id2assoc(sk, getaddrs.assoc_id); if (!asoc) @@ -4360,9 +4355,6 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, if (copy_from_user(&id, optval, sizeof(sctp_assoc_t))) return -EFAULT; - printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_NUM_OLD " - "socket option deprecated\n"); - /* * For UDP-style sockets, id specifies the association to query. * If the id field is set to the value '0' then the locally bound @@ -4520,13 +4512,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, if (copy_from_user(&getaddrs, optval, len)) return -EFAULT; - if (getaddrs.addr_num <= 0 || - getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr))) - return -EINVAL; - - printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_OLD " - "socket option deprecated\n"); - + if (getaddrs.addr_num <= 0) return -EINVAL; /* * For UDP-style sockets, id specifies the association to query. * If the id field is set to the value '0' then the locally bound diff --git a/trunk/net/socket.c b/trunk/net/socket.c index 81fe82513046..66c4a8cf6db9 100644 --- a/trunk/net/socket.c +++ b/trunk/net/socket.c @@ -90,7 +90,6 @@ #include #include -#include #include #include @@ -2211,19 +2210,10 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd, { struct socket *sock = file->private_data; int ret = -ENOIOCTLCMD; - struct sock *sk; - struct net *net; - - sk = sock->sk; - net = sock_net(sk); if (sock->ops->compat_ioctl) ret = sock->ops->compat_ioctl(sock, cmd, arg); - if (ret == -ENOIOCTLCMD && - (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) - ret = compat_wext_handle_ioctl(net, cmd, arg); - return ret; } #endif diff --git a/trunk/net/unix/af_unix.c b/trunk/net/unix/af_unix.c index 70ceb1604ad8..b4280490cf6e 100644 --- a/trunk/net/unix/af_unix.c +++ b/trunk/net/unix/af_unix.c @@ -485,8 +485,8 @@ static int unix_socketpair(struct socket *, struct socket *); static int unix_accept(struct socket *, struct socket *, int); static int unix_getname(struct socket *, struct sockaddr *, int *, int); static unsigned int unix_poll(struct file *, struct socket *, poll_table *); -static unsigned int unix_dgram_poll(struct file *, struct socket *, - poll_table *); +static unsigned int unix_datagram_poll(struct file *, struct socket *, + poll_table *); static int unix_ioctl(struct socket *, unsigned int, unsigned long); static int unix_shutdown(struct socket *, int); static int unix_stream_sendmsg(struct kiocb *, struct socket *, @@ -532,7 +532,7 @@ static const struct proto_ops unix_dgram_ops = { .socketpair = unix_socketpair, .accept = sock_no_accept, .getname = unix_getname, - .poll = unix_dgram_poll, + .poll = unix_datagram_poll, .ioctl = unix_ioctl, .listen = sock_no_listen, .shutdown = unix_shutdown, @@ -553,7 +553,7 @@ static const struct proto_ops unix_seqpacket_ops = { .socketpair = unix_socketpair, .accept = unix_accept, .getname = unix_getname, - .poll = unix_dgram_poll, + .poll = unix_datagram_poll, .ioctl = unix_ioctl, .listen = unix_listen, .shutdown = unix_shutdown, @@ -1992,13 +1992,29 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl return mask; } -static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, - poll_table *wait) +static unsigned int unix_datagram_poll(struct file *file, struct socket *sock, + poll_table *wait) { - struct sock *sk = sock->sk, *other; - unsigned int mask, writable; + struct sock *sk = sock->sk, *peer; + unsigned int mask; poll_wait(file, sk->sk_sleep, wait); + + peer = unix_peer_get(sk); + if (peer) { + if (peer != sk) { + /* + * Writability of a connected socket additionally + * depends on the state of the receive queue of the + * peer. + */ + poll_wait(file, &unix_sk(peer)->peer_wait, wait); + } else { + sock_put(peer); + peer = NULL; + } + } + mask = 0; /* exceptional events? */ @@ -2024,26 +2040,14 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, } /* writable? */ - writable = unix_writable(sk); - if (writable) { - other = unix_peer_get(sk); - if (other) { - if (unix_peer(other) != sk) { - poll_wait(file, &unix_sk(other)->peer_wait, - wait); - if (unix_recvq_full(other)) - writable = 0; - } - - sock_put(other); - } - } - - if (writable) + if (unix_writable(sk) && !(peer && unix_recvq_full(peer))) mask |= POLLOUT | POLLWRNORM | POLLWRBAND; else set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); + if (peer) + sock_put(peer); + return mask; } diff --git a/trunk/net/wireless/wext.c b/trunk/net/wireless/wext.c index 273a84359998..947188a5b937 100644 --- a/trunk/net/wireless/wext.c +++ b/trunk/net/wireless/wext.c @@ -500,7 +500,7 @@ static int call_commit_handler(struct net_device *dev) /* * Calculate size of private arguments */ -static int get_priv_size(__u16 args) +static inline int get_priv_size(__u16 args) { int num = args & IW_PRIV_SIZE_MASK; int type = (args & IW_PRIV_TYPE_MASK) >> 12; @@ -512,9 +512,10 @@ static int get_priv_size(__u16 args) /* * Re-calculate the size of private arguments */ -static int adjust_priv_size(__u16 args, struct iw_point *iwp) +static inline int adjust_priv_size(__u16 args, + union iwreq_data * wrqu) { - int num = iwp->length; + int num = wrqu->data.length; int max = args & IW_PRIV_SIZE_MASK; int type = (args & IW_PRIV_TYPE_MASK) >> 12; @@ -694,150 +695,19 @@ void wext_proc_exit(struct net *net) */ /* ---------------------------------------------------------------- */ -static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, - const struct iw_ioctl_description *descr, - iw_handler handler, struct net_device *dev, - struct iw_request_info *info) -{ - int err, extra_size, user_length = 0, essid_compat = 0; - char *extra; - - /* Calculate space needed by arguments. Always allocate - * for max space. - */ - extra_size = descr->max_tokens * descr->token_size; - - /* Check need for ESSID compatibility for WE < 21 */ - switch (cmd) { - case SIOCSIWESSID: - case SIOCGIWESSID: - case SIOCSIWNICKN: - case SIOCGIWNICKN: - if (iwp->length == descr->max_tokens + 1) - essid_compat = 1; - else if (IW_IS_SET(cmd) && (iwp->length != 0)) { - char essid[IW_ESSID_MAX_SIZE + 1]; - - err = copy_from_user(essid, iwp->pointer, - iwp->length * - descr->token_size); - if (err) - return -EFAULT; - - if (essid[iwp->length - 1] == '\0') - essid_compat = 1; - } - break; - default: - break; - } - - iwp->length -= essid_compat; - - /* Check what user space is giving us */ - if (IW_IS_SET(cmd)) { - /* Check NULL pointer */ - if (!iwp->pointer && iwp->length != 0) - return -EFAULT; - /* Check if number of token fits within bounds */ - if (iwp->length > descr->max_tokens) - return -E2BIG; - if (iwp->length < descr->min_tokens) - return -EINVAL; - } else { - /* Check NULL pointer */ - if (!iwp->pointer) - return -EFAULT; - /* Save user space buffer size for checking */ - user_length = iwp->length; - - /* Don't check if user_length > max to allow forward - * compatibility. The test user_length < min is - * implied by the test at the end. - */ - - /* Support for very large requests */ - if ((descr->flags & IW_DESCR_FLAG_NOMAX) && - (user_length > descr->max_tokens)) { - /* Allow userspace to GET more than max so - * we can support any size GET requests. - * There is still a limit : -ENOMEM. - */ - extra_size = user_length * descr->token_size; - - /* Note : user_length is originally a __u16, - * and token_size is controlled by us, - * so extra_size won't get negative and - * won't overflow... - */ - } - } - - /* kzalloc() ensures NULL-termination for essid_compat. */ - extra = kzalloc(extra_size, GFP_KERNEL); - if (!extra) - return -ENOMEM; - - /* If it is a SET, get all the extra data in here */ - if (IW_IS_SET(cmd) && (iwp->length != 0)) { - if (copy_from_user(extra, iwp->pointer, - iwp->length * - descr->token_size)) { - err = -EFAULT; - goto out; - } - } - - err = handler(dev, info, (union iwreq_data *) iwp, extra); - - iwp->length += essid_compat; - - /* If we have something to return to the user */ - if (!err && IW_IS_GET(cmd)) { - /* Check if there is enough buffer up there */ - if (user_length < iwp->length) { - err = -E2BIG; - goto out; - } - - if (copy_to_user(iwp->pointer, extra, - iwp->length * - descr->token_size)) { - err = -EFAULT; - goto out; - } - } - - /* Generate an event to notify listeners of the change */ - if ((descr->flags & IW_DESCR_FLAG_EVENT) && err == -EIWCOMMIT) { - union iwreq_data *data = (union iwreq_data *) iwp; - - if (descr->flags & IW_DESCR_FLAG_RESTRICT) - /* If the event is restricted, don't - * export the payload. - */ - wireless_send_event(dev, cmd, data, NULL); - else - wireless_send_event(dev, cmd, data, extra); - } - -out: - kfree(extra); - return err; -} - /* * Wrapper to call a standard Wireless Extension handler. * We do various checks and also take care of moving data between * user space and kernel space. */ static int ioctl_standard_call(struct net_device * dev, - struct iwreq *iwr, + struct ifreq * ifr, unsigned int cmd, - struct iw_request_info *info, iw_handler handler) { + struct iwreq * iwr = (struct iwreq *) ifr; const struct iw_ioctl_description * descr; + struct iw_request_info info; int ret = -EINVAL; /* Get the description of the IOCTL */ @@ -845,19 +715,145 @@ static int ioctl_standard_call(struct net_device * dev, return -EOPNOTSUPP; descr = &(standard_ioctl[cmd - SIOCIWFIRST]); + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; + /* Check if we have a pointer to user space data or not */ if (descr->header_type != IW_HEADER_TYPE_POINT) { /* No extra arguments. Trivial to handle */ - ret = handler(dev, info, &(iwr->u), NULL); + ret = handler(dev, &info, &(iwr->u), NULL); /* Generate an event to notify listeners of the change */ if ((descr->flags & IW_DESCR_FLAG_EVENT) && ((ret == 0) || (ret == -EIWCOMMIT))) wireless_send_event(dev, cmd, &(iwr->u), NULL); } else { - ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr, - handler, dev, info); + char * extra; + int extra_size; + int user_length = 0; + int err; + int essid_compat = 0; + + /* Calculate space needed by arguments. Always allocate + * for max space. Easier, and won't last long... */ + extra_size = descr->max_tokens * descr->token_size; + + /* Check need for ESSID compatibility for WE < 21 */ + switch (cmd) { + case SIOCSIWESSID: + case SIOCGIWESSID: + case SIOCSIWNICKN: + case SIOCGIWNICKN: + if (iwr->u.data.length == descr->max_tokens + 1) + essid_compat = 1; + else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { + char essid[IW_ESSID_MAX_SIZE + 1]; + + err = copy_from_user(essid, iwr->u.data.pointer, + iwr->u.data.length * + descr->token_size); + if (err) + return -EFAULT; + + if (essid[iwr->u.data.length - 1] == '\0') + essid_compat = 1; + } + break; + default: + break; + } + + iwr->u.data.length -= essid_compat; + + /* Check what user space is giving us */ + if (IW_IS_SET(cmd)) { + /* Check NULL pointer */ + if ((iwr->u.data.pointer == NULL) && + (iwr->u.data.length != 0)) + return -EFAULT; + /* Check if number of token fits within bounds */ + if (iwr->u.data.length > descr->max_tokens) + return -E2BIG; + if (iwr->u.data.length < descr->min_tokens) + return -EINVAL; + } else { + /* Check NULL pointer */ + if (iwr->u.data.pointer == NULL) + return -EFAULT; + /* Save user space buffer size for checking */ + user_length = iwr->u.data.length; + + /* Don't check if user_length > max to allow forward + * compatibility. The test user_length < min is + * implied by the test at the end. */ + + /* Support for very large requests */ + if ((descr->flags & IW_DESCR_FLAG_NOMAX) && + (user_length > descr->max_tokens)) { + /* Allow userspace to GET more than max so + * we can support any size GET requests. + * There is still a limit : -ENOMEM. */ + extra_size = user_length * descr->token_size; + /* Note : user_length is originally a __u16, + * and token_size is controlled by us, + * so extra_size won't get negative and + * won't overflow... */ + } + } + + /* Create the kernel buffer */ + /* kzalloc ensures NULL-termination for essid_compat */ + extra = kzalloc(extra_size, GFP_KERNEL); + if (extra == NULL) + return -ENOMEM; + + /* If it is a SET, get all the extra data in here */ + if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { + err = copy_from_user(extra, iwr->u.data.pointer, + iwr->u.data.length * + descr->token_size); + if (err) { + kfree(extra); + return -EFAULT; + } + } + + /* Call the handler */ + ret = handler(dev, &info, &(iwr->u), extra); + + iwr->u.data.length += essid_compat; + + /* If we have something to return to the user */ + if (!ret && IW_IS_GET(cmd)) { + /* Check if there is enough buffer up there */ + if (user_length < iwr->u.data.length) { + kfree(extra); + return -E2BIG; + } + + err = copy_to_user(iwr->u.data.pointer, extra, + iwr->u.data.length * + descr->token_size); + if (err) + ret = -EFAULT; + } + + /* Generate an event to notify listeners of the change */ + if ((descr->flags & IW_DESCR_FLAG_EVENT) && + ((ret == 0) || (ret == -EIWCOMMIT))) { + if (descr->flags & IW_DESCR_FLAG_RESTRICT) + /* If the event is restricted, don't + * export the payload */ + wireless_send_event(dev, cmd, &(iwr->u), NULL); + else + wireless_send_event(dev, cmd, &(iwr->u), + extra); + } + + /* Cleanup - I told you it wasn't that long ;-) */ + kfree(extra); } /* Call commit handler if needed and defined */ @@ -885,22 +881,25 @@ static int ioctl_standard_call(struct net_device * dev, * a iw_handler but process it in your ioctl handler (i.e. use the * old driver API). */ -static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd, - const struct iw_priv_args **descrp) +static int ioctl_private_call(struct net_device *dev, struct ifreq *ifr, + unsigned int cmd, iw_handler handler) { - const struct iw_priv_args *descr; - int i, extra_size; + struct iwreq * iwr = (struct iwreq *) ifr; + const struct iw_priv_args * descr = NULL; + struct iw_request_info info; + int extra_size = 0; + int i; + int ret = -EINVAL; - descr = NULL; - for (i = 0; i < dev->wireless_handlers->num_private_args; i++) { + /* Get the description of the IOCTL */ + for (i = 0; i < dev->wireless_handlers->num_private_args; i++) if (cmd == dev->wireless_handlers->private_args[i].cmd) { - descr = &dev->wireless_handlers->private_args[i]; + descr = &(dev->wireless_handlers->private_args[i]); break; } - } - extra_size = 0; - if (descr) { + /* Compute the size of the set/get arguments */ + if (descr != NULL) { if (IW_IS_SET(cmd)) { int offset = 0; /* For sub-ioctls */ /* Check for sub-ioctl handler */ @@ -925,78 +924,73 @@ static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd, extra_size = 0; } } - *descrp = descr; - return extra_size; -} -static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, - const struct iw_priv_args *descr, - iw_handler handler, struct net_device *dev, - struct iw_request_info *info, int extra_size) -{ - char *extra; - int err; + /* Prepare the call */ + info.cmd = cmd; + info.flags = 0; - /* Check what user space is giving us */ - if (IW_IS_SET(cmd)) { - if (!iwp->pointer && iwp->length != 0) - return -EFAULT; + /* Check if we have a pointer to user space data or not. */ + if (extra_size == 0) { + /* No extra arguments. Trivial to handle */ + ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); + } else { + char * extra; + int err; - if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK)) - return -E2BIG; - } else if (!iwp->pointer) - return -EFAULT; + /* Check what user space is giving us */ + if (IW_IS_SET(cmd)) { + /* Check NULL pointer */ + if ((iwr->u.data.pointer == NULL) && + (iwr->u.data.length != 0)) + return -EFAULT; - extra = kmalloc(extra_size, GFP_KERNEL); - if (!extra) - return -ENOMEM; + /* Does it fits within bounds ? */ + if (iwr->u.data.length > (descr->set_args & + IW_PRIV_SIZE_MASK)) + return -E2BIG; + } else if (iwr->u.data.pointer == NULL) + return -EFAULT; - /* If it is a SET, get all the extra data in here */ - if (IW_IS_SET(cmd) && (iwp->length != 0)) { - if (copy_from_user(extra, iwp->pointer, extra_size)) { - err = -EFAULT; - goto out; + /* Always allocate for max space. Easier, and won't last + * long... */ + extra = kmalloc(extra_size, GFP_KERNEL); + if (extra == NULL) + return -ENOMEM; + + /* If it is a SET, get all the extra data in here */ + if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { + err = copy_from_user(extra, iwr->u.data.pointer, + extra_size); + if (err) { + kfree(extra); + return -EFAULT; + } } - } - /* Call the handler */ - err = handler(dev, info, (union iwreq_data *) iwp, extra); + /* Call the handler */ + ret = handler(dev, &info, &(iwr->u), extra); - /* If we have something to return to the user */ - if (!err && IW_IS_GET(cmd)) { - /* Adjust for the actual length if it's variable, - * avoid leaking kernel bits outside. - */ - if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) - extra_size = adjust_priv_size(descr->get_args, iwp); + /* If we have something to return to the user */ + if (!ret && IW_IS_GET(cmd)) { - if (copy_to_user(iwp->pointer, extra, extra_size)) - err = -EFAULT; - } - -out: - kfree(extra); - return err; -} - -static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, - unsigned int cmd, struct iw_request_info *info, - iw_handler handler) -{ - int extra_size = 0, ret = -EINVAL; - const struct iw_priv_args *descr; + /* Adjust for the actual length if it's variable, + * avoid leaking kernel bits outside. */ + if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) { + extra_size = adjust_priv_size(descr->get_args, + &(iwr->u)); + } - extra_size = get_priv_descr_and_size(dev, cmd, &descr); + err = copy_to_user(iwr->u.data.pointer, extra, + extra_size); + if (err) + ret = -EFAULT; + } - /* Check if we have a pointer to user space data or not. */ - if (extra_size == 0) { - /* No extra arguments. Trivial to handle */ - ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); - } else { - ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, - handler, dev, info, extra_size); + /* Cleanup - I told you it wasn't that long ;-) */ + kfree(extra); } + /* Call commit handler if needed and defined */ if (ret == -EIWCOMMIT) ret = call_commit_handler(dev); @@ -1005,21 +999,12 @@ static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, } /* ---------------------------------------------------------------- */ -typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, - unsigned int, struct iw_request_info *, - iw_handler); - /* * Main IOCTl dispatcher. * Check the type of IOCTL and call the appropriate wrapper... */ -static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, - unsigned int cmd, - struct iw_request_info *info, - wext_ioctl_func standard, - wext_ioctl_func private) +static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd) { - struct iwreq *iwr = (struct iwreq *) ifr; struct net_device *dev; iw_handler handler; @@ -1034,12 +1019,12 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, * Note that 'cmd' is already filtered in dev_ioctl() with * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ if (cmd == SIOCGIWSTATS) - return standard(dev, iwr, cmd, info, - &iw_handler_get_iwstats); + return ioctl_standard_call(dev, ifr, cmd, + &iw_handler_get_iwstats); if (cmd == SIOCGIWPRIV && dev->wireless_handlers) - return standard(dev, iwr, cmd, info, - &iw_handler_get_private); + return ioctl_standard_call(dev, ifr, cmd, + &iw_handler_get_private); /* Basic check */ if (!netif_device_present(dev)) @@ -1050,9 +1035,9 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, if (handler) { /* Standard and private are not the same */ if (cmd < SIOCIWFIRSTPRIV) - return standard(dev, iwr, cmd, info, handler); + return ioctl_standard_call(dev, ifr, cmd, handler); else - return private(dev, iwr, cmd, info, handler); + return ioctl_private_call(dev, ifr, cmd, handler); } /* Old driver API : call driver ioctl handler */ if (dev->do_ioctl) @@ -1060,154 +1045,27 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, return -EOPNOTSUPP; } -/* If command is `set a parameter', or `get the encoding parameters', - * check if the user has the right to do it. - */ -static int wext_permission_check(unsigned int cmd) +/* entry point from dev ioctl */ +int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, + void __user *arg) { + int ret; + + /* If command is `set a parameter', or + * `get the encoding parameters', check if + * the user has the right to do it */ if ((IW_IS_SET(cmd) || cmd == SIOCGIWENCODE || cmd == SIOCGIWENCODEEXT) && !capable(CAP_NET_ADMIN)) return -EPERM; - return 0; -} - -/* entry point from dev ioctl */ -static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, - unsigned int cmd, struct iw_request_info *info, - wext_ioctl_func standard, - wext_ioctl_func private) -{ - int ret = wext_permission_check(cmd); - - if (ret) - return ret; - dev_load(net, ifr->ifr_name); rtnl_lock(); - ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private); + ret = wireless_process_ioctl(net, ifr, cmd); rtnl_unlock(); - - return ret; -} - -int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, - void __user *arg) -{ - struct iw_request_info info = { .cmd = cmd, .flags = 0 }; - int ret; - - ret = wext_ioctl_dispatch(net, ifr, cmd, &info, - ioctl_standard_call, - ioctl_private_call); - if (ret >= 0 && - IW_IS_GET(cmd) && - copy_to_user(arg, ifr, sizeof(struct iwreq))) - return -EFAULT; - - return ret; -} - -#ifdef CONFIG_COMPAT -static int compat_standard_call(struct net_device *dev, - struct iwreq *iwr, - unsigned int cmd, - struct iw_request_info *info, - iw_handler handler) -{ - const struct iw_ioctl_description *descr; - struct compat_iw_point *iwp_compat; - struct iw_point iwp; - int err; - - descr = standard_ioctl + (cmd - SIOCIWFIRST); - - if (descr->header_type != IW_HEADER_TYPE_POINT) - return ioctl_standard_call(dev, iwr, cmd, info, handler); - - iwp_compat = (struct compat_iw_point *) &iwr->u.data; - iwp.pointer = compat_ptr(iwp_compat->pointer); - iwp.length = iwp_compat->length; - iwp.flags = iwp_compat->flags; - - err = ioctl_standard_iw_point(&iwp, cmd, descr, handler, dev, info); - - iwp_compat->pointer = ptr_to_compat(iwp.pointer); - iwp_compat->length = iwp.length; - iwp_compat->flags = iwp.flags; - - return err; -} - -static int compat_private_call(struct net_device *dev, struct iwreq *iwr, - unsigned int cmd, struct iw_request_info *info, - iw_handler handler) -{ - const struct iw_priv_args *descr; - int ret, extra_size; - - extra_size = get_priv_descr_and_size(dev, cmd, &descr); - - /* Check if we have a pointer to user space data or not. */ - if (extra_size == 0) { - /* No extra arguments. Trivial to handle */ - ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); - } else { - struct compat_iw_point *iwp_compat; - struct iw_point iwp; - - iwp_compat = (struct compat_iw_point *) &iwr->u.data; - iwp.pointer = compat_ptr(iwp_compat->pointer); - iwp.length = iwp_compat->length; - iwp.flags = iwp_compat->flags; - - ret = ioctl_private_iw_point(&iwp, cmd, descr, - handler, dev, info, extra_size); - - iwp_compat->pointer = ptr_to_compat(iwp.pointer); - iwp_compat->length = iwp.length; - iwp_compat->flags = iwp.flags; - } - - /* Call commit handler if needed and defined */ - if (ret == -EIWCOMMIT) - ret = call_commit_handler(dev); - - return ret; -} - -int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, - unsigned long arg) -{ - void __user *argp = (void __user *)arg; - struct iw_request_info info; - struct iwreq iwr; - char *colon; - int ret; - - if (copy_from_user(&iwr, argp, sizeof(struct iwreq))) - return -EFAULT; - - iwr.ifr_name[IFNAMSIZ-1] = 0; - colon = strchr(iwr.ifr_name, ':'); - if (colon) - *colon = 0; - - info.cmd = cmd; - info.flags = IW_REQUEST_FLAG_COMPAT; - - ret = wext_ioctl_dispatch(net, (struct ifreq *) &iwr, cmd, &info, - compat_standard_call, - compat_private_call); - - if (ret >= 0 && - IW_IS_GET(cmd) && - copy_to_user(argp, &iwr, sizeof(struct iwreq))) + if (IW_IS_GET(cmd) && copy_to_user(arg, ifr, sizeof(struct iwreq))) return -EFAULT; - return ret; } -#endif /************************* EVENT PROCESSING *************************/ /*