diff --git a/debian/patches/bugfix/all/patch-2.6.25-rc8-git2 b/debian/patches/bugfix/all/patch-2.6.25-rc8-git2 new file mode 100644 index 000000000..8b9ec8c12 --- /dev/null +++ b/debian/patches/bugfix/all/patch-2.6.25-rc8-git2 @@ -0,0 +1,5349 @@ +diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches +index 08a1ed1..47a539c 100644 +--- a/Documentation/SubmittingPatches ++++ b/Documentation/SubmittingPatches +@@ -512,7 +512,7 @@ They provide type safety, have no length limitations, no formatting + limitations, and under gcc they are as cheap as macros. + + Macros should only be used for cases where a static inline is clearly +-suboptimal [there a few, isolated cases of this in fast paths], ++suboptimal [there are a few, isolated cases of this in fast paths], + or where it is impossible to use a static inline function [such as + string-izing]. + +diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX +index 02e56d4..c485ee0 100644 +--- a/Documentation/networking/00-INDEX ++++ b/Documentation/networking/00-INDEX +@@ -84,9 +84,6 @@ policy-routing.txt + - IP policy-based routing + ray_cs.txt + - Raylink Wireless LAN card driver info. +-sk98lin.txt +- - Marvell Yukon Chipset / SysKonnect SK-98xx compliant Gigabit +- Ethernet Adapter family driver info + skfp.txt + - SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info. + smc9.txt +diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt +deleted file mode 100644 +index 8590a95..0000000 +--- a/Documentation/networking/sk98lin.txt ++++ /dev/null +@@ -1,568 +0,0 @@ +-(C)Copyright 1999-2004 Marvell(R). +-All rights reserved +-=========================================================================== +- +-sk98lin.txt created 13-Feb-2004 +- +-Readme File for sk98lin v6.23 +-Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX +- +-This file contains +- 1 Overview +- 2 Required Files +- 3 Installation +- 3.1 Driver Installation +- 3.2 Inclusion of adapter at system start +- 4 Driver Parameters +- 4.1 Per-Port Parameters +- 4.2 Adapter Parameters +- 5 Large Frame Support +- 6 VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad) +- 7 Troubleshooting +- +-=========================================================================== +- +- +-1 Overview +-=========== +- +-The sk98lin driver supports the Marvell Yukon and SysKonnect +-SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter on Linux. It has +-been tested with Linux on Intel/x86 machines. +-*** +- +- +-2 Required Files +-================= +- +-The linux kernel source. +-No additional files required. +-*** +- +- +-3 Installation +-=============== +- +-It is recommended to download the latest version of the driver from the +-SysKonnect web site www.syskonnect.com. If you have downloaded the latest +-driver, the Linux kernel has to be patched before the driver can be +-installed. For details on how to patch a Linux kernel, refer to the +-patch.txt file. +- +-3.1 Driver Installation +------------------------- +- +-The following steps describe the actions that are required to install +-the driver and to start it manually. These steps should be carried +-out for the initial driver setup. Once confirmed to be ok, they can +-be included in the system start. +- +-NOTE 1: To perform the following tasks you need 'root' access. +- +-NOTE 2: In case of problems, please read the section "Troubleshooting" +- below. +- +-The driver can either be integrated into the kernel or it can be compiled +-as a module. Select the appropriate option during the kernel +-configuration. +- +-Compile/use the driver as a module +----------------------------------- +-To compile the driver, go to the directory /usr/src/linux and +-execute the command "make menuconfig" or "make xconfig" and proceed as +-follows: +- +-To integrate the driver permanently into the kernel, proceed as follows: +- +-1. Select the menu "Network device support" and then "Ethernet(1000Mbit)" +-2. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support" +- with (*) +-3. Build a new kernel when the configuration of the above options is +- finished. +-4. Install the new kernel. +-5. Reboot your system. +- +-To use the driver as a module, proceed as follows: +- +-1. Enable 'loadable module support' in the kernel. +-2. For automatic driver start, enable the 'Kernel module loader'. +-3. Select the menu "Network device support" and then "Ethernet(1000Mbit)" +-4. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support" +- with (M) +-5. Execute the command "make modules". +-6. Execute the command "make modules_install". +- The appropriate modules will be installed. +-7. Reboot your system. +- +- +-Load the module manually +------------------------- +-To load the module manually, proceed as follows: +- +-1. Enter "modprobe sk98lin". +-2. If a Marvell Yukon or SysKonnect SK-98xx adapter is installed in +- your computer and you have a /proc file system, execute the command: +- "ls /proc/net/sk98lin/" +- This should produce an output containing a line with the following +- format: +- eth0 eth1 ... +- which indicates that your adapter has been found and initialized. +- +- NOTE 1: If you have more than one Marvell Yukon or SysKonnect SK-98xx +- adapter installed, the adapters will be listed as 'eth0', +- 'eth1', 'eth2', etc. +- For each adapter, repeat steps 3 and 4 below. +- +- NOTE 2: If you have other Ethernet adapters installed, your Marvell +- Yukon or SysKonnect SK-98xx adapter will be mapped to the +- next available number, e.g. 'eth1'. The mapping is executed +- automatically. +- The module installation message (displayed either in a system +- log file or on the console) prints a line for each adapter +- found containing the corresponding 'ethX'. +- +-3. Select an IP address and assign it to the respective adapter by +- entering: +- ifconfig eth0 +- With this command, the adapter is connected to the Ethernet. +- +- SK-98xx Gigabit Ethernet Server Adapters: The yellow LED on the adapter +- is now active, the link status LED of the primary port is active and +- the link status LED of the secondary port (on dual port adapters) is +- blinking (if the ports are connected to a switch or hub). +- SK-98xx V2.0 Gigabit Ethernet Adapters: The link status LED is active. +- In addition, you will receive a status message on the console stating +- "ethX: network connection up using port Y" and showing the selected +- connection parameters (x stands for the ethernet device number +- (0,1,2, etc), y stands for the port name (A or B)). +- +- NOTE: If you are in doubt about IP addresses, ask your network +- administrator for assistance. +- +-4. Your adapter should now be fully operational. +- Use 'ping ' to verify the connection to other computers +- on your network. +-5. To check the adapter configuration view /proc/net/sk98lin/[devicename]. +- For example by executing: +- "cat /proc/net/sk98lin/eth0" +- +-Unload the module +------------------ +-To stop and unload the driver modules, proceed as follows: +- +-1. Execute the command "ifconfig eth0 down". +-2. Execute the command "rmmod sk98lin". +- +-3.2 Inclusion of adapter at system start +------------------------------------------ +- +-Since a large number of different Linux distributions are +-available, we are unable to describe a general installation procedure +-for the driver module. +-Because the driver is now integrated in the kernel, installation should +-be easy, using the standard mechanism of your distribution. +-Refer to the distribution's manual for installation of ethernet adapters. +- +-*** +- +-4 Driver Parameters +-==================== +- +-Parameters can be set at the command line after the module has been +-loaded with the command 'modprobe'. +-In some distributions, the configuration tools are able to pass parameters +-to the driver module. +- +-If you use the kernel module loader, you can set driver parameters +-in the file /etc/modprobe.conf (or /etc/modules.conf in 2.4 or earlier). +-To set the driver parameters in this file, proceed as follows: +- +-1. Insert a line of the form : +- options sk98lin ... +- For "...", the same syntax is required as described for the command +- line parameters of modprobe below. +-2. To activate the new parameters, either reboot your computer +- or +- unload and reload the driver. +- The syntax of the driver parameters is: +- +- modprobe sk98lin parameter=value1[,value2[,value3...]] +- +- where value1 refers to the first adapter, value2 to the second etc. +- +-NOTE: All parameters are case sensitive. Write them exactly as shown +- below. +- +-Example: +-Suppose you have two adapters. You want to set auto-negotiation +-on the first adapter to ON and on the second adapter to OFF. +-You also want to set DuplexCapabilities on the first adapter +-to FULL, and on the second adapter to HALF. +-Then, you must enter: +- +- modprobe sk98lin AutoNeg_A=On,Off DupCap_A=Full,Half +- +-NOTE: The number of adapters that can be configured this way is +- limited in the driver (file skge.c, constant SK_MAX_CARD_PARAM). +- The current limit is 16. If you happen to install +- more adapters, adjust this and recompile. +- +- +-4.1 Per-Port Parameters +------------------------- +- +-These settings are available for each port on the adapter. +-In the following description, '?' stands for the port for +-which you set the parameter (A or B). +- +-Speed +------ +-Parameter: Speed_? +-Values: 10, 100, 1000, Auto +-Default: Auto +- +-This parameter is used to set the speed capabilities. It is only valid +-for the SK-98xx V2.0 copper adapters. +-Usually, the speed is negotiated between the two ports during link +-establishment. If this fails, a port can be forced to a specific setting +-with this parameter. +- +-Auto-Negotiation +----------------- +-Parameter: AutoNeg_? +-Values: On, Off, Sense +-Default: On +- +-The "Sense"-mode automatically detects whether the link partner supports +-auto-negotiation or not. +- +-Duplex Capabilities +-------------------- +-Parameter: DupCap_? +-Values: Half, Full, Both +-Default: Both +- +-This parameters is only relevant if auto-negotiation for this port is +-not set to "Sense". If auto-negotiation is set to "On", all three values +-are possible. If it is set to "Off", only "Full" and "Half" are allowed. +-This parameter is useful if your link partner does not support all +-possible combinations. +- +-Flow Control +------------- +-Parameter: FlowCtrl_? +-Values: Sym, SymOrRem, LocSend, None +-Default: SymOrRem +- +-This parameter can be used to set the flow control capabilities the +-port reports during auto-negotiation. It can be set for each port +-individually. +-Possible modes: +- -- Sym = Symmetric: both link partners are allowed to send +- PAUSE frames +- -- SymOrRem = SymmetricOrRemote: both or only remote partner +- are allowed to send PAUSE frames +- -- LocSend = LocalSend: only local link partner is allowed +- to send PAUSE frames +- -- None = no link partner is allowed to send PAUSE frames +- +-NOTE: This parameter is ignored if auto-negotiation is set to "Off". +- +-Role in Master-Slave-Negotiation (1000Base-T only) +--------------------------------------------------- +-Parameter: Role_? +-Values: Auto, Master, Slave +-Default: Auto +- +-This parameter is only valid for the SK-9821 and SK-9822 adapters. +-For two 1000Base-T ports to communicate, one must take the role of the +-master (providing timing information), while the other must be the +-slave. Usually, this is negotiated between the two ports during link +-establishment. If this fails, a port can be forced to a specific setting +-with this parameter. +- +- +-4.2 Adapter Parameters +------------------------ +- +-Connection Type (SK-98xx V2.0 copper adapters only) +---------------- +-Parameter: ConType +-Values: Auto, 100FD, 100HD, 10FD, 10HD +-Default: Auto +- +-The parameter 'ConType' is a combination of all five per-port parameters +-within one single parameter. This simplifies the configuration of both ports +-of an adapter card! The different values of this variable reflect the most +-meaningful combinations of port parameters. +- +-The following table shows the values of 'ConType' and the corresponding +-combinations of the per-port parameters: +- +- ConType | DupCap AutoNeg FlowCtrl Role Speed +- ----------+------------------------------------------------------ +- Auto | Both On SymOrRem Auto Auto +- 100FD | Full Off None Auto (ignored) 100 +- 100HD | Half Off None Auto (ignored) 100 +- 10FD | Full Off None Auto (ignored) 10 +- 10HD | Half Off None Auto (ignored) 10 +- +-Stating any other port parameter together with this 'ConType' variable +-will result in a merged configuration of those settings. This due to +-the fact, that the per-port parameters (e.g. Speed_? ) have a higher +-priority than the combined variable 'ConType'. +- +-NOTE: This parameter is always used on both ports of the adapter card. +- +-Interrupt Moderation +--------------------- +-Parameter: Moderation +-Values: None, Static, Dynamic +-Default: None +- +-Interrupt moderation is employed to limit the maximum number of interrupts +-the driver has to serve. That is, one or more interrupts (which indicate any +-transmit or receive packet to be processed) are queued until the driver +-processes them. When queued interrupts are to be served, is determined by the +-'IntsPerSec' parameter, which is explained later below. +- +-Possible modes: +- +- -- None - No interrupt moderation is applied on the adapter card. +- Therefore, each transmit or receive interrupt is served immediately +- as soon as it appears on the interrupt line of the adapter card. +- +- -- Static - Interrupt moderation is applied on the adapter card. +- All transmit and receive interrupts are queued until a complete +- moderation interval ends. If such a moderation interval ends, all +- queued interrupts are processed in one big bunch without any delay. +- The term 'static' reflects the fact, that interrupt moderation is +- always enabled, regardless how much network load is currently +- passing via a particular interface. In addition, the duration of +- the moderation interval has a fixed length that never changes while +- the driver is operational. +- +- -- Dynamic - Interrupt moderation might be applied on the adapter card, +- depending on the load of the system. If the driver detects that the +- system load is too high, the driver tries to shield the system against +- too much network load by enabling interrupt moderation. If - at a later +- time - the CPU utilization decreases again (or if the network load is +- negligible) the interrupt moderation will automatically be disabled. +- +-Interrupt moderation should be used when the driver has to handle one or more +-interfaces with a high network load, which - as a consequence - leads also to a +-high CPU utilization. When moderation is applied in such high network load +-situations, CPU load might be reduced by 20-30%. +- +-NOTE: The drawback of using interrupt moderation is an increase of the round- +-trip-time (RTT), due to the queueing and serving of interrupts at dedicated +-moderation times. +- +-Interrupts per second +---------------------- +-Parameter: IntsPerSec +-Values: 30...40000 (interrupts per second) +-Default: 2000 +- +-This parameter is only used if either static or dynamic interrupt moderation +-is used on a network adapter card. Using this parameter if no moderation is +-applied will lead to no action performed. +- +-This parameter determines the length of any interrupt moderation interval. +-Assuming that static interrupt moderation is to be used, an 'IntsPerSec' +-parameter value of 2000 will lead to an interrupt moderation interval of +-500 microseconds. +- +-NOTE: The duration of the moderation interval is to be chosen with care. +-At first glance, selecting a very long duration (e.g. only 100 interrupts per +-second) seems to be meaningful, but the increase of packet-processing delay +-is tremendous. On the other hand, selecting a very short moderation time might +-compensate the use of any moderation being applied. +- +- +-Preferred Port +--------------- +-Parameter: PrefPort +-Values: A, B +-Default: A +- +-This is used to force the preferred port to A or B (on dual-port network +-adapters). The preferred port is the one that is used if both are detected +-as fully functional. +- +-RLMT Mode (Redundant Link Management Technology) +------------------------------------------------- +-Parameter: RlmtMode +-Values: CheckLinkState,CheckLocalPort, CheckSeg, DualNet +-Default: CheckLinkState +- +-RLMT monitors the status of the port. If the link of the active port +-fails, RLMT switches immediately to the standby link. The virtual link is +-maintained as long as at least one 'physical' link is up. +- +-Possible modes: +- +- -- CheckLinkState - Check link state only: RLMT uses the link state +- reported by the adapter hardware for each individual port to +- determine whether a port can be used for all network traffic or +- not. +- +- -- CheckLocalPort - In this mode, RLMT monitors the network path +- between the two ports of an adapter by regularly exchanging packets +- between them. This mode requires a network configuration in which +- the two ports are able to "see" each other (i.e. there must not be +- any router between the ports). +- +- -- CheckSeg - Check local port and segmentation: This mode supports the +- same functions as the CheckLocalPort mode and additionally checks +- network segmentation between the ports. Therefore, this mode is only +- to be used if Gigabit Ethernet switches are installed on the network +- that have been configured to use the Spanning Tree protocol. +- +- -- DualNet - In this mode, ports A and B are used as separate devices. +- If you have a dual port adapter, port A will be configured as eth0 +- and port B as eth1. Both ports can be used independently with +- distinct IP addresses. The preferred port setting is not used. +- RLMT is turned off. +- +-NOTE: RLMT modes CLP and CLPSS are designed to operate in configurations +- where a network path between the ports on one adapter exists. +- Moreover, they are not designed to work where adapters are connected +- back-to-back. +-*** +- +- +-5 Large Frame Support +-====================== +- +-The driver supports large frames (also called jumbo frames). Using large +-frames can result in an improved throughput if transferring large amounts +-of data. +-To enable large frames, set the MTU (maximum transfer unit) of the +-interface to the desired value (up to 9000), execute the following +-command: +- ifconfig eth0 mtu 9000 +-This will only work if you have two adapters connected back-to-back +-or if you use a switch that supports large frames. When using a switch, +-it should be configured to allow large frames and auto-negotiation should +-be set to OFF. The setting must be configured on all adapters that can be +-reached by the large frames. If one adapter is not set to receive large +-frames, it will simply drop them. +- +-You can switch back to the standard ethernet frame size by executing the +-following command: +- ifconfig eth0 mtu 1500 +- +-To permanently configure this setting, add a script with the 'ifconfig' +-line to the system startup sequence (named something like "S99sk98lin" +-in /etc/rc.d/rc2.d). +-*** +- +- +-6 VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad) +-================================================================== +- +-The Marvell Yukon/SysKonnect Linux drivers are able to support VLAN and +-Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad. +-These features are only available after installation of open source +-modules available on the Internet: +-For VLAN go to: http://www.candelatech.com/~greear/vlan.html +-For Link Aggregation go to: http://www.st.rim.or.jp/~yumo +- +-NOTE: SysKonnect GmbH does not offer any support for these open source +- modules and does not take the responsibility for any kind of +- failures or problems arising in connection with these modules. +- +-NOTE: Configuring Link Aggregation on a SysKonnect dual link adapter may +- cause problems when unloading the driver. +- +- +-7 Troubleshooting +-================== +- +-If any problems occur during the installation process, check the +-following list: +- +- +-Problem: The SK-98xx adapter cannot be found by the driver. +-Solution: In /proc/pci search for the following entry: +- 'Ethernet controller: SysKonnect SK-98xx ...' +- If this entry exists, the SK-98xx or SK-98xx V2.0 adapter has +- been found by the system and should be operational. +- If this entry does not exist or if the file '/proc/pci' is not +- found, there may be a hardware problem or the PCI support may +- not be enabled in your kernel. +- The adapter can be checked using the diagnostics program which +- is available on the SysKonnect web site: +- www.syskonnect.com +- +- Some COMPAQ machines have problems dealing with PCI under Linux. +- This problem is described in the 'PCI howto' document +- (included in some distributions or available from the +- web, e.g. at 'www.linux.org'). +- +- +-Problem: Programs such as 'ifconfig' or 'route' cannot be found or the +- error message 'Operation not permitted' is displayed. +-Reason: You are not logged in as user 'root'. +-Solution: Logout and login as 'root' or change to 'root' via 'su'. +- +- +-Problem: Upon use of the command 'ping
' the message +- "ping: sendto: Network is unreachable" is displayed. +-Reason: Your route is not set correctly. +-Solution: If you are using RedHat, you probably forgot to set up the +- route in the 'network configuration'. +- Check the existing routes with the 'route' command and check +- if an entry for 'eth0' exists, and if so, if it is set correctly. +- +- +-Problem: The driver can be started, the adapter is connected to the +- network, but you cannot receive or transmit any packets; +- e.g. 'ping' does not work. +-Reason: There is an incorrect route in your routing table. +-Solution: Check the routing table with the command 'route' and read the +- manual help pages dealing with routes (enter 'man route'). +- +-NOTE: Although the 2.2.x kernel versions generate the routing entry +- automatically, problems of this kind may occur here as well. We've +- come across a situation in which the driver started correctly at +- system start, but after the driver has been removed and reloaded, +- the route of the adapter's network pointed to the 'dummy0'device +- and had to be corrected manually. +- +- +-Problem: Your computer should act as a router between multiple +- IP subnetworks (using multiple adapters), but computers in +- other subnetworks cannot be reached. +-Reason: Either the router's kernel is not configured for IP forwarding +- or the routing table and gateway configuration of at least one +- computer is not working. +- +-Problem: Upon driver start, the following error message is displayed: +- "eth0: -- ERROR -- +- Class: internal Software error +- Nr: 0xcc +- Msg: SkGeInitPort() cannot init running ports" +-Reason: You are using a driver compiled for single processor machines +- on a multiprocessor machine with SMP (Symmetric MultiProcessor) +- kernel. +-Solution: Configure your kernel appropriately and recompile the kernel or +- the modules. +- +- +- +-If your problem is not listed here, please contact SysKonnect's technical +-support for help (linux@syskonnect.de). +-When contacting our technical support, please ensure that the following +-information is available: +-- System Manufacturer and HW Informations (CPU, Memory... ) +-- PCI-Boards in your system +-- Distribution +-- Kernel version +-- Driver version +-*** +- +- +- +-***End of Readme File*** +diff --git a/Documentation/unaligned-memory-access.txt b/Documentation/unaligned-memory-access.txt +index 6223eac..b0472ac 100644 +--- a/Documentation/unaligned-memory-access.txt ++++ b/Documentation/unaligned-memory-access.txt +@@ -57,7 +57,7 @@ here; a summary of the common scenarios is presented below: + unaligned access to be corrected. + - Some architectures are not capable of unaligned memory access, but will + silently perform a different memory access to the one that was requested, +- resulting a a subtle code bug that is hard to detect! ++ resulting in a subtle code bug that is hard to detect! + + It should be obvious from the above that if your code causes unaligned + memory accesses to happen, your code will not work correctly on certain +@@ -209,7 +209,7 @@ memory and you wish to avoid unaligned access, its usage is as follows: + + u32 value = get_unaligned((u32 *) data); + +-These macros work work for memory accesses of any length (not just 32 bits as ++These macros work for memory accesses of any length (not just 32 bits as + in the examples above). Be aware that when compared to standard access of + aligned memory, using these macros to access unaligned memory can be costly in + terms of performance. +diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c +index 4e1c086..dd6e334 100644 +--- a/arch/alpha/kernel/pci_iommu.c ++++ b/arch/alpha/kernel/pci_iommu.c +@@ -424,11 +424,13 @@ EXPORT_SYMBOL(pci_unmap_page); + else DMA_ADDRP is undefined. */ + + void * +-pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) ++__pci_alloc_consistent(struct pci_dev *pdev, size_t size, ++ dma_addr_t *dma_addrp, gfp_t gfp) + { + void *cpu_addr; + long order = get_order(size); +- gfp_t gfp = GFP_ATOMIC; ++ ++ gfp &= ~GFP_DMA; + + try_again: + cpu_addr = (void *)__get_free_pages(gfp, order); +@@ -458,7 +460,7 @@ try_again: + + return cpu_addr; + } +-EXPORT_SYMBOL(pci_alloc_consistent); ++EXPORT_SYMBOL(__pci_alloc_consistent); + + /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must + be values that were returned from pci_alloc_consistent. SIZE must +diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c +index b781d3d..756fa24 100644 +--- a/arch/sparc64/kernel/iommu.c ++++ b/arch/sparc64/kernel/iommu.c +@@ -516,9 +516,11 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, + unsigned long flags, handle, prot, ctx; + dma_addr_t dma_next = 0, dma_addr; + unsigned int max_seg_size; ++ unsigned long seg_boundary_size; + int outcount, incount, i; + struct strbuf *strbuf; + struct iommu *iommu; ++ unsigned long base_shift; + + BUG_ON(direction == DMA_NONE); + +@@ -549,8 +551,11 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, + outs->dma_length = 0; + + max_seg_size = dma_get_max_seg_size(dev); ++ seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, ++ IO_PAGE_SIZE) >> IO_PAGE_SHIFT; ++ base_shift = iommu->page_table_map_base >> IO_PAGE_SHIFT; + for_each_sg(sglist, s, nelems, i) { +- unsigned long paddr, npages, entry, slen; ++ unsigned long paddr, npages, entry, out_entry = 0, slen; + iopte_t *base; + + slen = s->length; +@@ -593,7 +598,9 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, + * - allocated dma_addr isn't contiguous to previous allocation + */ + if ((dma_addr != dma_next) || +- (outs->dma_length + s->length > max_seg_size)) { ++ (outs->dma_length + s->length > max_seg_size) || ++ (is_span_boundary(out_entry, base_shift, ++ seg_boundary_size, outs, s))) { + /* Can't merge: create a new segment */ + segstart = s; + outcount++; +@@ -607,6 +614,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, + /* This is a new segment, fill entries */ + outs->dma_address = dma_addr; + outs->dma_length = slen; ++ out_entry = entry; + } + + /* Calculate next page pointer for contiguous check */ +diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h +index 0713bd5..f3575a6 100644 +--- a/arch/sparc64/kernel/iommu_common.h ++++ b/arch/sparc64/kernel/iommu_common.h +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -45,17 +46,16 @@ static inline unsigned long iommu_num_pages(unsigned long vaddr, + return npages; + } + +-static inline unsigned long calc_npages(struct scatterlist *sglist, int nelems) ++static inline int is_span_boundary(unsigned long entry, ++ unsigned long shift, ++ unsigned long boundary_size, ++ struct scatterlist *outs, ++ struct scatterlist *sg) + { +- unsigned long i, npages = 0; +- struct scatterlist *sg; ++ unsigned long paddr = SG_ENT_PHYS_ADDRESS(outs); ++ int nr = iommu_num_pages(paddr, outs->dma_length + sg->length); + +- for_each_sg(sglist, sg, nelems, i) { +- unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg); +- npages += iommu_num_pages(paddr, sg->length); +- } +- +- return npages; ++ return iommu_is_span_boundary(entry, nr, shift, boundary_size); + } + + extern unsigned long iommu_range_alloc(struct device *dev, +diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c +index ddca6c6..0183970 100644 +--- a/arch/sparc64/kernel/pci_sun4v.c ++++ b/arch/sparc64/kernel/pci_sun4v.c +@@ -335,8 +335,10 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, + unsigned long flags, handle, prot; + dma_addr_t dma_next = 0, dma_addr; + unsigned int max_seg_size; ++ unsigned long seg_boundary_size; + int outcount, incount, i; + struct iommu *iommu; ++ unsigned long base_shift; + long err; + + BUG_ON(direction == DMA_NONE); +@@ -362,8 +364,11 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, + iommu_batch_start(dev, prot, ~0UL); + + max_seg_size = dma_get_max_seg_size(dev); ++ seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1, ++ IO_PAGE_SIZE) >> IO_PAGE_SHIFT; ++ base_shift = iommu->page_table_map_base >> IO_PAGE_SHIFT; + for_each_sg(sglist, s, nelems, i) { +- unsigned long paddr, npages, entry, slen; ++ unsigned long paddr, npages, entry, out_entry = 0, slen; + + slen = s->length; + /* Sanity check */ +@@ -406,7 +411,9 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, + * - allocated dma_addr isn't contiguous to previous allocation + */ + if ((dma_addr != dma_next) || +- (outs->dma_length + s->length > max_seg_size)) { ++ (outs->dma_length + s->length > max_seg_size) || ++ (is_span_boundary(out_entry, base_shift, ++ seg_boundary_size, outs, s))) { + /* Can't merge: create a new segment */ + segstart = s; + outcount++; +@@ -420,6 +427,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, + /* This is a new segment, fill entries */ + outs->dma_address = dma_addr; + outs->dma_length = slen; ++ out_entry = entry; + } + + /* Calculate next page pointer for contiguous check */ +diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c +index a0f000b..ae24919 100644 +--- a/arch/sparc64/mm/tlb.c ++++ b/arch/sparc64/mm/tlb.c +@@ -23,11 +23,8 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, }; + + void flush_tlb_pending(void) + { +- struct mmu_gather *mp; ++ struct mmu_gather *mp = &get_cpu_var(mmu_gathers); + +- preempt_disable(); +- +- mp = &__get_cpu_var(mmu_gathers); + if (mp->tlb_nr) { + flush_tsb_user(mp); + +@@ -43,7 +40,7 @@ void flush_tlb_pending(void) + mp->tlb_nr = 0; + } + +- preempt_enable(); ++ put_cpu_var(mmu_gathers); + } + + void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig) +diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c +index 236d2f8..576a03d 100644 +--- a/arch/x86/kernel/machine_kexec_64.c ++++ b/arch/x86/kernel/machine_kexec_64.c +@@ -233,6 +233,7 @@ NORET_TYPE void machine_kexec(struct kimage *image) + + void arch_crash_save_vmcoreinfo(void) + { ++ VMCOREINFO_SYMBOL(phys_base); + VMCOREINFO_SYMBOL(init_level4_pgt); + + #ifdef CONFIG_NUMA +diff --git a/block/blk-settings.c b/block/blk-settings.c +index 1344a0e..5713f7e 100644 +--- a/block/blk-settings.c ++++ b/block/blk-settings.c +@@ -140,7 +140,7 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_addr) + /* Assume anything <= 4GB can be handled by IOMMU. + Actually some IOMMUs can handle everything, but I don't + know of a way to test this here. */ +- if (b_pfn <= (min_t(u64, 0xffffffff, BLK_BOUNCE_HIGH) >> PAGE_SHIFT)) ++ if (b_pfn < (min_t(u64, 0x100000000UL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT)) + dma = 1; + q->bounce_pfn = max_low_pfn; + #else +diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c +index 0f962ec..f26da2b 100644 +--- a/block/cfq-iosched.c ++++ b/block/cfq-iosched.c +@@ -1143,24 +1143,37 @@ static void cfq_put_queue(struct cfq_queue *cfqq) + } + + /* +- * Call func for each cic attached to this ioc. Returns number of cic's seen. ++ * Call func for each cic attached to this ioc. + */ +-static unsigned int ++static void + call_for_each_cic(struct io_context *ioc, + void (*func)(struct io_context *, struct cfq_io_context *)) + { + struct cfq_io_context *cic; + struct hlist_node *n; +- int called = 0; + + rcu_read_lock(); +- hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) { ++ hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list) + func(ioc, cic); +- called++; +- } + rcu_read_unlock(); ++} ++ ++static void cfq_cic_free_rcu(struct rcu_head *head) ++{ ++ struct cfq_io_context *cic; ++ ++ cic = container_of(head, struct cfq_io_context, rcu_head); ++ ++ kmem_cache_free(cfq_ioc_pool, cic); ++ elv_ioc_count_dec(ioc_count); ++ ++ if (ioc_gone && !elv_ioc_count_read(ioc_count)) ++ complete(ioc_gone); ++} + +- return called; ++static void cfq_cic_free(struct cfq_io_context *cic) ++{ ++ call_rcu(&cic->rcu_head, cfq_cic_free_rcu); + } + + static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic) +@@ -1174,24 +1187,18 @@ static void cic_free_func(struct io_context *ioc, struct cfq_io_context *cic) + hlist_del_rcu(&cic->cic_list); + spin_unlock_irqrestore(&ioc->lock, flags); + +- kmem_cache_free(cfq_ioc_pool, cic); ++ cfq_cic_free(cic); + } + + static void cfq_free_io_context(struct io_context *ioc) + { +- int freed; +- + /* +- * ioc->refcount is zero here, so no more cic's are allowed to be +- * linked into this ioc. So it should be ok to iterate over the known +- * list, we will see all cic's since no new ones are added. ++ * ioc->refcount is zero here, or we are called from elv_unregister(), ++ * so no more cic's are allowed to be linked into this ioc. So it ++ * should be ok to iterate over the known list, we will see all cic's ++ * since no new ones are added. + */ +- freed = call_for_each_cic(ioc, cic_free_func); +- +- elv_ioc_count_mod(ioc_count, -freed); +- +- if (ioc_gone && !elv_ioc_count_read(ioc_count)) +- complete(ioc_gone); ++ call_for_each_cic(ioc, cic_free_func); + } + + static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) +@@ -1458,15 +1465,6 @@ cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc, + return cfqq; + } + +-static void cfq_cic_free(struct cfq_io_context *cic) +-{ +- kmem_cache_free(cfq_ioc_pool, cic); +- elv_ioc_count_dec(ioc_count); +- +- if (ioc_gone && !elv_ioc_count_read(ioc_count)) +- complete(ioc_gone); +-} +- + /* + * We drop cfq io contexts lazily, so we may find a dead one. + */ +@@ -2138,7 +2136,7 @@ static int __init cfq_slab_setup(void) + if (!cfq_pool) + goto fail; + +- cfq_ioc_pool = KMEM_CACHE(cfq_io_context, SLAB_DESTROY_BY_RCU); ++ cfq_ioc_pool = KMEM_CACHE(cfq_io_context, 0); + if (!cfq_ioc_pool) + goto fail; + +@@ -2286,7 +2284,6 @@ static void __exit cfq_exit(void) + smp_wmb(); + if (elv_ioc_count_read(ioc_count)) + wait_for_completion(ioc_gone); +- synchronize_rcu(); + cfq_slab_kill(); + } + +diff --git a/crypto/xcbc.c b/crypto/xcbc.c +index 2feb0f2..b63b633 100644 +--- a/crypto/xcbc.c ++++ b/crypto/xcbc.c +@@ -116,13 +116,11 @@ static int crypto_xcbc_digest_update2(struct hash_desc *pdesc, + struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); + struct crypto_cipher *tfm = ctx->child; + int bs = crypto_hash_blocksize(parent); +- unsigned int i = 0; + +- do { +- +- struct page *pg = sg_page(&sg[i]); +- unsigned int offset = sg[i].offset; +- unsigned int slen = sg[i].length; ++ for (;;) { ++ struct page *pg = sg_page(sg); ++ unsigned int offset = sg->offset; ++ unsigned int slen = sg->length; + + if (unlikely(slen > nbytes)) + slen = nbytes; +@@ -182,8 +180,11 @@ static int crypto_xcbc_digest_update2(struct hash_desc *pdesc, + offset = 0; + pg++; + } +- i++; +- } while (nbytes>0); ++ ++ if (!nbytes) ++ break; ++ sg = scatterwalk_sg_next(sg); ++ } + + return 0; + } +diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c +index 47c57a4..98099f5 100644 +--- a/drivers/atm/firestream.c ++++ b/drivers/atm/firestream.c +@@ -978,6 +978,7 @@ static int fs_open(struct atm_vcc *atm_vcc) + /* Docs are vague about this atm_hdr field. By the way, the FS + * chip makes odd errors if lower bits are set.... -- REW */ + tc->atm_hdr = (vpi << 20) | (vci << 4); ++ tmc0 = 0; + { + int pcr = atm_pcr_goal (txtp); + +diff --git a/drivers/atm/he.c b/drivers/atm/he.c +index 2e3395b..ffc4a5a 100644 +--- a/drivers/atm/he.c ++++ b/drivers/atm/he.c +@@ -3000,8 +3000,7 @@ he_proc_read(struct atm_dev *dev, loff_t *pos, char *page) + + /* eeprom routines -- see 4.7 */ + +-u8 +-read_prom_byte(struct he_dev *he_dev, int addr) ++static u8 read_prom_byte(struct he_dev *he_dev, int addr) + { + u32 val = 0, tmp_read = 0; + int i, j = 0; +diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c +index b967919..28d77b5 100644 +--- a/drivers/atm/idt77252.c ++++ b/drivers/atm/idt77252.c +@@ -2016,8 +2016,7 @@ idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam) + return 0; + } + +-int +-idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb) ++static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb) + { + return idt77252_send_skb(vcc, skb, 0); + } +@@ -3072,8 +3071,7 @@ idt77252_dev_open(struct idt77252_dev *card) + return 0; + } + +-void +-idt77252_dev_close(struct atm_dev *dev) ++static void idt77252_dev_close(struct atm_dev *dev) + { + struct idt77252_dev *card = dev->dev_data; + u32 conf; +diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c +index ef52452..670c093 100644 +--- a/drivers/atm/iphase.c ++++ b/drivers/atm/iphase.c +@@ -958,6 +958,7 @@ static void ia_suni_pm7345_init (IADEV *iadev) + + /***************************** IA_LIB END *****************************/ + ++#ifdef CONFIG_ATM_IA_DEBUG + static int tcnter = 0; + static void xdump( u_char* cp, int length, char* prefix ) + { +@@ -992,6 +993,7 @@ static void xdump( u_char* cp, int length, char* prefix ) + } + + } /* close xdump(... */ ++#endif /* CONFIG_ATM_IA_DEBUG */ + + + static struct atm_dev *ia_boards = NULL; +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index b53fdb0..60cc543 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -153,6 +153,12 @@ static int sock_xmit(struct nbd_device *lo, int send, void *buf, int size, + struct kvec iov; + sigset_t blocked, oldset; + ++ if (unlikely(!sock)) { ++ printk(KERN_ERR "%s: Attempted %s on closed socket in sock_xmit\n", ++ lo->disk->disk_name, (send ? "send" : "recv")); ++ return -EINVAL; ++ } ++ + /* Allow interception of SIGKILL only + * Don't allow other signals to interrupt the transmission */ + siginitsetinv(&blocked, sigmask(SIGKILL)); +diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c +index 991119c..9b52892 100644 +--- a/drivers/char/rio/riotable.c ++++ b/drivers/char/rio/riotable.c +@@ -425,8 +425,10 @@ int RIOApel(struct rio_info *p) + + MapP = &p->RIOConnectTable[Next++]; + MapP->HostUniqueNum = HostP->UniqueNum; +- if ((HostP->Flags & RUN_STATE) != RC_RUNNING) ++ if ((HostP->Flags & RUN_STATE) != RC_RUNNING) { ++ rio_spin_unlock_irqrestore(&HostP->HostLock, flags); + continue; ++ } + MapP->RtaUniqueNum = 0; + MapP->ID = 0; + MapP->Flags = SLOT_IN_USE; +diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c +index a4f0b1e..cfa5436 100644 +--- a/drivers/char/rio/riotty.c ++++ b/drivers/char/rio/riotty.c +@@ -319,6 +319,7 @@ int riotopen(struct tty_struct *tty, struct file *filp) + PortP->State |= RIO_WOPEN; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { ++ rio_spin_lock_irqsave(&PortP->portSem, flags); + /* + ** ACTION: verify that this is a good thing + ** to do here. -- ??? +@@ -334,6 +335,7 @@ int riotopen(struct tty_struct *tty, struct file *filp) + func_exit(); + return -EINTR; + } ++ rio_spin_lock_irqsave(&PortP->portSem, flags); + } + PortP->State &= ~RIO_WOPEN; + } +@@ -493,6 +495,7 @@ int riotclose(void *ptr) + + if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) { + RIOPreemptiveCmd(p, PortP, FCLOSE); ++ rio_spin_lock_irqsave(&PortP->portSem, flags); + goto close_end; + } + +@@ -508,6 +511,7 @@ int riotclose(void *ptr) + + if (p->RIOHalted) { + RIOClearUp(PortP); ++ rio_spin_lock_irqsave(&PortP->portSem, flags); + goto close_end; + } + if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { +diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c +index 43a70e9..be9ff73 100644 +--- a/drivers/ide/arm/ide_arm.c ++++ b/drivers/ide/arm/ide_arm.c +@@ -46,3 +46,5 @@ static int __init ide_arm_init(void) + } + + module_init(ide_arm_init); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c +index e79bf8f..c8ffbaf 100644 +--- a/drivers/ide/cris/ide-cris.c ++++ b/drivers/ide/cris/ide-cris.c +@@ -1067,3 +1067,5 @@ static void cris_dma_start(ide_drive_t *drive) + } + + module_init(init_e100_ide); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c +index 520aec0..4108ec4 100644 +--- a/drivers/ide/h8300/ide-h8300.c ++++ b/drivers/ide/h8300/ide-h8300.c +@@ -110,6 +110,7 @@ static int __init h8300_ide_init(void) + ide_init_port_data(hwif, index); + ide_init_port_hw(hwif, &hw); + hwif_setup(hwif); ++ hwif->host_flags = IDE_HFLAG_NO_IO_32BIT; + printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", index); + + idx[0] = index; +@@ -125,3 +126,5 @@ out_busy: + } + + module_init(h8300_ide_init); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c +index 01b9220..e77cee0 100644 +--- a/drivers/ide/ide-iops.c ++++ b/drivers/ide/ide-iops.c +@@ -658,7 +658,7 @@ int ide_driveid_update(ide_drive_t *drive) + local_irq_restore(flags); + return 0; + } +- ata_input_data(drive, id, SECTOR_WORDS); ++ hwif->ata_input_data(drive, id, SECTOR_WORDS); + (void)ide_read_status(drive); /* clear drive IRQ */ + local_irq_enable(); + local_irq_restore(flags); +diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c +index b163b2e..c14bb53 100644 +--- a/drivers/ide/ide-pnp.c ++++ b/drivers/ide/ide-pnp.c +@@ -86,3 +86,5 @@ static void __exit pnpide_exit(void) + + module_init(pnpide_init); + module_exit(pnpide_exit); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c +index 50ffa87..fdd3791 100644 +--- a/drivers/ide/legacy/buddha.c ++++ b/drivers/ide/legacy/buddha.c +@@ -241,3 +241,5 @@ fail_base2: + } + + module_init(buddha_init); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c +index 8949ce7..e950afa 100644 +--- a/drivers/ide/legacy/falconide.c ++++ b/drivers/ide/legacy/falconide.c +@@ -93,3 +93,5 @@ static int __init falconide_init(void) + } + + module_init(falconide_init); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c +index b7d8109..e3b4638 100644 +--- a/drivers/ide/legacy/gayle.c ++++ b/drivers/ide/legacy/gayle.c +@@ -195,3 +195,5 @@ found: + } + + module_init(gayle_init); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c +index 9a79098..eaf5dbe 100644 +--- a/drivers/ide/legacy/macide.c ++++ b/drivers/ide/legacy/macide.c +@@ -137,3 +137,5 @@ static int __init macide_init(void) + } + + module_init(macide_init); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c +index 1381b91..2da2875 100644 +--- a/drivers/ide/legacy/q40ide.c ++++ b/drivers/ide/legacy/q40ide.c +@@ -153,3 +153,5 @@ static int __init q40ide_init(void) + } + + module_init(q40ide_init); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c +index ec66798..29fbc5e 100644 +--- a/drivers/ide/pci/cmd640.c ++++ b/drivers/ide/pci/cmd640.c +@@ -881,3 +881,5 @@ module_param_named(probe_vlb, cmd640_vlb, bool, 0); + MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset"); + + module_init(cmd640x_init); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c +index 38fbfb8..ebaba01 100644 +--- a/drivers/ide/ppc/mpc8xx.c ++++ b/drivers/ide/ppc/mpc8xx.c +@@ -853,3 +853,5 @@ static int __init mpc8xx_ide_probe(void) + } + + module_init(mpc8xx_ide_probe); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c +index 78c9eeb..d9ca52e 100644 +--- a/drivers/ide/ppc/pmac.c ++++ b/drivers/ide/ppc/pmac.c +@@ -1771,3 +1771,5 @@ static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) + #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + + module_init(pmac_ide_probe); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c +index 34e317c..57b9e3a 100644 +--- a/drivers/media/radio/radio-cadet.c ++++ b/drivers/media/radio/radio-cadet.c +@@ -587,6 +587,8 @@ static struct video_device cadet_radio= + .vidioc_s_input = vidioc_s_input, + }; + ++#ifdef CONFIG_PNP ++ + static struct pnp_device_id cadet_pnp_devices[] = { + /* ADS Cadet AM/FM Radio Card */ + {.id = "MSM0c24", .driver_data = 0}, +@@ -621,6 +623,10 @@ static struct pnp_driver cadet_pnp_driver = { + .remove = NULL, + }; + ++#else ++static struct pnp_driver cadet_pnp_driver; ++#endif ++ + static int cadet_probe(void) + { + static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; +diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c +index a080c14..fcf8f2d 100644 +--- a/drivers/media/video/bt8xx/bttv-driver.c ++++ b/drivers/media/video/bt8xx/bttv-driver.c +@@ -1990,7 +1990,7 @@ static int bttv_g_frequency(struct file *file, void *priv, + if (0 != err) + return err; + +- f->type = V4L2_TUNER_ANALOG_TV; ++ f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; + f->frequency = btv->freq; + + return 0; +@@ -2009,7 +2009,8 @@ static int bttv_s_frequency(struct file *file, void *priv, + + if (unlikely(f->tuner != 0)) + return -EINVAL; +- if (unlikely(f->type != V4L2_TUNER_ANALOG_TV)) ++ if (unlikely(f->type != (btv->radio_user ++ ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) + return -EINVAL; + mutex_lock(&btv->lock); + btv->freq = f->frequency; +@@ -3415,6 +3416,7 @@ static int radio_open(struct inode *inode, struct file *file) + { + int minor = iminor(inode); + struct bttv *btv = NULL; ++ struct bttv_fh *fh; + unsigned int i; + + dprintk("bttv: open minor=%d\n",minor); +@@ -3429,12 +3431,19 @@ static int radio_open(struct inode *inode, struct file *file) + return -ENODEV; + + dprintk("bttv%d: open called (radio)\n",btv->c.nr); ++ ++ /* allocate per filehandle data */ ++ fh = kmalloc(sizeof(*fh), GFP_KERNEL); ++ if (NULL == fh) ++ return -ENOMEM; ++ file->private_data = fh; ++ *fh = btv->init; ++ v4l2_prio_open(&btv->prio, &fh->prio); ++ + mutex_lock(&btv->lock); + + btv->radio_user++; + +- file->private_data = btv; +- + bttv_call_i2c_clients(btv,AUDC_SET_RADIO,NULL); + audio_input(btv,TVAUDIO_INPUT_RADIO); + +@@ -3444,7 +3453,8 @@ static int radio_open(struct inode *inode, struct file *file) + + static int radio_release(struct inode *inode, struct file *file) + { +- struct bttv *btv = file->private_data; ++ struct bttv_fh *fh = file->private_data; ++ struct bttv *btv = fh->btv; + struct rds_command cmd; + + btv->radio_user--; +@@ -3508,8 +3518,12 @@ static int radio_enum_input(struct file *file, void *priv, + static int radio_g_audio(struct file *file, void *priv, + struct v4l2_audio *a) + { ++ if (a->index != 0) ++ return -EINVAL; ++ + memset(a, 0, sizeof(*a)); + strcpy(a->name, "Radio"); ++ + return 0; + } + +@@ -3569,7 +3583,8 @@ static int radio_g_input(struct file *filp, void *priv, unsigned int *i) + static ssize_t radio_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) + { +- struct bttv *btv = file->private_data; ++ struct bttv_fh *fh = file->private_data; ++ struct bttv *btv = fh->btv; + struct rds_command cmd; + cmd.block_count = count/3; + cmd.buffer = data; +@@ -3583,7 +3598,8 @@ static ssize_t radio_read(struct file *file, char __user *data, + + static unsigned int radio_poll(struct file *file, poll_table *wait) + { +- struct bttv *btv = file->private_data; ++ struct bttv_fh *fh = file->private_data; ++ struct bttv *btv = fh->btv; + struct rds_command cmd; + cmd.instance = file; + cmd.event_list = wait; +@@ -3599,6 +3615,7 @@ static const struct file_operations radio_fops = + .open = radio_open, + .read = radio_read, + .release = radio_release, ++ .compat_ioctl = v4l_compat_ioctl32, + .ioctl = video_ioctl2, + .llseek = no_llseek, + .poll = radio_poll, +diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c +index 2d414da..dfa2698 100644 +--- a/drivers/media/video/cx23885/cx23885-cards.c ++++ b/drivers/media/video/cx23885/cx23885-cards.c +@@ -232,6 +232,7 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) + case 78631: /* WinTV-HVR1800 (PCIe, OEM, No IR, No FM, Dual channel ATSC and MPEG2 HW Encoder */ + case 79001: /* WinTV-HVR1250 (PCIe, Retail, IR, full height, ATSC and Basic analog */ + case 79101: /* WinTV-HVR1250 (PCIe, Retail, IR, half height, ATSC and Basic analog */ ++ case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ + case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */ + case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ + break; +@@ -347,10 +348,13 @@ void cx23885_card_setup(struct cx23885_dev *dev) + case CX23885_BOARD_HAUPPAUGE_HVR1250: + case CX23885_BOARD_HAUPPAUGE_HVR1500: + case CX23885_BOARD_HAUPPAUGE_HVR1500Q: ++ if (dev->i2c_bus[0].i2c_rc == 0) ++ hauppauge_eeprom(dev, eeprom+0x80); ++ break; + case CX23885_BOARD_HAUPPAUGE_HVR1800: + case CX23885_BOARD_HAUPPAUGE_HVR1800lp: + if (dev->i2c_bus[0].i2c_rc == 0) +- hauppauge_eeprom(dev, eeprom+0x80); ++ hauppauge_eeprom(dev, eeprom+0xc0); + break; + } + +diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c +index 8e40c7b..7f10b27 100644 +--- a/drivers/media/video/cx23885/cx23885-core.c ++++ b/drivers/media/video/cx23885/cx23885-core.c +@@ -56,137 +56,6 @@ LIST_HEAD(cx23885_devlist); + + #define NO_SYNC_LINE (-1U) + +-/* +- * CX23885 Assumptions +- * 1 line = 16 bytes of CDT +- * cmds size = 80 +- * cdt size = 16 * linesize +- * iqsize = 64 +- * maxlines = 6 +- * +- * Address Space: +- * 0x00000000 0x00008fff FIFO clusters +- * 0x00010000 0x000104af Channel Management Data Structures +- * 0x000104b0 0x000104ff Free +- * 0x00010500 0x000108bf 15 channels * iqsize +- * 0x000108c0 0x000108ff Free +- * 0x00010900 0x00010e9f IQ's + Cluster Descriptor Tables +- * 15 channels * (iqsize + (maxlines * linesize)) +- * 0x00010ea0 0x00010xxx Free +- */ +- +-static struct sram_channel cx23885_sram_channels[] = { +- [SRAM_CH01] = { +- .name = "VID A", +- .cmds_start = 0x10000, +- .ctrl_start = 0x105b0, +- .cdt = 0x107b0, +- .fifo_start = 0x40, +- .fifo_size = 0x2800, +- .ptr1_reg = DMA1_PTR1, +- .ptr2_reg = DMA1_PTR2, +- .cnt1_reg = DMA1_CNT1, +- .cnt2_reg = DMA1_CNT2, +- .jumponly = 1, +- }, +- [SRAM_CH02] = { +- .name = "ch2", +- .cmds_start = 0x0, +- .ctrl_start = 0x0, +- .cdt = 0x0, +- .fifo_start = 0x0, +- .fifo_size = 0x0, +- .ptr1_reg = DMA2_PTR1, +- .ptr2_reg = DMA2_PTR2, +- .cnt1_reg = DMA2_CNT1, +- .cnt2_reg = DMA2_CNT2, +- }, +- [SRAM_CH03] = { +- .name = "TS1 B", +- .cmds_start = 0x100A0, +- .ctrl_start = 0x10630, +- .cdt = 0x10870, +- .fifo_start = 0x5000, +- .fifo_size = 0x1000, +- .ptr1_reg = DMA3_PTR1, +- .ptr2_reg = DMA3_PTR2, +- .cnt1_reg = DMA3_CNT1, +- .cnt2_reg = DMA3_CNT2, +- }, +- [SRAM_CH04] = { +- .name = "ch4", +- .cmds_start = 0x0, +- .ctrl_start = 0x0, +- .cdt = 0x0, +- .fifo_start = 0x0, +- .fifo_size = 0x0, +- .ptr1_reg = DMA4_PTR1, +- .ptr2_reg = DMA4_PTR2, +- .cnt1_reg = DMA4_CNT1, +- .cnt2_reg = DMA4_CNT2, +- }, +- [SRAM_CH05] = { +- .name = "ch5", +- .cmds_start = 0x0, +- .ctrl_start = 0x0, +- .cdt = 0x0, +- .fifo_start = 0x0, +- .fifo_size = 0x0, +- .ptr1_reg = DMA5_PTR1, +- .ptr2_reg = DMA5_PTR2, +- .cnt1_reg = DMA5_CNT1, +- .cnt2_reg = DMA5_CNT2, +- }, +- [SRAM_CH06] = { +- .name = "TS2 C", +- .cmds_start = 0x10140, +- .ctrl_start = 0x10680, +- .cdt = 0x108d0, +- .fifo_start = 0x6000, +- .fifo_size = 0x1000, +- .ptr1_reg = DMA5_PTR1, +- .ptr2_reg = DMA5_PTR2, +- .cnt1_reg = DMA5_CNT1, +- .cnt2_reg = DMA5_CNT2, +- }, +- [SRAM_CH07] = { +- .name = "ch7", +- .cmds_start = 0x0, +- .ctrl_start = 0x0, +- .cdt = 0x0, +- .fifo_start = 0x0, +- .fifo_size = 0x0, +- .ptr1_reg = DMA6_PTR1, +- .ptr2_reg = DMA6_PTR2, +- .cnt1_reg = DMA6_CNT1, +- .cnt2_reg = DMA6_CNT2, +- }, +- [SRAM_CH08] = { +- .name = "ch8", +- .cmds_start = 0x0, +- .ctrl_start = 0x0, +- .cdt = 0x0, +- .fifo_start = 0x0, +- .fifo_size = 0x0, +- .ptr1_reg = DMA7_PTR1, +- .ptr2_reg = DMA7_PTR2, +- .cnt1_reg = DMA7_CNT1, +- .cnt2_reg = DMA7_CNT2, +- }, +- [SRAM_CH09] = { +- .name = "ch9", +- .cmds_start = 0x0, +- .ctrl_start = 0x0, +- .cdt = 0x0, +- .fifo_start = 0x0, +- .fifo_size = 0x0, +- .ptr1_reg = DMA8_PTR1, +- .ptr2_reg = DMA8_PTR2, +- .cnt1_reg = DMA8_CNT1, +- .cnt2_reg = DMA8_CNT2, +- }, +-}; +- + /* FIXME, these allocations will change when + * analog arrives. The be reviewed. + * CX23887 Assumptions +@@ -754,6 +623,7 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) + atomic_inc(&dev->refcount); + + dev->nr = cx23885_devcount++; ++ dev->sram_channels = cx23887_sram_channels; + sprintf(dev->name, "cx23885[%d]", dev->nr); + + mutex_lock(&devlist); +@@ -763,13 +633,11 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) + /* Configure the internal memory */ + if(dev->pci->device == 0x8880) { + dev->bridge = CX23885_BRIDGE_887; +- dev->sram_channels = cx23887_sram_channels; + /* Apply a sensible clock frequency for the PCIe bridge */ + dev->clk_freq = 25000000; + } else + if(dev->pci->device == 0x8852) { + dev->bridge = CX23885_BRIDGE_885; +- dev->sram_channels = cx23885_sram_channels; + /* Apply a sensible clock frequency for the PCIe bridge */ + dev->clk_freq = 28000000; + } else +diff --git a/drivers/media/video/v4l2-int-device.c b/drivers/media/video/v4l2-int-device.c +index a545dca..0e45499 100644 +--- a/drivers/media/video/v4l2-int-device.c ++++ b/drivers/media/video/v4l2-int-device.c +@@ -156,3 +156,5 @@ int v4l2_int_ioctl_1(struct v4l2_int_device *d, int cmd, void *arg) + find_ioctl(d->u.slave, cmd, + (v4l2_int_ioctl_func *)no_such_ioctl_1))(d, arg); + } ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig +index fe7b5ec..3a0b20a 100644 +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -2635,7 +2635,7 @@ config NIU + + config PASEMI_MAC + tristate "PA Semi 1/10Gbit MAC" +- depends on PPC64 && PCI ++ depends on PPC_PASEMI && PCI + select PHYLIB + select INET_LRO + help +diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c +index c993a32..26b2dd5 100644 +--- a/drivers/net/bfin_mac.c ++++ b/drivers/net/bfin_mac.c +@@ -575,7 +575,6 @@ adjust_head: + static int bf537mac_hard_start_xmit(struct sk_buff *skb, + struct net_device *dev) + { +- struct bf537mac_local *lp = netdev_priv(dev); + unsigned int data; + + current_tx_ptr->skb = skb; +@@ -634,7 +633,6 @@ out: + static void bf537mac_rx(struct net_device *dev) + { + struct sk_buff *skb, *new_skb; +- struct bf537mac_local *lp = netdev_priv(dev); + unsigned short len; + + /* allocate a new skb for next time receive */ +diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c +index 90a1f31..979c2d0 100644 +--- a/drivers/net/bonding/bond_sysfs.c ++++ b/drivers/net/bonding/bond_sysfs.c +@@ -341,6 +341,7 @@ static ssize_t bonding_store_slaves(struct device *d, + + if (command[0] == '-') { + dev = NULL; ++ original_mtu = 0; + bond_for_each_slave(bond, slave, i) + if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) { + dev = slave->dev; +diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c +index 6f7e3fd..980c2c2 100644 +--- a/drivers/net/forcedeth.c ++++ b/drivers/net/forcedeth.c +@@ -1854,6 +1854,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) + struct ring_desc* start_tx; + struct ring_desc* prev_tx; + struct nv_skb_map* prev_tx_ctx; ++ unsigned long flags; + + /* add fragments to entries count */ + for (i = 0; i < fragments; i++) { +@@ -1863,10 +1864,10 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) + + empty_slots = nv_get_empty_tx_slots(np); + if (unlikely(empty_slots <= entries)) { +- spin_lock_irq(&np->lock); ++ spin_lock_irqsave(&np->lock, flags); + netif_stop_queue(dev); + np->tx_stop = 1; +- spin_unlock_irq(&np->lock); ++ spin_unlock_irqrestore(&np->lock, flags); + return NETDEV_TX_BUSY; + } + +@@ -1929,13 +1930,13 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) + tx_flags_extra = skb->ip_summed == CHECKSUM_PARTIAL ? + NV_TX2_CHECKSUM_L3 | NV_TX2_CHECKSUM_L4 : 0; + +- spin_lock_irq(&np->lock); ++ spin_lock_irqsave(&np->lock, flags); + + /* set tx flags */ + start_tx->flaglen |= cpu_to_le32(tx_flags | tx_flags_extra); + np->put_tx.orig = put_tx; + +- spin_unlock_irq(&np->lock); ++ spin_unlock_irqrestore(&np->lock, flags); + + dprintk(KERN_DEBUG "%s: nv_start_xmit: entries %d queued for transmission. tx_flags_extra: %x\n", + dev->name, entries, tx_flags_extra); +@@ -1971,6 +1972,7 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev) + struct ring_desc_ex* prev_tx; + struct nv_skb_map* prev_tx_ctx; + struct nv_skb_map* start_tx_ctx; ++ unsigned long flags; + + /* add fragments to entries count */ + for (i = 0; i < fragments; i++) { +@@ -1980,10 +1982,10 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev) + + empty_slots = nv_get_empty_tx_slots(np); + if (unlikely(empty_slots <= entries)) { +- spin_lock_irq(&np->lock); ++ spin_lock_irqsave(&np->lock, flags); + netif_stop_queue(dev); + np->tx_stop = 1; +- spin_unlock_irq(&np->lock); ++ spin_unlock_irqrestore(&np->lock, flags); + return NETDEV_TX_BUSY; + } + +@@ -2059,7 +2061,7 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev) + start_tx->txvlan = 0; + } + +- spin_lock_irq(&np->lock); ++ spin_lock_irqsave(&np->lock, flags); + + if (np->tx_limit) { + /* Limit the number of outstanding tx. Setup all fragments, but +@@ -2085,7 +2087,7 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev) + start_tx->flaglen |= cpu_to_le32(tx_flags | tx_flags_extra); + np->put_tx.ex = put_tx; + +- spin_unlock_irq(&np->lock); ++ spin_unlock_irqrestore(&np->lock, flags); + + dprintk(KERN_DEBUG "%s: nv_start_xmit_optimized: entries %d queued for transmission. tx_flags_extra: %x\n", + dev->name, entries, tx_flags_extra); +diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c +index 0789802..378a239 100644 +--- a/drivers/net/ibm_newemac/core.c ++++ b/drivers/net/ibm_newemac/core.c +@@ -1242,8 +1242,8 @@ static int emac_close(struct net_device *ndev) + static inline u16 emac_tx_csum(struct emac_instance *dev, + struct sk_buff *skb) + { +- if (emac_has_feature(dev, EMAC_FTR_HAS_TAH && +- skb->ip_summed == CHECKSUM_PARTIAL)) { ++ if (emac_has_feature(dev, EMAC_FTR_HAS_TAH) && ++ (skb->ip_summed == CHECKSUM_PARTIAL)) { + ++dev->stats.tx_packets_csum; + return EMAC_TX_CTRL_TAH_CSUM; + } +diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c +index 3c915b8..c082cf0 100644 +--- a/drivers/net/s2io.c ++++ b/drivers/net/s2io.c +@@ -84,7 +84,7 @@ + #include "s2io.h" + #include "s2io-regs.h" + +-#define DRV_VERSION "2.0.26.15-2" ++#define DRV_VERSION "2.0.26.20" + + /* S2io Driver name & version. */ + static char s2io_driver_name[] = "Neterion"; +diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c +index 54c6626..853bce0 100644 +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -4329,10 +4329,14 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) + if (!hw) + return 0; + ++ del_timer_sync(&hw->watchdog_timer); ++ cancel_work_sync(&hw->restart_work); ++ + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; + struct sky2_port *sky2 = netdev_priv(dev); + ++ netif_device_detach(dev); + if (netif_running(dev)) + sky2_down(dev); + +@@ -4383,6 +4387,8 @@ static int sky2_resume(struct pci_dev *pdev) + + for (i = 0; i < hw->ports; i++) { + struct net_device *dev = hw->dev[i]; ++ ++ netif_device_attach(dev); + if (netif_running(dev)) { + err = sky2_up(dev); + if (err) { +diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c +index 206918b..da2206f 100644 +--- a/drivers/net/tulip/eeprom.c ++++ b/drivers/net/tulip/eeprom.c +@@ -343,6 +343,12 @@ int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_l + void __iomem *ee_addr = tp->base_addr + CSR9; + int read_cmd = location | (EE_READ_CMD << addr_len); + ++ /* If location is past the end of what we can address, don't ++ * read some other location (ie truncate). Just return zero. ++ */ ++ if (location > (1 << addr_len) - 1) ++ return 0; ++ + iowrite32(EE_ENB & ~EE_CS, ee_addr); + iowrite32(EE_ENB, ee_addr); + +diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c +index ed600bf..82f404b 100644 +--- a/drivers/net/tulip/tulip_core.c ++++ b/drivers/net/tulip/tulip_core.c +@@ -1437,6 +1437,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, + EEPROM. + */ + ee_data = tp->eeprom; ++ memset(ee_data, 0, sizeof(tp->eeprom)); + sum = 0; + if (chip_idx == LC82C168) { + for (i = 0; i < 3; i++) { +@@ -1458,8 +1459,12 @@ static int __devinit tulip_init_one (struct pci_dev *pdev, + /* A serial EEPROM interface, we read now and sort it out later. */ + int sa_offset = 0; + int ee_addr_size = tulip_read_eeprom(dev, 0xff, 8) & 0x40000 ? 8 : 6; ++ int ee_max_addr = ((1 << ee_addr_size) - 1) * sizeof(u16); + +- for (i = 0; i < sizeof(tp->eeprom); i+=2) { ++ if (ee_max_addr > sizeof(tp->eeprom)) ++ ee_max_addr = sizeof(tp->eeprom); ++ ++ for (i = 0; i < ee_max_addr ; i += sizeof(u16)) { + u16 data = tulip_read_eeprom(dev, i/2, ee_addr_size); + ee_data[i] = data & 0xff; + ee_data[i + 1] = data >> 8; +diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig +index a12c9c4..0604f3f 100644 +--- a/drivers/net/usb/Kconfig ++++ b/drivers/net/usb/Kconfig +@@ -129,7 +129,7 @@ config USB_USBNET + + config USB_NET_AX8817X + tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters" +- depends on USB_USBNET && NET_ETHERNET ++ depends on USB_USBNET + select CRC32 + default y + help +diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c +index 0343b00..01660f6 100644 +--- a/drivers/net/usb/dm9601.c ++++ b/drivers/net/usb/dm9601.c +@@ -354,7 +354,7 @@ static void dm9601_set_multicast(struct net_device *net) + struct dev_mc_list *mc_list = net->mc_list; + int i; + +- for (i = 0; i < net->mc_count; i++) { ++ for (i = 0; i < net->mc_count; i++, mc_list = mc_list->next) { + u32 crc = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; + hashes[crc >> 3] |= 1 << (crc & 0x7); + } +diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c +index d1ed68a..b588c89 100644 +--- a/drivers/net/usb/pegasus.c ++++ b/drivers/net/usb/pegasus.c +@@ -1128,12 +1128,8 @@ pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) + { + pegasus_t *pegasus; + +- if (in_atomic()) +- return 0; +- + pegasus = netdev_priv(dev); + mii_ethtool_gset(&pegasus->mii, ecmd); +- + return 0; + } + +diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c +index fb37b80..824df3b 100644 +--- a/drivers/net/wan/lapbether.c ++++ b/drivers/net/wan/lapbether.c +@@ -58,7 +58,7 @@ struct lapbethdev { + struct net_device_stats stats; /* some statistics */ + }; + +-static struct list_head lapbeth_devices = LIST_HEAD_INIT(lapbeth_devices); ++static LIST_HEAD(lapbeth_devices); + + /* ------------------------------------------------------------------------ */ + +diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c +index cfbc1a2..948eb1f 100644 +--- a/drivers/net/wireless/b43/dma.c ++++ b/drivers/net/wireless/b43/dma.c +@@ -619,6 +619,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, + } + + if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { ++ b43err(ring->dev->wl, "RX DMA buffer allocation failed\n"); + dev_kfree_skb_any(skb); + return -EIO; + } +@@ -874,8 +875,12 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, + DMA_TO_DEVICE); + + if (b43_dma_mapping_error(ring, dma_test, +- b43_txhdr_size(dev), 1)) ++ b43_txhdr_size(dev), 1)) { ++ ++ b43err(dev->wl, ++ "TXHDR DMA allocation failed\n"); + goto err_kfree_txhdr_cache; ++ } + } + + dma_unmap_single(dev->dev->dev, +diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c +index b79a6bd..371e4a1 100644 +--- a/drivers/net/wireless/b43/pcmcia.c ++++ b/drivers/net/wireless/b43/pcmcia.c +@@ -91,6 +91,8 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) + + dev->conf.ConfigBase = parse.config.base; + dev->conf.Present = parse.config.rmask[0]; ++ dev->conf.Attributes = CONF_ENABLE_IRQ; ++ dev->conf.IntType = INT_MEMORY_AND_IO; + + dev->io.BasePort2 = 0; + dev->io.NumPorts2 = 0; +@@ -112,8 +114,8 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) + if (res != CS_SUCCESS) + goto err_disable; + +- dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FIRST_SHARED; +- dev->irq.IRQInfo1 = IRQ_LEVEL_ID | IRQ_SHARE_ID; ++ dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; ++ dev->irq.IRQInfo1 = IRQ_LEVEL_ID; + dev->irq.Handler = NULL; /* The handler is registered later. */ + dev->irq.Instance = NULL; + res = pcmcia_request_irq(dev, &dev->irq); +diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c +index d727de8..6576757 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-4965.c ++++ b/drivers/net/wireless/iwlwifi/iwl-4965.c +@@ -4589,7 +4589,7 @@ static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv, + + if (sta_ht_inf) { + if ((!sta_ht_inf->ht_supported) || +- (!sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH)) ++ (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH))) + return 0; + } + +diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c +index 5a9cadb..038c66a 100644 +--- a/drivers/net/wireless/libertas/if_cs.c ++++ b/drivers/net/wireless/libertas/if_cs.c +@@ -677,9 +677,7 @@ sbi_get_int_status_exit: + + /* Card has a command result for us */ + if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) { +- spin_lock(&priv->driver_lock); + ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len); +- spin_unlock(&priv->driver_lock); + if (ret < 0) + lbs_pr_err("could not receive cmd from card\n"); + } +diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c +index bd305f7..e873a39 100644 +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -1393,11 +1393,20 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) + + exit: + /* +- * Set device mode to sleep for power management. ++ * Set device mode to sleep for power management, ++ * on some hardware this call seems to consistently fail. ++ * From the specifications it is hard to tell why it fails, ++ * and if this is a "bad thing". ++ * Overall it is safe to just ignore the failure and ++ * continue suspending. The only downside is that the ++ * device will not be in optimal power save mode, but with ++ * the radio and the other components already disabled the ++ * device is as good as disabled. + */ + retval = rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP); + if (retval) +- return retval; ++ WARNING(rt2x00dev, "Device failed to enter sleep state, " ++ "continue suspending.\n"); + + return 0; + } +diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c +index 880c78b..ed7e0a1 100644 +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -218,18 +218,24 @@ int scsi_add_host(struct Scsi_Host *shost, struct device *dev) + + get_device(&shost->shost_gendev); + +- if (shost->transportt->host_size && +- (shost->shost_data = kzalloc(shost->transportt->host_size, +- GFP_KERNEL)) == NULL) +- goto out_del_classdev; ++ if (shost->transportt->host_size) { ++ shost->shost_data = kzalloc(shost->transportt->host_size, ++ GFP_KERNEL); ++ if (shost->shost_data == NULL) { ++ error = -ENOMEM; ++ goto out_del_classdev; ++ } ++ } + + if (shost->transportt->create_work_queue) { + snprintf(shost->work_q_name, KOBJ_NAME_LEN, "scsi_wq_%d", + shost->host_no); + shost->work_q = create_singlethread_workqueue( + shost->work_q_name); +- if (!shost->work_q) ++ if (!shost->work_q) { ++ error = -EINVAL; + goto out_free_shost_data; ++ } + } + + error = scsi_sysfs_add_host(shost); +diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c +index 31b9af2..709a6f7 100644 +--- a/drivers/scsi/libsas/sas_discover.c ++++ b/drivers/scsi/libsas/sas_discover.c +@@ -295,11 +295,14 @@ static void sas_discover_domain(struct work_struct *work) + case FANOUT_DEV: + error = sas_discover_root_expander(dev); + break; +-#ifdef CONFIG_SCSI_SAS_ATA + case SATA_DEV: + case SATA_PM: ++#ifdef CONFIG_SCSI_SAS_ATA + error = sas_discover_sata(dev); + break; ++#else ++ SAS_DPRINTK("ATA device seen but CONFIG_SCSI_SAS_ATA=N so cannot attach\n"); ++ /* Fall through */ + #endif + default: + error = -ENXIO; +diff --git a/drivers/scsi/mvsas.c b/drivers/scsi/mvsas.c +index 5ec0665..e55b903 100644 +--- a/drivers/scsi/mvsas.c ++++ b/drivers/scsi/mvsas.c +@@ -37,11 +37,13 @@ + #include + #include + #include ++#include ++#include + #include + + #define DRV_NAME "mvsas" +-#define DRV_VERSION "0.5.1" +-#define _MV_DUMP 0 ++#define DRV_VERSION "0.5.2" ++#define _MV_DUMP 0 + #define MVS_DISABLE_NVRAM + #define MVS_DISABLE_MSI + +@@ -52,7 +54,7 @@ + readl(regs + MVS_##reg); \ + } while (0) + +-#define MVS_ID_NOT_MAPPED 0xff ++#define MVS_ID_NOT_MAPPED 0x7f + #define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width) + + /* offset for D2H FIS in the Received FIS List Structure */ +@@ -84,6 +86,7 @@ enum driver_configuration { + MVS_RX_FIS_COUNT = 17, /* Optional rx'd FISs (max 17) */ + + MVS_QUEUE_SIZE = 30, /* Support Queue depth */ ++ MVS_CAN_QUEUE = MVS_SLOTS - 1, /* SCSI Queue depth */ + }; + + /* unchangeable hardware details */ +@@ -358,7 +361,20 @@ enum hw_register_bits { + + /* VSR */ + /* PHYMODE 6 (CDB) */ +- PHY_MODE6_DTL_SPEED = (1U << 27), ++ PHY_MODE6_LATECLK = (1U << 29), /* Lock Clock */ ++ PHY_MODE6_DTL_SPEED = (1U << 27), /* Digital Loop Speed */ ++ PHY_MODE6_FC_ORDER = (1U << 26), /* Fibre Channel Mode Order*/ ++ PHY_MODE6_MUCNT_EN = (1U << 24), /* u Count Enable */ ++ PHY_MODE6_SEL_MUCNT_LEN = (1U << 22), /* Training Length Select */ ++ PHY_MODE6_SELMUPI = (1U << 20), /* Phase Multi Select (init) */ ++ PHY_MODE6_SELMUPF = (1U << 18), /* Phase Multi Select (final) */ ++ PHY_MODE6_SELMUFF = (1U << 16), /* Freq Loop Multi Sel(final) */ ++ PHY_MODE6_SELMUFI = (1U << 14), /* Freq Loop Multi Sel(init) */ ++ PHY_MODE6_FREEZE_LOOP = (1U << 12), /* Freeze Rx CDR Loop */ ++ PHY_MODE6_INT_RXFOFFS = (1U << 3), /* Rx CDR Freq Loop Enable */ ++ PHY_MODE6_FRC_RXFOFFS = (1U << 2), /* Initial Rx CDR Offset */ ++ PHY_MODE6_STAU_0D8 = (1U << 1), /* Rx CDR Freq Loop Saturate */ ++ PHY_MODE6_RXSAT_DIS = (1U << 0), /* Saturate Ctl */ + }; + + enum mvs_info_flags { +@@ -511,7 +527,43 @@ enum status_buffer { + }; + + enum error_info_rec { +- CMD_ISS_STPD = (1U << 31), /* Cmd Issue Stopped */ ++ CMD_ISS_STPD = (1U << 31), /* Cmd Issue Stopped */ ++ CMD_PI_ERR = (1U << 30), /* Protection info error. see flags2 */ ++ RSP_OVER = (1U << 29), /* rsp buffer overflow */ ++ RETRY_LIM = (1U << 28), /* FIS/frame retry limit exceeded */ ++ UNK_FIS = (1U << 27), /* unknown FIS */ ++ DMA_TERM = (1U << 26), /* DMA terminate primitive rx'd */ ++ SYNC_ERR = (1U << 25), /* SYNC rx'd during frame xmit */ ++ TFILE_ERR = (1U << 24), /* SATA taskfile Error bit set */ ++ R_ERR = (1U << 23), /* SATA returned R_ERR prim */ ++ RD_OFS = (1U << 20), /* Read DATA frame invalid offset */ ++ XFER_RDY_OFS = (1U << 19), /* XFER_RDY offset error */ ++ UNEXP_XFER_RDY = (1U << 18), /* unexpected XFER_RDY error */ ++ DATA_OVER_UNDER = (1U << 16), /* data overflow/underflow */ ++ INTERLOCK = (1U << 15), /* interlock error */ ++ NAK = (1U << 14), /* NAK rx'd */ ++ ACK_NAK_TO = (1U << 13), /* ACK/NAK timeout */ ++ CXN_CLOSED = (1U << 12), /* cxn closed w/out ack/nak */ ++ OPEN_TO = (1U << 11), /* I_T nexus lost, open cxn timeout */ ++ PATH_BLOCKED = (1U << 10), /* I_T nexus lost, pathway blocked */ ++ NO_DEST = (1U << 9), /* I_T nexus lost, no destination */ ++ STP_RES_BSY = (1U << 8), /* STP resources busy */ ++ BREAK = (1U << 7), /* break received */ ++ BAD_DEST = (1U << 6), /* bad destination */ ++ BAD_PROTO = (1U << 5), /* protocol not supported */ ++ BAD_RATE = (1U << 4), /* cxn rate not supported */ ++ WRONG_DEST = (1U << 3), /* wrong destination error */ ++ CREDIT_TO = (1U << 2), /* credit timeout */ ++ WDOG_TO = (1U << 1), /* watchdog timeout */ ++ BUF_PAR = (1U << 0), /* buffer parity error */ ++}; ++ ++enum error_info_rec_2 { ++ SLOT_BSY_ERR = (1U << 31), /* Slot Busy Error */ ++ GRD_CHK_ERR = (1U << 14), /* Guard Check Error */ ++ APP_CHK_ERR = (1U << 13), /* Application Check error */ ++ REF_CHK_ERR = (1U << 12), /* Reference Check Error */ ++ USR_BLK_NM = (1U << 0), /* User Block Number */ + }; + + struct mvs_chip_info { +@@ -543,28 +595,12 @@ struct mvs_cmd_hdr { + __le32 reserved[4]; + }; + +-struct mvs_slot_info { +- struct sas_task *task; +- u32 n_elem; +- u32 tx; +- +- /* DMA buffer for storing cmd tbl, open addr frame, status buffer, +- * and PRD table +- */ +- void *buf; +- dma_addr_t buf_dma; +-#if _MV_DUMP +- u32 cmd_size; +-#endif +- +- void *response; +-}; +- + struct mvs_port { + struct asd_sas_port sas_port; + u8 port_attached; + u8 taskfileset; + u8 wide_port_phymap; ++ struct list_head list; + }; + + struct mvs_phy { +@@ -582,6 +618,27 @@ struct mvs_phy { + u32 frame_rcvd_size; + u8 frame_rcvd[32]; + u8 phy_attached; ++ enum sas_linkrate minimum_linkrate; ++ enum sas_linkrate maximum_linkrate; ++}; ++ ++struct mvs_slot_info { ++ struct list_head list; ++ struct sas_task *task; ++ u32 n_elem; ++ u32 tx; ++ ++ /* DMA buffer for storing cmd tbl, open addr frame, status buffer, ++ * and PRD table ++ */ ++ void *buf; ++ dma_addr_t buf_dma; ++#if _MV_DUMP ++ u32 cmd_size; ++#endif ++ ++ void *response; ++ struct mvs_port *port; + }; + + struct mvs_info { +@@ -612,21 +669,14 @@ struct mvs_info { + + const struct mvs_chip_info *chip; + +- unsigned long tags[MVS_SLOTS]; ++ u8 tags[MVS_SLOTS]; + struct mvs_slot_info slot_info[MVS_SLOTS]; + /* further per-slot information */ + struct mvs_phy phy[MVS_MAX_PHYS]; + struct mvs_port port[MVS_MAX_PHYS]; +- +- u32 can_queue; /* per adapter */ +- u32 tag_out; /*Get*/ +- u32 tag_in; /*Give*/ +-}; +- +-struct mvs_queue_task { +- struct list_head list; +- +- void *uldd_task; ++#ifdef MVS_USE_TASKLET ++ struct tasklet_struct tasklet; ++#endif + }; + + static int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, +@@ -641,10 +691,11 @@ static u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port); + static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i); + static void mvs_detect_porttype(struct mvs_info *mvi, int i); + static void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st); ++static void mvs_release_task(struct mvs_info *mvi, int phy_no); + + static int mvs_scan_finished(struct Scsi_Host *, unsigned long); + static void mvs_scan_start(struct Scsi_Host *); +-static int mvs_sas_slave_alloc(struct scsi_device *scsi_dev); ++static int mvs_slave_configure(struct scsi_device *sdev); + + static struct scsi_transport_template *mvs_stt; + +@@ -659,7 +710,7 @@ static struct scsi_host_template mvs_sht = { + .name = DRV_NAME, + .queuecommand = sas_queuecommand, + .target_alloc = sas_target_alloc, +- .slave_configure = sas_slave_configure, ++ .slave_configure = mvs_slave_configure, + .slave_destroy = sas_slave_destroy, + .scan_finished = mvs_scan_finished, + .scan_start = mvs_scan_start, +@@ -674,7 +725,7 @@ static struct scsi_host_template mvs_sht = { + .use_clustering = ENABLE_CLUSTERING, + .eh_device_reset_handler = sas_eh_device_reset_handler, + .eh_bus_reset_handler = sas_eh_bus_reset_handler, +- .slave_alloc = mvs_sas_slave_alloc, ++ .slave_alloc = sas_slave_alloc, + .target_destroy = sas_target_destroy, + .ioctl = sas_ioctl, + }; +@@ -709,10 +760,10 @@ static void mvs_hexdump(u32 size, u8 *data, u32 baseaddr) + printk("\n"); + } + ++#if _MV_DUMP + static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag, + enum sas_protocol proto) + { +-#if _MV_DUMP + u32 offset; + struct pci_dev *pdev = mvi->pdev; + struct mvs_slot_info *slot = &mvi->slot_info[tag]; +@@ -723,14 +774,14 @@ static void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag, + tag); + mvs_hexdump(32, (u8 *) slot->response, + (u32) slot->buf_dma + offset); +-#endif + } ++#endif + + static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, + enum sas_protocol proto) + { + #if _MV_DUMP +- u32 sz, w_ptr, r_ptr; ++ u32 sz, w_ptr; + u64 addr; + void __iomem *regs = mvi->regs; + struct pci_dev *pdev = mvi->pdev; +@@ -738,12 +789,10 @@ static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, + + /*Delivery Queue */ + sz = mr32(TX_CFG) & TX_RING_SZ_MASK; +- w_ptr = mr32(TX_PROD_IDX) & TX_RING_SZ_MASK; +- r_ptr = mr32(TX_CONS_IDX) & TX_RING_SZ_MASK; ++ w_ptr = slot->tx; + addr = mr32(TX_HI) << 16 << 16 | mr32(TX_LO); + dev_printk(KERN_DEBUG, &pdev->dev, +- "Delivery Queue Size=%04d , WRT_PTR=%04X , RD_PTR=%04X\n", +- sz, w_ptr, r_ptr); ++ "Delivery Queue Size=%04d , WRT_PTR=%04X\n", sz, w_ptr); + dev_printk(KERN_DEBUG, &pdev->dev, + "Delivery Queue Base Address=0x%llX (PA)" + "(tx_dma=0x%llX), Entry=%04d\n", +@@ -751,11 +800,11 @@ static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, + mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]), + (u32) mvi->tx_dma + sizeof(u32) * w_ptr); + /*Command List */ +- addr = mr32(CMD_LIST_HI) << 16 << 16 | mr32(CMD_LIST_LO); ++ addr = mvi->slot_dma; + dev_printk(KERN_DEBUG, &pdev->dev, + "Command List Base Address=0x%llX (PA)" + "(slot_dma=0x%llX), Header=%03d\n", +- addr, mvi->slot_dma, tag); ++ addr, slot->buf_dma, tag); + dev_printk(KERN_DEBUG, &pdev->dev, "Command Header[%03d]:\n", tag); + /*mvs_cmd_hdr */ + mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]), +@@ -779,7 +828,7 @@ static void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, + + static void mvs_hba_cq_dump(struct mvs_info *mvi) + { +-#if _MV_DUMP ++#if (_MV_DUMP > 2) + u64 addr; + void __iomem *regs = mvi->regs; + struct pci_dev *pdev = mvi->pdev; +@@ -788,8 +837,8 @@ static void mvs_hba_cq_dump(struct mvs_info *mvi) + + /*Completion Queue */ + addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO); +- dev_printk(KERN_DEBUG, &pdev->dev, "Completion Task = 0x%08X\n", +- (u32) mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task); ++ dev_printk(KERN_DEBUG, &pdev->dev, "Completion Task = 0x%p\n", ++ mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task); + dev_printk(KERN_DEBUG, &pdev->dev, + "Completion List Base Address=0x%llX (PA), " + "CQ_Entry=%04d, CQ_WP=0x%08X\n", +@@ -854,34 +903,53 @@ static int pci_go_64(struct pci_dev *pdev) + return rc; + } + ++static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag) ++{ ++ if (task->lldd_task) { ++ struct mvs_slot_info *slot; ++ slot = (struct mvs_slot_info *) task->lldd_task; ++ *tag = slot - mvi->slot_info; ++ return 1; ++ } ++ return 0; ++} ++ + static void mvs_tag_clear(struct mvs_info *mvi, u32 tag) + { +- mvi->tag_in = (mvi->tag_in + 1) & (MVS_SLOTS - 1); +- mvi->tags[mvi->tag_in] = tag; ++ void *bitmap = (void *) &mvi->tags; ++ clear_bit(tag, bitmap); + } + + static void mvs_tag_free(struct mvs_info *mvi, u32 tag) + { +- mvi->tag_out = (mvi->tag_out - 1) & (MVS_SLOTS - 1); ++ mvs_tag_clear(mvi, tag); ++} ++ ++static void mvs_tag_set(struct mvs_info *mvi, unsigned int tag) ++{ ++ void *bitmap = (void *) &mvi->tags; ++ set_bit(tag, bitmap); + } + + static int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out) + { +- if (mvi->tag_out != mvi->tag_in) { +- *tag_out = mvi->tags[mvi->tag_out]; +- mvi->tag_out = (mvi->tag_out + 1) & (MVS_SLOTS - 1); +- return 0; +- } +- return -EBUSY; ++ unsigned int index, tag; ++ void *bitmap = (void *) &mvi->tags; ++ ++ index = find_first_zero_bit(bitmap, MVS_SLOTS); ++ tag = index; ++ if (tag >= MVS_SLOTS) ++ return -SAS_QUEUE_FULL; ++ mvs_tag_set(mvi, tag); ++ *tag_out = tag; ++ return 0; + } + + static void mvs_tag_init(struct mvs_info *mvi) + { + int i; + for (i = 0; i < MVS_SLOTS; ++i) +- mvi->tags[i] = i; +- mvi->tag_out = 0; +- mvi->tag_in = MVS_SLOTS - 1; ++ mvs_tag_clear(mvi, i); + } + + #ifndef MVS_DISABLE_NVRAM +@@ -1013,10 +1081,21 @@ err_out: + static void mvs_bytes_dmaed(struct mvs_info *mvi, int i) + { + struct mvs_phy *phy = &mvi->phy[i]; ++ struct asd_sas_phy *sas_phy = mvi->sas.sas_phy[i]; + + if (!phy->phy_attached) + return; + ++ if (sas_phy->phy) { ++ struct sas_phy *sphy = sas_phy->phy; ++ ++ sphy->negotiated_linkrate = sas_phy->linkrate; ++ sphy->minimum_linkrate = phy->minimum_linkrate; ++ sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; ++ sphy->maximum_linkrate = phy->maximum_linkrate; ++ sphy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; ++ } ++ + if (phy->phy_type & PORT_TYPE_SAS) { + struct sas_identify_frame *id; + +@@ -1053,80 +1132,149 @@ static void mvs_scan_start(struct Scsi_Host *shost) + } + } + +-static int mvs_sas_slave_alloc(struct scsi_device *scsi_dev) ++static int mvs_slave_configure(struct scsi_device *sdev) + { +- int rc; ++ struct domain_device *dev = sdev_to_domain_dev(sdev); ++ int ret = sas_slave_configure(sdev); + +- rc = sas_slave_alloc(scsi_dev); ++ if (ret) ++ return ret; + +- return rc; ++ if (dev_is_sata(dev)) { ++ /* struct ata_port *ap = dev->sata_dev.ap; */ ++ /* struct ata_device *adev = ap->link.device; */ ++ ++ /* clamp at no NCQ for the time being */ ++ /* adev->flags |= ATA_DFLAG_NCQ_OFF; */ ++ scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1); ++ } ++ return 0; + } + +-static void mvs_int_port(struct mvs_info *mvi, int port_no, u32 events) ++static void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) + { + struct pci_dev *pdev = mvi->pdev; + struct sas_ha_struct *sas_ha = &mvi->sas; +- struct mvs_phy *phy = &mvi->phy[port_no]; ++ struct mvs_phy *phy = &mvi->phy[phy_no]; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + +- phy->irq_status = mvs_read_port_irq_stat(mvi, port_no); ++ phy->irq_status = mvs_read_port_irq_stat(mvi, phy_no); + /* + * events is port event now , + * we need check the interrupt status which belongs to per port. + */ + dev_printk(KERN_DEBUG, &pdev->dev, + "Port %d Event = %X\n", +- port_no, phy->irq_status); ++ phy_no, phy->irq_status); + + if (phy->irq_status & (PHYEV_POOF | PHYEV_DEC_ERR)) { +- if (!mvs_is_phy_ready(mvi, port_no)) { ++ mvs_release_task(mvi, phy_no); ++ if (!mvs_is_phy_ready(mvi, phy_no)) { + sas_phy_disconnected(sas_phy); + sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); ++ dev_printk(KERN_INFO, &pdev->dev, ++ "Port %d Unplug Notice\n", phy_no); ++ + } else + mvs_phy_control(sas_phy, PHY_FUNC_LINK_RESET, NULL); + } + if (!(phy->irq_status & PHYEV_DEC_ERR)) { + if (phy->irq_status & PHYEV_COMWAKE) { +- u32 tmp = mvs_read_port_irq_mask(mvi, port_no); +- mvs_write_port_irq_mask(mvi, port_no, ++ u32 tmp = mvs_read_port_irq_mask(mvi, phy_no); ++ mvs_write_port_irq_mask(mvi, phy_no, + tmp | PHYEV_SIG_FIS); + } + if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) { +- phy->phy_status = mvs_is_phy_ready(mvi, port_no); ++ phy->phy_status = mvs_is_phy_ready(mvi, phy_no); + if (phy->phy_status) { +- mvs_detect_porttype(mvi, port_no); ++ mvs_detect_porttype(mvi, phy_no); + + if (phy->phy_type & PORT_TYPE_SATA) { + u32 tmp = mvs_read_port_irq_mask(mvi, +- port_no); ++ phy_no); + tmp &= ~PHYEV_SIG_FIS; + mvs_write_port_irq_mask(mvi, +- port_no, tmp); ++ phy_no, tmp); + } + +- mvs_update_phyinfo(mvi, port_no, 0); ++ mvs_update_phyinfo(mvi, phy_no, 0); + sas_ha->notify_phy_event(sas_phy, + PHYE_OOB_DONE); +- mvs_bytes_dmaed(mvi, port_no); ++ mvs_bytes_dmaed(mvi, phy_no); + } else { + dev_printk(KERN_DEBUG, &pdev->dev, + "plugin interrupt but phy is gone\n"); + mvs_phy_control(sas_phy, PHY_FUNC_LINK_RESET, + NULL); + } +- } else if (phy->irq_status & PHYEV_BROAD_CH) ++ } else if (phy->irq_status & PHYEV_BROAD_CH) { ++ mvs_release_task(mvi, phy_no); + sas_ha->notify_port_event(sas_phy, + PORTE_BROADCAST_RCVD); ++ } + } +- mvs_write_port_irq_stat(mvi, port_no, phy->irq_status); ++ mvs_write_port_irq_stat(mvi, phy_no, phy->irq_status); + } + + static void mvs_int_sata(struct mvs_info *mvi) + { +- /* FIXME */ ++ u32 tmp; ++ void __iomem *regs = mvi->regs; ++ tmp = mr32(INT_STAT_SRS); ++ mw32(INT_STAT_SRS, tmp & 0xFFFF); ++} ++ ++static void mvs_slot_reset(struct mvs_info *mvi, struct sas_task *task, ++ u32 slot_idx) ++{ ++ void __iomem *regs = mvi->regs; ++ struct domain_device *dev = task->dev; ++ struct asd_sas_port *sas_port = dev->port; ++ struct mvs_port *port = mvi->slot_info[slot_idx].port; ++ u32 reg_set, phy_mask; ++ ++ if (!sas_protocol_ata(task->task_proto)) { ++ reg_set = 0; ++ phy_mask = (port->wide_port_phymap) ? port->wide_port_phymap : ++ sas_port->phy_mask; ++ } else { ++ reg_set = port->taskfileset; ++ phy_mask = sas_port->phy_mask; ++ } ++ mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | slot_idx | ++ (TXQ_CMD_SLOT_RESET << TXQ_CMD_SHIFT) | ++ (phy_mask << TXQ_PHY_SHIFT) | ++ (reg_set << TXQ_SRS_SHIFT)); ++ ++ mw32(TX_PROD_IDX, mvi->tx_prod); ++ mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); ++} ++ ++static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task, ++ u32 slot_idx, int err) ++{ ++ struct mvs_port *port = mvi->slot_info[slot_idx].port; ++ struct task_status_struct *tstat = &task->task_status; ++ struct ata_task_resp *resp = (struct ata_task_resp *)tstat->buf; ++ int stat = SAM_GOOD; ++ ++ resp->frame_len = sizeof(struct dev_to_host_fis); ++ memcpy(&resp->ending_fis[0], ++ SATA_RECEIVED_D2H_FIS(port->taskfileset), ++ sizeof(struct dev_to_host_fis)); ++ tstat->buf_valid_size = sizeof(*resp); ++ if (unlikely(err)) ++ stat = SAS_PROTO_RESPONSE; ++ return stat; + } + +-static void mvs_slot_free(struct mvs_info *mvi, struct sas_task *task, ++static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc) ++{ ++ u32 slot_idx = rx_desc & RXQ_SLOT_MASK; ++ mvs_tag_clear(mvi, slot_idx); ++} ++ ++static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task, + struct mvs_slot_info *slot, u32 slot_idx) + { + if (!sas_protocol_ata(task->task_proto)) +@@ -1149,38 +1297,58 @@ static void mvs_slot_free(struct mvs_info *mvi, struct sas_task *task, + /* do nothing */ + break; + } +- ++ list_del(&slot->list); ++ task->lldd_task = NULL; + slot->task = NULL; +- mvs_tag_clear(mvi, slot_idx); ++ slot->port = NULL; + } + +-static void mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, ++static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, + u32 slot_idx) + { + struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; +- u64 err_dw0 = *(u32 *) slot->response; +- void __iomem *regs = mvi->regs; +- u32 tmp; ++ u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response)); ++ u32 err_dw1 = le32_to_cpu(*(u32 *) (slot->response + 4)); ++ int stat = SAM_CHECK_COND; + +- if (err_dw0 & CMD_ISS_STPD) +- if (sas_protocol_ata(task->task_proto)) { +- tmp = mr32(INT_STAT_SRS); +- mw32(INT_STAT_SRS, tmp & 0xFFFF); +- } ++ if (err_dw1 & SLOT_BSY_ERR) { ++ stat = SAS_QUEUE_FULL; ++ mvs_slot_reset(mvi, task, slot_idx); ++ } ++ switch (task->task_proto) { ++ case SAS_PROTOCOL_SSP: ++ break; ++ case SAS_PROTOCOL_SMP: ++ break; ++ case SAS_PROTOCOL_SATA: ++ case SAS_PROTOCOL_STP: ++ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: ++ if (err_dw0 & TFILE_ERR) ++ stat = mvs_sata_done(mvi, task, slot_idx, 1); ++ break; ++ default: ++ break; ++ } + +- mvs_hba_sb_dump(mvi, slot_idx, task->task_proto); ++ mvs_hexdump(16, (u8 *) slot->response, 0); ++ return stat; + } + +-static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc) ++static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) + { + u32 slot_idx = rx_desc & RXQ_SLOT_MASK; + struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; + struct sas_task *task = slot->task; +- struct task_status_struct *tstat = &task->task_status; +- struct mvs_port *port = &mvi->port[task->dev->port->id]; ++ struct task_status_struct *tstat; ++ struct mvs_port *port; + bool aborted; + void *to; + ++ if (unlikely(!task || !task->lldd_task)) ++ return -1; ++ ++ mvs_hba_cq_dump(mvi); ++ + spin_lock(&task->task_state_lock); + aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED; + if (!aborted) { +@@ -1190,22 +1358,27 @@ static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc) + } + spin_unlock(&task->task_state_lock); + +- if (aborted) ++ if (aborted) { ++ mvs_slot_task_free(mvi, task, slot, slot_idx); ++ mvs_slot_free(mvi, rx_desc); + return -1; ++ } + ++ port = slot->port; ++ tstat = &task->task_status; + memset(tstat, 0, sizeof(*tstat)); + tstat->resp = SAS_TASK_COMPLETE; + +- +- if (unlikely(!port->port_attached)) { +- tstat->stat = SAS_PHY_DOWN; ++ if (unlikely(!port->port_attached || flags)) { ++ mvs_slot_err(mvi, task, slot_idx); ++ if (!sas_protocol_ata(task->task_proto)) ++ tstat->stat = SAS_PHY_DOWN; + goto out; + } + + /* error info record present */ +- if ((rx_desc & RXQ_ERR) && (*(u64 *) slot->response)) { +- tstat->stat = SAM_CHECK_COND; +- mvs_slot_err(mvi, task, slot_idx); ++ if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) { ++ tstat->stat = mvs_slot_err(mvi, task, slot_idx); + goto out; + } + +@@ -1242,21 +1415,7 @@ static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc) + case SAS_PROTOCOL_SATA: + case SAS_PROTOCOL_STP: + case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: { +- struct ata_task_resp *resp = +- (struct ata_task_resp *)tstat->buf; +- +- if ((rx_desc & (RXQ_DONE | RXQ_ERR | RXQ_ATTN)) == +- RXQ_DONE) +- tstat->stat = SAM_GOOD; +- else +- tstat->stat = SAM_CHECK_COND; +- +- resp->frame_len = sizeof(struct dev_to_host_fis); +- memcpy(&resp->ending_fis[0], +- SATA_RECEIVED_D2H_FIS(port->taskfileset), +- sizeof(struct dev_to_host_fis)); +- if (resp->ending_fis[2] & ATA_ERR) +- mvs_hexdump(16, resp->ending_fis, 0); ++ tstat->stat = mvs_sata_done(mvi, task, slot_idx, 0); + break; + } + +@@ -1266,11 +1425,34 @@ static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc) + } + + out: +- mvs_slot_free(mvi, task, slot, slot_idx); ++ mvs_slot_task_free(mvi, task, slot, slot_idx); ++ if (unlikely(tstat->stat != SAS_QUEUE_FULL)) ++ mvs_slot_free(mvi, rx_desc); ++ ++ spin_unlock(&mvi->lock); + task->task_done(task); ++ spin_lock(&mvi->lock); + return tstat->stat; + } + ++static void mvs_release_task(struct mvs_info *mvi, int phy_no) ++{ ++ struct list_head *pos, *n; ++ struct mvs_slot_info *slot; ++ struct mvs_phy *phy = &mvi->phy[phy_no]; ++ struct mvs_port *port = phy->port; ++ u32 rx_desc; ++ ++ if (!port) ++ return; ++ ++ list_for_each_safe(pos, n, &port->list) { ++ slot = container_of(pos, struct mvs_slot_info, list); ++ rx_desc = (u32) (slot - mvi->slot_info); ++ mvs_slot_complete(mvi, rx_desc, 1); ++ } ++} ++ + static void mvs_int_full(struct mvs_info *mvi) + { + void __iomem *regs = mvi->regs; +@@ -1305,40 +1487,43 @@ static int mvs_int_rx(struct mvs_info *mvi, bool self_clear) + * we don't have to stall the CPU reading that register. + * The actual RX ring is offset by one dword, due to this. + */ +- rx_prod_idx = mr32(RX_CONS_IDX) & RX_RING_SZ_MASK; +- if (rx_prod_idx == 0xfff) { /* h/w hasn't touched RX ring yet */ +- mvi->rx_cons = 0xfff; ++ rx_prod_idx = mvi->rx_cons; ++ mvi->rx_cons = le32_to_cpu(mvi->rx[0]); ++ if (mvi->rx_cons == 0xfff) /* h/w hasn't touched RX ring yet */ + return 0; +- } + + /* The CMPL_Q may come late, read from register and try again + * note: if coalescing is enabled, + * it will need to read from register every time for sure + */ + if (mvi->rx_cons == rx_prod_idx) +- return 0; ++ mvi->rx_cons = mr32(RX_CONS_IDX) & RX_RING_SZ_MASK; + +- if (mvi->rx_cons == 0xfff) +- mvi->rx_cons = MVS_RX_RING_SZ - 1; ++ if (mvi->rx_cons == rx_prod_idx) ++ return 0; + + while (mvi->rx_cons != rx_prod_idx) { + + /* increment our internal RX consumer pointer */ +- mvi->rx_cons = (mvi->rx_cons + 1) & (MVS_RX_RING_SZ - 1); ++ rx_prod_idx = (rx_prod_idx + 1) & (MVS_RX_RING_SZ - 1); + +- rx_desc = le32_to_cpu(mvi->rx[mvi->rx_cons + 1]); +- +- mvs_hba_cq_dump(mvi); ++ rx_desc = le32_to_cpu(mvi->rx[rx_prod_idx + 1]); + + if (likely(rx_desc & RXQ_DONE)) +- mvs_slot_complete(mvi, rx_desc); ++ mvs_slot_complete(mvi, rx_desc, 0); + if (rx_desc & RXQ_ATTN) { + attn = true; + dev_printk(KERN_DEBUG, &pdev->dev, "ATTN %X\n", + rx_desc); + } else if (rx_desc & RXQ_ERR) { ++ if (!(rx_desc & RXQ_DONE)) ++ mvs_slot_complete(mvi, rx_desc, 0); + dev_printk(KERN_DEBUG, &pdev->dev, "RXQ_ERR %X\n", + rx_desc); ++ } else if (rx_desc & RXQ_SLOT_RESET) { ++ dev_printk(KERN_DEBUG, &pdev->dev, "Slot reset[%X]\n", ++ rx_desc); ++ mvs_slot_free(mvi, rx_desc); + } + } + +@@ -1348,6 +1533,23 @@ static int mvs_int_rx(struct mvs_info *mvi, bool self_clear) + return 0; + } + ++#ifdef MVS_USE_TASKLET ++static void mvs_tasklet(unsigned long data) ++{ ++ struct mvs_info *mvi = (struct mvs_info *) data; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&mvi->lock, flags); ++ ++#ifdef MVS_DISABLE_MSI ++ mvs_int_full(mvi); ++#else ++ mvs_int_rx(mvi, true); ++#endif ++ spin_unlock_irqrestore(&mvi->lock, flags); ++} ++#endif ++ + static irqreturn_t mvs_interrupt(int irq, void *opaque) + { + struct mvs_info *mvi = opaque; +@@ -1356,18 +1558,21 @@ static irqreturn_t mvs_interrupt(int irq, void *opaque) + + stat = mr32(GBL_INT_STAT); + +- /* clear CMD_CMPLT ASAP */ +- mw32_f(INT_STAT, CINT_DONE); +- + if (stat == 0 || stat == 0xffffffff) + return IRQ_NONE; + ++ /* clear CMD_CMPLT ASAP */ ++ mw32_f(INT_STAT, CINT_DONE); ++ ++#ifndef MVS_USE_TASKLET + spin_lock(&mvi->lock); + + mvs_int_full(mvi); + + spin_unlock(&mvi->lock); +- ++#else ++ tasklet_schedule(&mvi->tasklet); ++#endif + return IRQ_HANDLED; + } + +@@ -1376,12 +1581,15 @@ static irqreturn_t mvs_msi_interrupt(int irq, void *opaque) + { + struct mvs_info *mvi = opaque; + ++#ifndef MVS_USE_TASKLET + spin_lock(&mvi->lock); + + mvs_int_rx(mvi, true); + + spin_unlock(&mvi->lock); +- ++#else ++ tasklet_schedule(&mvi->tasklet); ++#endif + return IRQ_HANDLED; + } + #endif +@@ -1576,15 +1784,19 @@ static u8 mvs_assign_reg_set(struct mvs_info *mvi, struct mvs_port *port) + return MVS_ID_NOT_MAPPED; + } + +-static u32 mvs_get_ncq_tag(struct sas_task *task) ++static u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag) + { +- u32 tag = 0; + struct ata_queued_cmd *qc = task->uldd_task; + +- if (qc) +- tag = qc->tag; ++ if (qc) { ++ if (qc->tf.command == ATA_CMD_FPDMA_WRITE || ++ qc->tf.command == ATA_CMD_FPDMA_READ) { ++ *tag = qc->tag; ++ return 1; ++ } ++ } + +- return tag; ++ return 0; + } + + static int mvs_task_prep_ata(struct mvs_info *mvi, +@@ -1628,11 +1840,9 @@ static int mvs_task_prep_ata(struct mvs_info *mvi, + hdr->flags = cpu_to_le32(flags); + + /* FIXME: the low order order 5 bits for the TAG if enable NCQ */ +- if (task->ata_task.use_ncq) { +- hdr->tags = cpu_to_le32(mvs_get_ncq_tag(task)); +- /*Fill in task file */ +- task->ata_task.fis.sector_count = hdr->tags << 3; +- } else ++ if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr->tags)) ++ task->ata_task.fis.sector_count |= hdr->tags << 3; ++ else + hdr->tags = cpu_to_le32(tag); + hdr->data_len = cpu_to_le32(task->total_xfer_len); + +@@ -1725,13 +1935,16 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi, + u32 flags; + u32 resp_len, req_len, i, tag = tei->tag; + const u32 max_resp_len = SB_RFB_MAX; ++ u8 phy_mask; + + slot = &mvi->slot_info[tag]; + ++ phy_mask = (port->wide_port_phymap) ? port->wide_port_phymap : ++ task->dev->port->phy_mask; + slot->tx = mvi->tx_prod; + mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag | + (TXQ_CMD_SSP << TXQ_CMD_SHIFT) | +- (port->wide_port_phymap << TXQ_PHY_SHIFT)); ++ (phy_mask << TXQ_PHY_SHIFT)); + + flags = MCH_RETRY; + if (task->ssp_task.enable_first_burst) { +@@ -1832,22 +2045,32 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags) + void __iomem *regs = mvi->regs; + struct mvs_task_exec_info tei; + struct sas_task *t = task; ++ struct mvs_slot_info *slot; + u32 tag = 0xdeadbeef, rc, n_elem = 0; + unsigned long flags; + u32 n = num, pass = 0; + + spin_lock_irqsave(&mvi->lock, flags); +- + do { ++ dev = t->dev; + tei.port = &mvi->port[dev->port->id]; + + if (!tei.port->port_attached) { +- struct task_status_struct *ts = &t->task_status; +- ts->stat = SAS_PHY_DOWN; +- t->task_done(t); +- rc = 0; +- goto exec_exit; ++ if (sas_protocol_ata(t->task_proto)) { ++ rc = SAS_PHY_DOWN; ++ goto out_done; ++ } else { ++ struct task_status_struct *ts = &t->task_status; ++ ts->resp = SAS_TASK_UNDELIVERED; ++ ts->stat = SAS_PHY_DOWN; ++ t->task_done(t); ++ if (n > 1) ++ t = list_entry(t->list.next, ++ struct sas_task, list); ++ continue; ++ } + } ++ + if (!sas_protocol_ata(t->task_proto)) { + if (t->num_scatter) { + n_elem = pci_map_sg(mvi->pdev, t->scatter, +@@ -1866,9 +2089,10 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags) + if (rc) + goto err_out; + +- mvi->slot_info[tag].task = t; +- mvi->slot_info[tag].n_elem = n_elem; +- memset(mvi->slot_info[tag].buf, 0, MVS_SLOT_BUF_SZ); ++ slot = &mvi->slot_info[tag]; ++ t->lldd_task = NULL; ++ slot->n_elem = n_elem; ++ memset(slot->buf, 0, MVS_SLOT_BUF_SZ); + tei.task = t; + tei.hdr = &mvi->slot[tag]; + tei.tag = tag; +@@ -1897,28 +2121,26 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags) + if (rc) + goto err_out_tag; + ++ slot->task = t; ++ slot->port = tei.port; ++ t->lldd_task = (void *) slot; ++ list_add_tail(&slot->list, &slot->port->list); + /* TODO: select normal or high priority */ + + spin_lock(&t->task_state_lock); + t->task_state_flags |= SAS_TASK_AT_INITIATOR; + spin_unlock(&t->task_state_lock); + +- if (n == 1) { +- spin_unlock_irqrestore(&mvi->lock, flags); +- mw32(TX_PROD_IDX, mvi->tx_prod); +- } + mvs_hba_memory_dump(mvi, tag, t->task_proto); + + ++pass; + mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); +- +- if (n == 1) +- break; +- +- t = list_entry(t->list.next, struct sas_task, list); ++ if (n > 1) ++ t = list_entry(t->list.next, struct sas_task, list); + } while (--n); + +- return 0; ++ rc = 0; ++ goto out_done; + + err_out_tag: + mvs_tag_free(mvi, tag); +@@ -1928,7 +2150,7 @@ err_out: + if (n_elem) + pci_unmap_sg(mvi->pdev, t->scatter, n_elem, + t->data_dir); +-exec_exit: ++out_done: + if (pass) + mw32(TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); + spin_unlock_irqrestore(&mvi->lock, flags); +@@ -1937,42 +2159,59 @@ exec_exit: + + static int mvs_task_abort(struct sas_task *task) + { +- int rc = 1; ++ int rc; + unsigned long flags; + struct mvs_info *mvi = task->dev->port->ha->lldd_ha; + struct pci_dev *pdev = mvi->pdev; ++ int tag; + + spin_lock_irqsave(&task->task_state_lock, flags); + if (task->task_state_flags & SAS_TASK_STATE_DONE) { + rc = TMF_RESP_FUNC_COMPLETE; ++ spin_unlock_irqrestore(&task->task_state_lock, flags); + goto out_done; + } + spin_unlock_irqrestore(&task->task_state_lock, flags); + +- /*FIXME*/ +- rc = TMF_RESP_FUNC_COMPLETE; +- + switch (task->task_proto) { + case SAS_PROTOCOL_SMP: +- dev_printk(KERN_DEBUG, &pdev->dev, "SMP Abort! "); ++ dev_printk(KERN_DEBUG, &pdev->dev, "SMP Abort! \n"); + break; + case SAS_PROTOCOL_SSP: +- dev_printk(KERN_DEBUG, &pdev->dev, "SSP Abort! "); ++ dev_printk(KERN_DEBUG, &pdev->dev, "SSP Abort! \n"); + break; + case SAS_PROTOCOL_SATA: + case SAS_PROTOCOL_STP: + case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:{ +- dev_printk(KERN_DEBUG, &pdev->dev, "STP Abort! " +- "Dump D2H FIS: \n"); ++ dev_printk(KERN_DEBUG, &pdev->dev, "STP Abort! \n"); ++#if _MV_DUMP ++ dev_printk(KERN_DEBUG, &pdev->dev, "Dump D2H FIS: \n"); + mvs_hexdump(sizeof(struct host_to_dev_fis), + (void *)&task->ata_task.fis, 0); + dev_printk(KERN_DEBUG, &pdev->dev, "Dump ATAPI Cmd : \n"); + mvs_hexdump(16, task->ata_task.atapi_packet, 0); ++#endif ++ spin_lock_irqsave(&task->task_state_lock, flags); ++ if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET) { ++ /* TODO */ ++ ; ++ } ++ spin_unlock_irqrestore(&task->task_state_lock, flags); + break; + } + default: + break; + } ++ ++ if (mvs_find_tag(mvi, task, &tag)) { ++ spin_lock_irqsave(&mvi->lock, flags); ++ mvs_slot_task_free(mvi, task, &mvi->slot_info[tag], tag); ++ spin_unlock_irqrestore(&mvi->lock, flags); ++ } ++ if (!mvs_task_exec(task, 1, GFP_ATOMIC)) ++ rc = TMF_RESP_FUNC_COMPLETE; ++ else ++ rc = TMF_RESP_FUNC_FAILED; + out_done: + return rc; + } +@@ -2001,7 +2240,7 @@ static void mvs_free(struct mvs_info *mvi) + mvi->rx_fis, mvi->rx_fis_dma); + if (mvi->rx) + dma_free_coherent(&mvi->pdev->dev, +- sizeof(*mvi->rx) * MVS_RX_RING_SZ, ++ sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1), + mvi->rx, mvi->rx_dma); + if (mvi->slot) + dma_free_coherent(&mvi->pdev->dev, +@@ -2109,6 +2348,9 @@ static struct mvs_info *__devinit mvs_alloc(struct pci_dev *pdev, + return NULL; + + spin_lock_init(&mvi->lock); ++#ifdef MVS_USE_TASKLET ++ tasklet_init(&mvi->tasklet, mvs_tasklet, (unsigned long)mvi); ++#endif + mvi->pdev = pdev; + mvi->chip = chip; + +@@ -2132,6 +2374,10 @@ static struct mvs_info *__devinit mvs_alloc(struct pci_dev *pdev, + mvs_phy_init(mvi, i); + arr_phy[i] = &mvi->phy[i].sas_phy; + arr_port[i] = &mvi->port[i].sas_port; ++ mvi->port[i].taskfileset = MVS_ID_NOT_MAPPED; ++ mvi->port[i].wide_port_phymap = 0; ++ mvi->port[i].port_attached = 0; ++ INIT_LIST_HEAD(&mvi->port[i].list); + } + + SHOST_TO_SAS_HA(mvi->shost) = &mvi->sas; +@@ -2148,9 +2394,10 @@ static struct mvs_info *__devinit mvs_alloc(struct pci_dev *pdev, + mvi->sas.sas_phy = arr_phy; + mvi->sas.sas_port = arr_port; + mvi->sas.num_phys = chip->n_phy; +- mvi->sas.lldd_max_execute_num = MVS_CHIP_SLOT_SZ - 1; ++ mvi->sas.lldd_max_execute_num = 1; + mvi->sas.lldd_queue_size = MVS_QUEUE_SIZE; +- mvi->can_queue = (MVS_CHIP_SLOT_SZ >> 1) - 1; ++ mvi->shost->can_queue = MVS_CAN_QUEUE; ++ mvi->shost->cmd_per_lun = MVS_SLOTS / mvi->sas.num_phys; + mvi->sas.lldd_ha = mvi; + mvi->sas.core.shost = mvi->shost; + +@@ -2203,11 +2450,11 @@ static struct mvs_info *__devinit mvs_alloc(struct pci_dev *pdev, + memset(mvi->rx_fis, 0, MVS_RX_FISL_SZ); + + mvi->rx = dma_alloc_coherent(&pdev->dev, +- sizeof(*mvi->rx) * MVS_RX_RING_SZ, ++ sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1), + &mvi->rx_dma, GFP_KERNEL); + if (!mvi->rx) + goto err_out; +- memset(mvi->rx, 0, sizeof(*mvi->rx) * MVS_RX_RING_SZ); ++ memset(mvi->rx, 0, sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1)); + + mvi->rx[0] = cpu_to_le32(0xfff); + mvi->rx_cons = 0xfff; +@@ -2357,7 +2604,7 @@ static void __devinit mvs_phy_hacks(struct mvs_info *mvi) + mvs_cw32(regs, CMD_SAS_CTL0, tmp); + + /* workaround for WDTIMEOUT , set to 550 ms */ +- mvs_cw32(regs, CMD_WD_TIMER, 0xffffff); ++ mvs_cw32(regs, CMD_WD_TIMER, 0x86470); + + /* not to halt for different port op during wideport link change */ + mvs_cw32(regs, CMD_APP_ERR_CONFIG, 0xffefbf7d); +@@ -2465,17 +2712,16 @@ static u32 mvs_is_phy_ready(struct mvs_info *mvi, int i) + { + u32 tmp; + struct mvs_phy *phy = &mvi->phy[i]; +- struct mvs_port *port; ++ struct mvs_port *port = phy->port;; + + tmp = mvs_read_phy_ctl(mvi, i); + + if ((tmp & PHY_READY_MASK) && !(phy->irq_status & PHYEV_POOF)) { +- if (!phy->port) ++ if (!port) + phy->phy_attached = 1; + return tmp; + } + +- port = phy->port; + if (port) { + if (phy->phy_type & PORT_TYPE_SAS) { + port->wide_port_phymap &= ~(1U << i); +@@ -2497,7 +2743,7 @@ static void mvs_update_phyinfo(struct mvs_info *mvi, int i, + { + struct mvs_phy *phy = &mvi->phy[i]; + struct pci_dev *pdev = mvi->pdev; +- u32 tmp, j; ++ u32 tmp; + u64 tmp64; + + mvs_write_port_cfg_addr(mvi, i, PHYR_IDENTIFY); +@@ -2524,46 +2770,20 @@ static void mvs_update_phyinfo(struct mvs_info *mvi, int i, + sas_phy->linkrate = + (phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >> + PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET; +- +- /* Updated attached_sas_addr */ +- mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_HI); +- phy->att_dev_sas_addr = +- (u64) mvs_read_port_cfg_data(mvi, i) << 32; +- +- mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_LO); +- phy->att_dev_sas_addr |= mvs_read_port_cfg_data(mvi, i); +- +- dev_printk(KERN_DEBUG, &pdev->dev, +- "phy[%d] Get Attached Address 0x%llX ," +- " SAS Address 0x%llX\n", +- i, phy->att_dev_sas_addr, phy->dev_sas_addr); +- dev_printk(KERN_DEBUG, &pdev->dev, +- "Rate = %x , type = %d\n", +- sas_phy->linkrate, phy->phy_type); +- +-#if 1 +- /* +- * If the device is capable of supporting a wide port +- * on its phys, it may configure the phys as a wide port. +- */ +- if (phy->phy_type & PORT_TYPE_SAS) +- for (j = 0; j < mvi->chip->n_phy && j != i; ++j) { +- if ((mvi->phy[j].phy_attached) && +- (mvi->phy[j].phy_type & PORT_TYPE_SAS)) +- if (phy->att_dev_sas_addr == +- mvi->phy[j].att_dev_sas_addr - 1) { +- phy->att_dev_sas_addr = +- mvi->phy[j].att_dev_sas_addr; +- break; +- } +- } +- +-#endif +- +- tmp64 = cpu_to_be64(phy->att_dev_sas_addr); +- memcpy(sas_phy->attached_sas_addr, &tmp64, SAS_ADDR_SIZE); ++ phy->minimum_linkrate = ++ (phy->phy_status & ++ PHY_MIN_SPP_PHYS_LINK_RATE_MASK) >> 8; ++ phy->maximum_linkrate = ++ (phy->phy_status & ++ PHY_MAX_SPP_PHYS_LINK_RATE_MASK) >> 12; + + if (phy->phy_type & PORT_TYPE_SAS) { ++ /* Updated attached_sas_addr */ ++ mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_HI); ++ phy->att_dev_sas_addr = ++ (u64) mvs_read_port_cfg_data(mvi, i) << 32; ++ mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_LO); ++ phy->att_dev_sas_addr |= mvs_read_port_cfg_data(mvi, i); + mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_DEV_INFO); + phy->att_dev_info = mvs_read_port_cfg_data(mvi, i); + phy->identify.device_type = +@@ -2582,6 +2802,7 @@ static void mvs_update_phyinfo(struct mvs_info *mvi, int i, + } else if (phy->phy_type & PORT_TYPE_SATA) { + phy->identify.target_port_protocols = SAS_PROTOCOL_STP; + if (mvs_is_sig_fis_received(phy->irq_status)) { ++ phy->att_dev_sas_addr = i; /* temp */ + if (phy_st & PHY_OOB_DTCTD) + sas_phy->oob_mode = SATA_OOB_MODE; + phy->frame_rcvd_size = +@@ -2591,20 +2812,34 @@ static void mvs_update_phyinfo(struct mvs_info *mvi, int i, + } else { + dev_printk(KERN_DEBUG, &pdev->dev, + "No sig fis\n"); ++ phy->phy_type &= ~(PORT_TYPE_SATA); ++ goto out_done; + } + } ++ tmp64 = cpu_to_be64(phy->att_dev_sas_addr); ++ memcpy(sas_phy->attached_sas_addr, &tmp64, SAS_ADDR_SIZE); ++ ++ dev_printk(KERN_DEBUG, &pdev->dev, ++ "phy[%d] Get Attached Address 0x%llX ," ++ " SAS Address 0x%llX\n", ++ i, phy->att_dev_sas_addr, phy->dev_sas_addr); ++ dev_printk(KERN_DEBUG, &pdev->dev, ++ "Rate = %x , type = %d\n", ++ sas_phy->linkrate, phy->phy_type); ++ + /* workaround for HW phy decoding error on 1.5g disk drive */ + mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE6); + tmp = mvs_read_port_vsr_data(mvi, i); + if (((phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >> + PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET) == + SAS_LINK_RATE_1_5_GBPS) +- tmp &= ~PHY_MODE6_DTL_SPEED; ++ tmp &= ~PHY_MODE6_LATECLK; + else +- tmp |= PHY_MODE6_DTL_SPEED; ++ tmp |= PHY_MODE6_LATECLK; + mvs_write_port_vsr_data(mvi, i, tmp); + + } ++out_done: + if (get_st) + mvs_write_port_irq_stat(mvi, i, phy->irq_status); + } +@@ -2629,6 +2864,11 @@ static void mvs_port_formed(struct asd_sas_phy *sas_phy) + spin_unlock_irqrestore(&mvi->lock, flags); + } + ++static int mvs_I_T_nexus_reset(struct domain_device *dev) ++{ ++ return TMF_RESP_FUNC_FAILED; ++} ++ + static int __devinit mvs_hw_init(struct mvs_info *mvi) + { + void __iomem *regs = mvi->regs; +@@ -2790,13 +3030,12 @@ static int __devinit mvs_hw_init(struct mvs_info *mvi) + /* enable CMD/CMPL_Q/RESP mode */ + mw32(PCS, PCS_SATA_RETRY | PCS_FIS_RX_EN | PCS_CMD_EN); + +- /* re-enable interrupts globally */ +- mvs_hba_interrupt_enable(mvi); +- + /* enable completion queue interrupt */ +- tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM); ++ tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS); + mw32(INT_MASK, tmp); + ++ /* Enable SRS interrupt */ ++ mw32(INT_MASK_SRS, 0xFF); + return 0; + } + +@@ -2870,6 +3109,8 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev, + + mvs_print_info(mvi); + ++ mvs_hba_interrupt_enable(mvi); ++ + scsi_scan_host(mvi->shost); + + return 0; +@@ -2915,12 +3156,22 @@ static struct sas_domain_function_template mvs_transport_ops = { + .lldd_execute_task = mvs_task_exec, + .lldd_control_phy = mvs_phy_control, + .lldd_abort_task = mvs_task_abort, +- .lldd_port_formed = mvs_port_formed ++ .lldd_port_formed = mvs_port_formed, ++ .lldd_I_T_nexus_reset = mvs_I_T_nexus_reset, + }; + + static struct pci_device_id __devinitdata mvs_pci_table[] = { + { PCI_VDEVICE(MARVELL, 0x6320), chip_6320 }, + { PCI_VDEVICE(MARVELL, 0x6340), chip_6440 }, ++ { ++ .vendor = PCI_VENDOR_ID_MARVELL, ++ .device = 0x6440, ++ .subvendor = PCI_ANY_ID, ++ .subdevice = 0x6480, ++ .class = 0, ++ .class_mask = 0, ++ .driver_data = chip_6480, ++ }, + { PCI_VDEVICE(MARVELL, 0x6440), chip_6440 }, + { PCI_VDEVICE(MARVELL, 0x6480), chip_6480 }, + +diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c +index b9b09a7..ed83cdb 100644 +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -294,7 +294,6 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) + } + + if (sdev->request_queue) { +- bsg_unregister_queue(sdev->request_queue); + sdev->request_queue->queuedata = NULL; + /* user context needed to free queue */ + scsi_free_queue(sdev->request_queue); +@@ -858,6 +857,7 @@ void __scsi_remove_device(struct scsi_device *sdev) + if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0) + return; + ++ bsg_unregister_queue(sdev->request_queue); + class_device_unregister(&sdev->sdev_classdev); + transport_remove_device(dev); + device_del(dev); +diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c +index d57bf3e..430997e 100644 +--- a/drivers/serial/atmel_serial.c ++++ b/drivers/serial/atmel_serial.c +@@ -96,6 +96,7 @@ + + /* PDC registers */ + #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) ++#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR) + #define UART_GET_PTSR(port) __raw_readl((port)->membase + ATMEL_PDC_PTSR) + + #define UART_PUT_RPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RPR) +@@ -106,6 +107,7 @@ + + #define UART_PUT_TPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TPR) + #define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR) ++#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR) + + static int (*atmel_open_hook)(struct uart_port *); + static void (*atmel_close_hook)(struct uart_port *); +@@ -562,17 +564,22 @@ static void atmel_tx_dma(struct uart_port *port) + struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; + int count; + ++ /* nothing left to transmit? */ ++ if (UART_GET_TCR(port)) ++ return; ++ + xmit->tail += pdc->ofs; + xmit->tail &= UART_XMIT_SIZE - 1; + + port->icount.tx += pdc->ofs; + pdc->ofs = 0; + +- if (!uart_circ_empty(xmit)) { +- /* more to transmit - setup next transfer */ ++ /* more to transmit - setup next transfer */ + +- /* disable PDC transmit */ +- UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); ++ /* disable PDC transmit */ ++ UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); ++ ++ if (!uart_circ_empty(xmit)) { + dma_sync_single_for_device(port->dev, + pdc->dma_addr, + pdc->dma_size, +@@ -586,11 +593,6 @@ static void atmel_tx_dma(struct uart_port *port) + /* re-enable PDC transmit and interrupts */ + UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); + UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); +- } else { +- /* nothing left to transmit - disable the transmitter */ +- +- /* disable PDC transmit */ +- UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) +@@ -1274,6 +1276,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) + { + struct uart_port *port = &atmel_ports[co->index].uart; + unsigned int status, imr; ++ unsigned int pdc_tx; + + /* + * First, save IMR and then disable interrupts +@@ -1281,6 +1284,10 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) + imr = UART_GET_IMR(port); + UART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY); + ++ /* Store PDC transmit status and disable it */ ++ pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN; ++ UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); ++ + uart_console_write(port, s, count, atmel_console_putchar); + + /* +@@ -1290,6 +1297,11 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) + do { + status = UART_GET_CSR(port); + } while (!(status & ATMEL_US_TXRDY)); ++ ++ /* Restore PDC transmit status */ ++ if (pdc_tx) ++ UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); ++ + /* set interrupts back the way they were */ + UART_PUT_IER(port, imr); + } +diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c +index 40e8240..4e065e5 100644 +--- a/drivers/usb/host/ehci-hub.c ++++ b/drivers/usb/host/ehci-hub.c +@@ -135,8 +135,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) + hcd->state = HC_STATE_QUIESCING; + } + ehci->command = ehci_readl(ehci, &ehci->regs->command); +- if (ehci->reclaim) +- end_unlink_async(ehci); + ehci_work(ehci); + + /* Unlike other USB host controller types, EHCI doesn't have +@@ -180,6 +178,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) + ehci_halt (ehci); + hcd->state = HC_STATE_SUSPENDED; + ++ if (ehci->reclaim) ++ end_unlink_async(ehci); ++ + /* allow remote wakeup */ + mask = INTR_MASK; + if (!device_may_wakeup(&hcd->self.root_hub->dev)) +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index dd4798e..33f1c1c 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -467,7 +467,7 @@ static void unlink_watchdog_func(unsigned long _ohci) + out: + kfree(seen); + if (ohci->eds_scheduled) +- mod_timer(&ohci->unlink_watchdog, round_jiffies_relative(HZ)); ++ mod_timer(&ohci->unlink_watchdog, round_jiffies(jiffies + HZ)); + done: + spin_unlock_irqrestore(&ohci->lock, flags); + } +diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c +index 5181732..9c9f3b5 100644 +--- a/drivers/usb/host/ohci-q.c ++++ b/drivers/usb/host/ohci-q.c +@@ -169,7 +169,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) + if (quirk_zfmicro(ohci) + && (ed->type == PIPE_INTERRUPT) + && !(ohci->eds_scheduled++)) +- mod_timer(&ohci->unlink_watchdog, round_jiffies_relative(HZ)); ++ mod_timer(&ohci->unlink_watchdog, round_jiffies(jiffies + HZ)); + wmb (); + + /* we care about rm_list when setting CLE/BLE in case the HC was at +diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c +index da922df..b6b5b2a 100644 +--- a/drivers/usb/misc/usbtest.c ++++ b/drivers/usb/misc/usbtest.c +@@ -378,6 +378,7 @@ alloc_sglist (int nents, int max, int vary) + sg = kmalloc (nents * sizeof *sg, GFP_KERNEL); + if (!sg) + return NULL; ++ sg_init_table(sg, nents); + + for (i = 0; i < nents; i++) { + char *buf; +@@ -390,7 +391,7 @@ alloc_sglist (int nents, int max, int vary) + } + + /* kmalloc pages are always physically contiguous! */ +- sg_init_one(&sg[i], buf, size); ++ sg_set_buf(&sg[i], buf, size); + + switch (pattern) { + case 0: +diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c +index f3ca660..324bb61 100644 +--- a/drivers/usb/serial/cp2101.c ++++ b/drivers/usb/serial/cp2101.c +@@ -75,6 +75,7 @@ static struct usb_device_id id_table [] = { + { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ + { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ + { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ ++ { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ +diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h +index 8a0d174..74ce8bc 100644 +--- a/drivers/usb/serial/keyspan.h ++++ b/drivers/usb/serial/keyspan.h +@@ -637,6 +637,7 @@ static struct usb_serial_driver keyspan_pre_device = { + .description = "Keyspan - (without firmware)", + .id_table = keyspan_pre_ids, + .num_interrupt_in = NUM_DONT_CARE, ++ .num_interrupt_out = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, +@@ -651,6 +652,7 @@ static struct usb_serial_driver keyspan_1port_device = { + .description = "Keyspan 1 port adapter", + .id_table = keyspan_1port_ids, + .num_interrupt_in = NUM_DONT_CARE, ++ .num_interrupt_out = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, +@@ -678,6 +680,7 @@ static struct usb_serial_driver keyspan_2port_device = { + .description = "Keyspan 2 port adapter", + .id_table = keyspan_2port_ids, + .num_interrupt_in = NUM_DONT_CARE, ++ .num_interrupt_out = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 2, +@@ -705,6 +708,7 @@ static struct usb_serial_driver keyspan_4port_device = { + .description = "Keyspan 4 port adapter", + .id_table = keyspan_4port_ids, + .num_interrupt_in = NUM_DONT_CARE, ++ .num_interrupt_out = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 4, +diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c +index b517f93..e3d241f 100644 +--- a/drivers/usb/serial/ti_usb_3410_5052.c ++++ b/drivers/usb/serial/ti_usb_3410_5052.c +@@ -265,8 +265,8 @@ static struct usb_serial_driver ti_1port_device = { + .description = "TI USB 3410 1 port adapter", + .usb_driver = &ti_usb_driver, + .id_table = ti_id_table_3410, +- .num_interrupt_in = 1, +- .num_bulk_in = 1, ++ .num_interrupt_in = NUM_DONT_CARE, ++ .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = 1, + .num_ports = 1, + .attach = ti_startup, +diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c +index 22b3f78..c2b01f7 100644 +--- a/drivers/usb/serial/visor.c ++++ b/drivers/usb/serial/visor.c +@@ -191,7 +191,7 @@ static struct usb_serial_driver handspring_device = { + .id_table = id_table, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = 2, +- .num_bulk_out = 2, ++ .num_bulk_out = NUM_DONT_CARE, + .num_ports = 2, + .open = visor_open, + .close = visor_close, +diff --git a/fs/afs/cell.c b/fs/afs/cell.c +index 788865d..584bb0f 100644 +--- a/fs/afs/cell.c ++++ b/fs/afs/cell.c +@@ -138,6 +138,7 @@ struct afs_cell *afs_cell_create(const char *name, char *vllist) + cell = afs_cell_alloc(name, vllist); + if (IS_ERR(cell)) { + _leave(" = %ld", PTR_ERR(cell)); ++ up_write(&afs_cells_sem); + return cell; + } + +diff --git a/fs/efs/inode.c b/fs/efs/inode.c +index 79e19e5..a8e7797 100644 +--- a/fs/efs/inode.c ++++ b/fs/efs/inode.c +@@ -140,7 +140,7 @@ struct inode *efs_iget(struct super_block *super, unsigned long ino) + brelse(bh); + + #ifdef DEBUG +- printk(KERN_DEBUG "EFS: read_inode(): inode %lu, extents %d, mode %o\n", ++ printk(KERN_DEBUG "EFS: efs_iget(): inode %lu, extents %d, mode %o\n", + inode->i_ino, in->numextents, inode->i_mode); + #endif + +diff --git a/include/asm-alpha/current.h b/include/asm-alpha/current.h +index 8d88a13..094d285 100644 +--- a/include/asm-alpha/current.h ++++ b/include/asm-alpha/current.h +@@ -3,7 +3,7 @@ + + #include + +-#define get_current() (current_thread_info()->task + 0) ++#define get_current() (current_thread_info()->task) + #define current get_current() + + #endif /* _ALPHA_CURRENT_H */ +diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h +index 75a1aff..db351d1 100644 +--- a/include/asm-alpha/dma-mapping.h ++++ b/include/asm-alpha/dma-mapping.h +@@ -11,7 +11,7 @@ + #define dma_unmap_single(dev, addr, size, dir) \ + pci_unmap_single(alpha_gendev_to_pci(dev), addr, size, dir) + #define dma_alloc_coherent(dev, size, addr, gfp) \ +- pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr) ++ __pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr, gfp) + #define dma_free_coherent(dev, size, va, addr) \ + pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr) + #define dma_map_page(dev, page, off, size, dir) \ +diff --git a/include/asm-alpha/kvm.h b/include/asm-alpha/kvm.h +new file mode 100644 +index 0000000..b9daec4 +--- /dev/null ++++ b/include/asm-alpha/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_ALPHA_H ++#define __LINUX_KVM_ALPHA_H ++ ++/* alpha does not support KVM */ ++ ++#endif +diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h +index d5b10ef..d31fd49 100644 +--- a/include/asm-alpha/pci.h ++++ b/include/asm-alpha/pci.h +@@ -76,7 +76,13 @@ extern inline void pcibios_penalize_isa_irq(int irq, int active) + successful and sets *DMA_ADDRP to the pci side dma address as well, + else DMA_ADDRP is undefined. */ + +-extern void *pci_alloc_consistent(struct pci_dev *, size_t, dma_addr_t *); ++extern void *__pci_alloc_consistent(struct pci_dev *, size_t, ++ dma_addr_t *, gfp_t); ++static inline void * ++pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma) ++{ ++ return __pci_alloc_consistent(dev, size, dma, GFP_ATOMIC); ++} + + /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must + be values that were returned from pci_alloc_consistent. SIZE must +diff --git a/include/asm-arm/kvm.h b/include/asm-arm/kvm.h +new file mode 100644 +index 0000000..cb3c08c +--- /dev/null ++++ b/include/asm-arm/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_ARM_H ++#define __LINUX_KVM_ARM_H ++ ++/* arm does not support KVM */ ++ ++#endif +diff --git a/include/asm-avr32/kvm.h b/include/asm-avr32/kvm.h +new file mode 100644 +index 0000000..8c57770 +--- /dev/null ++++ b/include/asm-avr32/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_AVR32_H ++#define __LINUX_KVM_AVR32_H ++ ++/* avr32 does not support KVM */ ++ ++#endif +diff --git a/include/asm-blackfin/kvm.h b/include/asm-blackfin/kvm.h +new file mode 100644 +index 0000000..e3477d7 +--- /dev/null ++++ b/include/asm-blackfin/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_BLACKFIN_H ++#define __LINUX_KVM_BLACKFIN_H ++ ++/* blackfin does not support KVM */ ++ ++#endif +diff --git a/include/asm-cris/kvm.h b/include/asm-cris/kvm.h +new file mode 100644 +index 0000000..c860f51 +--- /dev/null ++++ b/include/asm-cris/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_CRIS_H ++#define __LINUX_KVM_CRIS_H ++ ++/* cris does not support KVM */ ++ ++#endif +diff --git a/include/asm-frv/kvm.h b/include/asm-frv/kvm.h +new file mode 100644 +index 0000000..9c8a4f0 +--- /dev/null ++++ b/include/asm-frv/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_FRV_H ++#define __LINUX_KVM_FRV_H ++ ++/* frv does not support KVM */ ++ ++#endif +diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm +index fd9dcfd..92a6d91 100644 +--- a/include/asm-generic/Kbuild.asm ++++ b/include/asm-generic/Kbuild.asm +@@ -1,3 +1,5 @@ ++header-y += kvm.h ++ + ifeq ($(wildcard include/asm-$(SRCARCH)/a.out.h),include/asm-$(SRCARCH)/a.out.h) + unifdef-y += a.out.h + endif +diff --git a/include/asm-h8300/kvm.h b/include/asm-h8300/kvm.h +new file mode 100644 +index 0000000..bdbed7b +--- /dev/null ++++ b/include/asm-h8300/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_H8300_H ++#define __LINUX_KVM_H8300_H ++ ++/* h8300 does not support KVM */ ++ ++#endif +diff --git a/include/asm-ia64/kvm.h b/include/asm-ia64/kvm.h +new file mode 100644 +index 0000000..030d29b +--- /dev/null ++++ b/include/asm-ia64/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_IA64_H ++#define __LINUX_KVM_IA64_H ++ ++/* ia64 does not support KVM */ ++ ++#endif +diff --git a/include/asm-m32r/kvm.h b/include/asm-m32r/kvm.h +new file mode 100644 +index 0000000..99a4051 +--- /dev/null ++++ b/include/asm-m32r/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_M32R_H ++#define __LINUX_KVM_M32R_H ++ ++/* m32r does not support KVM */ ++ ++#endif +diff --git a/include/asm-m68k/kvm.h b/include/asm-m68k/kvm.h +new file mode 100644 +index 0000000..7ed27fc +--- /dev/null ++++ b/include/asm-m68k/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_M68K_H ++#define __LINUX_KVM_M68K_H ++ ++/* m68k does not support KVM */ ++ ++#endif +diff --git a/include/asm-m68knommu/kvm.h b/include/asm-m68knommu/kvm.h +new file mode 100644 +index 0000000..b49d425 +--- /dev/null ++++ b/include/asm-m68knommu/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_M68KNOMMU_H ++#define __LINUX_KVM_M68KNOMMU_H ++ ++/* m68knommu does not support KVM */ ++ ++#endif +diff --git a/include/asm-mips/kvm.h b/include/asm-mips/kvm.h +new file mode 100644 +index 0000000..093a5b7 +--- /dev/null ++++ b/include/asm-mips/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_MIPS_H ++#define __LINUX_KVM_MIPS_H ++ ++/* mips does not support KVM */ ++ ++#endif +diff --git a/include/asm-mn10300/kvm.h b/include/asm-mn10300/kvm.h +new file mode 100644 +index 0000000..f6b609f +--- /dev/null ++++ b/include/asm-mn10300/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_MN10300_H ++#define __LINUX_KVM_MN10300_H ++ ++/* mn10300 does not support KVM */ ++ ++#endif +diff --git a/include/asm-parisc/kvm.h b/include/asm-parisc/kvm.h +new file mode 100644 +index 0000000..00cc458 +--- /dev/null ++++ b/include/asm-parisc/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_PARISC_H ++#define __LINUX_KVM_PARISC_H ++ ++/* parisc does not support KVM */ ++ ++#endif +diff --git a/include/asm-powerpc/kvm.h b/include/asm-powerpc/kvm.h +new file mode 100644 +index 0000000..d1b530f +--- /dev/null ++++ b/include/asm-powerpc/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_POWERPC_H ++#define __LINUX_KVM_POWERPC_H ++ ++/* powerpc does not support KVM */ ++ ++#endif +diff --git a/include/asm-s390/kvm.h b/include/asm-s390/kvm.h +new file mode 100644 +index 0000000..573f2a3 +--- /dev/null ++++ b/include/asm-s390/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_S390_H ++#define __LINUX_KVM_S390_H ++ ++/* s390 does not support KVM */ ++ ++#endif +diff --git a/include/asm-sh/kvm.h b/include/asm-sh/kvm.h +new file mode 100644 +index 0000000..6af51db +--- /dev/null ++++ b/include/asm-sh/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_SH_H ++#define __LINUX_KVM_SH_H ++ ++/* sh does not support KVM */ ++ ++#endif +diff --git a/include/asm-sparc/kvm.h b/include/asm-sparc/kvm.h +new file mode 100644 +index 0000000..2e5478d +--- /dev/null ++++ b/include/asm-sparc/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_SPARC_H ++#define __LINUX_KVM_SPARC_H ++ ++/* sparc does not support KVM */ ++ ++#endif +diff --git a/include/asm-sparc64/kvm.h b/include/asm-sparc64/kvm.h +new file mode 100644 +index 0000000..380537a +--- /dev/null ++++ b/include/asm-sparc64/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_SPARC64_H ++#define __LINUX_KVM_SPARC64_H ++ ++/* sparc64 does not support KVM */ ++ ++#endif +diff --git a/include/asm-um/kvm.h b/include/asm-um/kvm.h +new file mode 100644 +index 0000000..66aa770 +--- /dev/null ++++ b/include/asm-um/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_UM_H ++#define __LINUX_KVM_UM_H ++ ++/* um does not support KVM */ ++ ++#endif +diff --git a/include/asm-v850/kvm.h b/include/asm-v850/kvm.h +new file mode 100644 +index 0000000..3f729b7 +--- /dev/null ++++ b/include/asm-v850/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_V850_H ++#define __LINUX_KVM_V850_H ++ ++/* v850 does not support KVM */ ++ ++#endif +diff --git a/include/asm-xtensa/kvm.h b/include/asm-xtensa/kvm.h +new file mode 100644 +index 0000000..bda4e33 +--- /dev/null ++++ b/include/asm-xtensa/kvm.h +@@ -0,0 +1,6 @@ ++#ifndef __LINUX_KVM_XTENSA_H ++#define __LINUX_KVM_XTENSA_H ++ ++/* xtensa does not support KVM */ ++ ++#endif +diff --git a/include/linux/Kbuild b/include/linux/Kbuild +index 4a446a1..9cdd12a 100644 +--- a/include/linux/Kbuild ++++ b/include/linux/Kbuild +@@ -253,7 +253,7 @@ unifdef-y += kd.h + unifdef-y += kernelcapi.h + unifdef-y += kernel.h + unifdef-y += keyboard.h +-unifdef-$(CONFIG_HAVE_KVM) += kvm.h ++unifdef-y += kvm.h + unifdef-y += llc.h + unifdef-y += loop.h + unifdef-y += lp.h +diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h +index 1b4ccf2..cac4b36 100644 +--- a/include/linux/iocontext.h ++++ b/include/linux/iocontext.h +@@ -2,6 +2,7 @@ + #define IOCONTEXT_H + + #include ++#include + + /* + * This is the per-process anticipatory I/O scheduler state. +@@ -54,6 +55,8 @@ struct cfq_io_context { + + void (*dtor)(struct io_context *); /* destructor */ + void (*exit)(struct io_context *); /* called on task exit */ ++ ++ struct rcu_head rcu_head; + }; + + /* +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index a2f0032..ee81906 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -383,9 +383,11 @@ static inline void __napi_complete(struct napi_struct *n) + + static inline void napi_complete(struct napi_struct *n) + { +- local_irq_disable(); ++ unsigned long flags; ++ ++ local_irq_save(flags); + __napi_complete(n); +- local_irq_enable(); ++ local_irq_restore(flags); + } + + /** +@@ -1072,12 +1074,14 @@ static inline int netif_is_multiqueue(const struct net_device *dev) + } + + /* Use this variant when it is known for sure that it +- * is executing from interrupt context. ++ * is executing from hardware interrupt context or with hardware interrupts ++ * disabled. + */ + extern void dev_kfree_skb_irq(struct sk_buff *skb); + + /* Use this variant in places where it could be invoked +- * either from interrupt or non-interrupt context. ++ * from either hardware interrupt or other context, with hardware interrupts ++ * either disabled or enabled. + */ + extern void dev_kfree_skb_any(struct sk_buff *skb); + +diff --git a/include/net/llc.h b/include/net/llc.h +index f502458..7940da1 100644 +--- a/include/net/llc.h ++++ b/include/net/llc.h +@@ -65,7 +65,6 @@ struct llc_sap { + + extern struct list_head llc_sap_list; + extern rwlock_t llc_sap_list_lock; +-extern unsigned char llc_station_mac_sa[ETH_ALEN]; + + extern int llc_rcv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, struct net_device *orig_dev); +diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h +index 4a8f58b..75b8e29 100644 +--- a/include/net/llc_pdu.h ++++ b/include/net/llc_pdu.h +@@ -381,7 +381,7 @@ static inline void llc_pdu_init_as_xid_cmd(struct sk_buff *skb, + xid_info->fmt_id = LLC_XID_FMT_ID; /* 0x81 */ + xid_info->type = svcs_supported; + xid_info->rw = rx_window << 1; /* size of receive window */ +- skb_put(skb, 3); ++ skb_put(skb, sizeof(struct llc_xid_info)); + } + + /** +@@ -406,7 +406,7 @@ static inline void llc_pdu_init_as_xid_rsp(struct sk_buff *skb, + xid_info->fmt_id = LLC_XID_FMT_ID; + xid_info->type = svcs_supported; + xid_info->rw = rx_window << 1; +- skb_put(skb, 3); ++ skb_put(skb, sizeof(struct llc_xid_info)); + } + + /* LLC Type 2 FRMR response information field format */ +diff --git a/include/net/llc_sap.h b/include/net/llc_sap.h +index 2c56dbe..ed25bec 100644 +--- a/include/net/llc_sap.h ++++ b/include/net/llc_sap.h +@@ -1,5 +1,8 @@ + #ifndef LLC_SAP_H + #define LLC_SAP_H ++ ++#include ++ + /* + * Copyright (c) 1997 by Procom Technology,Inc. + * 2001-2003 by Arnaldo Carvalho de Melo +@@ -19,8 +22,8 @@ struct sock; + extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); + extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb, + unsigned char prim); +-extern struct sk_buff *llc_alloc_frame(struct sock *sk, +- struct net_device *dev); ++extern struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev, ++ u8 type, u32 data_size); + + extern void llc_build_and_send_test_pkt(struct llc_sap *sap, + struct sk_buff *skb, +diff --git a/kernel/marker.c b/kernel/marker.c +index 041c33e..005b959 100644 +--- a/kernel/marker.c ++++ b/kernel/marker.c +@@ -671,6 +671,9 @@ int marker_probe_register(const char *name, const char *format, + entry->rcu_pending = 1; + /* write rcu_pending before calling the RCU callback */ + smp_wmb(); ++#ifdef CONFIG_PREEMPT_RCU ++ synchronize_sched(); /* Until we have the call_rcu_sched() */ ++#endif + call_rcu(&entry->rcu, free_old_closure); + end: + mutex_unlock(&markers_mutex); +@@ -714,6 +717,9 @@ int marker_probe_unregister(const char *name, + entry->rcu_pending = 1; + /* write rcu_pending before calling the RCU callback */ + smp_wmb(); ++#ifdef CONFIG_PREEMPT_RCU ++ synchronize_sched(); /* Until we have the call_rcu_sched() */ ++#endif + call_rcu(&entry->rcu, free_old_closure); + remove_marker(name); /* Ignore busy error message */ + ret = 0; +@@ -792,6 +798,9 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, + entry->rcu_pending = 1; + /* write rcu_pending before calling the RCU callback */ + smp_wmb(); ++#ifdef CONFIG_PREEMPT_RCU ++ synchronize_sched(); /* Until we have the call_rcu_sched() */ ++#endif + call_rcu(&entry->rcu, free_old_closure); + remove_marker(entry->name); /* Ignore busy error message */ + end: +diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c +index dbc81b9..b33410a 100644 +--- a/net/8021q/vlan.c ++++ b/net/8021q/vlan.c +@@ -374,17 +374,35 @@ static void vlan_sync_address(struct net_device *dev, + memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN); + } + ++static void __vlan_device_event(struct net_device *dev, unsigned long event) ++{ ++ switch (event) { ++ case NETDEV_CHANGENAME: ++ vlan_proc_rem_dev(dev); ++ if (vlan_proc_add_dev(dev) < 0) ++ pr_warning("8021q: failed to change proc name for %s\n", ++ dev->name); ++ break; ++ } ++} ++ + static int vlan_device_event(struct notifier_block *unused, unsigned long event, + void *ptr) + { + struct net_device *dev = ptr; +- struct vlan_group *grp = __vlan_find_group(dev->ifindex); ++ struct vlan_group *grp; + int i, flgs; + struct net_device *vlandev; + + if (dev->nd_net != &init_net) + return NOTIFY_DONE; + ++ if (is_vlan_dev(dev)) { ++ __vlan_device_event(dev, event); ++ goto out; ++ } ++ ++ grp = __vlan_find_group(dev->ifindex); + if (!grp) + goto out; + +diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h +index 73efcc7..51271ae 100644 +--- a/net/8021q/vlan.h ++++ b/net/8021q/vlan.h +@@ -45,4 +45,9 @@ void vlan_netlink_fini(void); + + extern struct rtnl_link_ops vlan_link_ops; + ++static inline int is_vlan_dev(struct net_device *dev) ++{ ++ return dev->priv_flags & IFF_802_1Q_VLAN; ++} ++ + #endif /* !(__BEN_VLAN_802_1Q_INC__) */ +diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c +index 146cfb0..9671aa5 100644 +--- a/net/8021q/vlanproc.c ++++ b/net/8021q/vlanproc.c +@@ -210,11 +210,6 @@ int vlan_proc_rem_dev(struct net_device *vlandev) + * The following few functions build the content of /proc/net/vlan/config + */ + +-static inline int is_vlan_dev(struct net_device *dev) +-{ +- return dev->priv_flags & IFF_802_1Q_VLAN; +-} +- + /* start read of /proc/net/vlan/config */ + static void *vlan_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(dev_base_lock) +diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c +index 1220d8a..d366423 100644 +--- a/net/bluetooth/af_bluetooth.c ++++ b/net/bluetooth/af_bluetooth.c +@@ -53,6 +53,30 @@ + /* Bluetooth sockets */ + #define BT_MAX_PROTO 8 + static struct net_proto_family *bt_proto[BT_MAX_PROTO]; ++ ++static struct lock_class_key bt_slock_key[BT_MAX_PROTO]; ++static struct lock_class_key bt_lock_key[BT_MAX_PROTO]; ++static const char *bt_key_strings[BT_MAX_PROTO] = { ++ "sk_lock-AF_BLUETOOTH-BTPROTO_L2CAP", ++ "sk_lock-AF_BLUETOOTH-BTPROTO_HCI", ++ "sk_lock-AF_BLUETOOTH-BTPROTO_SCO", ++ "sk_lock-AF_BLUETOOTH-BTPROTO_RFCOMM", ++ "sk_lock-AF_BLUETOOTH-BTPROTO_BNEP", ++ "sk_lock-AF_BLUETOOTH-BTPROTO_CMTP", ++ "sk_lock-AF_BLUETOOTH-BTPROTO_HIDP", ++ "sk_lock-AF_BLUETOOTH-BTPROTO_AVDTP", ++}; ++ ++static const char *bt_slock_key_strings[BT_MAX_PROTO] = { ++ "slock-AF_BLUETOOTH-BTPROTO_L2CAP", ++ "slock-AF_BLUETOOTH-BTPROTO_HCI", ++ "slock-AF_BLUETOOTH-BTPROTO_SCO", ++ "slock-AF_BLUETOOTH-BTPROTO_RFCOMM", ++ "slock-AF_BLUETOOTH-BTPROTO_BNEP", ++ "slock-AF_BLUETOOTH-BTPROTO_CMTP", ++ "slock-AF_BLUETOOTH-BTPROTO_HIDP", ++ "slock-AF_BLUETOOTH-BTPROTO_AVDTP", ++}; + static DEFINE_RWLOCK(bt_proto_lock); + + int bt_sock_register(int proto, struct net_proto_family *ops) +@@ -95,6 +119,21 @@ int bt_sock_unregister(int proto) + } + EXPORT_SYMBOL(bt_sock_unregister); + ++static void bt_reclassify_sock_lock(struct socket *sock, int proto) ++{ ++ struct sock *sk = sock->sk; ++ ++ if (!sk) ++ return; ++ BUG_ON(sock_owned_by_user(sk)); ++ ++ sock_lock_init_class_and_name(sk, ++ bt_slock_key_strings[proto], ++ &bt_slock_key[proto], ++ bt_key_strings[proto], ++ &bt_lock_key[proto]); ++} ++ + static int bt_sock_create(struct net *net, struct socket *sock, int proto) + { + int err; +@@ -117,6 +156,7 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto) + + if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { + err = bt_proto[proto]->create(net, sock, proto); ++ bt_reclassify_sock_lock(sock, proto); + module_put(bt_proto[proto]->owner); + } + +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index b5d4019..1d36c09 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -84,7 +84,7 @@ static struct hci_sec_filter hci_sec_filter = { + }; + + static struct bt_sock_list hci_sk_list = { +- .lock = RW_LOCK_UNLOCKED ++ .lock = __RW_LOCK_UNLOCKED(hci_sk_list.lock) + }; + + /* Send frame to RAW socket */ +diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c +index 34f8bf9..2957df4 100644 +--- a/net/bluetooth/l2cap.c ++++ b/net/bluetooth/l2cap.c +@@ -62,7 +62,7 @@ static u32 l2cap_feat_mask = 0x0000; + static const struct proto_ops l2cap_sock_ops; + + static struct bt_sock_list l2cap_sk_list = { +- .lock = RW_LOCK_UNLOCKED ++ .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) + }; + + static void __l2cap_sock_close(struct sock *sk, int reason); +diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c +index 0c2c937..eb62558 100644 +--- a/net/bluetooth/rfcomm/core.c ++++ b/net/bluetooth/rfcomm/core.c +@@ -423,8 +423,8 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) + + rfcomm_dlc_lock(d); + d->state = BT_CLOSED; +- d->state_change(d, err); + rfcomm_dlc_unlock(d); ++ d->state_change(d, err); + + skb_queue_purge(&d->tx_queue); + rfcomm_dlc_unlink(d); +diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c +index c46d510..af4e393 100644 +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -60,7 +60,7 @@ + static const struct proto_ops rfcomm_sock_ops; + + static struct bt_sock_list rfcomm_sk_list = { +- .lock = RW_LOCK_UNLOCKED ++ .lock = __RW_LOCK_UNLOCKED(rfcomm_sk_list.lock) + }; + + static void rfcomm_sock_close(struct sock *sk); +diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c +index e4c779b..c3f749a 100644 +--- a/net/bluetooth/rfcomm/tty.c ++++ b/net/bluetooth/rfcomm/tty.c +@@ -570,12 +570,7 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) + return; + + rfcomm_dev_del(dev); +- /* We have to drop DLC lock here, otherwise +- rfcomm_dev_put() will dead lock if it's +- the last reference. */ +- rfcomm_dlc_unlock(dlc); + rfcomm_dev_put(dev); +- rfcomm_dlc_lock(dlc); + } + } else + tty_hangup(dev->tty); +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index b91d3c8..cd887cd 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -58,7 +58,7 @@ + static const struct proto_ops sco_sock_ops; + + static struct bt_sock_list sco_sk_list = { +- .lock = RW_LOCK_UNLOCKED ++ .lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock) + }; + + static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); +diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c +index f3ceca3..4e73e57 100644 +--- a/net/ipv4/esp4.c ++++ b/net/ipv4/esp4.c +@@ -336,7 +336,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) + struct scatterlist *asg; + int err = -EINVAL; + +- if (!pskb_may_pull(skb, sizeof(*esph))) ++ if (!pskb_may_pull(skb, sizeof(*esph) + crypto_aead_ivsize(aead))) + goto out; + + if (elen <= 0) +diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c +index 724d69a..a0a3c78 100644 +--- a/net/ipv4/inet_fragment.c ++++ b/net/ipv4/inet_fragment.c +@@ -86,7 +86,10 @@ EXPORT_SYMBOL(inet_frags_fini); + void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f) + { + nf->low_thresh = 0; ++ ++ local_bh_disable(); + inet_frag_evictor(nf, f); ++ local_bh_enable(); + } + EXPORT_SYMBOL(inet_frags_exit_net); + +diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c +index 0b3b328..a4506c8 100644 +--- a/net/ipv4/ip_forward.c ++++ b/net/ipv4/ip_forward.c +@@ -85,7 +85,7 @@ int ip_forward(struct sk_buff *skb) + if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway) + goto sr_failed; + +- if (unlikely(skb->len > dst_mtu(&rt->u.dst) && ++ if (unlikely(skb->len > dst_mtu(&rt->u.dst) && !skb_is_gso(skb) && + (ip_hdr(skb)->frag_off & htons(IP_DF))) && !skb->local_df) { + IP_INC_STATS(IPSTATS_MIB_FRAGFAILS); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, +diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c +index fe05da4..4dc1628 100644 +--- a/net/ipv4/netfilter/ip_queue.c ++++ b/net/ipv4/netfilter/ip_queue.c +@@ -588,11 +588,9 @@ static int __init ip_queue_init(void) + } + + #ifdef CONFIG_PROC_FS +- proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net); +- if (proc) { +- proc->owner = THIS_MODULE; +- proc->proc_fops = &ip_queue_proc_fops; +- } else { ++ proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net, ++ &ip_queue_proc_fops); ++ if (!proc) { + printk(KERN_ERR "ip_queue: failed to create proc entry\n"); + goto cleanup_ipqnl; + } +diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c +index c6cf84c..52926c8 100644 +--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c ++++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c +@@ -167,14 +167,13 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip, + + /* create proc dir entry */ + sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip)); +- c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR, +- clusterip_procdir); ++ c->pde = proc_create(buffer, S_IWUSR|S_IRUSR, ++ clusterip_procdir, &clusterip_proc_fops); + if (!c->pde) { + kfree(c); + return NULL; + } + } +- c->pde->proc_fops = &clusterip_proc_fops; + c->pde->data = c; + #endif + +diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c +index 8e8f042..50e0669 100644 +--- a/net/ipv4/netfilter/ipt_recent.c ++++ b/net/ipv4/netfilter/ipt_recent.c +@@ -276,12 +276,11 @@ recent_mt_check(const char *tablename, const void *ip, + for (i = 0; i < ip_list_hash_size; i++) + INIT_LIST_HEAD(&t->iphash[i]); + #ifdef CONFIG_PROC_FS +- t->proc = create_proc_entry(t->name, ip_list_perms, proc_dir); ++ t->proc = proc_create(t->name, ip_list_perms, proc_dir, &recent_fops); + if (t->proc == NULL) { + kfree(t); + goto out; + } +- t->proc->proc_fops = &recent_fops; + t->proc->uid = ip_list_uid; + t->proc->gid = ip_list_gid; + t->proc->data = t; +diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +index 089252e..f500b0f 100644 +--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c ++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +@@ -395,13 +395,10 @@ int __init nf_conntrack_ipv4_compat_init(void) + if (!proc_exp) + goto err2; + +- proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, init_net.proc_net_stat); ++ proc_stat = proc_create("ip_conntrack", S_IRUGO, ++ init_net.proc_net_stat, &ct_cpu_seq_fops); + if (!proc_stat) + goto err3; +- +- proc_stat->proc_fops = &ct_cpu_seq_fops; +- proc_stat->owner = THIS_MODULE; +- + return 0; + + err3: +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 7ea1b67..1704c14 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1556,14 +1556,14 @@ static void *udp_seq_start(struct seq_file *seq, loff_t *pos) + __acquires(udp_hash_lock) + { + read_lock(&udp_hash_lock); +- return *pos ? udp_get_idx(seq, *pos-1) : (void *)1; ++ return *pos ? udp_get_idx(seq, *pos-1) : SEQ_START_TOKEN; + } + + static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos) + { + struct sock *sk; + +- if (v == (void *)1) ++ if (v == SEQ_START_TOKEN) + sk = udp_get_idx(seq, 0); + else + sk = udp_get_next(seq, v); +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 101e0e7..e7a1882 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -776,6 +776,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i + struct inet6_dev *idev = ifp->idev; + struct in6_addr addr, *tmpaddr; + unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp; ++ unsigned long regen_advance; + int tmp_plen; + int ret = 0; + int max_addresses; +@@ -836,8 +837,23 @@ retry: + tmp_tstamp = ifp->tstamp; + spin_unlock_bh(&ifp->lock); + ++ regen_advance = idev->cnf.regen_max_retry * ++ idev->cnf.dad_transmits * ++ idev->nd_parms->retrans_time / HZ; + write_unlock(&idev->lock); + ++ /* A temporary address is created only if this calculated Preferred ++ * Lifetime is greater than REGEN_ADVANCE time units. In particular, ++ * an implementation must not create a temporary address with a zero ++ * Preferred Lifetime. ++ */ ++ if (tmp_prefered_lft <= regen_advance) { ++ in6_ifa_put(ifp); ++ in6_dev_put(idev); ++ ret = -1; ++ goto out; ++ } ++ + addr_flags = IFA_F_TEMPORARY; + /* set in addrconf_prefix_rcv() */ + if (ifp->flags & IFA_F_OPTIMISTIC) +@@ -1831,6 +1847,9 @@ ok: + * lifetimes of an existing temporary address + * when processing a Prefix Information Option. + */ ++ if (ifp != ift->ifpub) ++ continue; ++ + spin_lock(&ift->lock); + flags = ift->flags; + if (ift->valid_lft > valid_lft && +diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c +index 0ec1402..c6bb4c6 100644 +--- a/net/ipv6/esp6.c ++++ b/net/ipv6/esp6.c +@@ -282,7 +282,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) + struct scatterlist *sg; + struct scatterlist *asg; + +- if (!pskb_may_pull(skb, sizeof(*esph))) { ++ if (!pskb_may_pull(skb, sizeof(*esph) + crypto_aead_ivsize(aead))) { + ret = -EINVAL; + goto out; + } +diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c +index 121d517..f204a72 100644 +--- a/net/ipv6/icmp.c ++++ b/net/ipv6/icmp.c +@@ -436,10 +436,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, + } + + if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) +- goto out; ++ goto out_dst_release; + + if (ip6_dst_lookup(sk, &dst2, &fl)) +- goto out; ++ goto out_dst_release; + + err = xfrm_lookup(&dst2, &fl, sk, XFRM_LOOKUP_ICMP); + if (err == -ENOENT) { +diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c +index 178aebc..98ab4f4 100644 +--- a/net/ipv6/ip6_input.c ++++ b/net/ipv6/ip6_input.c +@@ -239,8 +239,7 @@ int ip6_mc_input(struct sk_buff *skb) + IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); + + hdr = ipv6_hdr(skb); +- deliver = unlikely(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) || +- ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); ++ deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); + + /* + * IPv6 multicast router mode isnt currently supported. +diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c +index cc2f9af..8d366f7 100644 +--- a/net/ipv6/netfilter/ip6_queue.c ++++ b/net/ipv6/netfilter/ip6_queue.c +@@ -591,11 +591,9 @@ static int __init ip6_queue_init(void) + } + + #ifdef CONFIG_PROC_FS +- proc = create_proc_entry(IPQ_PROC_FS_NAME, 0, init_net.proc_net); +- if (proc) { +- proc->owner = THIS_MODULE; +- proc->proc_fops = &ip6_queue_proc_fops; +- } else { ++ proc = proc_create(IPQ_PROC_FS_NAME, 0, init_net.proc_net, ++ &ip6_queue_proc_fops); ++ if (!proc) { + printk(KERN_ERR "ip6_queue: failed to create proc entry\n"); + goto cleanup_ipqnl; + } +diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c +index 2a0d698..24c0d03 100644 +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -171,7 +171,9 @@ static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq) + + static void nf_ct_frag6_evictor(void) + { ++ local_bh_disable(); + inet_frag_evictor(&nf_init_frags, &nf_frags); ++ local_bh_enable(); + } + + static void nf_ct_frag6_expire(unsigned long data) +diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c +index 46cf962..8c50eb4 100644 +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -155,6 +155,9 @@ static int llc_ui_create(struct net *net, struct socket *sock, int protocol) + struct sock *sk; + int rc = -ESOCKTNOSUPPORT; + ++ if (!capable(CAP_NET_RAW)) ++ return -EPERM; ++ + if (net != &init_net) + return -EAFNOSUPPORT; + +diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c +index 860140c..71a0022 100644 +--- a/net/llc/llc_c_ac.c ++++ b/net/llc/llc_c_ac.c +@@ -198,7 +198,7 @@ int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -223,7 +223,7 @@ int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -249,7 +249,7 @@ int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -282,7 +282,8 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb) + llc_pdu_decode_pf_bit(skb, &f_bit); + else + f_bit = 0; +- nskb = llc_alloc_frame(sk, llc->dev); ++ nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, ++ sizeof(struct llc_frmr_info)); + if (nskb) { + struct llc_sap *sap = llc->sap; + +@@ -306,7 +307,8 @@ int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, ++ sizeof(struct llc_frmr_info)); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -336,7 +338,8 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) + struct llc_sock *llc = llc_sk(sk); + + llc_pdu_decode_pf_bit(skb, &f_bit); +- nskb = llc_alloc_frame(sk, llc->dev); ++ nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, ++ sizeof(struct llc_frmr_info)); + if (nskb) { + struct llc_sap *sap = llc->sap; + struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); +@@ -424,7 +427,7 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, + struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -459,7 +462,7 @@ int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -483,7 +486,7 @@ int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -507,7 +510,7 @@ int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -531,7 +534,7 @@ int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -555,7 +558,7 @@ int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -579,7 +582,7 @@ int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -615,7 +618,7 @@ int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -639,7 +642,7 @@ int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -663,7 +666,7 @@ int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -688,7 +691,7 @@ int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -712,7 +715,7 @@ int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -736,7 +739,7 @@ int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -770,7 +773,7 @@ int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb) + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +@@ -799,7 +802,7 @@ int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb) + u8 f_bit; + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_U, 0); + + llc_pdu_decode_pf_bit(skb, &f_bit); + if (nskb) { +@@ -956,7 +959,7 @@ static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk, + { + int rc = -ENOBUFS; + struct llc_sock *llc = llc_sk(sk); +- struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); ++ struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev, LLC_PDU_TYPE_S, 0); + + if (nskb) { + struct llc_sap *sap = llc->sap; +diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c +index 248b590..50d5b10 100644 +--- a/net/llc/llc_core.c ++++ b/net/llc/llc_core.c +@@ -25,8 +25,6 @@ + LIST_HEAD(llc_sap_list); + DEFINE_RWLOCK(llc_sap_list_lock); + +-unsigned char llc_station_mac_sa[ETH_ALEN]; +- + /** + * llc_sap_alloc - allocates and initializes sap. + * +@@ -37,8 +35,8 @@ static struct llc_sap *llc_sap_alloc(void) + struct llc_sap *sap = kzalloc(sizeof(*sap), GFP_ATOMIC); + + if (sap) { ++ /* sap->laddr.mac - leave as a null, it's filled by bind */ + sap->state = LLC_SAP_STATE_ACTIVE; +- memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); + rwlock_init(&sap->sk_list.lock); + atomic_set(&sap->refcnt, 1); + } +@@ -167,10 +165,6 @@ static int __init llc_init(void) + if (dev != NULL) + dev = next_net_device(dev); + +- if (dev != NULL) +- memcpy(llc_station_mac_sa, dev->dev_addr, ETH_ALEN); +- else +- memset(llc_station_mac_sa, 0, ETH_ALEN); + dev_add_pack(&llc_packet_type); + dev_add_pack(&llc_tr_packet_type); + return 0; +@@ -185,7 +179,6 @@ static void __exit llc_exit(void) + module_init(llc_init); + module_exit(llc_exit); + +-EXPORT_SYMBOL(llc_station_mac_sa); + EXPORT_SYMBOL(llc_sap_list); + EXPORT_SYMBOL(llc_sap_list_lock); + EXPORT_SYMBOL(llc_sap_find); +diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c +index c40c9b2..bfd2567 100644 +--- a/net/llc/llc_input.c ++++ b/net/llc/llc_input.c +@@ -117,8 +117,12 @@ static inline int llc_fixup_skb(struct sk_buff *skb) + skb_pull(skb, llc_len); + if (skb->protocol == htons(ETH_P_802_2)) { + __be16 pdulen = eth_hdr(skb)->h_proto; +- u16 data_size = ntohs(pdulen) - llc_len; ++ s32 data_size = ntohs(pdulen) - llc_len; + ++ if (data_size < 0 || ++ ((skb_tail_pointer(skb) - ++ (u8 *)pdu) - llc_len) < data_size) ++ return 0; + if (unlikely(pskb_trim_rcsum(skb, data_size))) + return 0; + } +diff --git a/net/llc/llc_pdu.c b/net/llc/llc_pdu.c +index fa83243..2e6cb79 100644 +--- a/net/llc/llc_pdu.c ++++ b/net/llc/llc_pdu.c +@@ -241,7 +241,7 @@ void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu, + FRMR_INFO_SET_PDU_INFO_2LONG_IND(frmr_info, vzyxw); + FRMR_INFO_SET_PDU_INVALID_Nr_IND(frmr_info, vzyxw); + FRMR_INFO_SET_PDU_INVALID_Ns_IND(frmr_info, vzyxw); +- skb_put(skb, 5); ++ skb_put(skb, sizeof(struct llc_frmr_info)); + } + + /** +diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c +index ac3d93b..a94bd56 100644 +--- a/net/llc/llc_s_ac.c ++++ b/net/llc/llc_s_ac.c +@@ -103,7 +103,8 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) + llc_pdu_decode_sa(skb, mac_da); + llc_pdu_decode_da(skb, mac_sa); + llc_pdu_decode_ssap(skb, &dsap); +- nskb = llc_alloc_frame(NULL, skb->dev); ++ nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, ++ sizeof(struct llc_xid_info)); + if (!nskb) + goto out; + llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, +@@ -144,11 +145,15 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) + u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap; + struct sk_buff *nskb; + int rc = 1; ++ u32 data_size; + + llc_pdu_decode_sa(skb, mac_da); + llc_pdu_decode_da(skb, mac_sa); + llc_pdu_decode_ssap(skb, &dsap); +- nskb = llc_alloc_frame(NULL, skb->dev); ++ ++ /* The test request command is type U (llc_len = 3) */ ++ data_size = ntohs(eth_hdr(skb)->h_proto) - 3; ++ nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size); + if (!nskb) + goto out; + llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, +diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c +index 2525165..e2ddde7 100644 +--- a/net/llc/llc_sap.c ++++ b/net/llc/llc_sap.c +@@ -24,20 +24,41 @@ + #include + #include + ++static int llc_mac_header_len(unsigned short devtype) ++{ ++ switch (devtype) { ++ case ARPHRD_ETHER: ++ case ARPHRD_LOOPBACK: ++ return sizeof(struct ethhdr); ++#ifdef CONFIG_TR ++ case ARPHRD_IEEE802_TR: ++ return sizeof(struct trh_hdr); ++#endif ++ } ++ return 0; ++} ++ + /** + * llc_alloc_frame - allocates sk_buff for frame + * @dev: network device this skb will be sent over ++ * @type: pdu type to allocate ++ * @data_size: data size to allocate + * + * Allocates an sk_buff for frame and initializes sk_buff fields. + * Returns allocated skb or %NULL when out of memory. + */ +-struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev) ++struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev, ++ u8 type, u32 data_size) + { +- struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); ++ int hlen = type == LLC_PDU_TYPE_U ? 3 : 4; ++ struct sk_buff *skb; ++ ++ hlen += llc_mac_header_len(dev->type); ++ skb = alloc_skb(hlen + data_size, GFP_ATOMIC); + + if (skb) { + skb_reset_mac_header(skb); +- skb_reserve(skb, 50); ++ skb_reserve(skb, hlen); + skb_reset_network_header(skb); + skb_reset_transport_header(skb); + skb->protocol = htons(ETH_P_802_2); +diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c +index 6f2ea20..83da133 100644 +--- a/net/llc/llc_station.c ++++ b/net/llc/llc_station.c +@@ -253,13 +253,14 @@ static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb) + static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) + { + int rc = 1; +- struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); ++ struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, ++ sizeof(struct llc_xid_info)); + + if (!nskb) + goto out; + llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD); + llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127); +- rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, llc_station_mac_sa); ++ rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, skb->dev->dev_addr); + if (unlikely(rc)) + goto free; + llc_station_send_pdu(nskb); +@@ -274,7 +275,8 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) + { + u8 mac_da[ETH_ALEN], dsap; + int rc = 1; +- struct sk_buff* nskb = llc_alloc_frame(NULL, skb->dev); ++ struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, ++ sizeof(struct llc_xid_info)); + + if (!nskb) + goto out; +@@ -283,7 +285,7 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) + llc_pdu_decode_ssap(skb, &dsap); + llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); + llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127); +- rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); ++ rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da); + if (unlikely(rc)) + goto free; + llc_station_send_pdu(nskb); +@@ -298,7 +300,12 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) + { + u8 mac_da[ETH_ALEN], dsap; + int rc = 1; +- struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); ++ u32 data_size; ++ struct sk_buff *nskb; ++ ++ /* The test request command is type U (llc_len = 3) */ ++ data_size = ntohs(eth_hdr(skb)->h_proto) - 3; ++ nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size); + + if (!nskb) + goto out; +@@ -307,7 +314,7 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) + llc_pdu_decode_ssap(skb, &dsap); + llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); + llc_pdu_init_as_test_rsp(nskb, skb); +- rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da); ++ rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da); + if (unlikely(rc)) + goto free; + llc_station_send_pdu(nskb); +diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c +index 28bcdf9..8e58639 100644 +--- a/net/mac80211/ieee80211.c ++++ b/net/mac80211/ieee80211.c +@@ -286,6 +286,18 @@ static int ieee80211_open(struct net_device *dev) + if (need_hw_reconfig) + ieee80211_hw_config(local); + ++ /* ++ * ieee80211_sta_work is disabled while network interface ++ * is down. Therefore, some configuration changes may not ++ * yet be effective. Trigger execution of ieee80211_sta_work ++ * to fix this. ++ */ ++ if(sdata->vif.type == IEEE80211_IF_TYPE_STA || ++ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { ++ struct ieee80211_if_sta *ifsta = &sdata->u.sta; ++ queue_work(local->hw.workqueue, &ifsta->work); ++ } ++ + netif_start_queue(dev); + + return 0; +diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c +index 9aeed53..e0c72d0 100644 +--- a/net/mac80211/ieee80211_sta.c ++++ b/net/mac80211/ieee80211_sta.c +@@ -319,7 +319,7 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, + struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; +- bool preamble_mode = (erp_value & WLAN_ERP_BARKER_PREAMBLE) != 0; ++ bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; + DECLARE_MAC_BUF(mac); + u32 changed = 0; + +@@ -335,16 +335,15 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, + changed |= BSS_CHANGED_ERP_CTS_PROT; + } + +- if (preamble_mode != bss_conf->use_short_preamble) { ++ if (use_short_preamble != bss_conf->use_short_preamble) { + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: switched to %s barker preamble" + " (BSSID=%s)\n", + sdata->dev->name, +- (preamble_mode == WLAN_ERP_PREAMBLE_SHORT) ? +- "short" : "long", ++ use_short_preamble ? "short" : "long", + print_mac(mac, ifsta->bssid)); + } +- bss_conf->use_short_preamble = preamble_mode; ++ bss_conf->use_short_preamble = use_short_preamble; + changed |= BSS_CHANGED_ERP_PREAMBLE; + } + +diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c +index e88e96a..8599068 100644 +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -395,7 +395,7 @@ EXPORT_SYMBOL_GPL(nf_ct_log_invalid); + static int __init nf_conntrack_standalone_init(void) + { + #ifdef CONFIG_PROC_FS +- struct proc_dir_entry *proc, *proc_stat; ++ struct proc_dir_entry *proc; + #endif + int ret = 0; + +@@ -407,12 +407,9 @@ static int __init nf_conntrack_standalone_init(void) + proc = proc_net_fops_create(&init_net, "nf_conntrack", 0440, &ct_file_ops); + if (!proc) goto cleanup_init; + +- proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, init_net.proc_net_stat); +- if (!proc_stat) ++ if (!proc_create("nf_conntrack", S_IRUGO, ++ init_net.proc_net_stat, &ct_cpu_seq_fops)) + goto cleanup_proc; +- +- proc_stat->proc_fops = &ct_cpu_seq_fops; +- proc_stat->owner = THIS_MODULE; + #endif + #ifdef CONFIG_SYSCTL + nf_ct_sysctl_header = register_sysctl_paths(nf_ct_path, +diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c +index cec9976..bc11d70 100644 +--- a/net/netfilter/nf_log.c ++++ b/net/netfilter/nf_log.c +@@ -168,13 +168,9 @@ static const struct file_operations nflog_file_ops = { + int __init netfilter_log_init(void) + { + #ifdef CONFIG_PROC_FS +- struct proc_dir_entry *pde; +- +- pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter); +- if (!pde) ++ if (!proc_create("nf_log", S_IRUGO, ++ proc_net_netfilter, &nflog_file_ops)) + return -1; +- +- pde->proc_fops = &nflog_file_ops; + #endif + return 0; + } +diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c +index ddc80ea..bbd2689 100644 +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -348,12 +348,9 @@ static const struct file_operations nfqueue_file_ops = { + int __init netfilter_queue_init(void) + { + #ifdef CONFIG_PROC_FS +- struct proc_dir_entry *pde; +- +- pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter); +- if (!pde) ++ if (!proc_create("nf_queue", S_IRUGO, ++ proc_net_netfilter, &nfqueue_file_ops)) + return -1; +- pde->proc_fops = &nfqueue_file_ops; + #endif + return 0; + } +diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c +index bf3f19b..b8173af 100644 +--- a/net/netfilter/nfnetlink_log.c ++++ b/net/netfilter/nfnetlink_log.c +@@ -923,9 +923,6 @@ static const struct file_operations nful_file_ops = { + static int __init nfnetlink_log_init(void) + { + int i, status = -ENOMEM; +-#ifdef CONFIG_PROC_FS +- struct proc_dir_entry *proc_nful; +-#endif + + for (i = 0; i < INSTANCE_BUCKETS; i++) + INIT_HLIST_HEAD(&instance_table[i]); +@@ -943,11 +940,9 @@ static int __init nfnetlink_log_init(void) + } + + #ifdef CONFIG_PROC_FS +- proc_nful = create_proc_entry("nfnetlink_log", 0440, +- proc_net_netfilter); +- if (!proc_nful) ++ if (!proc_create("nfnetlink_log", 0440, ++ proc_net_netfilter, &nful_file_ops)) + goto cleanup_subsys; +- proc_nful->proc_fops = &nful_file_ops; + #endif + return status; + +diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c +index 012cb69..10522c0 100644 +--- a/net/netfilter/nfnetlink_queue.c ++++ b/net/netfilter/nfnetlink_queue.c +@@ -896,9 +896,6 @@ static const struct file_operations nfqnl_file_ops = { + static int __init nfnetlink_queue_init(void) + { + int i, status = -ENOMEM; +-#ifdef CONFIG_PROC_FS +- struct proc_dir_entry *proc_nfqueue; +-#endif + + for (i = 0; i < INSTANCE_BUCKETS; i++) + INIT_HLIST_HEAD(&instance_table[i]); +@@ -911,11 +908,9 @@ static int __init nfnetlink_queue_init(void) + } + + #ifdef CONFIG_PROC_FS +- proc_nfqueue = create_proc_entry("nfnetlink_queue", 0440, +- proc_net_netfilter); +- if (!proc_nfqueue) ++ if (!proc_create("nfnetlink_queue", 0440, ++ proc_net_netfilter, &nfqnl_file_ops)) + goto cleanup_subsys; +- proc_nfqueue->proc_fops = &nfqnl_file_ops; + #endif + + register_netdevice_notifier(&nfqnl_dev_notifier); +diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c +index 5418ce5..dc29007 100644 +--- a/net/netfilter/xt_hashlimit.c ++++ b/net/netfilter/xt_hashlimit.c +@@ -237,14 +237,14 @@ static int htable_create_v0(struct xt_hashlimit_info *minfo, int family) + hinfo->family = family; + hinfo->rnd_initialized = 0; + spin_lock_init(&hinfo->lock); +- hinfo->pde = create_proc_entry(minfo->name, 0, +- family == AF_INET ? hashlimit_procdir4 : +- hashlimit_procdir6); ++ hinfo->pde = proc_create(minfo->name, 0, ++ family == AF_INET ? hashlimit_procdir4 : ++ hashlimit_procdir6, ++ &dl_file_ops); + if (!hinfo->pde) { + vfree(hinfo); + return -1; + } +- hinfo->pde->proc_fops = &dl_file_ops; + hinfo->pde->data = hinfo; + + setup_timer(&hinfo->timer, htable_gc, (unsigned long )hinfo); +@@ -301,14 +301,14 @@ static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, + hinfo->rnd_initialized = 0; + spin_lock_init(&hinfo->lock); + +- hinfo->pde = create_proc_entry(minfo->name, 0, +- family == AF_INET ? hashlimit_procdir4 : +- hashlimit_procdir6); ++ hinfo->pde = proc_create(minfo->name, 0, ++ family == AF_INET ? hashlimit_procdir4 : ++ hashlimit_procdir6, ++ &dl_file_ops); + if (hinfo->pde == NULL) { + vfree(hinfo); + return -1; + } +- hinfo->pde->proc_fops = &dl_file_ops; + hinfo->pde->data = hinfo; + + setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo); +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index 4a31a81..063cbc5 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -598,17 +598,24 @@ static int rose_release(struct socket *sock) + + if (sk == NULL) return 0; + ++ sock_hold(sk); ++ sock_orphan(sk); ++ lock_sock(sk); + rose = rose_sk(sk); + + switch (rose->state) { + case ROSE_STATE_0: ++ release_sock(sk); + rose_disconnect(sk, 0, -1, -1); ++ lock_sock(sk); + rose_destroy_socket(sk); + break; + + case ROSE_STATE_2: + rose->neighbour->use--; ++ release_sock(sk); + rose_disconnect(sk, 0, -1, -1); ++ lock_sock(sk); + rose_destroy_socket(sk); + break; + +@@ -633,6 +640,8 @@ static int rose_release(struct socket *sock) + } + + sock->sk = NULL; ++ release_sock(sk); ++ sock_put(sk); + + return 0; + } +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 10b5c08..b741618 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -184,10 +184,22 @@ static inline int qdisc_restart(struct net_device *dev) + + void __qdisc_run(struct net_device *dev) + { +- do { +- if (!qdisc_restart(dev)) ++ unsigned long start_time = jiffies; ++ ++ while (qdisc_restart(dev)) { ++ if (netif_queue_stopped(dev)) ++ break; ++ ++ /* ++ * Postpone processing if ++ * 1. another process needs the CPU; ++ * 2. we've been doing it for too long. ++ */ ++ if (need_resched() || jiffies != start_time) { ++ netif_schedule(dev); + break; +- } while (!netif_queue_stopped(dev)); ++ } ++ } + + clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state); + } +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index 41a049f..c2fef7b 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -1630,6 +1630,12 @@ static inline u32 file_to_av(struct file *file) + else + av |= FILE__WRITE; + } ++ if (!av) { ++ /* ++ * Special file opened with flags 3 for ioctl-only use. ++ */ ++ av = FILE__IOCTL; ++ } + + return av; + } diff --git a/debian/patches/series/1~experimental.1 b/debian/patches/series/1~experimental.1 index 96e1ff033..92fb68a24 100644 --- a/debian/patches/series/1~experimental.1 +++ b/debian/patches/series/1~experimental.1 @@ -1,3 +1,4 @@ ++ bugfix/all/patch-2.6.25-rc8-git2 + debian/version.patch + debian/kernelvariables.patch + debian/doc-build-parallel.patch