diff --git a/[refs] b/[refs] index 8a0c12023c53..e667d03047bc 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7f95e1880e70bb351b992b01ef70ff083fc00d30 +refs/heads/master: 3a8fc53a45c444400259e2e285ba414a87061e3d diff --git a/trunk/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt b/trunk/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt deleted file mode 100644 index ae8af1694e95..000000000000 --- a/trunk/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt +++ /dev/null @@ -1,93 +0,0 @@ -Pinctrl-based I2C Bus Mux - -This binding describes an I2C bus multiplexer that uses pin multiplexing to -route the I2C signals, and represents the pin multiplexing configuration -using the pinctrl device tree bindings. - - +-----+ +-----+ - | dev | | dev | - +------------------------+ +-----+ +-----+ - | SoC | | | - | /----|------+--------+ - | +---+ +------+ | child bus A, on first set of pins - | |I2C|---|Pinmux| | - | +---+ +------+ | child bus B, on second set of pins - | \----|------+--------+--------+ - | | | | | - +------------------------+ +-----+ +-----+ +-----+ - | dev | | dev | | dev | - +-----+ +-----+ +-----+ - -Required properties: -- compatible: i2c-mux-pinctrl -- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side - port is connected to. - -Also required are: - -* Standard pinctrl properties that specify the pin mux state for each child - bus. See ../pinctrl/pinctrl-bindings.txt. - -* Standard I2C mux properties. See mux.txt in this directory. - -* I2C child bus nodes. See mux.txt in this directory. - -For each named state defined in the pinctrl-names property, an I2C child bus -will be created. I2C child bus numbers are assigned based on the index into -the pinctrl-names property. - -The only exception is that no bus will be created for a state named "idle". If -such a state is defined, it must be the last entry in pinctrl-names. For -example: - - pinctrl-names = "ddc", "pta", "idle" -> ddc = bus 0, pta = bus 1 - pinctrl-names = "ddc", "idle", "pta" -> Invalid ("idle" not last) - pinctrl-names = "idle", "ddc", "pta" -> Invalid ("idle" not last) - -Whenever an access is made to a device on a child bus, the relevant pinctrl -state will be programmed into hardware. - -If an idle state is defined, whenever an access is not being made to a device -on a child bus, the idle pinctrl state will be programmed into hardware. - -If an idle state is not defined, the most recently used pinctrl state will be -left programmed into hardware whenever no access is being made of a device on -a child bus. - -Example: - - i2cmux { - compatible = "i2c-mux-pinctrl"; - #address-cells = <1>; - #size-cells = <0>; - - i2c-parent = <&i2c1>; - - pinctrl-names = "ddc", "pta", "idle"; - pinctrl-0 = <&state_i2cmux_ddc>; - pinctrl-1 = <&state_i2cmux_pta>; - pinctrl-2 = <&state_i2cmux_idle>; - - i2c@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - - eeprom { - compatible = "eeprom"; - reg = <0x50>; - }; - }; - - i2c@1 { - reg = <1>; - #address-cells = <1>; - #size-cells = <0>; - - eeprom { - compatible = "eeprom"; - reg = <0x50>; - }; - }; - }; - diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index a92c5ebf373e..c45513d806ab 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -2543,15 +2543,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. sched_debug [KNL] Enables verbose scheduler debug messages. - skew_tick= [KNL] Offset the periodic timer tick per cpu to mitigate - xtime_lock contention on larger systems, and/or RCU lock - contention on all systems with CONFIG_MAXSMP set. - Format: { "0" | "1" } - 0 -- disable. (may be 1 via CONFIG_CMDLINE="skew_tick=1" - 1 -- enable. - Note: increases power consumption, thus should only be - enabled if running jitter sensitive (HPC/RT) workloads. - security= [SECURITY] Choose a security module to enable at boot. If this boot parameter is not specified, only the first security module asking for security registration will be diff --git a/trunk/Documentation/vm/frontswap.txt b/trunk/Documentation/vm/frontswap.txt deleted file mode 100644 index 37067cf455f4..000000000000 --- a/trunk/Documentation/vm/frontswap.txt +++ /dev/null @@ -1,278 +0,0 @@ -Frontswap provides a "transcendent memory" interface for swap pages. -In some environments, dramatic performance savings may be obtained because -swapped pages are saved in RAM (or a RAM-like device) instead of a swap disk. - -(Note, frontswap -- and cleancache (merged at 3.0) -- are the "frontends" -and the only necessary changes to the core kernel for transcendent memory; -all other supporting code -- the "backends" -- is implemented as drivers. -See the LWN.net article "Transcendent memory in a nutshell" for a detailed -overview of frontswap and related kernel parts: -https://lwn.net/Articles/454795/ ) - -Frontswap is so named because it can be thought of as the opposite of -a "backing" store for a swap device. The storage is assumed to be -a synchronous concurrency-safe page-oriented "pseudo-RAM device" conforming -to the requirements of transcendent memory (such as Xen's "tmem", or -in-kernel compressed memory, aka "zcache", or future RAM-like devices); -this pseudo-RAM device is not directly accessible or addressable by the -kernel and is of unknown and possibly time-varying size. The driver -links itself to frontswap by calling frontswap_register_ops to set the -frontswap_ops funcs appropriately and the functions it provides must -conform to certain policies as follows: - -An "init" prepares the device to receive frontswap pages associated -with the specified swap device number (aka "type"). A "store" will -copy the page to transcendent memory and associate it with the type and -offset associated with the page. A "load" will copy the page, if found, -from transcendent memory into kernel memory, but will NOT remove the page -from from transcendent memory. An "invalidate_page" will remove the page -from transcendent memory and an "invalidate_area" will remove ALL pages -associated with the swap type (e.g., like swapoff) and notify the "device" -to refuse further stores with that swap type. - -Once a page is successfully stored, a matching load on the page will normally -succeed. So when the kernel finds itself in a situation where it needs -to swap out a page, it first attempts to use frontswap. If the store returns -success, the data has been successfully saved to transcendent memory and -a disk write and, if the data is later read back, a disk read are avoided. -If a store returns failure, transcendent memory has rejected the data, and the -page can be written to swap as usual. - -If a backend chooses, frontswap can be configured as a "writethrough -cache" by calling frontswap_writethrough(). In this mode, the reduction -in swap device writes is lost (and also a non-trivial performance advantage) -in order to allow the backend to arbitrarily "reclaim" space used to -store frontswap pages to more completely manage its memory usage. - -Note that if a page is stored and the page already exists in transcendent memory -(a "duplicate" store), either the store succeeds and the data is overwritten, -or the store fails AND the page is invalidated. This ensures stale data may -never be obtained from frontswap. - -If properly configured, monitoring of frontswap is done via debugfs in -the /sys/kernel/debug/frontswap directory. The effectiveness of -frontswap can be measured (across all swap devices) with: - -failed_stores - how many store attempts have failed -loads - how many loads were attempted (all should succeed) -succ_stores - how many store attempts have succeeded -invalidates - how many invalidates were attempted - -A backend implementation may provide additional metrics. - -FAQ - -1) Where's the value? - -When a workload starts swapping, performance falls through the floor. -Frontswap significantly increases performance in many such workloads by -providing a clean, dynamic interface to read and write swap pages to -"transcendent memory" that is otherwise not directly addressable to the kernel. -This interface is ideal when data is transformed to a different form -and size (such as with compression) or secretly moved (as might be -useful for write-balancing for some RAM-like devices). Swap pages (and -evicted page-cache pages) are a great use for this kind of slower-than-RAM- -but-much-faster-than-disk "pseudo-RAM device" and the frontswap (and -cleancache) interface to transcendent memory provides a nice way to read -and write -- and indirectly "name" -- the pages. - -Frontswap -- and cleancache -- with a fairly small impact on the kernel, -provides a huge amount of flexibility for more dynamic, flexible RAM -utilization in various system configurations: - -In the single kernel case, aka "zcache", pages are compressed and -stored in local memory, thus increasing the total anonymous pages -that can be safely kept in RAM. Zcache essentially trades off CPU -cycles used in compression/decompression for better memory utilization. -Benchmarks have shown little or no impact when memory pressure is -low while providing a significant performance improvement (25%+) -on some workloads under high memory pressure. - -"RAMster" builds on zcache by adding "peer-to-peer" transcendent memory -support for clustered systems. Frontswap pages are locally compressed -as in zcache, but then "remotified" to another system's RAM. This -allows RAM to be dynamically load-balanced back-and-forth as needed, -i.e. when system A is overcommitted, it can swap to system B, and -vice versa. RAMster can also be configured as a memory server so -many servers in a cluster can swap, dynamically as needed, to a single -server configured with a large amount of RAM... without pre-configuring -how much of the RAM is available for each of the clients! - -In the virtual case, the whole point of virtualization is to statistically -multiplex physical resources acrosst the varying demands of multiple -virtual machines. This is really hard to do with RAM and efforts to do -it well with no kernel changes have essentially failed (except in some -well-publicized special-case workloads). -Specifically, the Xen Transcendent Memory backend allows otherwise -"fallow" hypervisor-owned RAM to not only be "time-shared" between multiple -virtual machines, but the pages can be compressed and deduplicated to -optimize RAM utilization. And when guest OS's are induced to surrender -underutilized RAM (e.g. with "selfballooning"), sudden unexpected -memory pressure may result in swapping; frontswap allows those pages -to be swapped to and from hypervisor RAM (if overall host system memory -conditions allow), thus mitigating the potentially awful performance impact -of unplanned swapping. - -A KVM implementation is underway and has been RFC'ed to lkml. And, -using frontswap, investigation is also underway on the use of NVM as -a memory extension technology. - -2) Sure there may be performance advantages in some situations, but - what's the space/time overhead of frontswap? - -If CONFIG_FRONTSWAP is disabled, every frontswap hook compiles into -nothingness and the only overhead is a few extra bytes per swapon'ed -swap device. If CONFIG_FRONTSWAP is enabled but no frontswap "backend" -registers, there is one extra global variable compared to zero for -every swap page read or written. If CONFIG_FRONTSWAP is enabled -AND a frontswap backend registers AND the backend fails every "store" -request (i.e. provides no memory despite claiming it might), -CPU overhead is still negligible -- and since every frontswap fail -precedes a swap page write-to-disk, the system is highly likely -to be I/O bound and using a small fraction of a percent of a CPU -will be irrelevant anyway. - -As for space, if CONFIG_FRONTSWAP is enabled AND a frontswap backend -registers, one bit is allocated for every swap page for every swap -device that is swapon'd. This is added to the EIGHT bits (which -was sixteen until about 2.6.34) that the kernel already allocates -for every swap page for every swap device that is swapon'd. (Hugh -Dickins has observed that frontswap could probably steal one of -the existing eight bits, but let's worry about that minor optimization -later.) For very large swap disks (which are rare) on a standard -4K pagesize, this is 1MB per 32GB swap. - -When swap pages are stored in transcendent memory instead of written -out to disk, there is a side effect that this may create more memory -pressure that can potentially outweigh the other advantages. A -backend, such as zcache, must implement policies to carefully (but -dynamically) manage memory limits to ensure this doesn't happen. - -3) OK, how about a quick overview of what this frontswap patch does - in terms that a kernel hacker can grok? - -Let's assume that a frontswap "backend" has registered during -kernel initialization; this registration indicates that this -frontswap backend has access to some "memory" that is not directly -accessible by the kernel. Exactly how much memory it provides is -entirely dynamic and random. - -Whenever a swap-device is swapon'd frontswap_init() is called, -passing the swap device number (aka "type") as a parameter. -This notifies frontswap to expect attempts to "store" swap pages -associated with that number. - -Whenever the swap subsystem is readying a page to write to a swap -device (c.f swap_writepage()), frontswap_store is called. Frontswap -consults with the frontswap backend and if the backend says it does NOT -have room, frontswap_store returns -1 and the kernel swaps the page -to the swap device as normal. Note that the response from the frontswap -backend is unpredictable to the kernel; it may choose to never accept a -page, it could accept every ninth page, or it might accept every -page. But if the backend does accept a page, the data from the page -has already been copied and associated with the type and offset, -and the backend guarantees the persistence of the data. In this case, -frontswap sets a bit in the "frontswap_map" for the swap device -corresponding to the page offset on the swap device to which it would -otherwise have written the data. - -When the swap subsystem needs to swap-in a page (swap_readpage()), -it first calls frontswap_load() which checks the frontswap_map to -see if the page was earlier accepted by the frontswap backend. If -it was, the page of data is filled from the frontswap backend and -the swap-in is complete. If not, the normal swap-in code is -executed to obtain the page of data from the real swap device. - -So every time the frontswap backend accepts a page, a swap device read -and (potentially) a swap device write are replaced by a "frontswap backend -store" and (possibly) a "frontswap backend loads", which are presumably much -faster. - -4) Can't frontswap be configured as a "special" swap device that is - just higher priority than any real swap device (e.g. like zswap, - or maybe swap-over-nbd/NFS)? - -No. First, the existing swap subsystem doesn't allow for any kind of -swap hierarchy. Perhaps it could be rewritten to accomodate a hierarchy, -but this would require fairly drastic changes. Even if it were -rewritten, the existing swap subsystem uses the block I/O layer which -assumes a swap device is fixed size and any page in it is linearly -addressable. Frontswap barely touches the existing swap subsystem, -and works around the constraints of the block I/O subsystem to provide -a great deal of flexibility and dynamicity. - -For example, the acceptance of any swap page by the frontswap backend is -entirely unpredictable. This is critical to the definition of frontswap -backends because it grants completely dynamic discretion to the -backend. In zcache, one cannot know a priori how compressible a page is. -"Poorly" compressible pages can be rejected, and "poorly" can itself be -defined dynamically depending on current memory constraints. - -Further, frontswap is entirely synchronous whereas a real swap -device is, by definition, asynchronous and uses block I/O. The -block I/O layer is not only unnecessary, but may perform "optimizations" -that are inappropriate for a RAM-oriented device including delaying -the write of some pages for a significant amount of time. Synchrony is -required to ensure the dynamicity of the backend and to avoid thorny race -conditions that would unnecessarily and greatly complicate frontswap -and/or the block I/O subsystem. That said, only the initial "store" -and "load" operations need be synchronous. A separate asynchronous thread -is free to manipulate the pages stored by frontswap. For example, -the "remotification" thread in RAMster uses standard asynchronous -kernel sockets to move compressed frontswap pages to a remote machine. -Similarly, a KVM guest-side implementation could do in-guest compression -and use "batched" hypercalls. - -In a virtualized environment, the dynamicity allows the hypervisor -(or host OS) to do "intelligent overcommit". For example, it can -choose to accept pages only until host-swapping might be imminent, -then force guests to do their own swapping. - -There is a downside to the transcendent memory specifications for -frontswap: Since any "store" might fail, there must always be a real -slot on a real swap device to swap the page. Thus frontswap must be -implemented as a "shadow" to every swapon'd device with the potential -capability of holding every page that the swap device might have held -and the possibility that it might hold no pages at all. This means -that frontswap cannot contain more pages than the total of swapon'd -swap devices. For example, if NO swap device is configured on some -installation, frontswap is useless. Swapless portable devices -can still use frontswap but a backend for such devices must configure -some kind of "ghost" swap device and ensure that it is never used. - -5) Why this weird definition about "duplicate stores"? If a page - has been previously successfully stored, can't it always be - successfully overwritten? - -Nearly always it can, but no, sometimes it cannot. Consider an example -where data is compressed and the original 4K page has been compressed -to 1K. Now an attempt is made to overwrite the page with data that -is non-compressible and so would take the entire 4K. But the backend -has no more space. In this case, the store must be rejected. Whenever -frontswap rejects a store that would overwrite, it also must invalidate -the old data and ensure that it is no longer accessible. Since the -swap subsystem then writes the new data to the read swap device, -this is the correct course of action to ensure coherency. - -6) What is frontswap_shrink for? - -When the (non-frontswap) swap subsystem swaps out a page to a real -swap device, that page is only taking up low-value pre-allocated disk -space. But if frontswap has placed a page in transcendent memory, that -page may be taking up valuable real estate. The frontswap_shrink -routine allows code outside of the swap subsystem to force pages out -of the memory managed by frontswap and back into kernel-addressable memory. -For example, in RAMster, a "suction driver" thread will attempt -to "repatriate" pages sent to a remote machine back to the local machine; -this is driven using the frontswap_shrink mechanism when memory pressure -subsides. - -7) Why does the frontswap patch create the new include file swapfile.h? - -The frontswap code depends on some swap-subsystem-internal data -structures that have, over the years, moved back and forth between -static and global. This seemed a reasonable compromise: Define -them as global but declare them in a new include file that isn't -included by the large number of source files that include swap.h. - -Dan Magenheimer, last updated April 9, 2012 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index ae5a12a718cc..c5fd905206e7 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1077,7 +1077,7 @@ F: drivers/media/video/s5p-fimc/ ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT M: Kyungmin Park M: Kamil Debski -M: Jeongtae Park +M: Jeongtae Park L: linux-arm-kernel@lists.infradead.org L: linux-media@vger.kernel.org S: Maintained @@ -1743,10 +1743,10 @@ F: include/linux/can/platform/ CAPABILITIES M: Serge Hallyn L: linux-security-module@vger.kernel.org -S: Supported +S: Supported F: include/linux/capability.h F: security/capability.c -F: security/commoncap.c +F: security/commoncap.c F: kernel/capability.c CELL BROADBAND ENGINE ARCHITECTURE @@ -1800,9 +1800,6 @@ F: include/linux/cfag12864b.h CFG80211 and NL80211 M: Johannes Berg L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git S: Maintained F: include/linux/nl80211.h F: include/net/cfg80211.h @@ -2149,11 +2146,11 @@ S: Orphan F: drivers/net/wan/pc300* CYTTSP TOUCHSCREEN DRIVER -M: Javier Martinez Canillas -L: linux-input@vger.kernel.org -S: Maintained -F: drivers/input/touchscreen/cyttsp* -F: include/linux/input/cyttsp.h +M: Javier Martinez Canillas +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/input/touchscreen/cyttsp* +F: include/linux/input/cyttsp.h DAMA SLAVE for AX.25 M: Joerg Reuter @@ -2273,7 +2270,7 @@ F: include/linux/device-mapper.h F: include/linux/dm-*.h DIOLAN U2C-12 I2C DRIVER -M: Guenter Roeck +M: Guenter Roeck L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/busses/i2c-diolan-u2c.c @@ -2933,13 +2930,6 @@ F: Documentation/power/freezing-of-tasks.txt F: include/linux/freezer.h F: kernel/freezer.c -FRONTSWAP API -M: Konrad Rzeszutek Wilk -L: linux-kernel@vger.kernel.org -S: Maintained -F: mm/frontswap.c -F: include/linux/frontswap.h - FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS M: David Howells L: linux-cachefs@redhat.com @@ -3148,7 +3138,7 @@ F: drivers/tty/hvc/ HARDWARE MONITORING M: Jean Delvare -M: Guenter Roeck +M: Guenter Roeck L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.org/ T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/ @@ -4106,8 +4096,6 @@ F: drivers/scsi/53c700* LED SUBSYSTEM M: Bryan Wu M: Richard Purdie -L: linux-leds@vger.kernel.org -T: git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git S: Maintained F: drivers/leds/ F: include/linux/leds.h @@ -4352,8 +4340,7 @@ MAC80211 M: Johannes Berg L: linux-wireless@vger.kernel.org W: http://wireless.kernel.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git S: Maintained F: Documentation/networking/mac80211-injection.txt F: include/net/mac80211.h @@ -4364,8 +4351,7 @@ M: Stefano Brivio M: Mattias Nissler L: linux-wireless@vger.kernel.org W: http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/PID -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git S: Maintained F: net/mac80211/rc80211_pid* @@ -4425,13 +4411,6 @@ S: Orphan F: drivers/video/matrox/matroxfb_* F: include/linux/matroxfb.h -MAX16065 HARDWARE MONITOR DRIVER -M: Guenter Roeck -L: lm-sensors@lm-sensors.org -S: Maintained -F: Documentation/hwmon/max16065 -F: drivers/hwmon/max16065.c - MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER M: "Hans J. Koch" L: lm-sensors@lm-sensors.org @@ -5170,7 +5149,7 @@ F: drivers/leds/leds-pca9532.c F: include/linux/leds-pca9532.h PCA9541 I2C BUS MASTER SELECTOR DRIVER -M: Guenter Roeck +M: Guenter Roeck L: linux-i2c@vger.kernel.org S: Maintained F: drivers/i2c/muxes/i2c-mux-pca9541.c @@ -5190,7 +5169,7 @@ S: Maintained F: drivers/firmware/pcdp.* PCI ERROR RECOVERY -M: Linas Vepstas +M: Linas Vepstas L: linux-pci@vger.kernel.org S: Supported F: Documentation/PCI/pci-error-recovery.txt @@ -5320,7 +5299,7 @@ F: drivers/video/fb-puv3.c F: drivers/rtc/rtc-puv3.c PMBUS HARDWARE MONITORING DRIVERS -M: Guenter Roeck +M: Guenter Roeck L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.org/ W: http://www.roeck-us.net/linux/drivers/ @@ -5716,9 +5695,6 @@ F: include/linux/remoteproc.h RFKILL M: Johannes Berg L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git -T: git git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git S: Maintained F: Documentation/rfkill.txt F: net/rfkill/ @@ -7315,11 +7291,11 @@ F: Documentation/DocBook/uio-howto.tmpl F: drivers/uio/ F: include/linux/uio*.h -UTIL-LINUX PACKAGE +UTIL-LINUX-NG PACKAGE M: Karel Zak -L: util-linux@vger.kernel.org -W: http://en.wikipedia.org/wiki/Util-linux -T: git git://git.kernel.org/pub/scm/utils/util-linux/util-linux.git +L: util-linux-ng@vger.kernel.org +W: http://kernel.org/~kzak/util-linux-ng/ +T: git git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git S: Maintained UVESAFB DRIVER diff --git a/trunk/Makefile b/trunk/Makefile index d845c2a1aa68..0d718ede9ea5 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 5 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc1 NAME = Saber-toothed Squirrel # *DOCUMENTATION* diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index 84449dd8f031..b649c5904a4f 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -7,6 +7,7 @@ config ARM select HAVE_IDE if PCI || ISA || PCMCIA select HAVE_DMA_ATTRS select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7) + select CMA if (CPU_V6 || CPU_V6K || CPU_V7) select HAVE_MEMBLOCK select RTC_LIB select SYS_SUPPORTS_APM_EMULATION diff --git a/trunk/arch/arm/mach-omap2/display.c b/trunk/arch/arm/mach-omap2/display.c index 5fb47a14f4ba..54d49ddb9b81 100644 --- a/trunk/arch/arm/mach-omap2/display.c +++ b/trunk/arch/arm/mach-omap2/display.c @@ -271,9 +271,9 @@ static struct platform_device *create_simple_dss_pdev(const char *pdev_name, goto err; } - r = platform_device_add(pdev); + r = omap_device_register(pdev); if (r) { - pr_err("Could not register platform_device for %s\n", pdev_name); + pr_err("Could not register omap_device for %s\n", pdev_name); goto err; } diff --git a/trunk/arch/arm/mach-shmobile/Kconfig b/trunk/arch/arm/mach-shmobile/Kconfig index df33909205e2..f31383c32f9c 100644 --- a/trunk/arch/arm/mach-shmobile/Kconfig +++ b/trunk/arch/arm/mach-shmobile/Kconfig @@ -186,12 +186,6 @@ config SH_TIMER_TMU help This enables build of the TMU timer driver. -config EM_TIMER_STI - bool "STI timer driver" - default y - help - This enables build of the STI timer driver. - endmenu config SH_CLK_CPG diff --git a/trunk/arch/arm/mm/dma-mapping.c b/trunk/arch/arm/mm/dma-mapping.c index 106c4c0ebccd..ea6b43154090 100644 --- a/trunk/arch/arm/mm/dma-mapping.c +++ b/trunk/arch/arm/mm/dma-mapping.c @@ -268,8 +268,10 @@ static int __init consistent_init(void) unsigned long base = consistent_base; unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT; - if (IS_ENABLED(CONFIG_CMA) && !IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) +#ifndef CONFIG_ARM_DMA_USE_IOMMU + if (cpu_architecture() >= CPU_ARCH_ARMv6) return 0; +#endif consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL); if (!consistent_pte) { @@ -340,7 +342,7 @@ static int __init coherent_init(void) struct page *page; void *ptr; - if (!IS_ENABLED(CONFIG_CMA)) + if (cpu_architecture() < CPU_ARCH_ARMv6) return 0; ptr = __alloc_from_contiguous(NULL, size, prot, &page); @@ -702,7 +704,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, if (arch_is_coherent() || nommu()) addr = __alloc_simple_buffer(dev, size, gfp, &page); - else if (!IS_ENABLED(CONFIG_CMA)) + else if (cpu_architecture() < CPU_ARCH_ARMv6) addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller); else if (gfp & GFP_ATOMIC) addr = __alloc_from_pool(dev, size, &page, caller); @@ -771,7 +773,7 @@ void arm_dma_free(struct device *dev, size_t size, void *cpu_addr, if (arch_is_coherent() || nommu()) { __dma_free_buffer(page, size); - } else if (!IS_ENABLED(CONFIG_CMA)) { + } else if (cpu_architecture() < CPU_ARCH_ARMv6) { __dma_free_remap(cpu_addr, size); __dma_free_buffer(page, size); } else { diff --git a/trunk/arch/avr32/kernel/signal.c b/trunk/arch/avr32/kernel/signal.c index d552a854dacc..c140f9b41dce 100644 --- a/trunk/arch/avr32/kernel/signal.c +++ b/trunk/arch/avr32/kernel/signal.c @@ -300,7 +300,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR) syscall = 1; - if (ti->flags & _TIF_SIGPENDING) + if (ti->flags & _TIF_SIGPENDING)) do_signal(regs, syscall); if (ti->flags & _TIF_NOTIFY_RESUME) { diff --git a/trunk/arch/blackfin/kernel/process.c b/trunk/arch/blackfin/kernel/process.c index 62bcea7dcc6d..2e3994b20169 100644 --- a/trunk/arch/blackfin/kernel/process.c +++ b/trunk/arch/blackfin/kernel/process.c @@ -173,7 +173,7 @@ asmlinkage int bfin_clone(struct pt_regs *regs) unsigned long newsp; #ifdef __ARCH_SYNC_CORE_DCACHE - if (current->nr_cpus_allowed == num_possible_cpus()) + if (current->rt.nr_cpus_allowed == num_possible_cpus()) set_cpus_allowed_ptr(current, cpumask_of(smp_processor_id())); #endif diff --git a/trunk/arch/m68k/Kconfig b/trunk/arch/m68k/Kconfig index 147120128260..cac5b6be572a 100644 --- a/trunk/arch/m68k/Kconfig +++ b/trunk/arch/m68k/Kconfig @@ -7,8 +7,6 @@ config M68K select GENERIC_IRQ_SHOW select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS select GENERIC_CPU_DEVICES - select GENERIC_STRNCPY_FROM_USER if MMU - select GENERIC_STRNLEN_USER if MMU select FPU if MMU select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE diff --git a/trunk/arch/m68k/include/asm/Kbuild b/trunk/arch/m68k/include/asm/Kbuild index eafa2539a8ee..1a922fad76f7 100644 --- a/trunk/arch/m68k/include/asm/Kbuild +++ b/trunk/arch/m68k/include/asm/Kbuild @@ -1,4 +1,2 @@ include include/asm-generic/Kbuild.asm header-y += cachectl.h - -generic-y += word-at-a-time.h diff --git a/trunk/arch/m68k/include/asm/m528xsim.h b/trunk/arch/m68k/include/asm/m528xsim.h index 497c31c803ff..d63b99ff7ff7 100644 --- a/trunk/arch/m68k/include/asm/m528xsim.h +++ b/trunk/arch/m68k/include/asm/m528xsim.h @@ -86,7 +86,7 @@ /* * QSPI module. */ -#define MCFQSPI_BASE (MCF_IPSBAR + 0x340) +#define MCFQSPI_IOBASE (MCF_IPSBAR + 0x340) #define MCFQSPI_SIZE 0x40 #define MCFQSPI_CS0 147 diff --git a/trunk/arch/m68k/include/asm/uaccess_mm.h b/trunk/arch/m68k/include/asm/uaccess_mm.h index 472c891a4aee..9c80cd515b20 100644 --- a/trunk/arch/m68k/include/asm/uaccess_mm.h +++ b/trunk/arch/m68k/include/asm/uaccess_mm.h @@ -379,15 +379,12 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n) #define copy_from_user(to, from, n) __copy_from_user(to, from, n) #define copy_to_user(to, from, n) __copy_to_user(to, from, n) -#define user_addr_max() \ - (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) - -extern long strncpy_from_user(char *dst, const char __user *src, long count); -extern __must_check long strlen_user(const char __user *str); -extern __must_check long strnlen_user(const char __user *str, long n); - +long strncpy_from_user(char *dst, const char __user *src, long count); +long strnlen_user(const char __user *src, long n); unsigned long __clear_user(void __user *to, unsigned long n); #define clear_user __clear_user +#define strlen_user(str) strnlen_user(str, 32767) + #endif /* _M68K_UACCESS_H */ diff --git a/trunk/arch/m68k/kernel/ptrace.c b/trunk/arch/m68k/kernel/ptrace.c index 1bc10e62b9af..8b4a2222e658 100644 --- a/trunk/arch/m68k/kernel/ptrace.c +++ b/trunk/arch/m68k/kernel/ptrace.c @@ -286,7 +286,7 @@ asmlinkage void syscall_trace(void) } } -#if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) +#ifdef CONFIG_COLDFIRE asmlinkage int syscall_trace_enter(void) { int ret = 0; diff --git a/trunk/arch/m68k/kernel/time.c b/trunk/arch/m68k/kernel/time.c index 707f0573ec6b..d7deb7fc7eb5 100644 --- a/trunk/arch/m68k/kernel/time.c +++ b/trunk/arch/m68k/kernel/time.c @@ -85,7 +85,7 @@ void __init time_init(void) mach_sched_init(timer_interrupt); } -#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET +#ifdef CONFIG_M68KCLASSIC u32 arch_gettimeoffset(void) { @@ -108,4 +108,4 @@ static int __init rtc_init(void) module_init(rtc_init); -#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ +#endif /* CONFIG_M68KCLASSIC */ diff --git a/trunk/arch/m68k/lib/uaccess.c b/trunk/arch/m68k/lib/uaccess.c index 5e97f2ee7c11..5664386338da 100644 --- a/trunk/arch/m68k/lib/uaccess.c +++ b/trunk/arch/m68k/lib/uaccess.c @@ -103,6 +103,80 @@ unsigned long __generic_copy_to_user(void __user *to, const void *from, } EXPORT_SYMBOL(__generic_copy_to_user); +/* + * Copy a null terminated string from userspace. + */ +long strncpy_from_user(char *dst, const char __user *src, long count) +{ + long res; + char c; + + if (count <= 0) + return count; + + asm volatile ("\n" + "1: "MOVES".b (%2)+,%4\n" + " move.b %4,(%1)+\n" + " jeq 2f\n" + " subq.l #1,%3\n" + " jne 1b\n" + "2: sub.l %3,%0\n" + "3:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "10: move.l %5,%0\n" + " jra 3b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,10b\n" + " .previous" + : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c) + : "i" (-EFAULT), "0" (count)); + + return res; +} +EXPORT_SYMBOL(strncpy_from_user); + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 on exception, a value greater than N if too long + */ +long strnlen_user(const char __user *src, long n) +{ + char c; + long res; + + asm volatile ("\n" + "1: subq.l #1,%1\n" + " jmi 3f\n" + "2: "MOVES".b (%0)+,%2\n" + " tst.b %2\n" + " jne 1b\n" + " jra 4f\n" + "\n" + "3: addq.l #1,%0\n" + "4: sub.l %4,%0\n" + "5:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "20: sub.l %0,%0\n" + " jra 5b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 2b,20b\n" + " .previous\n" + : "=&a" (res), "+d" (n), "=&d" (c) + : "0" (src), "r" (src)); + + return res; +} +EXPORT_SYMBOL(strnlen_user); + /* * Zero Userspace */ diff --git a/trunk/arch/m68k/platform/68328/timers.c b/trunk/arch/m68k/platform/68328/timers.c index f4dc9b295609..c801c172b822 100644 --- a/trunk/arch/m68k/platform/68328/timers.c +++ b/trunk/arch/m68k/platform/68328/timers.c @@ -53,7 +53,6 @@ #endif static u32 m68328_tick_cnt; -static irq_handler_t timer_interrupt; /***************************************************************************/ @@ -63,7 +62,7 @@ static irqreturn_t hw_tick(int irq, void *dummy) TSTAT &= 0; m68328_tick_cnt += TICKS_PER_JIFFY; - return timer_interrupt(irq, dummy); + return arch_timer_interrupt(irq, dummy); } /***************************************************************************/ @@ -100,7 +99,7 @@ static struct clocksource m68328_clk = { /***************************************************************************/ -void hw_timer_init(irq_handler_t handler) +void hw_timer_init(void) { /* disable timer 1 */ TCTL = 0; @@ -116,7 +115,6 @@ void hw_timer_init(irq_handler_t handler) /* Enable timer 1 */ TCTL |= TCTL_TEN; clocksource_register_hz(&m68328_clk, TICKS_PER_JIFFY*HZ); - timer_interrupt = handler; } /***************************************************************************/ diff --git a/trunk/arch/m68k/platform/68360/config.c b/trunk/arch/m68k/platform/68360/config.c index 9877cefad1e7..255fc03913e9 100644 --- a/trunk/arch/m68k/platform/68360/config.c +++ b/trunk/arch/m68k/platform/68360/config.c @@ -35,7 +35,6 @@ extern void m360_cpm_reset(void); #define OSCILLATOR (unsigned long int)33000000 #endif -static irq_handler_t timer_interrupt; unsigned long int system_clock; extern QUICC *pquicc; @@ -53,7 +52,7 @@ static irqreturn_t hw_tick(int irq, void *dummy) pquicc->timer_ter1 = 0x0002; /* clear timer event */ - return timer_interrupt(irq, dummy); + return arch_timer_interrupt(irq, dummy); } static struct irqaction m68360_timer_irq = { @@ -62,7 +61,7 @@ static struct irqaction m68360_timer_irq = { .handler = hw_tick, }; -void hw_timer_init(irq_handler_t handler) +void hw_timer_init(void) { unsigned char prescaler; unsigned short tgcr_save; @@ -95,8 +94,6 @@ void hw_timer_init(irq_handler_t handler) pquicc->timer_ter1 = 0x0003; /* clear timer events */ - timer_interrupt = handler; - /* enable timer 1 interrupt in CIMR */ setup_irq(CPMVEC_TIMER1, &m68360_timer_irq); diff --git a/trunk/arch/parisc/Makefile b/trunk/arch/parisc/Makefile index 5707f1a62341..dbc3850b1d0d 100644 --- a/trunk/arch/parisc/Makefile +++ b/trunk/arch/parisc/Makefile @@ -21,7 +21,6 @@ KBUILD_DEFCONFIG := default_defconfig NM = sh $(srctree)/arch/parisc/nm CHECKFLAGS += -D__hppa__=1 -LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) MACHINE := $(shell uname -m) ifeq ($(MACHINE),parisc*) @@ -80,7 +79,7 @@ kernel-y := mm/ kernel/ math-emu/ kernel-$(CONFIG_HPUX) += hpux/ core-y += $(addprefix arch/parisc/, $(kernel-y)) -libs-y += arch/parisc/lib/ $(LIBGCC) +libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name` drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/ diff --git a/trunk/arch/parisc/include/asm/Kbuild b/trunk/arch/parisc/include/asm/Kbuild index 4383707d9801..19a434f55059 100644 --- a/trunk/arch/parisc/include/asm/Kbuild +++ b/trunk/arch/parisc/include/asm/Kbuild @@ -1,4 +1,3 @@ include include/asm-generic/Kbuild.asm header-y += pdc.h -generic-y += word-at-a-time.h diff --git a/trunk/arch/parisc/include/asm/bug.h b/trunk/arch/parisc/include/asm/bug.h index 62a33338549c..72cfdb0cfdd1 100644 --- a/trunk/arch/parisc/include/asm/bug.h +++ b/trunk/arch/parisc/include/asm/bug.h @@ -1,8 +1,6 @@ #ifndef _PARISC_BUG_H #define _PARISC_BUG_H -#include /* for BUGFLAG_TAINT */ - /* * Tell the user there is some problem. * The offending file and line are encoded in the __bug_table section. diff --git a/trunk/arch/powerpc/kernel/module_32.c b/trunk/arch/powerpc/kernel/module_32.c index 2e3200ca485f..0b6d79617d7b 100644 --- a/trunk/arch/powerpc/kernel/module_32.c +++ b/trunk/arch/powerpc/kernel/module_32.c @@ -176,8 +176,8 @@ int module_frob_arch_sections(Elf32_Ehdr *hdr, static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) { - if (entry->jump[0] == 0x3d800000 + ((val + 0x8000) >> 16) - && entry->jump[1] == 0x398c0000 + (val & 0xffff)) + if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16) + && entry->jump[1] == 0x396b0000 + (val & 0xffff)) return 1; return 0; } @@ -204,9 +204,10 @@ static uint32_t do_plt_call(void *location, entry++; } - entry->jump[0] = 0x3d800000+((val+0x8000)>>16); /* lis r12,sym@ha */ - entry->jump[1] = 0x398c0000 + (val&0xffff); /* addi r12,r12,sym@l*/ - entry->jump[2] = 0x7d8903a6; /* mtctr r12 */ + /* Stolen from Paul Mackerras as well... */ + entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */ + entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/ + entry->jump[2] = 0x7d6903a6; /* mtctr r11 */ entry->jump[3] = 0x4e800420; /* bctr */ DEBUGP("Initialized plt for 0x%x at %p\n", val, entry); diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c index be171ee73bf8..99a995c2a3f2 100644 --- a/trunk/arch/powerpc/kernel/time.c +++ b/trunk/arch/powerpc/kernel/time.c @@ -475,7 +475,6 @@ void timer_interrupt(struct pt_regs * regs) struct pt_regs *old_regs; u64 *next_tb = &__get_cpu_var(decrementers_next_tb); struct clock_event_device *evt = &__get_cpu_var(decrementers); - u64 now; /* Ensure a positive value is written to the decrementer, or else * some CPUs will continue to take decrementer exceptions. @@ -510,16 +509,9 @@ void timer_interrupt(struct pt_regs * regs) irq_work_run(); } - now = get_tb_or_rtc(); - if (now >= *next_tb) { - *next_tb = ~(u64)0; - if (evt->event_handler) - evt->event_handler(evt); - } else { - now = *next_tb - now; - if (now <= DECREMENTER_MAX) - set_dec((int)now); - } + *next_tb = ~(u64)0; + if (evt->event_handler) + evt->event_handler(evt); #ifdef CONFIG_PPC64 /* collect purr register values often, for accurate calculations */ diff --git a/trunk/arch/sh/Kconfig b/trunk/arch/sh/Kconfig index 31d9db7913e4..99bcd0ee838d 100644 --- a/trunk/arch/sh/Kconfig +++ b/trunk/arch/sh/Kconfig @@ -32,8 +32,6 @@ config SUPERH select GENERIC_SMP_IDLE_THREAD select GENERIC_CLOCKEVENTS select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER help The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast diff --git a/trunk/arch/sh/Makefile b/trunk/arch/sh/Makefile index aed701c7b11b..46edf070da1c 100644 --- a/trunk/arch/sh/Makefile +++ b/trunk/arch/sh/Makefile @@ -9,12 +9,6 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -ifneq ($(SUBARCH),$(ARCH)) - ifeq ($(CROSS_COMPILE),) - CROSS_COMPILE := $(call cc-cross-prefix, $(UTS_MACHINE)-linux- $(UTS_MACHINE)-linux-gnu- $(UTS_MACHINE)-unknown-linux-gnu-) - endif -endif - isa-y := any isa-$(CONFIG_SH_DSP) := sh isa-$(CONFIG_CPU_SH2) := sh2 @@ -112,13 +106,19 @@ LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_PAGE_OFFSET) \ KBUILD_DEFCONFIG := cayman_defconfig endif +ifneq ($(SUBARCH),$(ARCH)) + ifeq ($(CROSS_COMPILE),) + CROSS_COMPILE := $(call cc-cross-prefix, $(UTS_MACHINE)-linux- $(UTS_MACHINE)-linux-gnu- $(UTS_MACHINE)-unknown-linux-gnu-) + endif +endif + ifdef CONFIG_CPU_LITTLE_ENDIAN ld-bfd := elf32-$(UTS_MACHINE)-linux -LDFLAGS_vmlinux += --defsym jiffies=jiffies_64 --oformat $(ld-bfd) +LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64' --oformat $(ld-bfd) LDFLAGS += -EL else ld-bfd := elf32-$(UTS_MACHINE)big-linux -LDFLAGS_vmlinux += --defsym jiffies=jiffies_64+4 --oformat $(ld-bfd) +LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4' --oformat $(ld-bfd) LDFLAGS += -EB endif diff --git a/trunk/arch/sh/include/asm/Kbuild b/trunk/arch/sh/include/asm/Kbuild index 7b673ddcd555..7beb42322f60 100644 --- a/trunk/arch/sh/include/asm/Kbuild +++ b/trunk/arch/sh/include/asm/Kbuild @@ -1,39 +1,5 @@ include include/asm-generic/Kbuild.asm -generic-y += bitsperlong.h -generic-y += cputime.h -generic-y += current.h -generic-y += delay.h -generic-y += div64.h -generic-y += emergency-restart.h -generic-y += errno.h -generic-y += fcntl.h -generic-y += ioctl.h -generic-y += ipcbuf.h -generic-y += irq_regs.h -generic-y += kvm_para.h -generic-y += local.h -generic-y += local64.h -generic-y += param.h -generic-y += parport.h -generic-y += percpu.h -generic-y += poll.h -generic-y += mman.h -generic-y += msgbuf.h -generic-y += resource.h -generic-y += scatterlist.h -generic-y += sembuf.h -generic-y += serial.h -generic-y += shmbuf.h -generic-y += siginfo.h -generic-y += sizes.h -generic-y += socket.h -generic-y += statfs.h -generic-y += termbits.h -generic-y += termios.h -generic-y += ucontext.h -generic-y += xor.h - header-y += cachectl.h header-y += cpu-features.h header-y += hw_breakpoint.h diff --git a/trunk/arch/sh/include/asm/bitsperlong.h b/trunk/arch/sh/include/asm/bitsperlong.h new file mode 100644 index 000000000000..6dc0bb0c13b2 --- /dev/null +++ b/trunk/arch/sh/include/asm/bitsperlong.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/cputime.h b/trunk/arch/sh/include/asm/cputime.h new file mode 100644 index 000000000000..6ca395d1393e --- /dev/null +++ b/trunk/arch/sh/include/asm/cputime.h @@ -0,0 +1,6 @@ +#ifndef __SH_CPUTIME_H +#define __SH_CPUTIME_H + +#include + +#endif /* __SH_CPUTIME_H */ diff --git a/trunk/arch/sh/include/asm/current.h b/trunk/arch/sh/include/asm/current.h new file mode 100644 index 000000000000..4c51401b5537 --- /dev/null +++ b/trunk/arch/sh/include/asm/current.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/delay.h b/trunk/arch/sh/include/asm/delay.h new file mode 100644 index 000000000000..9670e127b7b2 --- /dev/null +++ b/trunk/arch/sh/include/asm/delay.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/div64.h b/trunk/arch/sh/include/asm/div64.h new file mode 100644 index 000000000000..6cd978cefb28 --- /dev/null +++ b/trunk/arch/sh/include/asm/div64.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/emergency-restart.h b/trunk/arch/sh/include/asm/emergency-restart.h new file mode 100644 index 000000000000..108d8c48e42e --- /dev/null +++ b/trunk/arch/sh/include/asm/emergency-restart.h @@ -0,0 +1,6 @@ +#ifndef _ASM_EMERGENCY_RESTART_H +#define _ASM_EMERGENCY_RESTART_H + +#include + +#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/trunk/arch/sh/include/asm/errno.h b/trunk/arch/sh/include/asm/errno.h new file mode 100644 index 000000000000..51cf6f9cebb8 --- /dev/null +++ b/trunk/arch/sh/include/asm/errno.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_ERRNO_H +#define __ASM_SH_ERRNO_H + +#include + +#endif /* __ASM_SH_ERRNO_H */ diff --git a/trunk/arch/sh/include/asm/fcntl.h b/trunk/arch/sh/include/asm/fcntl.h new file mode 100644 index 000000000000..46ab12db5739 --- /dev/null +++ b/trunk/arch/sh/include/asm/fcntl.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/ioctl.h b/trunk/arch/sh/include/asm/ioctl.h new file mode 100644 index 000000000000..b279fe06dfe5 --- /dev/null +++ b/trunk/arch/sh/include/asm/ioctl.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/ipcbuf.h b/trunk/arch/sh/include/asm/ipcbuf.h new file mode 100644 index 000000000000..84c7e51cb6d0 --- /dev/null +++ b/trunk/arch/sh/include/asm/ipcbuf.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/irq_regs.h b/trunk/arch/sh/include/asm/irq_regs.h new file mode 100644 index 000000000000..3dd9c0b70270 --- /dev/null +++ b/trunk/arch/sh/include/asm/irq_regs.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/kvm_para.h b/trunk/arch/sh/include/asm/kvm_para.h new file mode 100644 index 000000000000..14fab8f0b957 --- /dev/null +++ b/trunk/arch/sh/include/asm/kvm_para.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/local.h b/trunk/arch/sh/include/asm/local.h new file mode 100644 index 000000000000..9ed9b9cb459a --- /dev/null +++ b/trunk/arch/sh/include/asm/local.h @@ -0,0 +1,7 @@ +#ifndef __ASM_SH_LOCAL_H +#define __ASM_SH_LOCAL_H + +#include + +#endif /* __ASM_SH_LOCAL_H */ + diff --git a/trunk/arch/sh/include/asm/local64.h b/trunk/arch/sh/include/asm/local64.h new file mode 100644 index 000000000000..36c93b5cc239 --- /dev/null +++ b/trunk/arch/sh/include/asm/local64.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/mman.h b/trunk/arch/sh/include/asm/mman.h new file mode 100644 index 000000000000..8eebf89f5ab1 --- /dev/null +++ b/trunk/arch/sh/include/asm/mman.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/msgbuf.h b/trunk/arch/sh/include/asm/msgbuf.h new file mode 100644 index 000000000000..809134c644a6 --- /dev/null +++ b/trunk/arch/sh/include/asm/msgbuf.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/param.h b/trunk/arch/sh/include/asm/param.h new file mode 100644 index 000000000000..965d45427975 --- /dev/null +++ b/trunk/arch/sh/include/asm/param.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/parport.h b/trunk/arch/sh/include/asm/parport.h new file mode 100644 index 000000000000..cf252af64590 --- /dev/null +++ b/trunk/arch/sh/include/asm/parport.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/percpu.h b/trunk/arch/sh/include/asm/percpu.h new file mode 100644 index 000000000000..4db4b39a4399 --- /dev/null +++ b/trunk/arch/sh/include/asm/percpu.h @@ -0,0 +1,6 @@ +#ifndef __ARCH_SH_PERCPU +#define __ARCH_SH_PERCPU + +#include + +#endif /* __ARCH_SH_PERCPU */ diff --git a/trunk/arch/sh/include/asm/poll.h b/trunk/arch/sh/include/asm/poll.h new file mode 100644 index 000000000000..c98509d3149e --- /dev/null +++ b/trunk/arch/sh/include/asm/poll.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/resource.h b/trunk/arch/sh/include/asm/resource.h new file mode 100644 index 000000000000..9c2499a86ec0 --- /dev/null +++ b/trunk/arch/sh/include/asm/resource.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_RESOURCE_H +#define __ASM_SH_RESOURCE_H + +#include + +#endif /* __ASM_SH_RESOURCE_H */ diff --git a/trunk/arch/sh/include/asm/scatterlist.h b/trunk/arch/sh/include/asm/scatterlist.h new file mode 100644 index 000000000000..98dfc3510f10 --- /dev/null +++ b/trunk/arch/sh/include/asm/scatterlist.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_SCATTERLIST_H +#define __ASM_SH_SCATTERLIST_H + +#include + +#endif /* __ASM_SH_SCATTERLIST_H */ diff --git a/trunk/arch/sh/include/asm/sembuf.h b/trunk/arch/sh/include/asm/sembuf.h new file mode 100644 index 000000000000..7673b83cfef7 --- /dev/null +++ b/trunk/arch/sh/include/asm/sembuf.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/serial.h b/trunk/arch/sh/include/asm/serial.h new file mode 100644 index 000000000000..a0cb0caff152 --- /dev/null +++ b/trunk/arch/sh/include/asm/serial.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/shmbuf.h b/trunk/arch/sh/include/asm/shmbuf.h new file mode 100644 index 000000000000..83c05fc2de38 --- /dev/null +++ b/trunk/arch/sh/include/asm/shmbuf.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/siginfo.h b/trunk/arch/sh/include/asm/siginfo.h new file mode 100644 index 000000000000..813040ed68a9 --- /dev/null +++ b/trunk/arch/sh/include/asm/siginfo.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_SIGINFO_H +#define __ASM_SH_SIGINFO_H + +#include + +#endif /* __ASM_SH_SIGINFO_H */ diff --git a/trunk/arch/sh/include/asm/sizes.h b/trunk/arch/sh/include/asm/sizes.h new file mode 100644 index 000000000000..dd248c2e1085 --- /dev/null +++ b/trunk/arch/sh/include/asm/sizes.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/socket.h b/trunk/arch/sh/include/asm/socket.h new file mode 100644 index 000000000000..6b71384b9d8b --- /dev/null +++ b/trunk/arch/sh/include/asm/socket.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/statfs.h b/trunk/arch/sh/include/asm/statfs.h new file mode 100644 index 000000000000..9202a023328f --- /dev/null +++ b/trunk/arch/sh/include/asm/statfs.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_STATFS_H +#define __ASM_SH_STATFS_H + +#include + +#endif /* __ASM_SH_STATFS_H */ diff --git a/trunk/arch/sh/include/asm/termbits.h b/trunk/arch/sh/include/asm/termbits.h new file mode 100644 index 000000000000..3935b106de79 --- /dev/null +++ b/trunk/arch/sh/include/asm/termbits.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/termios.h b/trunk/arch/sh/include/asm/termios.h new file mode 100644 index 000000000000..280d78a9d966 --- /dev/null +++ b/trunk/arch/sh/include/asm/termios.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/uaccess.h b/trunk/arch/sh/include/asm/uaccess.h index 8698a80ed00c..050f221fa898 100644 --- a/trunk/arch/sh/include/asm/uaccess.h +++ b/trunk/arch/sh/include/asm/uaccess.h @@ -25,8 +25,6 @@ (__chk_user_ptr(addr), \ __access_ok((unsigned long __force)(addr), (size))) -#define user_addr_max() (current_thread_info()->addr_limit.seg) - /* * Uh, these should become the main single-value transfer routines ... * They automatically use the right size if we just have the right @@ -102,11 +100,6 @@ struct __large_struct { unsigned long buf[100]; }; # include "uaccess_64.h" #endif -extern long strncpy_from_user(char *dest, const char __user *src, long count); - -extern __must_check long strlen_user(const char __user *str); -extern __must_check long strnlen_user(const char __user *str, long n); - /* Generic arbitrary sized copy. */ /* Return the number of bytes NOT copied */ __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); @@ -144,6 +137,37 @@ __kernel_size_t __clear_user(void *addr, __kernel_size_t size); __cl_size; \ }) +/** + * strncpy_from_user: - Copy a NUL terminated string from userspace. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ +#define strncpy_from_user(dest,src,count) \ +({ \ + unsigned long __sfu_src = (unsigned long)(src); \ + int __sfu_count = (int)(count); \ + long __sfu_res = -EFAULT; \ + \ + if (__access_ok(__sfu_src, __sfu_count)) \ + __sfu_res = __strncpy_from_user((unsigned long)(dest), \ + __sfu_src, __sfu_count); \ + \ + __sfu_res; \ +}) + static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { @@ -168,6 +192,43 @@ copy_to_user(void __user *to, const void *from, unsigned long n) return __copy_size; } +/** + * strnlen_user: - Get the size of a string in user space. + * @s: The string to measure. + * @n: The maximum valid length + * + * Context: User context only. This function may sleep. + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * If the string is too long, returns a value greater than @n. + */ +static inline long strnlen_user(const char __user *s, long n) +{ + if (!__addr_ok(s)) + return 0; + else + return __strnlen_user(s, n); +} + +/** + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * + * Context: User context only. This function may sleep. + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * + * If there is a limit on the length of a valid string, you may wish to + * consider using strnlen_user() instead. + */ +#define strlen_user(str) strnlen_user(str, ~0UL >> 1) + /* * The exception table consists of pairs of addresses: the first is the * address of an instruction that is allowed to fault, and the second is diff --git a/trunk/arch/sh/include/asm/uaccess_32.h b/trunk/arch/sh/include/asm/uaccess_32.h index c0de7ee35ab7..ae0d24f6653f 100644 --- a/trunk/arch/sh/include/asm/uaccess_32.h +++ b/trunk/arch/sh/include/asm/uaccess_32.h @@ -170,4 +170,79 @@ __asm__ __volatile__( \ extern void __put_user_unknown(void); +static inline int +__strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count) +{ + __kernel_size_t res; + unsigned long __dummy, _d, _s, _c; + + __asm__ __volatile__( + "9:\n" + "mov.b @%2+, %1\n\t" + "cmp/eq #0, %1\n\t" + "bt/s 2f\n" + "1:\n" + "mov.b %1, @%3\n\t" + "dt %4\n\t" + "bf/s 9b\n\t" + " add #1, %3\n\t" + "2:\n\t" + "sub %4, %0\n" + "3:\n" + ".section .fixup,\"ax\"\n" + "4:\n\t" + "mov.l 5f, %1\n\t" + "jmp @%1\n\t" + " mov %9, %0\n\t" + ".balign 4\n" + "5: .long 3b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .balign 4\n" + " .long 9b,4b\n" + ".previous" + : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d), "=r"(_c) + : "0" (__count), "2" (__src), "3" (__dest), "4" (__count), + "i" (-EFAULT) + : "memory", "t"); + + return res; +} + +/* + * Return the size of a string (including the ending 0 even when we have + * exceeded the maximum string length). + */ +static inline long __strnlen_user(const char __user *__s, long __n) +{ + unsigned long res; + unsigned long __dummy; + + __asm__ __volatile__( + "1:\t" + "mov.b @(%0,%3), %1\n\t" + "cmp/eq %4, %0\n\t" + "bt/s 2f\n\t" + " add #1, %0\n\t" + "tst %1, %1\n\t" + "bf 1b\n\t" + "2:\n" + ".section .fixup,\"ax\"\n" + "3:\n\t" + "mov.l 4f, %1\n\t" + "jmp @%1\n\t" + " mov #0, %0\n" + ".balign 4\n" + "4: .long 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .balign 4\n" + " .long 1b,3b\n" + ".previous" + : "=z" (res), "=&r" (__dummy) + : "0" (0), "r" (__s), "r" (__n) + : "t"); + return res; +} + #endif /* __ASM_SH_UACCESS_32_H */ diff --git a/trunk/arch/sh/include/asm/uaccess_64.h b/trunk/arch/sh/include/asm/uaccess_64.h index 2e07e0f40c6a..56fd20b8cdcc 100644 --- a/trunk/arch/sh/include/asm/uaccess_64.h +++ b/trunk/arch/sh/include/asm/uaccess_64.h @@ -84,4 +84,8 @@ extern long __put_user_asm_l(void *, long); extern long __put_user_asm_q(void *, long); extern void __put_user_unknown(void); +extern long __strnlen_user(const char *__s, long __n); +extern int __strncpy_from_user(unsigned long __dest, + unsigned long __user __src, int __count); + #endif /* __ASM_SH_UACCESS_64_H */ diff --git a/trunk/arch/sh/include/asm/ucontext.h b/trunk/arch/sh/include/asm/ucontext.h new file mode 100644 index 000000000000..9bc07b9f30fb --- /dev/null +++ b/trunk/arch/sh/include/asm/ucontext.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/asm/word-at-a-time.h b/trunk/arch/sh/include/asm/word-at-a-time.h deleted file mode 100644 index 6e38953ff7fd..000000000000 --- a/trunk/arch/sh/include/asm/word-at-a-time.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __ASM_SH_WORD_AT_A_TIME_H -#define __ASM_SH_WORD_AT_A_TIME_H - -#ifdef CONFIG_CPU_BIG_ENDIAN -# include -#else -/* - * Little-endian version cribbed from x86. - */ -struct word_at_a_time { - const unsigned long one_bits, high_bits; -}; - -#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } - -/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ -static inline long count_masked_bytes(long mask) -{ - /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ - long a = (0x0ff0001+mask) >> 23; - /* Fix the 1 for 00 case */ - return a & mask; -} - -/* Return nonzero if it has a zero */ -static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c) -{ - unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; - *bits = mask; - return mask; -} - -static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c) -{ - return bits; -} - -static inline unsigned long create_zero_mask(unsigned long bits) -{ - bits = (bits - 1) & ~bits; - return bits >> 7; -} - -/* The mask we created is directly usable as a bytemask */ -#define zero_bytemask(mask) (mask) - -static inline unsigned long find_zero(unsigned long mask) -{ - return count_masked_bytes(mask); -} -#endif - -#endif diff --git a/trunk/arch/sh/include/asm/xor.h b/trunk/arch/sh/include/asm/xor.h new file mode 100644 index 000000000000..c82eb12a5b18 --- /dev/null +++ b/trunk/arch/sh/include/asm/xor.h @@ -0,0 +1 @@ +#include diff --git a/trunk/arch/sh/include/cpu-sh2a/cpu/ubc.h b/trunk/arch/sh/include/cpu-sh2a/cpu/ubc.h new file mode 100644 index 000000000000..1192e1c761a7 --- /dev/null +++ b/trunk/arch/sh/include/cpu-sh2a/cpu/ubc.h @@ -0,0 +1,28 @@ +/* + * SH-2A UBC definitions + * + * Copyright (C) 2008 Kieran Bingham + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#ifndef __ASM_CPU_SH2A_UBC_H +#define __ASM_CPU_SH2A_UBC_H + +#define UBC_BARA 0xfffc0400 +#define UBC_BAMRA 0xfffc0404 +#define UBC_BBRA 0xfffc04a0 /* 16 bit access */ +#define UBC_BDRA 0xfffc0408 +#define UBC_BDMRA 0xfffc040c + +#define UBC_BARB 0xfffc0410 +#define UBC_BAMRB 0xfffc0414 +#define UBC_BBRB 0xfffc04b0 /* 16 bit access */ +#define UBC_BDRB 0xfffc0418 +#define UBC_BDMRB 0xfffc041c + +#define UBC_BRCR 0xfffc04c0 + +#endif /* __ASM_CPU_SH2A_UBC_H */ diff --git a/trunk/arch/sh/kernel/cpu/sh5/entry.S b/trunk/arch/sh/kernel/cpu/sh5/entry.S index b7cf6a547f11..ff1f0e6e9bec 100644 --- a/trunk/arch/sh/kernel/cpu/sh5/entry.S +++ b/trunk/arch/sh/kernel/cpu/sh5/entry.S @@ -1568,6 +1568,86 @@ ___clear_user_exit: #endif /* CONFIG_MMU */ +/* + * int __strncpy_from_user(unsigned long __dest, unsigned long __src, + * int __count) + * + * Inputs: + * (r2) target address + * (r3) source address + * (r4) maximum size in bytes + * + * Ouputs: + * (*r2) copied data + * (r2) -EFAULT (in case of faulting) + * copied data (otherwise) + */ + .global __strncpy_from_user +__strncpy_from_user: + pta ___strncpy_from_user1, tr0 + pta ___strncpy_from_user_done, tr1 + or r4, ZERO, r5 /* r5 = original count */ + beq/u r4, r63, tr1 /* early exit if r4==0 */ + movi -(EFAULT), r6 /* r6 = reply, no real fixup */ + or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ + +___strncpy_from_user1: + ld.b r3, 0, r7 /* Fault address: only in reading */ + st.b r2, 0, r7 + addi r2, 1, r2 + addi r3, 1, r3 + beq/u ZERO, r7, tr1 + addi r4, -1, r4 /* return real number of copied bytes */ + bne/l ZERO, r4, tr0 + +___strncpy_from_user_done: + sub r5, r4, r6 /* If done, return copied */ + +___strncpy_from_user_exit: + or r6, ZERO, r2 + ptabs LINK, tr0 + blink tr0, ZERO + +/* + * extern long __strnlen_user(const char *__s, long __n) + * + * Inputs: + * (r2) source address + * (r3) source size in bytes + * + * Ouputs: + * (r2) -EFAULT (in case of faulting) + * string length (otherwise) + */ + .global __strnlen_user +__strnlen_user: + pta ___strnlen_user_set_reply, tr0 + pta ___strnlen_user1, tr1 + or ZERO, ZERO, r5 /* r5 = counter */ + movi -(EFAULT), r6 /* r6 = reply, no real fixup */ + or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ + beq r3, ZERO, tr0 + +___strnlen_user1: + ldx.b r2, r5, r7 /* Fault address: only in reading */ + addi r3, -1, r3 /* No real fixup */ + addi r5, 1, r5 + beq r3, ZERO, tr0 + bne r7, ZERO, tr1 +! The line below used to be active. This meant led to a junk byte lying between each pair +! of entries in the argv & envp structures in memory. Whilst the program saw the right data +! via the argv and envp arguments to main, it meant the 'flat' representation visible through +! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example. +! addi r5, 1, r5 /* Include '\0' */ + +___strnlen_user_set_reply: + or r5, ZERO, r6 /* If done, return counter */ + +___strnlen_user_exit: + or r6, ZERO, r2 + ptabs LINK, tr0 + blink tr0, ZERO + /* * extern long __get_user_asm_?(void *val, long addr) * @@ -1902,6 +1982,8 @@ asm_uaccess_start: .long ___copy_user2, ___copy_user_exit .long ___clear_user1, ___clear_user_exit #endif + .long ___strncpy_from_user1, ___strncpy_from_user_exit + .long ___strnlen_user1, ___strnlen_user_exit .long ___get_user_asm_b1, ___get_user_asm_b_exit .long ___get_user_asm_w1, ___get_user_asm_w_exit .long ___get_user_asm_l1, ___get_user_asm_l_exit diff --git a/trunk/arch/sh/kernel/process.c b/trunk/arch/sh/kernel/process.c index 055d91b70305..9b7a459a4613 100644 --- a/trunk/arch/sh/kernel/process.c +++ b/trunk/arch/sh/kernel/process.c @@ -4,7 +4,6 @@ #include #include #include -#include struct kmem_cache *task_xstate_cachep = NULL; unsigned int xstate_size; diff --git a/trunk/arch/sh/kernel/process_64.c b/trunk/arch/sh/kernel/process_64.c index 602545b12a86..4264583eabac 100644 --- a/trunk/arch/sh/kernel/process_64.c +++ b/trunk/arch/sh/kernel/process_64.c @@ -33,7 +33,6 @@ #include struct task_struct *last_task_used_math = NULL; -struct pt_regs fake_swapper_regs = { 0, }; void show_regs(struct pt_regs *regs) { diff --git a/trunk/arch/sh/kernel/sh_ksyms_64.c b/trunk/arch/sh/kernel/sh_ksyms_64.c index 26a0774f5272..45afa5c51f67 100644 --- a/trunk/arch/sh/kernel/sh_ksyms_64.c +++ b/trunk/arch/sh/kernel/sh_ksyms_64.c @@ -32,6 +32,8 @@ EXPORT_SYMBOL(__get_user_asm_b); EXPORT_SYMBOL(__get_user_asm_w); EXPORT_SYMBOL(__get_user_asm_l); EXPORT_SYMBOL(__get_user_asm_q); +EXPORT_SYMBOL(__strnlen_user); +EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__copy_user); diff --git a/trunk/arch/tile/include/asm/thread_info.h b/trunk/arch/tile/include/asm/thread_info.h index e9c670d7a7fe..7e1fef36bde6 100644 --- a/trunk/arch/tile/include/asm/thread_info.h +++ b/trunk/arch/tile/include/asm/thread_info.h @@ -91,6 +91,11 @@ extern void smp_nap(void); /* Enable interrupts racelessly and nap forever: helper for cpu_idle(). */ extern void _cpu_idle(void); +/* Switch boot idle thread to a freshly-allocated stack and free old stack. */ +extern void cpu_idle_on_new_stack(struct thread_info *old_ti, + unsigned long new_sp, + unsigned long new_ss10); + #else /* __ASSEMBLY__ */ /* diff --git a/trunk/arch/tile/kernel/entry.S b/trunk/arch/tile/kernel/entry.S index c31637baff28..133c4b56a99e 100644 --- a/trunk/arch/tile/kernel/entry.S +++ b/trunk/arch/tile/kernel/entry.S @@ -68,6 +68,20 @@ STD_ENTRY(KBacktraceIterator_init_current) jrp lr /* keep backtracer happy */ STD_ENDPROC(KBacktraceIterator_init_current) +/* + * Reset our stack to r1/r2 (sp and ksp0+cpu respectively), then + * free the old stack (passed in r0) and re-invoke cpu_idle(). + * We update sp and ksp0 simultaneously to avoid backtracer warnings. + */ +STD_ENTRY(cpu_idle_on_new_stack) + { + move sp, r1 + mtspr SPR_SYSTEM_SAVE_K_0, r2 + } + jal free_thread_info + j cpu_idle + STD_ENDPROC(cpu_idle_on_new_stack) + /* Loop forever on a nap during SMP boot. */ STD_ENTRY(smp_nap) nap diff --git a/trunk/arch/tile/kernel/setup.c b/trunk/arch/tile/kernel/setup.c index dd87f3420390..6098ccc59be2 100644 --- a/trunk/arch/tile/kernel/setup.c +++ b/trunk/arch/tile/kernel/setup.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/arch/x86/boot/header.S b/trunk/arch/x86/boot/header.S index efe5acfc79c3..8bbea6aa40d9 100644 --- a/trunk/arch/x86/boot/header.S +++ b/trunk/arch/x86/boot/header.S @@ -94,10 +94,10 @@ bs_die: .section ".bsdata", "a" bugger_off_msg: - .ascii "Direct floppy boot is not supported. " - .ascii "Use a boot loader program instead.\r\n" + .ascii "Direct booting from floppy is no longer supported.\r\n" + .ascii "Please use a boot loader program instead.\r\n" .ascii "\n" - .ascii "Remove disk and press any key to reboot ...\r\n" + .ascii "Remove disk and press any key to reboot . . .\r\n" .byte 0 #ifdef CONFIG_EFI_STUB @@ -111,7 +111,7 @@ coff_header: #else .word 0x8664 # x86-64 #endif - .word 3 # nr_sections + .word 2 # nr_sections .long 0 # TimeDateStamp .long 0 # PointerToSymbolTable .long 1 # NumberOfSymbols @@ -158,8 +158,8 @@ extra_header_fields: #else .quad 0 # ImageBase #endif - .long 0x20 # SectionAlignment - .long 0x20 # FileAlignment + .long 0x1000 # SectionAlignment + .long 0x200 # FileAlignment .word 0 # MajorOperatingSystemVersion .word 0 # MinorOperatingSystemVersion .word 0 # MajorImageVersion @@ -200,10 +200,8 @@ extra_header_fields: # Section table section_table: - # - # The offset & size fields are filled in by build.c. - # - .ascii ".setup" + .ascii ".text" + .byte 0 .byte 0 .byte 0 .long 0 @@ -219,8 +217,9 @@ section_table: # # The EFI application loader requires a relocation section - # because EFI applications must be relocatable. The .reloc - # offset & size fields are filled in by build.c. + # because EFI applications must be relocatable. But since + # we don't need the loader to fixup any relocs for us, we + # just create an empty (zero-length) .reloc section header. # .ascii ".reloc" .byte 0 @@ -234,25 +233,6 @@ section_table: .word 0 # NumberOfRelocations .word 0 # NumberOfLineNumbers .long 0x42100040 # Characteristics (section flags) - - # - # The offset & size fields are filled in by build.c. - # - .ascii ".text" - .byte 0 - .byte 0 - .byte 0 - .long 0 - .long 0x0 # startup_{32,64} - .long 0 # Size of initialized data - # on disk - .long 0x0 # startup_{32,64} - .long 0 # PointerToRelocations - .long 0 # PointerToLineNumbers - .word 0 # NumberOfRelocations - .word 0 # NumberOfLineNumbers - .long 0x60500020 # Characteristics (section flags) - #endif /* CONFIG_EFI_STUB */ # Kernel attributes; used by setup. This is part 1 of the diff --git a/trunk/arch/x86/boot/tools/build.c b/trunk/arch/x86/boot/tools/build.c index 4b8e165ee572..3f61f6e2b46f 100644 --- a/trunk/arch/x86/boot/tools/build.c +++ b/trunk/arch/x86/boot/tools/build.c @@ -50,8 +50,6 @@ typedef unsigned int u32; u8 buf[SETUP_SECT_MAX*512]; int is_big_kernel; -#define PECOFF_RELOC_RESERVE 0x20 - /*----------------------------------------------------------------------*/ static const u32 crctab32[] = { @@ -135,103 +133,11 @@ static void usage(void) die("Usage: build setup system [> image]"); } -#ifdef CONFIG_EFI_STUB - -static void update_pecoff_section_header(char *section_name, u32 offset, u32 size) -{ - unsigned int pe_header; - unsigned short num_sections; - u8 *section; - - pe_header = get_unaligned_le32(&buf[0x3c]); - num_sections = get_unaligned_le16(&buf[pe_header + 6]); - -#ifdef CONFIG_X86_32 - section = &buf[pe_header + 0xa8]; -#else - section = &buf[pe_header + 0xb8]; -#endif - - while (num_sections > 0) { - if (strncmp((char*)section, section_name, 8) == 0) { - /* section header size field */ - put_unaligned_le32(size, section + 0x8); - - /* section header vma field */ - put_unaligned_le32(offset, section + 0xc); - - /* section header 'size of initialised data' field */ - put_unaligned_le32(size, section + 0x10); - - /* section header 'file offset' field */ - put_unaligned_le32(offset, section + 0x14); - - break; - } - section += 0x28; - num_sections--; - } -} - -static void update_pecoff_setup_and_reloc(unsigned int size) -{ - u32 setup_offset = 0x200; - u32 reloc_offset = size - PECOFF_RELOC_RESERVE; - u32 setup_size = reloc_offset - setup_offset; - - update_pecoff_section_header(".setup", setup_offset, setup_size); - update_pecoff_section_header(".reloc", reloc_offset, PECOFF_RELOC_RESERVE); - - /* - * Modify .reloc section contents with a single entry. The - * relocation is applied to offset 10 of the relocation section. - */ - put_unaligned_le32(reloc_offset + 10, &buf[reloc_offset]); - put_unaligned_le32(10, &buf[reloc_offset + 4]); -} - -static void update_pecoff_text(unsigned int text_start, unsigned int file_sz) -{ - unsigned int pe_header; - unsigned int text_sz = file_sz - text_start; - - pe_header = get_unaligned_le32(&buf[0x3c]); - - /* Size of image */ - put_unaligned_le32(file_sz, &buf[pe_header + 0x50]); - - /* - * Size of code: Subtract the size of the first sector (512 bytes) - * which includes the header. - */ - put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]); - -#ifdef CONFIG_X86_32 - /* - * Address of entry point. - * - * The EFI stub entry point is +16 bytes from the start of - * the .text section. - */ - put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]); -#else - /* - * Address of entry point. startup_32 is at the beginning and - * the 64-bit entry point (startup_64) is always 512 bytes - * after. The EFI stub entry point is 16 bytes after that, as - * the first instruction allows legacy loaders to jump over - * the EFI stub initialisation - */ - put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]); -#endif /* CONFIG_X86_32 */ - - update_pecoff_section_header(".text", text_start, text_sz); -} - -#endif /* CONFIG_EFI_STUB */ - int main(int argc, char ** argv) { +#ifdef CONFIG_EFI_STUB + unsigned int file_sz, pe_header; +#endif unsigned int i, sz, setup_sectors; int c; u32 sys_size; @@ -257,12 +163,6 @@ int main(int argc, char ** argv) die("Boot block hasn't got boot flag (0xAA55)"); fclose(file); -#ifdef CONFIG_EFI_STUB - /* Reserve 0x20 bytes for .reloc section */ - memset(buf+c, 0, PECOFF_RELOC_RESERVE); - c += PECOFF_RELOC_RESERVE; -#endif - /* Pad unused space with zeros */ setup_sectors = (c + 511) / 512; if (setup_sectors < SETUP_SECT_MIN) @@ -270,10 +170,6 @@ int main(int argc, char ** argv) i = setup_sectors*512; memset(buf+c, 0, i-c); -#ifdef CONFIG_EFI_STUB - update_pecoff_setup_and_reloc(i); -#endif - /* Set the default root device */ put_unaligned_le16(DEFAULT_ROOT_DEV, &buf[508]); @@ -298,8 +194,66 @@ int main(int argc, char ** argv) put_unaligned_le32(sys_size, &buf[0x1f4]); #ifdef CONFIG_EFI_STUB - update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz)); -#endif + file_sz = sz + i + ((sys_size * 16) - sz); + + pe_header = get_unaligned_le32(&buf[0x3c]); + + /* Size of image */ + put_unaligned_le32(file_sz, &buf[pe_header + 0x50]); + + /* + * Subtract the size of the first section (512 bytes) which + * includes the header and .reloc section. The remaining size + * is that of the .text section. + */ + file_sz -= 512; + + /* Size of code */ + put_unaligned_le32(file_sz, &buf[pe_header + 0x1c]); + +#ifdef CONFIG_X86_32 + /* + * Address of entry point. + * + * The EFI stub entry point is +16 bytes from the start of + * the .text section. + */ + put_unaligned_le32(i + 16, &buf[pe_header + 0x28]); + + /* .text size */ + put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]); + + /* .text vma */ + put_unaligned_le32(0x200, &buf[pe_header + 0xb4]); + + /* .text size of initialised data */ + put_unaligned_le32(file_sz, &buf[pe_header + 0xb8]); + + /* .text file offset */ + put_unaligned_le32(0x200, &buf[pe_header + 0xbc]); +#else + /* + * Address of entry point. startup_32 is at the beginning and + * the 64-bit entry point (startup_64) is always 512 bytes + * after. The EFI stub entry point is 16 bytes after that, as + * the first instruction allows legacy loaders to jump over + * the EFI stub initialisation + */ + put_unaligned_le32(i + 528, &buf[pe_header + 0x28]); + + /* .text size */ + put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]); + + /* .text vma */ + put_unaligned_le32(0x200, &buf[pe_header + 0xc4]); + + /* .text size of initialised data */ + put_unaligned_le32(file_sz, &buf[pe_header + 0xc8]); + + /* .text file offset */ + put_unaligned_le32(0x200, &buf[pe_header + 0xcc]); +#endif /* CONFIG_X86_32 */ +#endif /* CONFIG_EFI_STUB */ crc = partial_crc32(buf, i, crc); if (fwrite(buf, 1, i, stdout) != i) diff --git a/trunk/arch/x86/crypto/aesni-intel_asm.S b/trunk/arch/x86/crypto/aesni-intel_asm.S index 3470624d7835..be6d9e365a80 100644 --- a/trunk/arch/x86/crypto/aesni-intel_asm.S +++ b/trunk/arch/x86/crypto/aesni-intel_asm.S @@ -2460,12 +2460,10 @@ ENTRY(aesni_cbc_dec) pxor IN3, STATE4 movaps IN4, IV #else + pxor (INP), STATE2 + pxor 0x10(INP), STATE3 pxor IN1, STATE4 movaps IN2, IV - movups (INP), IN1 - pxor IN1, STATE2 - movups 0x10(INP), IN2 - pxor IN2, STATE3 #endif movups STATE1, (OUTP) movups STATE2, 0x10(OUTP) diff --git a/trunk/arch/x86/include/asm/nmi.h b/trunk/arch/x86/include/asm/nmi.h index dc580c42851c..0e3793b821ef 100644 --- a/trunk/arch/x86/include/asm/nmi.h +++ b/trunk/arch/x86/include/asm/nmi.h @@ -54,20 +54,6 @@ struct nmiaction { __register_nmi_handler((t), &fn##_na); \ }) -/* - * For special handlers that register/unregister in the - * init section only. This should be considered rare. - */ -#define register_nmi_handler_initonly(t, fn, fg, n) \ -({ \ - static struct nmiaction fn##_na __initdata = { \ - .handler = (fn), \ - .name = (n), \ - .flags = (fg), \ - }; \ - __register_nmi_handler((t), &fn##_na); \ -}) - int __register_nmi_handler(unsigned int, struct nmiaction *); void unregister_nmi_handler(unsigned int, const char *); diff --git a/trunk/arch/x86/include/asm/uaccess.h b/trunk/arch/x86/include/asm/uaccess.h index e1f3a17034fc..04cd6882308e 100644 --- a/trunk/arch/x86/include/asm/uaccess.h +++ b/trunk/arch/x86/include/asm/uaccess.h @@ -33,8 +33,9 @@ #define segment_eq(a, b) ((a).seg == (b).seg) #define user_addr_max() (current_thread_info()->addr_limit.seg) -#define __addr_ok(addr) \ - ((unsigned long __force)(addr) < user_addr_max()) +#define __addr_ok(addr) \ + ((unsigned long __force)(addr) < \ + (current_thread_info()->addr_limit.seg)) /* * Test whether a block of memory is a valid user space address. @@ -46,14 +47,14 @@ * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... */ -#define __range_not_ok(addr, size, limit) \ +#define __range_not_ok(addr, size) \ ({ \ unsigned long flag, roksum; \ __chk_user_ptr(addr); \ asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \ : "=&r" (flag), "=r" (roksum) \ : "1" (addr), "g" ((long)(size)), \ - "rm" (limit)); \ + "rm" (current_thread_info()->addr_limit.seg)); \ flag; \ }) @@ -76,8 +77,7 @@ * checks that the pointer is in the user space range - after calling * this function, memory access functions may still return -EFAULT. */ -#define access_ok(type, addr, size) \ - (likely(__range_not_ok(addr, size, user_addr_max()) == 0)) +#define access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0)) /* * The exception table consists of pairs of addresses relative to the diff --git a/trunk/arch/x86/include/asm/uv/uv_bau.h b/trunk/arch/x86/include/asm/uv/uv_bau.h index 6149b476d9df..becf47b81735 100644 --- a/trunk/arch/x86/include/asm/uv/uv_bau.h +++ b/trunk/arch/x86/include/asm/uv/uv_bau.h @@ -149,6 +149,7 @@ /* 4 bits of software ack period */ #define UV2_ACK_MASK 0x7UL #define UV2_ACK_UNITS_SHFT 3 +#define UV2_LEG_SHFT UV2H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_SHFT #define UV2_EXT_SHFT UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT /* diff --git a/trunk/arch/x86/kernel/aperture_64.c b/trunk/arch/x86/kernel/aperture_64.c index d5fd66f0d4cd..6e76c191a835 100644 --- a/trunk/arch/x86/kernel/aperture_64.c +++ b/trunk/arch/x86/kernel/aperture_64.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +95,11 @@ static u32 __init allocate_aperture(void) return 0; } memblock_reserve(addr, aper_size); + /* + * Kmemleak should not scan this block as it may not be mapped via the + * kernel direct mapping. + */ + kmemleak_ignore(phys_to_virt(addr)); printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n", aper_size >> 10, addr); insert_aperture_resource((u32)addr, aper_size); diff --git a/trunk/arch/x86/kernel/apic/io_apic.c b/trunk/arch/x86/kernel/apic/io_apic.c index 5f0ff597437c..ac96561d1a99 100644 --- a/trunk/arch/x86/kernel/apic/io_apic.c +++ b/trunk/arch/x86/kernel/apic/io_apic.c @@ -1195,7 +1195,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg) BUG_ON(!cfg->vector); vector = cfg->vector; - for_each_cpu(cpu, cfg->domain) + for_each_cpu_and(cpu, cfg->domain, cpu_online_mask) per_cpu(vector_irq, cpu)[vector] = -1; cfg->vector = 0; @@ -1203,7 +1203,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg) if (likely(!cfg->move_in_progress)) return; - for_each_cpu(cpu, cfg->old_domain) { + for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) { for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { if (per_cpu(vector_irq, cpu)[vector] != irq) diff --git a/trunk/arch/x86/kernel/cpu/mcheck/mce.c b/trunk/arch/x86/kernel/cpu/mcheck/mce.c index da27c5d2168a..0a687fd185e6 100644 --- a/trunk/arch/x86/kernel/cpu/mcheck/mce.c +++ b/trunk/arch/x86/kernel/cpu/mcheck/mce.c @@ -1274,7 +1274,7 @@ static void mce_timer_fn(unsigned long data) */ iv = __this_cpu_read(mce_next_interval); if (mce_notify_irq()) - iv = max(iv / 2, (unsigned long) HZ/100); + iv = max(iv, (unsigned long) HZ/100); else iv = min(iv * 2, round_jiffies_relative(check_interval * HZ)); __this_cpu_write(mce_next_interval, iv); @@ -1557,7 +1557,7 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) static void __mcheck_cpu_init_timer(void) { struct timer_list *t = &__get_cpu_var(mce_timer); - unsigned long iv = check_interval * HZ; + unsigned long iv = __this_cpu_read(mce_next_interval); setup_timer(t, mce_timer_fn, smp_processor_id()); diff --git a/trunk/arch/x86/kernel/cpu/perf_event.c b/trunk/arch/x86/kernel/cpu/perf_event.c index c4706cf9c011..e049d6da0183 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.c +++ b/trunk/arch/x86/kernel/cpu/perf_event.c @@ -1496,7 +1496,6 @@ static struct cpu_hw_events *allocate_fake_cpuc(void) if (!cpuc->shared_regs) goto error; } - cpuc->is_fake = 1; return cpuc; error: free_fake_cpuc(cpuc); @@ -1757,12 +1756,6 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry); } -static inline int -valid_user_frame(const void __user *fp, unsigned long size) -{ - return (__range_not_ok(fp, size, TASK_SIZE) == 0); -} - #ifdef CONFIG_COMPAT #include @@ -1787,7 +1780,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) if (bytes != sizeof(frame)) break; - if (!valid_user_frame(fp, sizeof(frame))) + if (fp < compat_ptr(regs->sp)) break; perf_callchain_store(entry, frame.return_address); @@ -1833,7 +1826,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) if (bytes != sizeof(frame)) break; - if (!valid_user_frame(fp, sizeof(frame))) + if ((unsigned long)fp < regs->sp) break; perf_callchain_store(entry, frame.return_address); diff --git a/trunk/arch/x86/kernel/cpu/perf_event.h b/trunk/arch/x86/kernel/cpu/perf_event.h index 7241e2fc3c17..6638aaf54493 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.h +++ b/trunk/arch/x86/kernel/cpu/perf_event.h @@ -117,7 +117,6 @@ struct cpu_hw_events { struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ unsigned int group_flag; - int is_fake; /* * Intel DebugStore bits @@ -365,7 +364,6 @@ struct x86_pmu { int pebs_record_size; void (*drain_pebs)(struct pt_regs *regs); struct event_constraint *pebs_constraints; - void (*pebs_aliases)(struct perf_event *event); /* * Intel LBR diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel.c b/trunk/arch/x86/kernel/cpu/perf_event_intel.c index 187c294bc658..166546ec6aef 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel.c @@ -1119,33 +1119,27 @@ intel_bts_constraints(struct perf_event *event) return NULL; } -static int intel_alt_er(int idx) +static bool intel_try_alt_er(struct perf_event *event, int orig_idx) { if (!(x86_pmu.er_flags & ERF_HAS_RSP_1)) - return idx; + return false; - if (idx == EXTRA_REG_RSP_0) - return EXTRA_REG_RSP_1; - - if (idx == EXTRA_REG_RSP_1) - return EXTRA_REG_RSP_0; - - return idx; -} - -static void intel_fixup_er(struct perf_event *event, int idx) -{ - event->hw.extra_reg.idx = idx; - - if (idx == EXTRA_REG_RSP_0) { - event->hw.config &= ~INTEL_ARCH_EVENT_MASK; - event->hw.config |= 0x01b7; - event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0; - } else if (idx == EXTRA_REG_RSP_1) { + if (event->hw.extra_reg.idx == EXTRA_REG_RSP_0) { event->hw.config &= ~INTEL_ARCH_EVENT_MASK; event->hw.config |= 0x01bb; + event->hw.extra_reg.idx = EXTRA_REG_RSP_1; event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1; + } else if (event->hw.extra_reg.idx == EXTRA_REG_RSP_1) { + event->hw.config &= ~INTEL_ARCH_EVENT_MASK; + event->hw.config |= 0x01b7; + event->hw.extra_reg.idx = EXTRA_REG_RSP_0; + event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0; } + + if (event->hw.extra_reg.idx == orig_idx) + return false; + + return true; } /* @@ -1163,18 +1157,14 @@ __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, struct event_constraint *c = &emptyconstraint; struct er_account *era; unsigned long flags; - int idx = reg->idx; + int orig_idx = reg->idx; - /* - * reg->alloc can be set due to existing state, so for fake cpuc we - * need to ignore this, otherwise we might fail to allocate proper fake - * state for this extra reg constraint. Also see the comment below. - */ - if (reg->alloc && !cpuc->is_fake) + /* already allocated shared msr */ + if (reg->alloc) return NULL; /* call x86_get_event_constraint() */ again: - era = &cpuc->shared_regs->regs[idx]; + era = &cpuc->shared_regs->regs[reg->idx]; /* * we use spin_lock_irqsave() to avoid lockdep issues when * passing a fake cpuc @@ -1183,29 +1173,6 @@ __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, if (!atomic_read(&era->ref) || era->config == reg->config) { - /* - * If its a fake cpuc -- as per validate_{group,event}() we - * shouldn't touch event state and we can avoid doing so - * since both will only call get_event_constraints() once - * on each event, this avoids the need for reg->alloc. - * - * Not doing the ER fixup will only result in era->reg being - * wrong, but since we won't actually try and program hardware - * this isn't a problem either. - */ - if (!cpuc->is_fake) { - if (idx != reg->idx) - intel_fixup_er(event, idx); - - /* - * x86_schedule_events() can call get_event_constraints() - * multiple times on events in the case of incremental - * scheduling(). reg->alloc ensures we only do the ER - * allocation once. - */ - reg->alloc = 1; - } - /* lock in msr value */ era->config = reg->config; era->reg = reg->reg; @@ -1213,17 +1180,17 @@ __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, /* one more user */ atomic_inc(&era->ref); + /* no need to reallocate during incremental event scheduling */ + reg->alloc = 1; + /* * need to call x86_get_event_constraint() * to check if associated event has constraints */ c = NULL; - } else { - idx = intel_alt_er(idx); - if (idx != reg->idx) { - raw_spin_unlock_irqrestore(&era->lock, flags); - goto again; - } + } else if (intel_try_alt_er(event, orig_idx)) { + raw_spin_unlock_irqrestore(&era->lock, flags); + goto again; } raw_spin_unlock_irqrestore(&era->lock, flags); @@ -1237,14 +1204,11 @@ __intel_shared_reg_put_constraints(struct cpu_hw_events *cpuc, struct er_account *era; /* - * Only put constraint if extra reg was actually allocated. Also takes - * care of event which do not use an extra shared reg. - * - * Also, if this is a fake cpuc we shouldn't touch any event state - * (reg->alloc) and we don't care about leaving inconsistent cpuc state - * either since it'll be thrown out. + * only put constraint if extra reg was actually + * allocated. Also takes care of event which do + * not use an extra shared reg */ - if (!reg->alloc || cpuc->is_fake) + if (!reg->alloc) return; era = &cpuc->shared_regs->regs[reg->idx]; @@ -1336,9 +1300,15 @@ static void intel_put_event_constraints(struct cpu_hw_events *cpuc, intel_put_shared_regs_event_constraints(cpuc, event); } -static void intel_pebs_aliases_core2(struct perf_event *event) +static int intel_pmu_hw_config(struct perf_event *event) { - if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { + int ret = x86_pmu_hw_config(event); + + if (ret) + return ret; + + if (event->attr.precise_ip && + (event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { /* * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P * (0x003c) so that we can use it with PEBS. @@ -1359,48 +1329,10 @@ static void intel_pebs_aliases_core2(struct perf_event *event) */ u64 alt_config = X86_CONFIG(.event=0xc0, .inv=1, .cmask=16); - alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK); - event->hw.config = alt_config; - } -} - -static void intel_pebs_aliases_snb(struct perf_event *event) -{ - if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { - /* - * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P - * (0x003c) so that we can use it with PEBS. - * - * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't - * PEBS capable. However we can use UOPS_RETIRED.ALL - * (0x01c2), which is a PEBS capable event, to get the same - * count. - * - * UOPS_RETIRED.ALL counts the number of cycles that retires - * CNTMASK micro-ops. By setting CNTMASK to a value (16) - * larger than the maximum number of micro-ops that can be - * retired per cycle (4) and then inverting the condition, we - * count all cycles that retire 16 or less micro-ops, which - * is every cycle. - * - * Thereby we gain a PEBS capable cycle counter. - */ - u64 alt_config = X86_CONFIG(.event=0xc2, .umask=0x01, .inv=1, .cmask=16); alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK); event->hw.config = alt_config; } -} - -static int intel_pmu_hw_config(struct perf_event *event) -{ - int ret = x86_pmu_hw_config(event); - - if (ret) - return ret; - - if (event->attr.precise_ip && x86_pmu.pebs_aliases) - x86_pmu.pebs_aliases(event); if (intel_pmu_needs_lbr_smpl(event)) { ret = intel_pmu_setup_lbr_filter(event); @@ -1675,7 +1607,6 @@ static __initconst const struct x86_pmu intel_pmu = { .max_period = (1ULL << 31) - 1, .get_event_constraints = intel_get_event_constraints, .put_event_constraints = intel_put_event_constraints, - .pebs_aliases = intel_pebs_aliases_core2, .format_attrs = intel_arch3_formats_attr, @@ -1909,9 +1840,8 @@ __init int intel_pmu_init(void) break; case 42: /* SandyBridge */ - case 45: /* SandyBridge, "Romely-EP" */ x86_add_quirk(intel_sandybridge_quirk); - case 58: /* IvyBridge */ + case 45: /* SandyBridge, "Romely-EP" */ memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); @@ -1919,7 +1849,6 @@ __init int intel_pmu_init(void) x86_pmu.event_constraints = intel_snb_event_constraints; x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints; - x86_pmu.pebs_aliases = intel_pebs_aliases_snb; x86_pmu.extra_regs = intel_snb_extra_regs; /* all extra regs are per-cpu when HT is on */ x86_pmu.er_flags |= ERF_HAS_RSP_1; diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c index 35e2192df9f4..5a3edc27f6e5 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -400,7 +400,14 @@ struct event_constraint intel_snb_pebs_event_constraints[] = { INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.* */ - INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ + INTEL_UEVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */ + INTEL_UEVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */ + INTEL_UEVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */ + INTEL_UEVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */ + INTEL_UEVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */ + INTEL_UEVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */ + INTEL_UEVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */ + INTEL_UEVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */ INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ INTEL_UEVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */ diff --git a/trunk/arch/x86/kernel/kvmclock.c b/trunk/arch/x86/kernel/kvmclock.c index f1b42b3a186c..086eb58c6e80 100644 --- a/trunk/arch/x86/kernel/kvmclock.c +++ b/trunk/arch/x86/kernel/kvmclock.c @@ -120,6 +120,11 @@ bool kvm_check_and_clear_guest_paused(void) bool ret = false; struct pvclock_vcpu_time_info *src; + /* + * per_cpu() is safe here because this function is only called from + * timer functions where preemption is already disabled. + */ + WARN_ON(!in_atomic()); src = &__get_cpu_var(hv_clock); if ((src->flags & PVCLOCK_GUEST_STOPPED) != 0) { __this_cpu_and(hv_clock.flags, ~PVCLOCK_GUEST_STOPPED); diff --git a/trunk/arch/x86/kernel/nmi_selftest.c b/trunk/arch/x86/kernel/nmi_selftest.c index 149b8d9c6ad4..e31bf8d5c4d2 100644 --- a/trunk/arch/x86/kernel/nmi_selftest.c +++ b/trunk/arch/x86/kernel/nmi_selftest.c @@ -42,7 +42,7 @@ static int __init nmi_unk_cb(unsigned int val, struct pt_regs *regs) static void __init init_nmi_testsuite(void) { /* trap all the unknown NMIs we may generate */ - register_nmi_handler_initonly(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk"); + register_nmi_handler(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk"); } static void __init cleanup_nmi_testsuite(void) @@ -64,7 +64,7 @@ static void __init test_nmi_ipi(struct cpumask *mask) { unsigned long timeout; - if (register_nmi_handler_initonly(NMI_LOCAL, test_nmi_ipi_callback, + if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback, NMI_FLAG_FIRST, "nmi_selftest")) { nmi_fail = FAILURE; return; diff --git a/trunk/arch/x86/kernel/reboot.c b/trunk/arch/x86/kernel/reboot.c index 25b48edb847c..79c45af81604 100644 --- a/trunk/arch/x86/kernel/reboot.c +++ b/trunk/arch/x86/kernel/reboot.c @@ -639,11 +639,9 @@ void native_machine_shutdown(void) set_cpus_allowed_ptr(current, cpumask_of(reboot_cpu_id)); /* - * O.K Now that I'm on the appropriate processor, stop all of the - * others. Also disable the local irq to not receive the per-cpu - * timer interrupt which may trigger scheduler's load balance. + * O.K Now that I'm on the appropriate processor, + * stop all of the others. */ - local_irq_disable(); stop_other_cpus(); #endif diff --git a/trunk/arch/x86/kernel/smpboot.c b/trunk/arch/x86/kernel/smpboot.c index 3fab55bea29b..f56f96da77f5 100644 --- a/trunk/arch/x86/kernel/smpboot.c +++ b/trunk/arch/x86/kernel/smpboot.c @@ -382,15 +382,6 @@ void __cpuinit set_cpu_sibling_map(int cpu) if ((i == cpu) || (has_mc && match_llc(c, o))) link_mask(llc_shared, cpu, i); - } - - /* - * This needs a separate iteration over the cpus because we rely on all - * cpu_sibling_mask links to be set-up. - */ - for_each_cpu(i, cpu_sibling_setup_mask) { - o = &cpu_data(i); - if ((i == cpu) || (has_mc && match_mc(c, o))) { link_mask(core, cpu, i); @@ -419,7 +410,15 @@ void __cpuinit set_cpu_sibling_map(int cpu) /* maps the cpu to the sched domain representing multi-core */ const struct cpumask *cpu_coregroup_mask(int cpu) { - return cpu_llc_shared_mask(cpu); + struct cpuinfo_x86 *c = &cpu_data(cpu); + /* + * For perf, we return last level cache shared map. + * And for power savings, we return cpu_core_map + */ + if (!(cpu_has(c, X86_FEATURE_AMD_DCM))) + return cpu_core_mask(cpu); + else + return cpu_llc_shared_mask(cpu); } static void impress_friends(void) diff --git a/trunk/arch/x86/lib/usercopy.c b/trunk/arch/x86/lib/usercopy.c index 677b1ed184c9..f61ee67ec00f 100644 --- a/trunk/arch/x86/lib/usercopy.c +++ b/trunk/arch/x86/lib/usercopy.c @@ -8,7 +8,6 @@ #include #include -#include /* * best effort, GUP based copy_from_user() that is NMI-safe @@ -22,9 +21,6 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) void *map; int ret; - if (__range_not_ok(from, n, TASK_SIZE) == 0) - return len; - do { ret = __get_user_pages_fast(addr, 1, 0, &page); if (!ret) diff --git a/trunk/arch/x86/lib/x86-opcode-map.txt b/trunk/arch/x86/lib/x86-opcode-map.txt index 5d7e51f3fd28..819137904428 100644 --- a/trunk/arch/x86/lib/x86-opcode-map.txt +++ b/trunk/arch/x86/lib/x86-opcode-map.txt @@ -28,7 +28,7 @@ # - (66): the last prefix is 0x66 # - (F3): the last prefix is 0xF3 # - (F2): the last prefix is 0xF2 -# - (!F3) : the last prefix is not 0xF3 (including non-last prefix case) +# Table: one byte opcode Referrer: @@ -515,12 +515,12 @@ b4: LFS Gv,Mp b5: LGS Gv,Mp b6: MOVZX Gv,Eb b7: MOVZX Gv,Ew -b8: JMPE (!F3) | POPCNT Gv,Ev (F3) +b8: JMPE | POPCNT Gv,Ev (F3) b9: Grp10 (1A) ba: Grp8 Ev,Ib (1A) bb: BTC Ev,Gv -bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3) -bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3) +bc: BSF Gv,Ev | TZCNT Gv,Ev (F3) +bd: BSR Gv,Ev | LZCNT Gv,Ev (F3) be: MOVSX Gv,Eb bf: MOVSX Gv,Ew # 0x0f 0xc0-0xcf diff --git a/trunk/arch/x86/mm/init.c b/trunk/arch/x86/mm/init.c index bc4e9d84157f..97141c26a13a 100644 --- a/trunk/arch/x86/mm/init.c +++ b/trunk/arch/x86/mm/init.c @@ -62,8 +62,7 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en extra += PMD_SIZE; #endif /* The first 2/4M doesn't use large pages. */ - if (mr->start < PMD_SIZE) - extra += mr->end - mr->start; + extra += mr->end - mr->start; ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; } else diff --git a/trunk/arch/x86/mm/srat.c b/trunk/arch/x86/mm/srat.c index 4599c3e8bcb6..732af3a96183 100644 --- a/trunk/arch/x86/mm/srat.c +++ b/trunk/arch/x86/mm/srat.c @@ -176,8 +176,6 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) return; } - node_set(node, numa_nodes_parsed); - printk(KERN_INFO "SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n", node, pxm, (unsigned long long) start, (unsigned long long) end - 1); diff --git a/trunk/arch/x86/platform/mrst/mrst.c b/trunk/arch/x86/platform/mrst/mrst.c index fd41a9262d65..e31bcd8f2eee 100644 --- a/trunk/arch/x86/platform/mrst/mrst.c +++ b/trunk/arch/x86/platform/mrst/mrst.c @@ -782,7 +782,7 @@ BLOCKING_NOTIFIER_HEAD(intel_scu_notifier); EXPORT_SYMBOL_GPL(intel_scu_notifier); /* Called by IPC driver */ -void __devinit intel_scu_devices_create(void) +void intel_scu_devices_create(void) { int i; diff --git a/trunk/arch/x86/platform/uv/tlb_uv.c b/trunk/arch/x86/platform/uv/tlb_uv.c index 59880afa851f..3ae0e61abd23 100644 --- a/trunk/arch/x86/platform/uv/tlb_uv.c +++ b/trunk/arch/x86/platform/uv/tlb_uv.c @@ -1295,6 +1295,7 @@ static void __init enable_timeouts(void) */ mmr_image |= (1L << SOFTACK_MSHIFT); if (is_uv2_hub()) { + mmr_image &= ~(1L << UV2_LEG_SHFT); mmr_image |= (1L << UV2_EXT_SHFT); } write_mmr_misc_control(pnode, mmr_image); diff --git a/trunk/arch/x86/tools/gen-insn-attr-x86.awk b/trunk/arch/x86/tools/gen-insn-attr-x86.awk index ddcf39b1a18d..5f6a5b6c3a15 100644 --- a/trunk/arch/x86/tools/gen-insn-attr-x86.awk +++ b/trunk/arch/x86/tools/gen-insn-attr-x86.awk @@ -66,10 +66,9 @@ BEGIN { rex_expr = "^REX(\\.[XRWB]+)*" fpu_expr = "^ESC" # TODO - lprefix1_expr = "\\((66|!F3)\\)" + lprefix1_expr = "\\(66\\)" lprefix2_expr = "\\(F3\\)" - lprefix3_expr = "\\((F2|!F3)\\)" - lprefix_expr = "\\((66|F2|F3)\\)" + lprefix3_expr = "\\(F2\\)" max_lprefix = 4 # All opcodes starting with lower-case 'v' or with (v1) superscript @@ -334,16 +333,13 @@ function convert_operands(count,opnd, i,j,imm,mod) if (match(ext, lprefix1_expr)) { lptable1[idx] = add_flags(lptable1[idx],flags) variant = "INAT_VARIANT" - } - if (match(ext, lprefix2_expr)) { + } else if (match(ext, lprefix2_expr)) { lptable2[idx] = add_flags(lptable2[idx],flags) variant = "INAT_VARIANT" - } - if (match(ext, lprefix3_expr)) { + } else if (match(ext, lprefix3_expr)) { lptable3[idx] = add_flags(lptable3[idx],flags) variant = "INAT_VARIANT" - } - if (!match(ext, lprefix_expr)){ + } else { table[idx] = add_flags(table[idx],flags) } } diff --git a/trunk/arch/xtensa/include/asm/syscall.h b/trunk/arch/xtensa/include/asm/syscall.h index c1dacca312f3..0b9f2e13c781 100644 --- a/trunk/arch/xtensa/include/asm/syscall.h +++ b/trunk/arch/xtensa/include/asm/syscall.h @@ -31,5 +31,5 @@ asmlinkage long sys_pselect6(int n, fd_set __user *inp, fd_set __user *outp, asmlinkage long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds, struct timespec __user *tsp, const sigset_t __user *sigmask, size_t sigsetsize); -asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, - size_t sigsetsize); + + diff --git a/trunk/arch/xtensa/kernel/signal.c b/trunk/arch/xtensa/kernel/signal.c index efe4e854b3cd..b9f8e5850d3a 100644 --- a/trunk/arch/xtensa/kernel/signal.c +++ b/trunk/arch/xtensa/kernel/signal.c @@ -493,7 +493,7 @@ static void do_signal(struct pt_regs *regs) if (ret) return; - signal_delivered(signr, &info, &ka, regs, 0); + signal_delivered(signr, info, ka, regs, 0); if (current->ptrace & PT_SINGLESTEP) task_pt_regs(current)->icountlevel = 1; diff --git a/trunk/drivers/acpi/Kconfig b/trunk/drivers/acpi/Kconfig index 80998958cf45..47768ff87343 100644 --- a/trunk/drivers/acpi/Kconfig +++ b/trunk/drivers/acpi/Kconfig @@ -208,7 +208,7 @@ config ACPI_IPMI config ACPI_HOTPLUG_CPU bool - depends on EXPERIMENTAL && ACPI_PROCESSOR && HOTPLUG_CPU + depends on ACPI_PROCESSOR && HOTPLUG_CPU select ACPI_CONTAINER default y diff --git a/trunk/drivers/acpi/battery.c b/trunk/drivers/acpi/battery.c index 7dd3f9fb9f3f..86933ca8b472 100644 --- a/trunk/drivers/acpi/battery.c +++ b/trunk/drivers/acpi/battery.c @@ -643,19 +643,11 @@ static int acpi_battery_update(struct acpi_battery *battery) static void acpi_battery_refresh(struct acpi_battery *battery) { - int power_unit; - if (!battery->bat.dev) return; - power_unit = battery->power_unit; - acpi_battery_get_info(battery); - - if (power_unit == battery->power_unit) - return; - - /* The battery has changed its reporting units. */ + /* The battery may have changed its reporting units. */ sysfs_remove_battery(battery); sysfs_add_battery(battery); } diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index adceafda9c17..3188da3df8da 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -182,66 +182,41 @@ EXPORT_SYMBOL(acpi_bus_get_private_data); Power Management -------------------------------------------------------------------------- */ -static const char *state_string(int state) -{ - switch (state) { - case ACPI_STATE_D0: - return "D0"; - case ACPI_STATE_D1: - return "D1"; - case ACPI_STATE_D2: - return "D2"; - case ACPI_STATE_D3_HOT: - return "D3hot"; - case ACPI_STATE_D3_COLD: - return "D3"; - default: - return "(unknown)"; - } -} - static int __acpi_bus_get_power(struct acpi_device *device, int *state) { - int result = ACPI_STATE_UNKNOWN; + int result = 0; + acpi_status status = 0; + unsigned long long psc = 0; if (!device || !state) return -EINVAL; - if (!device->flags.power_manageable) { + *state = ACPI_STATE_UNKNOWN; + + if (device->flags.power_manageable) { + /* + * Get the device's power state either directly (via _PSC) or + * indirectly (via power resources). + */ + if (device->power.flags.power_resources) { + result = acpi_power_get_inferred_state(device, state); + if (result) + return result; + } else if (device->power.flags.explicit_get) { + status = acpi_evaluate_integer(device->handle, "_PSC", + NULL, &psc); + if (ACPI_FAILURE(status)) + return -ENODEV; + *state = (int)psc; + } + } else { /* TBD: Non-recursive algorithm for walking up hierarchy. */ *state = device->parent ? device->parent->power.state : ACPI_STATE_D0; - goto out; - } - - /* - * Get the device's power state either directly (via _PSC) or - * indirectly (via power resources). - */ - if (device->power.flags.explicit_get) { - unsigned long long psc; - acpi_status status = acpi_evaluate_integer(device->handle, - "_PSC", NULL, &psc); - if (ACPI_FAILURE(status)) - return -ENODEV; - - result = psc; - } - /* The test below covers ACPI_STATE_UNKNOWN too. */ - if (result <= ACPI_STATE_D2) { - ; /* Do nothing. */ - } else if (device->power.flags.power_resources) { - int error = acpi_power_get_inferred_state(device, &result); - if (error) - return error; - } else if (result == ACPI_STATE_D3_HOT) { - result = ACPI_STATE_D3; } - *state = result; - out: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is %s\n", - device->pnp.bus_id, state_string(*state))); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n", + device->pnp.bus_id, *state)); return 0; } @@ -259,14 +234,13 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) /* Make sure this is a valid target state */ if (state == device->power.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n", - state_string(state))); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n", + state)); return 0; } if (!device->power.states[state].flags.valid) { - printk(KERN_WARNING PREFIX "Device does not support %s\n", - state_string(state)); + printk(KERN_WARNING PREFIX "Device does not support D%d\n", state); return -ENODEV; } if (device->parent && (state < device->parent->power.state)) { @@ -320,13 +294,13 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state) end: if (result) printk(KERN_WARNING PREFIX - "Device [%s] failed to transition to %s\n", - device->pnp.bus_id, state_string(state)); + "Device [%s] failed to transition to D%d\n", + device->pnp.bus_id, state); else { device->power.state = state; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device [%s] transitioned to %s\n", - device->pnp.bus_id, state_string(state))); + "Device [%s] transitioned to D%d\n", + device->pnp.bus_id, state)); } return result; diff --git a/trunk/drivers/acpi/power.c b/trunk/drivers/acpi/power.c index dd6d6a3c6780..0500f719f63e 100644 --- a/trunk/drivers/acpi/power.c +++ b/trunk/drivers/acpi/power.c @@ -631,7 +631,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state) * We know a device's inferred power state when all the resources * required for a given D-state are 'on'. */ - for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) { + for (i = ACPI_STATE_D0; i < ACPI_STATE_D3_HOT; i++) { list = &device->power.states[i].resources; if (list->count < 1) continue; diff --git a/trunk/drivers/acpi/processor_perflib.c b/trunk/drivers/acpi/processor_perflib.c index a093dc163a42..0af48a8554cd 100644 --- a/trunk/drivers/acpi/processor_perflib.c +++ b/trunk/drivers/acpi/processor_perflib.c @@ -333,7 +333,6 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) struct acpi_buffer state = { 0, NULL }; union acpi_object *pss = NULL; int i; - int last_invalid = -1; status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); @@ -395,33 +394,14 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) ((u32)(px->core_frequency * 1000) != (px->core_frequency * 1000))) { printk(KERN_ERR FW_BUG PREFIX - "Invalid BIOS _PSS frequency found for processor %d: 0x%llx MHz\n", - pr->id, px->core_frequency); - if (last_invalid == -1) - last_invalid = i; - } else { - if (last_invalid != -1) { - /* - * Copy this valid entry over last_invalid entry - */ - memcpy(&(pr->performance->states[last_invalid]), - px, sizeof(struct acpi_processor_px)); - ++last_invalid; - } + "Invalid BIOS _PSS frequency: 0x%llx MHz\n", + px->core_frequency); + result = -EFAULT; + kfree(pr->performance->states); + goto end; } } - if (last_invalid == 0) { - printk(KERN_ERR FW_BUG PREFIX - "No valid BIOS _PSS frequency found for processor %d\n", pr->id); - result = -EFAULT; - kfree(pr->performance->states); - pr->performance->states = NULL; - } - - if (last_invalid > 0) - pr->performance->state_count = last_invalid; - end: kfree(buffer.pointer); diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index c8a1f3b68110..85cbfdccc97c 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -1567,7 +1567,6 @@ static int acpi_bus_scan_fixed(void) ACPI_BUS_TYPE_POWER_BUTTON, ACPI_STA_DEFAULT, &ops); - device_init_wakeup(&device->dev, true); } if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) { diff --git a/trunk/drivers/acpi/sleep.c b/trunk/drivers/acpi/sleep.c index 88561029cca8..74ee4ab577b6 100644 --- a/trunk/drivers/acpi/sleep.c +++ b/trunk/drivers/acpi/sleep.c @@ -57,7 +57,6 @@ MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); static u8 sleep_states[ACPI_S_STATE_COUNT]; -static bool pwr_btn_event_pending; static void acpi_sleep_tts_switch(u32 acpi_state) { @@ -185,14 +184,6 @@ static int acpi_pm_prepare(void) return error; } -static int find_powerf_dev(struct device *dev, void *data) -{ - struct acpi_device *device = to_acpi_device(dev); - const char *hid = acpi_device_hid(device); - - return !strcmp(hid, ACPI_BUTTON_HID_POWERF); -} - /** * acpi_pm_finish - Instruct the platform to leave a sleep state. * @@ -201,7 +192,6 @@ static int find_powerf_dev(struct device *dev, void *data) */ static void acpi_pm_finish(void) { - struct device *pwr_btn_dev; u32 acpi_state = acpi_target_sleep_state; acpi_ec_unblock_transactions(); @@ -219,23 +209,6 @@ static void acpi_pm_finish(void) acpi_set_firmware_waking_vector((acpi_physical_address) 0); acpi_target_sleep_state = ACPI_STATE_S0; - - /* If we were woken with the fixed power button, provide a small - * hint to userspace in the form of a wakeup event on the fixed power - * button device (if it can be found). - * - * We delay the event generation til now, as the PM layer requires - * timekeeping to be running before we generate events. */ - if (!pwr_btn_event_pending) - return; - - pwr_btn_event_pending = false; - pwr_btn_dev = bus_find_device(&acpi_bus_type, NULL, NULL, - find_powerf_dev); - if (pwr_btn_dev) { - pm_wakeup_event(pwr_btn_dev, 0); - put_device(pwr_btn_dev); - } } /** @@ -325,23 +298,9 @@ static int acpi_suspend_enter(suspend_state_t pm_state) /* ACPI 3.0 specs (P62) says that it's the responsibility * of the OSPM to clear the status bit [ implying that the * POWER_BUTTON event should not reach userspace ] - * - * However, we do generate a small hint for userspace in the form of - * a wakeup event. We flag this condition for now and generate the - * event later, as we're currently too early in resume to be able to - * generate wakeup events. */ - if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) { - acpi_event_status pwr_btn_status; - - acpi_get_event_status(ACPI_EVENT_POWER_BUTTON, &pwr_btn_status); - - if (pwr_btn_status & ACPI_EVENT_FLAG_SET) { - acpi_clear_event(ACPI_EVENT_POWER_BUTTON); - /* Flag for later */ - pwr_btn_event_pending = true; - } - } + if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3)) + acpi_clear_event(ACPI_EVENT_POWER_BUTTON); /* * Disable and clear GPE status before interrupt is enabled. Some GPEs @@ -771,8 +730,8 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) * can wake the system. _S0W may be valid, too. */ if (acpi_target_sleep_state == ACPI_STATE_S0 || - (device_may_wakeup(dev) && adev->wakeup.flags.valid && - adev->wakeup.sleep_state >= acpi_target_sleep_state)) { + (device_may_wakeup(dev) && + adev->wakeup.sleep_state <= acpi_target_sleep_state)) { acpi_status status; acpi_method[3] = 'W'; diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index a576575617d7..9577b6fa2650 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -1687,6 +1687,10 @@ static int acpi_video_bus_add(struct acpi_device *device) set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); set_bit(KEY_DISPLAY_OFF, input->keybit); + error = input_register_device(input); + if (error) + goto err_stop_video; + printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), video->flags.multihead ? "yes" : "no", @@ -1697,16 +1701,12 @@ static int acpi_video_bus_add(struct acpi_device *device) video->pm_nb.priority = 0; error = register_pm_notifier(&video->pm_nb); if (error) - goto err_stop_video; - - error = input_register_device(input); - if (error) - goto err_unregister_pm_notifier; + goto err_unregister_input_dev; return 0; - err_unregister_pm_notifier: - unregister_pm_notifier(&video->pm_nb); + err_unregister_input_dev: + input_unregister_device(input); err_stop_video: acpi_video_bus_stop_devices(video); err_free_input_dev: @@ -1743,18 +1743,9 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) return 0; } -static int __init is_i740(struct pci_dev *dev) -{ - if (dev->device == 0x00D1) - return 1; - if (dev->device == 0x7000) - return 1; - return 0; -} - static int __init intel_opregion_present(void) { - int opregion = 0; +#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) struct pci_dev *dev = NULL; u32 address; @@ -1763,15 +1754,13 @@ static int __init intel_opregion_present(void) continue; if (dev->vendor != PCI_VENDOR_ID_INTEL) continue; - /* We don't want to poke around undefined i740 registers */ - if (is_i740(dev)) - continue; pci_read_config_dword(dev, 0xfc, &address); if (!address) continue; - opregion = 1; + return 1; } - return opregion; +#endif + return 0; } int acpi_video_register(void) diff --git a/trunk/drivers/base/regmap/regmap.c b/trunk/drivers/base/regmap/regmap.c index c89aa01fb1de..0bcda488f11c 100644 --- a/trunk/drivers/base/regmap/regmap.c +++ b/trunk/drivers/base/regmap/regmap.c @@ -246,11 +246,11 @@ struct regmap *regmap_init(struct device *dev, map->lock = regmap_lock_mutex; map->unlock = regmap_unlock_mutex; } + map->format.buf_size = (config->reg_bits + config->val_bits) / 8; map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); map->format.pad_bytes = config->pad_bits / 8; map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); - map->format.buf_size = DIV_ROUND_UP(config->reg_bits + - config->val_bits + config->pad_bits, 8); + map->format.buf_size += map->format.pad_bytes; map->reg_shift = config->pad_bits % 8; if (config->reg_stride) map->reg_stride = config->reg_stride; @@ -368,7 +368,7 @@ struct regmap *regmap_init(struct device *dev, ret = regcache_init(map, config); if (ret < 0) - goto err_debugfs; + goto err_free_workbuf; /* Add a devres resource for dev_get_regmap() */ m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL); @@ -383,8 +383,7 @@ struct regmap *regmap_init(struct device *dev, err_cache: regcache_exit(map); -err_debugfs: - regmap_debugfs_exit(map); +err_free_workbuf: kfree(map->work_buf); err_map: kfree(map); @@ -472,7 +471,6 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) return ret; } -EXPORT_SYMBOL_GPL(regmap_reinit_cache); /** * regmap_exit(): Free a previously allocated register map diff --git a/trunk/drivers/bcma/driver_pci.c b/trunk/drivers/bcma/driver_pci.c index c32ebd537abe..9a96f14c8f47 100644 --- a/trunk/drivers/bcma/driver_pci.c +++ b/trunk/drivers/bcma/driver_pci.c @@ -232,19 +232,17 @@ void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core, bool enable) { - struct pci_dev *pdev; + struct pci_dev *pdev = pc->core->bus->host_pci; u32 coremask, tmp; int err = 0; - if (!pc || core->bus->hosttype != BCMA_HOSTTYPE_PCI) { + if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) { /* This bcma device is not on a PCI host-bus. So the IRQs are * not routed through the PCI core. * So we must not enable routing through the PCI core. */ goto out; } - pdev = pc->core->bus->host_pci; - err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); if (err) goto out; diff --git a/trunk/drivers/char/agp/intel-agp.c b/trunk/drivers/char/agp/intel-agp.c index 0a4185279417..764f70c5e690 100644 --- a/trunk/drivers/char/agp/intel-agp.c +++ b/trunk/drivers/char/agp/intel-agp.c @@ -898,7 +898,6 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_B43_HB), ID(PCI_DEVICE_ID_INTEL_B43_1_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), - ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), diff --git a/trunk/drivers/char/agp/intel-agp.h b/trunk/drivers/char/agp/intel-agp.h index 8e2d9140f300..c0091753a0d1 100644 --- a/trunk/drivers/char/agp/intel-agp.h +++ b/trunk/drivers/char/agp/intel-agp.h @@ -212,7 +212,6 @@ #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 -#define PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB 0x0069 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 diff --git a/trunk/drivers/char/hw_random/atmel-rng.c b/trunk/drivers/char/hw_random/atmel-rng.c index 6289f0eee24c..f518b99f53f5 100644 --- a/trunk/drivers/char/hw_random/atmel-rng.c +++ b/trunk/drivers/char/hw_random/atmel-rng.c @@ -36,13 +36,6 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max, /* data ready? */ if (readl(trng->base + TRNG_ODATA) & 1) { *data = readl(trng->base + TRNG_ODATA); - /* - ensure data ready is only set again AFTER the next data - word is ready in case it got set between checking ISR - and reading ODATA, so we don't risk re-reading the - same word - */ - readl(trng->base + TRNG_ISR); return 4; } else return 0; diff --git a/trunk/drivers/clocksource/Makefile b/trunk/drivers/clocksource/Makefile index dd3e661a124d..8d81a1d32653 100644 --- a/trunk/drivers/clocksource/Makefile +++ b/trunk/drivers/clocksource/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += cs5535-clockevt.o obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o -obj-$(CONFIG_EM_TIMER_STI) += em_sti.o obj-$(CONFIG_CLKBLD_I8253) += i8253.o obj-$(CONFIG_CLKSRC_MMIO) += mmio.o obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o diff --git a/trunk/drivers/clocksource/em_sti.c b/trunk/drivers/clocksource/em_sti.c deleted file mode 100644 index 372051d1bba8..000000000000 --- a/trunk/drivers/clocksource/em_sti.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Emma Mobile Timer Support - STI - * - * Copyright (C) 2012 Magnus Damm - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { USER_CLOCKSOURCE, USER_CLOCKEVENT, USER_NR }; - -struct em_sti_priv { - void __iomem *base; - struct clk *clk; - struct platform_device *pdev; - unsigned int active[USER_NR]; - unsigned long rate; - raw_spinlock_t lock; - struct clock_event_device ced; - struct clocksource cs; -}; - -#define STI_CONTROL 0x00 -#define STI_COMPA_H 0x10 -#define STI_COMPA_L 0x14 -#define STI_COMPB_H 0x18 -#define STI_COMPB_L 0x1c -#define STI_COUNT_H 0x20 -#define STI_COUNT_L 0x24 -#define STI_COUNT_RAW_H 0x28 -#define STI_COUNT_RAW_L 0x2c -#define STI_SET_H 0x30 -#define STI_SET_L 0x34 -#define STI_INTSTATUS 0x40 -#define STI_INTRAWSTATUS 0x44 -#define STI_INTENSET 0x48 -#define STI_INTENCLR 0x4c -#define STI_INTFFCLR 0x50 - -static inline unsigned long em_sti_read(struct em_sti_priv *p, int offs) -{ - return ioread32(p->base + offs); -} - -static inline void em_sti_write(struct em_sti_priv *p, int offs, - unsigned long value) -{ - iowrite32(value, p->base + offs); -} - -static int em_sti_enable(struct em_sti_priv *p) -{ - int ret; - - /* enable clock */ - ret = clk_enable(p->clk); - if (ret) { - dev_err(&p->pdev->dev, "cannot enable clock\n"); - return ret; - } - - /* configure channel, periodic mode and maximum timeout */ - p->rate = clk_get_rate(p->clk); - - /* reset the counter */ - em_sti_write(p, STI_SET_H, 0x40000000); - em_sti_write(p, STI_SET_L, 0x00000000); - - /* mask and clear pending interrupts */ - em_sti_write(p, STI_INTENCLR, 3); - em_sti_write(p, STI_INTFFCLR, 3); - - /* enable updates of counter registers */ - em_sti_write(p, STI_CONTROL, 1); - - return 0; -} - -static void em_sti_disable(struct em_sti_priv *p) -{ - /* mask interrupts */ - em_sti_write(p, STI_INTENCLR, 3); - - /* stop clock */ - clk_disable(p->clk); -} - -static cycle_t em_sti_count(struct em_sti_priv *p) -{ - cycle_t ticks; - unsigned long flags; - - /* the STI hardware buffers the 48-bit count, but to - * break it out into two 32-bit access the registers - * must be accessed in a certain order. - * Always read STI_COUNT_H before STI_COUNT_L. - */ - raw_spin_lock_irqsave(&p->lock, flags); - ticks = (cycle_t)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32; - ticks |= em_sti_read(p, STI_COUNT_L); - raw_spin_unlock_irqrestore(&p->lock, flags); - - return ticks; -} - -static cycle_t em_sti_set_next(struct em_sti_priv *p, cycle_t next) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&p->lock, flags); - - /* mask compare A interrupt */ - em_sti_write(p, STI_INTENCLR, 1); - - /* update compare A value */ - em_sti_write(p, STI_COMPA_H, next >> 32); - em_sti_write(p, STI_COMPA_L, next & 0xffffffff); - - /* clear compare A interrupt source */ - em_sti_write(p, STI_INTFFCLR, 1); - - /* unmask compare A interrupt */ - em_sti_write(p, STI_INTENSET, 1); - - raw_spin_unlock_irqrestore(&p->lock, flags); - - return next; -} - -static irqreturn_t em_sti_interrupt(int irq, void *dev_id) -{ - struct em_sti_priv *p = dev_id; - - p->ced.event_handler(&p->ced); - return IRQ_HANDLED; -} - -static int em_sti_start(struct em_sti_priv *p, unsigned int user) -{ - unsigned long flags; - int used_before; - int ret = 0; - - raw_spin_lock_irqsave(&p->lock, flags); - used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; - if (!used_before) - ret = em_sti_enable(p); - - if (!ret) - p->active[user] = 1; - raw_spin_unlock_irqrestore(&p->lock, flags); - - return ret; -} - -static void em_sti_stop(struct em_sti_priv *p, unsigned int user) -{ - unsigned long flags; - int used_before, used_after; - - raw_spin_lock_irqsave(&p->lock, flags); - used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; - p->active[user] = 0; - used_after = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; - - if (used_before && !used_after) - em_sti_disable(p); - raw_spin_unlock_irqrestore(&p->lock, flags); -} - -static struct em_sti_priv *cs_to_em_sti(struct clocksource *cs) -{ - return container_of(cs, struct em_sti_priv, cs); -} - -static cycle_t em_sti_clocksource_read(struct clocksource *cs) -{ - return em_sti_count(cs_to_em_sti(cs)); -} - -static int em_sti_clocksource_enable(struct clocksource *cs) -{ - int ret; - struct em_sti_priv *p = cs_to_em_sti(cs); - - ret = em_sti_start(p, USER_CLOCKSOURCE); - if (!ret) - __clocksource_updatefreq_hz(cs, p->rate); - return ret; -} - -static void em_sti_clocksource_disable(struct clocksource *cs) -{ - em_sti_stop(cs_to_em_sti(cs), USER_CLOCKSOURCE); -} - -static void em_sti_clocksource_resume(struct clocksource *cs) -{ - em_sti_clocksource_enable(cs); -} - -static int em_sti_register_clocksource(struct em_sti_priv *p) -{ - struct clocksource *cs = &p->cs; - - memset(cs, 0, sizeof(*cs)); - cs->name = dev_name(&p->pdev->dev); - cs->rating = 200; - cs->read = em_sti_clocksource_read; - cs->enable = em_sti_clocksource_enable; - cs->disable = em_sti_clocksource_disable; - cs->suspend = em_sti_clocksource_disable; - cs->resume = em_sti_clocksource_resume; - cs->mask = CLOCKSOURCE_MASK(48); - cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - - dev_info(&p->pdev->dev, "used as clock source\n"); - - /* Register with dummy 1 Hz value, gets updated in ->enable() */ - clocksource_register_hz(cs, 1); - return 0; -} - -static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced) -{ - return container_of(ced, struct em_sti_priv, ced); -} - -static void em_sti_clock_event_mode(enum clock_event_mode mode, - struct clock_event_device *ced) -{ - struct em_sti_priv *p = ced_to_em_sti(ced); - - /* deal with old setting first */ - switch (ced->mode) { - case CLOCK_EVT_MODE_ONESHOT: - em_sti_stop(p, USER_CLOCKEVENT); - break; - default: - break; - } - - switch (mode) { - case CLOCK_EVT_MODE_ONESHOT: - dev_info(&p->pdev->dev, "used for oneshot clock events\n"); - em_sti_start(p, USER_CLOCKEVENT); - clockevents_config(&p->ced, p->rate); - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - em_sti_stop(p, USER_CLOCKEVENT); - break; - default: - break; - } -} - -static int em_sti_clock_event_next(unsigned long delta, - struct clock_event_device *ced) -{ - struct em_sti_priv *p = ced_to_em_sti(ced); - cycle_t next; - int safe; - - next = em_sti_set_next(p, em_sti_count(p) + delta); - safe = em_sti_count(p) < (next - 1); - - return !safe; -} - -static void em_sti_register_clockevent(struct em_sti_priv *p) -{ - struct clock_event_device *ced = &p->ced; - - memset(ced, 0, sizeof(*ced)); - ced->name = dev_name(&p->pdev->dev); - ced->features = CLOCK_EVT_FEAT_ONESHOT; - ced->rating = 200; - ced->cpumask = cpumask_of(0); - ced->set_next_event = em_sti_clock_event_next; - ced->set_mode = em_sti_clock_event_mode; - - dev_info(&p->pdev->dev, "used for clock events\n"); - - /* Register with dummy 1 Hz value, gets updated in ->set_mode() */ - clockevents_config_and_register(ced, 1, 2, 0xffffffff); -} - -static int __devinit em_sti_probe(struct platform_device *pdev) -{ - struct em_sti_priv *p; - struct resource *res; - int irq, ret; - - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (p == NULL) { - dev_err(&pdev->dev, "failed to allocate driver data\n"); - ret = -ENOMEM; - goto err0; - } - - p->pdev = pdev; - platform_set_drvdata(pdev, p); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "failed to get I/O memory\n"); - ret = -EINVAL; - goto err0; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get irq\n"); - ret = -EINVAL; - goto err0; - } - - /* map memory, let base point to the STI instance */ - p->base = ioremap_nocache(res->start, resource_size(res)); - if (p->base == NULL) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); - ret = -ENXIO; - goto err0; - } - - /* get hold of clock */ - p->clk = clk_get(&pdev->dev, "sclk"); - if (IS_ERR(p->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); - ret = PTR_ERR(p->clk); - goto err1; - } - - if (request_irq(irq, em_sti_interrupt, - IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, - dev_name(&pdev->dev), p)) { - dev_err(&pdev->dev, "failed to request low IRQ\n"); - ret = -ENOENT; - goto err2; - } - - raw_spin_lock_init(&p->lock); - em_sti_register_clockevent(p); - em_sti_register_clocksource(p); - return 0; - -err2: - clk_put(p->clk); -err1: - iounmap(p->base); -err0: - kfree(p); - return ret; -} - -static int __devexit em_sti_remove(struct platform_device *pdev) -{ - return -EBUSY; /* cannot unregister clockevent and clocksource */ -} - -static const struct of_device_id em_sti_dt_ids[] __devinitconst = { - { .compatible = "renesas,em-sti", }, - {}, -}; -MODULE_DEVICE_TABLE(of, em_sti_dt_ids); - -static struct platform_driver em_sti_device_driver = { - .probe = em_sti_probe, - .remove = __devexit_p(em_sti_remove), - .driver = { - .name = "em_sti", - .of_match_table = em_sti_dt_ids, - } -}; - -module_platform_driver(em_sti_device_driver); - -MODULE_AUTHOR("Magnus Damm"); -MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/clocksource/sh_cmt.c b/trunk/drivers/clocksource/sh_cmt.c index 98b06baafcc6..32fe9ef5cc5c 100644 --- a/trunk/drivers/clocksource/sh_cmt.c +++ b/trunk/drivers/clocksource/sh_cmt.c @@ -48,13 +48,13 @@ struct sh_cmt_priv { unsigned long next_match_value; unsigned long max_match_value; unsigned long rate; - raw_spinlock_t lock; + spinlock_t lock; struct clock_event_device ced; struct clocksource cs; unsigned long total_cycles; }; -static DEFINE_RAW_SPINLOCK(sh_cmt_lock); +static DEFINE_SPINLOCK(sh_cmt_lock); #define CMSTR -1 /* shared register */ #define CMCSR 0 /* channel register */ @@ -139,7 +139,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) unsigned long flags, value; /* start stop register shared by multiple timer channels */ - raw_spin_lock_irqsave(&sh_cmt_lock, flags); + spin_lock_irqsave(&sh_cmt_lock, flags); value = sh_cmt_read(p, CMSTR); if (start) @@ -148,7 +148,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) value &= ~(1 << cfg->timer_bit); sh_cmt_write(p, CMSTR, value); - raw_spin_unlock_irqrestore(&sh_cmt_lock, flags); + spin_unlock_irqrestore(&sh_cmt_lock, flags); } static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) @@ -328,9 +328,9 @@ static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) { unsigned long flags; - raw_spin_lock_irqsave(&p->lock, flags); + spin_lock_irqsave(&p->lock, flags); __sh_cmt_set_next(p, delta); - raw_spin_unlock_irqrestore(&p->lock, flags); + spin_unlock_irqrestore(&p->lock, flags); } static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) @@ -385,7 +385,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag) int ret = 0; unsigned long flags; - raw_spin_lock_irqsave(&p->lock, flags); + spin_lock_irqsave(&p->lock, flags); if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) ret = sh_cmt_enable(p, &p->rate); @@ -398,7 +398,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag) if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT))) __sh_cmt_set_next(p, p->max_match_value); out: - raw_spin_unlock_irqrestore(&p->lock, flags); + spin_unlock_irqrestore(&p->lock, flags); return ret; } @@ -408,7 +408,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) unsigned long flags; unsigned long f; - raw_spin_lock_irqsave(&p->lock, flags); + spin_lock_irqsave(&p->lock, flags); f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE); p->flags &= ~flag; @@ -420,7 +420,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE)) __sh_cmt_set_next(p, p->max_match_value); - raw_spin_unlock_irqrestore(&p->lock, flags); + spin_unlock_irqrestore(&p->lock, flags); } static struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs) @@ -435,13 +435,13 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs) unsigned long value; int has_wrapped; - raw_spin_lock_irqsave(&p->lock, flags); + spin_lock_irqsave(&p->lock, flags); value = p->total_cycles; raw = sh_cmt_get_counter(p, &has_wrapped); if (unlikely(has_wrapped)) raw += p->match_value + 1; - raw_spin_unlock_irqrestore(&p->lock, flags); + spin_unlock_irqrestore(&p->lock, flags); return value + raw; } @@ -591,7 +591,7 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name, p->max_match_value = (1 << p->width) - 1; p->match_value = p->max_match_value; - raw_spin_lock_init(&p->lock); + spin_lock_init(&p->lock); if (clockevent_rating) sh_cmt_register_clockevent(p, name, clockevent_rating); diff --git a/trunk/drivers/clocksource/sh_mtu2.c b/trunk/drivers/clocksource/sh_mtu2.c index d9b76ca64a61..a2172f690418 100644 --- a/trunk/drivers/clocksource/sh_mtu2.c +++ b/trunk/drivers/clocksource/sh_mtu2.c @@ -43,7 +43,7 @@ struct sh_mtu2_priv { struct clock_event_device ced; }; -static DEFINE_RAW_SPINLOCK(sh_mtu2_lock); +static DEFINE_SPINLOCK(sh_mtu2_lock); #define TSTR -1 /* shared register */ #define TCR 0 /* channel register */ @@ -107,7 +107,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) unsigned long flags, value; /* start stop register shared by multiple timer channels */ - raw_spin_lock_irqsave(&sh_mtu2_lock, flags); + spin_lock_irqsave(&sh_mtu2_lock, flags); value = sh_mtu2_read(p, TSTR); if (start) @@ -116,7 +116,7 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) value &= ~(1 << cfg->timer_bit); sh_mtu2_write(p, TSTR, value); - raw_spin_unlock_irqrestore(&sh_mtu2_lock, flags); + spin_unlock_irqrestore(&sh_mtu2_lock, flags); } static int sh_mtu2_enable(struct sh_mtu2_priv *p) diff --git a/trunk/drivers/clocksource/sh_tmu.c b/trunk/drivers/clocksource/sh_tmu.c index c1b51d49d106..97f54b634be4 100644 --- a/trunk/drivers/clocksource/sh_tmu.c +++ b/trunk/drivers/clocksource/sh_tmu.c @@ -45,7 +45,7 @@ struct sh_tmu_priv { struct clocksource cs; }; -static DEFINE_RAW_SPINLOCK(sh_tmu_lock); +static DEFINE_SPINLOCK(sh_tmu_lock); #define TSTR -1 /* shared register */ #define TCOR 0 /* channel register */ @@ -95,7 +95,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) unsigned long flags, value; /* start stop register shared by multiple timer channels */ - raw_spin_lock_irqsave(&sh_tmu_lock, flags); + spin_lock_irqsave(&sh_tmu_lock, flags); value = sh_tmu_read(p, TSTR); if (start) @@ -104,7 +104,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) value &= ~(1 << cfg->timer_bit); sh_tmu_write(p, TSTR, value); - raw_spin_unlock_irqrestore(&sh_tmu_lock, flags); + spin_unlock_irqrestore(&sh_tmu_lock, flags); } static int sh_tmu_enable(struct sh_tmu_priv *p) @@ -245,7 +245,12 @@ static void sh_tmu_clock_event_start(struct sh_tmu_priv *p, int periodic) sh_tmu_enable(p); - clockevents_config(ced, p->rate); + /* TODO: calculate good shift from rate and counter bit width */ + + ced->shift = 32; + ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift); + ced->max_delta_ns = clockevent_delta2ns(0xffffffff, ced); + ced->min_delta_ns = 5000; if (periodic) { p->periodic = (p->rate + HZ/2) / HZ; @@ -318,8 +323,7 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, ced->set_mode = sh_tmu_clock_event_mode; dev_info(&p->pdev->dev, "used for clock events\n"); - - clockevents_config_and_register(ced, 1, 0x300, 0xffffffff); + clockevents_register_device(ced); ret = setup_irq(p->irqaction.irq, &p->irqaction); if (ret) { diff --git a/trunk/drivers/gpio/gpio-samsung.c b/trunk/drivers/gpio/gpio-samsung.c index b6453d0e44ad..7bb00448e13d 100644 --- a/trunk/drivers/gpio/gpio-samsung.c +++ b/trunk/drivers/gpio/gpio-samsung.c @@ -2833,7 +2833,7 @@ static __init void exynos5_gpiolib_init(void) } /* need to set base address for gpc4 */ - exynos5_gpios_1[11].base = gpio_base1 + 0x2E0; + exonys5_gpios_1[11].base = gpio_base1 + 0x2E0; /* need to set base address for gpx */ chip = &exynos5_gpios_1[21]; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c index d6de2e07fa03..420953197d0a 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -244,8 +244,8 @@ static const struct file_operations exynos_drm_driver_fops = { }; static struct drm_driver exynos_drm_driver = { - .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET | - DRIVER_GEM | DRIVER_PRIME, + .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM | + DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, .load = exynos_drm_load, .unload = exynos_drm_unload, .open = exynos_drm_open, diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c index 23d5ad379f86..6e9ac7bd1dcf 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -172,12 +172,19 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder) manager_ops->commit(manager->dev); } +static struct drm_crtc * +exynos_drm_encoder_get_crtc(struct drm_encoder *encoder) +{ + return encoder->crtc; +} + static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = { .dpms = exynos_drm_encoder_dpms, .mode_fixup = exynos_drm_encoder_mode_fixup, .mode_set = exynos_drm_encoder_mode_set, .prepare = exynos_drm_encoder_prepare, .commit = exynos_drm_encoder_commit, + .get_crtc = exynos_drm_encoder_get_crtc, }; static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c index 4ccfe4328fab..f82a299553fb 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -51,22 +51,11 @@ struct exynos_drm_fb { static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) { struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - unsigned int i; DRM_DEBUG_KMS("%s\n", __FILE__); drm_framebuffer_cleanup(fb); - for (i = 0; i < ARRAY_SIZE(exynos_fb->exynos_gem_obj); i++) { - struct drm_gem_object *obj; - - if (exynos_fb->exynos_gem_obj[i] == NULL) - continue; - - obj = &exynos_fb->exynos_gem_obj[i]->base; - drm_gem_object_unreference_unlocked(obj); - } - kfree(exynos_fb); exynos_fb = NULL; } @@ -145,11 +134,11 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(-ENOENT); } + drm_gem_object_unreference_unlocked(obj); + fb = exynos_drm_framebuffer_init(dev, mode_cmd, obj); - if (IS_ERR(fb)) { - drm_gem_object_unreference_unlocked(obj); + if (IS_ERR(fb)) return fb; - } exynos_fb = to_exynos_fb(fb); nr = exynos_drm_format_num_buffers(fb->pixel_format); @@ -163,6 +152,8 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(-ENOENT); } + drm_gem_object_unreference_unlocked(obj); + exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h index 50823756cdea..3ecb30d93552 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h @@ -31,10 +31,10 @@ static inline int exynos_drm_format_num_buffers(uint32_t format) { switch (format) { - case DRM_FORMAT_NV12: + case DRM_FORMAT_NV12M: case DRM_FORMAT_NV12MT: return 2; - case DRM_FORMAT_YUV420: + case DRM_FORMAT_YUV420M: return 3; default: return 1; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c index 5c8b683029ea..fc91293c4560 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -689,6 +689,7 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, struct drm_device *dev, uint32_t handle, uint64_t *offset) { + struct exynos_drm_gem_obj *exynos_gem_obj; struct drm_gem_object *obj; int ret = 0; @@ -709,13 +710,15 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, goto unlock; } - if (!obj->map_list.map) { - ret = drm_gem_create_mmap_offset(obj); + exynos_gem_obj = to_exynos_gem_obj(obj); + + if (!exynos_gem_obj->base.map_list.map) { + ret = drm_gem_create_mmap_offset(&exynos_gem_obj->base); if (ret) goto out; } - *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT; + *offset = (u64)exynos_gem_obj->base.map_list.hash.key << PAGE_SHIFT; DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset); out: diff --git a/trunk/drivers/gpu/drm/exynos/exynos_mixer.c b/trunk/drivers/gpu/drm/exynos/exynos_mixer.c index e2147a2ddcec..68ef01028375 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_mixer.c @@ -365,7 +365,7 @@ static void vp_video_buffer(struct mixer_context *ctx, int win) switch (win_data->pixel_format) { case DRM_FORMAT_NV12MT: tiled_mode = true; - case DRM_FORMAT_NV12: + case DRM_FORMAT_NV12M: crcb_mode = false; buf_num = 2; break; @@ -601,19 +601,17 @@ static void mixer_win_reset(struct mixer_context *ctx) mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); /* setting graphical layers */ + val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */ val |= MXR_GRP_CFG_WIN_BLEND_EN; - val |= MXR_GRP_CFG_BLEND_PRE_MUL; - val |= MXR_GRP_CFG_PIXEL_BLEND_EN; val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */ /* the same configuration for both layers */ mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val); - mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val); - /* setting video layers */ - val = MXR_GRP_CFG_ALPHA_VAL(0); - mixer_reg_write(res, MXR_VIDEO_CFG, val); + val |= MXR_GRP_CFG_BLEND_PRE_MUL; + val |= MXR_GRP_CFG_PIXEL_BLEND_EN; + mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val); /* configuration of Video Processor Registers */ vp_win_reset(ctx); diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.c b/trunk/drivers/gpu/drm/i915/i915_drv.c index 9fe9ebe52a7a..238a52165833 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.c +++ b/trunk/drivers/gpu/drm/i915/i915_drv.c @@ -233,7 +233,6 @@ static const struct intel_device_info intel_sandybridge_d_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_sandybridge_m_info = { @@ -244,7 +243,6 @@ static const struct intel_device_info intel_sandybridge_m_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_ivybridge_d_info = { @@ -254,7 +252,6 @@ static const struct intel_device_info intel_ivybridge_d_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_ivybridge_m_info = { @@ -265,7 +262,6 @@ static const struct intel_device_info intel_ivybridge_m_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_valleyview_m_info = { @@ -293,7 +289,6 @@ static const struct intel_device_info intel_haswell_d_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct intel_device_info intel_haswell_m_info = { @@ -303,7 +298,6 @@ static const struct intel_device_info intel_haswell_m_info = { .has_blt_ring = 1, .has_llc = 1, .has_pch_split = 1, - .has_force_wake = 1, }; static const struct pci_device_id pciidlist[] = { /* aka */ @@ -1145,9 +1139,10 @@ MODULE_LICENSE("GPL and additional rights"); /* We give fast paths for the really cool registers */ #define NEEDS_FORCE_WAKE(dev_priv, reg) \ - ((HAS_FORCE_WAKE((dev_priv)->dev)) && \ - ((reg) < 0x40000) && \ - ((reg) != FORCEWAKE)) + (((dev_priv)->info->gen >= 6) && \ + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE)) && \ + (!IS_VALLEYVIEW((dev_priv)->dev)) #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.h b/trunk/drivers/gpu/drm/i915/i915_drv.h index b0b676abde0d..c9cfc67c2cf5 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.h +++ b/trunk/drivers/gpu/drm/i915/i915_drv.h @@ -285,7 +285,6 @@ struct intel_device_info { u8 is_ivybridge:1; u8 is_valleyview:1; u8 has_pch_split:1; - u8 has_force_wake:1; u8 is_haswell:1; u8 has_fbc:1; u8 has_pipe_cxsr:1; @@ -1102,8 +1101,6 @@ struct drm_i915_file_private { #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) -#define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) - #include "i915_trace.h" /** diff --git a/trunk/drivers/gpu/drm/i915/i915_irq.c b/trunk/drivers/gpu/drm/i915/i915_irq.c index b1fe0edda955..1417660a93ec 100644 --- a/trunk/drivers/gpu/drm/i915/i915_irq.c +++ b/trunk/drivers/gpu/drm/i915/i915_irq.c @@ -510,7 +510,7 @@ static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) return ret; } -static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) +static void pch_irq_handler(struct drm_device *dev, u32 pch_iir) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe; @@ -550,35 +550,6 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir) DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); } -static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - int pipe; - - if (pch_iir & SDE_AUDIO_POWER_MASK_CPT) - DRM_DEBUG_DRIVER("PCH audio power change on port %d\n", - (pch_iir & SDE_AUDIO_POWER_MASK_CPT) >> - SDE_AUDIO_POWER_SHIFT_CPT); - - if (pch_iir & SDE_AUX_MASK_CPT) - DRM_DEBUG_DRIVER("AUX channel interrupt\n"); - - if (pch_iir & SDE_GMBUS_CPT) - DRM_DEBUG_DRIVER("PCH GMBUS interrupt\n"); - - if (pch_iir & SDE_AUDIO_CP_REQ_CPT) - DRM_DEBUG_DRIVER("Audio CP request interrupt\n"); - - if (pch_iir & SDE_AUDIO_CP_CHG_CPT) - DRM_DEBUG_DRIVER("Audio CP change interrupt\n"); - - if (pch_iir & SDE_FDI_MASK_CPT) - for_each_pipe(pipe) - DRM_DEBUG_DRIVER(" pipe %c FDI IIR: 0x%08x\n", - pipe_name(pipe), - I915_READ(FDI_RX_IIR(pipe))); -} - static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -620,7 +591,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) if (pch_iir & SDE_HOTPLUG_MASK_CPT) queue_work(dev_priv->wq, &dev_priv->hotplug_work); - cpt_irq_handler(dev, pch_iir); + pch_irq_handler(dev, pch_iir); /* clear PCH hotplug event before clear CPU irq */ I915_WRITE(SDEIIR, pch_iir); @@ -713,10 +684,7 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_PCH_EVENT) { if (pch_iir & hotplug_mask) queue_work(dev_priv->wq, &dev_priv->hotplug_work); - if (HAS_PCH_CPT(dev)) - cpt_irq_handler(dev, pch_iir); - else - ibx_irq_handler(dev, pch_iir); + pch_irq_handler(dev, pch_iir); } if (de_iir & DE_PCU_EVENT) { diff --git a/trunk/drivers/gpu/drm/i915/i915_reg.h b/trunk/drivers/gpu/drm/i915/i915_reg.h index 48d5e8e051cf..2d49b9507ed0 100644 --- a/trunk/drivers/gpu/drm/i915/i915_reg.h +++ b/trunk/drivers/gpu/drm/i915/i915_reg.h @@ -210,14 +210,6 @@ #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) -/* IVB has funny definitions for which plane to flip. */ -#define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19) -#define MI_DISPLAY_FLIP_IVB_PLANE_B (1 << 19) -#define MI_DISPLAY_FLIP_IVB_SPRITE_A (2 << 19) -#define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) -#define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) -#define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) - #define MI_SET_CONTEXT MI_INSTR(0x18, 0) #define MI_MM_SPACE_GTT (1<<8) #define MI_MM_SPACE_PHYSICAL (0<<8) @@ -3321,7 +3313,7 @@ /* PCH */ -/* south display engine interrupt: IBX */ +/* south display engine interrupt */ #define SDE_AUDIO_POWER_D (1 << 27) #define SDE_AUDIO_POWER_C (1 << 26) #define SDE_AUDIO_POWER_B (1 << 25) @@ -3357,44 +3349,15 @@ #define SDE_TRANSA_CRC_ERR (1 << 1) #define SDE_TRANSA_FIFO_UNDER (1 << 0) #define SDE_TRANS_MASK (0x3f) - -/* south display engine interrupt: CPT/PPT */ -#define SDE_AUDIO_POWER_D_CPT (1 << 31) -#define SDE_AUDIO_POWER_C_CPT (1 << 30) -#define SDE_AUDIO_POWER_B_CPT (1 << 29) -#define SDE_AUDIO_POWER_SHIFT_CPT 29 -#define SDE_AUDIO_POWER_MASK_CPT (7 << 29) -#define SDE_AUXD_CPT (1 << 27) -#define SDE_AUXC_CPT (1 << 26) -#define SDE_AUXB_CPT (1 << 25) -#define SDE_AUX_MASK_CPT (7 << 25) +/* CPT */ +#define SDE_CRT_HOTPLUG_CPT (1 << 19) #define SDE_PORTD_HOTPLUG_CPT (1 << 23) #define SDE_PORTC_HOTPLUG_CPT (1 << 22) #define SDE_PORTB_HOTPLUG_CPT (1 << 21) -#define SDE_CRT_HOTPLUG_CPT (1 << 19) #define SDE_HOTPLUG_MASK_CPT (SDE_CRT_HOTPLUG_CPT | \ SDE_PORTD_HOTPLUG_CPT | \ SDE_PORTC_HOTPLUG_CPT | \ SDE_PORTB_HOTPLUG_CPT) -#define SDE_GMBUS_CPT (1 << 17) -#define SDE_AUDIO_CP_REQ_C_CPT (1 << 10) -#define SDE_AUDIO_CP_CHG_C_CPT (1 << 9) -#define SDE_FDI_RXC_CPT (1 << 8) -#define SDE_AUDIO_CP_REQ_B_CPT (1 << 6) -#define SDE_AUDIO_CP_CHG_B_CPT (1 << 5) -#define SDE_FDI_RXB_CPT (1 << 4) -#define SDE_AUDIO_CP_REQ_A_CPT (1 << 2) -#define SDE_AUDIO_CP_CHG_A_CPT (1 << 1) -#define SDE_FDI_RXA_CPT (1 << 0) -#define SDE_AUDIO_CP_REQ_CPT (SDE_AUDIO_CP_REQ_C_CPT | \ - SDE_AUDIO_CP_REQ_B_CPT | \ - SDE_AUDIO_CP_REQ_A_CPT) -#define SDE_AUDIO_CP_CHG_CPT (SDE_AUDIO_CP_CHG_C_CPT | \ - SDE_AUDIO_CP_CHG_B_CPT | \ - SDE_AUDIO_CP_CHG_A_CPT) -#define SDE_FDI_MASK_CPT (SDE_FDI_RXC_CPT | \ - SDE_FDI_RXB_CPT | \ - SDE_FDI_RXA_CPT) #define SDEISR 0xc4000 #define SDEIMR 0xc4004 diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index e0aa064def31..914789420906 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -6158,34 +6158,17 @@ static int intel_gen7_queue_flip(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; - uint32_t plane_bit = 0; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) goto err; - switch(intel_crtc->plane) { - case PLANE_A: - plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A; - break; - case PLANE_B: - plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B; - break; - case PLANE_C: - plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C; - break; - default: - WARN_ONCE(1, "unknown plane in flip command\n"); - ret = -ENODEV; - goto err; - } - ret = intel_ring_begin(ring, 4); if (ret) goto err_unpin; - intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); + intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19)); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); intel_ring_emit(ring, (obj->gtt_offset)); intel_ring_emit(ring, (MI_NOOP)); diff --git a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c index e5b84ff89ca5..b59b6d5b7583 100644 --- a/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/trunk/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -266,15 +266,10 @@ u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) static int init_ring_common(struct intel_ring_buffer *ring) { - struct drm_device *dev = ring->dev; - drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_private_t *dev_priv = ring->dev->dev_private; struct drm_i915_gem_object *obj = ring->obj; - int ret = 0; u32 head; - if (HAS_FORCE_WAKE(dev)) - gen6_gt_force_wake_get(dev_priv); - /* Stop the ring if it's running. */ I915_WRITE_CTL(ring, 0); I915_WRITE_HEAD(ring, 0); @@ -322,8 +317,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_READ_HEAD(ring), I915_READ_TAIL(ring), I915_READ_START(ring)); - ret = -EIO; - goto out; + return -EIO; } if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) @@ -332,14 +326,9 @@ static int init_ring_common(struct intel_ring_buffer *ring) ring->head = I915_READ_HEAD(ring); ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; ring->space = ring_space(ring); - ring->last_retired_head = -1; } -out: - if (HAS_FORCE_WAKE(dev)) - gen6_gt_force_wake_put(dev_priv); - - return ret; + return 0; } static int @@ -998,10 +987,6 @@ static int intel_init_ring_buffer(struct drm_device *dev, if (ret) goto err_unref; - ret = i915_gem_object_set_to_gtt_domain(obj, true); - if (ret) - goto err_unpin; - ring->virtual_start = ioremap_wc(dev->agp->base + obj->gtt_offset, ring->size); if (ring->virtual_start == NULL) { diff --git a/trunk/drivers/gpu/drm/radeon/evergreen_cs.c b/trunk/drivers/gpu/drm/radeon/evergreen_cs.c index c16554122ccd..4e7dd2b4843d 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen_cs.c @@ -52,7 +52,6 @@ struct evergreen_cs_track { u32 cb_color_view[12]; u32 cb_color_pitch[12]; u32 cb_color_slice[12]; - u32 cb_color_slice_idx[12]; u32 cb_color_attrib[12]; u32 cb_color_cmask_slice[8];/* unused */ u32 cb_color_fmask_slice[8];/* unused */ @@ -128,14 +127,12 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->cb_color_info[i] = 0; track->cb_color_view[i] = 0xFFFFFFFF; track->cb_color_pitch[i] = 0; - track->cb_color_slice[i] = 0xfffffff; - track->cb_color_slice_idx[i] = 0; + track->cb_color_slice[i] = 0; } track->cb_target_mask = 0xFFFFFFFF; track->cb_shader_mask = 0xFFFFFFFF; track->cb_dirty = true; - track->db_depth_slice = 0xffffffff; track->db_depth_view = 0xFFFFC000; track->db_depth_size = 0xFFFFFFFF; track->db_depth_control = 0xFFFFFFFF; @@ -253,9 +250,10 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, { struct evergreen_cs_track *track = p->track; unsigned palign, halign, tileb, slice_pt; - unsigned mtile_pr, mtile_ps, mtileb; tileb = 64 * surf->bpe * surf->nsamples; + palign = track->group_size / (8 * surf->bpe * surf->nsamples); + palign = MAX(8, palign); slice_pt = 1; if (tileb > surf->tsplit) { slice_pt = tileb / surf->tsplit; @@ -264,10 +262,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, /* macro tile width & height */ palign = (8 * surf->bankw * track->npipes) * surf->mtilea; halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; - mtileb = (palign / 8) * (halign / 8) * tileb;; - mtile_pr = surf->nbx / palign; - mtile_ps = (mtile_pr * surf->nby) / halign; - surf->layer_size = mtile_ps * mtileb * slice_pt; + surf->layer_size = surf->nbx * surf->nby * surf->bpe * slice_pt; surf->base_align = (palign / 8) * (halign / 8) * tileb; surf->palign = palign; surf->halign = halign; @@ -439,39 +434,6 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i offset += surf.layer_size * mslice; if (offset > radeon_bo_size(track->cb_color_bo[id])) { - /* old ddx are broken they allocate bo with w*h*bpp but - * program slice with ALIGN(h, 8), catch this and patch - * command stream. - */ - if (!surf.mode) { - volatile u32 *ib = p->ib.ptr; - unsigned long tmp, nby, bsize, size, min = 0; - - /* find the height the ddx wants */ - if (surf.nby > 8) { - min = surf.nby - 8; - } - bsize = radeon_bo_size(track->cb_color_bo[id]); - tmp = track->cb_color_bo_offset[id] << 8; - for (nby = surf.nby; nby > min; nby--) { - size = nby * surf.nbx * surf.bpe * surf.nsamples; - if ((tmp + size * mslice) <= bsize) { - break; - } - } - if (nby > min) { - surf.nby = nby; - slice = ((nby * surf.nbx) / 64) - 1; - if (!evergreen_surface_check(p, &surf, "cb")) { - /* check if this one works */ - tmp += surf.layer_size * mslice; - if (tmp <= bsize) { - ib[track->cb_color_slice_idx[id]] = slice; - goto old_ddx_ok; - } - } - } - } dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " "offset %d, max layer %d, bo size %ld, slice %d)\n", __func__, __LINE__, id, surf.layer_size, @@ -484,7 +446,6 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i surf.tsplit, surf.mtilea); return -EINVAL; } -old_ddx_ok: return 0; } @@ -1571,7 +1532,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR7_SLICE: tmp = (reg - CB_COLOR0_SLICE) / 0x3c; track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); - track->cb_color_slice_idx[tmp] = idx; track->cb_dirty = true; break; case CB_COLOR8_SLICE: @@ -1580,7 +1540,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR11_SLICE: tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8; track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); - track->cb_color_slice_idx[tmp] = idx; track->cb_dirty = true; break; case CB_COLOR0_ATTRIB: diff --git a/trunk/drivers/gpu/drm/radeon/ni.c b/trunk/drivers/gpu/drm/radeon/ni.c index 3186522a4458..3df4efa11942 100644 --- a/trunk/drivers/gpu/drm/radeon/ni.c +++ b/trunk/drivers/gpu/drm/radeon/ni.c @@ -460,28 +460,15 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.max_pipes_per_simd = 4; rdev->config.cayman.max_tile_pipes = 2; if ((rdev->pdev->device == 0x9900) || - (rdev->pdev->device == 0x9901) || - (rdev->pdev->device == 0x9905) || - (rdev->pdev->device == 0x9906) || - (rdev->pdev->device == 0x9907) || - (rdev->pdev->device == 0x9908) || - (rdev->pdev->device == 0x9909) || - (rdev->pdev->device == 0x9910) || - (rdev->pdev->device == 0x9917)) { + (rdev->pdev->device == 0x9901)) { rdev->config.cayman.max_simds_per_se = 6; rdev->config.cayman.max_backends_per_se = 2; } else if ((rdev->pdev->device == 0x9903) || - (rdev->pdev->device == 0x9904) || - (rdev->pdev->device == 0x990A) || - (rdev->pdev->device == 0x9913) || - (rdev->pdev->device == 0x9918)) { + (rdev->pdev->device == 0x9904)) { rdev->config.cayman.max_simds_per_se = 4; rdev->config.cayman.max_backends_per_se = 2; - } else if ((rdev->pdev->device == 0x9919) || - (rdev->pdev->device == 0x9990) || - (rdev->pdev->device == 0x9991) || - (rdev->pdev->device == 0x9994) || - (rdev->pdev->device == 0x99A0)) { + } else if ((rdev->pdev->device == 0x9990) || + (rdev->pdev->device == 0x9991)) { rdev->config.cayman.max_simds_per_se = 3; rdev->config.cayman.max_backends_per_se = 1; } else { diff --git a/trunk/drivers/gpu/drm/radeon/r600.c b/trunk/drivers/gpu/drm/radeon/r600.c index f30dc95f83b1..45cfcea63507 100644 --- a/trunk/drivers/gpu/drm/radeon/r600.c +++ b/trunk/drivers/gpu/drm/radeon/r600.c @@ -2426,12 +2426,6 @@ int r600_startup(struct radeon_device *rdev) if (r) return r; - r = r600_audio_init(rdev); - if (r) { - DRM_ERROR("radeon: audio init failed\n"); - return r; - } - return 0; } @@ -2468,6 +2462,12 @@ int r600_resume(struct radeon_device *rdev) return r; } + r = r600_audio_init(rdev); + if (r) { + DRM_ERROR("radeon: audio resume failed\n"); + return r; + } + return r; } @@ -2577,6 +2577,9 @@ int r600_init(struct radeon_device *rdev) rdev->accel_working = false; } + r = r600_audio_init(rdev); + if (r) + return r; /* TODO error handling */ return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/r600_audio.c b/trunk/drivers/gpu/drm/radeon/r600_audio.c index 7479a5c503e4..7c4fa77f018f 100644 --- a/trunk/drivers/gpu/drm/radeon/r600_audio.c +++ b/trunk/drivers/gpu/drm/radeon/r600_audio.c @@ -192,7 +192,6 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); int base_rate = 48000; switch (radeon_encoder->encoder_id) { @@ -218,8 +217,8 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) WREG32(EVERGREEN_AUDIO_PLL1_DIV, clock * 10); WREG32(EVERGREEN_AUDIO_PLL1_UNK, 0x00000071); - /* Select DTO source */ - WREG32(0x5ac, radeon_crtc->crtc_id); + /* Some magic trigger or src sel? */ + WREG32_P(0x5ac, 0x01, ~0x77); } else { switch (dig->dig_encoder) { case 0: diff --git a/trunk/drivers/gpu/drm/radeon/r600_hdmi.c b/trunk/drivers/gpu/drm/radeon/r600_hdmi.c index 969c27529dfe..226379e00ac1 100644 --- a/trunk/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/trunk/drivers/gpu/drm/radeon/r600_hdmi.c @@ -348,6 +348,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod WREG32(HDMI0_AUDIO_PACKET_CONTROL + offset, HDMI0_AUDIO_SAMPLE_SEND | /* send audio packets */ HDMI0_AUDIO_DELAY_EN(1) | /* default audio delay */ + HDMI0_AUDIO_SEND_MAX_PACKETS | /* send NULL packets if no audio is available */ HDMI0_AUDIO_PACKETS_PER_LINE(3) | /* should be suffient for all audio modes and small enough for all hblanks */ HDMI0_60958_CS_UPDATE); /* allow 60958 channel status fields to be updated */ } diff --git a/trunk/drivers/gpu/drm/radeon/radeon.h b/trunk/drivers/gpu/drm/radeon/radeon.h index fefcca55c1eb..85dac33e3cce 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -1374,9 +1374,9 @@ struct cayman_asic { struct si_asic { unsigned max_shader_engines; + unsigned max_pipes_per_simd; unsigned max_tile_pipes; - unsigned max_cu_per_sh; - unsigned max_sh_per_se; + unsigned max_simds_per_se; unsigned max_backends_per_se; unsigned max_texture_channel_caches; unsigned max_gprs; @@ -1387,6 +1387,7 @@ struct si_asic { unsigned sc_hiz_tile_fifo_size; unsigned sc_earlyz_tile_fifo_size; + unsigned num_shader_engines; unsigned num_tile_pipes; unsigned num_backends_per_se; unsigned backend_disable_mask_per_asic; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_drv.c b/trunk/drivers/gpu/drm/radeon/radeon_drv.c index 03e5f5df40f1..f0bb2b543b13 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_drv.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_drv.c @@ -57,10 +57,9 @@ * 2.13.0 - virtual memory support, streamout * 2.14.0 - add evergreen tiling informations * 2.15.0 - add max_pipes query - * 2.16.0 - fix evergreen 2D tiled surface calculation */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 16 +#define KMS_DRIVER_MINOR 15 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_gart.c b/trunk/drivers/gpu/drm/radeon/radeon_gart.c index 59d44937dd9f..79db56e6c2ac 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_gart.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_gart.c @@ -476,18 +476,12 @@ int radeon_vm_bo_add(struct radeon_device *rdev, mutex_lock(&vm->mutex); if (last_pfn > vm->last_pfn) { - /* release mutex and lock in right order */ - mutex_unlock(&vm->mutex); + /* grow va space 32M by 32M */ + unsigned align = ((32 << 20) >> 12) - 1; radeon_mutex_lock(&rdev->cs_mutex); - mutex_lock(&vm->mutex); - /* and check again */ - if (last_pfn > vm->last_pfn) { - /* grow va space 32M by 32M */ - unsigned align = ((32 << 20) >> 12) - 1; - radeon_vm_unbind_locked(rdev, vm); - vm->last_pfn = (last_pfn + align) & ~align; - } + radeon_vm_unbind_locked(rdev, vm); radeon_mutex_unlock(&rdev->cs_mutex); + vm->last_pfn = (last_pfn + align) & ~align; } head = &vm->va; last_offset = 0; @@ -601,8 +595,8 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, if (bo_va == NULL) return 0; - radeon_mutex_lock(&rdev->cs_mutex); mutex_lock(&vm->mutex); + radeon_mutex_lock(&rdev->cs_mutex); radeon_vm_bo_update_pte(rdev, vm, bo, NULL); radeon_mutex_unlock(&rdev->cs_mutex); list_del(&bo_va->vm_list); @@ -647,8 +641,9 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) struct radeon_bo_va *bo_va, *tmp; int r; - radeon_mutex_lock(&rdev->cs_mutex); mutex_lock(&vm->mutex); + + radeon_mutex_lock(&rdev->cs_mutex); radeon_vm_unbind_locked(rdev, vm); radeon_mutex_unlock(&rdev->cs_mutex); diff --git a/trunk/drivers/gpu/drm/radeon/radeon_kms.c b/trunk/drivers/gpu/drm/radeon/radeon_kms.c index 5c58d7d90cb2..f1016a5820d1 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_kms.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_kms.c @@ -273,7 +273,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) break; case RADEON_INFO_MAX_PIPES: if (rdev->family >= CHIP_TAHITI) - value = rdev->config.si.max_cu_per_sh; + value = rdev->config.si.max_pipes_per_simd; else if (rdev->family >= CHIP_CAYMAN) value = rdev->config.cayman.max_pipes_per_simd; else if (rdev->family >= CHIP_CEDAR) diff --git a/trunk/drivers/gpu/drm/radeon/rs600.c b/trunk/drivers/gpu/drm/radeon/rs600.c index e95c5e61d4e2..25f9eef12c42 100644 --- a/trunk/drivers/gpu/drm/radeon/rs600.c +++ b/trunk/drivers/gpu/drm/radeon/rs600.c @@ -908,6 +908,12 @@ static int rs600_startup(struct radeon_device *rdev) return r; } + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "failed initializing audio\n"); + return r; + } + r = radeon_ib_pool_start(rdev); if (r) return r; @@ -916,12 +922,6 @@ static int rs600_startup(struct radeon_device *rdev) if (r) return r; - r = r600_audio_init(rdev); - if (r) { - dev_err(rdev->dev, "failed initializing audio\n"); - return r; - } - return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/rs690.c b/trunk/drivers/gpu/drm/radeon/rs690.c index 159b6a43fda0..3277ddecfe9f 100644 --- a/trunk/drivers/gpu/drm/radeon/rs690.c +++ b/trunk/drivers/gpu/drm/radeon/rs690.c @@ -637,6 +637,12 @@ static int rs690_startup(struct radeon_device *rdev) return r; } + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "failed initializing audio\n"); + return r; + } + r = radeon_ib_pool_start(rdev); if (r) return r; @@ -645,12 +651,6 @@ static int rs690_startup(struct radeon_device *rdev) if (r) return r; - r = r600_audio_init(rdev); - if (r) { - dev_err(rdev->dev, "failed initializing audio\n"); - return r; - } - return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/rv770.c b/trunk/drivers/gpu/drm/radeon/rv770.c index 4ad0281fdc37..04ddc365a908 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770.c +++ b/trunk/drivers/gpu/drm/radeon/rv770.c @@ -956,12 +956,6 @@ static int rv770_startup(struct radeon_device *rdev) if (r) return r; - r = r600_audio_init(rdev); - if (r) { - DRM_ERROR("radeon: audio init failed\n"); - return r; - } - return 0; } @@ -984,6 +978,12 @@ int rv770_resume(struct radeon_device *rdev) return r; } + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "radeon: audio init failed\n"); + return r; + } + return r; } @@ -1092,6 +1092,12 @@ int rv770_init(struct radeon_device *rdev) rdev->accel_working = false; } + r = r600_audio_init(rdev); + if (r) { + dev_err(rdev->dev, "radeon: audio init failed\n"); + return r; + } + return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/si.c b/trunk/drivers/gpu/drm/radeon/si.c index c7b61f16ecfd..549732e56ca9 100644 --- a/trunk/drivers/gpu/drm/radeon/si.c +++ b/trunk/drivers/gpu/drm/radeon/si.c @@ -867,6 +867,200 @@ void dce6_bandwidth_update(struct radeon_device *rdev) /* * Core functions */ +static u32 si_get_tile_pipe_to_backend_map(struct radeon_device *rdev, + u32 num_tile_pipes, + u32 num_backends_per_asic, + u32 *backend_disable_mask_per_asic, + u32 num_shader_engines) +{ + u32 backend_map = 0; + u32 enabled_backends_mask = 0; + u32 enabled_backends_count = 0; + u32 num_backends_per_se; + u32 cur_pipe; + u32 swizzle_pipe[SI_MAX_PIPES]; + u32 cur_backend = 0; + u32 i; + bool force_no_swizzle; + + /* force legal values */ + if (num_tile_pipes < 1) + num_tile_pipes = 1; + if (num_tile_pipes > rdev->config.si.max_tile_pipes) + num_tile_pipes = rdev->config.si.max_tile_pipes; + if (num_shader_engines < 1) + num_shader_engines = 1; + if (num_shader_engines > rdev->config.si.max_shader_engines) + num_shader_engines = rdev->config.si.max_shader_engines; + if (num_backends_per_asic < num_shader_engines) + num_backends_per_asic = num_shader_engines; + if (num_backends_per_asic > (rdev->config.si.max_backends_per_se * num_shader_engines)) + num_backends_per_asic = rdev->config.si.max_backends_per_se * num_shader_engines; + + /* make sure we have the same number of backends per se */ + num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines); + /* set up the number of backends per se */ + num_backends_per_se = num_backends_per_asic / num_shader_engines; + if (num_backends_per_se > rdev->config.si.max_backends_per_se) { + num_backends_per_se = rdev->config.si.max_backends_per_se; + num_backends_per_asic = num_backends_per_se * num_shader_engines; + } + + /* create enable mask and count for enabled backends */ + for (i = 0; i < SI_MAX_BACKENDS; ++i) { + if (((*backend_disable_mask_per_asic >> i) & 1) == 0) { + enabled_backends_mask |= (1 << i); + ++enabled_backends_count; + } + if (enabled_backends_count == num_backends_per_asic) + break; + } + + /* force the backends mask to match the current number of backends */ + if (enabled_backends_count != num_backends_per_asic) { + u32 this_backend_enabled; + u32 shader_engine; + u32 backend_per_se; + + enabled_backends_mask = 0; + enabled_backends_count = 0; + *backend_disable_mask_per_asic = SI_MAX_BACKENDS_MASK; + for (i = 0; i < SI_MAX_BACKENDS; ++i) { + /* calc the current se */ + shader_engine = i / rdev->config.si.max_backends_per_se; + /* calc the backend per se */ + backend_per_se = i % rdev->config.si.max_backends_per_se; + /* default to not enabled */ + this_backend_enabled = 0; + if ((shader_engine < num_shader_engines) && + (backend_per_se < num_backends_per_se)) + this_backend_enabled = 1; + if (this_backend_enabled) { + enabled_backends_mask |= (1 << i); + *backend_disable_mask_per_asic &= ~(1 << i); + ++enabled_backends_count; + } + } + } + + + memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * SI_MAX_PIPES); + switch (rdev->family) { + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_VERDE: + force_no_swizzle = true; + break; + default: + force_no_swizzle = false; + break; + } + if (force_no_swizzle) { + bool last_backend_enabled = false; + + force_no_swizzle = false; + for (i = 0; i < SI_MAX_BACKENDS; ++i) { + if (((enabled_backends_mask >> i) & 1) == 1) { + if (last_backend_enabled) + force_no_swizzle = true; + last_backend_enabled = true; + } else + last_backend_enabled = false; + } + } + + switch (num_tile_pipes) { + case 1: + case 3: + case 5: + case 7: + DRM_ERROR("odd number of pipes!\n"); + break; + case 2: + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + break; + case 4: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 1; + swizzle_pipe[3] = 3; + } + break; + case 6: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 1; + swizzle_pipe[4] = 3; + swizzle_pipe[5] = 5; + } + break; + case 8: + if (force_no_swizzle) { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 1; + swizzle_pipe[2] = 2; + swizzle_pipe[3] = 3; + swizzle_pipe[4] = 4; + swizzle_pipe[5] = 5; + swizzle_pipe[6] = 6; + swizzle_pipe[7] = 7; + } else { + swizzle_pipe[0] = 0; + swizzle_pipe[1] = 2; + swizzle_pipe[2] = 4; + swizzle_pipe[3] = 6; + swizzle_pipe[4] = 1; + swizzle_pipe[5] = 3; + swizzle_pipe[6] = 5; + swizzle_pipe[7] = 7; + } + break; + } + + for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { + while (((1 << cur_backend) & enabled_backends_mask) == 0) + cur_backend = (cur_backend + 1) % SI_MAX_BACKENDS; + + backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4))); + + cur_backend = (cur_backend + 1) % SI_MAX_BACKENDS; + } + + return backend_map; +} + +static u32 si_get_disable_mask_per_asic(struct radeon_device *rdev, + u32 disable_mask_per_se, + u32 max_disable_mask_per_se, + u32 num_shader_engines) +{ + u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se); + u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se; + + if (num_shader_engines == 1) + return disable_mask_per_asic; + else if (num_shader_engines == 2) + return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se); + else + return 0xffffffff; +} + static void si_tiling_mode_table_init(struct radeon_device *rdev) { const u32 num_tile_mode_states = 32; @@ -1368,151 +1562,18 @@ static void si_tiling_mode_table_init(struct radeon_device *rdev) DRM_ERROR("unknown asic: 0x%x\n", rdev->family); } -static void si_select_se_sh(struct radeon_device *rdev, - u32 se_num, u32 sh_num) -{ - u32 data = INSTANCE_BROADCAST_WRITES; - - if ((se_num == 0xffffffff) && (sh_num == 0xffffffff)) - data = SH_BROADCAST_WRITES | SE_BROADCAST_WRITES; - else if (se_num == 0xffffffff) - data |= SE_BROADCAST_WRITES | SH_INDEX(sh_num); - else if (sh_num == 0xffffffff) - data |= SH_BROADCAST_WRITES | SE_INDEX(se_num); - else - data |= SH_INDEX(sh_num) | SE_INDEX(se_num); - WREG32(GRBM_GFX_INDEX, data); -} - -static u32 si_create_bitmask(u32 bit_width) -{ - u32 i, mask = 0; - - for (i = 0; i < bit_width; i++) { - mask <<= 1; - mask |= 1; - } - return mask; -} - -static u32 si_get_cu_enabled(struct radeon_device *rdev, u32 cu_per_sh) -{ - u32 data, mask; - - data = RREG32(CC_GC_SHADER_ARRAY_CONFIG); - if (data & 1) - data &= INACTIVE_CUS_MASK; - else - data = 0; - data |= RREG32(GC_USER_SHADER_ARRAY_CONFIG); - - data >>= INACTIVE_CUS_SHIFT; - - mask = si_create_bitmask(cu_per_sh); - - return ~data & mask; -} - -static void si_setup_spi(struct radeon_device *rdev, - u32 se_num, u32 sh_per_se, - u32 cu_per_sh) -{ - int i, j, k; - u32 data, mask, active_cu; - - for (i = 0; i < se_num; i++) { - for (j = 0; j < sh_per_se; j++) { - si_select_se_sh(rdev, i, j); - data = RREG32(SPI_STATIC_THREAD_MGMT_3); - active_cu = si_get_cu_enabled(rdev, cu_per_sh); - - mask = 1; - for (k = 0; k < 16; k++) { - mask <<= k; - if (active_cu & mask) { - data &= ~mask; - WREG32(SPI_STATIC_THREAD_MGMT_3, data); - break; - } - } - } - } - si_select_se_sh(rdev, 0xffffffff, 0xffffffff); -} - -static u32 si_get_rb_disabled(struct radeon_device *rdev, - u32 max_rb_num, u32 se_num, - u32 sh_per_se) -{ - u32 data, mask; - - data = RREG32(CC_RB_BACKEND_DISABLE); - if (data & 1) - data &= BACKEND_DISABLE_MASK; - else - data = 0; - data |= RREG32(GC_USER_RB_BACKEND_DISABLE); - - data >>= BACKEND_DISABLE_SHIFT; - - mask = si_create_bitmask(max_rb_num / se_num / sh_per_se); - - return data & mask; -} - -static void si_setup_rb(struct radeon_device *rdev, - u32 se_num, u32 sh_per_se, - u32 max_rb_num) -{ - int i, j; - u32 data, mask; - u32 disabled_rbs = 0; - u32 enabled_rbs = 0; - - for (i = 0; i < se_num; i++) { - for (j = 0; j < sh_per_se; j++) { - si_select_se_sh(rdev, i, j); - data = si_get_rb_disabled(rdev, max_rb_num, se_num, sh_per_se); - disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH); - } - } - si_select_se_sh(rdev, 0xffffffff, 0xffffffff); - - mask = 1; - for (i = 0; i < max_rb_num; i++) { - if (!(disabled_rbs & mask)) - enabled_rbs |= mask; - mask <<= 1; - } - - for (i = 0; i < se_num; i++) { - si_select_se_sh(rdev, i, 0xffffffff); - data = 0; - for (j = 0; j < sh_per_se; j++) { - switch (enabled_rbs & 3) { - case 1: - data |= (RASTER_CONFIG_RB_MAP_0 << (i * sh_per_se + j) * 2); - break; - case 2: - data |= (RASTER_CONFIG_RB_MAP_3 << (i * sh_per_se + j) * 2); - break; - case 3: - default: - data |= (RASTER_CONFIG_RB_MAP_2 << (i * sh_per_se + j) * 2); - break; - } - enabled_rbs >>= 2; - } - WREG32(PA_SC_RASTER_CONFIG, data); - } - si_select_se_sh(rdev, 0xffffffff, 0xffffffff); -} - static void si_gpu_init(struct radeon_device *rdev) { + u32 cc_rb_backend_disable = 0; + u32 cc_gc_shader_array_config; u32 gb_addr_config = 0; u32 mc_shared_chmap, mc_arb_ramcfg; + u32 gb_backend_map; + u32 cgts_tcc_disable; u32 sx_debug_1; + u32 gc_user_shader_array_config; + u32 gc_user_rb_backend_disable; + u32 cgts_user_tcc_disable; u32 hdp_host_path_cntl; u32 tmp; int i, j; @@ -1520,9 +1581,9 @@ static void si_gpu_init(struct radeon_device *rdev) switch (rdev->family) { case CHIP_TAHITI: rdev->config.si.max_shader_engines = 2; + rdev->config.si.max_pipes_per_simd = 4; rdev->config.si.max_tile_pipes = 12; - rdev->config.si.max_cu_per_sh = 8; - rdev->config.si.max_sh_per_se = 2; + rdev->config.si.max_simds_per_se = 8; rdev->config.si.max_backends_per_se = 4; rdev->config.si.max_texture_channel_caches = 12; rdev->config.si.max_gprs = 256; @@ -1533,13 +1594,12 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.sc_prim_fifo_size_backend = 0x100; rdev->config.si.sc_hiz_tile_fifo_size = 0x30; rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_PITCAIRN: rdev->config.si.max_shader_engines = 2; + rdev->config.si.max_pipes_per_simd = 4; rdev->config.si.max_tile_pipes = 8; - rdev->config.si.max_cu_per_sh = 5; - rdev->config.si.max_sh_per_se = 2; + rdev->config.si.max_simds_per_se = 5; rdev->config.si.max_backends_per_se = 4; rdev->config.si.max_texture_channel_caches = 8; rdev->config.si.max_gprs = 256; @@ -1550,14 +1610,13 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.sc_prim_fifo_size_backend = 0x100; rdev->config.si.sc_hiz_tile_fifo_size = 0x30; rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN; break; case CHIP_VERDE: default: rdev->config.si.max_shader_engines = 1; + rdev->config.si.max_pipes_per_simd = 4; rdev->config.si.max_tile_pipes = 4; - rdev->config.si.max_cu_per_sh = 2; - rdev->config.si.max_sh_per_se = 2; + rdev->config.si.max_simds_per_se = 2; rdev->config.si.max_backends_per_se = 4; rdev->config.si.max_texture_channel_caches = 4; rdev->config.si.max_gprs = 256; @@ -1568,7 +1627,6 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.sc_prim_fifo_size_backend = 0x40; rdev->config.si.sc_hiz_tile_fifo_size = 0x30; rdev->config.si.sc_earlyz_tile_fifo_size = 0x130; - gb_addr_config = VERDE_GB_ADDR_CONFIG_GOLDEN; break; } @@ -1590,7 +1648,31 @@ static void si_gpu_init(struct radeon_device *rdev) mc_shared_chmap = RREG32(MC_SHARED_CHMAP); mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); + cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE); + cc_gc_shader_array_config = RREG32(CC_GC_SHADER_ARRAY_CONFIG); + cgts_tcc_disable = 0xffff0000; + for (i = 0; i < rdev->config.si.max_texture_channel_caches; i++) + cgts_tcc_disable &= ~(1 << (16 + i)); + gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE); + gc_user_shader_array_config = RREG32(GC_USER_SHADER_ARRAY_CONFIG); + cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE); + + rdev->config.si.num_shader_engines = rdev->config.si.max_shader_engines; rdev->config.si.num_tile_pipes = rdev->config.si.max_tile_pipes; + tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; + rdev->config.si.num_backends_per_se = r600_count_pipe_bits(tmp); + tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT; + rdev->config.si.backend_disable_mask_per_asic = + si_get_disable_mask_per_asic(rdev, tmp, SI_MAX_BACKENDS_PER_SE_MASK, + rdev->config.si.num_shader_engines); + rdev->config.si.backend_map = + si_get_tile_pipe_to_backend_map(rdev, rdev->config.si.num_tile_pipes, + rdev->config.si.num_backends_per_se * + rdev->config.si.num_shader_engines, + &rdev->config.si.backend_disable_mask_per_asic, + rdev->config.si.num_shader_engines); + tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT; + rdev->config.si.num_texture_channel_caches = r600_count_pipe_bits(tmp); rdev->config.si.mem_max_burst_length_bytes = 256; tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT; rdev->config.si.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024; @@ -1601,8 +1683,55 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.num_gpus = 1; rdev->config.si.multi_gpu_tile_size = 64; - /* fix up row size */ - gb_addr_config &= ~ROW_SIZE_MASK; + gb_addr_config = 0; + switch (rdev->config.si.num_tile_pipes) { + case 1: + gb_addr_config |= NUM_PIPES(0); + break; + case 2: + gb_addr_config |= NUM_PIPES(1); + break; + case 4: + gb_addr_config |= NUM_PIPES(2); + break; + case 8: + default: + gb_addr_config |= NUM_PIPES(3); + break; + } + + tmp = (rdev->config.si.mem_max_burst_length_bytes / 256) - 1; + gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp); + gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.si.num_shader_engines - 1); + tmp = (rdev->config.si.shader_engine_tile_size / 16) - 1; + gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp); + switch (rdev->config.si.num_gpus) { + case 1: + default: + gb_addr_config |= NUM_GPUS(0); + break; + case 2: + gb_addr_config |= NUM_GPUS(1); + break; + case 4: + gb_addr_config |= NUM_GPUS(2); + break; + } + switch (rdev->config.si.multi_gpu_tile_size) { + case 16: + gb_addr_config |= MULTI_GPU_TILE_SIZE(0); + break; + case 32: + default: + gb_addr_config |= MULTI_GPU_TILE_SIZE(1); + break; + case 64: + gb_addr_config |= MULTI_GPU_TILE_SIZE(2); + break; + case 128: + gb_addr_config |= MULTI_GPU_TILE_SIZE(3); + break; + } switch (rdev->config.si.mem_row_size_in_kb) { case 1: default: @@ -1616,6 +1745,26 @@ static void si_gpu_init(struct radeon_device *rdev) break; } + tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT; + rdev->config.si.num_tile_pipes = (1 << tmp); + tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT; + rdev->config.si.mem_max_burst_length_bytes = (tmp + 1) * 256; + tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT; + rdev->config.si.num_shader_engines = tmp + 1; + tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT; + rdev->config.si.num_gpus = tmp + 1; + tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT; + rdev->config.si.multi_gpu_tile_size = 1 << tmp; + tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT; + rdev->config.si.mem_row_size_in_kb = 1 << tmp; + + gb_backend_map = + si_get_tile_pipe_to_backend_map(rdev, rdev->config.si.num_tile_pipes, + rdev->config.si.num_backends_per_se * + rdev->config.si.num_shader_engines, + &rdev->config.si.backend_disable_mask_per_asic, + rdev->config.si.num_shader_engines); + /* setup tiling info dword. gb_addr_config is not adequate since it does * not have bank info, so create a custom tiling dword. * bits 3:0 num_pipes @@ -1640,29 +1789,33 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.tile_config |= (3 << 0); break; } - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.si.tile_config |= 1 << 4; - else - rdev->config.si.tile_config |= 0 << 4; + rdev->config.si.tile_config |= + ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; rdev->config.si.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; rdev->config.si.tile_config |= ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12; + rdev->config.si.backend_map = gb_backend_map; WREG32(GB_ADDR_CONFIG, gb_addr_config); WREG32(DMIF_ADDR_CONFIG, gb_addr_config); WREG32(HDP_ADDR_CONFIG, gb_addr_config); - si_tiling_mode_table_init(rdev); + /* primary versions */ + WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(CC_GC_SHADER_ARRAY_CONFIG, cc_gc_shader_array_config); - si_setup_rb(rdev, rdev->config.si.max_shader_engines, - rdev->config.si.max_sh_per_se, - rdev->config.si.max_backends_per_se); + WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable); - si_setup_spi(rdev, rdev->config.si.max_shader_engines, - rdev->config.si.max_sh_per_se, - rdev->config.si.max_cu_per_sh); + /* user versions */ + WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); + WREG32(GC_USER_SHADER_ARRAY_CONFIG, cc_gc_shader_array_config); + WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable); + + si_tiling_mode_table_init(rdev); /* set HW defaults for 3D engine */ WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | diff --git a/trunk/drivers/gpu/drm/radeon/sid.h b/trunk/drivers/gpu/drm/radeon/sid.h index db4067962868..53ea2c42dbd6 100644 --- a/trunk/drivers/gpu/drm/radeon/sid.h +++ b/trunk/drivers/gpu/drm/radeon/sid.h @@ -24,11 +24,6 @@ #ifndef SI_H #define SI_H -#define TAHITI_RB_BITMAP_WIDTH_PER_SH 2 - -#define TAHITI_GB_ADDR_CONFIG_GOLDEN 0x12011003 -#define VERDE_GB_ADDR_CONFIG_GOLDEN 0x12010002 - #define CG_MULT_THERMAL_STATUS 0x714 #define ASIC_MAX_TEMP(x) ((x) << 0) #define ASIC_MAX_TEMP_MASK 0x000001ff @@ -413,12 +408,6 @@ #define SOFT_RESET_IA (1 << 15) #define GRBM_GFX_INDEX 0x802C -#define INSTANCE_INDEX(x) ((x) << 0) -#define SH_INDEX(x) ((x) << 8) -#define SE_INDEX(x) ((x) << 16) -#define SH_BROADCAST_WRITES (1 << 29) -#define INSTANCE_BROADCAST_WRITES (1 << 30) -#define SE_BROADCAST_WRITES (1 << 31) #define GRBM_INT_CNTL 0x8060 # define RDERR_INT_ENABLE (1 << 0) @@ -491,8 +480,6 @@ #define VGT_TF_MEMORY_BASE 0x89B8 #define CC_GC_SHADER_ARRAY_CONFIG 0x89bc -#define INACTIVE_CUS_MASK 0xFFFF0000 -#define INACTIVE_CUS_SHIFT 16 #define GC_USER_SHADER_ARRAY_CONFIG 0x89c0 #define PA_CL_ENHANCE 0x8A14 @@ -701,12 +688,6 @@ #define RLC_MC_CNTL 0xC344 #define RLC_UCODE_CNTL 0xC348 -#define PA_SC_RASTER_CONFIG 0x28350 -# define RASTER_CONFIG_RB_MAP_0 0 -# define RASTER_CONFIG_RB_MAP_1 1 -# define RASTER_CONFIG_RB_MAP_2 2 -# define RASTER_CONFIG_RB_MAP_3 3 - #define VGT_EVENT_INITIATOR 0x28a90 # define SAMPLE_STREAMOUTSTATS1 (1 << 0) # define SAMPLE_STREAMOUTSTATS2 (2 << 0) diff --git a/trunk/drivers/gpu/drm/ttm/ttm_bo.c b/trunk/drivers/gpu/drm/ttm/ttm_bo.c index 36f4b28c1b90..b67cfcaa661f 100644 --- a/trunk/drivers/gpu/drm/ttm/ttm_bo.c +++ b/trunk/drivers/gpu/drm/ttm/ttm_bo.c @@ -1204,7 +1204,6 @@ int ttm_bo_init(struct ttm_bo_device *bdev, (*destroy)(bo); else kfree(bo); - ttm_mem_global_free(mem_glob, acc_size); return -EINVAL; } bo->destroy = destroy; @@ -1308,14 +1307,22 @@ int ttm_bo_create(struct ttm_bo_device *bdev, struct ttm_buffer_object **p_bo) { struct ttm_buffer_object *bo; + struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; size_t acc_size; int ret; + acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); + ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); + if (unlikely(ret != 0)) + return ret; + bo = kzalloc(sizeof(*bo), GFP_KERNEL); - if (unlikely(bo == NULL)) + + if (unlikely(bo == NULL)) { + ttm_mem_global_free(mem_glob, acc_size); return -ENOMEM; + } - acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment, buffer_start, interruptible, persistent_swap_storage, acc_size, NULL, NULL); diff --git a/trunk/drivers/gpu/vga/vga_switcheroo.c b/trunk/drivers/gpu/vga/vga_switcheroo.c index 5b3c7d135dc9..38f9534ac513 100644 --- a/trunk/drivers/gpu/vga/vga_switcheroo.c +++ b/trunk/drivers/gpu/vga/vga_switcheroo.c @@ -190,19 +190,6 @@ find_active_client(struct list_head *head) return NULL; } -int vga_switcheroo_get_client_state(struct pci_dev *pdev) -{ - struct vga_switcheroo_client *client; - - client = find_client_from_pci(&vgasr_priv.clients, pdev); - if (!client) - return VGA_SWITCHEROO_NOT_FOUND; - if (!vgasr_priv.active) - return VGA_SWITCHEROO_INIT; - return client->pwr_state; -} -EXPORT_SYMBOL(vga_switcheroo_get_client_state); - void vga_switcheroo_unregister_client(struct pci_dev *pdev) { struct vga_switcheroo_client *client; @@ -304,6 +291,8 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client) vga_switchon(new_client); vga_set_default_device(new_client->pdev); + set_audio_state(new_client->id, VGA_SWITCHEROO_ON); + return 0; } @@ -319,8 +308,6 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) active->active = false; - set_audio_state(active->id, VGA_SWITCHEROO_OFF); - if (new_client->fb_info) { struct fb_event event; event.info = new_client->fb_info; @@ -334,11 +321,11 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) if (new_client->ops->reprobe) new_client->ops->reprobe(new_client->pdev); + set_audio_state(active->id, VGA_SWITCHEROO_OFF); + if (active->pwr_state == VGA_SWITCHEROO_ON) vga_switchoff(active); - set_audio_state(new_client->id, VGA_SWITCHEROO_ON); - new_client->active = true; return 0; } @@ -384,9 +371,8 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, /* pwr off the device not in use */ if (strncmp(usercmd, "OFF", 3) == 0) { list_for_each_entry(client, &vgasr_priv.clients, list) { - if (client->active || client_is_audio(client)) + if (client->active) continue; - set_audio_state(client->id, VGA_SWITCHEROO_OFF); if (client->pwr_state == VGA_SWITCHEROO_ON) vga_switchoff(client); } @@ -395,11 +381,10 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf, /* pwr on the device not in use */ if (strncmp(usercmd, "ON", 2) == 0) { list_for_each_entry(client, &vgasr_priv.clients, list) { - if (client->active || client_is_audio(client)) + if (client->active) continue; if (client->pwr_state == VGA_SWITCHEROO_OFF) vga_switchon(client); - set_audio_state(client->id, VGA_SWITCHEROO_ON); } goto out; } diff --git a/trunk/drivers/i2c/muxes/Kconfig b/trunk/drivers/i2c/muxes/Kconfig index a0edd9854218..beb2491db274 100644 --- a/trunk/drivers/i2c/muxes/Kconfig +++ b/trunk/drivers/i2c/muxes/Kconfig @@ -37,16 +37,4 @@ config I2C_MUX_PCA954x This driver can also be built as a module. If so, the module will be called i2c-mux-pca954x. -config I2C_MUX_PINCTRL - tristate "pinctrl-based I2C multiplexer" - depends on PINCTRL - help - If you say yes to this option, support will be included for an I2C - multiplexer that uses the pinctrl subsystem, i.e. pin multiplexing. - This is useful for SoCs whose I2C module's signals can be routed to - different sets of pins at run-time. - - This driver can also be built as a module. If so, the module will be - called pinctrl-i2cmux. - endmenu diff --git a/trunk/drivers/i2c/muxes/Makefile b/trunk/drivers/i2c/muxes/Makefile index 76da8692afff..5826249b29ca 100644 --- a/trunk/drivers/i2c/muxes/Makefile +++ b/trunk/drivers/i2c/muxes/Makefile @@ -4,6 +4,5 @@ obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o -obj-$(CONFIG_I2C_MUX_PINCTRL) += i2c-mux-pinctrl.o ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/trunk/drivers/i2c/muxes/i2c-mux-pinctrl.c b/trunk/drivers/i2c/muxes/i2c-mux-pinctrl.c deleted file mode 100644 index 46a669763476..000000000000 --- a/trunk/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * I2C multiplexer using pinctrl API - * - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct i2c_mux_pinctrl { - struct device *dev; - struct i2c_mux_pinctrl_platform_data *pdata; - struct pinctrl *pinctrl; - struct pinctrl_state **states; - struct pinctrl_state *state_idle; - struct i2c_adapter *parent; - struct i2c_adapter **busses; -}; - -static int i2c_mux_pinctrl_select(struct i2c_adapter *adap, void *data, - u32 chan) -{ - struct i2c_mux_pinctrl *mux = data; - - return pinctrl_select_state(mux->pinctrl, mux->states[chan]); -} - -static int i2c_mux_pinctrl_deselect(struct i2c_adapter *adap, void *data, - u32 chan) -{ - struct i2c_mux_pinctrl *mux = data; - - return pinctrl_select_state(mux->pinctrl, mux->state_idle); -} - -#ifdef CONFIG_OF -static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, - struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - int num_names, i, ret; - struct device_node *adapter_np; - struct i2c_adapter *adapter; - - if (!np) - return 0; - - mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL); - if (!mux->pdata) { - dev_err(mux->dev, - "Cannot allocate i2c_mux_pinctrl_platform_data\n"); - return -ENOMEM; - } - - num_names = of_property_count_strings(np, "pinctrl-names"); - if (num_names < 0) { - dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n", - num_names); - return num_names; - } - - mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev, - sizeof(*mux->pdata->pinctrl_states) * num_names, - GFP_KERNEL); - if (!mux->pdata->pinctrl_states) { - dev_err(mux->dev, "Cannot allocate pinctrl_states\n"); - return -ENOMEM; - } - - for (i = 0; i < num_names; i++) { - ret = of_property_read_string_index(np, "pinctrl-names", i, - &mux->pdata->pinctrl_states[mux->pdata->bus_count]); - if (ret < 0) { - dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n", - ret); - return ret; - } - if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count], - "idle")) { - if (i != num_names - 1) { - dev_err(mux->dev, "idle state must be last\n"); - return -EINVAL; - } - mux->pdata->pinctrl_state_idle = "idle"; - } else { - mux->pdata->bus_count++; - } - } - - adapter_np = of_parse_phandle(np, "i2c-parent", 0); - if (!adapter_np) { - dev_err(mux->dev, "Cannot parse i2c-parent\n"); - return -ENODEV; - } - adapter = of_find_i2c_adapter_by_node(adapter_np); - if (!adapter) { - dev_err(mux->dev, "Cannot find parent bus\n"); - return -ENODEV; - } - mux->pdata->parent_bus_num = i2c_adapter_id(adapter); - put_device(&adapter->dev); - - return 0; -} -#else -static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, - struct platform_device *pdev) -{ - return 0; -} -#endif - -static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev) -{ - struct i2c_mux_pinctrl *mux; - int (*deselect)(struct i2c_adapter *, void *, u32); - int i, ret; - - mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); - if (!mux) { - dev_err(&pdev->dev, "Cannot allocate i2c_mux_pinctrl\n"); - ret = -ENOMEM; - goto err; - } - platform_set_drvdata(pdev, mux); - - mux->dev = &pdev->dev; - - mux->pdata = pdev->dev.platform_data; - if (!mux->pdata) { - ret = i2c_mux_pinctrl_parse_dt(mux, pdev); - if (ret < 0) - goto err; - } - if (!mux->pdata) { - dev_err(&pdev->dev, "Missing platform data\n"); - ret = -ENODEV; - goto err; - } - - mux->states = devm_kzalloc(&pdev->dev, - sizeof(*mux->states) * mux->pdata->bus_count, - GFP_KERNEL); - if (!mux->states) { - dev_err(&pdev->dev, "Cannot allocate states\n"); - ret = -ENOMEM; - goto err; - } - - mux->busses = devm_kzalloc(&pdev->dev, - sizeof(mux->busses) * mux->pdata->bus_count, - GFP_KERNEL); - if (!mux->states) { - dev_err(&pdev->dev, "Cannot allocate busses\n"); - ret = -ENOMEM; - goto err; - } - - mux->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(mux->pinctrl)) { - ret = PTR_ERR(mux->pinctrl); - dev_err(&pdev->dev, "Cannot get pinctrl: %d\n", ret); - goto err; - } - for (i = 0; i < mux->pdata->bus_count; i++) { - mux->states[i] = pinctrl_lookup_state(mux->pinctrl, - mux->pdata->pinctrl_states[i]); - if (IS_ERR(mux->states[i])) { - ret = PTR_ERR(mux->states[i]); - dev_err(&pdev->dev, - "Cannot look up pinctrl state %s: %d\n", - mux->pdata->pinctrl_states[i], ret); - goto err; - } - } - if (mux->pdata->pinctrl_state_idle) { - mux->state_idle = pinctrl_lookup_state(mux->pinctrl, - mux->pdata->pinctrl_state_idle); - if (IS_ERR(mux->state_idle)) { - ret = PTR_ERR(mux->state_idle); - dev_err(&pdev->dev, - "Cannot look up pinctrl state %s: %d\n", - mux->pdata->pinctrl_state_idle, ret); - goto err; - } - - deselect = i2c_mux_pinctrl_deselect; - } else { - deselect = NULL; - } - - mux->parent = i2c_get_adapter(mux->pdata->parent_bus_num); - if (!mux->parent) { - dev_err(&pdev->dev, "Parent adapter (%d) not found\n", - mux->pdata->parent_bus_num); - ret = -ENODEV; - goto err; - } - - for (i = 0; i < mux->pdata->bus_count; i++) { - u32 bus = mux->pdata->base_bus_num ? - (mux->pdata->base_bus_num + i) : 0; - - mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, - mux, bus, i, - i2c_mux_pinctrl_select, - deselect); - if (!mux->busses[i]) { - ret = -ENODEV; - dev_err(&pdev->dev, "Failed to add adapter %d\n", i); - goto err_del_adapter; - } - } - - return 0; - -err_del_adapter: - for (; i > 0; i--) - i2c_del_mux_adapter(mux->busses[i - 1]); - i2c_put_adapter(mux->parent); -err: - return ret; -} - -static int __devexit i2c_mux_pinctrl_remove(struct platform_device *pdev) -{ - struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < mux->pdata->bus_count; i++) - i2c_del_mux_adapter(mux->busses[i]); - - i2c_put_adapter(mux->parent); - - return 0; -} - -#ifdef CONFIG_OF -static const struct of_device_id i2c_mux_pinctrl_of_match[] __devinitconst = { - { .compatible = "i2c-mux-pinctrl", }, - {}, -}; -MODULE_DEVICE_TABLE(of, i2c_mux_pinctrl_of_match); -#endif - -static struct platform_driver i2c_mux_pinctrl_driver = { - .driver = { - .name = "i2c-mux-pinctrl", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(i2c_mux_pinctrl_of_match), - }, - .probe = i2c_mux_pinctrl_probe, - .remove = __devexit_p(i2c_mux_pinctrl_remove), -}; -module_platform_driver(i2c_mux_pinctrl_driver); - -MODULE_DESCRIPTION("pinctrl-based I2C multiplexer driver"); -MODULE_AUTHOR("Stephen Warren "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:i2c-mux-pinctrl"); diff --git a/trunk/drivers/infiniband/hw/cxgb4/cm.c b/trunk/drivers/infiniband/hw/cxgb4/cm.c index b18870c455ad..55ab284e22f2 100644 --- a/trunk/drivers/infiniband/hw/cxgb4/cm.c +++ b/trunk/drivers/infiniband/hw/cxgb4/cm.c @@ -1593,10 +1593,6 @@ static int import_ep(struct c4iw_ep *ep, __be32 peer_ip, struct dst_entry *dst, struct net_device *pdev; pdev = ip_dev_find(&init_net, peer_ip); - if (!pdev) { - err = -ENODEV; - goto out; - } ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, n, pdev, 0); if (!ep->l2t) diff --git a/trunk/drivers/infiniband/hw/mlx4/main.c b/trunk/drivers/infiniband/hw/mlx4/main.c index 3530c41fcd1f..ee1c577238f7 100644 --- a/trunk/drivers/infiniband/hw/mlx4/main.c +++ b/trunk/drivers/infiniband/hw/mlx4/main.c @@ -140,7 +140,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, props->max_mr_size = ~0ull; props->page_size_cap = dev->dev->caps.page_size_cap; props->max_qp = dev->dev->caps.num_qps - dev->dev->caps.reserved_qps; - props->max_qp_wr = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE; + props->max_qp_wr = dev->dev->caps.max_wqes; props->max_sge = min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg); props->max_cq = dev->dev->caps.num_cqs - dev->dev->caps.reserved_cqs; @@ -1084,9 +1084,12 @@ static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) int total_eqs = 0; int i, j, eq; - /* Legacy mode or comp_pool is not large enough */ - if (dev->caps.comp_pool == 0 || - dev->caps.num_ports > dev->caps.comp_pool) + /* Init eq table */ + ibdev->eq_table = NULL; + ibdev->eq_added = 0; + + /* Legacy mode? */ + if (dev->caps.comp_pool == 0) return; eq_per_port = rounddown_pow_of_two(dev->caps.comp_pool/ @@ -1132,10 +1135,7 @@ static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) { int i; - - /* no additional eqs were added */ - if (!ibdev->eq_table) - return; + int total_eqs; /* Reset the advertised EQ number */ ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors; @@ -1148,7 +1148,12 @@ static void mlx4_ib_free_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev) mlx4_release_eq(dev, ibdev->eq_table[i]); } + total_eqs = dev->caps.num_comp_vectors + ibdev->eq_added; + memset(ibdev->eq_table, 0, total_eqs * sizeof(int)); kfree(ibdev->eq_table); + + ibdev->eq_table = NULL; + ibdev->eq_added = 0; } static void *mlx4_ib_add(struct mlx4_dev *dev) diff --git a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h index ff36655d23d3..e62297cc77cc 100644 --- a/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/trunk/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -44,14 +44,6 @@ #include #include -enum { - MLX4_IB_SQ_MIN_WQE_SHIFT = 6, - MLX4_IB_MAX_HEADROOM = 2048 -}; - -#define MLX4_IB_SQ_HEADROOM(shift) ((MLX4_IB_MAX_HEADROOM >> (shift)) + 1) -#define MLX4_IB_SQ_MAX_SPARE (MLX4_IB_SQ_HEADROOM(MLX4_IB_SQ_MIN_WQE_SHIFT)) - struct mlx4_ib_ucontext { struct ib_ucontext ibucontext; struct mlx4_uar uar; diff --git a/trunk/drivers/infiniband/hw/mlx4/qp.c b/trunk/drivers/infiniband/hw/mlx4/qp.c index 8d4ed24aef93..ceb33327091a 100644 --- a/trunk/drivers/infiniband/hw/mlx4/qp.c +++ b/trunk/drivers/infiniband/hw/mlx4/qp.c @@ -310,8 +310,8 @@ static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, int is_user, int has_rq, struct mlx4_ib_qp *qp) { /* Sanity check RQ size before proceeding */ - if (cap->max_recv_wr > dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE || - cap->max_recv_sge > min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg)) + if (cap->max_recv_wr > dev->dev->caps.max_wqes || + cap->max_recv_sge > dev->dev->caps.max_rq_sg) return -EINVAL; if (!has_rq) { @@ -329,17 +329,8 @@ static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, qp->rq.wqe_shift = ilog2(qp->rq.max_gs * sizeof (struct mlx4_wqe_data_seg)); } - /* leave userspace return values as they were, so as not to break ABI */ - if (is_user) { - cap->max_recv_wr = qp->rq.max_post = qp->rq.wqe_cnt; - cap->max_recv_sge = qp->rq.max_gs; - } else { - cap->max_recv_wr = qp->rq.max_post = - min(dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE, qp->rq.wqe_cnt); - cap->max_recv_sge = min(qp->rq.max_gs, - min(dev->dev->caps.max_sq_sg, - dev->dev->caps.max_rq_sg)); - } + cap->max_recv_wr = qp->rq.max_post = qp->rq.wqe_cnt; + cap->max_recv_sge = qp->rq.max_gs; return 0; } @@ -350,8 +341,8 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, int s; /* Sanity check SQ size before proceeding */ - if (cap->max_send_wr > (dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE) || - cap->max_send_sge > min(dev->dev->caps.max_sq_sg, dev->dev->caps.max_rq_sg) || + if (cap->max_send_wr > dev->dev->caps.max_wqes || + cap->max_send_sge > dev->dev->caps.max_sq_sg || cap->max_inline_data + send_wqe_overhead(type, qp->flags) + sizeof (struct mlx4_wqe_inline_seg) > dev->dev->caps.max_sq_desc_sz) return -EINVAL; diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma.h b/trunk/drivers/infiniband/hw/ocrdma/ocrdma.h index 037f5cea85bd..85a69c958559 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma.h +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma.h @@ -231,6 +231,7 @@ struct ocrdma_qp_hwq_info { u32 entry_size; u32 max_cnt; u32 max_wqe_idx; + u32 free_delta; u16 dbid; /* qid, where to ring the doorbell. */ u32 len; dma_addr_t pa; diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_abi.h b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_abi.h index 517ab20b727c..a411a4e3193d 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_abi.h +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_abi.h @@ -101,6 +101,8 @@ struct ocrdma_create_qp_uresp { u32 rsvd1; u32 num_wqe_allocated; u32 num_rqe_allocated; + u32 free_wqe_delta; + u32 free_rqe_delta; u32 db_sq_offset; u32 db_rq_offset; u32 db_shift; @@ -124,7 +126,8 @@ struct ocrdma_create_srq_uresp { u32 db_rq_offset; u32 db_shift; - u64 rsvd2; + u32 free_rqe_delta; + u32 rsvd2; u64 rsvd3; } __packed; diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_hw.c index 9343a1522977..9b204b1ba336 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_hw.c +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_hw.c @@ -732,7 +732,7 @@ static void ocrdma_dispatch_ibevent(struct ocrdma_dev *dev, break; case OCRDMA_SRQ_LIMIT_EVENT: ib_evt.element.srq = &qp->srq->ibsrq; - ib_evt.event = IB_EVENT_SRQ_LIMIT_REACHED; + ib_evt.event = IB_EVENT_QP_LAST_WQE_REACHED; srq_event = 1; qp_event = 0; break; @@ -1990,12 +1990,19 @@ static void ocrdma_get_create_qp_rsp(struct ocrdma_create_qp_rsp *rsp, max_wqe_allocated = 1 << max_wqe_allocated; max_rqe_allocated = 1 << ((u16)rsp->max_wqe_rqe); + if (qp->dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) { + qp->sq.free_delta = 0; + qp->rq.free_delta = 1; + } else + qp->sq.free_delta = 1; + qp->sq.max_cnt = max_wqe_allocated; qp->sq.max_wqe_idx = max_wqe_allocated - 1; if (!attrs->srq) { qp->rq.max_cnt = max_rqe_allocated; qp->rq.max_wqe_idx = max_rqe_allocated - 1; + qp->rq.free_delta = 1; } } diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 04fef3de6d75..a20d16eaae71 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -26,6 +26,7 @@ *******************************************************************/ #include +#include #include #include #include diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index d16d172b6b6b..e9f74d1b48f6 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -940,6 +940,8 @@ static int ocrdma_copy_qp_uresp(struct ocrdma_qp *qp, uresp.db_rq_offset = OCRDMA_DB_RQ_OFFSET; uresp.db_shift = 16; } + uresp.free_wqe_delta = qp->sq.free_delta; + uresp.free_rqe_delta = qp->rq.free_delta; if (qp->dpp_enabled) { uresp.dpp_credit = dpp_credit_lmt; @@ -1305,6 +1307,8 @@ static int ocrdma_hwq_free_cnt(struct ocrdma_qp_hwq_info *q) free_cnt = (q->max_cnt - q->head) + q->tail; else free_cnt = q->tail - q->head; + if (q->free_delta) + free_cnt -= q->free_delta; return free_cnt; } @@ -1497,6 +1501,7 @@ static int ocrdma_copy_srq_uresp(struct ocrdma_srq *srq, struct ib_udata *udata) (srq->pd->id * srq->dev->nic_info.db_page_size); uresp.db_page_size = srq->dev->nic_info.db_page_size; uresp.num_rqe_allocated = srq->rq.max_cnt; + uresp.free_rqe_delta = 1; if (srq->dev->nic_info.dev_family == OCRDMA_GEN2_FAMILY) { uresp.db_rq_offset = OCRDMA_DB_GEN2_RQ1_OFFSET; uresp.db_shift = 24; diff --git a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h index 633f03d80274..e6483439f25f 100644 --- a/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h +++ b/trunk/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h @@ -28,6 +28,7 @@ #ifndef __OCRDMA_VERBS_H__ #define __OCRDMA_VERBS_H__ +#include int ocrdma_post_send(struct ib_qp *, struct ib_send_wr *, struct ib_send_wr **bad_wr); int ocrdma_post_recv(struct ib_qp *, struct ib_recv_wr *, diff --git a/trunk/drivers/iommu/amd_iommu.c b/trunk/drivers/iommu/amd_iommu.c index a2e418cba0ff..d90a421e9cac 100644 --- a/trunk/drivers/iommu/amd_iommu.c +++ b/trunk/drivers/iommu/amd_iommu.c @@ -547,12 +547,26 @@ static void iommu_poll_events(struct amd_iommu *iommu) spin_unlock_irqrestore(&iommu->lock, flags); } -static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw) +static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u32 head) { struct amd_iommu_fault fault; + volatile u64 *raw; + int i; INC_STATS_COUNTER(pri_requests); + raw = (u64 *)(iommu->ppr_log + head); + + /* + * Hardware bug: Interrupt may arrive before the entry is written to + * memory. If this happens we need to wait for the entry to arrive. + */ + for (i = 0; i < LOOP_TIMEOUT; ++i) { + if (PPR_REQ_TYPE(raw[0]) != 0) + break; + udelay(1); + } + if (PPR_REQ_TYPE(raw[0]) != PPR_REQ_FAULT) { pr_err_ratelimited("AMD-Vi: Unknown PPR request received\n"); return; @@ -564,6 +578,12 @@ static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw) fault.tag = PPR_TAG(raw[0]); fault.flags = PPR_FLAGS(raw[0]); + /* + * To detect the hardware bug we need to clear the entry + * to back to zero. + */ + raw[0] = raw[1] = 0; + atomic_notifier_call_chain(&ppr_notifier, 0, &fault); } @@ -575,62 +595,25 @@ static void iommu_poll_ppr_log(struct amd_iommu *iommu) if (iommu->ppr_log == NULL) return; - /* enable ppr interrupts again */ - writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET); - spin_lock_irqsave(&iommu->lock, flags); head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); while (head != tail) { - volatile u64 *raw; - u64 entry[2]; - int i; - - raw = (u64 *)(iommu->ppr_log + head); - - /* - * Hardware bug: Interrupt may arrive before the entry is - * written to memory. If this happens we need to wait for the - * entry to arrive. - */ - for (i = 0; i < LOOP_TIMEOUT; ++i) { - if (PPR_REQ_TYPE(raw[0]) != 0) - break; - udelay(1); - } - - /* Avoid memcpy function-call overhead */ - entry[0] = raw[0]; - entry[1] = raw[1]; - /* - * To detect the hardware bug we need to clear the entry - * back to zero. - */ - raw[0] = raw[1] = 0UL; + /* Handle PPR entry */ + iommu_handle_ppr_entry(iommu, head); - /* Update head pointer of hardware ring-buffer */ + /* Update and refresh ring-buffer state*/ head = (head + PPR_ENTRY_SIZE) % PPR_LOG_SIZE; writel(head, iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); - - /* - * Release iommu->lock because ppr-handling might need to - * re-aquire it - */ - spin_unlock_irqrestore(&iommu->lock, flags); - - /* Handle PPR entry */ - iommu_handle_ppr_entry(iommu, entry); - - spin_lock_irqsave(&iommu->lock, flags); - - /* Refresh ring-buffer information */ - head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); } + /* enable ppr interrupts again */ + writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET); + spin_unlock_irqrestore(&iommu->lock, flags); } diff --git a/trunk/drivers/iommu/amd_iommu_init.c b/trunk/drivers/iommu/amd_iommu_init.c index 542024ba6dba..c56790375e0f 100644 --- a/trunk/drivers/iommu/amd_iommu_init.c +++ b/trunk/drivers/iommu/amd_iommu_init.c @@ -1029,9 +1029,6 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (!iommu->dev) return 1; - iommu->root_pdev = pci_get_bus_and_slot(iommu->dev->bus->number, - PCI_DEVFN(0, 0)); - iommu->cap_ptr = h->cap_ptr; iommu->pci_seg = h->pci_seg; iommu->mmio_phys = h->mmio_phys; @@ -1326,16 +1323,20 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu) { int i, j; u32 ioc_feature_control; - struct pci_dev *pdev = iommu->root_pdev; + struct pci_dev *pdev = NULL; /* RD890 BIOSes may not have completely reconfigured the iommu */ - if (!is_rd890_iommu(iommu->dev) || !pdev) + if (!is_rd890_iommu(iommu->dev)) return; /* * First, we need to ensure that the iommu is enabled. This is * controlled by a register in the northbridge */ + pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0)); + + if (!pdev) + return; /* Select Northbridge indirect register 0x75 and enable writing */ pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7)); @@ -1345,6 +1346,8 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu) if (!(ioc_feature_control & 0x1)) pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1); + pci_dev_put(pdev); + /* Restore the iommu BAR */ pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4, iommu->stored_addr_lo); diff --git a/trunk/drivers/iommu/amd_iommu_types.h b/trunk/drivers/iommu/amd_iommu_types.h index 24355559a2ad..2452f3b71736 100644 --- a/trunk/drivers/iommu/amd_iommu_types.h +++ b/trunk/drivers/iommu/amd_iommu_types.h @@ -481,9 +481,6 @@ struct amd_iommu { /* Pointer to PCI device of this IOMMU */ struct pci_dev *dev; - /* Cache pdev to root device for resume quirks */ - struct pci_dev *root_pdev; - /* physical address of MMIO space */ u64 mmio_phys; /* virtual address of MMIO space */ diff --git a/trunk/drivers/leds/Kconfig b/trunk/drivers/leds/Kconfig index 12b2b55c519e..04cb8c88d74b 100644 --- a/trunk/drivers/leds/Kconfig +++ b/trunk/drivers/leds/Kconfig @@ -379,7 +379,7 @@ config LEDS_NETXBIG config LEDS_ASIC3 bool "LED support for the HTC ASIC3" - depends on LEDS_CLASS=y + depends on LEDS_CLASS depends on MFD_ASIC3 default y help @@ -390,7 +390,7 @@ config LEDS_ASIC3 config LEDS_RENESAS_TPU bool "LED support for Renesas TPU" - depends on LEDS_CLASS=y && HAVE_CLK && GENERIC_GPIO + depends on LEDS_CLASS && HAVE_CLK && GENERIC_GPIO help This option enables build of the LED TPU platform driver, suitable to drive any TPU channel on newer Renesas SoCs. diff --git a/trunk/drivers/leds/led-class.c b/trunk/drivers/leds/led-class.c index e663e6f413e9..8ee92c81aec2 100644 --- a/trunk/drivers/leds/led-class.c +++ b/trunk/drivers/leds/led-class.c @@ -29,7 +29,7 @@ static void led_update_brightness(struct led_classdev *led_cdev) led_cdev->brightness = led_cdev->brightness_get(led_cdev); } -static ssize_t led_brightness_show(struct device *dev, +static ssize_t led_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *led_cdev = dev_get_drvdata(dev); diff --git a/trunk/drivers/leds/led-core.c b/trunk/drivers/leds/led-core.c index d65353d8d3fc..d6860043f6f9 100644 --- a/trunk/drivers/leds/led-core.c +++ b/trunk/drivers/leds/led-core.c @@ -44,6 +44,13 @@ static void led_set_software_blink(struct led_classdev *led_cdev, if (!led_cdev->blink_brightness) led_cdev->blink_brightness = led_cdev->max_brightness; + if (led_get_trigger_data(led_cdev) && + delay_on == led_cdev->blink_delay_on && + delay_off == led_cdev->blink_delay_off) + return; + + led_stop_software_blink(led_cdev); + led_cdev->blink_delay_on = delay_on; led_cdev->blink_delay_off = delay_off; diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index a9c7981ddd24..835de7168cd3 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -2550,7 +2550,6 @@ static struct r1conf *setup_conf(struct mddev *mddev) err = -EINVAL; spin_lock_init(&conf->device_lock); rdev_for_each(rdev, mddev) { - struct request_queue *q; int disk_idx = rdev->raid_disk; if (disk_idx >= mddev->raid_disks || disk_idx < 0) @@ -2563,9 +2562,6 @@ static struct r1conf *setup_conf(struct mddev *mddev) if (disk->rdev) goto abort; disk->rdev = rdev; - q = bdev_get_queue(rdev->bdev); - if (q->merge_bvec_fn) - mddev->merge_check_needed = 1; disk->head_position = 0; } diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index 99ae6068e456..987db37cb875 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -3475,7 +3475,6 @@ static int run(struct mddev *mddev) rdev_for_each(rdev, mddev) { long long diff; - struct request_queue *q; disk_idx = rdev->raid_disk; if (disk_idx < 0) @@ -3494,9 +3493,6 @@ static int run(struct mddev *mddev) goto out_free_conf; disk->rdev = rdev; } - q = bdev_get_queue(rdev->bdev); - if (q->merge_bvec_fn) - mddev->merge_check_needed = 1; diff = (rdev->new_data_offset - rdev->data_offset); if (!mddev->reshape_backwards) diff = -diff; diff --git a/trunk/drivers/mtd/ubi/debug.c b/trunk/drivers/mtd/ubi/debug.c index 09d4f8d9d592..9f957c2d48e9 100644 --- a/trunk/drivers/mtd/ubi/debug.c +++ b/trunk/drivers/mtd/ubi/debug.c @@ -264,9 +264,6 @@ static struct dentry *dfs_rootdir; */ int ubi_debugfs_init(void) { - if (!IS_ENABLED(DEBUG_FS)) - return 0; - dfs_rootdir = debugfs_create_dir("ubi", NULL); if (IS_ERR_OR_NULL(dfs_rootdir)) { int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir); @@ -284,8 +281,7 @@ int ubi_debugfs_init(void) */ void ubi_debugfs_exit(void) { - if (IS_ENABLED(DEBUG_FS)) - debugfs_remove(dfs_rootdir); + debugfs_remove(dfs_rootdir); } /* Read an UBI debugfs file */ @@ -407,9 +403,6 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) struct dentry *dent; struct ubi_debug_info *d = ubi->dbg; - if (!IS_ENABLED(DEBUG_FS)) - return 0; - n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME, ubi->ubi_num); if (n == UBI_DFS_DIR_LEN) { @@ -477,6 +470,5 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi) */ void ubi_debugfs_exit_dev(struct ubi_device *ubi) { - if (IS_ENABLED(DEBUG_FS)) - debugfs_remove_recursive(ubi->dbg->dfs_dir); + debugfs_remove_recursive(ubi->dbg->dfs_dir); } diff --git a/trunk/drivers/mtd/ubi/wl.c b/trunk/drivers/mtd/ubi/wl.c index b6be644e7b85..9df100a4ec38 100644 --- a/trunk/drivers/mtd/ubi/wl.c +++ b/trunk/drivers/mtd/ubi/wl.c @@ -1262,11 +1262,11 @@ int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum) dbg_wl("flush pending work for LEB %d:%d (%d pending works)", vol_id, lnum, ubi->works_count); + down_write(&ubi->work_sem); while (found) { struct ubi_work *wrk; found = 0; - down_read(&ubi->work_sem); spin_lock(&ubi->wl_lock); list_for_each_entry(wrk, &ubi->works, list) { if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) && @@ -1277,27 +1277,18 @@ int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum) spin_unlock(&ubi->wl_lock); err = wrk->func(ubi, wrk, 0); - if (err) { - up_read(&ubi->work_sem); - return err; - } - + if (err) + goto out; spin_lock(&ubi->wl_lock); found = 1; break; } } spin_unlock(&ubi->wl_lock); - up_read(&ubi->work_sem); } - /* - * Make sure all the works which have been done in parallel are - * finished. - */ - down_write(&ubi->work_sem); +out: up_write(&ubi->work_sem); - return err; } diff --git a/trunk/drivers/net/bonding/bond_3ad.c b/trunk/drivers/net/bonding/bond_3ad.c index a030e635f001..3463b469e657 100644 --- a/trunk/drivers/net/bonding/bond_3ad.c +++ b/trunk/drivers/net/bonding/bond_3ad.c @@ -2454,27 +2454,24 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) out: if (res) { /* no suitable interface, frame not sent */ - kfree_skb(skb); + dev_kfree_skb(skb); } return NETDEV_TX_OK; } -int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, - struct slave *slave) +int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond, + struct slave *slave) { int ret = RX_HANDLER_ANOTHER; - struct lacpdu *lacpdu, _lacpdu; - if (skb->protocol != PKT_TYPE_LACPDU) return ret; - lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu); - if (!lacpdu) + if (!pskb_may_pull(skb, sizeof(struct lacpdu))) return ret; read_lock(&bond->lock); - ret = bond_3ad_rx_indication(lacpdu, slave, skb->len); + ret = bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len); read_unlock(&bond->lock); return ret; } diff --git a/trunk/drivers/net/bonding/bond_3ad.h b/trunk/drivers/net/bonding/bond_3ad.h index 0cfaa4afdece..5ee7e3c45db7 100644 --- a/trunk/drivers/net/bonding/bond_3ad.h +++ b/trunk/drivers/net/bonding/bond_3ad.h @@ -274,8 +274,8 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave); void bond_3ad_handle_link_change(struct slave *slave, char link); int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info); int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev); -int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, - struct slave *slave); +int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond, + struct slave *slave); int bond_3ad_set_carrier(struct bonding *bond); void bond_3ad_update_lacp_rate(struct bonding *bond); #endif //__BOND_3AD_H__ diff --git a/trunk/drivers/net/bonding/bond_alb.c b/trunk/drivers/net/bonding/bond_alb.c index e15cc11edbbe..0f59c1564e53 100644 --- a/trunk/drivers/net/bonding/bond_alb.c +++ b/trunk/drivers/net/bonding/bond_alb.c @@ -342,17 +342,27 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp) _unlock_rx_hashtbl_bh(bond); } -static int rlb_arp_recv(const struct sk_buff *skb, struct bonding *bond, - struct slave *slave) +static int rlb_arp_recv(struct sk_buff *skb, struct bonding *bond, + struct slave *slave) { - struct arp_pkt *arp, _arp; + struct arp_pkt *arp; if (skb->protocol != cpu_to_be16(ETH_P_ARP)) goto out; - arp = skb_header_pointer(skb, 0, sizeof(_arp), &_arp); - if (!arp) + arp = (struct arp_pkt *) skb->data; + if (!arp) { + pr_debug("Packet has no ARP data\n"); goto out; + } + + if (!pskb_may_pull(skb, arp_hdr_len(bond->dev))) + goto out; + + if (skb->len < sizeof(struct arp_pkt)) { + pr_debug("Packet is too small to be an ARP\n"); + goto out; + } if (arp->op_code == htons(ARPOP_REPLY)) { /* update rx hash table for this ARP */ @@ -1346,12 +1356,12 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) } } - read_unlock(&bond->curr_slave_lock); - if (res) { /* no suitable interface, frame not sent */ - kfree_skb(skb); + dev_kfree_skb(skb); } + read_unlock(&bond->curr_slave_lock); + return NETDEV_TX_OK; } diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index f5a40b925f5e..2ee8cf9e8a3b 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -76,7 +76,6 @@ #include #include #include -#include #include "bonding.h" #include "bond_3ad.h" #include "bond_alb.h" @@ -382,6 +381,8 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) return next; } +#define bond_queue_mapping(skb) (*(u16 *)((skb)->cb)) + /** * bond_dev_queue_xmit - Prepare skb for xmit. * @@ -394,9 +395,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, { skb->dev = slave_dev; - BUILD_BUG_ON(sizeof(skb->queue_mapping) != - sizeof(qdisc_skb_cb(skb)->bond_queue_mapping)); - skb->queue_mapping = qdisc_skb_cb(skb)->bond_queue_mapping; + skb->queue_mapping = bond_queue_mapping(skb); if (unlikely(netpoll_tx_running(slave_dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); @@ -1445,8 +1444,8 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) struct sk_buff *skb = *pskb; struct slave *slave; struct bonding *bond; - int (*recv_probe)(const struct sk_buff *, struct bonding *, - struct slave *); + int (*recv_probe)(struct sk_buff *, struct bonding *, + struct slave *); int ret = RX_HANDLER_ANOTHER; skb = skb_share_check(skb, GFP_ATOMIC); @@ -1463,10 +1462,15 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) recv_probe = ACCESS_ONCE(bond->recv_probe); if (recv_probe) { - ret = recv_probe(skb, bond, slave); - if (ret == RX_HANDLER_CONSUMED) { - consume_skb(skb); - return ret; + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); + + if (likely(nskb)) { + ret = recv_probe(nskb, bond, slave); + dev_kfree_skb(nskb); + if (ret == RX_HANDLER_CONSUMED) { + consume_skb(skb); + return ret; + } } } @@ -2733,31 +2737,25 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 } } -static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, - struct slave *slave) +static int bond_arp_rcv(struct sk_buff *skb, struct bonding *bond, + struct slave *slave) { - struct arphdr *arp = (struct arphdr *)skb->data; + struct arphdr *arp; unsigned char *arp_ptr; __be32 sip, tip; - int alen; if (skb->protocol != __cpu_to_be16(ETH_P_ARP)) return RX_HANDLER_ANOTHER; read_lock(&bond->lock); - alen = arp_hdr_len(bond->dev); pr_debug("bond_arp_rcv: bond %s skb->dev %s\n", bond->dev->name, skb->dev->name); - if (alen > skb_headlen(skb)) { - arp = kmalloc(alen, GFP_ATOMIC); - if (!arp) - goto out_unlock; - if (skb_copy_bits(skb, 0, arp, alen) < 0) - goto out_unlock; - } + if (!pskb_may_pull(skb, arp_hdr_len(bond->dev))) + goto out_unlock; + arp = arp_hdr(skb); if (arp->ar_hln != bond->dev->addr_len || skb->pkt_type == PACKET_OTHERHOST || skb->pkt_type == PACKET_LOOPBACK || @@ -2792,8 +2790,6 @@ static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, out_unlock: read_unlock(&bond->lock); - if (arp != (struct arphdr *)skb->data) - kfree(arp); return RX_HANDLER_ANOTHER; } @@ -3990,7 +3986,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev out: if (res) { /* no suitable interface, frame not sent */ - kfree_skb(skb); + dev_kfree_skb(skb); } return NETDEV_TX_OK; @@ -4012,11 +4008,11 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); - read_unlock(&bond->curr_slave_lock); - if (res) /* no suitable interface, frame not sent */ - kfree_skb(skb); + dev_kfree_skb(skb); + + read_unlock(&bond->curr_slave_lock); return NETDEV_TX_OK; } @@ -4055,7 +4051,7 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) if (res) { /* no suitable interface, frame not sent */ - kfree_skb(skb); + dev_kfree_skb(skb); } return NETDEV_TX_OK; @@ -4093,7 +4089,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) res = bond_dev_queue_xmit(bond, skb2, tx_dev); if (res) { - kfree_skb(skb2); + dev_kfree_skb(skb2); continue; } } @@ -4107,7 +4103,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) out: if (res) /* no suitable interface, frame not sent */ - kfree_skb(skb); + dev_kfree_skb(skb); /* frame sent to all suitable interfaces */ return NETDEV_TX_OK; @@ -4175,7 +4171,7 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) /* * Save the original txq to restore before passing to the driver */ - qdisc_skb_cb(skb)->bond_queue_mapping = skb->queue_mapping; + bond_queue_mapping(skb) = skb->queue_mapping; if (unlikely(txq >= dev->real_num_tx_queues)) { do { @@ -4213,7 +4209,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev pr_err("%s: Error: Unknown bonding mode %d\n", dev->name, bond->params.mode); WARN_ON_ONCE(1); - kfree_skb(skb); + dev_kfree_skb(skb); return NETDEV_TX_OK; } } @@ -4235,7 +4231,7 @@ static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev) if (bond->slave_cnt) ret = __bond_start_xmit(skb, dev); else - kfree_skb(skb); + dev_kfree_skb(skb); read_unlock(&bond->lock); diff --git a/trunk/drivers/net/bonding/bond_sysfs.c b/trunk/drivers/net/bonding/bond_sysfs.c index 485bedb8278c..aef42f045320 100644 --- a/trunk/drivers/net/bonding/bond_sysfs.c +++ b/trunk/drivers/net/bonding/bond_sysfs.c @@ -1082,12 +1082,8 @@ static ssize_t bonding_store_primary(struct device *d, } } - strncpy(bond->params.primary, ifname, IFNAMSIZ); - bond->params.primary[IFNAMSIZ - 1] = 0; - - pr_info("%s: Recording %s as primary, " - "but it has not been enslaved to %s yet.\n", - bond->dev->name, ifname, bond->dev->name); + pr_info("%s: Unable to set %.*s as primary slave.\n", + bond->dev->name, (int)strlen(buf) - 1, buf); out: write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); diff --git a/trunk/drivers/net/bonding/bonding.h b/trunk/drivers/net/bonding/bonding.h index f8af2fcd3d16..4581aa5ccaba 100644 --- a/trunk/drivers/net/bonding/bonding.h +++ b/trunk/drivers/net/bonding/bonding.h @@ -218,8 +218,8 @@ struct bonding { struct slave *primary_slave; bool force_primary; s32 slave_cnt; /* never change this value outside the attach/detach wrappers */ - int (*recv_probe)(const struct sk_buff *, struct bonding *, - struct slave *); + int (*recv_probe)(struct sk_buff *, struct bonding *, + struct slave *); rwlock_t lock; rwlock_t curr_slave_lock; u8 send_peer_notif; diff --git a/trunk/drivers/net/can/c_can/c_can.c b/trunk/drivers/net/can/c_can/c_can.c index eea660800a09..e2ce508c2753 100644 --- a/trunk/drivers/net/can/c_can/c_can.c +++ b/trunk/drivers/net/can/c_can/c_can.c @@ -594,8 +594,8 @@ static void c_can_chip_config(struct net_device *dev) priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR); - if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) && - (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) { + if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY & + CAN_CTRLMODE_LOOPBACK)) { /* loopback + silent mode : useful for hot self-test */ priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_EIE | CONTROL_SIE | CONTROL_IE | CONTROL_TEST); diff --git a/trunk/drivers/net/dummy.c b/trunk/drivers/net/dummy.c index bab0158f1cc3..442d91a2747b 100644 --- a/trunk/drivers/net/dummy.c +++ b/trunk/drivers/net/dummy.c @@ -187,10 +187,8 @@ static int __init dummy_init_module(void) rtnl_lock(); err = __rtnl_link_register(&dummy_link_ops); - for (i = 0; i < numdummies && !err; i++) { + for (i = 0; i < numdummies && !err; i++) err = dummy_init_one(); - cond_resched(); - } if (err < 0) __rtnl_link_unregister(&dummy_link_ops); rtnl_unlock(); diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 7de824184979..e30e2a2f354c 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -747,6 +747,21 @@ struct bnx2x_fastpath { #define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG +#define BNX2X_IP_CSUM_ERR(cqe) \ + (!((cqe)->fast_path_cqe.status_flags & \ + ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \ + ((cqe)->fast_path_cqe.type_error_flags & \ + ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG)) + +#define BNX2X_L4_CSUM_ERR(cqe) \ + (!((cqe)->fast_path_cqe.status_flags & \ + ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \ + ((cqe)->fast_path_cqe.type_error_flags & \ + ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) + +#define BNX2X_RX_CSUM_OK(cqe) \ + (!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe))) + #define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \ (((le16_to_cpu(flags) & \ PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 8098eea9704d..ad0743bf4bde 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -190,7 +190,7 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) if ((netif_tx_queue_stopped(txq)) && (bp->state == BNX2X_STATE_OPEN) && - (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 4)) + (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3)) netif_tx_wake_queue(txq); __netif_tx_unlock(txq); @@ -617,25 +617,6 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp, return 0; } -static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, - struct bnx2x_fastpath *fp) -{ - /* Do nothing if no IP/L4 csum validation was done */ - - if (cqe->fast_path_cqe.status_flags & - (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | - ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) - return; - - /* If both IP/L4 validation were done, check if an error was found. */ - - if (cqe->fast_path_cqe.type_error_flags & - (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | - ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) - fp->eth_q_stats.hw_csum_err++; - else - skb->ip_summed = CHECKSUM_UNNECESSARY; -} int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) { @@ -825,9 +806,13 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) skb_checksum_none_assert(skb); - if (bp->dev->features & NETIF_F_RXCSUM) - bnx2x_csum_validate(skb, cqe, fp); + if (bp->dev->features & NETIF_F_RXCSUM) { + if (likely(BNX2X_RX_CSUM_OK(cqe))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + fp->eth_q_stats.hw_csum_err++; + } skb_record_rx_queue(skb, fp->rx_queue); @@ -2516,6 +2501,8 @@ int bnx2x_poll(struct napi_struct *napi, int budget) /* we split the first BD into headers and data BDs * to ease the pain of our fellow microcode engineers * we use one mapping for both BDs + * So far this has only been observed to happen + * in Other Operating Systems(TM) */ static noinline u16 bnx2x_tx_split(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, @@ -3169,7 +3156,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) txdata->tx_bd_prod += nbd; - if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 4)) { + if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 3)) { netif_tx_stop_queue(txq); /* paired memory barrier is in bnx2x_tx_int(), we have to keep @@ -3178,7 +3165,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) smp_mb(); fp->eth_q_stats.driver_xoff++; - if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 4) + if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3) netif_tx_wake_queue(txq); } txdata->tx_pkt++; diff --git a/trunk/drivers/net/ethernet/broadcom/tg3.c b/trunk/drivers/net/ethernet/broadcom/tg3.c index e47ff8be1d7b..edeeb516807a 100644 --- a/trunk/drivers/net/ethernet/broadcom/tg3.c +++ b/trunk/drivers/net/ethernet/broadcom/tg3.c @@ -14275,8 +14275,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - if (tg3_flag(tp, 5755_PLUS) || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) + if (tg3_flag(tp, 5755_PLUS)) tg3_flag_set(tp, SHORT_DMA_BUG); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_main.c b/trunk/drivers/net/ethernet/emulex/benet/be_main.c index 5a34503b6a14..896f283967d4 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_main.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_main.c @@ -736,8 +736,6 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb); if (copied) { - int gso_segs = skb_shinfo(skb)->gso_segs; - /* record the sent skb in the sent_skb table */ BUG_ON(txo->sent_skb_list[start]); txo->sent_skb_list[start] = skb; @@ -755,7 +753,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, be_txq_notify(adapter, txq->id, wrb_cnt); - be_tx_stats_update(txo, wrb_cnt, copied, gso_segs, stopped); + be_tx_stats_update(txo, wrb_cnt, copied, + skb_shinfo(skb)->gso_segs, stopped); } else { txq->head = start; dev_kfree_skb_any(skb); diff --git a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c index ba86b3f8a404..31d37a2b5ba8 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c @@ -6238,8 +6238,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, } if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) - dev_info(&pdev->dev, - "PHY reset is blocked due to SOL/IDER session.\n"); + e_info("PHY reset is blocked due to SOL/IDER session.\n"); /* Set initial default active device features */ netdev->features = (NETIF_F_SG | @@ -6289,7 +6288,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (e1000_validate_nvm_checksum(&adapter->hw) >= 0) break; if (i == 2) { - dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); + e_err("The NVM Checksum Is Not Valid\n"); err = -EIO; goto err_eeprom; } @@ -6299,15 +6298,13 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* copy the MAC address */ if (e1000e_read_mac_addr(&adapter->hw)) - dev_err(&pdev->dev, - "NVM Read Error while reading MAC address\n"); + e_err("NVM Read Error while reading MAC address\n"); memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len); if (!is_valid_ether_addr(netdev->perm_addr)) { - dev_err(&pdev->dev, "Invalid MAC Address: %pM\n", - netdev->perm_addr); + e_err("Invalid MAC Address: %pM\n", netdev->perm_addr); err = -EIO; goto err_eeprom; } diff --git a/trunk/drivers/net/ethernet/intel/e1000e/param.c b/trunk/drivers/net/ethernet/intel/e1000e/param.c index dfbfa7fd98c3..55cc1565bc2f 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/param.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/param.c @@ -199,19 +199,16 @@ static int __devinit e1000_validate_option(unsigned int *value, case enable_option: switch (*value) { case OPTION_ENABLED: - dev_info(&adapter->pdev->dev, "%s Enabled\n", - opt->name); + e_info("%s Enabled\n", opt->name); return 0; case OPTION_DISABLED: - dev_info(&adapter->pdev->dev, "%s Disabled\n", - opt->name); + e_info("%s Disabled\n", opt->name); return 0; } break; case range_option: if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - dev_info(&adapter->pdev->dev, "%s set to %i\n", - opt->name, *value); + e_info("%s set to %i\n", opt->name, *value); return 0; } break; @@ -223,8 +220,7 @@ static int __devinit e1000_validate_option(unsigned int *value, ent = &opt->arg.l.p[i]; if (*value == ent->i) { if (ent->str[0] != '\0') - dev_info(&adapter->pdev->dev, "%s\n", - ent->str); + e_info("%s\n", ent->str); return 0; } } @@ -234,8 +230,8 @@ static int __devinit e1000_validate_option(unsigned int *value, BUG(); } - dev_info(&adapter->pdev->dev, "Invalid %s value specified (%i) %s\n", - opt->name, *value, opt->err); + e_info("Invalid %s value specified (%i) %s\n", opt->name, *value, + opt->err); *value = opt->def; return -1; } @@ -255,10 +251,8 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) int bd = adapter->bd_number; if (bd >= E1000_MAX_NIC) { - dev_notice(&adapter->pdev->dev, - "Warning: no configuration for board #%i\n", bd); - dev_notice(&adapter->pdev->dev, - "Using defaults for all values\n"); + e_notice("Warning: no configuration for board #%i\n", bd); + e_notice("Using defaults for all values\n"); } { /* Transmit Interrupt Delay */ @@ -372,32 +366,27 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) * default values */ if (adapter->itr > 4) - dev_info(&adapter->pdev->dev, - "%s set to default %d\n", opt.name, - adapter->itr); + e_info("%s set to default %d\n", opt.name, + adapter->itr); } adapter->itr_setting = adapter->itr; switch (adapter->itr) { case 0: - dev_info(&adapter->pdev->dev, "%s turned off\n", - opt.name); + e_info("%s turned off\n", opt.name); break; case 1: - dev_info(&adapter->pdev->dev, - "%s set to dynamic mode\n", opt.name); + e_info("%s set to dynamic mode\n", opt.name); adapter->itr = 20000; break; case 3: - dev_info(&adapter->pdev->dev, - "%s set to dynamic conservative mode\n", - opt.name); + e_info("%s set to dynamic conservative mode\n", + opt.name); adapter->itr = 20000; break; case 4: - dev_info(&adapter->pdev->dev, - "%s set to simplified (2000-8000 ints) mode\n", - opt.name); + e_info("%s set to simplified (2000-8000 ints) mode\n", + opt.name); break; default: /* diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/Makefile b/trunk/drivers/net/ethernet/intel/ixgbe/Makefile index 5fd5d04c26c9..0bdf06bc5c49 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/Makefile +++ b/trunk/drivers/net/ethernet/intel/ixgbe/Makefile @@ -34,11 +34,11 @@ obj-$(CONFIG_IXGBE) += ixgbe.o ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \ - ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o + ixgbe_mbx.o ixgbe_x540.o ixgbe_sysfs.o ixgbe_lib.o ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \ ixgbe_dcb_82599.o ixgbe_dcb_nl.o ixgbe-$(CONFIG_IXGBE_PTP) += ixgbe_ptp.o -ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o + ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 41f9f6e2a4c1..3ef3c5284e52 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -561,7 +561,6 @@ struct ixgbe_adapter { spinlock_t tmreg_lock; struct cyclecounter cc; struct timecounter tc; - int rx_hwtstamp_filter; u32 base_incval; u32 cycle_speed; #endif /* CONFIG_IXGBE_PTP */ @@ -719,7 +718,6 @@ extern void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter); extern void ixgbe_ptp_tx_hwtstamp(struct ixgbe_q_vector *q_vector, struct sk_buff *skb); extern void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, - union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb); extern int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, struct ifreq *ifr, int cmd); diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index b0ddfd47e473..17ad6a3c1be1 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -790,10 +790,12 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, total_packets += tx_buffer->gso_segs; #ifdef CONFIG_IXGBE_PTP - if (unlikely(tx_buffer->tx_flags & IXGBE_TX_FLAGS_TSTAMP)) - ixgbe_ptp_tx_hwtstamp(q_vector, tx_buffer->skb); -#endif + if (unlikely(tx_buffer->tx_flags & + IXGBE_TX_FLAGS_TSTAMP)) + ixgbe_ptp_tx_hwtstamp(q_vector, + tx_buffer->skb); +#endif /* free the skb */ dev_kfree_skb_any(tx_buffer->skb); @@ -1397,7 +1399,8 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, ixgbe_rx_checksum(rx_ring, rx_desc, skb); #ifdef CONFIG_IXGBE_PTP - ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb); + if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS)) + ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb); #endif if ((dev->features & NETIF_F_HW_VLAN_RX) && diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index cb7d1b2982c5..ddc6a4d19302 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -26,7 +26,6 @@ *******************************************************************************/ #include "ixgbe.h" #include -#include /* * The 82599 and the X540 do not have true 64bit nanosecond scale @@ -101,10 +100,6 @@ #define NSECS_PER_SEC 1000000000ULL #endif -static struct sock_filter ptp_filter[] = { - PTP_FILTER -}; - /** * ixgbe_ptp_read - read raw cycle counter (to be used by time counter) * @cc - the cyclecounter structure @@ -312,14 +307,13 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr) !(adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED)) return; - if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) { - switch (hw->mac.type) { - case ixgbe_mac_X540: + switch (hw->mac.type) { + case ixgbe_mac_X540: + if (eicr & IXGBE_EICR_TIMESYNC) ptp_clock_event(adapter->ptp_clock, &event); - break; - default: - break; - } + break; + default: + break; } } @@ -430,68 +424,6 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter) } } -/** - * ixgbe_ptp_match - determine if this skb matches a ptp packet - * @skb: pointer to the skb - * @hwtstamp: pointer to the hwtstamp_config to check - * - * Determine whether the skb should have been timestamped, assuming the - * hwtstamp was set via the hwtstamp ioctl. Returns non-zero when the packet - * should have a timestamp waiting in the registers, and 0 otherwise. - * - * V1 packets have to check the version type to determine whether they are - * correct. However, we can't directly access the data because it might be - * fragmented in the SKB, in paged memory. In order to work around this, we - * use skb_copy_bits which will properly copy the data whether it is in the - * paged memory fragments or not. We have to copy the IP header as well as the - * message type. - */ -static int ixgbe_ptp_match(struct sk_buff *skb, int rx_filter) -{ - struct iphdr iph; - u8 msgtype; - unsigned int type, offset; - - if (rx_filter == HWTSTAMP_FILTER_NONE) - return 0; - - type = sk_run_filter(skb, ptp_filter); - - if (likely(rx_filter == HWTSTAMP_FILTER_PTP_V2_EVENT)) - return type & PTP_CLASS_V2; - - /* For the remaining cases actually check message type */ - switch (type) { - case PTP_CLASS_V1_IPV4: - skb_copy_bits(skb, OFF_IHL, &iph, sizeof(iph)); - offset = ETH_HLEN + (iph.ihl << 2) + UDP_HLEN + OFF_PTP_CONTROL; - break; - case PTP_CLASS_V1_IPV6: - offset = OFF_PTP6 + OFF_PTP_CONTROL; - break; - default: - /* other cases invalid or handled above */ - return 0; - } - - /* Make sure our buffer is long enough */ - if (skb->len < offset) - return 0; - - skb_copy_bits(skb, offset, &msgtype, sizeof(msgtype)); - - switch (rx_filter) { - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - return (msgtype == IXGBE_RXMTRL_V1_SYNC_MSG); - break; - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - return (msgtype == IXGBE_RXMTRL_V1_DELAY_REQ_MSG); - break; - default: - return 0; - } -} - /** * ixgbe_ptp_tx_hwtstamp - utility function which checks for TX time stamp * @q_vector: structure containing interrupt and ring information @@ -541,7 +473,6 @@ void ixgbe_ptp_tx_hwtstamp(struct ixgbe_q_vector *q_vector, /** * ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp * @q_vector: structure containing interrupt and ring information - * @rx_desc: the rx descriptor * @skb: particular skb to send timestamp with * * if the timestamp is valid, we convert it into the timecounter ns @@ -549,7 +480,6 @@ void ixgbe_ptp_tx_hwtstamp(struct ixgbe_q_vector *q_vector, * is passed up the network stack */ void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, - union ixgbe_adv_rx_desc *rx_desc, struct sk_buff *skb) { struct ixgbe_adapter *adapter; @@ -567,33 +497,21 @@ void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, hw = &adapter->hw; tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); - - /* Check if we have a valid timestamp and make sure the skb should - * have been timestamped */ - if (likely(!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID) || - !ixgbe_ptp_match(skb, adapter->rx_hwtstamp_filter))) - return; - - /* - * Always read the registers, in order to clear a possible fault - * because of stagnant RX timestamp values for a packet that never - * reached the queue. - */ regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPL); regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPH) << 32; /* - * If the timestamp bit is set in the packet's descriptor, we know the - * timestamp belongs to this packet. No other packet can be - * timestamped until the registers for timestamping have been read. - * Therefor only one packet with this bit can be in the queue at a - * time, and the rx timestamp values that were in the registers belong - * to this packet. + * If this bit is set, then the RX registers contain the time stamp. No + * other packet will be time stamped until we read these registers, so + * read the registers to make them available again. Because only one + * packet can be time stamped at a time, we know that the register + * values must belong to this one here and therefore we don't need to + * compare any of the additional attributes stored for it. * * If nothing went wrong, then it should have a skb_shared_tx that we * can turn into a skb_shared_hwtstamps. */ - if (unlikely(!ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS))) + if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID)) return; spin_lock_irqsave(&adapter->tmreg_lock, flags); @@ -621,11 +539,6 @@ void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, * type has to be specified. Matching the kind of event packet is * not supported, with the exception of "all V2 events regardless of * level 2 or 4". - * - * Since hardware always timestamps Path delay packets when timestamping V2 - * packets, regardless of the type specified in the register, only use V2 - * Event mode. This more accurately tells the user what the hardware is going - * to do anyways. */ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, struct ifreq *ifr, int cmd) @@ -669,30 +582,41 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG; is_l4 = true; break; - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2; + tsync_rx_mtrl = IXGBE_RXMTRL_V2_SYNC_MSG; + is_l2 = true; + is_l4 = true; + config.rx_filter = HWTSTAMP_FILTER_SOME; + break; case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2; + tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L2_L4_V2; + tsync_rx_mtrl = IXGBE_RXMTRL_V2_DELAY_REQ_MSG; is_l2 = true; is_l4 = true; + config.rx_filter = HWTSTAMP_FILTER_SOME; + break; + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2; config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; + is_l2 = true; + is_l4 = true; break; case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: case HWTSTAMP_FILTER_ALL: default: /* - * register RXMTRL must be set in order to do V1 packets, - * therefore it is not possible to time stamp both V1 Sync and - * Delay_Req messages and hardware does not support - * timestamping all packets => return error + * register RXMTRL must be set, therefore it is not + * possible to time stamp both V1 Sync and Delay_Req messages + * and hardware does not support timestamping all packets + * => return error */ - config.rx_filter = HWTSTAMP_FILTER_NONE; return -ERANGE; } @@ -702,9 +626,6 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, return 0; } - /* Store filter value for later use */ - adapter->rx_hwtstamp_filter = config.rx_filter; - /* define ethertype filter for timestamped packets */ if (is_l2) IXGBE_WRITE_REG(hw, IXGBE_ETQF(3), @@ -940,10 +861,6 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) return; } - /* initialize the ptp filter */ - if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) - e_dev_warn("ptp_filter_init failed\n"); - spin_lock_init(&adapter->tmreg_lock); ixgbe_ptp_start_cyclecounter(adapter); diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c index 2334fce47018..1d80b1cefa6a 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_sysfs.c @@ -37,6 +37,7 @@ #include #include +#ifdef CONFIG_IXGBE_HWMON /* hwmon callback functions */ static ssize_t ixgbe_hwmon_show_location(struct device *dev, struct device_attribute *attr, @@ -240,4 +241,5 @@ int ixgbe_sysfs_init(struct ixgbe_adapter *adapter) exit: return rc; } +#endif /* CONFIG_IXGBE_HWMON */ diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 1085c0739a3c..204848d2448c 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -2419,7 +2419,7 @@ typedef u32 ixgbe_physical_layer; */ /* BitTimes (BT) conversion */ -#define IXGBE_BT2KB(BT) ((BT + (8 * 1024 - 1)) / (8 * 1024)) +#define IXGBE_BT2KB(BT) ((BT + 1023) / (8 * 1024)) #define IXGBE_B2BT(BT) (BT * 8) /* Calculate Delay to respond to PFC */ @@ -2450,31 +2450,24 @@ typedef u32 ixgbe_physical_layer; #define IXGBE_PCI_DELAY 10000 /* Calculate X540 delay value in bit times */ -#define IXGBE_DV_X540(_max_frame_link, _max_frame_tc) \ - ((36 * \ - (IXGBE_B2BT(_max_frame_link) + \ - IXGBE_PFC_D + \ - (2 * IXGBE_CABLE_DC) + \ - (2 * IXGBE_ID_X540) + \ - IXGBE_HD) / 25 + 1) + \ - 2 * IXGBE_B2BT(_max_frame_tc)) +#define IXGBE_FILL_RATE (36 / 25) + +#define IXGBE_DV_X540(LINK, TC) (IXGBE_FILL_RATE * \ + (IXGBE_B2BT(LINK) + IXGBE_PFC_D + \ + (2 * IXGBE_CABLE_DC) + \ + (2 * IXGBE_ID_X540) + \ + IXGBE_HD + IXGBE_B2BT(TC))) /* Calculate 82599, 82598 delay value in bit times */ -#define IXGBE_DV(_max_frame_link, _max_frame_tc) \ - ((36 * \ - (IXGBE_B2BT(_max_frame_link) + \ - IXGBE_PFC_D + \ - (2 * IXGBE_CABLE_DC) + \ - (2 * IXGBE_ID) + \ - IXGBE_HD) / 25 + 1) + \ - 2 * IXGBE_B2BT(_max_frame_tc)) +#define IXGBE_DV(LINK, TC) (IXGBE_FILL_RATE * \ + (IXGBE_B2BT(LINK) + IXGBE_PFC_D + \ + (2 * IXGBE_CABLE_DC) + (2 * IXGBE_ID) + \ + IXGBE_HD + IXGBE_B2BT(TC))) /* Calculate low threshold delay values */ -#define IXGBE_LOW_DV_X540(_max_frame_tc) \ - (2 * IXGBE_B2BT(_max_frame_tc) + \ - (36 * IXGBE_PCI_DELAY / 25) + 1) -#define IXGBE_LOW_DV(_max_frame_tc) \ - (2 * IXGBE_LOW_DV_X540(_max_frame_tc)) +#define IXGBE_LOW_DV_X540(TC) (2 * IXGBE_B2BT(TC) + \ + (IXGBE_FILL_RATE * IXGBE_PCI_DELAY)) +#define IXGBE_LOW_DV(TC) (2 * IXGBE_LOW_DV_X540(TC)) /* Software ATR hash keys */ #define IXGBE_ATR_BUCKET_HASH_KEY 0x3DAD14E2 diff --git a/trunk/drivers/net/ethernet/marvell/sky2.c b/trunk/drivers/net/ethernet/marvell/sky2.c index 28a54451a3e5..cace36f2ab92 100644 --- a/trunk/drivers/net/ethernet/marvell/sky2.c +++ b/trunk/drivers/net/ethernet/marvell/sky2.c @@ -4381,12 +4381,10 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features) struct sky2_port *sky2 = netdev_priv(dev); netdev_features_t changed = dev->features ^ features; - if ((changed & NETIF_F_RXCSUM) && - !(sky2->hw->flags & SKY2_HW_NEW_LE)) { - sky2_write32(sky2->hw, - Q_ADDR(rxqaddr[sky2->port], Q_CSR), - (features & NETIF_F_RXCSUM) - ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + if (changed & NETIF_F_RXCSUM) { + bool on = features & NETIF_F_RXCSUM; + sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), + on ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } if (changed & NETIF_F_RXHASH) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/port.c b/trunk/drivers/net/ethernet/mellanox/mlx4/port.c index a8fb52992c64..1fe2c7a8b40c 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/port.c @@ -697,10 +697,10 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, if (slave != dev->caps.function) memset(inbox->buf, 0, 256); if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { - *(u8 *) inbox->buf |= !!reset_qkey_viols << 6; + *(u8 *) inbox->buf = !!reset_qkey_viols << 6; ((__be32 *) inbox->buf)[2] = agg_cap_mask; } else { - ((u8 *) inbox->buf)[3] |= !!reset_qkey_viols; + ((u8 *) inbox->buf)[3] = !!reset_qkey_viols; ((__be32 *) inbox->buf)[1] = agg_cap_mask; } diff --git a/trunk/drivers/net/ethernet/nxp/lpc_eth.c b/trunk/drivers/net/ethernet/nxp/lpc_eth.c index 083d6715335c..8d2666fcffd7 100644 --- a/trunk/drivers/net/ethernet/nxp/lpc_eth.c +++ b/trunk/drivers/net/ethernet/nxp/lpc_eth.c @@ -946,16 +946,16 @@ static void __lpc_handle_xmit(struct net_device *ndev) /* Update stats */ ndev->stats.tx_packets++; ndev->stats.tx_bytes += skb->len; + + /* Free buffer */ + dev_kfree_skb_irq(skb); } - dev_kfree_skb_irq(skb); txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base)); } - if (pldat->num_used_tx_buffs <= ENET_TX_DESC/2) { - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); - } + if (netif_queue_stopped(ndev)) + netif_wake_queue(ndev); } static int __lpc_handle_recv(struct net_device *ndev, int budget) @@ -1320,7 +1320,6 @@ static const struct net_device_ops lpc_netdev_ops = { .ndo_set_rx_mode = lpc_eth_set_multicast_list, .ndo_do_ioctl = lpc_eth_ioctl, .ndo_set_mac_address = lpc_set_mac_address, - .ndo_change_mtu = eth_change_mtu, }; static int lpc_eth_drv_probe(struct platform_device *pdev) diff --git a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 212c12193275..33c3e46e59c4 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -479,7 +479,7 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter) for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { pfn = pci_info[i].id; - if (pfn >= QLCNIC_MAX_PCI_FUNC) { + if (pfn > QLCNIC_MAX_PCI_FUNC) { ret = QL_STATUS_INVALID_PARAM; goto err_eswitch; } diff --git a/trunk/drivers/net/ethernet/realtek/r8169.c b/trunk/drivers/net/ethernet/realtek/r8169.c index 7260aa79466a..9757ce3543a0 100644 --- a/trunk/drivers/net/ethernet/realtek/r8169.c +++ b/trunk/drivers/net/ethernet/realtek/r8169.c @@ -5889,7 +5889,11 @@ static void rtl_slow_event_work(struct rtl8169_private *tp) if (status & LinkChg) __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true); - rtl_irq_enable_all(tp); + napi_disable(&tp->napi); + rtl_irq_disable(tp); + + napi_enable(&tp->napi); + napi_schedule(&tp->napi); } static void rtl_task(struct work_struct *work) diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/Kconfig b/trunk/drivers/net/ethernet/stmicro/stmmac/Kconfig index 9f448279e12a..0076f770e637 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -15,7 +15,6 @@ if STMMAC_ETH config STMMAC_PLATFORM bool "STMMAC Platform bus support" depends on STMMAC_ETH - default y ---help--- This selects the platform specific bus support for the stmmac device driver. This is the driver used diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h index dc20c56efc9d..6d07ba2c8661 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -26,7 +26,6 @@ #include #include #include -#include #include "common.h" #ifdef CONFIG_STMMAC_TIMER #include "stmmac_timer.h" @@ -96,6 +95,8 @@ extern int stmmac_mdio_register(struct net_device *ndev); extern void stmmac_set_ethtool_ops(struct net_device *netdev); extern const struct stmmac_desc_ops enh_desc_ops; extern const struct stmmac_desc_ops ndesc_ops; +extern struct pci_driver stmmac_pci_driver; +extern struct platform_driver stmmac_pltfr_driver; int stmmac_freeze(struct net_device *ndev); int stmmac_restore(struct net_device *ndev); int stmmac_resume(struct net_device *ndev); @@ -109,7 +110,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, static inline int stmmac_clk_enable(struct stmmac_priv *priv) { if (!IS_ERR(priv->stmmac_clk)) - return clk_prepare_enable(priv->stmmac_clk); + return clk_enable(priv->stmmac_clk); return 0; } @@ -119,7 +120,7 @@ static inline void stmmac_clk_disable(struct stmmac_priv *priv) if (IS_ERR(priv->stmmac_clk)) return; - clk_disable_unprepare(priv->stmmac_clk); + clk_disable(priv->stmmac_clk); } static inline int stmmac_clk_get(struct stmmac_priv *priv) { @@ -143,60 +144,3 @@ static inline int stmmac_clk_get(struct stmmac_priv *priv) return 0; } #endif /* CONFIG_HAVE_CLK */ - - -#ifdef CONFIG_STMMAC_PLATFORM -extern struct platform_driver stmmac_pltfr_driver; -static inline int stmmac_register_platform(void) -{ - int err; - - err = platform_driver_register(&stmmac_pltfr_driver); - if (err) - pr_err("stmmac: failed to register the platform driver\n"); - - return err; -} -static inline void stmmac_unregister_platform(void) -{ - platform_driver_register(&stmmac_pltfr_driver); -} -#else -static inline int stmmac_register_platform(void) -{ - pr_debug("stmmac: do not register the platf driver\n"); - - return -EINVAL; -} -static inline void stmmac_unregister_platform(void) -{ -} -#endif /* CONFIG_STMMAC_PLATFORM */ - -#ifdef CONFIG_STMMAC_PCI -extern struct pci_driver stmmac_pci_driver; -static inline int stmmac_register_pci(void) -{ - int err; - - err = pci_register_driver(&stmmac_pci_driver); - if (err) - pr_err("stmmac: failed to register the PCI driver\n"); - - return err; -} -static inline void stmmac_unregister_pci(void) -{ - pci_unregister_driver(&stmmac_pci_driver); -} -#else -static inline int stmmac_register_pci(void) -{ - pr_debug("stmmac: do not register the PCI driver\n"); - - return -EINVAL; -} -static inline void stmmac_unregister_pci(void) -{ -} -#endif /* CONFIG_STMMAC_PCI */ diff --git a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 590e95b4cbfa..8899e105da9f 100644 --- a/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -42,6 +42,7 @@ #include #include #include +#include #ifdef CONFIG_STMMAC_DEBUG_FS #include #include @@ -2092,29 +2093,25 @@ int stmmac_restore(struct net_device *ndev) } #endif /* CONFIG_PM */ -/* Driver can be configured w/ and w/ both PCI and Platf drivers - * depending on the configuration selected. - */ static int __init stmmac_init(void) { - int err_plt = 0; - int err_pci = 0; + int err = 0; - err_plt = stmmac_register_platform(); - err_pci = stmmac_register_pci(); + err = platform_driver_register(&stmmac_pltfr_driver); - if ((err_pci) && (err_plt)) { - pr_err("stmmac: driver registration failed\n"); - return -EINVAL; + if (!err) { + err = pci_register_driver(&stmmac_pci_driver); + if (err) + platform_driver_unregister(&stmmac_pltfr_driver); } - return 0; + return err; } static void __exit stmmac_exit(void) { - stmmac_unregister_platform(); - stmmac_unregister_pci(); + pci_unregister_driver(&stmmac_pci_driver); + platform_driver_unregister(&stmmac_pltfr_driver); } module_init(stmmac_init); diff --git a/trunk/drivers/net/ethernet/sun/niu.c b/trunk/drivers/net/ethernet/sun/niu.c index 8c726b7004d3..703c8cce2a2c 100644 --- a/trunk/drivers/net/ethernet/sun/niu.c +++ b/trunk/drivers/net/ethernet/sun/niu.c @@ -3598,6 +3598,7 @@ static int release_tx_packet(struct niu *np, struct tx_ring_info *rp, int idx) static void niu_tx_work(struct niu *np, struct tx_ring_info *rp) { struct netdev_queue *txq; + unsigned int tx_bytes; u16 pkt_cnt, tmp; int cons, index; u64 cs; @@ -3620,12 +3621,18 @@ static void niu_tx_work(struct niu *np, struct tx_ring_info *rp) netif_printk(np, tx_done, KERN_DEBUG, np->dev, "%s() pkt_cnt[%u] cons[%d]\n", __func__, pkt_cnt, cons); - while (pkt_cnt--) + tx_bytes = 0; + tmp = pkt_cnt; + while (tmp--) { + tx_bytes += rp->tx_buffs[cons].skb->len; cons = release_tx_packet(np, rp, cons); + } rp->cons = cons; smp_mb(); + netdev_tx_completed_queue(txq, pkt_cnt, tx_bytes); + out: if (unlikely(netif_tx_queue_stopped(txq) && (niu_tx_avail(rp) > NIU_TX_WAKEUP_THRESH(rp)))) { @@ -4326,6 +4333,7 @@ static void niu_free_channels(struct niu *np) struct tx_ring_info *rp = &np->tx_rings[i]; niu_free_tx_ring_info(np, rp); + netdev_tx_reset_queue(netdev_get_tx_queue(np->dev, i)); } kfree(np->tx_rings); np->tx_rings = NULL; @@ -6731,6 +6739,8 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb, prod = NEXT_TX(rp, prod); } + netdev_tx_sent_queue(txq, skb->len); + if (prod < rp->prod) rp->wrap_bit ^= TX_RING_KICK_WRAP; rp->prod = prod; diff --git a/trunk/drivers/net/ethernet/tile/Kconfig b/trunk/drivers/net/ethernet/tile/Kconfig index 098b1c42b393..2d9218f86bca 100644 --- a/trunk/drivers/net/ethernet/tile/Kconfig +++ b/trunk/drivers/net/ethernet/tile/Kconfig @@ -7,8 +7,6 @@ config TILE_NET depends on TILE default y select CRC32 - select TILE_GXIO_MPIPE if TILEGX - select HIGH_RES_TIMERS if TILEGX ---help--- This is a standard Linux network device driver for the on-chip Tilera Gigabit Ethernet and XAUI interfaces. diff --git a/trunk/drivers/net/ethernet/tile/Makefile b/trunk/drivers/net/ethernet/tile/Makefile index 0ef9eefd3211..f634f142cab4 100644 --- a/trunk/drivers/net/ethernet/tile/Makefile +++ b/trunk/drivers/net/ethernet/tile/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_TILE_NET) += tile_net.o ifdef CONFIG_TILEGX -tile_net-y := tilegx.o +tile_net-objs := tilegx.o mpipe.o iorpc_mpipe.o dma_queue.o else -tile_net-y := tilepro.o +tile_net-objs := tilepro.o endif diff --git a/trunk/drivers/net/ethernet/tile/tilegx.c b/trunk/drivers/net/ethernet/tile/tilegx.c deleted file mode 100644 index 83b4b388ad49..000000000000 --- a/trunk/drivers/net/ethernet/tile/tilegx.c +++ /dev/null @@ -1,1898 +0,0 @@ -/* - * Copyright 2012 Tilera Corporation. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for - * more details. - */ - -#include -#include -#include -#include -#include /* printk() */ -#include /* kmalloc() */ -#include /* error codes */ -#include /* size_t */ -#include -#include -#include -#include /* struct device, and other headers */ -#include /* eth_type_trans */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* Default transmit lockup timeout period, in jiffies. */ -#define TILE_NET_TIMEOUT (5 * HZ) - -/* The maximum number of distinct channels (idesc.channel is 5 bits). */ -#define TILE_NET_CHANNELS 32 - -/* Maximum number of idescs to handle per "poll". */ -#define TILE_NET_BATCH 128 - -/* Maximum number of packets to handle per "poll". */ -#define TILE_NET_WEIGHT 64 - -/* Number of entries in each iqueue. */ -#define IQUEUE_ENTRIES 512 - -/* Number of entries in each equeue. */ -#define EQUEUE_ENTRIES 2048 - -/* Total header bytes per equeue slot. Must be big enough for 2 bytes - * of NET_IP_ALIGN alignment, plus 14 bytes (?) of L2 header, plus up to - * 60 bytes of actual TCP header. We round up to align to cache lines. - */ -#define HEADER_BYTES 128 - -/* Maximum completions per cpu per device (must be a power of two). - * ISSUE: What is the right number here? If this is too small, then - * egress might block waiting for free space in a completions array. - * ISSUE: At the least, allocate these only for initialized echannels. - */ -#define TILE_NET_MAX_COMPS 64 - -#define MAX_FRAGS (MAX_SKB_FRAGS + 1) - -/* Size of completions data to allocate. - * ISSUE: Probably more than needed since we don't use all the channels. - */ -#define COMPS_SIZE (TILE_NET_CHANNELS * sizeof(struct tile_net_comps)) - -/* Size of NotifRing data to allocate. */ -#define NOTIF_RING_SIZE (IQUEUE_ENTRIES * sizeof(gxio_mpipe_idesc_t)) - -/* Timeout to wake the per-device TX timer after we stop the queue. - * We don't want the timeout too short (adds overhead, and might end - * up causing stop/wake/stop/wake cycles) or too long (affects performance). - * For the 10 Gb NIC, 30 usec means roughly 30+ 1500-byte packets. - */ -#define TX_TIMER_DELAY_USEC 30 - -/* Timeout to wake the per-cpu egress timer to free completions. */ -#define EGRESS_TIMER_DELAY_USEC 1000 - -MODULE_AUTHOR("Tilera Corporation"); -MODULE_LICENSE("GPL"); - -/* A "packet fragment" (a chunk of memory). */ -struct frag { - void *buf; - size_t length; -}; - -/* A single completion. */ -struct tile_net_comp { - /* The "complete_count" when the completion will be complete. */ - s64 when; - /* The buffer to be freed when the completion is complete. */ - struct sk_buff *skb; -}; - -/* The completions for a given cpu and echannel. */ -struct tile_net_comps { - /* The completions. */ - struct tile_net_comp comp_queue[TILE_NET_MAX_COMPS]; - /* The number of completions used. */ - unsigned long comp_next; - /* The number of completions freed. */ - unsigned long comp_last; -}; - -/* The transmit wake timer for a given cpu and echannel. */ -struct tile_net_tx_wake { - struct hrtimer timer; - struct net_device *dev; -}; - -/* Info for a specific cpu. */ -struct tile_net_info { - /* The NAPI struct. */ - struct napi_struct napi; - /* Packet queue. */ - gxio_mpipe_iqueue_t iqueue; - /* Our cpu. */ - int my_cpu; - /* True if iqueue is valid. */ - bool has_iqueue; - /* NAPI flags. */ - bool napi_added; - bool napi_enabled; - /* Number of small sk_buffs which must still be provided. */ - unsigned int num_needed_small_buffers; - /* Number of large sk_buffs which must still be provided. */ - unsigned int num_needed_large_buffers; - /* A timer for handling egress completions. */ - struct hrtimer egress_timer; - /* True if "egress_timer" is scheduled. */ - bool egress_timer_scheduled; - /* Comps for each egress channel. */ - struct tile_net_comps *comps_for_echannel[TILE_NET_CHANNELS]; - /* Transmit wake timer for each egress channel. */ - struct tile_net_tx_wake tx_wake[TILE_NET_CHANNELS]; -}; - -/* Info for egress on a particular egress channel. */ -struct tile_net_egress { - /* The "equeue". */ - gxio_mpipe_equeue_t *equeue; - /* The headers for TSO. */ - unsigned char *headers; -}; - -/* Info for a specific device. */ -struct tile_net_priv { - /* Our network device. */ - struct net_device *dev; - /* The primary link. */ - gxio_mpipe_link_t link; - /* The primary channel, if open, else -1. */ - int channel; - /* The "loopify" egress link, if needed. */ - gxio_mpipe_link_t loopify_link; - /* The "loopify" egress channel, if open, else -1. */ - int loopify_channel; - /* The egress channel (channel or loopify_channel). */ - int echannel; - /* Total stats. */ - struct net_device_stats stats; -}; - -/* Egress info, indexed by "priv->echannel" (lazily created as needed). */ -static struct tile_net_egress egress_for_echannel[TILE_NET_CHANNELS]; - -/* Devices currently associated with each channel. - * NOTE: The array entry can become NULL after ifconfig down, but - * we do not free the underlying net_device structures, so it is - * safe to use a pointer after reading it from this array. - */ -static struct net_device *tile_net_devs_for_channel[TILE_NET_CHANNELS]; - -/* A mutex for "tile_net_devs_for_channel". */ -static DEFINE_MUTEX(tile_net_devs_for_channel_mutex); - -/* The per-cpu info. */ -static DEFINE_PER_CPU(struct tile_net_info, per_cpu_info); - -/* The "context" for all devices. */ -static gxio_mpipe_context_t context; - -/* Buffer sizes and mpipe enum codes for buffer stacks. - * See arch/tile/include/gxio/mpipe.h for the set of possible values. - */ -#define BUFFER_SIZE_SMALL_ENUM GXIO_MPIPE_BUFFER_SIZE_128 -#define BUFFER_SIZE_SMALL 128 -#define BUFFER_SIZE_LARGE_ENUM GXIO_MPIPE_BUFFER_SIZE_1664 -#define BUFFER_SIZE_LARGE 1664 - -/* The small/large "buffer stacks". */ -static int small_buffer_stack = -1; -static int large_buffer_stack = -1; - -/* Amount of memory allocated for each buffer stack. */ -static size_t buffer_stack_size; - -/* The actual memory allocated for the buffer stacks. */ -static void *small_buffer_stack_va; -static void *large_buffer_stack_va; - -/* The buckets. */ -static int first_bucket = -1; -static int num_buckets = 1; - -/* The ingress irq. */ -static int ingress_irq = -1; - -/* Text value of tile_net.cpus if passed as a module parameter. */ -static char *network_cpus_string; - -/* The actual cpus in "network_cpus". */ -static struct cpumask network_cpus_map; - -/* If "loopify=LINK" was specified, this is "LINK". */ -static char *loopify_link_name; - -/* If "tile_net.custom" was specified, this is non-NULL. */ -static char *custom_str; - -/* The "tile_net.cpus" argument specifies the cpus that are dedicated - * to handle ingress packets. - * - * The parameter should be in the form "tile_net.cpus=m-n[,x-y]", where - * m, n, x, y are integer numbers that represent the cpus that can be - * neither a dedicated cpu nor a dataplane cpu. - */ -static bool network_cpus_init(void) -{ - char buf[1024]; - int rc; - - if (network_cpus_string == NULL) - return false; - - rc = cpulist_parse_crop(network_cpus_string, &network_cpus_map); - if (rc != 0) { - pr_warn("tile_net.cpus=%s: malformed cpu list\n", - network_cpus_string); - return false; - } - - /* Remove dedicated cpus. */ - cpumask_and(&network_cpus_map, &network_cpus_map, cpu_possible_mask); - - if (cpumask_empty(&network_cpus_map)) { - pr_warn("Ignoring empty tile_net.cpus='%s'.\n", - network_cpus_string); - return false; - } - - cpulist_scnprintf(buf, sizeof(buf), &network_cpus_map); - pr_info("Linux network CPUs: %s\n", buf); - return true; -} - -module_param_named(cpus, network_cpus_string, charp, 0444); -MODULE_PARM_DESC(cpus, "cpulist of cores that handle network interrupts"); - -/* The "tile_net.loopify=LINK" argument causes the named device to - * actually use "loop0" for ingress, and "loop1" for egress. This - * allows an app to sit between the actual link and linux, passing - * (some) packets along to linux, and forwarding (some) packets sent - * out by linux. - */ -module_param_named(loopify, loopify_link_name, charp, 0444); -MODULE_PARM_DESC(loopify, "name the device to use loop0/1 for ingress/egress"); - -/* The "tile_net.custom" argument causes us to ignore the "conventional" - * classifier metadata, in particular, the "l2_offset". - */ -module_param_named(custom, custom_str, charp, 0444); -MODULE_PARM_DESC(custom, "indicates a (heavily) customized classifier"); - -/* Atomically update a statistics field. - * Note that on TILE-Gx, this operation is fire-and-forget on the - * issuing core (single-cycle dispatch) and takes only a few cycles - * longer than a regular store when the request reaches the home cache. - * No expensive bus management overhead is required. - */ -static void tile_net_stats_add(unsigned long value, unsigned long *field) -{ - BUILD_BUG_ON(sizeof(atomic_long_t) != sizeof(unsigned long)); - atomic_long_add(value, (atomic_long_t *)field); -} - -/* Allocate and push a buffer. */ -static bool tile_net_provide_buffer(bool small) -{ - int stack = small ? small_buffer_stack : large_buffer_stack; - const unsigned long buffer_alignment = 128; - struct sk_buff *skb; - int len; - - len = sizeof(struct sk_buff **) + buffer_alignment; - len += (small ? BUFFER_SIZE_SMALL : BUFFER_SIZE_LARGE); - skb = dev_alloc_skb(len); - if (skb == NULL) - return false; - - /* Make room for a back-pointer to 'skb' and guarantee alignment. */ - skb_reserve(skb, sizeof(struct sk_buff **)); - skb_reserve(skb, -(long)skb->data & (buffer_alignment - 1)); - - /* Save a back-pointer to 'skb'. */ - *(struct sk_buff **)(skb->data - sizeof(struct sk_buff **)) = skb; - - /* Make sure "skb" and the back-pointer have been flushed. */ - wmb(); - - gxio_mpipe_push_buffer(&context, stack, - (void *)va_to_tile_io_addr(skb->data)); - - return true; -} - -/* Convert a raw mpipe buffer to its matching skb pointer. */ -static struct sk_buff *mpipe_buf_to_skb(void *va) -{ - /* Acquire the associated "skb". */ - struct sk_buff **skb_ptr = va - sizeof(*skb_ptr); - struct sk_buff *skb = *skb_ptr; - - /* Paranoia. */ - if (skb->data != va) { - /* Panic here since there's a reasonable chance - * that corrupt buffers means generic memory - * corruption, with unpredictable system effects. - */ - panic("Corrupt linux buffer! va=%p, skb=%p, skb->data=%p", - va, skb, skb->data); - } - - return skb; -} - -static void tile_net_pop_all_buffers(int stack) -{ - for (;;) { - tile_io_addr_t addr = - (tile_io_addr_t)gxio_mpipe_pop_buffer(&context, stack); - if (addr == 0) - break; - dev_kfree_skb_irq(mpipe_buf_to_skb(tile_io_addr_to_va(addr))); - } -} - -/* Provide linux buffers to mPIPE. */ -static void tile_net_provide_needed_buffers(void) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - - while (info->num_needed_small_buffers != 0) { - if (!tile_net_provide_buffer(true)) - goto oops; - info->num_needed_small_buffers--; - } - - while (info->num_needed_large_buffers != 0) { - if (!tile_net_provide_buffer(false)) - goto oops; - info->num_needed_large_buffers--; - } - - return; - -oops: - /* Add a description to the page allocation failure dump. */ - pr_notice("Tile %d still needs some buffers\n", info->my_cpu); -} - -static inline bool filter_packet(struct net_device *dev, void *buf) -{ - /* Filter packets received before we're up. */ - if (dev == NULL || !(dev->flags & IFF_UP)) - return true; - - /* Filter out packets that aren't for us. */ - if (!(dev->flags & IFF_PROMISC) && - !is_multicast_ether_addr(buf) && - compare_ether_addr(dev->dev_addr, buf) != 0) - return true; - - return false; -} - -static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb, - gxio_mpipe_idesc_t *idesc, unsigned long len) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - - /* Encode the actual packet length. */ - skb_put(skb, len); - - skb->protocol = eth_type_trans(skb, dev); - - /* Acknowledge "good" hardware checksums. */ - if (idesc->cs && idesc->csum_seed_val == 0xFFFF) - skb->ip_summed = CHECKSUM_UNNECESSARY; - - netif_receive_skb(skb); - - /* Update stats. */ - tile_net_stats_add(1, &priv->stats.rx_packets); - tile_net_stats_add(len, &priv->stats.rx_bytes); - - /* Need a new buffer. */ - if (idesc->size == BUFFER_SIZE_SMALL_ENUM) - info->num_needed_small_buffers++; - else - info->num_needed_large_buffers++; -} - -/* Handle a packet. Return true if "processed", false if "filtered". */ -static bool tile_net_handle_packet(gxio_mpipe_idesc_t *idesc) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct net_device *dev = tile_net_devs_for_channel[idesc->channel]; - uint8_t l2_offset; - void *va; - void *buf; - unsigned long len; - bool filter; - - /* Drop packets for which no buffer was available. - * NOTE: This happens under heavy load. - */ - if (idesc->be) { - struct tile_net_priv *priv = netdev_priv(dev); - tile_net_stats_add(1, &priv->stats.rx_dropped); - gxio_mpipe_iqueue_consume(&info->iqueue, idesc); - if (net_ratelimit()) - pr_info("Dropping packet (insufficient buffers).\n"); - return false; - } - - /* Get the "l2_offset", if allowed. */ - l2_offset = custom_str ? 0 : gxio_mpipe_idesc_get_l2_offset(idesc); - - /* Get the raw buffer VA (includes "headroom"). */ - va = tile_io_addr_to_va((unsigned long)(long)idesc->va); - - /* Get the actual packet start/length. */ - buf = va + l2_offset; - len = idesc->l2_size - l2_offset; - - /* Point "va" at the raw buffer. */ - va -= NET_IP_ALIGN; - - filter = filter_packet(dev, buf); - if (filter) { - gxio_mpipe_iqueue_drop(&info->iqueue, idesc); - } else { - struct sk_buff *skb = mpipe_buf_to_skb(va); - - /* Skip headroom, and any custom header. */ - skb_reserve(skb, NET_IP_ALIGN + l2_offset); - - tile_net_receive_skb(dev, skb, idesc, len); - } - - gxio_mpipe_iqueue_consume(&info->iqueue, idesc); - return !filter; -} - -/* Handle some packets for the current CPU. - * - * This function handles up to TILE_NET_BATCH idescs per call. - * - * ISSUE: Since we do not provide new buffers until this function is - * complete, we must initially provide enough buffers for each network - * cpu to fill its iqueue and also its batched idescs. - * - * ISSUE: The "rotting packet" race condition occurs if a packet - * arrives after the queue appears to be empty, and before the - * hypervisor interrupt is re-enabled. - */ -static int tile_net_poll(struct napi_struct *napi, int budget) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - unsigned int work = 0; - gxio_mpipe_idesc_t *idesc; - int i, n; - - /* Process packets. */ - while ((n = gxio_mpipe_iqueue_try_peek(&info->iqueue, &idesc)) > 0) { - for (i = 0; i < n; i++) { - if (i == TILE_NET_BATCH) - goto done; - if (tile_net_handle_packet(idesc + i)) { - if (++work >= budget) - goto done; - } - } - } - - /* There are no packets left. */ - napi_complete(&info->napi); - - /* Re-enable hypervisor interrupts. */ - gxio_mpipe_enable_notif_ring_interrupt(&context, info->iqueue.ring); - - /* HACK: Avoid the "rotting packet" problem. */ - if (gxio_mpipe_iqueue_try_peek(&info->iqueue, &idesc) > 0) - napi_schedule(&info->napi); - - /* ISSUE: Handle completions? */ - -done: - tile_net_provide_needed_buffers(); - - return work; -} - -/* Handle an ingress interrupt on the current cpu. */ -static irqreturn_t tile_net_handle_ingress_irq(int irq, void *unused) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - napi_schedule(&info->napi); - return IRQ_HANDLED; -} - -/* Free some completions. This must be called with interrupts blocked. */ -static int tile_net_free_comps(gxio_mpipe_equeue_t *equeue, - struct tile_net_comps *comps, - int limit, bool force_update) -{ - int n = 0; - while (comps->comp_last < comps->comp_next) { - unsigned int cid = comps->comp_last % TILE_NET_MAX_COMPS; - struct tile_net_comp *comp = &comps->comp_queue[cid]; - if (!gxio_mpipe_equeue_is_complete(equeue, comp->when, - force_update || n == 0)) - break; - dev_kfree_skb_irq(comp->skb); - comps->comp_last++; - if (++n == limit) - break; - } - return n; -} - -/* Add a completion. This must be called with interrupts blocked. - * tile_net_equeue_try_reserve() will have ensured a free completion entry. - */ -static void add_comp(gxio_mpipe_equeue_t *equeue, - struct tile_net_comps *comps, - uint64_t when, struct sk_buff *skb) -{ - int cid = comps->comp_next % TILE_NET_MAX_COMPS; - comps->comp_queue[cid].when = when; - comps->comp_queue[cid].skb = skb; - comps->comp_next++; -} - -static void tile_net_schedule_tx_wake_timer(struct net_device *dev) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - - hrtimer_start(&info->tx_wake[priv->echannel].timer, - ktime_set(0, TX_TIMER_DELAY_USEC * 1000UL), - HRTIMER_MODE_REL_PINNED); -} - -static enum hrtimer_restart tile_net_handle_tx_wake_timer(struct hrtimer *t) -{ - struct tile_net_tx_wake *tx_wake = - container_of(t, struct tile_net_tx_wake, timer); - netif_wake_subqueue(tx_wake->dev, smp_processor_id()); - return HRTIMER_NORESTART; -} - -/* Make sure the egress timer is scheduled. */ -static void tile_net_schedule_egress_timer(void) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - - if (!info->egress_timer_scheduled) { - hrtimer_start(&info->egress_timer, - ktime_set(0, EGRESS_TIMER_DELAY_USEC * 1000UL), - HRTIMER_MODE_REL_PINNED); - info->egress_timer_scheduled = true; - } -} - -/* The "function" for "info->egress_timer". - * - * This timer will reschedule itself as long as there are any pending - * completions expected for this tile. - */ -static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - unsigned long irqflags; - bool pending = false; - int i; - - local_irq_save(irqflags); - - /* The timer is no longer scheduled. */ - info->egress_timer_scheduled = false; - - /* Free all possible comps for this tile. */ - for (i = 0; i < TILE_NET_CHANNELS; i++) { - struct tile_net_egress *egress = &egress_for_echannel[i]; - struct tile_net_comps *comps = info->comps_for_echannel[i]; - if (comps->comp_last >= comps->comp_next) - continue; - tile_net_free_comps(egress->equeue, comps, -1, true); - pending = pending || (comps->comp_last < comps->comp_next); - } - - /* Reschedule timer if needed. */ - if (pending) - tile_net_schedule_egress_timer(); - - local_irq_restore(irqflags); - - return HRTIMER_NORESTART; -} - -/* Helper function for "tile_net_update()". - * "dev" (i.e. arg) is the device being brought up or down, - * or NULL if all devices are now down. - */ -static void tile_net_update_cpu(void *arg) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct net_device *dev = arg; - - if (!info->has_iqueue) - return; - - if (dev != NULL) { - if (!info->napi_added) { - netif_napi_add(dev, &info->napi, - tile_net_poll, TILE_NET_WEIGHT); - info->napi_added = true; - } - if (!info->napi_enabled) { - napi_enable(&info->napi); - info->napi_enabled = true; - } - enable_percpu_irq(ingress_irq, 0); - } else { - disable_percpu_irq(ingress_irq); - if (info->napi_enabled) { - napi_disable(&info->napi); - info->napi_enabled = false; - } - /* FIXME: Drain the iqueue. */ - } -} - -/* Helper function for tile_net_open() and tile_net_stop(). - * Always called under tile_net_devs_for_channel_mutex. - */ -static int tile_net_update(struct net_device *dev) -{ - static gxio_mpipe_rules_t rules; /* too big to fit on the stack */ - bool saw_channel = false; - int channel; - int rc; - int cpu; - - gxio_mpipe_rules_init(&rules, &context); - - for (channel = 0; channel < TILE_NET_CHANNELS; channel++) { - if (tile_net_devs_for_channel[channel] == NULL) - continue; - if (!saw_channel) { - saw_channel = true; - gxio_mpipe_rules_begin(&rules, first_bucket, - num_buckets, NULL); - gxio_mpipe_rules_set_headroom(&rules, NET_IP_ALIGN); - } - gxio_mpipe_rules_add_channel(&rules, channel); - } - - /* NOTE: This can fail if there is no classifier. - * ISSUE: Can anything else cause it to fail? - */ - rc = gxio_mpipe_rules_commit(&rules); - if (rc != 0) { - netdev_warn(dev, "gxio_mpipe_rules_commit failed: %d\n", rc); - return -EIO; - } - - /* Update all cpus, sequentially (to protect "netif_napi_add()"). */ - for_each_online_cpu(cpu) - smp_call_function_single(cpu, tile_net_update_cpu, - (saw_channel ? dev : NULL), 1); - - /* HACK: Allow packets to flow in the simulator. */ - if (saw_channel) - sim_enable_mpipe_links(0, -1); - - return 0; -} - -/* Allocate and initialize mpipe buffer stacks, and register them in - * the mPIPE TLBs, for both small and large packet sizes. - * This routine supports tile_net_init_mpipe(), below. - */ -static int init_buffer_stacks(struct net_device *dev, int num_buffers) -{ - pte_t hash_pte = pte_set_home((pte_t) { 0 }, PAGE_HOME_HASH); - int rc; - - /* Compute stack bytes; we round up to 64KB and then use - * alloc_pages() so we get the required 64KB alignment as well. - */ - buffer_stack_size = - ALIGN(gxio_mpipe_calc_buffer_stack_bytes(num_buffers), - 64 * 1024); - - /* Allocate two buffer stack indices. */ - rc = gxio_mpipe_alloc_buffer_stacks(&context, 2, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_buffer_stacks failed: %d\n", - rc); - return rc; - } - small_buffer_stack = rc; - large_buffer_stack = rc + 1; - - /* Allocate the small memory stack. */ - small_buffer_stack_va = - alloc_pages_exact(buffer_stack_size, GFP_KERNEL); - if (small_buffer_stack_va == NULL) { - netdev_err(dev, - "Could not alloc %zd bytes for buffer stacks\n", - buffer_stack_size); - return -ENOMEM; - } - rc = gxio_mpipe_init_buffer_stack(&context, small_buffer_stack, - BUFFER_SIZE_SMALL_ENUM, - small_buffer_stack_va, - buffer_stack_size, 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_init_buffer_stack: %d\n", rc); - return rc; - } - rc = gxio_mpipe_register_client_memory(&context, small_buffer_stack, - hash_pte, 0); - if (rc != 0) { - netdev_err(dev, - "gxio_mpipe_register_buffer_memory failed: %d\n", - rc); - return rc; - } - - /* Allocate the large buffer stack. */ - large_buffer_stack_va = - alloc_pages_exact(buffer_stack_size, GFP_KERNEL); - if (large_buffer_stack_va == NULL) { - netdev_err(dev, - "Could not alloc %zd bytes for buffer stacks\n", - buffer_stack_size); - return -ENOMEM; - } - rc = gxio_mpipe_init_buffer_stack(&context, large_buffer_stack, - BUFFER_SIZE_LARGE_ENUM, - large_buffer_stack_va, - buffer_stack_size, 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_init_buffer_stack failed: %d\n", - rc); - return rc; - } - rc = gxio_mpipe_register_client_memory(&context, large_buffer_stack, - hash_pte, 0); - if (rc != 0) { - netdev_err(dev, - "gxio_mpipe_register_buffer_memory failed: %d\n", - rc); - return rc; - } - - return 0; -} - -/* Allocate per-cpu resources (memory for completions and idescs). - * This routine supports tile_net_init_mpipe(), below. - */ -static int alloc_percpu_mpipe_resources(struct net_device *dev, - int cpu, int ring) -{ - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - int order, i, rc; - struct page *page; - void *addr; - - /* Allocate the "comps". */ - order = get_order(COMPS_SIZE); - page = homecache_alloc_pages(GFP_KERNEL, order, cpu); - if (page == NULL) { - netdev_err(dev, "Failed to alloc %zd bytes comps memory\n", - COMPS_SIZE); - return -ENOMEM; - } - addr = pfn_to_kaddr(page_to_pfn(page)); - memset(addr, 0, COMPS_SIZE); - for (i = 0; i < TILE_NET_CHANNELS; i++) - info->comps_for_echannel[i] = - addr + i * sizeof(struct tile_net_comps); - - /* If this is a network cpu, create an iqueue. */ - if (cpu_isset(cpu, network_cpus_map)) { - order = get_order(NOTIF_RING_SIZE); - page = homecache_alloc_pages(GFP_KERNEL, order, cpu); - if (page == NULL) { - netdev_err(dev, - "Failed to alloc %zd bytes iqueue memory\n", - NOTIF_RING_SIZE); - return -ENOMEM; - } - addr = pfn_to_kaddr(page_to_pfn(page)); - rc = gxio_mpipe_iqueue_init(&info->iqueue, &context, ring++, - addr, NOTIF_RING_SIZE, 0); - if (rc < 0) { - netdev_err(dev, - "gxio_mpipe_iqueue_init failed: %d\n", rc); - return rc; - } - info->has_iqueue = true; - } - - return ring; -} - -/* Initialize NotifGroup and buckets. - * This routine supports tile_net_init_mpipe(), below. - */ -static int init_notif_group_and_buckets(struct net_device *dev, - int ring, int network_cpus_count) -{ - int group, rc; - - /* Allocate one NotifGroup. */ - rc = gxio_mpipe_alloc_notif_groups(&context, 1, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_notif_groups failed: %d\n", - rc); - return rc; - } - group = rc; - - /* Initialize global num_buckets value. */ - if (network_cpus_count > 4) - num_buckets = 256; - else if (network_cpus_count > 1) - num_buckets = 16; - - /* Allocate some buckets, and set global first_bucket value. */ - rc = gxio_mpipe_alloc_buckets(&context, num_buckets, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_buckets failed: %d\n", rc); - return rc; - } - first_bucket = rc; - - /* Init group and buckets. */ - rc = gxio_mpipe_init_notif_group_and_buckets( - &context, group, ring, network_cpus_count, - first_bucket, num_buckets, - GXIO_MPIPE_BUCKET_STICKY_FLOW_LOCALITY); - if (rc != 0) { - netdev_err( - dev, - "gxio_mpipe_init_notif_group_and_buckets failed: %d\n", - rc); - return rc; - } - - return 0; -} - -/* Create an irq and register it, then activate the irq and request - * interrupts on all cores. Note that "ingress_irq" being initialized - * is how we know not to call tile_net_init_mpipe() again. - * This routine supports tile_net_init_mpipe(), below. - */ -static int tile_net_setup_interrupts(struct net_device *dev) -{ - int cpu, rc; - - rc = create_irq(); - if (rc < 0) { - netdev_err(dev, "create_irq failed: %d\n", rc); - return rc; - } - ingress_irq = rc; - tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU); - rc = request_irq(ingress_irq, tile_net_handle_ingress_irq, - 0, NULL, NULL); - if (rc != 0) { - netdev_err(dev, "request_irq failed: %d\n", rc); - destroy_irq(ingress_irq); - ingress_irq = -1; - return rc; - } - - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - if (info->has_iqueue) { - gxio_mpipe_request_notif_ring_interrupt( - &context, cpu_x(cpu), cpu_y(cpu), - 1, ingress_irq, info->iqueue.ring); - } - } - - return 0; -} - -/* Undo any state set up partially by a failed call to tile_net_init_mpipe. */ -static void tile_net_init_mpipe_fail(void) -{ - int cpu; - - /* Do cleanups that require the mpipe context first. */ - if (small_buffer_stack >= 0) - tile_net_pop_all_buffers(small_buffer_stack); - if (large_buffer_stack >= 0) - tile_net_pop_all_buffers(large_buffer_stack); - - /* Destroy mpipe context so the hardware no longer owns any memory. */ - gxio_mpipe_destroy(&context); - - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - free_pages((unsigned long)(info->comps_for_echannel[0]), - get_order(COMPS_SIZE)); - info->comps_for_echannel[0] = NULL; - free_pages((unsigned long)(info->iqueue.idescs), - get_order(NOTIF_RING_SIZE)); - info->iqueue.idescs = NULL; - } - - if (small_buffer_stack_va) - free_pages_exact(small_buffer_stack_va, buffer_stack_size); - if (large_buffer_stack_va) - free_pages_exact(large_buffer_stack_va, buffer_stack_size); - - small_buffer_stack_va = NULL; - large_buffer_stack_va = NULL; - large_buffer_stack = -1; - small_buffer_stack = -1; - first_bucket = -1; -} - -/* The first time any tilegx network device is opened, we initialize - * the global mpipe state. If this step fails, we fail to open the - * device, but if it succeeds, we never need to do it again, and since - * tile_net can't be unloaded, we never undo it. - * - * Note that some resources in this path (buffer stack indices, - * bindings from init_buffer_stack, etc.) are hypervisor resources - * that are freed implicitly by gxio_mpipe_destroy(). - */ -static int tile_net_init_mpipe(struct net_device *dev) -{ - int i, num_buffers, rc; - int cpu; - int first_ring, ring; - int network_cpus_count = cpus_weight(network_cpus_map); - - if (!hash_default) { - netdev_err(dev, "Networking requires hash_default!\n"); - return -EIO; - } - - rc = gxio_mpipe_init(&context, 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_init failed: %d\n", rc); - return -EIO; - } - - /* Set up the buffer stacks. */ - num_buffers = - network_cpus_count * (IQUEUE_ENTRIES + TILE_NET_BATCH); - rc = init_buffer_stacks(dev, num_buffers); - if (rc != 0) - goto fail; - - /* Provide initial buffers. */ - rc = -ENOMEM; - for (i = 0; i < num_buffers; i++) { - if (!tile_net_provide_buffer(true)) { - netdev_err(dev, "Cannot allocate initial sk_bufs!\n"); - goto fail; - } - } - for (i = 0; i < num_buffers; i++) { - if (!tile_net_provide_buffer(false)) { - netdev_err(dev, "Cannot allocate initial sk_bufs!\n"); - goto fail; - } - } - - /* Allocate one NotifRing for each network cpu. */ - rc = gxio_mpipe_alloc_notif_rings(&context, network_cpus_count, 0, 0); - if (rc < 0) { - netdev_err(dev, "gxio_mpipe_alloc_notif_rings failed %d\n", - rc); - goto fail; - } - - /* Init NotifRings per-cpu. */ - first_ring = rc; - ring = first_ring; - for_each_online_cpu(cpu) { - rc = alloc_percpu_mpipe_resources(dev, cpu, ring); - if (rc < 0) - goto fail; - ring = rc; - } - - /* Initialize NotifGroup and buckets. */ - rc = init_notif_group_and_buckets(dev, first_ring, network_cpus_count); - if (rc != 0) - goto fail; - - /* Create and enable interrupts. */ - rc = tile_net_setup_interrupts(dev); - if (rc != 0) - goto fail; - - return 0; - -fail: - tile_net_init_mpipe_fail(); - return rc; -} - -/* Create persistent egress info for a given egress channel. - * Note that this may be shared between, say, "gbe0" and "xgbe0". - * ISSUE: Defer header allocation until TSO is actually needed? - */ -static int tile_net_init_egress(struct net_device *dev, int echannel) -{ - struct page *headers_page, *edescs_page, *equeue_page; - gxio_mpipe_edesc_t *edescs; - gxio_mpipe_equeue_t *equeue; - unsigned char *headers; - int headers_order, edescs_order, equeue_order; - size_t edescs_size; - int edma; - int rc = -ENOMEM; - - /* Only initialize once. */ - if (egress_for_echannel[echannel].equeue != NULL) - return 0; - - /* Allocate memory for the "headers". */ - headers_order = get_order(EQUEUE_ENTRIES * HEADER_BYTES); - headers_page = alloc_pages(GFP_KERNEL, headers_order); - if (headers_page == NULL) { - netdev_warn(dev, - "Could not alloc %zd bytes for TSO headers.\n", - PAGE_SIZE << headers_order); - goto fail; - } - headers = pfn_to_kaddr(page_to_pfn(headers_page)); - - /* Allocate memory for the "edescs". */ - edescs_size = EQUEUE_ENTRIES * sizeof(*edescs); - edescs_order = get_order(edescs_size); - edescs_page = alloc_pages(GFP_KERNEL, edescs_order); - if (edescs_page == NULL) { - netdev_warn(dev, - "Could not alloc %zd bytes for eDMA ring.\n", - edescs_size); - goto fail_headers; - } - edescs = pfn_to_kaddr(page_to_pfn(edescs_page)); - - /* Allocate memory for the "equeue". */ - equeue_order = get_order(sizeof(*equeue)); - equeue_page = alloc_pages(GFP_KERNEL, equeue_order); - if (equeue_page == NULL) { - netdev_warn(dev, - "Could not alloc %zd bytes for equeue info.\n", - PAGE_SIZE << equeue_order); - goto fail_edescs; - } - equeue = pfn_to_kaddr(page_to_pfn(equeue_page)); - - /* Allocate an edma ring. Note that in practice this can't - * fail, which is good, because we will leak an edma ring if so. - */ - rc = gxio_mpipe_alloc_edma_rings(&context, 1, 0, 0); - if (rc < 0) { - netdev_warn(dev, "gxio_mpipe_alloc_edma_rings failed: %d\n", - rc); - goto fail_equeue; - } - edma = rc; - - /* Initialize the equeue. */ - rc = gxio_mpipe_equeue_init(equeue, &context, edma, echannel, - edescs, edescs_size, 0); - if (rc != 0) { - netdev_err(dev, "gxio_mpipe_equeue_init failed: %d\n", rc); - goto fail_equeue; - } - - /* Done. */ - egress_for_echannel[echannel].equeue = equeue; - egress_for_echannel[echannel].headers = headers; - return 0; - -fail_equeue: - __free_pages(equeue_page, equeue_order); - -fail_edescs: - __free_pages(edescs_page, edescs_order); - -fail_headers: - __free_pages(headers_page, headers_order); - -fail: - return rc; -} - -/* Return channel number for a newly-opened link. */ -static int tile_net_link_open(struct net_device *dev, gxio_mpipe_link_t *link, - const char *link_name) -{ - int rc = gxio_mpipe_link_open(link, &context, link_name, 0); - if (rc < 0) { - netdev_err(dev, "Failed to open '%s'\n", link_name); - return rc; - } - rc = gxio_mpipe_link_channel(link); - if (rc < 0 || rc >= TILE_NET_CHANNELS) { - netdev_err(dev, "gxio_mpipe_link_channel bad value: %d\n", rc); - gxio_mpipe_link_close(link); - return -EINVAL; - } - return rc; -} - -/* Help the kernel activate the given network interface. */ -static int tile_net_open(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int cpu, rc; - - mutex_lock(&tile_net_devs_for_channel_mutex); - - /* Do one-time initialization the first time any device is opened. */ - if (ingress_irq < 0) { - rc = tile_net_init_mpipe(dev); - if (rc != 0) - goto fail; - } - - /* Determine if this is the "loopify" device. */ - if (unlikely((loopify_link_name != NULL) && - !strcmp(dev->name, loopify_link_name))) { - rc = tile_net_link_open(dev, &priv->link, "loop0"); - if (rc < 0) - goto fail; - priv->channel = rc; - rc = tile_net_link_open(dev, &priv->loopify_link, "loop1"); - if (rc < 0) - goto fail; - priv->loopify_channel = rc; - priv->echannel = rc; - } else { - rc = tile_net_link_open(dev, &priv->link, dev->name); - if (rc < 0) - goto fail; - priv->channel = rc; - priv->echannel = rc; - } - - /* Initialize egress info (if needed). Once ever, per echannel. */ - rc = tile_net_init_egress(dev, priv->echannel); - if (rc != 0) - goto fail; - - tile_net_devs_for_channel[priv->channel] = dev; - - rc = tile_net_update(dev); - if (rc != 0) - goto fail; - - mutex_unlock(&tile_net_devs_for_channel_mutex); - - /* Initialize the transmit wake timer for this device for each cpu. */ - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - struct tile_net_tx_wake *tx_wake = - &info->tx_wake[priv->echannel]; - - hrtimer_init(&tx_wake->timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - tx_wake->timer.function = tile_net_handle_tx_wake_timer; - tx_wake->dev = dev; - } - - for_each_online_cpu(cpu) - netif_start_subqueue(dev, cpu); - netif_carrier_on(dev); - return 0; - -fail: - if (priv->loopify_channel >= 0) { - if (gxio_mpipe_link_close(&priv->loopify_link) != 0) - netdev_warn(dev, "Failed to close loopify link!\n"); - priv->loopify_channel = -1; - } - if (priv->channel >= 0) { - if (gxio_mpipe_link_close(&priv->link) != 0) - netdev_warn(dev, "Failed to close link!\n"); - priv->channel = -1; - } - priv->echannel = -1; - tile_net_devs_for_channel[priv->channel] = NULL; - mutex_unlock(&tile_net_devs_for_channel_mutex); - - /* Don't return raw gxio error codes to generic Linux. */ - return (rc > -512) ? rc : -EIO; -} - -/* Help the kernel deactivate the given network interface. */ -static int tile_net_stop(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - int cpu; - - for_each_online_cpu(cpu) { - struct tile_net_info *info = &per_cpu(per_cpu_info, cpu); - struct tile_net_tx_wake *tx_wake = - &info->tx_wake[priv->echannel]; - - hrtimer_cancel(&tx_wake->timer); - netif_stop_subqueue(dev, cpu); - } - - mutex_lock(&tile_net_devs_for_channel_mutex); - tile_net_devs_for_channel[priv->channel] = NULL; - (void)tile_net_update(dev); - if (priv->loopify_channel >= 0) { - if (gxio_mpipe_link_close(&priv->loopify_link) != 0) - netdev_warn(dev, "Failed to close loopify link!\n"); - priv->loopify_channel = -1; - } - if (priv->channel >= 0) { - if (gxio_mpipe_link_close(&priv->link) != 0) - netdev_warn(dev, "Failed to close link!\n"); - priv->channel = -1; - } - priv->echannel = -1; - mutex_unlock(&tile_net_devs_for_channel_mutex); - - return 0; -} - -/* Determine the VA for a fragment. */ -static inline void *tile_net_frag_buf(skb_frag_t *f) -{ - unsigned long pfn = page_to_pfn(skb_frag_page(f)); - return pfn_to_kaddr(pfn) + f->page_offset; -} - -/* Acquire a completion entry and an egress slot, or if we can't, - * stop the queue and schedule the tx_wake timer. - */ -static s64 tile_net_equeue_try_reserve(struct net_device *dev, - struct tile_net_comps *comps, - gxio_mpipe_equeue_t *equeue, - int num_edescs) -{ - /* Try to acquire a completion entry. */ - if (comps->comp_next - comps->comp_last < TILE_NET_MAX_COMPS - 1 || - tile_net_free_comps(equeue, comps, 32, false) != 0) { - - /* Try to acquire an egress slot. */ - s64 slot = gxio_mpipe_equeue_try_reserve(equeue, num_edescs); - if (slot >= 0) - return slot; - - /* Freeing some completions gives the equeue time to drain. */ - tile_net_free_comps(equeue, comps, TILE_NET_MAX_COMPS, false); - - slot = gxio_mpipe_equeue_try_reserve(equeue, num_edescs); - if (slot >= 0) - return slot; - } - - /* Still nothing; give up and stop the queue for a short while. */ - netif_stop_subqueue(dev, smp_processor_id()); - tile_net_schedule_tx_wake_timer(dev); - return -1; -} - -/* Determine how many edesc's are needed for TSO. - * - * Sometimes, if "sendfile()" requires copying, we will be called with - * "data" containing the header and payload, with "frags" being empty. - * Sometimes, for example when using NFS over TCP, a single segment can - * span 3 fragments. This requires special care. - */ -static int tso_count_edescs(struct sk_buff *skb) -{ - struct skb_shared_info *sh = skb_shinfo(skb); - unsigned int data_len = skb->data_len; - unsigned int p_len = sh->gso_size; - long f_id = -1; /* id of the current fragment */ - long f_size = -1; /* size of the current fragment */ - long f_used = -1; /* bytes used from the current fragment */ - long n; /* size of the current piece of payload */ - int num_edescs = 0; - int segment; - - for (segment = 0; segment < sh->gso_segs; segment++) { - - unsigned int p_used = 0; - - /* One edesc for header and for each piece of the payload. */ - for (num_edescs++; p_used < p_len; num_edescs++) { - - /* Advance as needed. */ - while (f_used >= f_size) { - f_id++; - f_size = sh->frags[f_id].size; - f_used = 0; - } - - /* Use bytes from the current fragment. */ - n = p_len - p_used; - if (n > f_size - f_used) - n = f_size - f_used; - f_used += n; - p_used += n; - } - - /* The last segment may be less than gso_size. */ - data_len -= p_len; - if (data_len < p_len) - p_len = data_len; - } - - return num_edescs; -} - -/* Prepare modified copies of the skbuff headers. - * FIXME: add support for IPv6. - */ -static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, - s64 slot) -{ - struct skb_shared_info *sh = skb_shinfo(skb); - struct iphdr *ih; - struct tcphdr *th; - unsigned int data_len = skb->data_len; - unsigned char *data = skb->data; - unsigned int ih_off, th_off, sh_len, p_len; - unsigned int isum_seed, tsum_seed, id, seq; - long f_id = -1; /* id of the current fragment */ - long f_size = -1; /* size of the current fragment */ - long f_used = -1; /* bytes used from the current fragment */ - long n; /* size of the current piece of payload */ - int segment; - - /* Locate original headers and compute various lengths. */ - ih = ip_hdr(skb); - th = tcp_hdr(skb); - ih_off = skb_network_offset(skb); - th_off = skb_transport_offset(skb); - sh_len = th_off + tcp_hdrlen(skb); - p_len = sh->gso_size; - - /* Set up seed values for IP and TCP csum and initialize id and seq. */ - isum_seed = ((0xFFFF - ih->check) + - (0xFFFF - ih->tot_len) + - (0xFFFF - ih->id)); - tsum_seed = th->check + (0xFFFF ^ htons(skb->len)); - id = ntohs(ih->id); - seq = ntohl(th->seq); - - /* Prepare all the headers. */ - for (segment = 0; segment < sh->gso_segs; segment++) { - unsigned char *buf; - unsigned int p_used = 0; - - /* Copy to the header memory for this segment. */ - buf = headers + (slot % EQUEUE_ENTRIES) * HEADER_BYTES + - NET_IP_ALIGN; - memcpy(buf, data, sh_len); - - /* Update copied ip header. */ - ih = (struct iphdr *)(buf + ih_off); - ih->tot_len = htons(sh_len + p_len - ih_off); - ih->id = htons(id); - ih->check = csum_long(isum_seed + ih->tot_len + - ih->id) ^ 0xffff; - - /* Update copied tcp header. */ - th = (struct tcphdr *)(buf + th_off); - th->seq = htonl(seq); - th->check = csum_long(tsum_seed + htons(sh_len + p_len)); - if (segment != sh->gso_segs - 1) { - th->fin = 0; - th->psh = 0; - } - - /* Skip past the header. */ - slot++; - - /* Skip past the payload. */ - while (p_used < p_len) { - - /* Advance as needed. */ - while (f_used >= f_size) { - f_id++; - f_size = sh->frags[f_id].size; - f_used = 0; - } - - /* Use bytes from the current fragment. */ - n = p_len - p_used; - if (n > f_size - f_used) - n = f_size - f_used; - f_used += n; - p_used += n; - - slot++; - } - - id++; - seq += p_len; - - /* The last segment may be less than gso_size. */ - data_len -= p_len; - if (data_len < p_len) - p_len = data_len; - } - - /* Flush the headers so they are ready for hardware DMA. */ - wmb(); -} - -/* Pass all the data to mpipe for egress. */ -static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, - struct sk_buff *skb, unsigned char *headers, s64 slot) -{ - struct tile_net_priv *priv = netdev_priv(dev); - struct skb_shared_info *sh = skb_shinfo(skb); - unsigned int data_len = skb->data_len; - unsigned int p_len = sh->gso_size; - gxio_mpipe_edesc_t edesc_head = { { 0 } }; - gxio_mpipe_edesc_t edesc_body = { { 0 } }; - long f_id = -1; /* id of the current fragment */ - long f_size = -1; /* size of the current fragment */ - long f_used = -1; /* bytes used from the current fragment */ - long n; /* size of the current piece of payload */ - unsigned long tx_packets = 0, tx_bytes = 0; - unsigned int csum_start, sh_len; - int segment; - - /* Prepare to egress the headers: set up header edesc. */ - csum_start = skb_checksum_start_offset(skb); - sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - edesc_head.csum = 1; - edesc_head.csum_start = csum_start; - edesc_head.csum_dest = csum_start + skb->csum_offset; - edesc_head.xfer_size = sh_len; - - /* This is only used to specify the TLB. */ - edesc_head.stack_idx = large_buffer_stack; - edesc_body.stack_idx = large_buffer_stack; - - /* Egress all the edescs. */ - for (segment = 0; segment < sh->gso_segs; segment++) { - void *va; - unsigned char *buf; - unsigned int p_used = 0; - - /* Egress the header. */ - buf = headers + (slot % EQUEUE_ENTRIES) * HEADER_BYTES + - NET_IP_ALIGN; - edesc_head.va = va_to_tile_io_addr(buf); - gxio_mpipe_equeue_put_at(equeue, edesc_head, slot); - slot++; - - /* Egress the payload. */ - while (p_used < p_len) { - - /* Advance as needed. */ - while (f_used >= f_size) { - f_id++; - f_size = sh->frags[f_id].size; - f_used = 0; - } - - va = tile_net_frag_buf(&sh->frags[f_id]) + f_used; - - /* Use bytes from the current fragment. */ - n = p_len - p_used; - if (n > f_size - f_used) - n = f_size - f_used; - f_used += n; - p_used += n; - - /* Egress a piece of the payload. */ - edesc_body.va = va_to_tile_io_addr(va); - edesc_body.xfer_size = n; - edesc_body.bound = !(p_used < p_len); - gxio_mpipe_equeue_put_at(equeue, edesc_body, slot); - slot++; - } - - tx_packets++; - tx_bytes += sh_len + p_len; - - /* The last segment may be less than gso_size. */ - data_len -= p_len; - if (data_len < p_len) - p_len = data_len; - } - - /* Update stats. */ - tile_net_stats_add(tx_packets, &priv->stats.tx_packets); - tile_net_stats_add(tx_bytes, &priv->stats.tx_bytes); -} - -/* Do "TSO" handling for egress. - * - * Normally drivers set NETIF_F_TSO only to support hardware TSO; - * otherwise the stack uses scatter-gather to implement GSO in software. - * On our testing, enabling GSO support (via NETIF_F_SG) drops network - * performance down to around 7.5 Gbps on the 10G interfaces, although - * also dropping cpu utilization way down, to under 8%. But - * implementing "TSO" in the driver brings performance back up to line - * rate, while dropping cpu usage even further, to less than 4%. In - * practice, profiling of GSO shows that skb_segment() is what causes - * the performance overheads; we benefit in the driver from using - * preallocated memory to duplicate the TCP/IP headers. - */ -static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - int channel = priv->echannel; - struct tile_net_egress *egress = &egress_for_echannel[channel]; - struct tile_net_comps *comps = info->comps_for_echannel[channel]; - gxio_mpipe_equeue_t *equeue = egress->equeue; - unsigned long irqflags; - int num_edescs; - s64 slot; - - /* Determine how many mpipe edesc's are needed. */ - num_edescs = tso_count_edescs(skb); - - local_irq_save(irqflags); - - /* Try to acquire a completion entry and an egress slot. */ - slot = tile_net_equeue_try_reserve(dev, comps, equeue, num_edescs); - if (slot < 0) { - local_irq_restore(irqflags); - return NETDEV_TX_BUSY; - } - - /* Set up copies of header data properly. */ - tso_headers_prepare(skb, egress->headers, slot); - - /* Actually pass the data to the network hardware. */ - tso_egress(dev, equeue, skb, egress->headers, slot); - - /* Add a completion record. */ - add_comp(equeue, comps, slot + num_edescs - 1, skb); - - local_irq_restore(irqflags); - - /* Make sure the egress timer is scheduled. */ - tile_net_schedule_egress_timer(); - - return NETDEV_TX_OK; -} - -/* Analyze the body and frags for a transmit request. */ -static unsigned int tile_net_tx_frags(struct frag *frags, - struct sk_buff *skb, - void *b_data, unsigned int b_len) -{ - unsigned int i, n = 0; - - struct skb_shared_info *sh = skb_shinfo(skb); - - if (b_len != 0) { - frags[n].buf = b_data; - frags[n++].length = b_len; - } - - for (i = 0; i < sh->nr_frags; i++) { - skb_frag_t *f = &sh->frags[i]; - frags[n].buf = tile_net_frag_buf(f); - frags[n++].length = skb_frag_size(f); - } - - return n; -} - -/* Help the kernel transmit a packet. */ -static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - struct tile_net_priv *priv = netdev_priv(dev); - struct tile_net_egress *egress = &egress_for_echannel[priv->echannel]; - gxio_mpipe_equeue_t *equeue = egress->equeue; - struct tile_net_comps *comps = - info->comps_for_echannel[priv->echannel]; - unsigned int len = skb->len; - unsigned char *data = skb->data; - unsigned int num_edescs; - struct frag frags[MAX_FRAGS]; - gxio_mpipe_edesc_t edescs[MAX_FRAGS]; - unsigned long irqflags; - gxio_mpipe_edesc_t edesc = { { 0 } }; - unsigned int i; - s64 slot; - - if (skb_is_gso(skb)) - return tile_net_tx_tso(skb, dev); - - num_edescs = tile_net_tx_frags(frags, skb, data, skb_headlen(skb)); - - /* This is only used to specify the TLB. */ - edesc.stack_idx = large_buffer_stack; - - /* Prepare the edescs. */ - for (i = 0; i < num_edescs; i++) { - edesc.xfer_size = frags[i].length; - edesc.va = va_to_tile_io_addr(frags[i].buf); - edescs[i] = edesc; - } - - /* Mark the final edesc. */ - edescs[num_edescs - 1].bound = 1; - - /* Add checksum info to the initial edesc, if needed. */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { - unsigned int csum_start = skb_checksum_start_offset(skb); - edescs[0].csum = 1; - edescs[0].csum_start = csum_start; - edescs[0].csum_dest = csum_start + skb->csum_offset; - } - - local_irq_save(irqflags); - - /* Try to acquire a completion entry and an egress slot. */ - slot = tile_net_equeue_try_reserve(dev, comps, equeue, num_edescs); - if (slot < 0) { - local_irq_restore(irqflags); - return NETDEV_TX_BUSY; - } - - for (i = 0; i < num_edescs; i++) - gxio_mpipe_equeue_put_at(equeue, edescs[i], slot++); - - /* Add a completion record. */ - add_comp(equeue, comps, slot - 1, skb); - - /* NOTE: Use ETH_ZLEN for short packets (e.g. 42 < 60). */ - tile_net_stats_add(1, &priv->stats.tx_packets); - tile_net_stats_add(max_t(unsigned int, len, ETH_ZLEN), - &priv->stats.tx_bytes); - - local_irq_restore(irqflags); - - /* Make sure the egress timer is scheduled. */ - tile_net_schedule_egress_timer(); - - return NETDEV_TX_OK; -} - -/* Return subqueue id on this core (one per core). */ -static u16 tile_net_select_queue(struct net_device *dev, struct sk_buff *skb) -{ - return smp_processor_id(); -} - -/* Deal with a transmit timeout. */ -static void tile_net_tx_timeout(struct net_device *dev) -{ - int cpu; - - for_each_online_cpu(cpu) - netif_wake_subqueue(dev, cpu); -} - -/* Ioctl commands. */ -static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - return -EOPNOTSUPP; -} - -/* Get system network statistics for device. */ -static struct net_device_stats *tile_net_get_stats(struct net_device *dev) -{ - struct tile_net_priv *priv = netdev_priv(dev); - return &priv->stats; -} - -/* Change the MTU. */ -static int tile_net_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 1500)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -/* Change the Ethernet address of the NIC. - * - * The hypervisor driver does not support changing MAC address. However, - * the hardware does not do anything with the MAC address, so the address - * which gets used on outgoing packets, and which is accepted on incoming - * packets, is completely up to us. - * - * Returns 0 on success, negative on failure. - */ -static int tile_net_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - return 0; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void tile_net_netpoll(struct net_device *dev) -{ - disable_percpu_irq(ingress_irq); - tile_net_handle_ingress_irq(ingress_irq, NULL); - enable_percpu_irq(ingress_irq, 0); -} -#endif - -static const struct net_device_ops tile_net_ops = { - .ndo_open = tile_net_open, - .ndo_stop = tile_net_stop, - .ndo_start_xmit = tile_net_tx, - .ndo_select_queue = tile_net_select_queue, - .ndo_do_ioctl = tile_net_ioctl, - .ndo_get_stats = tile_net_get_stats, - .ndo_change_mtu = tile_net_change_mtu, - .ndo_tx_timeout = tile_net_tx_timeout, - .ndo_set_mac_address = tile_net_set_mac_address, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = tile_net_netpoll, -#endif -}; - -/* The setup function. - * - * This uses ether_setup() to assign various fields in dev, including - * setting IFF_BROADCAST and IFF_MULTICAST, then sets some extra fields. - */ -static void tile_net_setup(struct net_device *dev) -{ - ether_setup(dev); - dev->netdev_ops = &tile_net_ops; - dev->watchdog_timeo = TILE_NET_TIMEOUT; - dev->features |= NETIF_F_LLTX; - dev->features |= NETIF_F_HW_CSUM; - dev->features |= NETIF_F_SG; - dev->features |= NETIF_F_TSO; - dev->mtu = 1500; -} - -/* Allocate the device structure, register the device, and obtain the - * MAC address from the hypervisor. - */ -static void tile_net_dev_init(const char *name, const uint8_t *mac) -{ - int ret; - int i; - int nz_addr = 0; - struct net_device *dev; - struct tile_net_priv *priv; - - /* HACK: Ignore "loop" links. */ - if (strncmp(name, "loop", 4) == 0) - return; - - /* Allocate the device structure. Normally, "name" is a - * template, instantiated by register_netdev(), but not for us. - */ - dev = alloc_netdev_mqs(sizeof(*priv), name, tile_net_setup, - NR_CPUS, 1); - if (!dev) { - pr_err("alloc_netdev_mqs(%s) failed\n", name); - return; - } - - /* Initialize "priv". */ - priv = netdev_priv(dev); - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - priv->channel = -1; - priv->loopify_channel = -1; - priv->echannel = -1; - - /* Get the MAC address and set it in the device struct; this must - * be done before the device is opened. If the MAC is all zeroes, - * we use a random address, since we're probably on the simulator. - */ - for (i = 0; i < 6; i++) - nz_addr |= mac[i]; - - if (nz_addr) { - memcpy(dev->dev_addr, mac, 6); - dev->addr_len = 6; - } else { - random_ether_addr(dev->dev_addr); - } - - /* Register the network device. */ - ret = register_netdev(dev); - if (ret) { - netdev_err(dev, "register_netdev failed %d\n", ret); - free_netdev(dev); - return; - } -} - -/* Per-cpu module initialization. */ -static void tile_net_init_module_percpu(void *unused) -{ - struct tile_net_info *info = &__get_cpu_var(per_cpu_info); - int my_cpu = smp_processor_id(); - - info->has_iqueue = false; - - info->my_cpu = my_cpu; - - /* Initialize the egress timer. */ - hrtimer_init(&info->egress_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - info->egress_timer.function = tile_net_handle_egress_timer; -} - -/* Module initialization. */ -static int __init tile_net_init_module(void) -{ - int i; - char name[GXIO_MPIPE_LINK_NAME_LEN]; - uint8_t mac[6]; - - pr_info("Tilera Network Driver\n"); - - mutex_init(&tile_net_devs_for_channel_mutex); - - /* Initialize each CPU. */ - on_each_cpu(tile_net_init_module_percpu, NULL, 1); - - /* Find out what devices we have, and initialize them. */ - for (i = 0; gxio_mpipe_link_enumerate_mac(i, name, mac) >= 0; i++) - tile_net_dev_init(name, mac); - - if (!network_cpus_init()) - network_cpus_map = *cpu_online_mask; - - return 0; -} - -module_init(tile_net_init_module); diff --git a/trunk/drivers/net/phy/mdio_bus.c b/trunk/drivers/net/phy/mdio_bus.c index 31470b0d0c32..d4a4992b4935 100644 --- a/trunk/drivers/net/phy/mdio_bus.c +++ b/trunk/drivers/net/phy/mdio_bus.c @@ -99,7 +99,7 @@ static int of_mdio_bus_match(struct device *dev, void *mdio_bus_np) } /** * of_mdio_find_bus - Given an mii_bus node, find the mii_bus. - * @mdio_bus_np: Pointer to the mii_bus. + * @mdio_np: Pointer to the mii_bus. * * Returns a pointer to the mii_bus, or NULL if none found. * diff --git a/trunk/drivers/net/usb/cdc-phonet.c b/trunk/drivers/net/usb/cdc-phonet.c index 187c144c5e5b..d848d4dd5754 100644 --- a/trunk/drivers/net/usb/cdc-phonet.c +++ b/trunk/drivers/net/usb/cdc-phonet.c @@ -394,7 +394,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) SET_NETDEV_DEV(dev, &intf->dev); pnd->dev = dev; - pnd->usb = usbdev; + pnd->usb = usb_get_dev(usbdev); pnd->intf = intf; pnd->data_intf = data_intf; spin_lock_init(&pnd->tx_lock); @@ -440,6 +440,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id) static void usbpn_disconnect(struct usb_interface *intf) { struct usbpn_dev *pnd = usb_get_intfdata(intf); + struct usb_device *usb = pnd->usb; if (pnd->disconnected) return; @@ -448,6 +449,7 @@ static void usbpn_disconnect(struct usb_interface *intf) usb_driver_release_interface(&usbpn_driver, (pnd->intf == intf) ? pnd->data_intf : pnd->intf); unregister_netdev(pnd->dev); + usb_put_dev(usb); } static struct usb_driver usbpn_driver = { diff --git a/trunk/drivers/net/usb/pegasus.c b/trunk/drivers/net/usb/pegasus.c index a0b5807b30d4..7023220456c5 100644 --- a/trunk/drivers/net/usb/pegasus.c +++ b/trunk/drivers/net/usb/pegasus.c @@ -1329,6 +1329,8 @@ static int pegasus_probe(struct usb_interface *intf, } pegasus_count++; + usb_get_dev(dev); + net = alloc_etherdev(sizeof(struct pegasus)); if (!net) goto out; @@ -1405,6 +1407,7 @@ static int pegasus_probe(struct usb_interface *intf, out1: free_netdev(net); out: + usb_put_dev(dev); pegasus_dec_workqueue(); return res; } @@ -1422,6 +1425,7 @@ static void pegasus_disconnect(struct usb_interface *intf) pegasus->flags |= PEGASUS_UNPLUG; cancel_delayed_work(&pegasus->carrier_check); unregister_netdev(pegasus->net); + usb_put_dev(interface_to_usbdev(intf)); unlink_all_urbs(pegasus); free_all_urbs(pegasus); free_skb_pool(pegasus); diff --git a/trunk/drivers/net/usb/usbnet.c b/trunk/drivers/net/usb/usbnet.c index ac2e4936b421..9f58330f1312 100644 --- a/trunk/drivers/net/usb/usbnet.c +++ b/trunk/drivers/net/usb/usbnet.c @@ -180,40 +180,7 @@ int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress) } EXPORT_SYMBOL_GPL(usbnet_get_ethernet_addr); -static void intr_complete (struct urb *urb) -{ - struct usbnet *dev = urb->context; - int status = urb->status; - - switch (status) { - /* success */ - case 0: - dev->driver_info->status(dev, urb); - break; - - /* software-driven interface shutdown */ - case -ENOENT: /* urb killed */ - case -ESHUTDOWN: /* hardware gone */ - netif_dbg(dev, ifdown, dev->net, - "intr shutdown, code %d\n", status); - return; - - /* NOTE: not throttling like RX/TX, since this endpoint - * already polls infrequently - */ - default: - netdev_dbg(dev->net, "intr status %d\n", status); - break; - } - - if (!netif_running (dev->net)) - return; - - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status != 0) - netif_err(dev, timer, dev->net, - "intr resubmit --> %d\n", status); -} +static void intr_complete (struct urb *urb); static int init_status (struct usbnet *dev, struct usb_interface *intf) { @@ -552,6 +519,42 @@ static void rx_complete (struct urb *urb) netif_dbg(dev, rx_err, dev->net, "no read resubmitted\n"); } +static void intr_complete (struct urb *urb) +{ + struct usbnet *dev = urb->context; + int status = urb->status; + + switch (status) { + /* success */ + case 0: + dev->driver_info->status(dev, urb); + break; + + /* software-driven interface shutdown */ + case -ENOENT: /* urb killed */ + case -ESHUTDOWN: /* hardware gone */ + netif_dbg(dev, ifdown, dev->net, + "intr shutdown, code %d\n", status); + return; + + /* NOTE: not throttling like RX/TX, since this endpoint + * already polls infrequently + */ + default: + netdev_dbg(dev->net, "intr status %d\n", status); + break; + } + + if (!netif_running (dev->net)) + return; + + memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); + status = usb_submit_urb (urb, GFP_ATOMIC); + if (status != 0) + netif_err(dev, timer, dev->net, + "intr resubmit --> %d\n", status); +} + /*-------------------------------------------------------------------------*/ void usbnet_pause_rx(struct usbnet *dev) { @@ -1304,6 +1307,7 @@ void usbnet_disconnect (struct usb_interface *intf) usb_free_urb(dev->interrupt); free_netdev(net); + usb_put_dev (xdev); } EXPORT_SYMBOL_GPL(usbnet_disconnect); @@ -1359,6 +1363,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) xdev = interface_to_usbdev (udev); interface = udev->cur_altsetting; + usb_get_dev (xdev); + status = -ENOMEM; // set up our own records @@ -1487,6 +1493,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) out1: free_netdev(net); out: + usb_put_dev(xdev); return status; } EXPORT_SYMBOL_GPL(usbnet_probe); diff --git a/trunk/drivers/net/virtio_net.c b/trunk/drivers/net/virtio_net.c index f18149ae2588..5214b1eceb95 100644 --- a/trunk/drivers/net/virtio_net.c +++ b/trunk/drivers/net/virtio_net.c @@ -42,8 +42,7 @@ module_param(gso, bool, 0444); #define VIRTNET_DRIVER_VERSION "1.0.0" struct virtnet_stats { - struct u64_stats_sync tx_syncp; - struct u64_stats_sync rx_syncp; + struct u64_stats_sync syncp; u64 tx_bytes; u64 tx_packets; @@ -301,10 +300,10 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len) hdr = skb_vnet_hdr(skb); - u64_stats_update_begin(&stats->rx_syncp); + u64_stats_update_begin(&stats->syncp); stats->rx_bytes += skb->len; stats->rx_packets++; - u64_stats_update_end(&stats->rx_syncp); + u64_stats_update_end(&stats->syncp); if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { pr_debug("Needs csum!\n"); @@ -566,10 +565,10 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) { pr_debug("Sent skb %p\n", skb); - u64_stats_update_begin(&stats->tx_syncp); + u64_stats_update_begin(&stats->syncp); stats->tx_bytes += skb->len; stats->tx_packets++; - u64_stats_update_end(&stats->tx_syncp); + u64_stats_update_end(&stats->syncp); tot_sgs += skb_vnet_hdr(skb)->num_sg; dev_kfree_skb_any(skb); @@ -704,16 +703,12 @@ static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev, u64 tpackets, tbytes, rpackets, rbytes; do { - start = u64_stats_fetch_begin(&stats->tx_syncp); + start = u64_stats_fetch_begin(&stats->syncp); tpackets = stats->tx_packets; tbytes = stats->tx_bytes; - } while (u64_stats_fetch_retry(&stats->tx_syncp, start)); - - do { - start = u64_stats_fetch_begin(&stats->rx_syncp); rpackets = stats->rx_packets; rbytes = stats->rx_bytes; - } while (u64_stats_fetch_retry(&stats->rx_syncp, start)); + } while (u64_stats_fetch_retry(&stats->syncp, start)); tot->rx_packets += rpackets; tot->tx_packets += tpackets; diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index c06b6cb5c91e..67c13af6f206 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -877,10 +877,6 @@ struct b43_wl { * from the mac80211 subsystem. */ u16 mac80211_initially_registered_queues; - /* Set this if we call ieee80211_register_hw() and check if we call - * ieee80211_unregister_hw(). */ - bool hw_registred; - /* We can only have one operating interface (802.11 core) * at a time. General information about this interface follows. */ diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index acd03a4f9730..5a39b226b2e3 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -2437,7 +2437,6 @@ static void b43_request_firmware(struct work_struct *work) err = ieee80211_register_hw(wl->hw); if (err) goto err_one_core_detach; - wl->hw_registred = true; b43_leds_register(wl->current_dev); goto out; @@ -5300,7 +5299,6 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1; wl->mac80211_initially_registered_queues = hw->queues; - wl->hw_registred = false; hw->max_rates = 2; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) @@ -5372,15 +5370,12 @@ static void b43_bcma_remove(struct bcma_device *core) * as the ieee80211 unreg will destroy the workqueue. */ cancel_work_sync(&wldev->restart_work); - B43_WARN_ON(!wl); - if (wl->current_dev == wldev && wl->hw_registred) { - /* Restore the queues count before unregistering, because firmware detect - * might have modified it. Restoring is important, so the networking - * stack can properly free resources. */ - wl->hw->queues = wl->mac80211_initially_registered_queues; - b43_leds_stop(wldev); - ieee80211_unregister_hw(wl->hw); - } + /* Restore the queues count before unregistering, because firmware detect + * might have modified it. Restoring is important, so the networking + * stack can properly free resources. */ + wl->hw->queues = wl->mac80211_initially_registered_queues; + b43_leds_stop(wldev); + ieee80211_unregister_hw(wl->hw); b43_one_core_detach(wldev->dev); @@ -5451,7 +5446,7 @@ static void b43_ssb_remove(struct ssb_device *sdev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); - if (wl->current_dev == wldev && wl->hw_registred) { + if (wl->current_dev == wldev) { /* Restore the queues count before unregistering, because firmware detect * might have modified it. Restoring is important, so the networking * stack can properly free resources. */ diff --git a/trunk/drivers/net/wireless/ipw2x00/ipw2100.c b/trunk/drivers/net/wireless/ipw2x00/ipw2100.c index 95aa8e1683ec..9cfae0c08707 100644 --- a/trunk/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/trunk/drivers/net/wireless/ipw2x00/ipw2100.c @@ -1903,6 +1903,14 @@ static void ipw2100_down(struct ipw2100_priv *priv) netif_stop_queue(priv->net_dev); } +/* Called by register_netdev() */ +static int ipw2100_net_init(struct net_device *dev) +{ + struct ipw2100_priv *priv = libipw_priv(dev); + + return ipw2100_up(priv, 1); +} + static int ipw2100_wdev_init(struct net_device *dev) { struct ipw2100_priv *priv = libipw_priv(dev); @@ -6079,6 +6087,7 @@ static const struct net_device_ops ipw2100_netdev_ops = { .ndo_stop = ipw2100_close, .ndo_start_xmit = libipw_xmit, .ndo_change_mtu = libipw_change_mtu, + .ndo_init = ipw2100_net_init, .ndo_tx_timeout = ipw2100_tx_timeout, .ndo_set_mac_address = ipw2100_set_address, .ndo_validate_addr = eth_validate_addr, @@ -6320,10 +6329,6 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2100 Network Connection\n"); - err = ipw2100_up(priv, 1); - if (err) - goto fail; - err = ipw2100_wdev_init(dev); if (err) goto fail; @@ -6333,7 +6338,12 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, * network device we would call ipw2100_up. This introduced a race * condition with newer hotplug configurations (network was coming * up and making calls before the device was initialized). - */ + * + * If we called ipw2100_up before we registered the device, then the + * device name wasn't registered. So, we instead use the net_dev->init + * member to call a function that then just turns and calls ipw2100_up. + * net_dev->init is called after name allocation but before the + * notifier chain is called */ err = register_netdev(dev); if (err) { printk(KERN_WARNING DRV_NAME diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c b/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c index b29b798f7550..286ce4e18068 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/sta.c @@ -1251,7 +1251,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, key_flags |= STA_KEY_MULTICAST_MSK; sta_cmd.key.key_flags = key_flags; - sta_cmd.key.key_offset = keyconf->hw_key_idx; + sta_cmd.key.key_offset = WEP_INVALID_OFFSET; sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; sta_cmd.mode = STA_CONTROL_MODIFY_MSK; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h index 9253ef1dba72..a9f0415916c7 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -224,7 +224,6 @@ #define SCD_TXFACT (SCD_BASE + 0x10) #define SCD_ACTIVE (SCD_BASE + 0x14) #define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) -#define SCD_CHAINEXT_EN (SCD_BASE + 0x244) #define SCD_AGGR_SEL (SCD_BASE + 0x248) #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/6000.c b/trunk/drivers/net/wireless/iwlwifi/pcie/6000.c index cb08ba03aae7..8dd8a6fe61e8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/6000.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/6000.c @@ -35,20 +35,17 @@ #define IWL6000_UCODE_API_MAX 6 #define IWL6050_UCODE_API_MAX 5 #define IWL6000G2_UCODE_API_MAX 6 -#define IWL6035_UCODE_API_MAX 6 /* Oldest version we won't warn about */ #define IWL6000_UCODE_API_OK 4 #define IWL6000G2_UCODE_API_OK 5 #define IWL6050_UCODE_API_OK 5 #define IWL6000G2B_UCODE_API_OK 6 -#define IWL6035_UCODE_API_OK 6 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 4 #define IWL6050_UCODE_API_MIN 4 -#define IWL6000G2_UCODE_API_MIN 5 -#define IWL6035_UCODE_API_MIN 6 +#define IWL6000G2_UCODE_API_MIN 4 /* EEPROM versions */ #define EEPROM_6000_TX_POWER_VERSION (4) @@ -246,25 +243,9 @@ const struct iwl_cfg iwl6030_2bg_cfg = { IWL_DEVICE_6030, }; -#define IWL_DEVICE_6035 \ - .fw_name_pre = IWL6030_FW_PRE, \ - .ucode_api_max = IWL6035_UCODE_API_MAX, \ - .ucode_api_ok = IWL6035_UCODE_API_OK, \ - .ucode_api_min = IWL6035_UCODE_API_MIN, \ - .device_family = IWL_DEVICE_FAMILY_6030, \ - .max_inst_size = IWL60_RTC_INST_SIZE, \ - .max_data_size = IWL60_RTC_DATA_SIZE, \ - .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ - .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ - .base_params = &iwl6000_g2_base_params, \ - .bt_params = &iwl6000_bt_params, \ - .need_temp_offset_calib = true, \ - .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true - const struct iwl_cfg iwl6035_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", - IWL_DEVICE_6035, + IWL_DEVICE_6030, .ht_params = &iwl6000_ht_params, }; diff --git a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c index 7461a6a14338..969f78f421df 100644 --- a/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/trunk/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1065,12 +1065,6 @@ static void iwl_tx_start(struct iwl_trans *trans) /* Activate all Tx DMA/FIFO channels */ iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); - /* The chain extension of the SCD doesn't work well. This feature is - * enabled by default by the HW, so we need to disable it manually. - */ - iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); - - /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index a0b7cfd34685..4c9336cee817 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -1555,7 +1555,6 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, hdr = (struct ieee80211_hdr *) skb->data; mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2); } - txi->flags |= IEEE80211_TX_STAT_ACK; } ieee80211_tx_status_irqsafe(data2->hw, skb); return 0; diff --git a/trunk/drivers/net/wireless/rtl818x/rtl8187/leds.c b/trunk/drivers/net/wireless/rtl818x/rtl8187/leds.c index c2d5b495c179..2e0de2f5f0f9 100644 --- a/trunk/drivers/net/wireless/rtl818x/rtl8187/leds.c +++ b/trunk/drivers/net/wireless/rtl818x/rtl8187/leds.c @@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, radio_on = true; } else if (radio_on) { radio_on = false; - cancel_delayed_work(&priv->led_on); + cancel_delayed_work_sync(&priv->led_on); ieee80211_queue_delayed_work(hw, &priv->led_off, 0); } } else if (radio_on) { diff --git a/trunk/drivers/pinctrl/core.c b/trunk/drivers/pinctrl/core.c index 0cc053af70bd..c3b331b74fa0 100644 --- a/trunk/drivers/pinctrl/core.c +++ b/trunk/drivers/pinctrl/core.c @@ -61,7 +61,7 @@ static LIST_HEAD(pinctrl_maps); list_for_each_entry(_maps_node_, &pinctrl_maps, node) \ for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \ _i_ < _maps_node_->num_maps; \ - _i_++, _map_ = &_maps_node_->maps[_i_]) + i++, _map_ = &_maps_node_->maps[_i_]) /** * pinctrl_provide_dummies() - indicate if pinctrl provides dummy state support diff --git a/trunk/drivers/pinctrl/pinctrl-imx.c b/trunk/drivers/pinctrl/pinctrl-imx.c index dd6d93aa5334..f6e7c670906c 100644 --- a/trunk/drivers/pinctrl/pinctrl-imx.c +++ b/trunk/drivers/pinctrl/pinctrl-imx.c @@ -27,16 +27,16 @@ #include "core.h" #include "pinctrl-imx.h" -#define IMX_PMX_DUMP(info, p, m, c, n) \ -{ \ - int i, j; \ - printk(KERN_DEBUG "Format: Pin Mux Config\n"); \ - for (i = 0; i < n; i++) { \ - j = p[i]; \ - printk(KERN_DEBUG "%s %d 0x%lx\n", \ - info->pins[j].name, \ - m[i], c[i]); \ - } \ +#define IMX_PMX_DUMP(info, p, m, c, n) \ +{ \ + int i, j; \ + printk("Format: Pin Mux Config\n"); \ + for (i = 0; i < n; i++) { \ + j = p[i]; \ + printk("%s %d 0x%lx\n", \ + info->pins[j].name, \ + m[i], c[i]); \ + } \ } /* The bits in CONFIG cell defined in binding doc*/ @@ -173,10 +173,8 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, /* create mux map */ parent = of_get_parent(np); - if (!parent) { - kfree(new_map); + if (!parent) return -EINVAL; - } new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; new_map[0].data.mux.function = parent->name; new_map[0].data.mux.group = np->name; @@ -195,7 +193,7 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, } dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", - (*map)->data.mux.function, (*map)->data.mux.group, map_num); + new_map->data.mux.function, new_map->data.mux.group, map_num); return 0; } @@ -203,7 +201,10 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev, static void imx_dt_free_map(struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps) { - kfree(map); + int i; + + for (i = 0; i < num_maps; i++) + kfree(map); } static struct pinctrl_ops imx_pctrl_ops = { @@ -474,8 +475,9 @@ static int __devinit imx_pinctrl_parse_groups(struct device_node *np, grp->configs[j] = config & ~IMX_PAD_SION; } +#ifdef DEBUG IMX_PMX_DUMP(info, grp->pins, grp->mux_mode, grp->configs, grp->npins); - +#endif return 0; } diff --git a/trunk/drivers/pinctrl/pinctrl-mxs.c b/trunk/drivers/pinctrl/pinctrl-mxs.c index afb50ee64598..556e45a213eb 100644 --- a/trunk/drivers/pinctrl/pinctrl-mxs.c +++ b/trunk/drivers/pinctrl/pinctrl-mxs.c @@ -107,10 +107,8 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, /* Compose group name */ group = kzalloc(length, GFP_KERNEL); - if (!group) { - ret = -ENOMEM; - goto free; - } + if (!group) + return -ENOMEM; snprintf(group, length, "%s.%d", np->name, reg); new_map[i].data.mux.group = group; i++; @@ -120,7 +118,7 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, pconfig = kmemdup(&config, sizeof(config), GFP_KERNEL); if (!pconfig) { ret = -ENOMEM; - goto free_group; + goto free; } new_map[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; @@ -135,9 +133,6 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev, return 0; -free_group: - if (!purecfg) - free(group); free: kfree(new_map); return ret; @@ -516,7 +511,6 @@ int __devinit mxs_pinctrl_probe(struct platform_device *pdev, return 0; err: - platform_set_drvdata(pdev, NULL); iounmap(d->base); return ret; } @@ -526,7 +520,6 @@ int __devexit mxs_pinctrl_remove(struct platform_device *pdev) { struct mxs_pinctrl_data *d = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); pinctrl_unregister(d->pctl); iounmap(d->base); diff --git a/trunk/drivers/pinctrl/pinctrl-nomadik.c b/trunk/drivers/pinctrl/pinctrl-nomadik.c index e8937e7e4999..b26395d16347 100644 --- a/trunk/drivers/pinctrl/pinctrl-nomadik.c +++ b/trunk/drivers/pinctrl/pinctrl-nomadik.c @@ -673,7 +673,7 @@ static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, * wakeup is anyhow controlled by the RIMSC and FIMSC registers. */ if (nmk_chip->sleepmode && on) { - __nmk_gpio_set_slpm(nmk_chip, gpio % NMK_GPIO_PER_CHIP, + __nmk_gpio_set_slpm(nmk_chip, gpio % nmk_chip->chip.base, NMK_GPIO_SLPM_WAKEUP_ENABLE); } @@ -1246,7 +1246,6 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) ret = PTR_ERR(clk); goto out_unmap; } - clk_prepare(clk); nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); if (!nmk_chip) { diff --git a/trunk/drivers/pinctrl/pinctrl-sirf.c b/trunk/drivers/pinctrl/pinctrl-sirf.c index e9f8e7d11001..ba15b1a29e52 100644 --- a/trunk/drivers/pinctrl/pinctrl-sirf.c +++ b/trunk/drivers/pinctrl/pinctrl-sirf.c @@ -1184,7 +1184,7 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev) return ret; } -static const struct of_device_id pinmux_ids[] __devinitconst = { +static const struct of_device_id pinmux_ids[] = { { .compatible = "sirf,prima2-gpio-pinmux" }, {} }; diff --git a/trunk/drivers/platform/x86/acerhdf.c b/trunk/drivers/platform/x86/acerhdf.c index 2fd9d36acd15..639db4d0aa76 100644 --- a/trunk/drivers/platform/x86/acerhdf.c +++ b/trunk/drivers/platform/x86/acerhdf.c @@ -5,7 +5,7 @@ * * (C) 2009 - Peter Feuerer peter (a) piie.net * http://piie.net - * 2009 Borislav Petkov bp (a) alien8.de + * 2009 Borislav Petkov * * Inspired by and many thanks to: * o acerfand - Rachel Greenham diff --git a/trunk/drivers/regulator/anatop-regulator.c b/trunk/drivers/regulator/anatop-regulator.c index e82e7eaac0f1..3660bace123c 100644 --- a/trunk/drivers/regulator/anatop-regulator.c +++ b/trunk/drivers/regulator/anatop-regulator.c @@ -224,7 +224,7 @@ static struct platform_driver anatop_regulator_driver = { .of_match_table = of_anatop_regulator_match_tbl, }, .probe = anatop_regulator_probe, - .remove = __devexit_p(anatop_regulator_remove), + .remove = anatop_regulator_remove, }; static int __init anatop_regulator_init(void) diff --git a/trunk/drivers/regulator/core.c b/trunk/drivers/regulator/core.c index 09a737c868b5..7584a74eec8a 100644 --- a/trunk/drivers/regulator/core.c +++ b/trunk/drivers/regulator/core.c @@ -2050,9 +2050,6 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev, return -EINVAL; } - if (min_uV < rdev->desc->min_uV) - min_uV = rdev->desc->min_uV; - ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); if (ret < 0) return ret; diff --git a/trunk/drivers/regulator/gpio-regulator.c b/trunk/drivers/regulator/gpio-regulator.c index 242851a4c1a6..9997d7aaca84 100644 --- a/trunk/drivers/regulator/gpio-regulator.c +++ b/trunk/drivers/regulator/gpio-regulator.c @@ -101,20 +101,16 @@ static int gpio_regulator_get_value(struct regulator_dev *dev) } static int gpio_regulator_set_value(struct regulator_dev *dev, - int min, int max, unsigned *selector) + int min, int max) { struct gpio_regulator_data *data = rdev_get_drvdata(dev); - int ptr, target = 0, state, best_val = INT_MAX; + int ptr, target, state, best_val = INT_MAX; for (ptr = 0; ptr < data->nr_states; ptr++) if (data->states[ptr].value < best_val && data->states[ptr].value >= min && - data->states[ptr].value <= max) { + data->states[ptr].value <= max) target = data->states[ptr].gpios; - best_val = data->states[ptr].value; - if (selector) - *selector = ptr; - } if (best_val == INT_MAX) return -EINVAL; @@ -132,7 +128,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev, int min_uV, int max_uV, unsigned *selector) { - return gpio_regulator_set_value(dev, min_uV, max_uV, selector); + return gpio_regulator_set_value(dev, min_uV, max_uV); } static int gpio_regulator_list_voltage(struct regulator_dev *dev, @@ -149,7 +145,7 @@ static int gpio_regulator_list_voltage(struct regulator_dev *dev, static int gpio_regulator_set_current_limit(struct regulator_dev *dev, int min_uA, int max_uA) { - return gpio_regulator_set_value(dev, min_uA, max_uA, NULL); + return gpio_regulator_set_value(dev, min_uA, max_uA); } static struct regulator_ops gpio_regulator_voltage_ops = { @@ -290,7 +286,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) cfg.dev = &pdev->dev; cfg.init_data = config->init_data; - cfg.driver_data = drvdata; + cfg.driver_data = &drvdata; drvdata->dev = regulator_register(&drvdata->desc, &cfg); if (IS_ERR(drvdata->dev)) { diff --git a/trunk/drivers/regulator/max8649.c b/trunk/drivers/regulator/max8649.c index 9d540cd02dab..1f4bb80457b3 100644 --- a/trunk/drivers/regulator/max8649.c +++ b/trunk/drivers/regulator/max8649.c @@ -259,7 +259,6 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, config.dev = &client->dev; config.init_data = pdata->regulator; config.driver_data = info; - config.regmap = info->regmap; info->regulator = regulator_register(&dcdc_desc, &config); if (IS_ERR(info->regulator)) { diff --git a/trunk/drivers/regulator/palmas-regulator.c b/trunk/drivers/regulator/palmas-regulator.c index 9b7ca90057d5..c4435f608df7 100644 --- a/trunk/drivers/regulator/palmas-regulator.c +++ b/trunk/drivers/regulator/palmas-regulator.c @@ -775,6 +775,9 @@ static __devinit int palmas_probe(struct platform_device *pdev) err_unregister_regulator: while (--id >= 0) regulator_unregister(pmic->rdev[id]); + kfree(pmic->rdev); + kfree(pmic->desc); + kfree(pmic); return ret; } @@ -785,6 +788,10 @@ static int __devexit palmas_remove(struct platform_device *pdev) for (id = 0; id < PALMAS_NUM_REGS; id++) regulator_unregister(pmic->rdev[id]); + + kfree(pmic->rdev); + kfree(pmic->desc); + kfree(pmic); return 0; } diff --git a/trunk/drivers/rtc/rtc-cmos.c b/trunk/drivers/rtc/rtc-cmos.c index 4267789ca995..7d5f56edb8ef 100644 --- a/trunk/drivers/rtc/rtc-cmos.c +++ b/trunk/drivers/rtc/rtc-cmos.c @@ -910,17 +910,14 @@ static inline int cmos_poweroff(struct device *dev) static u32 rtc_handler(void *context) { - struct device *dev = context; - - pm_wakeup_event(dev, 0); acpi_clear_event(ACPI_EVENT_RTC); acpi_disable_event(ACPI_EVENT_RTC, 0); return ACPI_INTERRUPT_HANDLED; } -static inline void rtc_wake_setup(struct device *dev) +static inline void rtc_wake_setup(void) { - acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, dev); + acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); /* * After the RTC handler is installed, the Fixed_RTC event should * be disabled. Only when the RTC alarm is set will it be enabled. @@ -953,7 +950,7 @@ cmos_wake_setup(struct device *dev) if (acpi_disabled) return; - rtc_wake_setup(dev); + rtc_wake_setup(); acpi_rtc_info.wake_on = rtc_wake_on; acpi_rtc_info.wake_off = rtc_wake_off; diff --git a/trunk/drivers/staging/ramster/zcache-main.c b/trunk/drivers/staging/ramster/zcache-main.c index d46764b5aaba..4e7ef0e6b79c 100644 --- a/trunk/drivers/staging/ramster/zcache-main.c +++ b/trunk/drivers/staging/ramster/zcache-main.c @@ -3002,7 +3002,7 @@ static inline struct tmem_oid oswiz(unsigned type, u32 ind) return oid; } -static int zcache_frontswap_store(unsigned type, pgoff_t offset, +static int zcache_frontswap_put_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -3025,7 +3025,7 @@ static int zcache_frontswap_store(unsigned type, pgoff_t offset, /* returns 0 if the page was successfully gotten from frontswap, -1 if * was not present (should never happen!) */ -static int zcache_frontswap_load(unsigned type, pgoff_t offset, +static int zcache_frontswap_get_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -3080,8 +3080,8 @@ static void zcache_frontswap_init(unsigned ignored) } static struct frontswap_ops zcache_frontswap_ops = { - .store = zcache_frontswap_store, - .load = zcache_frontswap_load, + .put_page = zcache_frontswap_put_page, + .get_page = zcache_frontswap_get_page, .invalidate_page = zcache_frontswap_flush_page, .invalidate_area = zcache_frontswap_flush_area, .init = zcache_frontswap_init diff --git a/trunk/drivers/staging/zcache/zcache-main.c b/trunk/drivers/staging/zcache/zcache-main.c index 784c796b9848..2734dacacbaf 100644 --- a/trunk/drivers/staging/zcache/zcache-main.c +++ b/trunk/drivers/staging/zcache/zcache-main.c @@ -1835,7 +1835,7 @@ static int zcache_frontswap_poolid = -1; * Swizzling increases objects per swaptype, increasing tmem concurrency * for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS * Setting SWIZ_BITS to 27 basically reconstructs the swap entry from - * frontswap_load(), but has side-effects. Hence using 8. + * frontswap_get_page(), but has side-effects. Hence using 8. */ #define SWIZ_BITS 8 #define SWIZ_MASK ((1 << SWIZ_BITS) - 1) @@ -1849,7 +1849,7 @@ static inline struct tmem_oid oswiz(unsigned type, u32 ind) return oid; } -static int zcache_frontswap_store(unsigned type, pgoff_t offset, +static int zcache_frontswap_put_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -1870,7 +1870,7 @@ static int zcache_frontswap_store(unsigned type, pgoff_t offset, /* returns 0 if the page was successfully gotten from frontswap, -1 if * was not present (should never happen!) */ -static int zcache_frontswap_load(unsigned type, pgoff_t offset, +static int zcache_frontswap_get_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -1919,8 +1919,8 @@ static void zcache_frontswap_init(unsigned ignored) } static struct frontswap_ops zcache_frontswap_ops = { - .store = zcache_frontswap_store, - .load = zcache_frontswap_load, + .put_page = zcache_frontswap_put_page, + .get_page = zcache_frontswap_get_page, .invalidate_page = zcache_frontswap_flush_page, .invalidate_area = zcache_frontswap_flush_area, .init = zcache_frontswap_init diff --git a/trunk/drivers/target/sbp/sbp_target.c b/trunk/drivers/target/sbp/sbp_target.c index 7e6136e2ce81..37c609898f84 100644 --- a/trunk/drivers/target/sbp/sbp_target.c +++ b/trunk/drivers/target/sbp/sbp_target.c @@ -587,14 +587,14 @@ static void sbp_management_request_logout( { struct sbp_tport *tport = agent->tport; struct sbp_tpg *tpg = tport->tpg; - int id; + int login_id; struct sbp_login_descriptor *login; - id = LOGOUT_ORB_LOGIN_ID(be32_to_cpu(req->orb.misc)); + login_id = LOGOUT_ORB_LOGIN_ID(be32_to_cpu(req->orb.misc)); - login = sbp_login_find_by_id(tpg, id); + login = sbp_login_find_by_id(tpg, login_id); if (!login) { - pr_warn("cannot find login: %d\n", id); + pr_warn("cannot find login: %d\n", login_id); req->status.status = cpu_to_be32( STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) | diff --git a/trunk/drivers/target/target_core_file.c b/trunk/drivers/target/target_core_file.c index 9f99d0404908..686dba189f8e 100644 --- a/trunk/drivers/target/target_core_file.c +++ b/trunk/drivers/target/target_core_file.c @@ -133,11 +133,16 @@ static struct se_device *fd_create_virtdevice( ret = PTR_ERR(dev_p); goto fail; } + + /* O_DIRECT too? */ + flags = O_RDWR | O_CREAT | O_LARGEFILE; + /* - * Use O_DSYNC by default instead of O_SYNC to forgo syncing - * of pure timestamp updates. + * If fd_buffered_io=1 has not been set explicitly (the default), + * use O_SYNC to force FILEIO writes to disk. */ - flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; + if (!(fd_dev->fbd_flags & FDBD_USE_BUFFERED_IO)) + flags |= O_SYNC; file = filp_open(dev_p, flags, 0600); if (IS_ERR(file)) { @@ -375,6 +380,23 @@ static void fd_emulate_sync_cache(struct se_cmd *cmd) } } +static void fd_emulate_write_fua(struct se_cmd *cmd) +{ + struct se_device *dev = cmd->se_dev; + struct fd_dev *fd_dev = dev->dev_ptr; + loff_t start = cmd->t_task_lba * + dev->se_sub_dev->se_dev_attrib.block_size; + loff_t end = start + cmd->data_length; + int ret; + + pr_debug("FILEIO: FUA WRITE LBA: %llu, bytes: %u\n", + cmd->t_task_lba, cmd->data_length); + + ret = vfs_fsync_range(fd_dev->fd_file, start, end, 1); + if (ret != 0) + pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret); +} + static int fd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, enum dma_data_direction data_direction) { @@ -389,21 +411,19 @@ static int fd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl, ret = fd_do_readv(cmd, sgl, sgl_nents); } else { ret = fd_do_writev(cmd, sgl, sgl_nents); - /* - * Perform implict vfs_fsync_range() for fd_do_writev() ops - * for SCSI WRITEs with Forced Unit Access (FUA) set. - * Allow this to happen independent of WCE=0 setting. - */ + if (ret > 0 && + dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0 && dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 && (cmd->se_cmd_flags & SCF_FUA)) { - struct fd_dev *fd_dev = dev->dev_ptr; - loff_t start = cmd->t_task_lba * - dev->se_sub_dev->se_dev_attrib.block_size; - loff_t end = start + cmd->data_length; - - vfs_fsync_range(fd_dev->fd_file, start, end, 1); + /* + * We might need to be a bit smarter here + * and return some sense data to let the initiator + * know the FUA WRITE cache sync failed..? + */ + fd_emulate_write_fua(cmd); } + } if (ret < 0) { @@ -422,6 +442,7 @@ enum { static match_table_t tokens = { {Opt_fd_dev_name, "fd_dev_name=%s"}, {Opt_fd_dev_size, "fd_dev_size=%s"}, + {Opt_fd_buffered_io, "fd_buffered_io=%d"}, {Opt_err, NULL} }; @@ -433,7 +454,7 @@ static ssize_t fd_set_configfs_dev_params( struct fd_dev *fd_dev = se_dev->se_dev_su_ptr; char *orig, *ptr, *arg_p, *opts; substring_t args[MAX_OPT_ARGS]; - int ret = 0, token; + int ret = 0, arg, token; opts = kstrdup(page, GFP_KERNEL); if (!opts) @@ -477,6 +498,19 @@ static ssize_t fd_set_configfs_dev_params( " bytes\n", fd_dev->fd_dev_size); fd_dev->fbd_flags |= FBDF_HAS_SIZE; break; + case Opt_fd_buffered_io: + match_int(args, &arg); + if (arg != 1) { + pr_err("bogus fd_buffered_io=%d value\n", arg); + ret = -EINVAL; + goto out; + } + + pr_debug("FILEIO: Using buffered I/O" + " operations for struct fd_dev\n"); + + fd_dev->fbd_flags |= FDBD_USE_BUFFERED_IO; + break; default: break; } @@ -508,8 +542,10 @@ static ssize_t fd_show_configfs_dev_params( ssize_t bl = 0; bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id); - bl += sprintf(b + bl, " File: %s Size: %llu Mode: O_DSYNC\n", - fd_dev->fd_dev_name, fd_dev->fd_dev_size); + bl += sprintf(b + bl, " File: %s Size: %llu Mode: %s\n", + fd_dev->fd_dev_name, fd_dev->fd_dev_size, + (fd_dev->fbd_flags & FDBD_USE_BUFFERED_IO) ? + "Buffered" : "Synchronous"); return bl; } diff --git a/trunk/drivers/target/target_core_file.h b/trunk/drivers/target/target_core_file.h index 70ce7fd7111d..fbd59ef7d8be 100644 --- a/trunk/drivers/target/target_core_file.h +++ b/trunk/drivers/target/target_core_file.h @@ -14,6 +14,7 @@ #define FBDF_HAS_PATH 0x01 #define FBDF_HAS_SIZE 0x02 +#define FDBD_USE_BUFFERED_IO 0x04 struct fd_dev { u32 fbd_flags; diff --git a/trunk/drivers/tty/serial/sh-sci.c b/trunk/drivers/tty/serial/sh-sci.c index 1bd9163bc118..4604153b7954 100644 --- a/trunk/drivers/tty/serial/sh-sci.c +++ b/trunk/drivers/tty/serial/sh-sci.c @@ -2179,16 +2179,6 @@ static int __devinit sci_init_single(struct platform_device *dev, return 0; } -static void sci_cleanup_single(struct sci_port *port) -{ - sci_free_gpios(port); - - clk_put(port->iclk); - clk_put(port->fclk); - - pm_runtime_disable(port->port.dev); -} - #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE static void serial_console_putchar(struct uart_port *port, int ch) { @@ -2370,10 +2360,14 @@ static int sci_remove(struct platform_device *dev) cpufreq_unregister_notifier(&port->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); + sci_free_gpios(port); + uart_remove_one_port(&sci_uart_driver, &port->port); - sci_cleanup_single(port); + clk_put(port->iclk); + clk_put(port->fclk); + pm_runtime_disable(&dev->dev); return 0; } @@ -2391,20 +2385,14 @@ static int __devinit sci_probe_single(struct platform_device *dev, index+1, SCI_NPORTS); dev_notice(&dev->dev, "Consider bumping " "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); - return -EINVAL; + return 0; } ret = sci_init_single(dev, sciport, index, p); if (ret) return ret; - ret = uart_add_one_port(&sci_uart_driver, &sciport->port); - if (ret) { - sci_cleanup_single(sciport); - return ret; - } - - return 0; + return uart_add_one_port(&sci_uart_driver, &sciport->port); } static int __devinit sci_probe(struct platform_device *dev) @@ -2425,22 +2413,24 @@ static int __devinit sci_probe(struct platform_device *dev) ret = sci_probe_single(dev, dev->id, p, sp); if (ret) - return ret; + goto err_unreg; sp->freq_transition.notifier_call = sci_notifier; ret = cpufreq_register_notifier(&sp->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); - if (unlikely(ret < 0)) { - sci_cleanup_single(sp); - return ret; - } + if (unlikely(ret < 0)) + goto err_unreg; #ifdef CONFIG_SH_STANDARD_BIOS sh_bios_gdb_detach(); #endif return 0; + +err_unreg: + sci_remove(dev); + return ret; } static int sci_suspend(struct device *dev) diff --git a/trunk/drivers/video/omap2/displays/panel-taal.c b/trunk/drivers/video/omap2/displays/panel-taal.c index 901576eb5a84..2ce9992f403b 100644 --- a/trunk/drivers/video/omap2/displays/panel-taal.c +++ b/trunk/drivers/video/omap2/displays/panel-taal.c @@ -526,7 +526,7 @@ static ssize_t taal_num_errors_show(struct device *dev, { struct omap_dss_device *dssdev = to_dss_device(dev); struct taal_data *td = dev_get_drvdata(&dssdev->dev); - u8 errors = 0; + u8 errors; int r; mutex_lock(&td->lock); diff --git a/trunk/drivers/video/omap2/dss/core.c b/trunk/drivers/video/omap2/dss/core.c index 5066eee10ccf..72ded9cd2cb0 100644 --- a/trunk/drivers/video/omap2/dss/core.c +++ b/trunk/drivers/video/omap2/dss/core.c @@ -194,7 +194,8 @@ static inline int dss_initialize_debugfs(void) static inline void dss_uninitialize_debugfs(void) { } -int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) +static inline int dss_debugfs_create_file(const char *name, + void (*write)(struct seq_file *)) { return 0; } diff --git a/trunk/drivers/video/omap2/dss/dsi.c b/trunk/drivers/video/omap2/dss/dsi.c index ca8382d346e9..ec363d8390ed 100644 --- a/trunk/drivers/video/omap2/dss/dsi.c +++ b/trunk/drivers/video/omap2/dss/dsi.c @@ -3724,7 +3724,7 @@ static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs, /* CLKIN4DDR = 16 * TXBYTECLKHS */ tlp_avail = thsbyte_clk * (blank - trans_lp); - ttxclkesc = tdsi_fclk * lp_clk_div; + ttxclkesc = tdsi_fclk / lp_clk_div; lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc - 26) / 16; diff --git a/trunk/drivers/video/omap2/dss/dss.c b/trunk/drivers/video/omap2/dss/dss.c index 770632359a17..6ea1ff149f6f 100644 --- a/trunk/drivers/video/omap2/dss/dss.c +++ b/trunk/drivers/video/omap2/dss/dss.c @@ -731,7 +731,7 @@ static void dss_runtime_put(void) DSSDBG("dss_runtime_put\n"); r = pm_runtime_put_sync(&dss.pdev->dev); - WARN_ON(r < 0 && r != -EBUSY); + WARN_ON(r < 0); } /* DEBUGFS */ diff --git a/trunk/drivers/xen/tmem.c b/trunk/drivers/xen/tmem.c index 89f264c67420..dcb79521e6c8 100644 --- a/trunk/drivers/xen/tmem.c +++ b/trunk/drivers/xen/tmem.c @@ -269,7 +269,7 @@ static inline struct tmem_oid oswiz(unsigned type, u32 ind) } /* returns 0 if the page was successfully put into frontswap, -1 if not */ -static int tmem_frontswap_store(unsigned type, pgoff_t offset, +static int tmem_frontswap_put_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -295,7 +295,7 @@ static int tmem_frontswap_store(unsigned type, pgoff_t offset, * returns 0 if the page was successfully gotten from frontswap, -1 if * was not present (should never happen!) */ -static int tmem_frontswap_load(unsigned type, pgoff_t offset, +static int tmem_frontswap_get_page(unsigned type, pgoff_t offset, struct page *page) { u64 ind64 = (u64)offset; @@ -362,8 +362,8 @@ static int __init no_frontswap(char *s) __setup("nofrontswap", no_frontswap); static struct frontswap_ops __initdata tmem_frontswap_ops = { - .store = tmem_frontswap_store, - .load = tmem_frontswap_load, + .put_page = tmem_frontswap_put_page, + .get_page = tmem_frontswap_get_page, .invalidate_page = tmem_frontswap_flush_page, .invalidate_area = tmem_frontswap_flush_area, .init = tmem_frontswap_init diff --git a/trunk/fs/cifs/cifsglob.h b/trunk/fs/cifs/cifsglob.h index 6df0cbe1cbc9..20350a93ed99 100644 --- a/trunk/fs/cifs/cifsglob.h +++ b/trunk/fs/cifs/cifsglob.h @@ -174,7 +174,6 @@ struct smb_version_operations { void (*add_credits)(struct TCP_Server_Info *, const unsigned int); void (*set_credits)(struct TCP_Server_Info *, const int); int * (*get_credits_field)(struct TCP_Server_Info *); - __u64 (*get_next_mid)(struct TCP_Server_Info *); /* data offset from read response message */ unsigned int (*read_data_offset)(char *); /* data length from read response message */ @@ -400,12 +399,6 @@ set_credits(struct TCP_Server_Info *server, const int val) server->ops->set_credits(server, val); } -static inline __u64 -get_next_mid(struct TCP_Server_Info *server) -{ - return server->ops->get_next_mid(server); -} - /* * Macros to allow the TCP_Server_Info->net field and related code to drop out * when CONFIG_NET_NS isn't set. diff --git a/trunk/fs/cifs/cifsproto.h b/trunk/fs/cifs/cifsproto.h index 0a6cbfe2761e..5ec21ecf7980 100644 --- a/trunk/fs/cifs/cifsproto.h +++ b/trunk/fs/cifs/cifsproto.h @@ -114,6 +114,7 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct, void **request_buf); extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, const struct nls_table *nls_cp); +extern __u64 GetNextMid(struct TCP_Server_Info *server); extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); extern u64 cifs_UnixTimeToNT(struct timespec); extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, diff --git a/trunk/fs/cifs/cifssmb.c b/trunk/fs/cifs/cifssmb.c index 5b400730c213..b5ad716b2642 100644 --- a/trunk/fs/cifs/cifssmb.c +++ b/trunk/fs/cifs/cifssmb.c @@ -268,7 +268,7 @@ small_smb_init_no_tc(const int smb_command, const int wct, return rc; buffer = (struct smb_hdr *)*request_buf; - buffer->Mid = get_next_mid(ses->server); + buffer->Mid = GetNextMid(ses->server); if (ses->capabilities & CAP_UNICODE) buffer->Flags2 |= SMBFLG2_UNICODE; if (ses->capabilities & CAP_STATUS32) @@ -402,7 +402,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses) cFYI(1, "secFlags 0x%x", secFlags); - pSMB->hdr.Mid = get_next_mid(server); + pSMB->hdr.Mid = GetNextMid(server); pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) @@ -782,7 +782,7 @@ CIFSSMBLogoff(const int xid, struct cifs_ses *ses) return rc; } - pSMB->hdr.Mid = get_next_mid(ses->server); + pSMB->hdr.Mid = GetNextMid(ses->server); if (ses->server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) @@ -4762,7 +4762,7 @@ CIFSGetDFSRefer(const int xid, struct cifs_ses *ses, /* server pointer checked in called function, but should never be null here anyway */ - pSMB->hdr.Mid = get_next_mid(ses->server); + pSMB->hdr.Mid = GetNextMid(ses->server); pSMB->hdr.Tid = ses->ipc_tid; pSMB->hdr.Uid = ses->Suid; if (ses->capabilities & CAP_STATUS32) diff --git a/trunk/fs/cifs/connect.c b/trunk/fs/cifs/connect.c index 78db68a5cf44..ccafdedd0dbc 100644 --- a/trunk/fs/cifs/connect.c +++ b/trunk/fs/cifs/connect.c @@ -1058,15 +1058,13 @@ cifs_demultiplex_thread(void *p) if (mid_entry != NULL) { if (!mid_entry->multiRsp || mid_entry->multiEnd) mid_entry->callback(mid_entry); - } else if (!server->ops->is_oplock_break || - !server->ops->is_oplock_break(buf, server)) { + } else if (!server->ops->is_oplock_break(buf, server)) { cERROR(1, "No task to wake, unknown frame received! " "NumMids %d", atomic_read(&midCount)); cifs_dump_mem("Received Data is: ", buf, HEADER_SIZE(server)); #ifdef CONFIG_CIFS_DEBUG2 - if (server->ops->dump_detail) - server->ops->dump_detail(buf); + server->ops->dump_detail(buf); cifs_dump_mids(server); #endif /* CIFS_DEBUG2 */ @@ -3940,7 +3938,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, NULL /*no tid */ , 4 /*wct */ ); - smb_buffer->Mid = get_next_mid(ses->server); + smb_buffer->Mid = GetNextMid(ses->server); smb_buffer->Uid = ses->Suid; pSMB = (TCONX_REQ *) smb_buffer; pSMBr = (TCONX_RSP *) smb_buffer_response; diff --git a/trunk/fs/cifs/file.c b/trunk/fs/cifs/file.c index 513adbc211d7..253170dfa716 100644 --- a/trunk/fs/cifs/file.c +++ b/trunk/fs/cifs/file.c @@ -876,7 +876,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) struct cifsLockInfo *li, *tmp; struct cifs_tcon *tcon; struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); - unsigned int num, max_num, max_buf; + unsigned int num, max_num; LOCKING_ANDX_RANGE *buf, *cur; int types[] = {LOCKING_ANDX_LARGE_FILES, LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; @@ -892,19 +892,8 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) return rc; } - /* - * Accessing maxBuf is racy with cifs_reconnect - need to store value - * and check it for zero before using. - */ - max_buf = tcon->ses->server->maxBuf; - if (!max_buf) { - mutex_unlock(&cinode->lock_mutex); - FreeXid(xid); - return -EINVAL; - } - - max_num = (max_buf - sizeof(struct smb_hdr)) / - sizeof(LOCKING_ANDX_RANGE); + max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) / + sizeof(LOCKING_ANDX_RANGE); buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); if (!buf) { mutex_unlock(&cinode->lock_mutex); @@ -1229,7 +1218,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) int types[] = {LOCKING_ANDX_LARGE_FILES, LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; unsigned int i; - unsigned int max_num, num, max_buf; + unsigned int max_num, num; LOCKING_ANDX_RANGE *buf, *cur; struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); @@ -1239,16 +1228,8 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) INIT_LIST_HEAD(&tmp_llist); - /* - * Accessing maxBuf is racy with cifs_reconnect - need to store value - * and check it for zero before using. - */ - max_buf = tcon->ses->server->maxBuf; - if (!max_buf) - return -EINVAL; - - max_num = (max_buf - sizeof(struct smb_hdr)) / - sizeof(LOCKING_ANDX_RANGE); + max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) / + sizeof(LOCKING_ANDX_RANGE); buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); if (!buf) return -ENOMEM; @@ -1266,7 +1247,46 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) continue; if (types[i] != li->type) continue; - if (cinode->can_cache_brlcks) { + if (!cinode->can_cache_brlcks) { + cur->Pid = cpu_to_le16(li->pid); + cur->LengthLow = cpu_to_le32((u32)li->length); + cur->LengthHigh = + cpu_to_le32((u32)(li->length>>32)); + cur->OffsetLow = cpu_to_le32((u32)li->offset); + cur->OffsetHigh = + cpu_to_le32((u32)(li->offset>>32)); + /* + * We need to save a lock here to let us add + * it again to the file's list if the unlock + * range request fails on the server. + */ + list_move(&li->llist, &tmp_llist); + if (++num == max_num) { + stored_rc = cifs_lockv(xid, tcon, + cfile->netfid, + li->type, num, + 0, buf); + if (stored_rc) { + /* + * We failed on the unlock range + * request - add all locks from + * the tmp list to the head of + * the file's list. + */ + cifs_move_llist(&tmp_llist, + &cfile->llist); + rc = stored_rc; + } else + /* + * The unlock range request + * succeed - free the tmp list. + */ + cifs_free_llist(&tmp_llist); + cur = buf; + num = 0; + } else + cur++; + } else { /* * We can cache brlock requests - simply remove * a lock from the file's list. @@ -1274,41 +1294,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) list_del(&li->llist); cifs_del_lock_waiters(li); kfree(li); - continue; } - cur->Pid = cpu_to_le16(li->pid); - cur->LengthLow = cpu_to_le32((u32)li->length); - cur->LengthHigh = cpu_to_le32((u32)(li->length>>32)); - cur->OffsetLow = cpu_to_le32((u32)li->offset); - cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32)); - /* - * We need to save a lock here to let us add it again to - * the file's list if the unlock range request fails on - * the server. - */ - list_move(&li->llist, &tmp_llist); - if (++num == max_num) { - stored_rc = cifs_lockv(xid, tcon, cfile->netfid, - li->type, num, 0, buf); - if (stored_rc) { - /* - * We failed on the unlock range - * request - add all locks from the tmp - * list to the head of the file's list. - */ - cifs_move_llist(&tmp_llist, - &cfile->llist); - rc = stored_rc; - } else - /* - * The unlock range request succeed - - * free the tmp list. - */ - cifs_free_llist(&tmp_llist); - cur = buf; - num = 0; - } else - cur++; } if (num) { stored_rc = cifs_lockv(xid, tcon, cfile->netfid, diff --git a/trunk/fs/cifs/misc.c b/trunk/fs/cifs/misc.c index 557506ae1e2a..e2552d2b2e42 100644 --- a/trunk/fs/cifs/misc.c +++ b/trunk/fs/cifs/misc.c @@ -212,6 +212,93 @@ cifs_small_buf_release(void *buf_to_free) return; } +/* + * Find a free multiplex id (SMB mid). Otherwise there could be + * mid collisions which might cause problems, demultiplexing the + * wrong response to this request. Multiplex ids could collide if + * one of a series requests takes much longer than the others, or + * if a very large number of long lived requests (byte range + * locks or FindNotify requests) are pending. No more than + * 64K-1 requests can be outstanding at one time. If no + * mids are available, return zero. A future optimization + * could make the combination of mids and uid the key we use + * to demultiplex on (rather than mid alone). + * In addition to the above check, the cifs demultiplex + * code already used the command code as a secondary + * check of the frame and if signing is negotiated the + * response would be discarded if the mid were the same + * but the signature was wrong. Since the mid is not put in the + * pending queue until later (when it is about to be dispatched) + * we do have to limit the number of outstanding requests + * to somewhat less than 64K-1 although it is hard to imagine + * so many threads being in the vfs at one time. + */ +__u64 GetNextMid(struct TCP_Server_Info *server) +{ + __u64 mid = 0; + __u16 last_mid, cur_mid; + bool collision; + + spin_lock(&GlobalMid_Lock); + + /* mid is 16 bit only for CIFS/SMB */ + cur_mid = (__u16)((server->CurrentMid) & 0xffff); + /* we do not want to loop forever */ + last_mid = cur_mid; + cur_mid++; + + /* + * This nested loop looks more expensive than it is. + * In practice the list of pending requests is short, + * fewer than 50, and the mids are likely to be unique + * on the first pass through the loop unless some request + * takes longer than the 64 thousand requests before it + * (and it would also have to have been a request that + * did not time out). + */ + while (cur_mid != last_mid) { + struct mid_q_entry *mid_entry; + unsigned int num_mids; + + collision = false; + if (cur_mid == 0) + cur_mid++; + + num_mids = 0; + list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { + ++num_mids; + if (mid_entry->mid == cur_mid && + mid_entry->mid_state == MID_REQUEST_SUBMITTED) { + /* This mid is in use, try a different one */ + collision = true; + break; + } + } + + /* + * if we have more than 32k mids in the list, then something + * is very wrong. Possibly a local user is trying to DoS the + * box by issuing long-running calls and SIGKILL'ing them. If + * we get to 2^16 mids then we're in big trouble as this + * function could loop forever. + * + * Go ahead and assign out the mid in this situation, but force + * an eventual reconnect to clean out the pending_mid_q. + */ + if (num_mids > 32768) + server->tcpStatus = CifsNeedReconnect; + + if (!collision) { + mid = (__u64)cur_mid; + server->CurrentMid = mid; + break; + } + cur_mid++; + } + spin_unlock(&GlobalMid_Lock); + return mid; +} + /* NB: MID can not be set if treeCon not passed in, in that case it is responsbility of caller to set the mid */ void @@ -247,7 +334,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , /* Uid is not converted */ buffer->Uid = treeCon->ses->Suid; - buffer->Mid = get_next_mid(treeCon->ses->server); + buffer->Mid = GetNextMid(treeCon->ses->server); } if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) buffer->Flags2 |= SMBFLG2_DFS; diff --git a/trunk/fs/cifs/smb1ops.c b/trunk/fs/cifs/smb1ops.c index 6dec38f5522d..d9d615fbed3f 100644 --- a/trunk/fs/cifs/smb1ops.c +++ b/trunk/fs/cifs/smb1ops.c @@ -125,94 +125,6 @@ cifs_get_credits_field(struct TCP_Server_Info *server) return &server->credits; } -/* - * Find a free multiplex id (SMB mid). Otherwise there could be - * mid collisions which might cause problems, demultiplexing the - * wrong response to this request. Multiplex ids could collide if - * one of a series requests takes much longer than the others, or - * if a very large number of long lived requests (byte range - * locks or FindNotify requests) are pending. No more than - * 64K-1 requests can be outstanding at one time. If no - * mids are available, return zero. A future optimization - * could make the combination of mids and uid the key we use - * to demultiplex on (rather than mid alone). - * In addition to the above check, the cifs demultiplex - * code already used the command code as a secondary - * check of the frame and if signing is negotiated the - * response would be discarded if the mid were the same - * but the signature was wrong. Since the mid is not put in the - * pending queue until later (when it is about to be dispatched) - * we do have to limit the number of outstanding requests - * to somewhat less than 64K-1 although it is hard to imagine - * so many threads being in the vfs at one time. - */ -static __u64 -cifs_get_next_mid(struct TCP_Server_Info *server) -{ - __u64 mid = 0; - __u16 last_mid, cur_mid; - bool collision; - - spin_lock(&GlobalMid_Lock); - - /* mid is 16 bit only for CIFS/SMB */ - cur_mid = (__u16)((server->CurrentMid) & 0xffff); - /* we do not want to loop forever */ - last_mid = cur_mid; - cur_mid++; - - /* - * This nested loop looks more expensive than it is. - * In practice the list of pending requests is short, - * fewer than 50, and the mids are likely to be unique - * on the first pass through the loop unless some request - * takes longer than the 64 thousand requests before it - * (and it would also have to have been a request that - * did not time out). - */ - while (cur_mid != last_mid) { - struct mid_q_entry *mid_entry; - unsigned int num_mids; - - collision = false; - if (cur_mid == 0) - cur_mid++; - - num_mids = 0; - list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { - ++num_mids; - if (mid_entry->mid == cur_mid && - mid_entry->mid_state == MID_REQUEST_SUBMITTED) { - /* This mid is in use, try a different one */ - collision = true; - break; - } - } - - /* - * if we have more than 32k mids in the list, then something - * is very wrong. Possibly a local user is trying to DoS the - * box by issuing long-running calls and SIGKILL'ing them. If - * we get to 2^16 mids then we're in big trouble as this - * function could loop forever. - * - * Go ahead and assign out the mid in this situation, but force - * an eventual reconnect to clean out the pending_mid_q. - */ - if (num_mids > 32768) - server->tcpStatus = CifsNeedReconnect; - - if (!collision) { - mid = (__u64)cur_mid; - server->CurrentMid = mid; - break; - } - cur_mid++; - } - spin_unlock(&GlobalMid_Lock); - return mid; -} - struct smb_version_operations smb1_operations = { .send_cancel = send_nt_cancel, .compare_fids = cifs_compare_fids, @@ -221,7 +133,6 @@ struct smb_version_operations smb1_operations = { .add_credits = cifs_add_credits, .set_credits = cifs_set_credits, .get_credits_field = cifs_get_credits_field, - .get_next_mid = cifs_get_next_mid, .read_data_offset = cifs_read_data_offset, .read_data_length = cifs_read_data_length, .map_error = map_smb_to_linux_error, diff --git a/trunk/fs/cifs/transport.c b/trunk/fs/cifs/transport.c index 3097ee58fd7d..1b36ffe6a47b 100644 --- a/trunk/fs/cifs/transport.c +++ b/trunk/fs/cifs/transport.c @@ -779,7 +779,7 @@ send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon, pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; pSMB->Timeout = 0; - pSMB->hdr.Mid = get_next_mid(ses->server); + pSMB->hdr.Mid = GetNextMid(ses->server); return SendReceive(xid, ses, in_buf, out_buf, &bytes_returned, 0); diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index 40469044088d..85c9e2bff8e6 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -683,8 +683,6 @@ EXPORT_SYMBOL(dget_parent); /** * d_find_alias - grab a hashed alias of inode * @inode: inode in question - * @want_discon: flag, used by d_splice_alias, to request - * that only a DISCONNECTED alias be returned. * * If inode has a hashed alias, or is a directory and has any alias, * acquire the reference to alias and return it. Otherwise return NULL. @@ -693,10 +691,9 @@ EXPORT_SYMBOL(dget_parent); * of a filesystem. * * If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer - * any other hashed alias over that one unless @want_discon is set, - * in which case only return an IS_ROOT, DCACHE_DISCONNECTED alias. + * any other hashed alias over that. */ -static struct dentry *__d_find_alias(struct inode *inode, int want_discon) +static struct dentry *__d_find_alias(struct inode *inode) { struct dentry *alias, *discon_alias; @@ -708,7 +705,7 @@ static struct dentry *__d_find_alias(struct inode *inode, int want_discon) if (IS_ROOT(alias) && (alias->d_flags & DCACHE_DISCONNECTED)) { discon_alias = alias; - } else if (!want_discon) { + } else { __dget_dlock(alias); spin_unlock(&alias->d_lock); return alias; @@ -739,7 +736,7 @@ struct dentry *d_find_alias(struct inode *inode) if (!list_empty(&inode->i_dentry)) { spin_lock(&inode->i_lock); - de = __d_find_alias(inode, 0); + de = __d_find_alias(inode); spin_unlock(&inode->i_lock); } return de; @@ -1650,9 +1647,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) if (inode && S_ISDIR(inode->i_mode)) { spin_lock(&inode->i_lock); - new = __d_find_alias(inode, 1); + new = __d_find_any_alias(inode); if (new) { - BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED)); spin_unlock(&inode->i_lock); security_d_instantiate(new, inode); d_move(new, dentry); @@ -2482,7 +2478,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) struct dentry *alias; /* Does an aliased dentry already exist? */ - alias = __d_find_alias(inode, 0); + alias = __d_find_alias(inode); if (alias) { actual = alias; write_seqlock(&rename_lock); diff --git a/trunk/fs/exofs/sys.c b/trunk/fs/exofs/sys.c index 5a7b691e748b..e32bc919e4e3 100644 --- a/trunk/fs/exofs/sys.c +++ b/trunk/fs/exofs/sys.c @@ -109,7 +109,7 @@ static struct kobj_type odev_ktype = { static struct kobj_type uuid_ktype = { }; -void exofs_sysfs_dbg_print(void) +void exofs_sysfs_dbg_print() { #ifdef CONFIG_EXOFS_DEBUG struct kobject *k_name, *k_tmp; diff --git a/trunk/fs/ext4/balloc.c b/trunk/fs/ext4/balloc.c index cee7812cc3cf..99b6324290db 100644 --- a/trunk/fs/ext4/balloc.c +++ b/trunk/fs/ext4/balloc.c @@ -90,8 +90,8 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb, * unusual file system layouts. */ if (ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), block_group)) { - block_cluster = EXT4_B2C(sbi, - ext4_block_bitmap(sb, gdp) - start); + block_cluster = EXT4_B2C(sbi, (start - + ext4_block_bitmap(sb, gdp))); if (block_cluster < num_clusters) block_cluster = -1; else if (block_cluster == num_clusters) { @@ -102,7 +102,7 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb, if (ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), block_group)) { inode_cluster = EXT4_B2C(sbi, - ext4_inode_bitmap(sb, gdp) - start); + start - ext4_inode_bitmap(sb, gdp)); if (inode_cluster < num_clusters) inode_cluster = -1; else if (inode_cluster == num_clusters) { @@ -114,7 +114,7 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb, itbl_blk = ext4_inode_table(sb, gdp); for (i = 0; i < sbi->s_itb_per_group; i++) { if (ext4_block_in_group(sb, itbl_blk + i, block_group)) { - c = EXT4_B2C(sbi, itbl_blk + i - start); + c = EXT4_B2C(sbi, start - itbl_blk + i); if ((c < num_clusters) || (c == inode_cluster) || (c == block_cluster) || (c == itbl_cluster)) continue; diff --git a/trunk/fs/ext4/ioctl.c b/trunk/fs/ext4/ioctl.c index e34deac3f366..8ad112ae0ade 100644 --- a/trunk/fs/ext4/ioctl.c +++ b/trunk/fs/ext4/ioctl.c @@ -123,6 +123,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) else ext4_clear_inode_flag(inode, i); } + ei->i_flags = flags; ext4_set_inode_flags(inode); inode->i_ctime = ext4_current_time(inode); diff --git a/trunk/fs/fs-writeback.c b/trunk/fs/fs-writeback.c index 41a3ccff18d8..8d2fb8c88cf3 100644 --- a/trunk/fs/fs-writeback.c +++ b/trunk/fs/fs-writeback.c @@ -664,7 +664,6 @@ static long writeback_sb_inodes(struct super_block *sb, /* Wait for I_SYNC. This function drops i_lock... */ inode_sleep_on_writeback(inode); /* Inode may be gone, start again */ - spin_lock(&wb->list_lock); continue; } inode->i_state |= I_SYNC; diff --git a/trunk/fs/fuse/control.c b/trunk/fs/fuse/control.c index 03ff5b1eba93..42593c587d48 100644 --- a/trunk/fs/fuse/control.c +++ b/trunk/fs/fuse/control.c @@ -75,13 +75,19 @@ static ssize_t fuse_conn_limit_write(struct file *file, const char __user *buf, unsigned global_limit) { unsigned long t; + char tmp[32]; unsigned limit = (1 << 16) - 1; int err; - if (*ppos) + if (*ppos || count >= sizeof(tmp) - 1) + return -EINVAL; + + if (copy_from_user(tmp, buf, count)) return -EINVAL; - err = kstrtoul_from_user(buf, count, 0, &t); + tmp[count] = '\0'; + + err = strict_strtoul(tmp, 0, &t); if (err) return err; diff --git a/trunk/fs/fuse/dir.c b/trunk/fs/fuse/dir.c index 334e0b18a014..df5ac048dc74 100644 --- a/trunk/fs/fuse/dir.c +++ b/trunk/fs/fuse/dir.c @@ -775,8 +775,6 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, struct kstat *stat) { - unsigned int blkbits; - stat->dev = inode->i_sb->s_dev; stat->ino = attr->ino; stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); @@ -792,13 +790,7 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, stat->ctime.tv_nsec = attr->ctimensec; stat->size = attr->size; stat->blocks = attr->blocks; - - if (attr->blksize != 0) - blkbits = ilog2(attr->blksize); - else - blkbits = inode->i_sb->s_blocksize_bits; - - stat->blksize = 1 << blkbits; + stat->blksize = (1 << inode->i_blkbits); } static int fuse_do_getattr(struct inode *inode, struct kstat *stat, @@ -871,7 +863,6 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, if (stat) { generic_fillattr(inode, stat); stat->mode = fi->orig_i_mode; - stat->ino = fi->orig_ino; } } diff --git a/trunk/fs/fuse/file.c b/trunk/fs/fuse/file.c index b321a688cde7..9562109d3a87 100644 --- a/trunk/fs/fuse/file.c +++ b/trunk/fs/fuse/file.c @@ -2173,44 +2173,6 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, return ret; } -long fuse_file_fallocate(struct file *file, int mode, loff_t offset, - loff_t length) -{ - struct fuse_file *ff = file->private_data; - struct fuse_conn *fc = ff->fc; - struct fuse_req *req; - struct fuse_fallocate_in inarg = { - .fh = ff->fh, - .offset = offset, - .length = length, - .mode = mode - }; - int err; - - if (fc->no_fallocate) - return -EOPNOTSUPP; - - req = fuse_get_req(fc); - if (IS_ERR(req)) - return PTR_ERR(req); - - req->in.h.opcode = FUSE_FALLOCATE; - req->in.h.nodeid = ff->nodeid; - req->in.numargs = 1; - req->in.args[0].size = sizeof(inarg); - req->in.args[0].value = &inarg; - fuse_request_send(fc, req); - err = req->out.h.error; - if (err == -ENOSYS) { - fc->no_fallocate = 1; - err = -EOPNOTSUPP; - } - fuse_put_request(fc, req); - - return err; -} -EXPORT_SYMBOL_GPL(fuse_file_fallocate); - static const struct file_operations fuse_file_operations = { .llseek = fuse_file_llseek, .read = do_sync_read, @@ -2228,7 +2190,6 @@ static const struct file_operations fuse_file_operations = { .unlocked_ioctl = fuse_file_ioctl, .compat_ioctl = fuse_file_compat_ioctl, .poll = fuse_file_poll, - .fallocate = fuse_file_fallocate, }; static const struct file_operations fuse_direct_io_file_operations = { @@ -2245,7 +2206,6 @@ static const struct file_operations fuse_direct_io_file_operations = { .unlocked_ioctl = fuse_file_ioctl, .compat_ioctl = fuse_file_compat_ioctl, .poll = fuse_file_poll, - .fallocate = fuse_file_fallocate, /* no splice_read */ }; diff --git a/trunk/fs/fuse/fuse_i.h b/trunk/fs/fuse/fuse_i.h index 771fb6322c07..572cefc78012 100644 --- a/trunk/fs/fuse/fuse_i.h +++ b/trunk/fs/fuse/fuse_i.h @@ -82,9 +82,6 @@ struct fuse_inode { preserve the original mode */ umode_t orig_i_mode; - /** 64 bit inode number */ - u64 orig_ino; - /** Version of last attribute change */ u64 attr_version; @@ -481,9 +478,6 @@ struct fuse_conn { /** Are BSD file locking primitives not implemented by fs? */ unsigned no_flock:1; - /** Is fallocate not implemented by fs? */ - unsigned no_fallocate:1; - /** The number of requests waiting for completion */ atomic_t num_waiting; diff --git a/trunk/fs/fuse/inode.c b/trunk/fs/fuse/inode.c index 1cd61652018c..42678a33b7bb 100644 --- a/trunk/fs/fuse/inode.c +++ b/trunk/fs/fuse/inode.c @@ -91,7 +91,6 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) fi->nlookup = 0; fi->attr_version = 0; fi->writectr = 0; - fi->orig_ino = 0; INIT_LIST_HEAD(&fi->write_files); INIT_LIST_HEAD(&fi->queued_writes); INIT_LIST_HEAD(&fi->writepages); @@ -140,18 +139,6 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) return 0; } -/* - * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down - * so that it will fit. - */ -static ino_t fuse_squash_ino(u64 ino64) -{ - ino_t ino = (ino_t) ino64; - if (sizeof(ino_t) < sizeof(u64)) - ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8; - return ino; -} - void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, u64 attr_valid) { @@ -161,7 +148,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, fi->attr_version = ++fc->attr_version; fi->i_time = attr_valid; - inode->i_ino = fuse_squash_ino(attr->ino); + inode->i_ino = attr->ino; inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); set_nlink(inode, attr->nlink); inode->i_uid = attr->uid; @@ -187,8 +174,6 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, fi->orig_i_mode = inode->i_mode; if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) inode->i_mode &= ~S_ISVTX; - - fi->orig_ino = attr->ino; } void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, diff --git a/trunk/fs/proc/base.c b/trunk/fs/proc/base.c index 437195f204e1..616f41a7cde6 100644 --- a/trunk/fs/proc/base.c +++ b/trunk/fs/proc/base.c @@ -1803,7 +1803,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) rcu_read_lock(); file = fcheck_files(files, fd); if (file) { - unsigned f_mode = file->f_mode; + unsigned i_mode, f_mode = file->f_mode; rcu_read_unlock(); put_files_struct(files); @@ -1819,14 +1819,12 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) inode->i_gid = GLOBAL_ROOT_GID; } - if (S_ISLNK(inode->i_mode)) { - unsigned i_mode = S_IFLNK; - if (f_mode & FMODE_READ) - i_mode |= S_IRUSR | S_IXUSR; - if (f_mode & FMODE_WRITE) - i_mode |= S_IWUSR | S_IXUSR; - inode->i_mode = i_mode; - } + i_mode = S_IFLNK; + if (f_mode & FMODE_READ) + i_mode |= S_IRUSR | S_IXUSR; + if (f_mode & FMODE_WRITE) + i_mode |= S_IWUSR | S_IXUSR; + inode->i_mode = i_mode; security_task_to_inode(task, inode); put_task_struct(task); @@ -1861,7 +1859,6 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, ei = PROC_I(inode); ei->fd = fd; - inode->i_mode = S_IFLNK; inode->i_op = &proc_pid_link_inode_operations; inode->i_size = 64; ei->op.proc_get_link = proc_fd_link; diff --git a/trunk/fs/ubifs/debug.c b/trunk/fs/ubifs/debug.c index 84a7e6f3c046..685a83756b2b 100644 --- a/trunk/fs/ubifs/debug.c +++ b/trunk/fs/ubifs/debug.c @@ -2918,9 +2918,6 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) struct dentry *dent; struct ubifs_debug_info *d = c->dbg; - if (!IS_ENABLED(DEBUG_FS)) - return 0; - n = snprintf(d->dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME, c->vi.ubi_num, c->vi.vol_id); if (n == UBIFS_DFS_DIR_LEN) { @@ -3013,8 +3010,7 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) */ void dbg_debugfs_exit_fs(struct ubifs_info *c) { - if (IS_ENABLED(DEBUG_FS)) - debugfs_remove_recursive(c->dbg->dfs_dir); + debugfs_remove_recursive(c->dbg->dfs_dir); } struct ubifs_global_debug_info ubifs_dbg; @@ -3099,9 +3095,6 @@ int dbg_debugfs_init(void) const char *fname; struct dentry *dent; - if (!IS_ENABLED(DEBUG_FS)) - return 0; - fname = "ubifs"; dent = debugfs_create_dir(fname, NULL); if (IS_ERR_OR_NULL(dent)) @@ -3166,8 +3159,7 @@ int dbg_debugfs_init(void) */ void dbg_debugfs_exit(void) { - if (IS_ENABLED(DEBUG_FS)) - debugfs_remove_recursive(dfs_rootdir); + debugfs_remove_recursive(dfs_rootdir); } /** diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index 9e6e1c6eb60a..b0d62820ada1 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -440,8 +440,8 @@ static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable) #else /* CONFIG_ACPI */ -static inline int register_acpi_bus_type(void *bus) { return 0; } -static inline int unregister_acpi_bus_type(void *bus) { return 0; } +static int register_acpi_bus_type(struct acpi_bus_type *bus) { return 0; } +static int unregister_acpi_bus_type(struct acpi_bus_type *bus) { return 0; } #endif /* CONFIG_ACPI */ diff --git a/trunk/include/asm-generic/bug.h b/trunk/include/asm-generic/bug.h index 9f02005f217a..2520a6e241dc 100644 --- a/trunk/include/asm-generic/bug.h +++ b/trunk/include/asm-generic/bug.h @@ -2,7 +2,6 @@ #define _ASM_GENERIC_BUG_H #include -#include #ifdef CONFIG_BUG diff --git a/trunk/include/drm/drm_crtc.h b/trunk/include/drm/drm_crtc.h index bac55c215113..73e45600f95d 100644 --- a/trunk/include/drm/drm_crtc.h +++ b/trunk/include/drm/drm_crtc.h @@ -54,7 +54,7 @@ struct drm_mode_object { struct drm_object_properties *properties; }; -#define DRM_OBJECT_MAX_PROPERTY 24 +#define DRM_OBJECT_MAX_PROPERTY 16 struct drm_object_properties { int count; uint32_t ids[DRM_OBJECT_MAX_PROPERTY]; diff --git a/trunk/include/drm/drm_pciids.h b/trunk/include/drm/drm_pciids.h index 81368ab6c611..58d0bdab68dd 100644 --- a/trunk/include/drm/drm_pciids.h +++ b/trunk/include/drm/drm_pciids.h @@ -181,7 +181,6 @@ {0x1002, 0x6747, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6748, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x674A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6758, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ @@ -199,7 +198,6 @@ {0x1002, 0x6767, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6768, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6771, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ @@ -231,11 +229,10 @@ {0x1002, 0x6827, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ @@ -534,7 +531,6 @@ {0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ - {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ @@ -554,7 +550,6 @@ {0x1002, 0x9807, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x980A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ @@ -566,19 +561,11 @@ {0x1002, 0x9909, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x990A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x990F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x9910, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x9913, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x9917, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x9918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x9919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9990, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9991, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9993, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9994, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x99A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x99A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x99A4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0, 0, 0} #define r128_PCI_IDS \ diff --git a/trunk/include/drm/exynos_drm.h b/trunk/include/drm/exynos_drm.h index 68733587e700..b6d7ce92eadd 100644 --- a/trunk/include/drm/exynos_drm.h +++ b/trunk/include/drm/exynos_drm.h @@ -64,7 +64,6 @@ struct drm_exynos_gem_map_off { * A structure for mapping buffer. * * @handle: a handle to gem object created. - * @pad: just padding to be 64-bit aligned. * @size: memory size to be mapped. * @mapped: having user virtual address mmaped. * - this variable would be filled by exynos gem module @@ -73,8 +72,7 @@ struct drm_exynos_gem_map_off { */ struct drm_exynos_gem_mmap { unsigned int handle; - unsigned int pad; - uint64_t size; + unsigned int size; uint64_t mapped; }; diff --git a/trunk/include/linux/clockchips.h b/trunk/include/linux/clockchips.h index acba894374a1..81e803e90aa4 100644 --- a/trunk/include/linux/clockchips.h +++ b/trunk/include/linux/clockchips.h @@ -132,7 +132,6 @@ extern u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt); extern void clockevents_register_device(struct clock_event_device *dev); -extern void clockevents_config(struct clock_event_device *dev, u32 freq); extern void clockevents_config_and_register(struct clock_event_device *dev, u32 freq, unsigned long min_delta, unsigned long max_delta); diff --git a/trunk/include/linux/compaction.h b/trunk/include/linux/compaction.h index 51a90b7f2d60..e988037abd2a 100644 --- a/trunk/include/linux/compaction.h +++ b/trunk/include/linux/compaction.h @@ -1,6 +1,8 @@ #ifndef _LINUX_COMPACTION_H #define _LINUX_COMPACTION_H +#include + /* Return values for compact_zone() and try_to_compact_pages() */ /* compaction didn't start as it was not possible or direct reclaim was more suitable */ #define COMPACT_SKIPPED 0 @@ -11,6 +13,23 @@ /* The full zone was compacted */ #define COMPACT_COMPLETE 3 +/* + * compaction supports three modes + * + * COMPACT_ASYNC_MOVABLE uses asynchronous migration and only scans + * MIGRATE_MOVABLE pageblocks as migration sources and targets. + * COMPACT_ASYNC_UNMOVABLE uses asynchronous migration and only scans + * MIGRATE_MOVABLE pageblocks as migration sources. + * MIGRATE_UNMOVABLE pageblocks are scanned as potential migration + * targets and convers them to MIGRATE_MOVABLE if possible + * COMPACT_SYNC uses synchronous migration and scans all pageblocks + */ +enum compact_mode { + COMPACT_ASYNC_MOVABLE, + COMPACT_ASYNC_UNMOVABLE, + COMPACT_SYNC, +}; + #ifdef CONFIG_COMPACTION extern int sysctl_compact_memory; extern int sysctl_compaction_handler(struct ctl_table *table, int write, diff --git a/trunk/include/linux/frontswap.h b/trunk/include/linux/frontswap.h deleted file mode 100644 index 0e4e2eec5c1d..000000000000 --- a/trunk/include/linux/frontswap.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef _LINUX_FRONTSWAP_H -#define _LINUX_FRONTSWAP_H - -#include -#include -#include - -struct frontswap_ops { - void (*init)(unsigned); - int (*store)(unsigned, pgoff_t, struct page *); - int (*load)(unsigned, pgoff_t, struct page *); - void (*invalidate_page)(unsigned, pgoff_t); - void (*invalidate_area)(unsigned); -}; - -extern bool frontswap_enabled; -extern struct frontswap_ops - frontswap_register_ops(struct frontswap_ops *ops); -extern void frontswap_shrink(unsigned long); -extern unsigned long frontswap_curr_pages(void); -extern void frontswap_writethrough(bool); - -extern void __frontswap_init(unsigned type); -extern int __frontswap_store(struct page *page); -extern int __frontswap_load(struct page *page); -extern void __frontswap_invalidate_page(unsigned, pgoff_t); -extern void __frontswap_invalidate_area(unsigned); - -#ifdef CONFIG_FRONTSWAP - -static inline bool frontswap_test(struct swap_info_struct *sis, pgoff_t offset) -{ - bool ret = false; - - if (frontswap_enabled && sis->frontswap_map) - ret = test_bit(offset, sis->frontswap_map); - return ret; -} - -static inline void frontswap_set(struct swap_info_struct *sis, pgoff_t offset) -{ - if (frontswap_enabled && sis->frontswap_map) - set_bit(offset, sis->frontswap_map); -} - -static inline void frontswap_clear(struct swap_info_struct *sis, pgoff_t offset) -{ - if (frontswap_enabled && sis->frontswap_map) - clear_bit(offset, sis->frontswap_map); -} - -static inline void frontswap_map_set(struct swap_info_struct *p, - unsigned long *map) -{ - p->frontswap_map = map; -} - -static inline unsigned long *frontswap_map_get(struct swap_info_struct *p) -{ - return p->frontswap_map; -} -#else -/* all inline routines become no-ops and all externs are ignored */ - -#define frontswap_enabled (0) - -static inline bool frontswap_test(struct swap_info_struct *sis, pgoff_t offset) -{ - return false; -} - -static inline void frontswap_set(struct swap_info_struct *sis, pgoff_t offset) -{ -} - -static inline void frontswap_clear(struct swap_info_struct *sis, pgoff_t offset) -{ -} - -static inline void frontswap_map_set(struct swap_info_struct *p, - unsigned long *map) -{ -} - -static inline unsigned long *frontswap_map_get(struct swap_info_struct *p) -{ - return NULL; -} -#endif - -static inline int frontswap_store(struct page *page) -{ - int ret = -1; - - if (frontswap_enabled) - ret = __frontswap_store(page); - return ret; -} - -static inline int frontswap_load(struct page *page) -{ - int ret = -1; - - if (frontswap_enabled) - ret = __frontswap_load(page); - return ret; -} - -static inline void frontswap_invalidate_page(unsigned type, pgoff_t offset) -{ - if (frontswap_enabled) - __frontswap_invalidate_page(type, offset); -} - -static inline void frontswap_invalidate_area(unsigned type) -{ - if (frontswap_enabled) - __frontswap_invalidate_area(type); -} - -static inline void frontswap_init(unsigned type) -{ - if (frontswap_enabled) - __frontswap_init(type); -} - -#endif /* _LINUX_FRONTSWAP_H */ diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 17fd887c798f..51978ed43e97 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -802,14 +802,13 @@ struct inode { unsigned int __i_nlink; }; dev_t i_rdev; - loff_t i_size; struct timespec i_atime; struct timespec i_mtime; struct timespec i_ctime; spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned short i_bytes; - unsigned int i_blkbits; blkcnt_t i_blocks; + loff_t i_size; #ifdef __NEED_I_SIZE_ORDERED seqcount_t i_size_seqcount; @@ -829,8 +828,9 @@ struct inode { struct list_head i_dentry; struct rcu_head i_rcu; }; - u64 i_version; atomic_t i_count; + unsigned int i_blkbits; + u64 i_version; atomic_t i_dio_count; atomic_t i_writecount; const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ diff --git a/trunk/include/linux/fuse.h b/trunk/include/linux/fuse.h index 9303348965fb..8f2ab8fef929 100644 --- a/trunk/include/linux/fuse.h +++ b/trunk/include/linux/fuse.h @@ -54,9 +54,6 @@ * 7.18 * - add FUSE_IOCTL_DIR flag * - add FUSE_NOTIFY_DELETE - * - * 7.19 - * - add FUSE_FALLOCATE */ #ifndef _LINUX_FUSE_H @@ -88,7 +85,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 19 +#define FUSE_KERNEL_MINOR_VERSION 18 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -281,7 +278,6 @@ enum fuse_opcode { FUSE_POLL = 40, FUSE_NOTIFY_REPLY = 41, FUSE_BATCH_FORGET = 42, - FUSE_FALLOCATE = 43, /* CUSE specific operations */ CUSE_INIT = 4096, @@ -575,14 +571,6 @@ struct fuse_notify_poll_wakeup_out { __u64 kh; }; -struct fuse_fallocate_in { - __u64 fh; - __u64 offset; - __u64 length; - __u32 mode; - __u32 padding; -}; - struct fuse_in_header { __u32 len; __u32 opcode; diff --git a/trunk/include/linux/i2c-mux-pinctrl.h b/trunk/include/linux/i2c-mux-pinctrl.h deleted file mode 100644 index a65c86429e84..000000000000 --- a/trunk/include/linux/i2c-mux-pinctrl.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * i2c-mux-pinctrl platform data - * - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _LINUX_I2C_MUX_PINCTRL_H -#define _LINUX_I2C_MUX_PINCTRL_H - -/** - * struct i2c_mux_pinctrl_platform_data - Platform data for i2c-mux-pinctrl - * @parent_bus_num: Parent I2C bus number - * @base_bus_num: Base I2C bus number for the child busses. 0 for dynamic. - * @bus_count: Number of child busses. Also the number of elements in - * @pinctrl_states - * @pinctrl_states: The names of the pinctrl state to select for each child bus - * @pinctrl_state_idle: The pinctrl state to select when no child bus is being - * accessed. If NULL, the most recently used pinctrl state will be left - * selected. - */ -struct i2c_mux_pinctrl_platform_data { - int parent_bus_num; - int base_bus_num; - int bus_count; - const char **pinctrl_states; - const char *pinctrl_state_idle; -}; - -#endif diff --git a/trunk/include/linux/init_task.h b/trunk/include/linux/init_task.h index 9e65eff6af3b..e4baff5f7ff4 100644 --- a/trunk/include/linux/init_task.h +++ b/trunk/include/linux/init_task.h @@ -149,7 +149,6 @@ extern struct cred init_cred; .normal_prio = MAX_PRIO-20, \ .policy = SCHED_NORMAL, \ .cpus_allowed = CPU_MASK_ALL, \ - .nr_cpus_allowed= NR_CPUS, \ .mm = NULL, \ .active_mm = &init_mm, \ .se = { \ @@ -158,6 +157,7 @@ extern struct cred init_cred; .rt = { \ .run_list = LIST_HEAD_INIT(tsk.rt.run_list), \ .time_slice = RR_TIMESLICE, \ + .nr_cpus_allowed = NR_CPUS, \ }, \ .tasks = LIST_HEAD_INIT(tsk.tasks), \ INIT_PUSHABLE_TASKS(tsk) \ diff --git a/trunk/include/linux/moduleparam.h b/trunk/include/linux/moduleparam.h index d6a58065c09c..1b14d25162cb 100644 --- a/trunk/include/linux/moduleparam.h +++ b/trunk/include/linux/moduleparam.h @@ -128,7 +128,7 @@ struct kparam_array * The ops can have NULL set or get functions. */ #define module_param_cb(name, ops, arg, perm) \ - __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1) + __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, 0) /** * _param_cb - general callback for a module/cmdline parameter @@ -192,7 +192,7 @@ struct kparam_array { (void *)set, (void *)get }; \ __module_param_call(MODULE_PARAM_PREFIX, \ name, &__param_ops_##name, arg, \ - (perm) + sizeof(__check_old_set_param(set))*0, -1) + (perm) + sizeof(__check_old_set_param(set))*0, 0) /* We don't get oldget: it's often a new-style param_get_uint, etc. */ static inline int @@ -272,7 +272,7 @@ static inline void __kernel_param_unlock(void) */ #define core_param(name, var, type, perm) \ param_check_##type(name, &(var)); \ - __module_param_call("", name, ¶m_ops_##type, &var, perm, -1) + __module_param_call("", name, ¶m_ops_##type, &var, perm, 0) #endif /* !MODULE */ /** @@ -290,7 +290,7 @@ static inline void __kernel_param_unlock(void) = { len, string }; \ __module_param_call(MODULE_PARAM_PREFIX, name, \ ¶m_ops_string, \ - .str = &__param_string_##name, perm, -1); \ + .str = &__param_string_##name, perm, 0); \ __MODULE_PARM_TYPE(name, "string") /** @@ -432,7 +432,7 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp); __module_param_call(MODULE_PARAM_PREFIX, name, \ ¶m_array_ops, \ .arr = &__param_arr_##name, \ - perm, -1); \ + perm, 0); \ __MODULE_PARM_TYPE(name, "array of " #type) extern struct kernel_param_ops param_array_ops; diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 2c2ecea28a1b..a0b84e3b087c 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -1627,7 +1627,6 @@ extern int dev_alloc_name(struct net_device *dev, const char *name); extern int dev_open(struct net_device *dev); extern int dev_close(struct net_device *dev); extern void dev_disable_lro(struct net_device *dev); -extern int dev_loopback_xmit(struct sk_buff *newskb); extern int dev_queue_xmit(struct sk_buff *skb); extern int register_netdevice(struct net_device *dev); extern void unregister_netdevice_queue(struct net_device *dev, diff --git a/trunk/include/linux/netfilter/xt_HMARK.h b/trunk/include/linux/netfilter/xt_HMARK.h index 826fc5807577..abb1650940d2 100644 --- a/trunk/include/linux/netfilter/xt_HMARK.h +++ b/trunk/include/linux/netfilter/xt_HMARK.h @@ -27,12 +27,7 @@ union hmark_ports { __u16 src; __u16 dst; } p16; - struct { - __be16 src; - __be16 dst; - } b16; __u32 v32; - __be32 b32; }; struct xt_hmark_info { diff --git a/trunk/include/linux/perf_event.h b/trunk/include/linux/perf_event.h index 45db49f64bb4..f32578634d9d 100644 --- a/trunk/include/linux/perf_event.h +++ b/trunk/include/linux/perf_event.h @@ -555,8 +555,6 @@ enum perf_event_type { PERF_RECORD_MAX, /* non-ABI */ }; -#define PERF_MAX_STACK_DEPTH 127 - enum perf_callchain_context { PERF_CONTEXT_HV = (__u64)-32, PERF_CONTEXT_KERNEL = (__u64)-128, @@ -611,6 +609,8 @@ struct perf_guest_info_callbacks { #include #include +#define PERF_MAX_STACK_DEPTH 255 + struct perf_callchain_entry { __u64 nr; __u64 ip[PERF_MAX_STACK_DEPTH]; diff --git a/trunk/include/linux/prctl.h b/trunk/include/linux/prctl.h index 3988012255dc..711e0a30aacc 100644 --- a/trunk/include/linux/prctl.h +++ b/trunk/include/linux/prctl.h @@ -127,8 +127,8 @@ #define PR_SET_PTRACER 0x59616d61 # define PR_SET_PTRACER_ANY ((unsigned long)-1) -#define PR_SET_CHILD_SUBREAPER 36 -#define PR_GET_CHILD_SUBREAPER 37 +#define PR_SET_CHILD_SUBREAPER 36 +#define PR_GET_CHILD_SUBREAPER 37 /* * If no_new_privs is set, then operations that grant new privileges (i.e. @@ -142,9 +142,7 @@ * asking selinux for a specific new context (e.g. with runcon) will result * in execve returning -EPERM. */ -#define PR_SET_NO_NEW_PRIVS 38 -#define PR_GET_NO_NEW_PRIVS 39 - -#define PR_GET_TID_ADDRESS 40 +#define PR_SET_NO_NEW_PRIVS 38 +#define PR_GET_NO_NEW_PRIVS 39 #endif /* _LINUX_PRCTL_H */ diff --git a/trunk/include/linux/radix-tree.h b/trunk/include/linux/radix-tree.h index ffc444c38b0a..0d04cd69ab9b 100644 --- a/trunk/include/linux/radix-tree.h +++ b/trunk/include/linux/radix-tree.h @@ -368,11 +368,8 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) iter->index++; if (likely(*slot)) return slot; - if (flags & RADIX_TREE_ITER_CONTIG) { - /* forbid switching to the next chunk */ - iter->next_index = 0; + if (flags & RADIX_TREE_ITER_CONTIG) break; - } } } return NULL; diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 4059c0f33f07..f34437e835a7 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -145,7 +145,6 @@ extern unsigned long this_cpu_load(void); extern void calc_global_load(unsigned long ticks); -extern void update_cpu_load_nohz(void); extern unsigned long get_parent_ip(unsigned long addr); @@ -439,7 +438,6 @@ extern int get_dumpable(struct mm_struct *mm); /* leave room for more dump flags */ #define MMF_VM_MERGEABLE 16 /* KSM may merge identical pages */ #define MMF_VM_HUGEPAGE 17 /* set when VM_HUGEPAGE is set on vma */ -#define MMF_EXE_FILE_CHANGED 18 /* see prctl_set_mm_exe_file() */ #define MMF_INIT_MASK (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK) @@ -877,8 +875,6 @@ struct sched_group_power { * Number of busy cpus in this group. */ atomic_t nr_busy_cpus; - - unsigned long cpumask[0]; /* iteration mask */ }; struct sched_group { @@ -903,15 +899,6 @@ static inline struct cpumask *sched_group_cpus(struct sched_group *sg) return to_cpumask(sg->cpumask); } -/* - * cpumask masking which cpus in the group are allowed to iterate up the domain - * tree. - */ -static inline struct cpumask *sched_group_mask(struct sched_group *sg) -{ - return to_cpumask(sg->sgp->cpumask); -} - /** * group_first_cpu - Returns the first cpu in the cpumask of a sched_group. * @group: The group whose first cpu is to be returned. @@ -1200,6 +1187,7 @@ struct sched_rt_entity { struct list_head run_list; unsigned long timeout; unsigned int time_slice; + int nr_cpus_allowed; struct sched_rt_entity *back; #ifdef CONFIG_RT_GROUP_SCHED @@ -1264,7 +1252,6 @@ struct task_struct { #endif unsigned int policy; - int nr_cpus_allowed; cpumask_t cpus_allowed; #ifdef CONFIG_PREEMPT_RCU diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index 642cb7355df3..b534a1be540a 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -225,11 +225,14 @@ enum { /* device driver is going to provide hardware time stamp */ SKBTX_IN_PROGRESS = 1 << 2, + /* ensure the originating sk reference is available on driver level */ + SKBTX_DRV_NEEDS_SK_REF = 1 << 3, + /* device driver supports TX zero-copy buffers */ - SKBTX_DEV_ZEROCOPY = 1 << 3, + SKBTX_DEV_ZEROCOPY = 1 << 4, /* generate wifi status information (where possible) */ - SKBTX_WIFI_STATUS = 1 << 4, + SKBTX_WIFI_STATUS = 1 << 5, }; /* diff --git a/trunk/include/linux/swap.h b/trunk/include/linux/swap.h index c84ec68eaec9..b6661933e252 100644 --- a/trunk/include/linux/swap.h +++ b/trunk/include/linux/swap.h @@ -197,10 +197,6 @@ struct swap_info_struct { struct block_device *bdev; /* swap device or bdev of swap file */ struct file *swap_file; /* seldom referenced */ unsigned int old_block_size; /* seldom referenced */ -#ifdef CONFIG_FRONTSWAP - unsigned long *frontswap_map; /* frontswap in-use, one bit per page */ - atomic_t frontswap_pages; /* frontswap pages in-use counter */ -#endif }; struct swap_list_t { diff --git a/trunk/include/linux/swapfile.h b/trunk/include/linux/swapfile.h deleted file mode 100644 index e282624e8c10..000000000000 --- a/trunk/include/linux/swapfile.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _LINUX_SWAPFILE_H -#define _LINUX_SWAPFILE_H - -/* - * these were static in swapfile.c but frontswap.c needs them and we don't - * want to expose them to the dozens of source files that include swap.h - */ -extern spinlock_t swap_lock; -extern struct swap_list_t swap_list; -extern struct swap_info_struct *swap_info[]; -extern int try_to_unuse(unsigned int, bool, unsigned long); - -#endif /* _LINUX_SWAPFILE_H */ diff --git a/trunk/include/linux/tcp.h b/trunk/include/linux/tcp.h index 7d3bcedc062a..23e8234f75a5 100644 --- a/trunk/include/linux/tcp.h +++ b/trunk/include/linux/tcp.h @@ -69,16 +69,16 @@ union tcp_word_hdr { #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) enum { - TCP_FLAG_CWR = __constant_cpu_to_be32(0x00800000), - TCP_FLAG_ECE = __constant_cpu_to_be32(0x00400000), - TCP_FLAG_URG = __constant_cpu_to_be32(0x00200000), - TCP_FLAG_ACK = __constant_cpu_to_be32(0x00100000), - TCP_FLAG_PSH = __constant_cpu_to_be32(0x00080000), - TCP_FLAG_RST = __constant_cpu_to_be32(0x00040000), - TCP_FLAG_SYN = __constant_cpu_to_be32(0x00020000), - TCP_FLAG_FIN = __constant_cpu_to_be32(0x00010000), - TCP_RESERVED_BITS = __constant_cpu_to_be32(0x0F000000), - TCP_DATA_OFFSET = __constant_cpu_to_be32(0xF0000000) + TCP_FLAG_CWR = __cpu_to_be32(0x00800000), + TCP_FLAG_ECE = __cpu_to_be32(0x00400000), + TCP_FLAG_URG = __cpu_to_be32(0x00200000), + TCP_FLAG_ACK = __cpu_to_be32(0x00100000), + TCP_FLAG_PSH = __cpu_to_be32(0x00080000), + TCP_FLAG_RST = __cpu_to_be32(0x00040000), + TCP_FLAG_SYN = __cpu_to_be32(0x00020000), + TCP_FLAG_FIN = __cpu_to_be32(0x00010000), + TCP_RESERVED_BITS = __cpu_to_be32(0x0F000000), + TCP_DATA_OFFSET = __cpu_to_be32(0xF0000000) }; /* diff --git a/trunk/include/linux/usb/usbnet.h b/trunk/include/linux/usb/usbnet.h index f87cf622317f..76f439647c4b 100644 --- a/trunk/include/linux/usb/usbnet.h +++ b/trunk/include/linux/usb/usbnet.h @@ -66,8 +66,9 @@ struct usbnet { # define EVENT_STS_SPLIT 3 # define EVENT_LINK_RESET 4 # define EVENT_RX_PAUSED 5 -# define EVENT_DEV_ASLEEP 6 -# define EVENT_DEV_OPEN 7 +# define EVENT_DEV_WAKING 6 +# define EVENT_DEV_ASLEEP 7 +# define EVENT_DEV_OPEN 8 }; static inline struct usb_driver *driver_of(struct usb_interface *intf) diff --git a/trunk/include/linux/vga_switcheroo.h b/trunk/include/linux/vga_switcheroo.h index 60da41fe9dc2..b455c7c212eb 100644 --- a/trunk/include/linux/vga_switcheroo.h +++ b/trunk/include/linux/vga_switcheroo.h @@ -12,9 +12,6 @@ enum vga_switcheroo_state { VGA_SWITCHEROO_OFF, VGA_SWITCHEROO_ON, - /* below are referred only from vga_switcheroo_get_client_state() */ - VGA_SWITCHEROO_INIT, - VGA_SWITCHEROO_NOT_FOUND, }; enum vga_switcheroo_client_id { @@ -53,8 +50,6 @@ void vga_switcheroo_unregister_handler(void); int vga_switcheroo_process_delayed_switch(void); -int vga_switcheroo_get_client_state(struct pci_dev *dev); - #else static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {} @@ -67,7 +62,5 @@ static inline int vga_switcheroo_register_audio_client(struct pci_dev *pdev, int id, bool active) { return 0; } static inline void vga_switcheroo_unregister_handler(void) {} static inline int vga_switcheroo_process_delayed_switch(void) { return 0; } -static inline int vga_switcheroo_get_client_state(struct pci_dev *dev) { return VGA_SWITCHEROO_ON; } - #endif diff --git a/trunk/include/net/dst.h b/trunk/include/net/dst.h index f0bf3b8d5911..8197eadca819 100644 --- a/trunk/include/net/dst.h +++ b/trunk/include/net/dst.h @@ -48,8 +48,8 @@ struct dst_entry { #else void *__pad1; #endif - int (*input)(struct sk_buff *); - int (*output)(struct sk_buff *); + int (*input)(struct sk_buff*); + int (*output)(struct sk_buff*); int flags; #define DST_HOST 0x0001 @@ -241,7 +241,7 @@ dst_metric_locked(const struct dst_entry *dst, int metric) return dst_metric(dst, RTAX_LOCK) & (1<lastuse = time; } -static inline struct dst_entry *dst_clone(struct dst_entry *dst) +static inline +struct dst_entry * dst_clone(struct dst_entry * dst) { if (dst) atomic_inc(&dst->__refcnt); @@ -370,12 +371,12 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) } extern int dst_discard(struct sk_buff *skb); -extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev, +extern void *dst_alloc(struct dst_ops * ops, struct net_device *dev, int initial_ref, int initial_obsolete, int flags); -extern void __dst_free(struct dst_entry *dst); -extern struct dst_entry *dst_destroy(struct dst_entry *dst); +extern void __dst_free(struct dst_entry * dst); +extern struct dst_entry *dst_destroy(struct dst_entry * dst); -static inline void dst_free(struct dst_entry *dst) +static inline void dst_free(struct dst_entry * dst) { if (dst->obsolete > 1) return; diff --git a/trunk/include/net/ip6_route.h b/trunk/include/net/ip6_route.h index 58cb3fc34879..a2cda240ca95 100644 --- a/trunk/include/net/ip6_route.h +++ b/trunk/include/net/ip6_route.h @@ -140,10 +140,10 @@ extern void rt6_redirect(const struct in6_addr *dest, u8 *lladdr, int on_link); -extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, - int oif, u32 mark); -extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, - __be32 mtu); +extern void rt6_pmtu_discovery(const struct in6_addr *daddr, + const struct in6_addr *saddr, + struct net_device *dev, + u32 pmtu); struct netlink_callback; diff --git a/trunk/include/net/netfilter/nf_conntrack_expect.h b/trunk/include/net/netfilter/nf_conntrack_expect.h index 4619caadd9d1..983f00263243 100644 --- a/trunk/include/net/netfilter/nf_conntrack_expect.h +++ b/trunk/include/net/netfilter/nf_conntrack_expect.h @@ -59,10 +59,12 @@ static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp) return nf_ct_net(exp->master); } +#define NF_CT_EXP_POLICY_NAME_LEN 16 + struct nf_conntrack_expect_policy { unsigned int max_expected; unsigned int timeout; - const char *name; + char name[NF_CT_EXP_POLICY_NAME_LEN]; }; #define NF_CT_EXPECT_CLASS_DEFAULT 0 diff --git a/trunk/include/net/netfilter/nf_conntrack_helper.h b/trunk/include/net/netfilter/nf_conntrack_helper.h index 1d1889409b9e..5f5a4d9d4df5 100644 --- a/trunk/include/net/netfilter/nf_conntrack_helper.h +++ b/trunk/include/net/netfilter/nf_conntrack_helper.h @@ -19,7 +19,7 @@ struct module; struct nf_conntrack_helper { struct hlist_node hnode; /* Internal use. */ - const char *name; /* name of the module */ + char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */ struct module *me; /* pointer to self */ const struct nf_conntrack_expect_policy *expect_policy; diff --git a/trunk/include/net/route.h b/trunk/include/net/route.h index 47eb25ac1f7f..2bfbc9329ea9 100644 --- a/trunk/include/net/route.h +++ b/trunk/include/net/route.h @@ -164,9 +164,9 @@ static inline struct rtable *ip_route_output(struct net *net, __be32 daddr, { struct flowi4 fl4 = { .flowi4_oif = oif, - .flowi4_tos = tos, .daddr = daddr, .saddr = saddr, + .flowi4_tos = tos, }; return ip_route_output_key(net, &fl4); } @@ -215,10 +215,7 @@ static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 s return ip_route_input_common(skb, dst, src, tos, devin, true); } -extern void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, - int oif, u32 mark, u8 protocol, int flow_flags); -extern void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu); -extern void ip_rt_send_redirect(struct sk_buff *skb); +extern void ip_rt_send_redirect(struct sk_buff *skb); extern unsigned int inet_addr_type(struct net *net, __be32 addr); extern unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr); diff --git a/trunk/include/net/sch_generic.h b/trunk/include/net/sch_generic.h index 9d7d54a00e63..55ce96b53b09 100644 --- a/trunk/include/net/sch_generic.h +++ b/trunk/include/net/sch_generic.h @@ -220,16 +220,13 @@ struct tcf_proto { struct qdisc_skb_cb { unsigned int pkt_len; - u16 bond_queue_mapping; - u16 _pad; - unsigned char data[20]; + unsigned char data[24]; }; static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) { struct qdisc_skb_cb *qcb; - - BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz); + BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz); BUILD_BUG_ON(sizeof(qcb->data) < sz); } diff --git a/trunk/init/main.c b/trunk/init/main.c index b5cc0a7c4708..1ca6b32c4828 100644 --- a/trunk/init/main.c +++ b/trunk/init/main.c @@ -508,7 +508,7 @@ asmlinkage void __init start_kernel(void) parse_early_param(); parse_args("Booting kernel", static_command_line, __start___param, __stop___param - __start___param, - -1, -1, &unknown_bootoption); + 0, 0, &unknown_bootoption); jump_label_init(); @@ -755,8 +755,13 @@ static void __init do_initcalls(void) { int level; - for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) + for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) { + pr_info("initlevel:%d=%s, %d registered initcalls\n", + level, initcall_level_names[level], + (int) (initcall_levels[level+1] + - initcall_levels[level])); do_initcall_level(level); + } } /* diff --git a/trunk/ipc/shm.c b/trunk/ipc/shm.c index 41c1285d697a..5e2cbfdab6fc 100644 --- a/trunk/ipc/shm.c +++ b/trunk/ipc/shm.c @@ -393,16 +393,6 @@ static int shm_fsync(struct file *file, loff_t start, loff_t end, int datasync) return sfd->file->f_op->fsync(sfd->file, start, end, datasync); } -static long shm_fallocate(struct file *file, int mode, loff_t offset, - loff_t len) -{ - struct shm_file_data *sfd = shm_file_data(file); - - if (!sfd->file->f_op->fallocate) - return -EOPNOTSUPP; - return sfd->file->f_op->fallocate(file, mode, offset, len); -} - static unsigned long shm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) @@ -420,7 +410,6 @@ static const struct file_operations shm_file_operations = { .get_unmapped_area = shm_get_unmapped_area, #endif .llseek = noop_llseek, - .fallocate = shm_fallocate, }; static const struct file_operations shm_file_operations_huge = { @@ -429,7 +418,6 @@ static const struct file_operations shm_file_operations_huge = { .release = shm_release, .get_unmapped_area = shm_get_unmapped_area, .llseek = noop_llseek, - .fallocate = shm_fallocate, }; int is_file_shm_hugepages(struct file *file) diff --git a/trunk/kernel/cgroup.c b/trunk/kernel/cgroup.c index 72fcd3069a90..0f3527d6184a 100644 --- a/trunk/kernel/cgroup.c +++ b/trunk/kernel/cgroup.c @@ -896,13 +896,10 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode) mutex_unlock(&cgroup_mutex); /* - * We want to drop the active superblock reference from the - * cgroup creation after all the dentry refs are gone - - * kill_sb gets mighty unhappy otherwise. Mark - * dentry->d_fsdata with cgroup_diput() to tell - * cgroup_d_release() to call deactivate_super(). + * Drop the active superblock reference that we took when we + * created the cgroup */ - dentry->d_fsdata = cgroup_diput; + deactivate_super(cgrp->root->sb); /* * if we're getting rid of the cgroup, refcount should ensure @@ -928,13 +925,6 @@ static int cgroup_delete(const struct dentry *d) return 1; } -static void cgroup_d_release(struct dentry *dentry) -{ - /* did cgroup_diput() tell me to deactivate super? */ - if (dentry->d_fsdata == cgroup_diput) - deactivate_super(dentry->d_sb); -} - static void remove_dir(struct dentry *d) { struct dentry *parent = dget(d->d_parent); @@ -1542,7 +1532,6 @@ static int cgroup_get_rootdir(struct super_block *sb) static const struct dentry_operations cgroup_dops = { .d_iput = cgroup_diput, .d_delete = cgroup_delete, - .d_release = cgroup_d_release, }; struct inode *inode = diff --git a/trunk/kernel/events/core.c b/trunk/kernel/events/core.c index f85c0154b333..5b06cbbf6931 100644 --- a/trunk/kernel/events/core.c +++ b/trunk/kernel/events/core.c @@ -3181,6 +3181,7 @@ static void perf_event_for_each(struct perf_event *event, event = event->group_leader; perf_event_for_each_child(event, func); + func(event); list_for_each_entry(sibling, &event->sibling_list, group_entry) perf_event_for_each_child(sibling, func); mutex_unlock(&ctx->mutex); diff --git a/trunk/kernel/irq/chip.c b/trunk/kernel/irq/chip.c index eebd6d5cfb44..fc275e4f629b 100644 --- a/trunk/kernel/irq/chip.c +++ b/trunk/kernel/irq/chip.c @@ -275,10 +275,8 @@ void handle_nested_irq(unsigned int irq) kstat_incr_irqs_this_cpu(irq, desc); action = desc->action; - if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) { - desc->istate |= IRQS_PENDING; + if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) goto out_unlock; - } irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); raw_spin_unlock_irq(&desc->lock); @@ -326,10 +324,8 @@ handle_simple_irq(unsigned int irq, struct irq_desc *desc) desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); kstat_incr_irqs_this_cpu(irq, desc); - if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { - desc->istate |= IRQS_PENDING; + if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) goto out_unlock; - } handle_irq_event(desc); diff --git a/trunk/kernel/irq/internals.h b/trunk/kernel/irq/internals.h index 001fa5bab490..8e5c56b3b7d9 100644 --- a/trunk/kernel/irq/internals.h +++ b/trunk/kernel/irq/internals.h @@ -101,9 +101,6 @@ extern int irq_select_affinity_usr(unsigned int irq, struct cpumask *mask); extern void irq_set_thread_affinity(struct irq_desc *desc); -extern int irq_do_set_affinity(struct irq_data *data, - const struct cpumask *dest, bool force); - /* Inline functions for support of irq chips on slow busses */ static inline void chip_bus_lock(struct irq_desc *desc) { diff --git a/trunk/kernel/irq/manage.c b/trunk/kernel/irq/manage.c index 8c548232ba39..ea0c6c2ae6f7 100644 --- a/trunk/kernel/irq/manage.c +++ b/trunk/kernel/irq/manage.c @@ -142,25 +142,6 @@ static inline void irq_get_pending(struct cpumask *mask, struct irq_desc *desc) { } #endif -int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, - bool force) -{ - struct irq_desc *desc = irq_data_to_desc(data); - struct irq_chip *chip = irq_data_get_irq_chip(data); - int ret; - - ret = chip->irq_set_affinity(data, mask, false); - switch (ret) { - case IRQ_SET_MASK_OK: - cpumask_copy(data->affinity, mask); - case IRQ_SET_MASK_OK_NOCOPY: - irq_set_thread_affinity(desc); - ret = 0; - } - - return ret; -} - int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) { struct irq_chip *chip = irq_data_get_irq_chip(data); @@ -171,7 +152,14 @@ int __irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask) return -EINVAL; if (irq_can_move_pcntxt(data)) { - ret = irq_do_set_affinity(data, mask, false); + ret = chip->irq_set_affinity(data, mask, false); + switch (ret) { + case IRQ_SET_MASK_OK: + cpumask_copy(data->affinity, mask); + case IRQ_SET_MASK_OK_NOCOPY: + irq_set_thread_affinity(desc); + ret = 0; + } } else { irqd_set_move_pending(data); irq_copy_pending(desc, mask); @@ -295,8 +283,9 @@ EXPORT_SYMBOL_GPL(irq_set_affinity_notifier); static int setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask) { + struct irq_chip *chip = irq_desc_get_chip(desc); struct cpumask *set = irq_default_affinity; - int node = desc->irq_data.node; + int ret, node = desc->irq_data.node; /* Excludes PER_CPU and NO_BALANCE interrupts */ if (!irq_can_set_affinity(irq)) @@ -322,7 +311,13 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask) if (cpumask_intersects(mask, nodemask)) cpumask_and(mask, mask, nodemask); } - irq_do_set_affinity(&desc->irq_data, mask, false); + ret = chip->irq_set_affinity(&desc->irq_data, mask, false); + switch (ret) { + case IRQ_SET_MASK_OK: + cpumask_copy(desc->irq_data.affinity, mask); + case IRQ_SET_MASK_OK_NOCOPY: + irq_set_thread_affinity(desc); + } return 0; } #else diff --git a/trunk/kernel/irq/migration.c b/trunk/kernel/irq/migration.c index ca3f4aaff707..c3c89751b327 100644 --- a/trunk/kernel/irq/migration.c +++ b/trunk/kernel/irq/migration.c @@ -42,8 +42,17 @@ void irq_move_masked_irq(struct irq_data *idata) * For correct operation this depends on the caller * masking the irqs. */ - if (cpumask_any_and(desc->pending_mask, cpu_online_mask) < nr_cpu_ids) - irq_do_set_affinity(&desc->irq_data, desc->pending_mask, false); + if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask) + < nr_cpu_ids)) { + int ret = chip->irq_set_affinity(&desc->irq_data, + desc->pending_mask, false); + switch (ret) { + case IRQ_SET_MASK_OK: + cpumask_copy(desc->irq_data.affinity, desc->pending_mask); + case IRQ_SET_MASK_OK_NOCOPY: + irq_set_thread_affinity(desc); + } + } cpumask_clear(desc->pending_mask); } diff --git a/trunk/kernel/sched/core.c b/trunk/kernel/sched/core.c index d5594a4268d4..39eb6011bc38 100644 --- a/trunk/kernel/sched/core.c +++ b/trunk/kernel/sched/core.c @@ -142,8 +142,9 @@ const_debug unsigned int sysctl_sched_features = #define SCHED_FEAT(name, enabled) \ #name , -static const char * const sched_feat_names[] = { +static __read_mostly char *sched_feat_names[] = { #include "features.h" + NULL }; #undef SCHED_FEAT @@ -2516,32 +2517,25 @@ static void __update_cpu_load(struct rq *this_rq, unsigned long this_load, sched_avg_update(this_rq); } -#ifdef CONFIG_NO_HZ -/* - * There is no sane way to deal with nohz on smp when using jiffies because the - * cpu doing the jiffies update might drift wrt the cpu doing the jiffy reading - * causing off-by-one errors in observed deltas; {0,2} instead of {1,1}. - * - * Therefore we cannot use the delta approach from the regular tick since that - * would seriously skew the load calculation. However we'll make do for those - * updates happening while idle (nohz_idle_balance) or coming out of idle - * (tick_nohz_idle_exit). - * - * This means we might still be one tick off for nohz periods. - */ - /* * Called from nohz_idle_balance() to update the load ratings before doing the * idle balance. */ void update_idle_cpu_load(struct rq *this_rq) { - unsigned long curr_jiffies = ACCESS_ONCE(jiffies); + unsigned long curr_jiffies = jiffies; unsigned long load = this_rq->load.weight; unsigned long pending_updates; /* - * bail if there's load or we're actually up-to-date. + * Bloody broken means of dealing with nohz, but better than nothing.. + * jiffies is updated by one cpu, another cpu can drift wrt the jiffy + * update and see 0 difference the one time and 2 the next, even though + * we ticked at roughtly the same rate. + * + * Hence we only use this from nohz_idle_balance() and skip this + * nonsense when called from the scheduler_tick() since that's + * guaranteed a stable rate. */ if (load || curr_jiffies == this_rq->last_load_update_tick) return; @@ -2552,39 +2546,13 @@ void update_idle_cpu_load(struct rq *this_rq) __update_cpu_load(this_rq, load, pending_updates); } -/* - * Called from tick_nohz_idle_exit() -- try and fix up the ticks we missed. - */ -void update_cpu_load_nohz(void) -{ - struct rq *this_rq = this_rq(); - unsigned long curr_jiffies = ACCESS_ONCE(jiffies); - unsigned long pending_updates; - - if (curr_jiffies == this_rq->last_load_update_tick) - return; - - raw_spin_lock(&this_rq->lock); - pending_updates = curr_jiffies - this_rq->last_load_update_tick; - if (pending_updates) { - this_rq->last_load_update_tick = curr_jiffies; - /* - * We were idle, this means load 0, the current load might be - * !0 due to remote wakeups and the sort. - */ - __update_cpu_load(this_rq, 0, pending_updates); - } - raw_spin_unlock(&this_rq->lock); -} -#endif /* CONFIG_NO_HZ */ - /* * Called from scheduler_tick() */ static void update_cpu_load_active(struct rq *this_rq) { /* - * See the mess around update_idle_cpu_load() / update_cpu_load_nohz(). + * See the mess in update_idle_cpu_load(). */ this_rq->last_load_update_tick = jiffies; __update_cpu_load(this_rq, this_rq->load.weight, 1); @@ -5014,7 +4982,7 @@ void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask) p->sched_class->set_cpus_allowed(p, new_mask); cpumask_copy(&p->cpus_allowed, new_mask); - p->nr_cpus_allowed = cpumask_weight(new_mask); + p->rt.nr_cpus_allowed = cpumask_weight(new_mask); } /* @@ -5556,20 +5524,15 @@ static cpumask_var_t sched_domains_tmpmask; /* sched_domains_mutex */ #ifdef CONFIG_SCHED_DEBUG -static __read_mostly int sched_debug_enabled; +static __read_mostly int sched_domain_debug_enabled; -static int __init sched_debug_setup(char *str) +static int __init sched_domain_debug_setup(char *str) { - sched_debug_enabled = 1; + sched_domain_debug_enabled = 1; return 0; } -early_param("sched_debug", sched_debug_setup); - -static inline bool sched_debug(void) -{ - return sched_debug_enabled; -} +early_param("sched_debug", sched_domain_debug_setup); static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level, struct cpumask *groupmask) @@ -5609,12 +5572,7 @@ static int sched_domain_debug_one(struct sched_domain *sd, int cpu, int level, break; } - /* - * Even though we initialize ->power to something semi-sane, - * we leave power_orig unset. This allows us to detect if - * domain iteration is still funny without causing /0 traps. - */ - if (!group->sgp->power_orig) { + if (!group->sgp->power) { printk(KERN_CONT "\n"); printk(KERN_ERR "ERROR: domain->cpu_power not " "set\n"); @@ -5662,7 +5620,7 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu) { int level = 0; - if (!sched_debug_enabled) + if (!sched_domain_debug_enabled) return; if (!sd) { @@ -5683,10 +5641,6 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu) } #else /* !CONFIG_SCHED_DEBUG */ # define sched_domain_debug(sd, cpu) do { } while (0) -static inline bool sched_debug(void) -{ - return false; -} #endif /* CONFIG_SCHED_DEBUG */ static int sd_degenerate(struct sched_domain *sd) @@ -6008,44 +5962,6 @@ struct sched_domain_topology_level { struct sd_data data; }; -/* - * Build an iteration mask that can exclude certain CPUs from the upwards - * domain traversal. - * - * Asymmetric node setups can result in situations where the domain tree is of - * unequal depth, make sure to skip domains that already cover the entire - * range. - * - * In that case build_sched_domains() will have terminated the iteration early - * and our sibling sd spans will be empty. Domains should always include the - * cpu they're built on, so check that. - * - */ -static void build_group_mask(struct sched_domain *sd, struct sched_group *sg) -{ - const struct cpumask *span = sched_domain_span(sd); - struct sd_data *sdd = sd->private; - struct sched_domain *sibling; - int i; - - for_each_cpu(i, span) { - sibling = *per_cpu_ptr(sdd->sd, i); - if (!cpumask_test_cpu(i, sched_domain_span(sibling))) - continue; - - cpumask_set_cpu(i, sched_group_mask(sg)); - } -} - -/* - * Return the canonical balance cpu for this group, this is the first cpu - * of this group that's also in the iteration mask. - */ -int group_balance_cpu(struct sched_group *sg) -{ - return cpumask_first_and(sched_group_cpus(sg), sched_group_mask(sg)); -} - static int build_overlap_sched_groups(struct sched_domain *sd, int cpu) { @@ -6064,12 +5980,6 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu) if (cpumask_test_cpu(i, covered)) continue; - child = *per_cpu_ptr(sdd->sd, i); - - /* See the comment near build_group_mask(). */ - if (!cpumask_test_cpu(i, sched_domain_span(child))) - continue; - sg = kzalloc_node(sizeof(struct sched_group) + cpumask_size(), GFP_KERNEL, cpu_to_node(cpu)); @@ -6077,6 +5987,8 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu) goto fail; sg_span = sched_group_cpus(sg); + + child = *per_cpu_ptr(sdd->sd, i); if (child->child) { child = child->child; cpumask_copy(sg_span, sched_domain_span(child)); @@ -6085,24 +5997,10 @@ build_overlap_sched_groups(struct sched_domain *sd, int cpu) cpumask_or(covered, covered, sg_span); - sg->sgp = *per_cpu_ptr(sdd->sgp, i); - if (atomic_inc_return(&sg->sgp->ref) == 1) - build_group_mask(sd, sg); + sg->sgp = *per_cpu_ptr(sdd->sgp, cpumask_first(sg_span)); + atomic_inc(&sg->sgp->ref); - /* - * Initialize sgp->power such that even if we mess up the - * domains and no possible iteration will get us here, we won't - * die on a /0 trap. - */ - sg->sgp->power = SCHED_POWER_SCALE * cpumask_weight(sg_span); - - /* - * Make sure the first group of this domain contains the - * canonical balance cpu. Otherwise the sched_domain iteration - * breaks. See update_sg_lb_stats(). - */ - if ((!groups && cpumask_test_cpu(cpu, sg_span)) || - group_balance_cpu(sg) == cpu) + if (cpumask_test_cpu(cpu, sg_span)) groups = sg; if (!first) @@ -6176,7 +6074,6 @@ build_sched_groups(struct sched_domain *sd, int cpu) cpumask_clear(sched_group_cpus(sg)); sg->sgp->power = 0; - cpumask_setall(sched_group_mask(sg)); for_each_cpu(j, span) { if (get_group(j, sdd, NULL) != group) @@ -6218,7 +6115,7 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd) sg = sg->next; } while (sg != sd->groups); - if (cpu != group_balance_cpu(sg)) + if (cpu != group_first_cpu(sg)) return; update_group_power(sd, cpu); @@ -6268,8 +6165,11 @@ int sched_domain_level_max; static int __init setup_relax_domain_level(char *str) { - if (kstrtoint(str, 0, &default_relax_domain_level)) - pr_warn("Unable to set relax_domain_level\n"); + unsigned long val; + + val = simple_strtoul(str, NULL, 0); + if (val < sched_domain_level_max) + default_relax_domain_level = val; return 1; } @@ -6379,13 +6279,14 @@ static struct sched_domain_topology_level *sched_domain_topology = default_topol #ifdef CONFIG_NUMA static int sched_domains_numa_levels; +static int sched_domains_numa_scale; static int *sched_domains_numa_distance; static struct cpumask ***sched_domains_numa_masks; static int sched_domains_curr_level; static inline int sd_local_flags(int level) { - if (sched_domains_numa_distance[level] > RECLAIM_DISTANCE) + if (sched_domains_numa_distance[level] > REMOTE_DISTANCE) return 0; return SD_BALANCE_EXEC | SD_BALANCE_FORK | SD_WAKE_AFFINE; @@ -6443,42 +6344,6 @@ static const struct cpumask *sd_numa_mask(int cpu) return sched_domains_numa_masks[sched_domains_curr_level][cpu_to_node(cpu)]; } -static void sched_numa_warn(const char *str) -{ - static int done = false; - int i,j; - - if (done) - return; - - done = true; - - printk(KERN_WARNING "ERROR: %s\n\n", str); - - for (i = 0; i < nr_node_ids; i++) { - printk(KERN_WARNING " "); - for (j = 0; j < nr_node_ids; j++) - printk(KERN_CONT "%02d ", node_distance(i,j)); - printk(KERN_CONT "\n"); - } - printk(KERN_WARNING "\n"); -} - -static bool find_numa_distance(int distance) -{ - int i; - - if (distance == node_distance(0, 0)) - return true; - - for (i = 0; i < sched_domains_numa_levels; i++) { - if (sched_domains_numa_distance[i] == distance) - return true; - } - - return false; -} - static void sched_init_numa(void) { int next_distance, curr_distance = node_distance(0, 0); @@ -6486,6 +6351,7 @@ static void sched_init_numa(void) int level = 0; int i, j, k; + sched_domains_numa_scale = curr_distance; sched_domains_numa_distance = kzalloc(sizeof(int) * nr_node_ids, GFP_KERNEL); if (!sched_domains_numa_distance) return; @@ -6496,41 +6362,23 @@ static void sched_init_numa(void) * * Assumes node_distance(0,j) includes all distances in * node_distance(i,j) in order to avoid cubic time. + * + * XXX: could be optimized to O(n log n) by using sort() */ next_distance = curr_distance; for (i = 0; i < nr_node_ids; i++) { for (j = 0; j < nr_node_ids; j++) { - for (k = 0; k < nr_node_ids; k++) { - int distance = node_distance(i, k); - - if (distance > curr_distance && - (distance < next_distance || - next_distance == curr_distance)) - next_distance = distance; - - /* - * While not a strong assumption it would be nice to know - * about cases where if node A is connected to B, B is not - * equally connected to A. - */ - if (sched_debug() && node_distance(k, i) != distance) - sched_numa_warn("Node-distance not symmetric"); - - if (sched_debug() && i && !find_numa_distance(distance)) - sched_numa_warn("Node-0 not representative"); - } - if (next_distance != curr_distance) { - sched_domains_numa_distance[level++] = next_distance; - sched_domains_numa_levels = level; - curr_distance = next_distance; - } else break; + int distance = node_distance(0, j); + if (distance > curr_distance && + (distance < next_distance || + next_distance == curr_distance)) + next_distance = distance; } - - /* - * In case of sched_debug() we verify the above assumption. - */ - if (!sched_debug()) - break; + if (next_distance != curr_distance) { + sched_domains_numa_distance[level++] = next_distance; + sched_domains_numa_levels = level; + curr_distance = next_distance; + } else break; } /* * 'level' contains the number of unique distances, excluding the @@ -6555,7 +6403,7 @@ static void sched_init_numa(void) return; for (j = 0; j < nr_node_ids; j++) { - struct cpumask *mask = kzalloc(cpumask_size(), GFP_KERNEL); + struct cpumask *mask = kzalloc_node(cpumask_size(), GFP_KERNEL, j); if (!mask) return; @@ -6642,7 +6490,7 @@ static int __sdt_alloc(const struct cpumask *cpu_map) *per_cpu_ptr(sdd->sg, j) = sg; - sgp = kzalloc_node(sizeof(struct sched_group_power) + cpumask_size(), + sgp = kzalloc_node(sizeof(struct sched_group_power), GFP_KERNEL, cpu_to_node(j)); if (!sgp) return -ENOMEM; @@ -6695,6 +6543,7 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl, if (!sd) return child; + set_domain_attribute(sd, attr); cpumask_and(sched_domain_span(sd), cpu_map, tl->mask(cpu)); if (child) { sd->level = child->level + 1; @@ -6702,7 +6551,6 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl, child->parent = sd; } sd->child = child; - set_domain_attribute(sd, attr); return sd; } @@ -6843,6 +6691,7 @@ static int init_sched_domains(const struct cpumask *cpu_map) if (!doms_cur) doms_cur = &fallback_doms; cpumask_andnot(doms_cur[0], cpu_map, cpu_isolated_map); + dattr_cur = NULL; err = build_sched_domains(doms_cur[0], NULL); register_sched_domain_sysctl(); diff --git a/trunk/kernel/sched/fair.c b/trunk/kernel/sched/fair.c index c099cc6eebe3..940e6d17cf96 100644 --- a/trunk/kernel/sched/fair.c +++ b/trunk/kernel/sched/fair.c @@ -2703,7 +2703,7 @@ select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags) int want_sd = 1; int sync = wake_flags & WF_SYNC; - if (p->nr_cpus_allowed == 1) + if (p->rt.nr_cpus_allowed == 1) return prev_cpu; if (sd_flag & SD_BALANCE_WAKE) { @@ -3503,22 +3503,15 @@ unsigned long __weak arch_scale_smt_power(struct sched_domain *sd, int cpu) unsigned long scale_rt_power(int cpu) { struct rq *rq = cpu_rq(cpu); - u64 total, available, age_stamp, avg; + u64 total, available; - /* - * Since we're reading these variables without serialization make sure - * we read them once before doing sanity checks on them. - */ - age_stamp = ACCESS_ONCE(rq->age_stamp); - avg = ACCESS_ONCE(rq->rt_avg); - - total = sched_avg_period() + (rq->clock - age_stamp); + total = sched_avg_period() + (rq->clock - rq->age_stamp); - if (unlikely(total < avg)) { + if (unlikely(total < rq->rt_avg)) { /* Ensures that power won't end up being negative */ available = 0; } else { - available = total - avg; + available = total - rq->rt_avg; } if (unlikely((s64)total < SCHED_POWER_SCALE)) @@ -3581,28 +3574,13 @@ void update_group_power(struct sched_domain *sd, int cpu) power = 0; - if (child->flags & SD_OVERLAP) { - /* - * SD_OVERLAP domains cannot assume that child groups - * span the current group. - */ - - for_each_cpu(cpu, sched_group_cpus(sdg)) - power += power_of(cpu); - } else { - /* - * !SD_OVERLAP domains can assume that child groups - * span the current group. - */ - - group = child->groups; - do { - power += group->sgp->power; - group = group->next; - } while (group != child->groups); - } + group = child->groups; + do { + power += group->sgp->power; + group = group->next; + } while (group != child->groups); - sdg->sgp->power_orig = sdg->sgp->power = power; + sdg->sgp->power = power; } /* @@ -3632,7 +3610,7 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group) /** * update_sg_lb_stats - Update sched_group's statistics for load balancing. - * @env: The load balancing environment. + * @sd: The sched_domain whose statistics are to be updated. * @group: sched_group whose statistics are to be updated. * @load_idx: Load index of sched_domain of this_cpu for load calc. * @local_group: Does group contain this_cpu. @@ -3652,7 +3630,7 @@ static inline void update_sg_lb_stats(struct lb_env *env, int i; if (local_group) - balance_cpu = group_balance_cpu(group); + balance_cpu = group_first_cpu(group); /* Tally up the load of all CPUs in the group */ max_cpu_load = 0; @@ -3667,8 +3645,7 @@ static inline void update_sg_lb_stats(struct lb_env *env, /* Bias balancing toward cpus of our domain */ if (local_group) { - if (idle_cpu(i) && !first_idle_cpu && - cpumask_test_cpu(i, sched_group_mask(group))) { + if (idle_cpu(i) && !first_idle_cpu) { first_idle_cpu = 1; balance_cpu = i; } @@ -3742,10 +3719,11 @@ static inline void update_sg_lb_stats(struct lb_env *env, /** * update_sd_pick_busiest - return 1 on busiest group - * @env: The load balancing environment. + * @sd: sched_domain whose statistics are to be checked * @sds: sched_domain statistics * @sg: sched_group candidate to be checked for being the busiest * @sgs: sched_group statistics + * @this_cpu: the current cpu * * Determine if @sg is a busier group than the previously selected * busiest group. @@ -3783,7 +3761,9 @@ static bool update_sd_pick_busiest(struct lb_env *env, /** * update_sd_lb_stats - Update sched_domain's statistics for load balancing. - * @env: The load balancing environment. + * @sd: sched_domain whose statistics are to be updated. + * @this_cpu: Cpu for which load balance is currently performed. + * @idle: Idle status of this_cpu * @cpus: Set of cpus considered for load balancing. * @balance: Should we balance. * @sds: variable to hold the statistics for this sched_domain. @@ -3872,8 +3852,10 @@ static inline void update_sd_lb_stats(struct lb_env *env, * Returns 1 when packing is required and a task should be moved to * this CPU. The amount of the imbalance is returned in *imbalance. * - * @env: The load balancing environment. + * @sd: The sched_domain whose packing is to be checked. * @sds: Statistics of the sched_domain which is to be packed + * @this_cpu: The cpu at whose sched_domain we're performing load-balance. + * @imbalance: returns amount of imbalanced due to packing. */ static int check_asym_packing(struct lb_env *env, struct sd_lb_stats *sds) { @@ -3899,8 +3881,9 @@ static int check_asym_packing(struct lb_env *env, struct sd_lb_stats *sds) * fix_small_imbalance - Calculate the minor imbalance that exists * amongst the groups of a sched_domain, during * load balancing. - * @env: The load balancing environment. * @sds: Statistics of the sched_domain whose imbalance is to be calculated. + * @this_cpu: The cpu at whose sched_domain we're performing load-balance. + * @imbalance: Variable to store the imbalance. */ static inline void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds) @@ -4043,7 +4026,11 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s * Also calculates the amount of weighted load which should be moved * to restore balance. * - * @env: The load balancing environment. + * @sd: The sched_domain whose busiest group is to be returned. + * @this_cpu: The cpu for which load balancing is currently being performed. + * @imbalance: Variable which stores amount of weighted load which should + * be moved to restore balance/put a group to idle. + * @idle: The idle status of this_cpu. * @cpus: The set of CPUs under consideration for load-balancing. * @balance: Pointer to a variable indicating if this_cpu * is the appropriate cpu to perform load balancing at this_level. diff --git a/trunk/kernel/sched/rt.c b/trunk/kernel/sched/rt.c index 573e1ca01102..c5565c3c515f 100644 --- a/trunk/kernel/sched/rt.c +++ b/trunk/kernel/sched/rt.c @@ -274,16 +274,13 @@ static void update_rt_migration(struct rt_rq *rt_rq) static void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) { - struct task_struct *p; - if (!rt_entity_is_task(rt_se)) return; - p = rt_task_of(rt_se); rt_rq = &rq_of_rt_rq(rt_rq)->rt; rt_rq->rt_nr_total++; - if (p->nr_cpus_allowed > 1) + if (rt_se->nr_cpus_allowed > 1) rt_rq->rt_nr_migratory++; update_rt_migration(rt_rq); @@ -291,16 +288,13 @@ static void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) static void dec_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq) { - struct task_struct *p; - if (!rt_entity_is_task(rt_se)) return; - p = rt_task_of(rt_se); rt_rq = &rq_of_rt_rq(rt_rq)->rt; rt_rq->rt_nr_total--; - if (p->nr_cpus_allowed > 1) + if (rt_se->nr_cpus_allowed > 1) rt_rq->rt_nr_migratory--; update_rt_migration(rt_rq); @@ -1167,7 +1161,7 @@ enqueue_task_rt(struct rq *rq, struct task_struct *p, int flags) enqueue_rt_entity(rt_se, flags & ENQUEUE_HEAD); - if (!task_current(rq, p) && p->nr_cpus_allowed > 1) + if (!task_current(rq, p) && p->rt.nr_cpus_allowed > 1) enqueue_pushable_task(rq, p); inc_nr_running(rq); @@ -1231,7 +1225,7 @@ select_task_rq_rt(struct task_struct *p, int sd_flag, int flags) cpu = task_cpu(p); - if (p->nr_cpus_allowed == 1) + if (p->rt.nr_cpus_allowed == 1) goto out; /* For anything but wake ups, just return the task_cpu */ @@ -1266,9 +1260,9 @@ select_task_rq_rt(struct task_struct *p, int sd_flag, int flags) * will have to sort it out. */ if (curr && unlikely(rt_task(curr)) && - (curr->nr_cpus_allowed < 2 || + (curr->rt.nr_cpus_allowed < 2 || curr->prio <= p->prio) && - (p->nr_cpus_allowed > 1)) { + (p->rt.nr_cpus_allowed > 1)) { int target = find_lowest_rq(p); if (target != -1) @@ -1282,10 +1276,10 @@ select_task_rq_rt(struct task_struct *p, int sd_flag, int flags) static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p) { - if (rq->curr->nr_cpus_allowed == 1) + if (rq->curr->rt.nr_cpus_allowed == 1) return; - if (p->nr_cpus_allowed != 1 + if (p->rt.nr_cpus_allowed != 1 && cpupri_find(&rq->rd->cpupri, p, NULL)) return; @@ -1401,7 +1395,7 @@ static void put_prev_task_rt(struct rq *rq, struct task_struct *p) * The previous task needs to be made eligible for pushing * if it is still active */ - if (on_rt_rq(&p->rt) && p->nr_cpus_allowed > 1) + if (on_rt_rq(&p->rt) && p->rt.nr_cpus_allowed > 1) enqueue_pushable_task(rq, p); } @@ -1414,7 +1408,7 @@ static int pick_rt_task(struct rq *rq, struct task_struct *p, int cpu) { if (!task_running(rq, p) && (cpu < 0 || cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) && - (p->nr_cpus_allowed > 1)) + (p->rt.nr_cpus_allowed > 1)) return 1; return 0; } @@ -1470,7 +1464,7 @@ static int find_lowest_rq(struct task_struct *task) if (unlikely(!lowest_mask)) return -1; - if (task->nr_cpus_allowed == 1) + if (task->rt.nr_cpus_allowed == 1) return -1; /* No other targets possible */ if (!cpupri_find(&task_rq(task)->rd->cpupri, task, lowest_mask)) @@ -1562,7 +1556,7 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq) task_running(rq, task) || !task->on_rq)) { - double_unlock_balance(rq, lowest_rq); + raw_spin_unlock(&lowest_rq->lock); lowest_rq = NULL; break; } @@ -1592,7 +1586,7 @@ static struct task_struct *pick_next_pushable_task(struct rq *rq) BUG_ON(rq->cpu != task_cpu(p)); BUG_ON(task_current(rq, p)); - BUG_ON(p->nr_cpus_allowed <= 1); + BUG_ON(p->rt.nr_cpus_allowed <= 1); BUG_ON(!p->on_rq); BUG_ON(!rt_task(p)); @@ -1799,9 +1793,9 @@ static void task_woken_rt(struct rq *rq, struct task_struct *p) if (!task_running(rq, p) && !test_tsk_need_resched(rq->curr) && has_pushable_tasks(rq) && - p->nr_cpus_allowed > 1 && + p->rt.nr_cpus_allowed > 1 && rt_task(rq->curr) && - (rq->curr->nr_cpus_allowed < 2 || + (rq->curr->rt.nr_cpus_allowed < 2 || rq->curr->prio <= p->prio)) push_rt_tasks(rq); } @@ -1823,7 +1817,7 @@ static void set_cpus_allowed_rt(struct task_struct *p, * Only update if the process changes its state from whether it * can migrate or not. */ - if ((p->nr_cpus_allowed > 1) == (weight > 1)) + if ((p->rt.nr_cpus_allowed > 1) == (weight > 1)) return; rq = task_rq(p); @@ -1985,8 +1979,6 @@ static void watchdog(struct rq *rq, struct task_struct *p) static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued) { - struct sched_rt_entity *rt_se = &p->rt; - update_curr_rt(rq); watchdog(rq, p); @@ -2004,15 +1996,12 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued) p->rt.time_slice = RR_TIMESLICE; /* - * Requeue to the end of queue if we (and all of our ancestors) are the - * only element on the queue + * Requeue to the end of queue if we are not the only element + * on the queue: */ - for_each_sched_rt_entity(rt_se) { - if (rt_se->run_list.prev != rt_se->run_list.next) { - requeue_task_rt(rq, p, 0); - set_tsk_need_resched(p); - return; - } + if (p->rt.run_list.prev != p->rt.run_list.next) { + requeue_task_rt(rq, p, 0); + set_tsk_need_resched(p); } } diff --git a/trunk/kernel/sched/sched.h b/trunk/kernel/sched/sched.h index 6d52cea7f33d..ba9dccfd24ce 100644 --- a/trunk/kernel/sched/sched.h +++ b/trunk/kernel/sched/sched.h @@ -526,8 +526,6 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag) DECLARE_PER_CPU(struct sched_domain *, sd_llc); DECLARE_PER_CPU(int, sd_llc_id); -extern int group_balance_cpu(struct sched_group *sg); - #endif /* CONFIG_SMP */ #include "stats.h" diff --git a/trunk/kernel/smpboot.c b/trunk/kernel/smpboot.c index 98f60c5caa1b..e1a797e028a3 100644 --- a/trunk/kernel/smpboot.c +++ b/trunk/kernel/smpboot.c @@ -31,12 +31,6 @@ void __init idle_thread_set_boot_cpu(void) per_cpu(idle_threads, smp_processor_id()) = current; } -/** - * idle_init - Initialize the idle thread for a cpu - * @cpu: The cpu for which the idle thread should be initialized - * - * Creates the thread if it does not exist. - */ static inline void idle_init(unsigned int cpu) { struct task_struct *tsk = per_cpu(idle_threads, cpu); @@ -51,16 +45,17 @@ static inline void idle_init(unsigned int cpu) } /** - * idle_threads_init - Initialize idle threads for all cpus + * idle_thread_init - Initialize the idle thread for a cpu + * @cpu: The cpu for which the idle thread should be initialized + * + * Creates the thread if it does not exist. */ void __init idle_threads_init(void) { - unsigned int cpu, boot_cpu; - - boot_cpu = smp_processor_id(); + unsigned int cpu; for_each_possible_cpu(cpu) { - if (cpu != boot_cpu) + if (cpu != smp_processor_id()) idle_init(cpu); } } diff --git a/trunk/kernel/sys.c b/trunk/kernel/sys.c index f0ec44dcd415..9ff89cb9657a 100644 --- a/trunk/kernel/sys.c +++ b/trunk/kernel/sys.c @@ -1786,13 +1786,27 @@ SYSCALL_DEFINE1(umask, int, mask) } #ifdef CONFIG_CHECKPOINT_RESTORE +static bool vma_flags_mismatch(struct vm_area_struct *vma, + unsigned long required, + unsigned long banned) +{ + return (vma->vm_flags & required) != required || + (vma->vm_flags & banned); +} + static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) { - struct vm_area_struct *vma; struct file *exe_file; struct dentry *dentry; int err; + /* + * Setting new mm::exe_file is only allowed when no VM_EXECUTABLE vma's + * remain. So perform a quick test first. + */ + if (mm->num_exe_file_vmas) + return -EBUSY; + exe_file = fget(fd); if (!exe_file) return -EBADF; @@ -1813,30 +1827,17 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) if (err) goto exit; - down_write(&mm->mmap_sem); - - /* - * Forbid mm->exe_file change if there are mapped other files. - */ - err = -EBUSY; - for (vma = mm->mmap; vma; vma = vma->vm_next) { - if (vma->vm_file && !path_equal(&vma->vm_file->f_path, - &exe_file->f_path)) - goto exit_unlock; - } - /* * The symlink can be changed only once, just to disallow arbitrary * transitions malicious software might bring in. This means one * could make a snapshot over all processes running and monitor * /proc/pid/exe changes to notice unusual activity if needed. */ - err = -EPERM; - if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags)) - goto exit_unlock; - - set_mm_exe_file(mm, exe_file); -exit_unlock: + down_write(&mm->mmap_sem); + if (likely(!mm->exe_file)) + set_mm_exe_file(mm, exe_file); + else + err = -EBUSY; up_write(&mm->mmap_sem); exit: @@ -1861,7 +1862,7 @@ static int prctl_set_mm(int opt, unsigned long addr, if (opt == PR_SET_MM_EXE_FILE) return prctl_set_mm_exe_file(mm, (unsigned int)addr); - if (addr >= TASK_SIZE || addr < mmap_min_addr) + if (addr >= TASK_SIZE) return -EINVAL; error = -EINVAL; @@ -1923,6 +1924,12 @@ static int prctl_set_mm(int opt, unsigned long addr, error = -EFAULT; goto out; } +#ifdef CONFIG_STACK_GROWSUP + if (vma_flags_mismatch(vma, VM_READ | VM_WRITE | VM_GROWSUP, 0)) +#else + if (vma_flags_mismatch(vma, VM_READ | VM_WRITE | VM_GROWSDOWN, 0)) +#endif + goto out; if (opt == PR_SET_MM_START_STACK) mm->start_stack = addr; else if (opt == PR_SET_MM_ARG_START) @@ -1974,22 +1981,12 @@ static int prctl_set_mm(int opt, unsigned long addr, up_read(&mm->mmap_sem); return error; } - -static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr) -{ - return put_user(me->clear_child_tid, tid_addr); -} - #else /* CONFIG_CHECKPOINT_RESTORE */ static int prctl_set_mm(int opt, unsigned long addr, unsigned long arg4, unsigned long arg5) { return -EINVAL; } -static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr) -{ - return -EINVAL; -} #endif SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, @@ -2127,9 +2124,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, else return -EINVAL; break; - case PR_GET_TID_ADDRESS: - error = prctl_get_tid_address(me, (int __user **)arg2); - break; default: return -EINVAL; } diff --git a/trunk/kernel/time/clockevents.c b/trunk/kernel/time/clockevents.c index 7e1ce012a851..9cd928f7a7c6 100644 --- a/trunk/kernel/time/clockevents.c +++ b/trunk/kernel/time/clockevents.c @@ -297,7 +297,8 @@ void clockevents_register_device(struct clock_event_device *dev) } EXPORT_SYMBOL_GPL(clockevents_register_device); -void clockevents_config(struct clock_event_device *dev, u32 freq) +static void clockevents_config(struct clock_event_device *dev, + u32 freq) { u64 sec; diff --git a/trunk/kernel/time/tick-sched.c b/trunk/kernel/time/tick-sched.c index da70c6db496c..6a3a5b9ff561 100644 --- a/trunk/kernel/time/tick-sched.c +++ b/trunk/kernel/time/tick-sched.c @@ -576,7 +576,6 @@ void tick_nohz_idle_exit(void) /* Update jiffies first */ select_nohz_load_balancer(0); tick_do_update_jiffies64(now); - update_cpu_load_nohz(); #ifndef CONFIG_VIRT_CPU_ACCOUNTING /* @@ -815,16 +814,6 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer) return HRTIMER_RESTART; } -static int sched_skew_tick; - -static int __init skew_tick(char *str) -{ - get_option(&str, &sched_skew_tick); - - return 0; -} -early_param("skew_tick", skew_tick); - /** * tick_setup_sched_timer - setup the tick emulation timer */ @@ -842,14 +831,6 @@ void tick_setup_sched_timer(void) /* Get the next period (per cpu) */ hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update()); - /* Offset the tick to avert xtime_lock contention. */ - if (sched_skew_tick) { - u64 offset = ktime_to_ns(tick_period) >> 1; - do_div(offset, num_possible_cpus()); - offset *= smp_processor_id(); - hrtimer_add_expires_ns(&ts->sched_timer, offset); - } - for (;;) { hrtimer_forward(&ts->sched_timer, now, tick_period); hrtimer_start_expires(&ts->sched_timer, diff --git a/trunk/kernel/time/timekeeping.c b/trunk/kernel/time/timekeeping.c index 6f46a00a1e8a..6e46cacf5969 100644 --- a/trunk/kernel/time/timekeeping.c +++ b/trunk/kernel/time/timekeeping.c @@ -962,7 +962,6 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) timekeeper.xtime.tv_sec++; leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; - timekeeper.wall_to_monotonic.tv_sec -= leap; } /* Accumulate raw time */ @@ -1078,7 +1077,6 @@ static void update_wall_time(void) timekeeper.xtime.tv_sec++; leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; - timekeeper.wall_to_monotonic.tv_sec -= leap; } timekeeping_update(false); diff --git a/trunk/lib/btree.c b/trunk/lib/btree.c index f9a484676cb6..e5ec1e9c1aa5 100644 --- a/trunk/lib/btree.c +++ b/trunk/lib/btree.c @@ -319,8 +319,8 @@ void *btree_get_prev(struct btree_head *head, struct btree_geo *geo, if (head->height == 0) return NULL; - longcpy(key, __key, geo->keylen); retry: + longcpy(key, __key, geo->keylen); dec_key(geo, key); node = head->node; @@ -351,7 +351,7 @@ void *btree_get_prev(struct btree_head *head, struct btree_geo *geo, } miss: if (retry_key) { - longcpy(key, retry_key, geo->keylen); + __key = retry_key; retry_key = NULL; goto retry; } @@ -509,7 +509,6 @@ static int btree_insert_level(struct btree_head *head, struct btree_geo *geo, int btree_insert(struct btree_head *head, struct btree_geo *geo, unsigned long *key, void *val, gfp_t gfp) { - BUG_ON(!val); return btree_insert_level(head, geo, key, val, 1, gfp); } EXPORT_SYMBOL_GPL(btree_insert); diff --git a/trunk/lib/radix-tree.c b/trunk/lib/radix-tree.c index e7964296fd50..d7c878cc006c 100644 --- a/trunk/lib/radix-tree.c +++ b/trunk/lib/radix-tree.c @@ -686,9 +686,6 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, * during iterating; it can be zero only at the beginning. * And we cannot overflow iter->next_index in a single step, * because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG. - * - * This condition also used by radix_tree_next_slot() to stop - * contiguous iterating, and forbid swithing to the next chunk. */ index = iter->next_index; if (!index && iter->index) diff --git a/trunk/lib/raid6/recov.c b/trunk/lib/raid6/recov.c index a95bccb8497d..1805a5cc5daa 100644 --- a/trunk/lib/raid6/recov.c +++ b/trunk/lib/raid6/recov.c @@ -22,8 +22,8 @@ #include /* Recover two failed data blocks. */ -static void raid6_2data_recov_intx1(int disks, size_t bytes, int faila, - int failb, void **ptrs) +void raid6_2data_recov_intx1(int disks, size_t bytes, int faila, int failb, + void **ptrs) { u8 *p, *q, *dp, *dq; u8 px, qx, db; @@ -66,8 +66,7 @@ static void raid6_2data_recov_intx1(int disks, size_t bytes, int faila, } /* Recover failure of one data block plus the P block */ -static void raid6_datap_recov_intx1(int disks, size_t bytes, int faila, - void **ptrs) +void raid6_datap_recov_intx1(int disks, size_t bytes, int faila, void **ptrs) { u8 *p, *q, *dq; const u8 *qmul; /* Q multiplier table */ diff --git a/trunk/lib/raid6/recov_ssse3.c b/trunk/lib/raid6/recov_ssse3.c index ecb710c0b4d9..37ae61930559 100644 --- a/trunk/lib/raid6/recov_ssse3.c +++ b/trunk/lib/raid6/recov_ssse3.c @@ -19,8 +19,8 @@ static int raid6_has_ssse3(void) boot_cpu_has(X86_FEATURE_SSSE3); } -static void raid6_2data_recov_ssse3(int disks, size_t bytes, int faila, - int failb, void **ptrs) +void raid6_2data_recov_ssse3(int disks, size_t bytes, int faila, int failb, + void **ptrs) { u8 *p, *q, *dp, *dq; const u8 *pbmul; /* P multiplier table for B data */ @@ -194,8 +194,7 @@ static void raid6_2data_recov_ssse3(int disks, size_t bytes, int faila, } -static void raid6_datap_recov_ssse3(int disks, size_t bytes, int faila, - void **ptrs) +void raid6_datap_recov_ssse3(int disks, size_t bytes, int faila, void **ptrs) { u8 *p, *q, *dq; const u8 *qmul; /* Q multiplier table */ diff --git a/trunk/mm/Kconfig b/trunk/mm/Kconfig index 82fed4eb2b6f..b2176374b98e 100644 --- a/trunk/mm/Kconfig +++ b/trunk/mm/Kconfig @@ -389,20 +389,3 @@ config CLEANCACHE in a negligible performance hit. If unsure, say Y to enable cleancache - -config FRONTSWAP - bool "Enable frontswap to cache swap pages if tmem is present" - depends on SWAP - default n - help - Frontswap is so named because it can be thought of as the opposite - of a "backing" store for a swap device. The data is stored into - "transcendent memory", memory that is not directly accessible or - addressable by the kernel and is of unknown and possibly - time-varying size. When space in transcendent memory is available, - a significant swap I/O reduction may be achieved. When none is - available, all frontswap calls are reduced to a single pointer- - compare-against-NULL resulting in a negligible performance hit - and swap data is stored as normal on the matching swap device. - - If unsure, say Y to enable frontswap. diff --git a/trunk/mm/Makefile b/trunk/mm/Makefile index 2e2fbbefb99f..a156285ce88d 100644 --- a/trunk/mm/Makefile +++ b/trunk/mm/Makefile @@ -29,7 +29,6 @@ obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o obj-$(CONFIG_BOUNCE) += bounce.o obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o -obj-$(CONFIG_FRONTSWAP) += frontswap.o obj-$(CONFIG_HAS_DMA) += dmapool.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_NUMA) += mempolicy.o diff --git a/trunk/mm/compaction.c b/trunk/mm/compaction.c index 7ea259d82a99..4ac338af5120 100644 --- a/trunk/mm/compaction.c +++ b/trunk/mm/compaction.c @@ -236,7 +236,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, */ while (unlikely(too_many_isolated(zone))) { /* async migration should just abort */ - if (!cc->sync) + if (cc->mode != COMPACT_SYNC) return 0; congestion_wait(BLK_RW_ASYNC, HZ/10); @@ -304,7 +304,8 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, * satisfies the allocation */ pageblock_nr = low_pfn >> pageblock_order; - if (!cc->sync && last_pageblock_nr != pageblock_nr && + if (cc->mode != COMPACT_SYNC && + last_pageblock_nr != pageblock_nr && !migrate_async_suitable(get_pageblock_migratetype(page))) { low_pfn += pageblock_nr_pages; low_pfn = ALIGN(low_pfn, pageblock_nr_pages) - 1; @@ -325,7 +326,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, continue; } - if (!cc->sync) + if (cc->mode != COMPACT_SYNC) mode |= ISOLATE_ASYNC_MIGRATE; lruvec = mem_cgroup_page_lruvec(page, zone); @@ -360,27 +361,90 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc, #endif /* CONFIG_COMPACTION || CONFIG_CMA */ #ifdef CONFIG_COMPACTION +/* + * Returns true if MIGRATE_UNMOVABLE pageblock was successfully + * converted to MIGRATE_MOVABLE type, false otherwise. + */ +static bool rescue_unmovable_pageblock(struct page *page) +{ + unsigned long pfn, start_pfn, end_pfn; + struct page *start_page, *end_page; + + pfn = page_to_pfn(page); + start_pfn = pfn & ~(pageblock_nr_pages - 1); + end_pfn = start_pfn + pageblock_nr_pages; + + start_page = pfn_to_page(start_pfn); + end_page = pfn_to_page(end_pfn); + + /* Do not deal with pageblocks that overlap zones */ + if (page_zone(start_page) != page_zone(end_page)) + return false; + + for (page = start_page, pfn = start_pfn; page < end_page; pfn++, + page++) { + if (!pfn_valid_within(pfn)) + continue; + + if (PageBuddy(page)) { + int order = page_order(page); + + pfn += (1 << order) - 1; + page += (1 << order) - 1; + + continue; + } else if (page_count(page) == 0 || PageLRU(page)) + continue; + + return false; + } + + set_pageblock_migratetype(page, MIGRATE_MOVABLE); + move_freepages_block(page_zone(page), page, MIGRATE_MOVABLE); + return true; +} -/* Returns true if the page is within a block suitable for migration to */ -static bool suitable_migration_target(struct page *page) +enum smt_result { + GOOD_AS_MIGRATION_TARGET, + FAIL_UNMOVABLE_TARGET, + FAIL_BAD_TARGET, +}; + +/* + * Returns GOOD_AS_MIGRATION_TARGET if the page is within a block + * suitable for migration to, FAIL_UNMOVABLE_TARGET if the page + * is within a MIGRATE_UNMOVABLE block, FAIL_BAD_TARGET otherwise. + */ +static enum smt_result suitable_migration_target(struct page *page, + struct compact_control *cc) { int migratetype = get_pageblock_migratetype(page); /* Don't interfere with memory hot-remove or the min_free_kbytes blocks */ if (migratetype == MIGRATE_ISOLATE || migratetype == MIGRATE_RESERVE) - return false; + return FAIL_BAD_TARGET; /* If the page is a large free page, then allow migration */ if (PageBuddy(page) && page_order(page) >= pageblock_order) - return true; + return GOOD_AS_MIGRATION_TARGET; /* If the block is MIGRATE_MOVABLE or MIGRATE_CMA, allow migration */ - if (migrate_async_suitable(migratetype)) - return true; + if (cc->mode != COMPACT_ASYNC_UNMOVABLE && + migrate_async_suitable(migratetype)) + return GOOD_AS_MIGRATION_TARGET; + + if (cc->mode == COMPACT_ASYNC_MOVABLE && + migratetype == MIGRATE_UNMOVABLE) + return FAIL_UNMOVABLE_TARGET; + + if (cc->mode != COMPACT_ASYNC_MOVABLE && + migratetype == MIGRATE_UNMOVABLE && + rescue_unmovable_pageblock(page)) + return GOOD_AS_MIGRATION_TARGET; /* Otherwise skip the block */ - return false; + return FAIL_BAD_TARGET; } /* @@ -413,6 +477,13 @@ static void isolate_freepages(struct zone *zone, zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages; + /* + * isolate_freepages() may be called more than once during + * compact_zone_order() run and we want only the most recent + * count. + */ + cc->nr_pageblocks_skipped = 0; + /* * Isolate free pages until enough are available to migrate the * pages on cc->migratepages. We stop searching if the migrate @@ -421,6 +492,7 @@ static void isolate_freepages(struct zone *zone, for (; pfn > low_pfn && cc->nr_migratepages > nr_freepages; pfn -= pageblock_nr_pages) { unsigned long isolated; + enum smt_result ret; if (!pfn_valid(pfn)) continue; @@ -437,9 +509,12 @@ static void isolate_freepages(struct zone *zone, continue; /* Check the block is suitable for migration */ - if (!suitable_migration_target(page)) + ret = suitable_migration_target(page, cc); + if (ret != GOOD_AS_MIGRATION_TARGET) { + if (ret == FAIL_UNMOVABLE_TARGET) + cc->nr_pageblocks_skipped++; continue; - + } /* * Found a block suitable for isolating free pages from. Now * we disabled interrupts, double check things are ok and @@ -448,12 +523,14 @@ static void isolate_freepages(struct zone *zone, */ isolated = 0; spin_lock_irqsave(&zone->lock, flags); - if (suitable_migration_target(page)) { + ret = suitable_migration_target(page, cc); + if (ret == GOOD_AS_MIGRATION_TARGET) { end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn); isolated = isolate_freepages_block(pfn, end_pfn, freelist, false); nr_freepages += isolated; - } + } else if (ret == FAIL_UNMOVABLE_TARGET) + cc->nr_pageblocks_skipped++; spin_unlock_irqrestore(&zone->lock, flags); /* @@ -685,8 +762,9 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) nr_migrate = cc->nr_migratepages; err = migrate_pages(&cc->migratepages, compaction_alloc, - (unsigned long)cc, false, - cc->sync ? MIGRATE_SYNC_LIGHT : MIGRATE_ASYNC); + (unsigned long)&cc->freepages, false, + (cc->mode == COMPACT_SYNC) ? MIGRATE_SYNC_LIGHT + : MIGRATE_ASYNC); update_nr_listpages(cc); nr_remaining = cc->nr_migratepages; @@ -715,7 +793,8 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) static unsigned long compact_zone_order(struct zone *zone, int order, gfp_t gfp_mask, - bool sync) + enum compact_mode mode, + unsigned long *nr_pageblocks_skipped) { struct compact_control cc = { .nr_freepages = 0, @@ -723,12 +802,17 @@ static unsigned long compact_zone_order(struct zone *zone, .order = order, .migratetype = allocflags_to_migratetype(gfp_mask), .zone = zone, - .sync = sync, + .mode = mode, }; + unsigned long rc; + INIT_LIST_HEAD(&cc.freepages); INIT_LIST_HEAD(&cc.migratepages); - return compact_zone(zone, &cc); + rc = compact_zone(zone, &cc); + *nr_pageblocks_skipped = cc.nr_pageblocks_skipped; + + return rc; } int sysctl_extfrag_threshold = 500; @@ -753,6 +837,8 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist, struct zoneref *z; struct zone *zone; int rc = COMPACT_SKIPPED; + unsigned long nr_pageblocks_skipped; + enum compact_mode mode; /* * Check whether it is worth even starting compaction. The order check is @@ -769,12 +855,22 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist, nodemask) { int status; - status = compact_zone_order(zone, order, gfp_mask, sync); + mode = sync ? COMPACT_SYNC : COMPACT_ASYNC_MOVABLE; +retry: + status = compact_zone_order(zone, order, gfp_mask, mode, + &nr_pageblocks_skipped); rc = max(status, rc); /* If a normal allocation would succeed, stop compacting */ if (zone_watermark_ok(zone, order, low_wmark_pages(zone), 0, 0)) break; + + if (rc == COMPACT_COMPLETE && mode == COMPACT_ASYNC_MOVABLE) { + if (nr_pageblocks_skipped) { + mode = COMPACT_ASYNC_UNMOVABLE; + goto retry; + } + } } return rc; @@ -808,7 +904,7 @@ static int __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc) if (ok && cc->order > zone->compact_order_failed) zone->compact_order_failed = cc->order + 1; /* Currently async compaction is never deferred. */ - else if (!ok && cc->sync) + else if (!ok && cc->mode == COMPACT_SYNC) defer_compaction(zone, cc->order); } @@ -823,7 +919,7 @@ int compact_pgdat(pg_data_t *pgdat, int order) { struct compact_control cc = { .order = order, - .sync = false, + .mode = COMPACT_ASYNC_MOVABLE, }; return __compact_pgdat(pgdat, &cc); @@ -833,7 +929,7 @@ static int compact_node(int nid) { struct compact_control cc = { .order = -1, - .sync = true, + .mode = COMPACT_SYNC, }; return __compact_pgdat(NODE_DATA(nid), &cc); diff --git a/trunk/mm/frontswap.c b/trunk/mm/frontswap.c deleted file mode 100644 index e25025574a02..000000000000 --- a/trunk/mm/frontswap.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Frontswap frontend - * - * This code provides the generic "frontend" layer to call a matching - * "backend" driver implementation of frontswap. See - * Documentation/vm/frontswap.txt for more information. - * - * Copyright (C) 2009-2012 Oracle Corp. All rights reserved. - * Author: Dan Magenheimer - * - * This work is licensed under the terms of the GNU GPL, version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * frontswap_ops is set by frontswap_register_ops to contain the pointers - * to the frontswap "backend" implementation functions. - */ -static struct frontswap_ops frontswap_ops __read_mostly; - -/* - * This global enablement flag reduces overhead on systems where frontswap_ops - * has not been registered, so is preferred to the slower alternative: a - * function call that checks a non-global. - */ -bool frontswap_enabled __read_mostly; -EXPORT_SYMBOL(frontswap_enabled); - -/* - * If enabled, frontswap_store will return failure even on success. As - * a result, the swap subsystem will always write the page to swap, in - * effect converting frontswap into a writethrough cache. In this mode, - * there is no direct reduction in swap writes, but a frontswap backend - * can unilaterally "reclaim" any pages in use with no data loss, thus - * providing increases control over maximum memory usage due to frontswap. - */ -static bool frontswap_writethrough_enabled __read_mostly; - -#ifdef CONFIG_DEBUG_FS -/* - * Counters available via /sys/kernel/debug/frontswap (if debugfs is - * properly configured). These are for information only so are not protected - * against increment races. - */ -static u64 frontswap_loads; -static u64 frontswap_succ_stores; -static u64 frontswap_failed_stores; -static u64 frontswap_invalidates; - -static inline void inc_frontswap_loads(void) { - frontswap_loads++; -} -static inline void inc_frontswap_succ_stores(void) { - frontswap_succ_stores++; -} -static inline void inc_frontswap_failed_stores(void) { - frontswap_failed_stores++; -} -static inline void inc_frontswap_invalidates(void) { - frontswap_invalidates++; -} -#else -static inline void inc_frontswap_loads(void) { } -static inline void inc_frontswap_succ_stores(void) { } -static inline void inc_frontswap_failed_stores(void) { } -static inline void inc_frontswap_invalidates(void) { } -#endif -/* - * Register operations for frontswap, returning previous thus allowing - * detection of multiple backends and possible nesting. - */ -struct frontswap_ops frontswap_register_ops(struct frontswap_ops *ops) -{ - struct frontswap_ops old = frontswap_ops; - - frontswap_ops = *ops; - frontswap_enabled = true; - return old; -} -EXPORT_SYMBOL(frontswap_register_ops); - -/* - * Enable/disable frontswap writethrough (see above). - */ -void frontswap_writethrough(bool enable) -{ - frontswap_writethrough_enabled = enable; -} -EXPORT_SYMBOL(frontswap_writethrough); - -/* - * Called when a swap device is swapon'd. - */ -void __frontswap_init(unsigned type) -{ - struct swap_info_struct *sis = swap_info[type]; - - BUG_ON(sis == NULL); - if (sis->frontswap_map == NULL) - return; - if (frontswap_enabled) - (*frontswap_ops.init)(type); -} -EXPORT_SYMBOL(__frontswap_init); - -/* - * "Store" data from a page to frontswap and associate it with the page's - * swaptype and offset. Page must be locked and in the swap cache. - * If frontswap already contains a page with matching swaptype and - * offset, the frontswap implmentation may either overwrite the data and - * return success or invalidate the page from frontswap and return failure. - */ -int __frontswap_store(struct page *page) -{ - int ret = -1, dup = 0; - swp_entry_t entry = { .val = page_private(page), }; - int type = swp_type(entry); - struct swap_info_struct *sis = swap_info[type]; - pgoff_t offset = swp_offset(entry); - - BUG_ON(!PageLocked(page)); - BUG_ON(sis == NULL); - if (frontswap_test(sis, offset)) - dup = 1; - ret = (*frontswap_ops.store)(type, offset, page); - if (ret == 0) { - frontswap_set(sis, offset); - inc_frontswap_succ_stores(); - if (!dup) - atomic_inc(&sis->frontswap_pages); - } else if (dup) { - /* - failed dup always results in automatic invalidate of - the (older) page from frontswap - */ - frontswap_clear(sis, offset); - atomic_dec(&sis->frontswap_pages); - inc_frontswap_failed_stores(); - } else - inc_frontswap_failed_stores(); - if (frontswap_writethrough_enabled) - /* report failure so swap also writes to swap device */ - ret = -1; - return ret; -} -EXPORT_SYMBOL(__frontswap_store); - -/* - * "Get" data from frontswap associated with swaptype and offset that were - * specified when the data was put to frontswap and use it to fill the - * specified page with data. Page must be locked and in the swap cache. - */ -int __frontswap_load(struct page *page) -{ - int ret = -1; - swp_entry_t entry = { .val = page_private(page), }; - int type = swp_type(entry); - struct swap_info_struct *sis = swap_info[type]; - pgoff_t offset = swp_offset(entry); - - BUG_ON(!PageLocked(page)); - BUG_ON(sis == NULL); - if (frontswap_test(sis, offset)) - ret = (*frontswap_ops.load)(type, offset, page); - if (ret == 0) - inc_frontswap_loads(); - return ret; -} -EXPORT_SYMBOL(__frontswap_load); - -/* - * Invalidate any data from frontswap associated with the specified swaptype - * and offset so that a subsequent "get" will fail. - */ -void __frontswap_invalidate_page(unsigned type, pgoff_t offset) -{ - struct swap_info_struct *sis = swap_info[type]; - - BUG_ON(sis == NULL); - if (frontswap_test(sis, offset)) { - (*frontswap_ops.invalidate_page)(type, offset); - atomic_dec(&sis->frontswap_pages); - frontswap_clear(sis, offset); - inc_frontswap_invalidates(); - } -} -EXPORT_SYMBOL(__frontswap_invalidate_page); - -/* - * Invalidate all data from frontswap associated with all offsets for the - * specified swaptype. - */ -void __frontswap_invalidate_area(unsigned type) -{ - struct swap_info_struct *sis = swap_info[type]; - - BUG_ON(sis == NULL); - if (sis->frontswap_map == NULL) - return; - (*frontswap_ops.invalidate_area)(type); - atomic_set(&sis->frontswap_pages, 0); - memset(sis->frontswap_map, 0, sis->max / sizeof(long)); -} -EXPORT_SYMBOL(__frontswap_invalidate_area); - -/* - * Frontswap, like a true swap device, may unnecessarily retain pages - * under certain circumstances; "shrink" frontswap is essentially a - * "partial swapoff" and works by calling try_to_unuse to attempt to - * unuse enough frontswap pages to attempt to -- subject to memory - * constraints -- reduce the number of pages in frontswap to the - * number given in the parameter target_pages. - */ -void frontswap_shrink(unsigned long target_pages) -{ - struct swap_info_struct *si = NULL; - int si_frontswap_pages; - unsigned long total_pages = 0, total_pages_to_unuse; - unsigned long pages = 0, pages_to_unuse = 0; - int type; - bool locked = false; - - /* - * we don't want to hold swap_lock while doing a very - * lengthy try_to_unuse, but swap_list may change - * so restart scan from swap_list.head each time - */ - spin_lock(&swap_lock); - locked = true; - total_pages = 0; - for (type = swap_list.head; type >= 0; type = si->next) { - si = swap_info[type]; - total_pages += atomic_read(&si->frontswap_pages); - } - if (total_pages <= target_pages) - goto out; - total_pages_to_unuse = total_pages - target_pages; - for (type = swap_list.head; type >= 0; type = si->next) { - si = swap_info[type]; - si_frontswap_pages = atomic_read(&si->frontswap_pages); - if (total_pages_to_unuse < si_frontswap_pages) - pages = pages_to_unuse = total_pages_to_unuse; - else { - pages = si_frontswap_pages; - pages_to_unuse = 0; /* unuse all */ - } - /* ensure there is enough RAM to fetch pages from frontswap */ - if (security_vm_enough_memory_mm(current->mm, pages)) - continue; - vm_unacct_memory(pages); - break; - } - if (type < 0) - goto out; - locked = false; - spin_unlock(&swap_lock); - try_to_unuse(type, true, pages_to_unuse); -out: - if (locked) - spin_unlock(&swap_lock); - return; -} -EXPORT_SYMBOL(frontswap_shrink); - -/* - * Count and return the number of frontswap pages across all - * swap devices. This is exported so that backend drivers can - * determine current usage without reading debugfs. - */ -unsigned long frontswap_curr_pages(void) -{ - int type; - unsigned long totalpages = 0; - struct swap_info_struct *si = NULL; - - spin_lock(&swap_lock); - for (type = swap_list.head; type >= 0; type = si->next) { - si = swap_info[type]; - totalpages += atomic_read(&si->frontswap_pages); - } - spin_unlock(&swap_lock); - return totalpages; -} -EXPORT_SYMBOL(frontswap_curr_pages); - -static int __init init_frontswap(void) -{ -#ifdef CONFIG_DEBUG_FS - struct dentry *root = debugfs_create_dir("frontswap", NULL); - if (root == NULL) - return -ENXIO; - debugfs_create_u64("loads", S_IRUGO, root, &frontswap_loads); - debugfs_create_u64("succ_stores", S_IRUGO, root, &frontswap_succ_stores); - debugfs_create_u64("failed_stores", S_IRUGO, root, - &frontswap_failed_stores); - debugfs_create_u64("invalidates", S_IRUGO, - root, &frontswap_invalidates); -#endif - return 0; -} - -module_init(init_frontswap); diff --git a/trunk/mm/internal.h b/trunk/mm/internal.h index 2ba87fbfb75b..5cbb78190041 100644 --- a/trunk/mm/internal.h +++ b/trunk/mm/internal.h @@ -94,6 +94,9 @@ extern void putback_lru_page(struct page *page); /* * in mm/page_alloc.c */ +extern void set_pageblock_migratetype(struct page *page, int migratetype); +extern int move_freepages_block(struct zone *zone, struct page *page, + int migratetype); extern void __free_pages_bootmem(struct page *page, unsigned int order); extern void prep_compound_page(struct page *page, unsigned long order); #ifdef CONFIG_MEMORY_FAILURE @@ -101,6 +104,7 @@ extern bool is_free_buddy_page(struct page *page); #endif #if defined CONFIG_COMPACTION || defined CONFIG_CMA +#include /* * in mm/compaction.c @@ -119,11 +123,14 @@ struct compact_control { unsigned long nr_migratepages; /* Number of pages to migrate */ unsigned long free_pfn; /* isolate_freepages search base */ unsigned long migrate_pfn; /* isolate_migratepages search base */ - bool sync; /* Synchronous migration */ + enum compact_mode mode; /* Compaction mode */ int order; /* order a direct compactor needs */ int migratetype; /* MOVABLE, RECLAIMABLE etc */ struct zone *zone; + + /* Number of UNMOVABLE destination pageblocks skipped during scan */ + unsigned long nr_pageblocks_skipped; }; unsigned long diff --git a/trunk/mm/migrate.c b/trunk/mm/migrate.c index be26d5cbe56b..ab81d482ae6f 100644 --- a/trunk/mm/migrate.c +++ b/trunk/mm/migrate.c @@ -436,10 +436,7 @@ void migrate_page_copy(struct page *newpage, struct page *page) * is actually a signal that all of the page has become dirty. * Whereas only part of our page may be dirty. */ - if (PageSwapBacked(page)) - SetPageDirty(newpage); - else - __set_page_dirty_nobuffers(newpage); + __set_page_dirty_nobuffers(newpage); } mlock_migrate_page(newpage, page); diff --git a/trunk/mm/nommu.c b/trunk/mm/nommu.c index d4b0c10872de..c4acfbc09972 100644 --- a/trunk/mm/nommu.c +++ b/trunk/mm/nommu.c @@ -1486,7 +1486,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff); + ret = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff); if (file) fput(file); diff --git a/trunk/mm/oom_kill.c b/trunk/mm/oom_kill.c index 416637f0e924..ed0e19677360 100644 --- a/trunk/mm/oom_kill.c +++ b/trunk/mm/oom_kill.c @@ -183,7 +183,7 @@ static bool oom_unkillable_task(struct task_struct *p, unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg, const nodemask_t *nodemask, unsigned long totalpages) { - long points; + unsigned long points; if (oom_unkillable_task(p, memcg, nodemask)) return 0; @@ -223,7 +223,7 @@ unsigned long oom_badness(struct task_struct *p, struct mem_cgroup *memcg, * Never return 0 for an eligible task regardless of the root bonus and * oom_score_adj (oom_score_adj can't be OOM_SCORE_ADJ_MIN here). */ - return points > 0 ? points : 1; + return points ? points : 1; } /* diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index 44030096da63..6092f331b32e 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -219,7 +219,7 @@ EXPORT_SYMBOL(nr_online_nodes); int page_group_by_mobility_disabled __read_mostly; -static void set_pageblock_migratetype(struct page *page, int migratetype) +void set_pageblock_migratetype(struct page *page, int migratetype) { if (unlikely(page_group_by_mobility_disabled)) @@ -954,8 +954,8 @@ static int move_freepages(struct zone *zone, return pages_moved; } -static int move_freepages_block(struct zone *zone, struct page *page, - int migratetype) +int move_freepages_block(struct zone *zone, struct page *page, + int migratetype) { unsigned long start_pfn, end_pfn; struct page *start_page, *end_page; @@ -5651,7 +5651,7 @@ static int __alloc_contig_migrate_range(unsigned long start, unsigned long end) .nr_migratepages = 0, .order = -1, .zone = page_zone(pfn_to_page(start)), - .sync = true, + .mode = COMPACT_SYNC, }; INIT_LIST_HEAD(&cc.migratepages); diff --git a/trunk/mm/page_io.c b/trunk/mm/page_io.c index 34f02923744c..dc76b4d0611e 100644 --- a/trunk/mm/page_io.c +++ b/trunk/mm/page_io.c @@ -18,7 +18,6 @@ #include #include #include -#include #include static struct bio *get_swap_bio(gfp_t gfp_flags, @@ -99,12 +98,6 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) unlock_page(page); goto out; } - if (frontswap_store(page) == 0) { - set_page_writeback(page); - unlock_page(page); - end_page_writeback(page); - goto out; - } bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write); if (bio == NULL) { set_page_dirty(page); @@ -129,11 +122,6 @@ int swap_readpage(struct page *page) VM_BUG_ON(!PageLocked(page)); VM_BUG_ON(PageUptodate(page)); - if (frontswap_load(page) == 0) { - SetPageUptodate(page); - unlock_page(page); - goto out; - } bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read); if (bio == NULL) { unlock_page(page); diff --git a/trunk/mm/shmem.c b/trunk/mm/shmem.c index a15a466d0d1d..585bd220a21e 100644 --- a/trunk/mm/shmem.c +++ b/trunk/mm/shmem.c @@ -683,21 +683,10 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, mutex_lock(&shmem_swaplist_mutex); /* * We needed to drop mutex to make that restrictive page - * allocation, but the inode might have been freed while we - * dropped it: although a racing shmem_evict_inode() cannot - * complete without emptying the radix_tree, our page lock - * on this swapcache page is not enough to prevent that - - * free_swap_and_cache() of our swap entry will only - * trylock_page(), removing swap from radix_tree whatever. - * - * We must not proceed to shmem_add_to_page_cache() if the - * inode has been freed, but of course we cannot rely on - * inode or mapping or info to check that. However, we can - * safely check if our swap entry is still in use (and here - * it can't have got reused for another page): if it's still - * in use, then the inode cannot have been freed yet, and we - * can safely proceed (if it's no longer in use, that tells - * nothing about the inode, but we don't need to unuse swap). + * allocation; but the inode might already be freed by now, + * and we cannot refer to inode or mapping or info to check. + * However, we do hold page lock on the PageSwapCache page, + * so can check if that still has our reference remaining. */ if (!page_swapcount(*pagep)) error = -ENOENT; @@ -741,9 +730,9 @@ int shmem_unuse(swp_entry_t swap, struct page *page) /* * There's a faint possibility that swap page was replaced before - * caller locked it: caller will come back later with the right page. + * caller locked it: it will come back later with the right page. */ - if (unlikely(!PageSwapCache(page) || page_private(page) != swap.val)) + if (unlikely(!PageSwapCache(page))) goto out; /* @@ -1006,15 +995,21 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp, newpage = shmem_alloc_page(gfp, info, index); if (!newpage) return -ENOMEM; + VM_BUG_ON(shmem_should_replace_page(newpage, gfp)); + *pagep = newpage; page_cache_get(newpage); copy_highpage(newpage, oldpage); - flush_dcache_page(newpage); + VM_BUG_ON(!PageLocked(oldpage)); __set_page_locked(newpage); + VM_BUG_ON(!PageUptodate(oldpage)); SetPageUptodate(newpage); + VM_BUG_ON(!PageSwapBacked(oldpage)); SetPageSwapBacked(newpage); + VM_BUG_ON(!swap_index); set_page_private(newpage, swap_index); + VM_BUG_ON(!PageSwapCache(oldpage)); SetPageSwapCache(newpage); /* @@ -1024,24 +1019,13 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp, spin_lock_irq(&swap_mapping->tree_lock); error = shmem_radix_tree_replace(swap_mapping, swap_index, oldpage, newpage); - if (!error) { - __inc_zone_page_state(newpage, NR_FILE_PAGES); - __dec_zone_page_state(oldpage, NR_FILE_PAGES); - } + __inc_zone_page_state(newpage, NR_FILE_PAGES); + __dec_zone_page_state(oldpage, NR_FILE_PAGES); spin_unlock_irq(&swap_mapping->tree_lock); + BUG_ON(error); - if (unlikely(error)) { - /* - * Is this possible? I think not, now that our callers check - * both PageSwapCache and page_private after getting page lock; - * but be defensive. Reverse old to newpage for clear and free. - */ - oldpage = newpage; - } else { - mem_cgroup_replace_page_cache(oldpage, newpage); - lru_cache_add_anon(newpage); - *pagep = newpage; - } + mem_cgroup_replace_page_cache(oldpage, newpage); + lru_cache_add_anon(newpage); ClearPageSwapCache(oldpage); set_page_private(oldpage, 0); @@ -1049,7 +1033,7 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp, unlock_page(oldpage); page_cache_release(oldpage); page_cache_release(oldpage); - return error; + return 0; } /* @@ -1123,8 +1107,7 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index, /* We have to do this with page locked to prevent races */ lock_page(page); - if (!PageSwapCache(page) || page_private(page) != swap.val || - page->mapping) { + if (!PageSwapCache(page) || page->mapping) { error = -EEXIST; /* try again */ goto failed; } diff --git a/trunk/mm/swapfile.c b/trunk/mm/swapfile.c index de5bc51c4a66..457b10baef59 100644 --- a/trunk/mm/swapfile.c +++ b/trunk/mm/swapfile.c @@ -31,8 +31,6 @@ #include #include #include -#include -#include #include #include @@ -44,7 +42,7 @@ static bool swap_count_continued(struct swap_info_struct *, pgoff_t, static void free_swap_count_continuations(struct swap_info_struct *); static sector_t map_swap_entry(swp_entry_t, struct block_device**); -DEFINE_SPINLOCK(swap_lock); +static DEFINE_SPINLOCK(swap_lock); static unsigned int nr_swapfiles; long nr_swap_pages; long total_swap_pages; @@ -55,9 +53,9 @@ static const char Unused_file[] = "Unused swap file entry "; static const char Bad_offset[] = "Bad swap offset entry "; static const char Unused_offset[] = "Unused swap offset entry "; -struct swap_list_t swap_list = {-1, -1}; +static struct swap_list_t swap_list = {-1, -1}; -struct swap_info_struct *swap_info[MAX_SWAPFILES]; +static struct swap_info_struct *swap_info[MAX_SWAPFILES]; static DEFINE_MUTEX(swapon_mutex); @@ -558,7 +556,6 @@ static unsigned char swap_entry_free(struct swap_info_struct *p, swap_list.next = p->type; nr_swap_pages++; p->inuse_pages--; - frontswap_invalidate_page(p->type, offset); if ((p->flags & SWP_BLKDEV) && disk->fops->swap_slot_free_notify) disk->fops->swap_slot_free_notify(p->bdev, offset); @@ -988,12 +985,11 @@ static int unuse_mm(struct mm_struct *mm, } /* - * Scan swap_map (or frontswap_map if frontswap parameter is true) - * from current position to next entry still in use. + * Scan swap_map from current position to next entry still in use. * Recycle to start on reaching the end, returning 0 when empty. */ static unsigned int find_next_to_unuse(struct swap_info_struct *si, - unsigned int prev, bool frontswap) + unsigned int prev) { unsigned int max = si->max; unsigned int i = prev; @@ -1019,12 +1015,6 @@ static unsigned int find_next_to_unuse(struct swap_info_struct *si, prev = 0; i = 1; } - if (frontswap) { - if (frontswap_test(si, i)) - break; - else - continue; - } count = si->swap_map[i]; if (count && swap_count(count) != SWAP_MAP_BAD) break; @@ -1036,12 +1026,8 @@ static unsigned int find_next_to_unuse(struct swap_info_struct *si, * We completely avoid races by reading each swap page in advance, * and then search for the process using it. All the necessary * page table adjustments can then be made atomically. - * - * if the boolean frontswap is true, only unuse pages_to_unuse pages; - * pages_to_unuse==0 means all pages; ignored if frontswap is false */ -int try_to_unuse(unsigned int type, bool frontswap, - unsigned long pages_to_unuse) +static int try_to_unuse(unsigned int type) { struct swap_info_struct *si = swap_info[type]; struct mm_struct *start_mm; @@ -1074,7 +1060,7 @@ int try_to_unuse(unsigned int type, bool frontswap, * one pass through swap_map is enough, but not necessarily: * there are races when an instance of an entry might be missed. */ - while ((i = find_next_to_unuse(si, i, frontswap)) != 0) { + while ((i = find_next_to_unuse(si, i)) != 0) { if (signal_pending(current)) { retval = -EINTR; break; @@ -1241,10 +1227,6 @@ int try_to_unuse(unsigned int type, bool frontswap, * interactive performance. */ cond_resched(); - if (frontswap && pages_to_unuse > 0) { - if (!--pages_to_unuse) - break; - } } mmput(start_mm); @@ -1504,8 +1486,7 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) } static void enable_swap_info(struct swap_info_struct *p, int prio, - unsigned char *swap_map, - unsigned long *frontswap_map) + unsigned char *swap_map) { int i, prev; @@ -1515,7 +1496,6 @@ static void enable_swap_info(struct swap_info_struct *p, int prio, else p->prio = --least_priority; p->swap_map = swap_map; - frontswap_map_set(p, frontswap_map); p->flags |= SWP_WRITEOK; nr_swap_pages += p->pages; total_swap_pages += p->pages; @@ -1532,7 +1512,6 @@ static void enable_swap_info(struct swap_info_struct *p, int prio, swap_list.head = swap_list.next = p->type; else swap_info[prev]->next = p->type; - frontswap_init(p->type); spin_unlock(&swap_lock); } @@ -1606,7 +1585,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) spin_unlock(&swap_lock); oom_score_adj = test_set_oom_score_adj(OOM_SCORE_ADJ_MAX); - err = try_to_unuse(type, false, 0); /* force all pages to be unused */ + err = try_to_unuse(type); compare_swap_oom_score_adj(OOM_SCORE_ADJ_MAX, oom_score_adj); if (err) { @@ -1617,7 +1596,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) * sys_swapoff for this swap_info_struct at this point. */ /* re-insert swap space back into swap_list */ - enable_swap_info(p, p->prio, p->swap_map, frontswap_map_get(p)); + enable_swap_info(p, p->prio, p->swap_map); goto out_dput; } @@ -1643,11 +1622,9 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) swap_map = p->swap_map; p->swap_map = NULL; p->flags = 0; - frontswap_invalidate_area(type); spin_unlock(&swap_lock); mutex_unlock(&swapon_mutex); vfree(swap_map); - vfree(frontswap_map_get(p)); /* Destroy swap account informatin */ swap_cgroup_swapoff(type); @@ -2011,7 +1988,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) sector_t span; unsigned long maxpages; unsigned char *swap_map = NULL; - unsigned long *frontswap_map = NULL; struct page *page = NULL; struct inode *inode = NULL; @@ -2095,9 +2071,6 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) error = nr_extents; goto bad_swap; } - /* frontswap enabled? set up bit-per-page map for frontswap */ - if (frontswap_enabled) - frontswap_map = vzalloc(maxpages / sizeof(long)); if (p->bdev) { if (blk_queue_nonrot(bdev_get_queue(p->bdev))) { @@ -2113,15 +2086,14 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) if (swap_flags & SWAP_FLAG_PREFER) prio = (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT; - enable_swap_info(p, prio, swap_map, frontswap_map); + enable_swap_info(p, prio, swap_map); printk(KERN_INFO "Adding %uk swap on %s. " - "Priority:%d extents:%d across:%lluk %s%s%s\n", + "Priority:%d extents:%d across:%lluk %s%s\n", p->pages<<(PAGE_SHIFT-10), name, p->prio, nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10), (p->flags & SWP_SOLIDSTATE) ? "SS" : "", - (p->flags & SWP_DISCARDABLE) ? "D" : "", - (frontswap_map) ? "FS" : ""); + (p->flags & SWP_DISCARDABLE) ? "D" : ""); mutex_unlock(&swapon_mutex); atomic_inc(&proc_poll_event); diff --git a/trunk/net/appletalk/ddp.c b/trunk/net/appletalk/ddp.c index 86852963b7f7..0301b328cf0f 100644 --- a/trunk/net/appletalk/ddp.c +++ b/trunk/net/appletalk/ddp.c @@ -1208,7 +1208,9 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, if (addr->sat_addr.s_node == ATADDR_BCAST && !sock_flag(sk, SOCK_BROADCAST)) { #if 1 - pr_warn("atalk_connect: %s is broken and did not set SO_BROADCAST.\n", + printk(KERN_WARNING "%s is broken and did not set " + "SO_BROADCAST. It will break when 2.2 is " + "released.\n", current->comm); #else return -EACCES; diff --git a/trunk/net/can/raw.c b/trunk/net/can/raw.c index 46cca3a91d19..cde1b4a20f75 100644 --- a/trunk/net/can/raw.c +++ b/trunk/net/can/raw.c @@ -681,6 +681,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, if (err < 0) goto free_skb; + /* to be able to check the received tx sock reference in raw_rcv() */ + skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF; + skb->dev = dev; skb->sk = sk; diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 57c4f9bc6858..cd0981977f5c 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -2089,6 +2089,25 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features) return 0; } +/* + * Try to orphan skb early, right before transmission by the device. + * We cannot orphan skb if tx timestamp is requested or the sk-reference + * is needed on driver level for other reasons, e.g. see net/can/raw.c + */ +static inline void skb_orphan_try(struct sk_buff *skb) +{ + struct sock *sk = skb->sk; + + if (sk && !skb_shinfo(skb)->tx_flags) { + /* skb_tx_hash() wont be able to get sk. + * We copy sk_hash into skb->rxhash + */ + if (!skb->rxhash) + skb->rxhash = sk->sk_hash; + skb_orphan(skb); + } +} + static bool can_checksum_protocol(netdev_features_t features, __be16 protocol) { return ((features & NETIF_F_GEN_CSUM) || @@ -2174,6 +2193,8 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, if (!list_empty(&ptype_all)) dev_queue_xmit_nit(skb, dev); + skb_orphan_try(skb); + features = netif_skb_features(skb); if (vlan_tx_tag_present(skb) && @@ -2283,7 +2304,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb, if (skb->sk && skb->sk->sk_hash) hash = skb->sk->sk_hash; else - hash = (__force u16) skb->protocol; + hash = (__force u16) skb->protocol ^ skb->rxhash; hash = jhash_1word(hash, hashrnd); return (u16) (((u64) hash * qcount) >> 32) + qoffset; @@ -2454,23 +2475,6 @@ static void skb_update_prio(struct sk_buff *skb) static DEFINE_PER_CPU(int, xmit_recursion); #define RECURSION_LIMIT 10 -/** - * dev_loopback_xmit - loop back @skb - * @skb: buffer to transmit - */ -int dev_loopback_xmit(struct sk_buff *skb) -{ - skb_reset_mac_header(skb); - __skb_pull(skb, skb_network_offset(skb)); - skb->pkt_type = PACKET_LOOPBACK; - skb->ip_summed = CHECKSUM_UNNECESSARY; - WARN_ON(!skb_dst(skb)); - skb_dst_force(skb); - netif_rx_ni(skb); - return 0; -} -EXPORT_SYMBOL(dev_loopback_xmit); - /** * dev_queue_xmit - transmit a buffer * @skb: buffer to transmit diff --git a/trunk/net/core/ethtool.c b/trunk/net/core/ethtool.c index cbf033dcaf1f..c73d0a59212c 100644 --- a/trunk/net/core/ethtool.c +++ b/trunk/net/core/ethtool.c @@ -1443,7 +1443,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_GSET: case ETHTOOL_GDRVINFO: case ETHTOOL_GMSGLVL: - case ETHTOOL_GLINK: case ETHTOOL_GCOALESCE: case ETHTOOL_GRINGPARAM: case ETHTOOL_GPAUSEPARAM: @@ -1452,7 +1451,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_GSG: case ETHTOOL_GSSET_INFO: case ETHTOOL_GSTRINGS: - case ETHTOOL_GSTATS: case ETHTOOL_GTSO: case ETHTOOL_GPERMADDR: case ETHTOOL_GUFO: @@ -1465,11 +1463,8 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) case ETHTOOL_GRXCLSRLCNT: case ETHTOOL_GRXCLSRULE: case ETHTOOL_GRXCLSRLALL: - case ETHTOOL_GRXFHINDIR: case ETHTOOL_GFEATURES: - case ETHTOOL_GCHANNELS: case ETHTOOL_GET_TS_INFO: - case ETHTOOL_GEEE: break; default: if (!capable(CAP_NET_ADMIN)) diff --git a/trunk/net/core/filter.c b/trunk/net/core/filter.c index d4ce2dc712e3..a3eddb515d1b 100644 --- a/trunk/net/core/filter.c +++ b/trunk/net/core/filter.c @@ -616,9 +616,9 @@ static int __sk_prepare_filter(struct sk_filter *fp) /** * sk_unattached_filter_create - create an unattached filter * @fprog: the filter program - * @pfp: the unattached filter that is created + * @sk: the socket to use * - * Create a filter independent of any socket. We first run some + * Create a filter independent ofr any socket. We first run some * sanity checks on it to make sure it does not explode on us later. * If an error occurs or there is insufficient memory for the filter * a negative errno code is returned. On success the return is zero. diff --git a/trunk/net/core/neighbour.c b/trunk/net/core/neighbour.c index d81d026138f0..eb09f8bbbf07 100644 --- a/trunk/net/core/neighbour.c +++ b/trunk/net/core/neighbour.c @@ -2219,7 +2219,9 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, rcu_read_lock_bh(); nht = rcu_dereference_bh(tbl->nht); - for (h = s_h; h < (1 << nht->hash_shift); h++) { + for (h = 0; h < (1 << nht->hash_shift); h++) { + if (h < s_h) + continue; if (h > s_h) s_idx = 0; for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0; @@ -2258,7 +2260,9 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, read_lock_bh(&tbl->lock); - for (h = s_h; h <= PNEIGH_HASHMASK; h++) { + for (h = 0; h <= PNEIGH_HASHMASK; h++) { + if (h < s_h) + continue; if (h > s_h) s_idx = 0; for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) { @@ -2293,7 +2297,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) struct neigh_table *tbl; int t, family, s_t; int proxy = 0; - int err; + int err = 0; read_lock(&neigh_tbl_lock); family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; @@ -2307,7 +2311,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) s_t = cb->args[0]; - for (tbl = neigh_tables, t = 0; tbl; + for (tbl = neigh_tables, t = 0; tbl && (err >= 0); tbl = tbl->next, t++) { if (t < s_t || (family && tbl->family != family)) continue; @@ -2318,8 +2322,6 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) err = pneigh_dump_table(tbl, skb, cb); else err = neigh_dump_table(tbl, skb, cb); - if (err < 0) - break; } read_unlock(&neigh_tbl_lock); diff --git a/trunk/net/core/netpoll.c b/trunk/net/core/netpoll.c index f9f40b932e4b..3d84fb9d8873 100644 --- a/trunk/net/core/netpoll.c +++ b/trunk/net/core/netpoll.c @@ -362,23 +362,22 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev); void netpoll_send_udp(struct netpoll *np, const char *msg, int len) { - int total_len, ip_len, udp_len; + int total_len, eth_len, ip_len, udp_len; struct sk_buff *skb; struct udphdr *udph; struct iphdr *iph; struct ethhdr *eth; udp_len = len + sizeof(*udph); - ip_len = udp_len + sizeof(*iph); - total_len = ip_len + LL_RESERVED_SPACE(np->dev); + ip_len = eth_len = udp_len + sizeof(*iph); + total_len = eth_len + ETH_HLEN + NET_IP_ALIGN; - skb = find_skb(np, total_len + np->dev->needed_tailroom, - total_len - len); + skb = find_skb(np, total_len, total_len - len); if (!skb) return; skb_copy_to_linear_data(skb, msg, len); - skb_put(skb, len); + skb->len += len; skb_push(skb, sizeof(*udph)); skb_reset_transport_header(skb); diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 5b21522ed0e1..1d74cea22aaa 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -3361,7 +3361,7 @@ EXPORT_SYMBOL(kfree_skb_partial); * @to: prior buffer * @from: buffer to add * @fragstolen: pointer to boolean - * @delta_truesize: how much more was allocated than was requested + * */ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, bool *fragstolen, int *delta_truesize) diff --git a/trunk/net/dcb/dcbnl.c b/trunk/net/dcb/dcbnl.c index 0a360072cfec..656c7c75b192 100644 --- a/trunk/net/dcb/dcbnl.c +++ b/trunk/net/dcb/dcbnl.c @@ -196,66 +196,92 @@ static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = { static LIST_HEAD(dcb_app_list); static DEFINE_SPINLOCK(dcb_lock); -static struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq, - u32 flags, struct nlmsghdr **nlhp) +/* standard netlink reply call */ +static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, + u32 seq, u16 flags) { - struct sk_buff *skb; + struct sk_buff *dcbnl_skb; struct dcbmsg *dcb; struct nlmsghdr *nlh; + int ret = -EINVAL; - skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); - if (!skb) - return NULL; + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!dcbnl_skb) + return ret; - nlh = nlmsg_put(skb, port, seq, type, sizeof(*dcb), flags); - BUG_ON(!nlh); + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, event, sizeof(*dcb), flags); - dcb = nlmsg_data(nlh); + dcb = NLMSG_DATA(nlh); dcb->dcb_family = AF_UNSPEC; dcb->cmd = cmd; dcb->dcb_pad = 0; - if (nlhp) - *nlhp = nlh; + ret = nla_put_u8(dcbnl_skb, attr, value); + if (ret) + goto err; - return skb; + /* end the message, assign the nlmsg_len. */ + nlmsg_end(dcbnl_skb, nlh); + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); + if (ret) + return -EINVAL; + + return 0; +nlmsg_failure: +err: + kfree_skb(dcbnl_skb); + return ret; } -static int dcbnl_getstate(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_getstate(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + int ret = -EINVAL; + /* if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->getstate) */ if (!netdev->dcbnl_ops->getstate) - return -EOPNOTSUPP; + return ret; - return nla_put_u8(skb, DCB_ATTR_STATE, - netdev->dcbnl_ops->getstate(netdev)); + ret = dcbnl_reply(netdev->dcbnl_ops->getstate(netdev), RTM_GETDCB, + DCB_CMD_GSTATE, DCB_ATTR_STATE, pid, seq, flags); + + return ret; } -static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_getpfccfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + struct sk_buff *dcbnl_skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1], *nest; u8 value; - int ret; + int ret = -EINVAL; int i; int getall = 0; - if (!tb[DCB_ATTR_PFC_CFG]) - return -EINVAL; - - if (!netdev->dcbnl_ops->getpfccfg) - return -EOPNOTSUPP; + if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->getpfccfg) + return ret; ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, tb[DCB_ATTR_PFC_CFG], dcbnl_pfc_up_nest); if (ret) - return ret; + goto err_out; + + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!dcbnl_skb) + goto err_out; - nest = nla_nest_start(skb, DCB_ATTR_PFC_CFG); + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = DCB_CMD_PFC_GCFG; + + nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PFC_CFG); if (!nest) - return -EMSGSIZE; + goto err; if (data[DCB_PFC_UP_ATTR_ALL]) getall = 1; @@ -266,53 +292,103 @@ static int dcbnl_getpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, netdev->dcbnl_ops->getpfccfg(netdev, i - DCB_PFC_UP_ATTR_0, &value); - ret = nla_put_u8(skb, i, value); + ret = nla_put_u8(dcbnl_skb, i, value); + if (ret) { - nla_nest_cancel(skb, nest); - return ret; + nla_nest_cancel(dcbnl_skb, nest); + goto err; } } - nla_nest_end(skb, nest); + nla_nest_end(dcbnl_skb, nest); + + nlmsg_end(dcbnl_skb, nlh); + + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); + if (ret) + goto err_out; return 0; +nlmsg_failure: +err: + kfree_skb(dcbnl_skb); +err_out: + return -EINVAL; } -static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + struct sk_buff *dcbnl_skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; u8 perm_addr[MAX_ADDR_LEN]; + int ret = -EINVAL; if (!netdev->dcbnl_ops->getpermhwaddr) - return -EOPNOTSUPP; + return ret; + + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!dcbnl_skb) + goto err_out; + + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = DCB_CMD_GPERM_HWADDR; netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); - return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr); + ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), + perm_addr); + + nlmsg_end(dcbnl_skb, nlh); + + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); + if (ret) + goto err_out; + + return 0; + +nlmsg_failure: + kfree_skb(dcbnl_skb); +err_out: + return -EINVAL; } -static int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_getcap(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + struct sk_buff *dcbnl_skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; struct nlattr *data[DCB_CAP_ATTR_MAX + 1], *nest; u8 value; - int ret; + int ret = -EINVAL; int i; int getall = 0; - if (!tb[DCB_ATTR_CAP]) - return -EINVAL; - - if (!netdev->dcbnl_ops->getcap) - return -EOPNOTSUPP; + if (!tb[DCB_ATTR_CAP] || !netdev->dcbnl_ops->getcap) + return ret; ret = nla_parse_nested(data, DCB_CAP_ATTR_MAX, tb[DCB_ATTR_CAP], dcbnl_cap_nest); if (ret) - return ret; + goto err_out; - nest = nla_nest_start(skb, DCB_ATTR_CAP); + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!dcbnl_skb) + goto err_out; + + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = DCB_CMD_GCAP; + + nest = nla_nest_start(dcbnl_skb, DCB_ATTR_CAP); if (!nest) - return -EMSGSIZE; + goto err; if (data[DCB_CAP_ATTR_ALL]) getall = 1; @@ -322,41 +398,69 @@ static int dcbnl_getcap(struct net_device *netdev, struct nlmsghdr *nlh, continue; if (!netdev->dcbnl_ops->getcap(netdev, i, &value)) { - ret = nla_put_u8(skb, i, value); + ret = nla_put_u8(dcbnl_skb, i, value); + if (ret) { - nla_nest_cancel(skb, nest); - return ret; + nla_nest_cancel(dcbnl_skb, nest); + goto err; } } } - nla_nest_end(skb, nest); + nla_nest_end(dcbnl_skb, nest); + + nlmsg_end(dcbnl_skb, nlh); + + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); + if (ret) + goto err_out; return 0; +nlmsg_failure: +err: + kfree_skb(dcbnl_skb); +err_out: + return -EINVAL; } -static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_getnumtcs(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + struct sk_buff *dcbnl_skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1], *nest; u8 value; - int ret; + int ret = -EINVAL; int i; int getall = 0; - if (!tb[DCB_ATTR_NUMTCS]) - return -EINVAL; - - if (!netdev->dcbnl_ops->getnumtcs) - return -EOPNOTSUPP; + if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->getnumtcs) + return ret; ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], dcbnl_numtcs_nest); - if (ret) - return ret; + if (ret) { + ret = -EINVAL; + goto err_out; + } - nest = nla_nest_start(skb, DCB_ATTR_NUMTCS); - if (!nest) - return -EMSGSIZE; + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!dcbnl_skb) { + ret = -EINVAL; + goto err_out; + } + + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = DCB_CMD_GNUMTCS; + + nest = nla_nest_start(dcbnl_skb, DCB_ATTR_NUMTCS); + if (!nest) { + ret = -EINVAL; + goto err; + } if (data[DCB_NUMTCS_ATTR_ALL]) getall = 1; @@ -367,37 +471,53 @@ static int dcbnl_getnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, ret = netdev->dcbnl_ops->getnumtcs(netdev, i, &value); if (!ret) { - ret = nla_put_u8(skb, i, value); + ret = nla_put_u8(dcbnl_skb, i, value); + if (ret) { - nla_nest_cancel(skb, nest); - return ret; + nla_nest_cancel(dcbnl_skb, nest); + ret = -EINVAL; + goto err; } - } else - return -EINVAL; + } else { + goto err; + } + } + nla_nest_end(dcbnl_skb, nest); + + nlmsg_end(dcbnl_skb, nlh); + + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); + if (ret) { + ret = -EINVAL; + goto err_out; } - nla_nest_end(skb, nest); return 0; +nlmsg_failure: +err: + kfree_skb(dcbnl_skb); +err_out: + return ret; } -static int dcbnl_setnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_setnumtcs(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { struct nlattr *data[DCB_NUMTCS_ATTR_MAX + 1]; - int ret; + int ret = -EINVAL; u8 value; int i; - if (!tb[DCB_ATTR_NUMTCS]) - return -EINVAL; - - if (!netdev->dcbnl_ops->setnumtcs) - return -EOPNOTSUPP; + if (!tb[DCB_ATTR_NUMTCS] || !netdev->dcbnl_ops->setnumtcs) + return ret; ret = nla_parse_nested(data, DCB_NUMTCS_ATTR_MAX, tb[DCB_ATTR_NUMTCS], dcbnl_numtcs_nest); - if (ret) - return ret; + + if (ret) { + ret = -EINVAL; + goto err; + } for (i = DCB_NUMTCS_ATTR_ALL+1; i <= DCB_NUMTCS_ATTR_MAX; i++) { if (data[i] == NULL) @@ -406,68 +526,84 @@ static int dcbnl_setnumtcs(struct net_device *netdev, struct nlmsghdr *nlh, value = nla_get_u8(data[i]); ret = netdev->dcbnl_ops->setnumtcs(netdev, i, value); + if (ret) - break; + goto operr; } - return nla_put_u8(skb, DCB_ATTR_NUMTCS, !!ret); +operr: + ret = dcbnl_reply(!!ret, RTM_SETDCB, DCB_CMD_SNUMTCS, + DCB_ATTR_NUMTCS, pid, seq, flags); + +err: + return ret; } -static int dcbnl_getpfcstate(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_getpfcstate(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + int ret = -EINVAL; + if (!netdev->dcbnl_ops->getpfcstate) - return -EOPNOTSUPP; + return ret; + + ret = dcbnl_reply(netdev->dcbnl_ops->getpfcstate(netdev), RTM_GETDCB, + DCB_CMD_PFC_GSTATE, DCB_ATTR_PFC_STATE, + pid, seq, flags); - return nla_put_u8(skb, DCB_ATTR_PFC_STATE, - netdev->dcbnl_ops->getpfcstate(netdev)); + return ret; } -static int dcbnl_setpfcstate(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + int ret = -EINVAL; u8 value; - if (!tb[DCB_ATTR_PFC_STATE]) - return -EINVAL; - - if (!netdev->dcbnl_ops->setpfcstate) - return -EOPNOTSUPP; + if (!tb[DCB_ATTR_PFC_STATE] || !netdev->dcbnl_ops->setpfcstate) + return ret; value = nla_get_u8(tb[DCB_ATTR_PFC_STATE]); netdev->dcbnl_ops->setpfcstate(netdev, value); - return nla_put_u8(skb, DCB_ATTR_PFC_STATE, 0); + ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SSTATE, DCB_ATTR_PFC_STATE, + pid, seq, flags); + + return ret; } -static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + struct sk_buff *dcbnl_skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; struct nlattr *app_nest; struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; u16 id; u8 up, idtype; - int ret; + int ret = -EINVAL; if (!tb[DCB_ATTR_APP]) - return -EINVAL; + goto out; ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], dcbnl_app_nest); if (ret) - return ret; + goto out; + ret = -EINVAL; /* all must be non-null */ if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || (!app_tb[DCB_APP_ATTR_ID])) - return -EINVAL; + goto out; /* either by eth type or by socket number */ idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && (idtype != DCB_APP_IDTYPE_PORTNUM)) - return -EINVAL; + goto out; id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); @@ -481,106 +617,138 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh, up = dcb_getapp(netdev, &app); } - app_nest = nla_nest_start(skb, DCB_ATTR_APP); + /* send this back */ + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!dcbnl_skb) + goto out; + + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = DCB_CMD_GAPP; + + app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP); if (!app_nest) - return -EMSGSIZE; + goto out_cancel; - ret = nla_put_u8(skb, DCB_APP_ATTR_IDTYPE, idtype); + ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype); if (ret) goto out_cancel; - ret = nla_put_u16(skb, DCB_APP_ATTR_ID, id); + ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id); if (ret) goto out_cancel; - ret = nla_put_u8(skb, DCB_APP_ATTR_PRIORITY, up); + ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up); if (ret) goto out_cancel; - nla_nest_end(skb, app_nest); + nla_nest_end(dcbnl_skb, app_nest); + nlmsg_end(dcbnl_skb, nlh); - return 0; + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); + if (ret) + goto nlmsg_failure; + + goto out; out_cancel: - nla_nest_cancel(skb, app_nest); + nla_nest_cancel(dcbnl_skb, app_nest); +nlmsg_failure: + kfree_skb(dcbnl_skb); +out: return ret; } -static int dcbnl_setapp(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { - int ret; + int err, ret = -EINVAL; u16 id; u8 up, idtype; struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; if (!tb[DCB_ATTR_APP]) - return -EINVAL; + goto out; ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], dcbnl_app_nest); if (ret) - return ret; + goto out; + ret = -EINVAL; /* all must be non-null */ if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || (!app_tb[DCB_APP_ATTR_ID]) || (!app_tb[DCB_APP_ATTR_PRIORITY])) - return -EINVAL; + goto out; /* either by eth type or by socket number */ idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && (idtype != DCB_APP_IDTYPE_PORTNUM)) - return -EINVAL; + goto out; id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); if (netdev->dcbnl_ops->setapp) { - ret = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); + err = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); } else { struct dcb_app app; app.selector = idtype; app.protocol = id; app.priority = up; - ret = dcb_setapp(netdev, &app); + err = dcb_setapp(netdev, &app); } - ret = nla_put_u8(skb, DCB_ATTR_APP, ret); + ret = dcbnl_reply(err, RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, + pid, seq, flags); dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SAPP, seq, 0); - +out: return ret; } -static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, - struct nlattr **tb, struct sk_buff *skb, int dir) +static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags, int dir) { + struct sk_buff *dcbnl_skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; struct nlattr *pg_nest, *param_nest, *data; struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; u8 prio, pgid, tc_pct, up_map; - int ret; + int ret = -EINVAL; int getall = 0; int i; - if (!tb[DCB_ATTR_PG_CFG]) - return -EINVAL; - - if (!netdev->dcbnl_ops->getpgtccfgtx || + if (!tb[DCB_ATTR_PG_CFG] || + !netdev->dcbnl_ops->getpgtccfgtx || !netdev->dcbnl_ops->getpgtccfgrx || !netdev->dcbnl_ops->getpgbwgcfgtx || !netdev->dcbnl_ops->getpgbwgcfgrx) - return -EOPNOTSUPP; + return ret; ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); + if (ret) - return ret; + goto err_out; + + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!dcbnl_skb) + goto err_out; - pg_nest = nla_nest_start(skb, DCB_ATTR_PG_CFG); + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = (dir) ? DCB_CMD_PGRX_GCFG : DCB_CMD_PGTX_GCFG; + + pg_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_PG_CFG); if (!pg_nest) - return -EMSGSIZE; + goto err; if (pg_tb[DCB_PG_ATTR_TC_ALL]) getall = 1; @@ -598,7 +766,7 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, if (ret) goto err_pg; - param_nest = nla_nest_start(skb, i); + param_nest = nla_nest_start(dcbnl_skb, i); if (!param_nest) goto err_pg; @@ -621,33 +789,33 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, if (param_tb[DCB_TC_ATTR_PARAM_PGID] || param_tb[DCB_TC_ATTR_PARAM_ALL]) { - ret = nla_put_u8(skb, + ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_PGID, pgid); if (ret) goto err_param; } if (param_tb[DCB_TC_ATTR_PARAM_UP_MAPPING] || param_tb[DCB_TC_ATTR_PARAM_ALL]) { - ret = nla_put_u8(skb, + ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map); if (ret) goto err_param; } if (param_tb[DCB_TC_ATTR_PARAM_STRICT_PRIO] || param_tb[DCB_TC_ATTR_PARAM_ALL]) { - ret = nla_put_u8(skb, + ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio); if (ret) goto err_param; } if (param_tb[DCB_TC_ATTR_PARAM_BW_PCT] || param_tb[DCB_TC_ATTR_PARAM_ALL]) { - ret = nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, + ret = nla_put_u8(dcbnl_skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct); if (ret) goto err_param; } - nla_nest_end(skb, param_nest); + nla_nest_end(dcbnl_skb, param_nest); } if (pg_tb[DCB_PG_ATTR_BW_ID_ALL]) @@ -670,71 +838,80 @@ static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, netdev->dcbnl_ops->getpgbwgcfgtx(netdev, i - DCB_PG_ATTR_BW_ID_0, &tc_pct); } - ret = nla_put_u8(skb, i, tc_pct); + ret = nla_put_u8(dcbnl_skb, i, tc_pct); + if (ret) goto err_pg; } - nla_nest_end(skb, pg_nest); + nla_nest_end(dcbnl_skb, pg_nest); + + nlmsg_end(dcbnl_skb, nlh); + + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); + if (ret) + goto err_out; return 0; err_param: - nla_nest_cancel(skb, param_nest); + nla_nest_cancel(dcbnl_skb, param_nest); err_pg: - nla_nest_cancel(skb, pg_nest); - - return -EMSGSIZE; + nla_nest_cancel(dcbnl_skb, pg_nest); +nlmsg_failure: +err: + kfree_skb(dcbnl_skb); +err_out: + ret = -EINVAL; + return ret; } -static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_pgtx_getcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { - return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 0); + return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 0); } -static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_pgrx_getcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { - return __dcbnl_pg_getcfg(netdev, nlh, tb, skb, 1); + return __dcbnl_pg_getcfg(netdev, tb, pid, seq, flags, 1); } -static int dcbnl_setstate(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_setstate(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + int ret = -EINVAL; u8 value; - if (!tb[DCB_ATTR_STATE]) - return -EINVAL; - - if (!netdev->dcbnl_ops->setstate) - return -EOPNOTSUPP; + if (!tb[DCB_ATTR_STATE] || !netdev->dcbnl_ops->setstate) + return ret; value = nla_get_u8(tb[DCB_ATTR_STATE]); - return nla_put_u8(skb, DCB_ATTR_STATE, - netdev->dcbnl_ops->setstate(netdev, value)); + ret = dcbnl_reply(netdev->dcbnl_ops->setstate(netdev, value), + RTM_SETDCB, DCB_CMD_SSTATE, DCB_ATTR_STATE, + pid, seq, flags); + + return ret; } -static int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_setpfccfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { struct nlattr *data[DCB_PFC_UP_ATTR_MAX + 1]; int i; - int ret; + int ret = -EINVAL; u8 value; - if (!tb[DCB_ATTR_PFC_CFG]) - return -EINVAL; - - if (!netdev->dcbnl_ops->setpfccfg) - return -EOPNOTSUPP; + if (!tb[DCB_ATTR_PFC_CFG] || !netdev->dcbnl_ops->setpfccfg) + return ret; ret = nla_parse_nested(data, DCB_PFC_UP_ATTR_MAX, tb[DCB_ATTR_PFC_CFG], dcbnl_pfc_up_nest); if (ret) - return ret; + goto err; for (i = DCB_PFC_UP_ATTR_0; i <= DCB_PFC_UP_ATTR_7; i++) { if (data[i] == NULL) @@ -744,53 +921,50 @@ static int dcbnl_setpfccfg(struct net_device *netdev, struct nlmsghdr *nlh, data[i]->nla_type - DCB_PFC_UP_ATTR_0, value); } - return nla_put_u8(skb, DCB_ATTR_PFC_CFG, 0); + ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_PFC_SCFG, DCB_ATTR_PFC_CFG, + pid, seq, flags); +err: + return ret; } -static int dcbnl_setall(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_setall(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { - int ret; - - if (!tb[DCB_ATTR_SET_ALL]) - return -EINVAL; + int ret = -EINVAL; - if (!netdev->dcbnl_ops->setall) - return -EOPNOTSUPP; + if (!tb[DCB_ATTR_SET_ALL] || !netdev->dcbnl_ops->setall) + return ret; - ret = nla_put_u8(skb, DCB_ATTR_SET_ALL, - netdev->dcbnl_ops->setall(netdev)); + ret = dcbnl_reply(netdev->dcbnl_ops->setall(netdev), RTM_SETDCB, + DCB_CMD_SET_ALL, DCB_ATTR_SET_ALL, pid, seq, flags); dcbnl_cee_notify(netdev, RTM_SETDCB, DCB_CMD_SET_ALL, seq, 0); return ret; } -static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb, - int dir) +static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags, int dir) { struct nlattr *pg_tb[DCB_PG_ATTR_MAX + 1]; struct nlattr *param_tb[DCB_TC_ATTR_PARAM_MAX + 1]; - int ret; + int ret = -EINVAL; int i; u8 pgid; u8 up_map; u8 prio; u8 tc_pct; - if (!tb[DCB_ATTR_PG_CFG]) - return -EINVAL; - - if (!netdev->dcbnl_ops->setpgtccfgtx || + if (!tb[DCB_ATTR_PG_CFG] || + !netdev->dcbnl_ops->setpgtccfgtx || !netdev->dcbnl_ops->setpgtccfgrx || !netdev->dcbnl_ops->setpgbwgcfgtx || !netdev->dcbnl_ops->setpgbwgcfgrx) - return -EOPNOTSUPP; + return ret; ret = nla_parse_nested(pg_tb, DCB_PG_ATTR_MAX, tb[DCB_ATTR_PG_CFG], dcbnl_pg_nest); if (ret) - return ret; + goto err; for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { if (!pg_tb[i]) @@ -799,7 +973,7 @@ static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, ret = nla_parse_nested(param_tb, DCB_TC_ATTR_PARAM_MAX, pg_tb[i], dcbnl_tc_param_nest); if (ret) - return ret; + goto err; pgid = DCB_ATTR_VALUE_UNDEFINED; prio = DCB_ATTR_VALUE_UNDEFINED; @@ -852,48 +1026,63 @@ static int __dcbnl_pg_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, } } - return nla_put_u8(skb, - (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), 0); + ret = dcbnl_reply(0, RTM_SETDCB, + (dir ? DCB_CMD_PGRX_SCFG : DCB_CMD_PGTX_SCFG), + DCB_ATTR_PG_CFG, pid, seq, flags); + +err: + return ret; } -static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_pgtx_setcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { - return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 0); + return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 0); } -static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_pgrx_setcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { - return __dcbnl_pg_setcfg(netdev, nlh, seq, tb, skb, 1); + return __dcbnl_pg_setcfg(netdev, tb, pid, seq, flags, 1); } -static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + struct sk_buff *dcbnl_skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; struct nlattr *bcn_nest; struct nlattr *bcn_tb[DCB_BCN_ATTR_MAX + 1]; u8 value_byte; u32 value_integer; - int ret; + int ret = -EINVAL; bool getall = false; int i; - if (!tb[DCB_ATTR_BCN]) - return -EINVAL; - - if (!netdev->dcbnl_ops->getbcnrp || + if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->getbcnrp || !netdev->dcbnl_ops->getbcncfg) - return -EOPNOTSUPP; + return ret; ret = nla_parse_nested(bcn_tb, DCB_BCN_ATTR_MAX, tb[DCB_ATTR_BCN], dcbnl_bcn_nest); + if (ret) - return ret; + goto err_out; + + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!dcbnl_skb) + goto err_out; + + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = DCB_CMD_BCN_GCFG; - bcn_nest = nla_nest_start(skb, DCB_ATTR_BCN); + bcn_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_BCN); if (!bcn_nest) - return -EMSGSIZE; + goto err; if (bcn_tb[DCB_BCN_ATTR_ALL]) getall = true; @@ -904,7 +1093,7 @@ static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, netdev->dcbnl_ops->getbcnrp(netdev, i - DCB_BCN_ATTR_RP_0, &value_byte); - ret = nla_put_u8(skb, i, value_byte); + ret = nla_put_u8(dcbnl_skb, i, value_byte); if (ret) goto err_bcn; } @@ -915,41 +1104,49 @@ static int dcbnl_bcn_getcfg(struct net_device *netdev, struct nlmsghdr *nlh, netdev->dcbnl_ops->getbcncfg(netdev, i, &value_integer); - ret = nla_put_u32(skb, i, value_integer); + ret = nla_put_u32(dcbnl_skb, i, value_integer); if (ret) goto err_bcn; } - nla_nest_end(skb, bcn_nest); + nla_nest_end(dcbnl_skb, bcn_nest); + + nlmsg_end(dcbnl_skb, nlh); + + ret = rtnl_unicast(dcbnl_skb, &init_net, pid); + if (ret) + goto err_out; return 0; err_bcn: - nla_nest_cancel(skb, bcn_nest); + nla_nest_cancel(dcbnl_skb, bcn_nest); +nlmsg_failure: +err: + kfree_skb(dcbnl_skb); +err_out: + ret = -EINVAL; return ret; } -static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { struct nlattr *data[DCB_BCN_ATTR_MAX + 1]; int i; - int ret; + int ret = -EINVAL; u8 value_byte; u32 value_int; - if (!tb[DCB_ATTR_BCN]) - return -EINVAL; - - if (!netdev->dcbnl_ops->setbcncfg || + if (!tb[DCB_ATTR_BCN] || !netdev->dcbnl_ops->setbcncfg || !netdev->dcbnl_ops->setbcnrp) - return -EOPNOTSUPP; + return ret; ret = nla_parse_nested(data, DCB_BCN_ATTR_MAX, tb[DCB_ATTR_BCN], dcbnl_pfc_up_nest); if (ret) - return ret; + goto err; for (i = DCB_BCN_ATTR_RP_0; i <= DCB_BCN_ATTR_RP_7; i++) { if (data[i] == NULL) @@ -967,7 +1164,10 @@ static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh, i, value_int); } - return nla_put_u8(skb, DCB_ATTR_BCN, 0); + ret = dcbnl_reply(0, RTM_SETDCB, DCB_CMD_BCN_SCFG, DCB_ATTR_BCN, + pid, seq, flags); +err: + return ret; } static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb, @@ -1033,21 +1233,20 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) struct dcb_app_type *itr; const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; int dcbx; - int err; + int err = -EMSGSIZE; if (nla_put_string(skb, DCB_ATTR_IFNAME, netdev->name)) - return -EMSGSIZE; - + goto nla_put_failure; ieee = nla_nest_start(skb, DCB_ATTR_IEEE); if (!ieee) - return -EMSGSIZE; + goto nla_put_failure; if (ops->ieee_getets) { struct ieee_ets ets; err = ops->ieee_getets(netdev, &ets); if (!err && nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets)) - return -EMSGSIZE; + goto nla_put_failure; } if (ops->ieee_getmaxrate) { @@ -1057,7 +1256,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE, sizeof(maxrate), &maxrate); if (err) - return -EMSGSIZE; + goto nla_put_failure; } } @@ -1066,12 +1265,12 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) err = ops->ieee_getpfc(netdev, &pfc); if (!err && nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc)) - return -EMSGSIZE; + goto nla_put_failure; } app = nla_nest_start(skb, DCB_ATTR_IEEE_APP_TABLE); if (!app) - return -EMSGSIZE; + goto nla_put_failure; spin_lock(&dcb_lock); list_for_each_entry(itr, &dcb_app_list, list) { @@ -1080,7 +1279,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) &itr->app); if (err) { spin_unlock(&dcb_lock); - return -EMSGSIZE; + goto nla_put_failure; } } } @@ -1099,7 +1298,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) err = ops->ieee_peer_getets(netdev, &ets); if (!err && nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets)) - return -EMSGSIZE; + goto nla_put_failure; } if (ops->ieee_peer_getpfc) { @@ -1107,7 +1306,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) err = ops->ieee_peer_getpfc(netdev, &pfc); if (!err && nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc)) - return -EMSGSIZE; + goto nla_put_failure; } if (ops->peer_getappinfo && ops->peer_getapptable) { @@ -1116,17 +1315,20 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) DCB_ATTR_IEEE_APP_UNSPEC, DCB_ATTR_IEEE_APP); if (err) - return -EMSGSIZE; + goto nla_put_failure; } nla_nest_end(skb, ieee); if (dcbx >= 0) { err = nla_put_u8(skb, DCB_ATTR_DCBX, dcbx); if (err) - return -EMSGSIZE; + goto nla_put_failure; } return 0; + +nla_put_failure: + return err; } static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, @@ -1138,13 +1340,13 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, struct nlattr *pg = nla_nest_start(skb, i); if (!pg) - return -EMSGSIZE; + goto nla_put_failure; for (i = DCB_PG_ATTR_TC_0; i <= DCB_PG_ATTR_TC_7; i++) { struct nlattr *tc_nest = nla_nest_start(skb, i); if (!tc_nest) - return -EMSGSIZE; + goto nla_put_failure; pgid = DCB_ATTR_VALUE_UNDEFINED; prio = DCB_ATTR_VALUE_UNDEFINED; @@ -1162,7 +1364,7 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, nla_put_u8(skb, DCB_TC_ATTR_PARAM_UP_MAPPING, up_map) || nla_put_u8(skb, DCB_TC_ATTR_PARAM_STRICT_PRIO, prio) || nla_put_u8(skb, DCB_TC_ATTR_PARAM_BW_PCT, tc_pct)) - return -EMSGSIZE; + goto nla_put_failure; nla_nest_end(skb, tc_nest); } @@ -1176,10 +1378,13 @@ static int dcbnl_cee_pg_fill(struct sk_buff *skb, struct net_device *dev, ops->getpgbwgcfgtx(dev, i - DCB_PG_ATTR_BW_ID_0, &tc_pct); if (nla_put_u8(skb, i, tc_pct)) - return -EMSGSIZE; + goto nla_put_failure; } nla_nest_end(skb, pg); return 0; + +nla_put_failure: + return -EMSGSIZE; } static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) @@ -1326,16 +1531,27 @@ static int dcbnl_notify(struct net_device *dev, int event, int cmd, struct net *net = dev_net(dev); struct sk_buff *skb; struct nlmsghdr *nlh; + struct dcbmsg *dcb; const struct dcbnl_rtnl_ops *ops = dev->dcbnl_ops; int err; if (!ops) return -EOPNOTSUPP; - skb = dcbnl_newmsg(event, cmd, pid, seq, 0, &nlh); + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!skb) return -ENOBUFS; + nlh = nlmsg_put(skb, pid, 0, event, sizeof(*dcb), 0); + if (nlh == NULL) { + nlmsg_free(skb); + return -EMSGSIZE; + } + + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = cmd; + if (dcbx_ver == DCB_CAP_DCBX_VER_IEEE) err = dcbnl_ieee_fill(skb, dev); else @@ -1343,7 +1559,8 @@ static int dcbnl_notify(struct net_device *dev, int event, int cmd, if (err < 0) { /* Report error to broadcast listeners */ - nlmsg_free(skb); + nlmsg_cancel(skb, nlh); + kfree_skb(skb); rtnl_set_sk_err(net, RTNLGRP_DCB, err); } else { /* End nlmsg and notify broadcast listeners */ @@ -1373,15 +1590,15 @@ EXPORT_SYMBOL(dcbnl_cee_notify); * No attempt is made to reconcile the case where only part of the * cmd can be completed. */ -static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_ieee_set(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1]; - int err; + int err = -EOPNOTSUPP; if (!ops) - return -EOPNOTSUPP; + return err; if (!tb[DCB_ATTR_IEEE]) return -EINVAL; @@ -1432,28 +1649,58 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh, } err: - err = nla_put_u8(skb, DCB_ATTR_IEEE, err); + dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_SET, DCB_ATTR_IEEE, + pid, seq, flags); dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, seq, 0); return err; } -static int dcbnl_ieee_get(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + struct net *net = dev_net(netdev); + struct sk_buff *skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; + int err; if (!ops) return -EOPNOTSUPP; - return dcbnl_ieee_fill(skb, netdev); + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!skb) + return -ENOBUFS; + + nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + if (nlh == NULL) { + nlmsg_free(skb); + return -EMSGSIZE; + } + + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = DCB_CMD_IEEE_GET; + + err = dcbnl_ieee_fill(skb, netdev); + + if (err < 0) { + nlmsg_cancel(skb, nlh); + kfree_skb(skb); + } else { + nlmsg_end(skb, nlh); + err = rtnl_unicast(skb, net, pid); + } + + return err; } -static int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_ieee_del(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; struct nlattr *ieee[DCB_ATTR_IEEE_MAX + 1]; - int err; + int err = -EOPNOTSUPP; if (!ops) return -EOPNOTSUPP; @@ -1486,26 +1733,32 @@ static int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh, } err: - err = nla_put_u8(skb, DCB_ATTR_IEEE, err); + dcbnl_reply(err, RTM_SETDCB, DCB_CMD_IEEE_DEL, DCB_ATTR_IEEE, + pid, seq, flags); dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_DEL, seq, 0); return err; } /* DCBX configuration */ -static int dcbnl_getdcbx(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_getdcbx(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + int ret; + if (!netdev->dcbnl_ops->getdcbx) return -EOPNOTSUPP; - return nla_put_u8(skb, DCB_ATTR_DCBX, - netdev->dcbnl_ops->getdcbx(netdev)); + ret = dcbnl_reply(netdev->dcbnl_ops->getdcbx(netdev), RTM_GETDCB, + DCB_CMD_GDCBX, DCB_ATTR_DCBX, pid, seq, flags); + + return ret; } -static int dcbnl_setdcbx(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_setdcbx(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + int ret; u8 value; if (!netdev->dcbnl_ops->setdcbx) @@ -1516,13 +1769,19 @@ static int dcbnl_setdcbx(struct net_device *netdev, struct nlmsghdr *nlh, value = nla_get_u8(tb[DCB_ATTR_DCBX]); - return nla_put_u8(skb, DCB_ATTR_DCBX, - netdev->dcbnl_ops->setdcbx(netdev, value)); + ret = dcbnl_reply(netdev->dcbnl_ops->setdcbx(netdev, value), + RTM_SETDCB, DCB_CMD_SDCBX, DCB_ATTR_DCBX, + pid, seq, flags); + + return ret; } -static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + struct sk_buff *dcbnl_skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1], *nest; u8 value; int ret, i; @@ -1537,11 +1796,25 @@ static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh, ret = nla_parse_nested(data, DCB_FEATCFG_ATTR_MAX, tb[DCB_ATTR_FEATCFG], dcbnl_featcfg_nest); if (ret) - return ret; + goto err_out; - nest = nla_nest_start(skb, DCB_ATTR_FEATCFG); - if (!nest) - return -EMSGSIZE; + dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!dcbnl_skb) { + ret = -ENOBUFS; + goto err_out; + } + + nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = DCB_CMD_GFEATCFG; + + nest = nla_nest_start(dcbnl_skb, DCB_ATTR_FEATCFG); + if (!nest) { + ret = -EMSGSIZE; + goto nla_put_failure; + } if (data[DCB_FEATCFG_ATTR_ALL]) getall = 1; @@ -1552,21 +1825,28 @@ static int dcbnl_getfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh, ret = netdev->dcbnl_ops->getfeatcfg(netdev, i, &value); if (!ret) - ret = nla_put_u8(skb, i, value); + ret = nla_put_u8(dcbnl_skb, i, value); if (ret) { - nla_nest_cancel(skb, nest); + nla_nest_cancel(dcbnl_skb, nest); goto nla_put_failure; } } - nla_nest_end(skb, nest); + nla_nest_end(dcbnl_skb, nest); + nlmsg_end(dcbnl_skb, nlh); + + return rtnl_unicast(dcbnl_skb, &init_net, pid); nla_put_failure: + nlmsg_cancel(dcbnl_skb, nlh); +nlmsg_failure: + kfree_skb(dcbnl_skb); +err_out: return ret; } -static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { struct nlattr *data[DCB_FEATCFG_ATTR_MAX + 1]; int ret, i; @@ -1596,73 +1876,60 @@ static int dcbnl_setfeatcfg(struct net_device *netdev, struct nlmsghdr *nlh, goto err; } err: - ret = nla_put_u8(skb, DCB_ATTR_FEATCFG, ret); + dcbnl_reply(ret, RTM_SETDCB, DCB_CMD_SFEATCFG, DCB_ATTR_FEATCFG, + pid, seq, flags); return ret; } /* Handle CEE DCBX GET commands. */ -static int dcbnl_cee_get(struct net_device *netdev, struct nlmsghdr *nlh, - u32 seq, struct nlattr **tb, struct sk_buff *skb) +static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb, + u32 pid, u32 seq, u16 flags) { + struct net *net = dev_net(netdev); + struct sk_buff *skb; + struct nlmsghdr *nlh; + struct dcbmsg *dcb; const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops; + int err; if (!ops) return -EOPNOTSUPP; - return dcbnl_cee_fill(skb, netdev); -} + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!skb) + return -ENOBUFS; -struct reply_func { - /* reply netlink message type */ - int type; + nlh = nlmsg_put(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); + if (nlh == NULL) { + nlmsg_free(skb); + return -EMSGSIZE; + } - /* function to fill message contents */ - int (*cb)(struct net_device *, struct nlmsghdr *, u32, - struct nlattr **, struct sk_buff *); -}; + dcb = NLMSG_DATA(nlh); + dcb->dcb_family = AF_UNSPEC; + dcb->cmd = DCB_CMD_CEE_GET; -static const struct reply_func reply_funcs[DCB_CMD_MAX+1] = { - [DCB_CMD_GSTATE] = { RTM_GETDCB, dcbnl_getstate }, - [DCB_CMD_SSTATE] = { RTM_SETDCB, dcbnl_setstate }, - [DCB_CMD_PFC_GCFG] = { RTM_GETDCB, dcbnl_getpfccfg }, - [DCB_CMD_PFC_SCFG] = { RTM_SETDCB, dcbnl_setpfccfg }, - [DCB_CMD_GPERM_HWADDR] = { RTM_GETDCB, dcbnl_getperm_hwaddr }, - [DCB_CMD_GCAP] = { RTM_GETDCB, dcbnl_getcap }, - [DCB_CMD_GNUMTCS] = { RTM_GETDCB, dcbnl_getnumtcs }, - [DCB_CMD_SNUMTCS] = { RTM_SETDCB, dcbnl_setnumtcs }, - [DCB_CMD_PFC_GSTATE] = { RTM_GETDCB, dcbnl_getpfcstate }, - [DCB_CMD_PFC_SSTATE] = { RTM_SETDCB, dcbnl_setpfcstate }, - [DCB_CMD_GAPP] = { RTM_GETDCB, dcbnl_getapp }, - [DCB_CMD_SAPP] = { RTM_SETDCB, dcbnl_setapp }, - [DCB_CMD_PGTX_GCFG] = { RTM_GETDCB, dcbnl_pgtx_getcfg }, - [DCB_CMD_PGTX_SCFG] = { RTM_SETDCB, dcbnl_pgtx_setcfg }, - [DCB_CMD_PGRX_GCFG] = { RTM_GETDCB, dcbnl_pgrx_getcfg }, - [DCB_CMD_PGRX_SCFG] = { RTM_SETDCB, dcbnl_pgrx_setcfg }, - [DCB_CMD_SET_ALL] = { RTM_SETDCB, dcbnl_setall }, - [DCB_CMD_BCN_GCFG] = { RTM_GETDCB, dcbnl_bcn_getcfg }, - [DCB_CMD_BCN_SCFG] = { RTM_SETDCB, dcbnl_bcn_setcfg }, - [DCB_CMD_IEEE_GET] = { RTM_GETDCB, dcbnl_ieee_get }, - [DCB_CMD_IEEE_SET] = { RTM_SETDCB, dcbnl_ieee_set }, - [DCB_CMD_IEEE_DEL] = { RTM_SETDCB, dcbnl_ieee_del }, - [DCB_CMD_GDCBX] = { RTM_GETDCB, dcbnl_getdcbx }, - [DCB_CMD_SDCBX] = { RTM_SETDCB, dcbnl_setdcbx }, - [DCB_CMD_GFEATCFG] = { RTM_GETDCB, dcbnl_getfeatcfg }, - [DCB_CMD_SFEATCFG] = { RTM_SETDCB, dcbnl_setfeatcfg }, - [DCB_CMD_CEE_GET] = { RTM_GETDCB, dcbnl_cee_get }, -}; + err = dcbnl_cee_fill(skb, netdev); + + if (err < 0) { + nlmsg_cancel(skb, nlh); + nlmsg_free(skb); + } else { + nlmsg_end(skb, nlh); + err = rtnl_unicast(skb, net, pid); + } + return err; +} static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct net *net = sock_net(skb->sk); struct net_device *netdev; - struct dcbmsg *dcb = nlmsg_data(nlh); + struct dcbmsg *dcb = (struct dcbmsg *)NLMSG_DATA(nlh); struct nlattr *tb[DCB_ATTR_MAX + 1]; u32 pid = skb ? NETLINK_CB(skb).pid : 0; int ret = -EINVAL; - struct sk_buff *reply_skb; - struct nlmsghdr *reply_nlh = NULL; - const struct reply_func *fn; if (!net_eq(net, &init_net)) return -EINVAL; @@ -1672,78 +1939,136 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (ret < 0) return ret; - if (dcb->cmd > DCB_CMD_MAX) - return -EINVAL; - - /* check if a reply function has been defined for the command */ - fn = &reply_funcs[dcb->cmd]; - if (!fn->cb) - return -EOPNOTSUPP; - if (!tb[DCB_ATTR_IFNAME]) return -EINVAL; netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME])); if (!netdev) - return -ENODEV; + return -EINVAL; - if (!netdev->dcbnl_ops) { - ret = -EOPNOTSUPP; - goto out; - } + if (!netdev->dcbnl_ops) + goto errout; - reply_skb = dcbnl_newmsg(fn->type, dcb->cmd, pid, nlh->nlmsg_seq, - nlh->nlmsg_flags, &reply_nlh); - if (!reply_skb) { - ret = -ENOBUFS; + switch (dcb->cmd) { + case DCB_CMD_GSTATE: + ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_PFC_GCFG: + ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_GPERM_HWADDR: + ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_PGTX_GCFG: + ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_PGRX_GCFG: + ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_BCN_GCFG: + ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_SSTATE: + ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_PFC_SCFG: + ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); goto out; - } - ret = fn->cb(netdev, nlh, nlh->nlmsg_seq, tb, reply_skb); - if (ret < 0) { - nlmsg_free(reply_skb); + case DCB_CMD_SET_ALL: + ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_PGTX_SCFG: + ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_PGRX_SCFG: + ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_GCAP: + ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_GNUMTCS: + ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_SNUMTCS: + ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_PFC_GSTATE: + ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_PFC_SSTATE: + ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_BCN_SCFG: + ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_GAPP: + ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_SAPP: + ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_IEEE_SET: + ret = dcbnl_ieee_set(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_IEEE_GET: + ret = dcbnl_ieee_get(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_IEEE_DEL: + ret = dcbnl_ieee_del(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_GDCBX: + ret = dcbnl_getdcbx(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_SDCBX: + ret = dcbnl_setdcbx(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_GFEATCFG: + ret = dcbnl_getfeatcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + case DCB_CMD_SFEATCFG: + ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); goto out; + case DCB_CMD_CEE_GET: + ret = dcbnl_cee_get(netdev, tb, pid, nlh->nlmsg_seq, + nlh->nlmsg_flags); + goto out; + default: + goto errout; } - - nlmsg_end(reply_skb, reply_nlh); - - ret = rtnl_unicast(reply_skb, &init_net, pid); +errout: + ret = -EINVAL; out: dev_put(netdev); return ret; } -static struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app, - int ifindex, int prio) -{ - struct dcb_app_type *itr; - - list_for_each_entry(itr, &dcb_app_list, list) { - if (itr->app.selector == app->selector && - itr->app.protocol == app->protocol && - itr->ifindex == ifindex && - (!prio || itr->app.priority == prio)) - return itr; - } - - return NULL; -} - -static int dcb_app_add(const struct dcb_app *app, int ifindex) -{ - struct dcb_app_type *entry; - - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (!entry) - return -ENOMEM; - - memcpy(&entry->app, app, sizeof(*app)); - entry->ifindex = ifindex; - list_add(&entry->list, &dcb_app_list); - - return 0; -} - /** * dcb_getapp - retrieve the DCBX application user priority * @@ -1757,8 +2082,14 @@ u8 dcb_getapp(struct net_device *dev, struct dcb_app *app) u8 prio = 0; spin_lock(&dcb_lock); - if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) - prio = itr->app.priority; + list_for_each_entry(itr, &dcb_app_list, list) { + if (itr->app.selector == app->selector && + itr->app.protocol == app->protocol && + itr->ifindex == dev->ifindex) { + prio = itr->app.priority; + break; + } + } spin_unlock(&dcb_lock); return prio; @@ -1776,7 +2107,6 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new) { struct dcb_app_type *itr; struct dcb_app_type event; - int err = 0; event.ifindex = dev->ifindex; memcpy(&event.app, new, sizeof(event.app)); @@ -1785,23 +2115,36 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new) spin_lock(&dcb_lock); /* Search for existing match and replace */ - if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) { - if (new->priority) - itr->app.priority = new->priority; - else { - list_del(&itr->list); - kfree(itr); + list_for_each_entry(itr, &dcb_app_list, list) { + if (itr->app.selector == new->selector && + itr->app.protocol == new->protocol && + itr->ifindex == dev->ifindex) { + if (new->priority) + itr->app.priority = new->priority; + else { + list_del(&itr->list); + kfree(itr); + } + goto out; } - goto out; } /* App type does not exist add new application type */ - if (new->priority) - err = dcb_app_add(new, dev->ifindex); + if (new->priority) { + struct dcb_app_type *entry; + entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC); + if (!entry) { + spin_unlock(&dcb_lock); + return -ENOMEM; + } + + memcpy(&entry->app, new, sizeof(*new)); + entry->ifindex = dev->ifindex; + list_add(&entry->list, &dcb_app_list); + } out: spin_unlock(&dcb_lock); - if (!err) - call_dcbevent_notifiers(DCB_APP_EVENT, &event); - return err; + call_dcbevent_notifiers(DCB_APP_EVENT, &event); + return 0; } EXPORT_SYMBOL(dcb_setapp); @@ -1818,8 +2161,13 @@ u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app) u8 prio = 0; spin_lock(&dcb_lock); - if ((itr = dcb_app_lookup(app, dev->ifindex, 0))) - prio |= 1 << itr->app.priority; + list_for_each_entry(itr, &dcb_app_list, list) { + if (itr->app.selector == app->selector && + itr->app.protocol == app->protocol && + itr->ifindex == dev->ifindex) { + prio |= 1 << itr->app.priority; + } + } spin_unlock(&dcb_lock); return prio; @@ -1835,6 +2183,7 @@ EXPORT_SYMBOL(dcb_ieee_getapp_mask); */ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new) { + struct dcb_app_type *itr, *entry; struct dcb_app_type event; int err = 0; @@ -1845,12 +2194,26 @@ int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new) spin_lock(&dcb_lock); /* Search for existing match and abort if found */ - if (dcb_app_lookup(new, dev->ifindex, new->priority)) { - err = -EEXIST; + list_for_each_entry(itr, &dcb_app_list, list) { + if (itr->app.selector == new->selector && + itr->app.protocol == new->protocol && + itr->app.priority == new->priority && + itr->ifindex == dev->ifindex) { + err = -EEXIST; + goto out; + } + } + + /* App entry does not exist add new entry */ + entry = kmalloc(sizeof(struct dcb_app_type), GFP_ATOMIC); + if (!entry) { + err = -ENOMEM; goto out; } - err = dcb_app_add(new, dev->ifindex); + memcpy(&entry->app, new, sizeof(*new)); + entry->ifindex = dev->ifindex; + list_add(&entry->list, &dcb_app_list); out: spin_unlock(&dcb_lock); if (!err) @@ -1877,12 +2240,19 @@ int dcb_ieee_delapp(struct net_device *dev, struct dcb_app *del) spin_lock(&dcb_lock); /* Search for existing match and remove it. */ - if ((itr = dcb_app_lookup(del, dev->ifindex, del->priority))) { - list_del(&itr->list); - kfree(itr); - err = 0; + list_for_each_entry(itr, &dcb_app_list, list) { + if (itr->app.selector == del->selector && + itr->app.protocol == del->protocol && + itr->app.priority == del->priority && + itr->ifindex == dev->ifindex) { + list_del(&itr->list); + kfree(itr); + err = 0; + goto out; + } } +out: spin_unlock(&dcb_lock); if (!err) call_dcbevent_notifiers(DCB_APP_EVENT, &event); diff --git a/trunk/net/dccp/ipv6.c b/trunk/net/dccp/ipv6.c index 9991be083ad0..fa9512d86f3b 100644 --- a/trunk/net/dccp/ipv6.c +++ b/trunk/net/dccp/ipv6.c @@ -165,8 +165,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, } else dst_hold(dst); - dst->ops->update_pmtu(dst, ntohl(info)); - if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) { dccp_sync_mss(sk, dst_mtu(dst)); } /* else let the usual retransmit timer handle it */ diff --git a/trunk/net/ipv4/ah4.c b/trunk/net/ipv4/ah4.c index 916d5ecaf6c6..e8f2617ecd47 100644 --- a/trunk/net/ipv4/ah4.c +++ b/trunk/net/ipv4/ah4.c @@ -408,7 +408,6 @@ static void ah4_err(struct sk_buff *skb, u32 info) return; pr_debug("pmtu discovery on SA AH/%08x/%08x\n", ntohl(ah->spi), ntohl(iph->daddr)); - ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv4/esp4.c b/trunk/net/ipv4/esp4.c index 7b95b49a36ce..cb982a61536f 100644 --- a/trunk/net/ipv4/esp4.c +++ b/trunk/net/ipv4/esp4.c @@ -494,7 +494,6 @@ static void esp4_err(struct sk_buff *skb, u32 info) return; NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n", ntohl(esph->spi), ntohl(iph->daddr)); - ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv4/ip_forward.c b/trunk/net/ipv4/ip_forward.c index ab09b126423c..e5c44fc586ab 100644 --- a/trunk/net/ipv4/ip_forward.c +++ b/trunk/net/ipv4/ip_forward.c @@ -44,7 +44,6 @@ static int ip_forward_finish(struct sk_buff *skb) struct ip_options *opt = &(IPCB(skb)->opt); IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); - IP_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTOCTETS, skb->len); if (unlikely(opt->optlen)) ip_forward_options(skb); diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index 594cec35ac4d..f49047b79609 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -516,6 +516,9 @@ static void ipgre_err(struct sk_buff *skb, u32 info) case ICMP_PORT_UNREACH: /* Impossible event. */ return; + case ICMP_FRAG_NEEDED: + /* Soft state for pmtu is maintained by IP core. */ + return; default: /* All others are translated to HOST_UNREACH. rfc2003 contains "deep thoughts" about NET_UNREACH, @@ -535,16 +538,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) flags & GRE_KEY ? *(((__be32 *)p) + (grehlen / 4) - 1) : 0, p[1]); - if (t == NULL) - goto out; - - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - ipv4_update_pmtu(skb, dev_net(skb->dev), info, - t->parms.link, 0, IPPROTO_GRE, 0); - goto out; - } - - if (t->parms.iph.daddr == 0 || + if (t == NULL || t->parms.iph.daddr == 0 || ipv4_is_multicast(t->parms.iph.daddr)) goto out; diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index 0f3185a662c3..b99ca4e154b9 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -113,6 +113,19 @@ int ip_local_out(struct sk_buff *skb) } EXPORT_SYMBOL_GPL(ip_local_out); +/* dev_loopback_xmit for use with netfilter. */ +static int ip_dev_loopback_xmit(struct sk_buff *newskb) +{ + skb_reset_mac_header(newskb); + __skb_pull(newskb, skb_network_offset(newskb)); + newskb->pkt_type = PACKET_LOOPBACK; + newskb->ip_summed = CHECKSUM_UNNECESSARY; + WARN_ON(!skb_dst(newskb)); + skb_dst_force(newskb); + netif_rx_ni(newskb); + return 0; +} + static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst) { int ttl = inet->uc_ttl; @@ -268,7 +281,7 @@ int ip_mc_output(struct sk_buff *skb) if (newskb) NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, newskb, NULL, newskb->dev, - dev_loopback_xmit); + ip_dev_loopback_xmit); } /* Multicasts with ttl 0 must not go beyond the host */ @@ -283,7 +296,7 @@ int ip_mc_output(struct sk_buff *skb) struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); if (newskb) NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, newskb, - NULL, newskb->dev, dev_loopback_xmit); + NULL, newskb->dev, ip_dev_loopback_xmit); } return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, diff --git a/trunk/net/ipv4/ipcomp.c b/trunk/net/ipv4/ipcomp.c index b91375482d84..63b64c45a826 100644 --- a/trunk/net/ipv4/ipcomp.c +++ b/trunk/net/ipv4/ipcomp.c @@ -42,7 +42,6 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) return; NETDEBUG(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/%pI4\n", spi, &iph->daddr); - ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index 715338a1b205..2d0f99bf61b3 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -348,6 +348,9 @@ static int ipip_err(struct sk_buff *skb, u32 info) case ICMP_PORT_UNREACH: /* Impossible event. */ return 0; + case ICMP_FRAG_NEEDED: + /* Soft state for pmtu is maintained by IP core. */ + return 0; default: /* All others are translated to HOST_UNREACH. rfc2003 contains "deep thoughts" about NET_UNREACH, @@ -366,17 +369,7 @@ static int ipip_err(struct sk_buff *skb, u32 info) rcu_read_lock(); t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); - if (t == NULL) - goto out; - - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - ipv4_update_pmtu(skb, dev_net(skb->dev), info, - t->dev->ifindex, 0, IPPROTO_IPIP, 0); - err = 0; - goto out; - } - - if (t->parms.iph.daddr == 0) + if (t == NULL || t->parms.iph.daddr == 0) goto out; err = 0; diff --git a/trunk/net/ipv4/ipmr.c b/trunk/net/ipv4/ipmr.c index c94bbc6f2ba3..a9e519ad6db5 100644 --- a/trunk/net/ipv4/ipmr.c +++ b/trunk/net/ipv4/ipmr.c @@ -1574,7 +1574,6 @@ static inline int ipmr_forward_finish(struct sk_buff *skb) struct ip_options *opt = &(IPCB(skb)->opt); IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS); - IP_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTOCTETS, skb->len); if (unlikely(opt->optlen)) ip_forward_options(skb); diff --git a/trunk/net/ipv4/ping.c b/trunk/net/ipv4/ping.c index 340fcf29a966..2c00e8bf684d 100644 --- a/trunk/net/ipv4/ping.c +++ b/trunk/net/ipv4/ping.c @@ -371,7 +371,6 @@ void ping_err(struct sk_buff *skb, u32 info) break; case ICMP_DEST_UNREACH: if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ - ipv4_sk_update_pmtu(skb, sk, info); if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { err = EMSGSIZE; harderr = 1; diff --git a/trunk/net/ipv4/raw.c b/trunk/net/ipv4/raw.c index 659ddfb10947..4032b818f3e4 100644 --- a/trunk/net/ipv4/raw.c +++ b/trunk/net/ipv4/raw.c @@ -216,9 +216,6 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) int err = 0; int harderr = 0; - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) - ipv4_sk_update_pmtu(skb, sk, info); - /* Report error on raw socket, if: 1. User requested ip_recverr. 2. Socket is connected (otherwise the error indication diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 41df5297a412..655506af47ca 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -1711,34 +1711,6 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) } } -void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, - int oif, u32 mark, u8 protocol, int flow_flags) -{ - const struct iphdr *iph = (const struct iphdr *)skb->data; - struct flowi4 fl4; - struct rtable *rt; - - flowi4_init_output(&fl4, oif, mark, RT_TOS(iph->tos), RT_SCOPE_UNIVERSE, - protocol, flow_flags | FLOWI_FLAG_PRECOW_METRICS, - iph->daddr, iph->saddr, 0, 0); - rt = __ip_route_output_key(net, &fl4); - if (!IS_ERR(rt)) { - ip_rt_update_pmtu(&rt->dst, mtu); - ip_rt_put(rt); - } -} -EXPORT_SYMBOL_GPL(ipv4_update_pmtu); - -void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) -{ - const struct inet_sock *inet = inet_sk(sk); - - return ipv4_update_pmtu(skb, sock_net(sk), mtu, - sk->sk_bound_dev_if, sk->sk_mark, - inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, - inet_sk_flowi_flags(sk)); -} -EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu); static void ipv4_validate_peer(struct rtable *rt) { diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index db017efb76ea..eaca73644e79 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -615,7 +615,6 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) break; case ICMP_DEST_UNREACH: if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ - ipv4_sk_update_pmtu(skb, sk, info); if (inet->pmtudisc != IP_PMTUDISC_DONT) { err = EMSGSIZE; harderr = 1; diff --git a/trunk/net/ipv6/ah6.c b/trunk/net/ipv6/ah6.c index 49d4d26bda88..f1a4a2c28ed3 100644 --- a/trunk/net/ipv6/ah6.c +++ b/trunk/net/ipv6/ah6.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -622,7 +621,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/%pI6\n", ntohl(ah->spi), &iph->daddr); - ip6_update_pmtu(skb, net, info, 0, 0); + xfrm_state_put(x); } diff --git a/trunk/net/ipv6/esp6.c b/trunk/net/ipv6/esp6.c index 89a615ba84f8..db1521fcda5b 100644 --- a/trunk/net/ipv6/esp6.c +++ b/trunk/net/ipv6/esp6.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -443,7 +442,6 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return; pr_debug("pmtu discovery on SA ESP/%08x/%pI6\n", ntohl(esph->spi), &iph->daddr); - ip6_update_pmtu(skb, net, info, 0, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv6/icmp.c b/trunk/net/ipv6/icmp.c index 5247d5c211f9..ed89bba745a1 100644 --- a/trunk/net/ipv6/icmp.c +++ b/trunk/net/ipv6/icmp.c @@ -649,6 +649,7 @@ static int icmpv6_rcv(struct sk_buff *skb) struct net_device *dev = skb->dev; struct inet6_dev *idev = __in6_dev_get(dev); const struct in6_addr *saddr, *daddr; + const struct ipv6hdr *orig_hdr; struct icmp6hdr *hdr; u8 type; @@ -660,7 +661,7 @@ static int icmpv6_rcv(struct sk_buff *skb) XFRM_STATE_ICMP)) goto drop_no_count; - if (!pskb_may_pull(skb, sizeof(*hdr) + sizeof(struct ipv6hdr))) + if (!pskb_may_pull(skb, sizeof(*hdr) + sizeof(*orig_hdr))) goto drop_no_count; nh = skb_network_offset(skb); @@ -721,6 +722,9 @@ static int icmpv6_rcv(struct sk_buff *skb) if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto discard_it; hdr = icmp6_hdr(skb); + orig_hdr = (struct ipv6hdr *) (hdr + 1); + rt6_pmtu_discovery(&orig_hdr->daddr, &orig_hdr->saddr, dev, + ntohl(hdr->icmp6_mtu)); /* * Drop through to notify diff --git a/trunk/net/ipv6/ip6_fib.c b/trunk/net/ipv6/ip6_fib.c index 215afc74d8aa..7ef0743f06f0 100644 --- a/trunk/net/ipv6/ip6_fib.c +++ b/trunk/net/ipv6/ip6_fib.c @@ -1562,7 +1562,7 @@ static int fib6_age(struct rt6_info *rt, void *arg) neigh_flags = neigh->flags; neigh_release(neigh); } - if (!(neigh_flags & NTF_ROUTER)) { + if (neigh_flags & NTF_ROUTER) { RT6_TRACE("purging route %p via non-router but gateway\n", rt); return -1; diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index a233a7ccbc3a..62fcf3e48aca 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -83,6 +83,19 @@ int ip6_local_out(struct sk_buff *skb) } EXPORT_SYMBOL_GPL(ip6_local_out); +/* dev_loopback_xmit for use with netfilter. */ +static int ip6_dev_loopback_xmit(struct sk_buff *newskb) +{ + skb_reset_mac_header(newskb); + __skb_pull(newskb, skb_network_offset(newskb)); + newskb->pkt_type = PACKET_LOOPBACK; + newskb->ip_summed = CHECKSUM_UNNECESSARY; + WARN_ON(!skb_dst(newskb)); + + netif_rx_ni(newskb); + return 0; +} + static int ip6_finish_output2(struct sk_buff *skb) { struct dst_entry *dst = skb_dst(skb); @@ -108,7 +121,7 @@ static int ip6_finish_output2(struct sk_buff *skb) if (newskb) NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, newskb, NULL, newskb->dev, - dev_loopback_xmit); + ip6_dev_loopback_xmit); if (ipv6_hdr(skb)->hop_limit == 0) { IP6_INC_STATS(dev_net(dev), idev, @@ -513,7 +526,6 @@ int ip6_forward(struct sk_buff *skb) hdr->hop_limit--; IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); - IP6_ADD_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTOCTETS, skb->len); return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish); diff --git a/trunk/net/ipv6/ip6mr.c b/trunk/net/ipv6/ip6mr.c index 461e47c8e956..b15dc08643a4 100644 --- a/trunk/net/ipv6/ip6mr.c +++ b/trunk/net/ipv6/ip6mr.c @@ -1886,8 +1886,6 @@ static inline int ip6mr_forward2_finish(struct sk_buff *skb) { IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_OUTFORWDATAGRAMS); - IP6_ADD_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), - IPSTATS_MIB_OUTOCTETS, skb->len); return dst_output(skb); } diff --git a/trunk/net/ipv6/ipcomp6.c b/trunk/net/ipv6/ipcomp6.c index 92832385a8ef..5cb75bfe45b1 100644 --- a/trunk/net/ipv6/ipcomp6.c +++ b/trunk/net/ipv6/ipcomp6.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -75,7 +74,6 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, pr_debug("pmtu discovery on SA IPCOMP/%08x/%pI6\n", spi, &iph->daddr); - ip6_update_pmtu(skb, net, info, 0, 0); xfrm_state_put(x); } diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index 43b0042f15f4..93d69836fded 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -328,10 +328,9 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb, return; harderr = icmpv6_err_convert(type, code, &err); - if (type == ICMPV6_PKT_TOOBIG) { - ip6_sk_update_pmtu(skb, sk, info); + if (type == ICMPV6_PKT_TOOBIG) harderr = (np->pmtudisc == IPV6_PMTUDISC_DO); - } + if (np->recverr) { u8 *payload = skb->data; if (!inet->hdrincl) diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index e649cd78c15f..58a3ec23da2f 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -1049,10 +1049,7 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) { struct rt6_info *rt6 = (struct rt6_info*)dst; - dst_confirm(dst); if (mtu < dst_mtu(dst) && rt6->rt6i_dst.plen == 128) { - struct net *net = dev_net(dst->dev); - rt6->rt6i_flags |= RTF_MODIFIED; if (mtu < IPV6_MIN_MTU) { u32 features = dst_metric(dst, RTAX_FEATURES); @@ -1061,39 +1058,9 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) dst_metric_set(dst, RTAX_FEATURES, features); } dst_metric_set(dst, RTAX_MTU, mtu); - rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); } } -void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, - int oif, u32 mark) -{ - const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; - struct dst_entry *dst; - struct flowi6 fl6; - - memset(&fl6, 0, sizeof(fl6)); - fl6.flowi6_oif = oif; - fl6.flowi6_mark = mark; - fl6.flowi6_flags = FLOWI_FLAG_PRECOW_METRICS; - fl6.daddr = iph->daddr; - fl6.saddr = iph->saddr; - fl6.flowlabel = (*(__be32 *) iph) & IPV6_FLOWINFO_MASK; - - dst = ip6_route_output(net, NULL, &fl6); - if (!dst->error) - ip6_rt_update_pmtu(dst, ntohl(mtu)); - dst_release(dst); -} -EXPORT_SYMBOL_GPL(ip6_update_pmtu); - -void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) -{ - ip6_update_pmtu(skb, sock_net(sk), mtu, - sk->sk_bound_dev_if, sk->sk_mark); -} -EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu); - static unsigned int ip6_default_advmss(const struct dst_entry *dst) { struct net_device *dev = dst->dev; @@ -1736,6 +1703,116 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, dst_release(&rt->dst); } +/* + * Handle ICMP "packet too big" messages + * i.e. Path MTU discovery + */ + +static void rt6_do_pmtu_disc(const struct in6_addr *daddr, const struct in6_addr *saddr, + struct net *net, u32 pmtu, int ifindex) +{ + struct rt6_info *rt, *nrt; + int allfrag = 0; +again: + rt = rt6_lookup(net, daddr, saddr, ifindex, 0); + if (!rt) + return; + + if (rt6_check_expired(rt)) { + ip6_del_rt(rt); + goto again; + } + + if (pmtu >= dst_mtu(&rt->dst)) + goto out; + + if (pmtu < IPV6_MIN_MTU) { + /* + * According to RFC2460, PMTU is set to the IPv6 Minimum Link + * MTU (1280) and a fragment header should always be included + * after a node receiving Too Big message reporting PMTU is + * less than the IPv6 Minimum Link MTU. + */ + pmtu = IPV6_MIN_MTU; + allfrag = 1; + } + + /* New mtu received -> path was valid. + They are sent only in response to data packets, + so that this nexthop apparently is reachable. --ANK + */ + dst_confirm(&rt->dst); + + /* Host route. If it is static, it would be better + not to override it, but add new one, so that + when cache entry will expire old pmtu + would return automatically. + */ + if (rt->rt6i_flags & RTF_CACHE) { + dst_metric_set(&rt->dst, RTAX_MTU, pmtu); + if (allfrag) { + u32 features = dst_metric(&rt->dst, RTAX_FEATURES); + features |= RTAX_FEATURE_ALLFRAG; + dst_metric_set(&rt->dst, RTAX_FEATURES, features); + } + rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires); + rt->rt6i_flags |= RTF_MODIFIED; + goto out; + } + + /* Network route. + Two cases are possible: + 1. It is connected route. Action: COW + 2. It is gatewayed route or NONEXTHOP route. Action: clone it. + */ + if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) + nrt = rt6_alloc_cow(rt, daddr, saddr); + else + nrt = rt6_alloc_clone(rt, daddr); + + if (nrt) { + dst_metric_set(&nrt->dst, RTAX_MTU, pmtu); + if (allfrag) { + u32 features = dst_metric(&nrt->dst, RTAX_FEATURES); + features |= RTAX_FEATURE_ALLFRAG; + dst_metric_set(&nrt->dst, RTAX_FEATURES, features); + } + + /* According to RFC 1981, detecting PMTU increase shouldn't be + * happened within 5 mins, the recommended timer is 10 mins. + * Here this route expiration time is set to ip6_rt_mtu_expires + * which is 10 mins. After 10 mins the decreased pmtu is expired + * and detecting PMTU increase will be automatically happened. + */ + rt6_update_expires(nrt, net->ipv6.sysctl.ip6_rt_mtu_expires); + nrt->rt6i_flags |= RTF_DYNAMIC; + ip6_ins_rt(nrt); + } +out: + dst_release(&rt->dst); +} + +void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *saddr, + struct net_device *dev, u32 pmtu) +{ + struct net *net = dev_net(dev); + + /* + * RFC 1981 states that a node "MUST reduce the size of the packets it + * is sending along the path" that caused the Packet Too Big message. + * Since it's not possible in the general case to determine which + * interface was used to send the original packet, we update the MTU + * on the interface that will be used to send future packets. We also + * update the MTU on the interface that received the Packet Too Big in + * case the original packet was forced out that interface with + * SO_BINDTODEVICE or similar. This is the next best thing to the + * correct behaviour, which would be to update the MTU on all + * interfaces. + */ + rt6_do_pmtu_disc(daddr, saddr, net, pmtu, 0); + rt6_do_pmtu_disc(daddr, saddr, net, pmtu, dev->ifindex); +} + /* * Misc support functions */ @@ -2974,13 +3051,13 @@ int __init ip6_route_init(void) if (ret) goto out_kmem_cache; - ret = register_pernet_subsys(&ipv6_inetpeer_ops); + ret = register_pernet_subsys(&ip6_route_net_ops); if (ret) goto out_dst_entries; - ret = register_pernet_subsys(&ip6_route_net_ops); + ret = register_pernet_subsys(&ipv6_inetpeer_ops); if (ret) - goto out_register_inetpeer; + goto out_register_subsys; ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; @@ -2997,7 +3074,7 @@ int __init ip6_route_init(void) #endif ret = fib6_init(); if (ret) - goto out_register_subsys; + goto out_register_inetpeer; ret = xfrm6_init(); if (ret) @@ -3026,10 +3103,10 @@ int __init ip6_route_init(void) xfrm6_fini(); out_fib6_init: fib6_gc_cleanup(); -out_register_subsys: - unregister_pernet_subsys(&ip6_route_net_ops); out_register_inetpeer: unregister_pernet_subsys(&ipv6_inetpeer_ops); +out_register_subsys: + unregister_pernet_subsys(&ip6_route_net_ops); out_dst_entries: dst_entries_destroy(&ip6_dst_blackhole_ops); out_kmem_cache: diff --git a/trunk/net/ipv6/sit.c b/trunk/net/ipv6/sit.c index 49aea94c9be3..60415711563f 100644 --- a/trunk/net/ipv6/sit.c +++ b/trunk/net/ipv6/sit.c @@ -527,6 +527,9 @@ static int ipip6_err(struct sk_buff *skb, u32 info) case ICMP_PORT_UNREACH: /* Impossible event. */ return 0; + case ICMP_FRAG_NEEDED: + /* Soft state for pmtu is maintained by IP core. */ + return 0; default: /* All others are translated to HOST_UNREACH. rfc2003 contains "deep thoughts" about NET_UNREACH, @@ -548,17 +551,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) skb->dev, iph->daddr, iph->saddr); - if (t == NULL) - goto out; - - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - ipv4_update_pmtu(skb, dev_net(skb->dev), info, - t->dev->ifindex, 0, IPPROTO_IPV6, 0); - err = 0; - goto out; - } - - if (t->parms.iph.daddr == 0) + if (t == NULL || t->parms.iph.daddr == 0) goto out; err = 0; diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index 26a88623940b..f91b0bfd12d5 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -415,8 +415,6 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, } else dst_hold(dst); - dst->ops->update_pmtu(dst, ntohl(info)); - if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) { tcp_sync_mss(sk, dst_mtu(dst)); tcp_simple_retransmit(sk); diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 051ad481973f..f05099fc5901 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -479,9 +479,6 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (sk == NULL) return; - if (type == ICMPV6_PKT_TOOBIG) - ip6_sk_update_pmtu(skb, sk, info); - np = inet6_sk(sk); if (!icmpv6_err_convert(type, code, &err) && !np->recverr) diff --git a/trunk/net/iucv/af_iucv.c b/trunk/net/iucv/af_iucv.c index cd6f7a991d80..07d7d55a1b93 100644 --- a/trunk/net/iucv/af_iucv.c +++ b/trunk/net/iucv/af_iucv.c @@ -372,6 +372,7 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock, skb_trim(skb, skb->dev->mtu); } skb->protocol = ETH_P_AF_IUCV; + skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF; nskb = skb_clone(skb, GFP_ATOMIC); if (!nskb) return -ENOMEM; diff --git a/trunk/net/l2tp/l2tp_eth.c b/trunk/net/l2tp/l2tp_eth.c index 185f12f4a5fa..443591d629ca 100644 --- a/trunk/net/l2tp/l2tp_eth.c +++ b/trunk/net/l2tp/l2tp_eth.c @@ -162,7 +162,6 @@ static void l2tp_eth_delete(struct l2tp_session *session) if (dev) { unregister_netdev(dev); spriv->dev = NULL; - module_put(THIS_MODULE); } } } @@ -250,7 +249,6 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p if (rc < 0) goto out_del_dev; - __module_get(THIS_MODULE); /* Must be done after register_netdev() */ strlcpy(session->ifname, dev->name, IFNAMSIZ); diff --git a/trunk/net/l2tp/l2tp_ip.c b/trunk/net/l2tp/l2tp_ip.c index 61d8b75d2686..70614e7affab 100644 --- a/trunk/net/l2tp/l2tp_ip.c +++ b/trunk/net/l2tp/l2tp_ip.c @@ -464,12 +464,10 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m sk->sk_bound_dev_if); if (IS_ERR(rt)) goto no_route; - if (connected) { + if (connected) sk_setup_caps(sk, &rt->dst); - } else { - skb_dst_set(skb, &rt->dst); - goto xmit; - } + else + dst_release(&rt->dst); /* safe since we hold rcu_read_lock */ } /* We dont need to clone dst here, it is guaranteed to not disappear. @@ -477,7 +475,6 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m */ skb_dst_set_noref(skb, &rt->dst); -xmit: /* Queue the packet to IP for output */ rc = ip_queue_xmit(skb, &inet->cork.fl); rcu_read_unlock(); diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index d7134c170336..0f45d02e0ba7 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -3100,7 +3100,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, } local->oper_channel = cbss->channel; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); + ieee80211_hw_config(local, 0); if (!have_sta) { u32 rates = 0, basic_rates = 0; diff --git a/trunk/net/netfilter/nf_conntrack_ftp.c b/trunk/net/netfilter/nf_conntrack_ftp.c index 8c5c95c6d34f..44e47c9e14fb 100644 --- a/trunk/net/netfilter/nf_conntrack_ftp.c +++ b/trunk/net/netfilter/nf_conntrack_ftp.c @@ -512,7 +512,6 @@ static int help(struct sk_buff *skb, } static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly; -static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")] __read_mostly; static const struct nf_conntrack_expect_policy ftp_exp_policy = { .max_expected = 1, @@ -541,7 +540,6 @@ static void nf_conntrack_ftp_fini(void) static int __init nf_conntrack_ftp_init(void) { int i, j = -1, ret = 0; - char *tmpname; ftp_buffer = kmalloc(65536, GFP_KERNEL); if (!ftp_buffer) @@ -561,12 +559,10 @@ static int __init nf_conntrack_ftp_init(void) ftp[i][j].expect_policy = &ftp_exp_policy; ftp[i][j].me = THIS_MODULE; ftp[i][j].help = help; - tmpname = &ftp_names[i][j][0]; if (ports[i] == FTP_PORT) - sprintf(tmpname, "ftp"); + sprintf(ftp[i][j].name, "ftp"); else - sprintf(tmpname, "ftp-%d", ports[i]); - ftp[i][j].name = tmpname; + sprintf(ftp[i][j].name, "ftp-%d", ports[i]); pr_debug("nf_ct_ftp: registering helper for pf: %d " "port: %d\n", diff --git a/trunk/net/netfilter/nf_conntrack_h323_main.c b/trunk/net/netfilter/nf_conntrack_h323_main.c index 31f50bc3a312..46d69d7f1bb4 100644 --- a/trunk/net/netfilter/nf_conntrack_h323_main.c +++ b/trunk/net/netfilter/nf_conntrack_h323_main.c @@ -270,8 +270,9 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, return 0; /* RTP port is even */ - rtp_port = port & ~htons(1); - rtcp_port = port | htons(1); + port &= htons(~1); + rtp_port = port; + rtcp_port = htons(ntohs(port) + 1); /* Create expect for RTP */ if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL) diff --git a/trunk/net/netfilter/nf_conntrack_irc.c b/trunk/net/netfilter/nf_conntrack_irc.c index 81366c118271..009c52cfd1ec 100644 --- a/trunk/net/netfilter/nf_conntrack_irc.c +++ b/trunk/net/netfilter/nf_conntrack_irc.c @@ -221,7 +221,6 @@ static int help(struct sk_buff *skb, unsigned int protoff, } static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly; -static char irc_names[MAX_PORTS][sizeof("irc-65535")] __read_mostly; static struct nf_conntrack_expect_policy irc_exp_policy; static void nf_conntrack_irc_fini(void); @@ -229,7 +228,6 @@ static void nf_conntrack_irc_fini(void); static int __init nf_conntrack_irc_init(void) { int i, ret; - char *tmpname; if (max_dcc_channels < 1) { printk(KERN_ERR "nf_ct_irc: max_dcc_channels must not be zero\n"); @@ -255,12 +253,10 @@ static int __init nf_conntrack_irc_init(void) irc[i].me = THIS_MODULE; irc[i].help = help; - tmpname = &irc_names[i][0]; if (ports[i] == IRC_PORT) - sprintf(tmpname, "irc"); + sprintf(irc[i].name, "irc"); else - sprintf(tmpname, "irc-%u", i); - irc[i].name = tmpname; + sprintf(irc[i].name, "irc-%u", i); ret = nf_conntrack_helper_register(&irc[i]); if (ret) { diff --git a/trunk/net/netfilter/nf_conntrack_sane.c b/trunk/net/netfilter/nf_conntrack_sane.c index 8501823b3f9b..ec3fc18c4ef6 100644 --- a/trunk/net/netfilter/nf_conntrack_sane.c +++ b/trunk/net/netfilter/nf_conntrack_sane.c @@ -163,7 +163,6 @@ static int help(struct sk_buff *skb, } static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly; -static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly; static const struct nf_conntrack_expect_policy sane_exp_policy = { .max_expected = 1, @@ -190,7 +189,6 @@ static void nf_conntrack_sane_fini(void) static int __init nf_conntrack_sane_init(void) { int i, j = -1, ret = 0; - char *tmpname; sane_buffer = kmalloc(65536, GFP_KERNEL); if (!sane_buffer) @@ -210,12 +208,10 @@ static int __init nf_conntrack_sane_init(void) sane[i][j].expect_policy = &sane_exp_policy; sane[i][j].me = THIS_MODULE; sane[i][j].help = help; - tmpname = &sane_names[i][j][0]; if (ports[i] == SANE_PORT) - sprintf(tmpname, "sane"); + sprintf(sane[i][j].name, "sane"); else - sprintf(tmpname, "sane-%d", ports[i]); - sane[i][j].name = tmpname; + sprintf(sane[i][j].name, "sane-%d", ports[i]); pr_debug("nf_ct_sane: registering helper for pf: %d " "port: %d\n", diff --git a/trunk/net/netfilter/nf_conntrack_sip.c b/trunk/net/netfilter/nf_conntrack_sip.c index 93faf6a3a637..dfd3ff382243 100644 --- a/trunk/net/netfilter/nf_conntrack_sip.c +++ b/trunk/net/netfilter/nf_conntrack_sip.c @@ -1556,7 +1556,6 @@ static void nf_conntrack_sip_fini(void) static int __init nf_conntrack_sip_init(void) { int i, j, ret; - char *tmpname; if (ports_c == 0) ports[ports_c++] = SIP_PORT; @@ -1584,12 +1583,10 @@ static int __init nf_conntrack_sip_init(void) sip[i][j].expect_class_max = SIP_EXPECT_MAX; sip[i][j].me = THIS_MODULE; - tmpname = &sip_names[i][j][0]; if (ports[i] == SIP_PORT) - sprintf(tmpname, "sip"); + sprintf(sip_names[i][j], "sip"); else - sprintf(tmpname, "sip-%u", i); - sip[i][j].name = tmpname; + sprintf(sip_names[i][j], "sip-%u", i); pr_debug("port #%u: %u\n", i, ports[i]); diff --git a/trunk/net/netfilter/nf_conntrack_tftp.c b/trunk/net/netfilter/nf_conntrack_tftp.c index 75466fd72f4f..81fc61c05263 100644 --- a/trunk/net/netfilter/nf_conntrack_tftp.c +++ b/trunk/net/netfilter/nf_conntrack_tftp.c @@ -92,7 +92,6 @@ static int tftp_help(struct sk_buff *skb, } static struct nf_conntrack_helper tftp[MAX_PORTS][2] __read_mostly; -static char tftp_names[MAX_PORTS][2][sizeof("tftp-65535")] __read_mostly; static const struct nf_conntrack_expect_policy tftp_exp_policy = { .max_expected = 1, @@ -112,7 +111,6 @@ static void nf_conntrack_tftp_fini(void) static int __init nf_conntrack_tftp_init(void) { int i, j, ret; - char *tmpname; if (ports_c == 0) ports[ports_c++] = TFTP_PORT; @@ -129,12 +127,10 @@ static int __init nf_conntrack_tftp_init(void) tftp[i][j].me = THIS_MODULE; tftp[i][j].help = tftp_help; - tmpname = &tftp_names[i][j][0]; if (ports[i] == TFTP_PORT) - sprintf(tmpname, "tftp"); + sprintf(tftp[i][j].name, "tftp"); else - sprintf(tmpname, "tftp-%u", i); - tftp[i][j].name = tmpname; + sprintf(tftp[i][j].name, "tftp-%u", i); ret = nf_conntrack_helper_register(&tftp[i][j]); if (ret) { diff --git a/trunk/net/netfilter/xt_HMARK.c b/trunk/net/netfilter/xt_HMARK.c index 1686ca1b53a1..0a96a43108ed 100644 --- a/trunk/net/netfilter/xt_HMARK.c +++ b/trunk/net/netfilter/xt_HMARK.c @@ -32,13 +32,13 @@ MODULE_ALIAS("ipt_HMARK"); MODULE_ALIAS("ip6t_HMARK"); struct hmark_tuple { - __be32 src; - __be32 dst; + u32 src; + u32 dst; union hmark_ports uports; - u8 proto; + uint8_t proto; }; -static inline __be32 hmark_addr6_mask(const __be32 *addr32, const __be32 *mask) +static inline u32 hmark_addr6_mask(const __u32 *addr32, const __u32 *mask) { return (addr32[0] & mask[0]) ^ (addr32[1] & mask[1]) ^ @@ -46,8 +46,8 @@ static inline __be32 hmark_addr6_mask(const __be32 *addr32, const __be32 *mask) (addr32[3] & mask[3]); } -static inline __be32 -hmark_addr_mask(int l3num, const __be32 *addr32, const __be32 *mask) +static inline u32 +hmark_addr_mask(int l3num, const __u32 *addr32, const __u32 *mask) { switch (l3num) { case AF_INET: @@ -58,22 +58,6 @@ hmark_addr_mask(int l3num, const __be32 *addr32, const __be32 *mask) return 0; } -static inline void hmark_swap_ports(union hmark_ports *uports, - const struct xt_hmark_info *info) -{ - union hmark_ports hp; - u16 src, dst; - - hp.b32 = (uports->b32 & info->port_mask.b32) | info->port_set.b32; - src = ntohs(hp.b16.src); - dst = ntohs(hp.b16.dst); - - if (dst > src) - uports->v32 = (dst << 16) | src; - else - uports->v32 = (src << 16) | dst; -} - static int hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t, const struct xt_hmark_info *info) @@ -90,19 +74,22 @@ hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t, otuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; rtuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; - t->src = hmark_addr_mask(otuple->src.l3num, otuple->src.u3.ip6, - info->src_mask.ip6); - t->dst = hmark_addr_mask(otuple->src.l3num, rtuple->src.u3.ip6, - info->dst_mask.ip6); + t->src = hmark_addr_mask(otuple->src.l3num, otuple->src.u3.all, + info->src_mask.all); + t->dst = hmark_addr_mask(otuple->src.l3num, rtuple->src.u3.all, + info->dst_mask.all); if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)) return 0; t->proto = nf_ct_protonum(ct); if (t->proto != IPPROTO_ICMP) { - t->uports.b16.src = otuple->src.u.all; - t->uports.b16.dst = rtuple->src.u.all; - hmark_swap_ports(&t->uports, info); + t->uports.p16.src = otuple->src.u.all; + t->uports.p16.dst = rtuple->src.u.all; + t->uports.v32 = (t->uports.v32 & info->port_mask.v32) | + info->port_set.v32; + if (t->uports.p16.dst < t->uports.p16.src) + swap(t->uports.p16.dst, t->uports.p16.src); } return 0; @@ -111,19 +98,15 @@ hmark_ct_set_htuple(const struct sk_buff *skb, struct hmark_tuple *t, #endif } -/* This hash function is endian independent, to ensure consistent hashing if - * the cluster is composed of big and little endian systems. */ static inline u32 hmark_hash(struct hmark_tuple *t, const struct xt_hmark_info *info) { u32 hash; - u32 src = ntohl(t->src); - u32 dst = ntohl(t->dst); - if (dst < src) - swap(src, dst); + if (t->dst < t->src) + swap(t->src, t->dst); - hash = jhash_3words(src, dst, t->uports.v32, info->hashrnd); + hash = jhash_3words(t->src, t->dst, t->uports.v32, info->hashrnd); hash = hash ^ (t->proto & info->proto_mask); return (((u64)hash * info->hmodulus) >> 32) + info->hoffset; @@ -143,7 +126,11 @@ hmark_set_tuple_ports(const struct sk_buff *skb, unsigned int nhoff, if (skb_copy_bits(skb, nhoff, &t->uports, sizeof(t->uports)) < 0) return; - hmark_swap_ports(&t->uports, info); + t->uports.v32 = (t->uports.v32 & info->port_mask.v32) | + info->port_set.v32; + + if (t->uports.p16.dst < t->uports.p16.src) + swap(t->uports.p16.dst, t->uports.p16.src); } #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) @@ -191,8 +178,8 @@ hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t, return -1; } noicmp: - t->src = hmark_addr6_mask(ip6->saddr.s6_addr32, info->src_mask.ip6); - t->dst = hmark_addr6_mask(ip6->daddr.s6_addr32, info->dst_mask.ip6); + t->src = hmark_addr6_mask(ip6->saddr.s6_addr32, info->src_mask.all); + t->dst = hmark_addr6_mask(ip6->daddr.s6_addr32, info->dst_mask.all); if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)) return 0; @@ -268,8 +255,11 @@ hmark_pkt_set_htuple_ipv4(const struct sk_buff *skb, struct hmark_tuple *t, } } - t->src = ip->saddr & info->src_mask.ip; - t->dst = ip->daddr & info->dst_mask.ip; + t->src = (__force u32) ip->saddr; + t->dst = (__force u32) ip->daddr; + + t->src &= info->src_mask.ip; + t->dst &= info->dst_mask.ip; if (info->flags & XT_HMARK_FLAG(XT_HMARK_METHOD_L3)) return 0; diff --git a/trunk/net/nfc/llcp/sock.c b/trunk/net/nfc/llcp/sock.c index 2c0b317344b7..30e3cc71be7a 100644 --- a/trunk/net/nfc/llcp/sock.c +++ b/trunk/net/nfc/llcp/sock.c @@ -292,9 +292,6 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, pr_debug("%p\n", sk); - if (llcp_sock == NULL) - return -EBADFD; - addr->sa_family = AF_NFC; *len = sizeof(struct sockaddr_nfc_llcp); diff --git a/trunk/sound/core/compress_offload.c b/trunk/sound/core/compress_offload.c index ec2118d0e27a..a68aed7fce02 100644 --- a/trunk/sound/core/compress_offload.c +++ b/trunk/sound/core/compress_offload.c @@ -502,8 +502,10 @@ static int snd_compr_pause(struct snd_compr_stream *stream) if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) return -EPERM; retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH); - if (!retval) + if (!retval) { stream->runtime->state = SNDRV_PCM_STATE_PAUSED; + wake_up(&stream->runtime->sleep); + } return retval; } @@ -542,10 +544,6 @@ static int snd_compr_stop(struct snd_compr_stream *stream) if (!retval) { stream->runtime->state = SNDRV_PCM_STATE_SETUP; wake_up(&stream->runtime->sleep); - stream->runtime->hw_pointer = 0; - stream->runtime->app_pointer = 0; - stream->runtime->total_bytes_available = 0; - stream->runtime->total_bytes_transferred = 0; } return retval; } diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index 02763827dde0..2b6392be451c 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -2484,9 +2484,9 @@ static void azx_notifier_unregister(struct azx *chip) static int DELAYED_INIT_MARK azx_first_init(struct azx *chip); static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip); -#ifdef SUPPORT_VGA_SWITCHEROO static struct pci_dev __devinit *get_bound_vga(struct pci_dev *pci); +#ifdef SUPPORT_VGA_SWITCHEROO static void azx_vs_set_state(struct pci_dev *pci, enum vga_switcheroo_state state) { @@ -2578,7 +2578,6 @@ static int __devinit register_vga_switcheroo(struct azx *chip) #else #define init_vga_switcheroo(chip) /* NOP */ #define register_vga_switcheroo(chip) 0 -#define check_hdmi_disabled(pci) false #endif /* SUPPORT_VGA_SWITCHER */ /* @@ -2639,7 +2638,6 @@ static int azx_dev_free(struct snd_device *device) return azx_free(device->device_data); } -#ifdef SUPPORT_VGA_SWITCHEROO /* * Check of disabled HDMI controller by vga-switcheroo */ @@ -2672,13 +2670,12 @@ static bool __devinit check_hdmi_disabled(struct pci_dev *pci) struct pci_dev *p = get_bound_vga(pci); if (p) { - if (vga_switcheroo_get_client_state(p) == VGA_SWITCHEROO_OFF) + if (vga_default_device() && p != vga_default_device()) vga_inactive = true; pci_dev_put(p); } return vga_inactive; } -#endif /* SUPPORT_VGA_SWITCHEROO */ /* * white/black-listing for position_fix @@ -3354,11 +3351,6 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, /* Creative X-Fi (CA0110-IBG) */ - /* CTHDA chips */ - { PCI_DEVICE(0x1102, 0x0010), - .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, - { PCI_DEVICE(0x1102, 0x0012), - .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, #if !defined(CONFIG_SND_CTXFI) && !defined(CONFIG_SND_CTXFI_MODULE) /* the following entry conflicts with snd-ctxfi driver, * as ctxfi driver mutates from HD-audio to native mode with @@ -3375,6 +3367,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, #endif + /* CTHDA chips */ + { PCI_DEVICE(0x1102, 0x0010), + .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, + { PCI_DEVICE(0x1102, 0x0012), + .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, /* Vortex86MX */ { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, /* VMware HDAudio */ diff --git a/trunk/sound/pci/hda/patch_conexant.c b/trunk/sound/pci/hda/patch_conexant.c index 172370b3793b..3acb5824ad39 100644 --- a/trunk/sound/pci/hda/patch_conexant.c +++ b/trunk/sound/pci/hda/patch_conexant.c @@ -4061,7 +4061,7 @@ static void cx_auto_init_digital(struct hda_codec *codec) static int cx_auto_init(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; - snd_hda_gen_apply_verbs(codec); + /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ cx_auto_init_output(codec); cx_auto_init_input(codec); cx_auto_init_digital(codec); diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index f8f4906e498d..224410e8e9e7 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -1896,7 +1896,6 @@ static int alc_init(struct hda_codec *codec) alc_fix_pll(codec); alc_auto_init_amp(codec, spec->init_amp); - snd_hda_gen_apply_verbs(codec); alc_init_special_input_src(codec); alc_auto_init_std(codec); @@ -6440,7 +6439,6 @@ enum { ALC662_FIXUP_ASUS_MODE7, ALC662_FIXUP_ASUS_MODE8, ALC662_FIXUP_NO_JACK_DETECT, - ALC662_FIXUP_ZOTAC_Z68, }; static const struct alc_fixup alc662_fixups[] = { @@ -6590,13 +6588,6 @@ static const struct alc_fixup alc662_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc_fixup_no_jack_detect, }, - [ALC662_FIXUP_ZOTAC_Z68] = { - .type = ALC_FIXUP_PINS, - .v.pins = (const struct alc_pincfg[]) { - { 0x1b, 0x02214020 }, /* Front HP */ - { } - } - }, }; static const struct snd_pci_quirk alc662_fixup_tbl[] = { @@ -6610,7 +6601,6 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), - SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68), SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T), #if 0 diff --git a/trunk/sound/soc/codecs/wm2000.c b/trunk/sound/soc/codecs/wm2000.c index 0418fa11e6bd..a75c3766aede 100644 --- a/trunk/sound/soc/codecs/wm2000.c +++ b/trunk/sound/soc/codecs/wm2000.c @@ -99,9 +99,8 @@ static void wm2000_reset(struct wm2000_priv *wm2000) } static int wm2000_poll_bit(struct i2c_client *i2c, - unsigned int reg, u8 mask) + unsigned int reg, u8 mask, int timeout) { - int timeout = 4000; int val; val = wm2000_read(i2c, reg); @@ -120,7 +119,7 @@ static int wm2000_poll_bit(struct i2c_client *i2c, static int wm2000_power_up(struct i2c_client *i2c, int analogue) { struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); - int ret; + int ret, timeout; BUG_ON(wm2000->anc_mode != ANC_OFF); @@ -141,13 +140,13 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) /* Wait for ANC engine to become ready */ if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, - WM2000_ANC_ENG_IDLE)) { + WM2000_ANC_ENG_IDLE, 1)) { dev_err(&i2c->dev, "ANC engine failed to reset\n"); return -ETIMEDOUT; } if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_BOOT_COMPLETE)) { + WM2000_STATUS_BOOT_COMPLETE, 1)) { dev_err(&i2c->dev, "ANC engine failed to initialise\n"); return -ETIMEDOUT; } @@ -174,13 +173,16 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) dev_dbg(&i2c->dev, "Download complete\n"); if (analogue) { - wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, 248 / 4); + timeout = 248; + wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4); wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_ANA_SEQ_INCLUDE | WM2000_MODE_MOUSE_ENABLE | WM2000_MODE_THERMAL_ENABLE); } else { + timeout = 10; + wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_MOUSE_ENABLE | WM2000_MODE_THERMAL_ENABLE); @@ -199,8 +201,9 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_MOUSE_ACTIVE)) { - dev_err(&i2c->dev, "Timed out waiting for device\n"); + WM2000_STATUS_MOUSE_ACTIVE, timeout)) { + dev_err(&i2c->dev, "Timed out waiting for device after %dms\n", + timeout * 10); return -ETIMEDOUT; } @@ -215,25 +218,28 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) static int wm2000_power_down(struct i2c_client *i2c, int analogue) { struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); + int timeout; if (analogue) { - wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, 248 / 4); + timeout = 248; + wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4); wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_ANA_SEQ_INCLUDE | WM2000_MODE_POWER_DOWN); } else { + timeout = 10; wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_POWER_DOWN); } if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_POWER_DOWN_COMPLETE)) { + WM2000_STATUS_POWER_DOWN_COMPLETE, timeout)) { dev_err(&i2c->dev, "Timeout waiting for ANC power down\n"); return -ETIMEDOUT; } if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, - WM2000_ANC_ENG_IDLE)) { + WM2000_ANC_ENG_IDLE, 1)) { dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n"); return -ETIMEDOUT; } @@ -262,13 +268,13 @@ static int wm2000_enter_bypass(struct i2c_client *i2c, int analogue) } if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_ANC_DISABLED)) { + WM2000_STATUS_ANC_DISABLED, 10)) { dev_err(&i2c->dev, "Timeout waiting for ANC disable\n"); return -ETIMEDOUT; } if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, - WM2000_ANC_ENG_IDLE)) { + WM2000_ANC_ENG_IDLE, 1)) { dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n"); return -ETIMEDOUT; } @@ -305,7 +311,7 @@ static int wm2000_exit_bypass(struct i2c_client *i2c, int analogue) wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_MOUSE_ACTIVE)) { + WM2000_STATUS_MOUSE_ACTIVE, 10)) { dev_err(&i2c->dev, "Timed out waiting for MOUSE\n"); return -ETIMEDOUT; } @@ -319,32 +325,38 @@ static int wm2000_exit_bypass(struct i2c_client *i2c, int analogue) static int wm2000_enter_standby(struct i2c_client *i2c, int analogue) { struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); + int timeout; BUG_ON(wm2000->anc_mode != ANC_ACTIVE); if (analogue) { - wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, 248 / 4); + timeout = 248; + wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4); wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_ANA_SEQ_INCLUDE | WM2000_MODE_THERMAL_ENABLE | WM2000_MODE_STANDBY_ENTRY); } else { + timeout = 10; + wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_THERMAL_ENABLE | WM2000_MODE_STANDBY_ENTRY); } if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_ANC_DISABLED)) { + WM2000_STATUS_ANC_DISABLED, timeout)) { dev_err(&i2c->dev, "Timed out waiting for ANC disable after 1ms\n"); return -ETIMEDOUT; } - if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, WM2000_ANC_ENG_IDLE)) { + if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, WM2000_ANC_ENG_IDLE, + 1)) { dev_err(&i2c->dev, - "Timed out waiting for standby\n"); + "Timed out waiting for standby after %dms\n", + timeout * 10); return -ETIMEDOUT; } @@ -362,19 +374,23 @@ static int wm2000_enter_standby(struct i2c_client *i2c, int analogue) static int wm2000_exit_standby(struct i2c_client *i2c, int analogue) { struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); + int timeout; BUG_ON(wm2000->anc_mode != ANC_STANDBY); wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0); if (analogue) { - wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, 248 / 4); + timeout = 248; + wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4); wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_ANA_SEQ_INCLUDE | WM2000_MODE_THERMAL_ENABLE | WM2000_MODE_MOUSE_ENABLE); } else { + timeout = 10; + wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL, WM2000_MODE_THERMAL_ENABLE | WM2000_MODE_MOUSE_ENABLE); @@ -384,8 +400,9 @@ static int wm2000_exit_standby(struct i2c_client *i2c, int analogue) wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR); if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, - WM2000_STATUS_MOUSE_ACTIVE)) { - dev_err(&i2c->dev, "Timed out waiting for MOUSE\n"); + WM2000_STATUS_MOUSE_ACTIVE, timeout)) { + dev_err(&i2c->dev, "Timed out waiting for MOUSE after %dms\n", + timeout * 10); return -ETIMEDOUT; } diff --git a/trunk/sound/soc/codecs/wm8994.c b/trunk/sound/soc/codecs/wm8994.c index aa8c98b628da..993639d694ce 100644 --- a/trunk/sound/soc/codecs/wm8994.c +++ b/trunk/sound/soc/codecs/wm8994.c @@ -46,39 +46,6 @@ #define WM8994_NUM_DRC 3 #define WM8994_NUM_EQ 3 -static struct { - unsigned int reg; - unsigned int mask; -} wm8994_vu_bits[] = { - { WM8994_LEFT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, - { WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, - { WM8994_LEFT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, - { WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, - { WM8994_SPEAKER_VOLUME_LEFT, WM8994_SPKOUT_VU }, - { WM8994_SPEAKER_VOLUME_RIGHT, WM8994_SPKOUT_VU }, - { WM8994_LEFT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, - { WM8994_RIGHT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, - { WM8994_LEFT_OPGA_VOLUME, WM8994_MIXOUT_VU }, - { WM8994_RIGHT_OPGA_VOLUME, WM8994_MIXOUT_VU }, - - { WM8994_AIF1_DAC1_LEFT_VOLUME, WM8994_AIF1DAC1_VU }, - { WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU }, - { WM8994_AIF1_DAC2_LEFT_VOLUME, WM8994_AIF1DAC2_VU }, - { WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU }, - { WM8994_AIF2_DAC_LEFT_VOLUME, WM8994_AIF2DAC_VU }, - { WM8994_AIF2_DAC_RIGHT_VOLUME, WM8994_AIF2DAC_VU }, - { WM8994_AIF1_ADC1_LEFT_VOLUME, WM8994_AIF1ADC1_VU }, - { WM8994_AIF1_ADC1_RIGHT_VOLUME, WM8994_AIF1ADC1_VU }, - { WM8994_AIF1_ADC2_LEFT_VOLUME, WM8994_AIF1ADC2_VU }, - { WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, - { WM8994_AIF2_ADC_LEFT_VOLUME, WM8994_AIF2ADC_VU }, - { WM8994_AIF2_ADC_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, - { WM8994_DAC1_LEFT_VOLUME, WM8994_DAC1_VU }, - { WM8994_DAC1_RIGHT_VOLUME, WM8994_DAC1_VU }, - { WM8994_DAC2_LEFT_VOLUME, WM8994_DAC2_VU }, - { WM8994_DAC2_RIGHT_VOLUME, WM8994_DAC2_VU }, -}; - static int wm8994_drc_base[] = { WM8994_AIF1_DRC1_1, WM8994_AIF1_DRC2_1, @@ -1022,7 +989,6 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = w->codec; struct wm8994 *control = codec->control_data; int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; - int i; int dac; int adc; int val; @@ -1081,13 +1047,6 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, WM8994_AIF1DAC2L_ENA); break; - case SND_SOC_DAPM_POST_PMU: - for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) - snd_soc_write(codec, wm8994_vu_bits[i].reg, - snd_soc_read(codec, - wm8994_vu_bits[i].reg)); - break; - case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, @@ -1113,7 +1072,6 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - int i; int dac; int adc; int val; @@ -1164,13 +1122,6 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, WM8994_AIF2DACR_ENA); break; - case SND_SOC_DAPM_POST_PMU: - for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) - snd_soc_write(codec, wm8994_vu_bits[i].reg, - snd_soc_read(codec, - wm8994_vu_bits[i].reg)); - break; - case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, @@ -1239,19 +1190,17 @@ static int late_enable_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: if (wm8994->aif1clk_enable) { - aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); + aif1clk_ev(w, kcontrol, event); snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, WM8994_AIF1CLK_ENA_MASK, WM8994_AIF1CLK_ENA); - aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); wm8994->aif1clk_enable = 0; } if (wm8994->aif2clk_enable) { - aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); + aif2clk_ev(w, kcontrol, event); snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, WM8994_AIF2CLK_ENA_MASK, WM8994_AIF2CLK_ENA); - aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); wm8994->aif2clk_enable = 0; } break; @@ -1272,17 +1221,15 @@ static int late_disable_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMD: if (wm8994->aif1clk_disable) { - aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, WM8994_AIF1CLK_ENA_MASK, 0); - aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); + aif1clk_ev(w, kcontrol, event); wm8994->aif1clk_disable = 0; } if (wm8994->aif2clk_disable) { - aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, WM8994_AIF2CLK_ENA_MASK, 0); - aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); + aif2clk_ev(w, kcontrol, event); wm8994->aif2clk_disable = 0; } break; @@ -1580,11 +1527,9 @@ SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, aif1clk_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), @@ -3934,11 +3879,39 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) pm_runtime_put(codec->dev); - /* Latch volume update bits */ - for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) - snd_soc_update_bits(codec, wm8994_vu_bits[i].reg, - wm8994_vu_bits[i].mask, - wm8994_vu_bits[i].mask); + /* Latch volume updates (right only; we always do left then right). */ + snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, + WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); + snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, + WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); + snd_soc_update_bits(codec, WM8994_AIF1_DAC2_LEFT_VOLUME, + WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); + snd_soc_update_bits(codec, WM8994_AIF1_DAC2_RIGHT_VOLUME, + WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); + snd_soc_update_bits(codec, WM8994_AIF2_DAC_LEFT_VOLUME, + WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); + snd_soc_update_bits(codec, WM8994_AIF2_DAC_RIGHT_VOLUME, + WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); + snd_soc_update_bits(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, + WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); + snd_soc_update_bits(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, + WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); + snd_soc_update_bits(codec, WM8994_AIF1_ADC2_LEFT_VOLUME, + WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); + snd_soc_update_bits(codec, WM8994_AIF1_ADC2_RIGHT_VOLUME, + WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); + snd_soc_update_bits(codec, WM8994_AIF2_ADC_LEFT_VOLUME, + WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); + snd_soc_update_bits(codec, WM8994_AIF2_ADC_RIGHT_VOLUME, + WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); + snd_soc_update_bits(codec, WM8994_DAC1_LEFT_VOLUME, + WM8994_DAC1_VU, WM8994_DAC1_VU); + snd_soc_update_bits(codec, WM8994_DAC1_RIGHT_VOLUME, + WM8994_DAC1_VU, WM8994_DAC1_VU); + snd_soc_update_bits(codec, WM8994_DAC2_LEFT_VOLUME, + WM8994_DAC2_VU, WM8994_DAC2_VU); + snd_soc_update_bits(codec, WM8994_DAC2_RIGHT_VOLUME, + WM8994_DAC2_VU, WM8994_DAC2_VU); /* Set the low bit of the 3D stereo depth so TLV matches */ snd_soc_update_bits(codec, WM8994_AIF1_DAC1_FILTERS_2, diff --git a/trunk/sound/soc/fsl/imx-audmux.c b/trunk/sound/soc/fsl/imx-audmux.c index 080327414c6b..f23700359c67 100644 --- a/trunk/sound/soc/fsl/imx-audmux.c +++ b/trunk/sound/soc/fsl/imx-audmux.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "imx-audmux.h" @@ -250,7 +249,6 @@ EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port); static int __devinit imx_audmux_probe(struct platform_device *pdev) { struct resource *res; - struct pinctrl *pinctrl; const struct of_device_id *of_id = of_match_device(imx_audmux_dt_ids, &pdev->dev); @@ -259,12 +257,6 @@ static int __devinit imx_audmux_probe(struct platform_device *pdev) if (!audmux_base) return -EADDRNOTAVAIL; - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - dev_err(&pdev->dev, "setup pinctrl failed!"); - return PTR_ERR(pinctrl); - } - audmux_clk = clk_get(&pdev->dev, "audmux"); if (IS_ERR(audmux_clk)) { dev_dbg(&pdev->dev, "cannot get clock: %ld\n", diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index 89eae93445cf..90ee77d2409d 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -913,7 +913,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget, /* do we need to add this widget to the list ? */ if (list) { int err; - err = dapm_list_add_widget(list, path->source); + err = dapm_list_add_widget(list, path->sink); if (err < 0) { dev_err(widget->dapm->dev, "could not add widget %s\n", widget->name); @@ -954,7 +954,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, if (stream == SNDRV_PCM_STREAM_PLAYBACK) paths = is_connected_output_ep(dai->playback_widget, list); else - paths = is_connected_input_ep(dai->capture_widget, list); + paths = is_connected_input_ep(dai->playback_widget, list); trace_snd_soc_dapm_connected(paths, stream); dapm_clear_walk(&card->dapm); diff --git a/trunk/sound/soc/soc-pcm.c b/trunk/sound/soc/soc-pcm.c index 48fd15b312c1..bedd1717a373 100644 --- a/trunk/sound/soc/soc-pcm.c +++ b/trunk/sound/soc/soc-pcm.c @@ -794,9 +794,6 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, for (i = 0; i < card->num_links; i++) { be = &card->rtd[i]; - if (!be->dai_link->no_pcm) - continue; - if (be->cpu_dai->playback_widget == widget || be->codec_dai->playback_widget == widget) return be; @@ -806,9 +803,6 @@ static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card, for (i = 0; i < card->num_links; i++) { be = &card->rtd[i]; - if (!be->dai_link->no_pcm) - continue; - if (be->cpu_dai->capture_widget == widget || be->codec_dai->capture_widget == widget) return be; diff --git a/trunk/sound/soc/tegra/tegra30_ahub.c b/trunk/sound/soc/tegra/tegra30_ahub.c index f43edb364a18..57cd419f743e 100644 --- a/trunk/sound/soc/tegra/tegra30_ahub.c +++ b/trunk/sound/soc/tegra/tegra30_ahub.c @@ -629,4 +629,3 @@ MODULE_AUTHOR("Stephen Warren "); MODULE_DESCRIPTION("Tegra30 AHUB driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRV_NAME); -MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match); diff --git a/trunk/sound/usb/card.h b/trunk/sound/usb/card.h index 2b9fffff23b6..0d37238b8457 100644 --- a/trunk/sound/usb/card.h +++ b/trunk/sound/usb/card.h @@ -119,7 +119,6 @@ struct snd_usb_substream { unsigned long unlink_mask; /* bitmask of unlinked urbs */ /* data and sync endpoints for this stream */ - unsigned int ep_num; /* the endpoint number */ struct snd_usb_endpoint *data_endpoint; struct snd_usb_endpoint *sync_endpoint; unsigned long flags; diff --git a/trunk/sound/usb/stream.c b/trunk/sound/usb/stream.c index 083ed81160e5..6b7d7a2b7baa 100644 --- a/trunk/sound/usb/stream.c +++ b/trunk/sound/usb/stream.c @@ -97,7 +97,6 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, subs->formats |= fp->formats; subs->num_formats++; subs->fmt_type = fp->fmt_type; - subs->ep_num = fp->endpoint; } /* @@ -120,7 +119,9 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, if (as->fmt_type != fp->fmt_type) continue; subs = &as->substream[stream]; - if (subs->ep_num == fp->endpoint) { + if (!subs->data_endpoint) + continue; + if (subs->data_endpoint->ep_num == fp->endpoint) { list_add_tail(&fp->list, &subs->fmt_list); subs->num_formats++; subs->formats |= fp->formats; @@ -133,7 +134,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip, if (as->fmt_type != fp->fmt_type) continue; subs = &as->substream[stream]; - if (subs->ep_num) + if (subs->data_endpoint) continue; err = snd_pcm_new_stream(as->pcm, stream, 1); if (err < 0) diff --git a/trunk/tools/perf/MANIFEST b/trunk/tools/perf/MANIFEST index b4b572e8c100..5476bc0a1eac 100644 --- a/trunk/tools/perf/MANIFEST +++ b/trunk/tools/perf/MANIFEST @@ -1,6 +1,4 @@ tools/perf -tools/scripts -tools/lib/traceevent include/linux/const.h include/linux/perf_event.h include/linux/rbtree.h diff --git a/trunk/tools/perf/builtin-report.c b/trunk/tools/perf/builtin-report.c index 25249f76329d..8c767c6bca91 100644 --- a/trunk/tools/perf/builtin-report.c +++ b/trunk/tools/perf/builtin-report.c @@ -152,7 +152,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, if (symbol_conf.use_callchain) { err = callchain_append(he->callchain, - &callchain_cursor, + &evsel->hists.callchain_cursor, sample->period); if (err) return err; @@ -162,7 +162,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, * so we don't allocated the extra space needed because the stdio * code will not use it. */ - if (he->ms.sym != NULL && use_browser > 0) { + if (al->sym != NULL && use_browser > 0) { struct annotation *notes = symbol__annotation(he->ms.sym); assert(evsel != NULL); diff --git a/trunk/tools/perf/builtin-stat.c b/trunk/tools/perf/builtin-stat.c index 262589991ea4..62ae30d34fa6 100644 --- a/trunk/tools/perf/builtin-stat.c +++ b/trunk/tools/perf/builtin-stat.c @@ -1129,7 +1129,7 @@ static int add_default_attributes(void) return 0; if (!evsel_list->nr_entries) { - if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0) + if (perf_evlist__add_attrs_array(evsel_list, default_attrs) < 0) return -1; } @@ -1139,21 +1139,21 @@ static int add_default_attributes(void) return 0; /* Append detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) + if (perf_evlist__add_attrs_array(evsel_list, detailed_attrs) < 0) return -1; if (detailed_run < 2) return 0; /* Append very detailed run extra attributes: */ - if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) + if (perf_evlist__add_attrs_array(evsel_list, very_detailed_attrs) < 0) return -1; if (detailed_run < 3) return 0; /* Append very, very detailed run extra attributes: */ - return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); + return perf_evlist__add_attrs_array(evsel_list, very_very_detailed_attrs); } int cmd_stat(int argc, const char **argv, const char *prefix __used) diff --git a/trunk/tools/perf/builtin-top.c b/trunk/tools/perf/builtin-top.c index 6bb0277b7dfe..871b540293e1 100644 --- a/trunk/tools/perf/builtin-top.c +++ b/trunk/tools/perf/builtin-top.c @@ -787,7 +787,7 @@ static void perf_event__process_sample(struct perf_tool *tool, } if (symbol_conf.use_callchain) { - err = callchain_append(he->callchain, &callchain_cursor, + err = callchain_append(he->callchain, &evsel->hists.callchain_cursor, sample->period); if (err) return; diff --git a/trunk/tools/perf/design.txt b/trunk/tools/perf/design.txt index 67e5d0cace85..bd0bb1b1279b 100644 --- a/trunk/tools/perf/design.txt +++ b/trunk/tools/perf/design.txt @@ -409,15 +409,14 @@ Counters can be enabled and disabled in two ways: via ioctl and via prctl. When a counter is disabled, it doesn't count or generate events but does continue to exist and maintain its count value. -An individual counter can be enabled with +An individual counter or counter group can be enabled with - ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); + ioctl(fd, PERF_EVENT_IOC_ENABLE); or disabled with - ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); + ioctl(fd, PERF_EVENT_IOC_DISABLE); -For a counter group, pass PERF_IOC_FLAG_GROUP as the third argument. Enabling or disabling the leader of a group enables or disables the whole group; that is, while the group leader is disabled, none of the counters in the group will count. Enabling or disabling a member of a diff --git a/trunk/tools/perf/ui/browsers/annotate.c b/trunk/tools/perf/ui/browsers/annotate.c index 34b1c46eaf42..4deea6aaf927 100644 --- a/trunk/tools/perf/ui/browsers/annotate.c +++ b/trunk/tools/perf/ui/browsers/annotate.c @@ -668,7 +668,7 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx, "q/ESC/CTRL+C Exit\n\n" "-> Go to target\n" "<- Exit\n" - "H Cycle thru hottest instructions\n" + "h Cycle thru hottest instructions\n" "j Toggle showing jump to target arrows\n" "J Toggle showing number of jump sources on targets\n" "n Search next string\n" diff --git a/trunk/tools/perf/util/PERF-VERSION-GEN b/trunk/tools/perf/util/PERF-VERSION-GEN index 95264f304179..ad73300f7bac 100755 --- a/trunk/tools/perf/util/PERF-VERSION-GEN +++ b/trunk/tools/perf/util/PERF-VERSION-GEN @@ -12,7 +12,7 @@ LF=' # First check if there is a .git to get the version from git describe # otherwise try to get the version from the kernel makefile if test -d ../../.git -o -f ../../.git && - VN=$(git describe --match 'v[0-9].[0-9]*' --abbrev=4 HEAD 2>/dev/null) && + VN=$(git describe --abbrev=4 HEAD 2>/dev/null) && case "$VN" in *$LF*) (exit 1) ;; v[0-9]*) diff --git a/trunk/tools/perf/util/callchain.c b/trunk/tools/perf/util/callchain.c index 3a6bff47614f..9f7106a8d9a4 100644 --- a/trunk/tools/perf/util/callchain.c +++ b/trunk/tools/perf/util/callchain.c @@ -18,8 +18,6 @@ #include "util.h" #include "callchain.h" -__thread struct callchain_cursor callchain_cursor; - bool ip_callchain__valid(struct ip_callchain *chain, const union perf_event *event) { diff --git a/trunk/tools/perf/util/callchain.h b/trunk/tools/perf/util/callchain.h index 3bdb407f9cd9..7f9c0f1ae3a9 100644 --- a/trunk/tools/perf/util/callchain.h +++ b/trunk/tools/perf/util/callchain.h @@ -76,8 +76,6 @@ struct callchain_cursor { struct callchain_cursor_node *curr; }; -extern __thread struct callchain_cursor callchain_cursor; - static inline void callchain_init(struct callchain_root *root) { INIT_LIST_HEAD(&root->node.siblings); diff --git a/trunk/tools/perf/util/evlist.c b/trunk/tools/perf/util/evlist.c index 7400fb3fc50c..4ac5f5ae4ce9 100644 --- a/trunk/tools/perf/util/evlist.c +++ b/trunk/tools/perf/util/evlist.c @@ -159,17 +159,6 @@ int perf_evlist__add_attrs(struct perf_evlist *evlist, return -1; } -int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs) -{ - size_t i; - - for (i = 0; i < nr_attrs; i++) - event_attr_init(attrs + i); - - return perf_evlist__add_attrs(evlist, attrs, nr_attrs); -} - static int trace_event__id(const char *evname) { char *filename, *colon; @@ -274,8 +263,7 @@ void perf_evlist__disable(struct perf_evlist *evlist) for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { list_for_each_entry(pos, &evlist->entries, node) { for (thread = 0; thread < evlist->threads->nr; thread++) - ioctl(FD(pos, cpu, thread), - PERF_EVENT_IOC_DISABLE, 0); + ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_DISABLE); } } } @@ -288,8 +276,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { list_for_each_entry(pos, &evlist->entries, node) { for (thread = 0; thread < evlist->threads->nr; thread++) - ioctl(FD(pos, cpu, thread), - PERF_EVENT_IOC_ENABLE, 0); + ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_ENABLE); } } } diff --git a/trunk/tools/perf/util/evlist.h b/trunk/tools/perf/util/evlist.h index 989bee9624c2..58abb63ac13a 100644 --- a/trunk/tools/perf/util/evlist.h +++ b/trunk/tools/perf/util/evlist.h @@ -54,8 +54,6 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); int perf_evlist__add_default(struct perf_evlist *evlist); int perf_evlist__add_attrs(struct perf_evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs); -int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, - struct perf_event_attr *attrs, size_t nr_attrs); int perf_evlist__add_tracepoints(struct perf_evlist *evlist, const char *tracepoints[], size_t nr_tracepoints); int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, @@ -64,8 +62,6 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, #define perf_evlist__add_attrs_array(evlist, array) \ perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array)) -#define perf_evlist__add_default_attrs(evlist, array) \ - __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) #define perf_evlist__add_tracepoints_array(evlist, array) \ perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array)) diff --git a/trunk/tools/perf/util/evsel.c b/trunk/tools/perf/util/evsel.c index 9f6cebd798ee..91d19138f3ec 100644 --- a/trunk/tools/perf/util/evsel.c +++ b/trunk/tools/perf/util/evsel.c @@ -494,24 +494,16 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel, } static int perf_event__parse_id_sample(const union perf_event *event, u64 type, - struct perf_sample *sample, - bool swapped) + struct perf_sample *sample) { const u64 *array = event->sample.array; - union u64_swap u; array += ((event->header.size - sizeof(event->header)) / sizeof(u64)) - 1; if (type & PERF_SAMPLE_CPU) { - u.val64 = *array; - if (swapped) { - /* undo swap of u64, then swap on individual u32s */ - u.val64 = bswap_64(u.val64); - u.val32[0] = bswap_32(u.val32[0]); - } - - sample->cpu = u.val32[0]; + u32 *p = (u32 *)array; + sample->cpu = *p; array--; } @@ -531,16 +523,9 @@ static int perf_event__parse_id_sample(const union perf_event *event, u64 type, } if (type & PERF_SAMPLE_TID) { - u.val64 = *array; - if (swapped) { - /* undo swap of u64, then swap on individual u32s */ - u.val64 = bswap_64(u.val64); - u.val32[0] = bswap_32(u.val32[0]); - u.val32[1] = bswap_32(u.val32[1]); - } - - sample->pid = u.val32[0]; - sample->tid = u.val32[1]; + u32 *p = (u32 *)array; + sample->pid = p[0]; + sample->tid = p[1]; } return 0; @@ -577,7 +562,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, if (event->header.type != PERF_RECORD_SAMPLE) { if (!sample_id_all) return 0; - return perf_event__parse_id_sample(event, type, data, swapped); + return perf_event__parse_id_sample(event, type, data); } array = event->sample.array; diff --git a/trunk/tools/perf/util/hist.c b/trunk/tools/perf/util/hist.c index 514e2a4b367d..1293b5ebea4d 100644 --- a/trunk/tools/perf/util/hist.c +++ b/trunk/tools/perf/util/hist.c @@ -378,7 +378,7 @@ void hist_entry__free(struct hist_entry *he) * collapse the histogram */ -static bool hists__collapse_insert_entry(struct hists *hists __used, +static bool hists__collapse_insert_entry(struct hists *hists, struct rb_root *root, struct hist_entry *he) { @@ -397,9 +397,8 @@ static bool hists__collapse_insert_entry(struct hists *hists __used, iter->period += he->period; iter->nr_events += he->nr_events; if (symbol_conf.use_callchain) { - callchain_cursor_reset(&callchain_cursor); - callchain_merge(&callchain_cursor, - iter->callchain, + callchain_cursor_reset(&hists->callchain_cursor); + callchain_merge(&hists->callchain_cursor, iter->callchain, he->callchain); } hist_entry__free(he); diff --git a/trunk/tools/perf/util/hist.h b/trunk/tools/perf/util/hist.h index 34bb556d6219..cfc64e293f90 100644 --- a/trunk/tools/perf/util/hist.h +++ b/trunk/tools/perf/util/hist.h @@ -67,6 +67,8 @@ struct hists { struct events_stats stats; u64 event_stream; u16 col_len[HISTC_NR_COLS]; + /* Best would be to reuse the session callchain cursor */ + struct callchain_cursor callchain_cursor; }; struct hist_entry *__hists__add_entry(struct hists *self, diff --git a/trunk/tools/perf/util/pager.c b/trunk/tools/perf/util/pager.c index 3322b8446e89..1915de20dcac 100644 --- a/trunk/tools/perf/util/pager.c +++ b/trunk/tools/perf/util/pager.c @@ -57,10 +57,6 @@ void setup_pager(void) } if (!pager) pager = getenv("PAGER"); - if (!pager) { - if (!access("/usr/bin/pager", X_OK)) - pager = "/usr/bin/pager"; - } if (!pager) pager = "less"; else if (!*pager || !strcmp(pager, "cat")) diff --git a/trunk/tools/perf/util/probe-event.c b/trunk/tools/perf/util/probe-event.c index 0dda25d82d06..59dccc98b554 100644 --- a/trunk/tools/perf/util/probe-event.c +++ b/trunk/tools/perf/util/probe-event.c @@ -2164,12 +2164,16 @@ int del_perf_probe_events(struct strlist *dellist) error: if (kfd >= 0) { - strlist__delete(namelist); + if (namelist) + strlist__delete(namelist); + close(kfd); } if (ufd >= 0) { - strlist__delete(unamelist); + if (unamelist) + strlist__delete(unamelist); + close(ufd); } diff --git a/trunk/tools/perf/util/session.c b/trunk/tools/perf/util/session.c index 2600916efa83..93d355d27109 100644 --- a/trunk/tools/perf/util/session.c +++ b/trunk/tools/perf/util/session.c @@ -288,8 +288,7 @@ struct branch_info *machine__resolve_bstack(struct machine *self, return bi; } -int machine__resolve_callchain(struct machine *self, - struct perf_evsel *evsel __used, +int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, struct thread *thread, struct ip_callchain *chain, struct symbol **parent) @@ -298,12 +297,7 @@ int machine__resolve_callchain(struct machine *self, unsigned int i; int err; - callchain_cursor_reset(&callchain_cursor); - - if (chain->nr > PERF_MAX_STACK_DEPTH) { - pr_warning("corrupted callchain. skipping...\n"); - return 0; - } + callchain_cursor_reset(&evsel->hists.callchain_cursor); for (i = 0; i < chain->nr; i++) { u64 ip; @@ -323,14 +317,7 @@ int machine__resolve_callchain(struct machine *self, case PERF_CONTEXT_USER: cpumode = PERF_RECORD_MISC_USER; break; default: - pr_debug("invalid callchain context: " - "%"PRId64"\n", (s64) ip); - /* - * It seems the callchain is corrupted. - * Discard all. - */ - callchain_cursor_reset(&callchain_cursor); - return 0; + break; } continue; } @@ -346,7 +333,7 @@ int machine__resolve_callchain(struct machine *self, break; } - err = callchain_cursor_append(&callchain_cursor, + err = callchain_cursor_append(&evsel->hists.callchain_cursor, ip, al.map, al.sym); if (err) return err; @@ -454,65 +441,37 @@ void mem_bswap_64(void *src, int byte_size) } } -static void swap_sample_id_all(union perf_event *event, void *data) -{ - void *end = (void *) event + event->header.size; - int size = end - data; - - BUG_ON(size % sizeof(u64)); - mem_bswap_64(data, size); -} - -static void perf_event__all64_swap(union perf_event *event, - bool sample_id_all __used) +static void perf_event__all64_swap(union perf_event *event) { struct perf_event_header *hdr = &event->header; mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); } -static void perf_event__comm_swap(union perf_event *event, bool sample_id_all) +static void perf_event__comm_swap(union perf_event *event) { event->comm.pid = bswap_32(event->comm.pid); event->comm.tid = bswap_32(event->comm.tid); - - if (sample_id_all) { - void *data = &event->comm.comm; - - data += ALIGN(strlen(data) + 1, sizeof(u64)); - swap_sample_id_all(event, data); - } } -static void perf_event__mmap_swap(union perf_event *event, - bool sample_id_all) +static void perf_event__mmap_swap(union perf_event *event) { event->mmap.pid = bswap_32(event->mmap.pid); event->mmap.tid = bswap_32(event->mmap.tid); event->mmap.start = bswap_64(event->mmap.start); event->mmap.len = bswap_64(event->mmap.len); event->mmap.pgoff = bswap_64(event->mmap.pgoff); - - if (sample_id_all) { - void *data = &event->mmap.filename; - - data += ALIGN(strlen(data) + 1, sizeof(u64)); - swap_sample_id_all(event, data); - } } -static void perf_event__task_swap(union perf_event *event, bool sample_id_all) +static void perf_event__task_swap(union perf_event *event) { event->fork.pid = bswap_32(event->fork.pid); event->fork.tid = bswap_32(event->fork.tid); event->fork.ppid = bswap_32(event->fork.ppid); event->fork.ptid = bswap_32(event->fork.ptid); event->fork.time = bswap_64(event->fork.time); - - if (sample_id_all) - swap_sample_id_all(event, &event->fork + 1); } -static void perf_event__read_swap(union perf_event *event, bool sample_id_all) +static void perf_event__read_swap(union perf_event *event) { event->read.pid = bswap_32(event->read.pid); event->read.tid = bswap_32(event->read.tid); @@ -520,9 +479,6 @@ static void perf_event__read_swap(union perf_event *event, bool sample_id_all) event->read.time_enabled = bswap_64(event->read.time_enabled); event->read.time_running = bswap_64(event->read.time_running); event->read.id = bswap_64(event->read.id); - - if (sample_id_all) - swap_sample_id_all(event, &event->read + 1); } static u8 revbyte(u8 b) @@ -574,8 +530,7 @@ void perf_event__attr_swap(struct perf_event_attr *attr) swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); } -static void perf_event__hdr_attr_swap(union perf_event *event, - bool sample_id_all __used) +static void perf_event__hdr_attr_swap(union perf_event *event) { size_t size; @@ -586,21 +541,18 @@ static void perf_event__hdr_attr_swap(union perf_event *event, mem_bswap_64(event->attr.id, size); } -static void perf_event__event_type_swap(union perf_event *event, - bool sample_id_all __used) +static void perf_event__event_type_swap(union perf_event *event) { event->event_type.event_type.event_id = bswap_64(event->event_type.event_type.event_id); } -static void perf_event__tracing_data_swap(union perf_event *event, - bool sample_id_all __used) +static void perf_event__tracing_data_swap(union perf_event *event) { event->tracing_data.size = bswap_32(event->tracing_data.size); } -typedef void (*perf_event__swap_op)(union perf_event *event, - bool sample_id_all); +typedef void (*perf_event__swap_op)(union perf_event *event); static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_MMAP] = perf_event__mmap_swap, @@ -1034,15 +986,6 @@ static int perf_session__process_user_event(struct perf_session *session, union } } -static void event_swap(union perf_event *event, bool sample_id_all) -{ - perf_event__swap_op swap; - - swap = perf_event__swap_ops[event->header.type]; - if (swap) - swap(event, sample_id_all); -} - static int perf_session__process_event(struct perf_session *session, union perf_event *event, struct perf_tool *tool, @@ -1051,8 +994,9 @@ static int perf_session__process_event(struct perf_session *session, struct perf_sample sample; int ret; - if (session->header.needs_swap) - event_swap(event, session->sample_id_all); + if (session->header.needs_swap && + perf_event__swap_ops[event->header.type]) + perf_event__swap_ops[event->header.type](event); if (event->header.type >= PERF_RECORD_HEADER_MAX) return -EINVAL; @@ -1484,6 +1428,7 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, int print_sym, int print_dso, int print_symoffset) { struct addr_location al; + struct callchain_cursor *cursor = &evsel->hists.callchain_cursor; struct callchain_cursor_node *node; if (perf_event__preprocess_sample(event, machine, &al, sample, @@ -1501,10 +1446,10 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, error("Failed to resolve callchain. Skipping\n"); return; } - callchain_cursor_commit(&callchain_cursor); + callchain_cursor_commit(cursor); while (1) { - node = callchain_cursor_current(&callchain_cursor); + node = callchain_cursor_current(cursor); if (!node) break; @@ -1515,12 +1460,12 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample, } if (print_dso) { printf(" ("); - map__fprintf_dsoname(node->map, stdout); + map__fprintf_dsoname(al.map, stdout); printf(")"); } printf("\n"); - callchain_cursor_advance(&callchain_cursor); + callchain_cursor_advance(cursor); } } else { diff --git a/trunk/tools/perf/util/symbol.c b/trunk/tools/perf/util/symbol.c index 3e2e5ea0f03f..e2ba8858f3e1 100644 --- a/trunk/tools/perf/util/symbol.c +++ b/trunk/tools/perf/util/symbol.c @@ -323,7 +323,6 @@ struct dso *dso__new(const char *name) dso->sorted_by_name = 0; dso->has_build_id = 0; dso->kernel = DSO_TYPE_USER; - dso->needs_swap = DSO_SWAP__UNSET; INIT_LIST_HEAD(&dso->node); } @@ -1157,33 +1156,6 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) return -1; } -static int dso__swap_init(struct dso *dso, unsigned char eidata) -{ - static unsigned int const endian = 1; - - dso->needs_swap = DSO_SWAP__NO; - - switch (eidata) { - case ELFDATA2LSB: - /* We are big endian, DSO is little endian. */ - if (*(unsigned char const *)&endian != 1) - dso->needs_swap = DSO_SWAP__YES; - break; - - case ELFDATA2MSB: - /* We are little endian, DSO is big endian. */ - if (*(unsigned char const *)&endian != 0) - dso->needs_swap = DSO_SWAP__YES; - break; - - default: - pr_err("unrecognized DSO data encoding %d\n", eidata); - return -EINVAL; - } - - return 0; -} - static int dso__load_sym(struct dso *dso, struct map *map, const char *name, int fd, symbol_filter_t filter, int kmodule, int want_symtab) @@ -1215,9 +1187,6 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, goto out_elf_end; } - if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) - goto out_elf_end; - /* Always reject images with a mismatched build-id: */ if (dso->has_build_id) { u8 build_id[BUILD_ID_SIZE]; @@ -1303,7 +1272,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, if (opdsec && sym.st_shndx == opdidx) { u32 offset = sym.st_value - opdshdr.sh_addr; u64 *opd = opddata->d_buf + offset; - sym.st_value = DSO__SWAP(dso, u64, *opd); + sym.st_value = *opd; sym.st_shndx = elf_addr_to_index(elf, sym.st_value); } @@ -2817,11 +2786,8 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type, struct map *dso__new_map(const char *name) { - struct map *map = NULL; struct dso *dso = dso__new(name); - - if (dso) - map = map__new2(0, dso, MAP__FUNCTION); + struct map *map = map__new2(0, dso, MAP__FUNCTION); return map; } diff --git a/trunk/tools/perf/util/symbol.h b/trunk/tools/perf/util/symbol.h index af0752b1aca1..5649d63798cb 100644 --- a/trunk/tools/perf/util/symbol.h +++ b/trunk/tools/perf/util/symbol.h @@ -9,7 +9,6 @@ #include #include #include -#include #ifdef HAVE_CPLUS_DEMANGLE extern char *cplus_demangle(const char *, int); @@ -161,18 +160,11 @@ enum dso_kernel_type { DSO_TYPE_GUEST_KERNEL }; -enum dso_swap_type { - DSO_SWAP__UNSET, - DSO_SWAP__NO, - DSO_SWAP__YES, -}; - struct dso { struct list_head node; struct rb_root symbols[MAP__NR_TYPES]; struct rb_root symbol_names[MAP__NR_TYPES]; enum dso_kernel_type kernel; - enum dso_swap_type needs_swap; u8 adjust_symbols:1; u8 has_build_id:1; u8 hit:1; @@ -190,28 +182,6 @@ struct dso { char name[0]; }; -#define DSO__SWAP(dso, type, val) \ -({ \ - type ____r = val; \ - BUG_ON(dso->needs_swap == DSO_SWAP__UNSET); \ - if (dso->needs_swap == DSO_SWAP__YES) { \ - switch (sizeof(____r)) { \ - case 2: \ - ____r = bswap_16(val); \ - break; \ - case 4: \ - ____r = bswap_32(val); \ - break; \ - case 8: \ - ____r = bswap_64(val); \ - break; \ - default: \ - BUG_ON(1); \ - } \ - } \ - ____r; \ -}) - struct dso *dso__new(const char *name); void dso__delete(struct dso *dso); diff --git a/trunk/tools/power/x86/turbostat/turbostat.c b/trunk/tools/power/x86/turbostat/turbostat.c index 16de7ad4850f..ab2f682fd44c 100644 --- a/trunk/tools/power/x86/turbostat/turbostat.c +++ b/trunk/tools/power/x86/turbostat/turbostat.c @@ -73,8 +73,8 @@ int backwards_count; char *progname; int num_cpus; -cpu_set_t *cpu_present_set, *cpu_mask; -size_t cpu_present_setsize, cpu_mask_size; +cpu_set_t *cpu_mask; +size_t cpu_mask_size; struct counters { unsigned long long tsc; /* per thread */ @@ -103,12 +103,6 @@ struct timeval tv_even; struct timeval tv_odd; struct timeval tv_delta; -int mark_cpu_present(int pkg, int core, int cpu) -{ - CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set); - return 0; -} - /* * cpu_mask_init(ncpus) * @@ -124,18 +118,6 @@ void cpu_mask_init(int ncpus) } cpu_mask_size = CPU_ALLOC_SIZE(ncpus); CPU_ZERO_S(cpu_mask_size, cpu_mask); - - /* - * Allocate and initialize cpu_present_set - */ - cpu_present_set = CPU_ALLOC(ncpus); - if (cpu_present_set == NULL) { - perror("CPU_ALLOC"); - exit(3); - } - cpu_present_setsize = CPU_ALLOC_SIZE(ncpus); - CPU_ZERO_S(cpu_present_setsize, cpu_present_set); - for_all_cpus(mark_cpu_present); } void cpu_mask_uninit() @@ -143,9 +125,6 @@ void cpu_mask_uninit() CPU_FREE(cpu_mask); cpu_mask = NULL; cpu_mask_size = 0; - CPU_FREE(cpu_present_set); - cpu_present_set = NULL; - cpu_present_setsize = 0; } int cpu_migrate(int cpu) @@ -933,8 +912,6 @@ int is_snb(unsigned int family, unsigned int model) switch (model) { case 0x2A: case 0x2D: - case 0x3A: /* IVB */ - case 0x3D: /* IVB Xeon */ return 1; } return 0; @@ -1070,9 +1047,6 @@ int fork_it(char **argv) int retval; pid_t child_pid; get_counters(cnt_even); - - /* clear affinity side-effect of get_counters() */ - sched_setaffinity(0, cpu_present_setsize, cpu_present_set); gettimeofday(&tv_even, (struct timezone *)NULL); child_pid = fork(); diff --git a/trunk/virt/kvm/irq_comm.c b/trunk/virt/kvm/irq_comm.c index 5afb43114020..a6a0365475ed 100644 --- a/trunk/virt/kvm/irq_comm.c +++ b/trunk/virt/kvm/irq_comm.c @@ -332,7 +332,6 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt, */ hlist_for_each_entry(ei, n, &rt->map[ue->gsi], link) if (ei->type == KVM_IRQ_ROUTING_MSI || - ue->type == KVM_IRQ_ROUTING_MSI || ue->u.irqchip.irqchip == ei->irqchip.irqchip) return r;