diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-08-27 07:08:39 -0700 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-08-27 07:08:39 -0700 | 
| commit | 9db48aaf18d675ac41f550c9384154e0c00de2ef (patch) | |
| tree | 70a19b9164c103e5f52dddff609e01672f8ef616 | |
| parent | 0592969e73ae50ce6852d1aff3d222a335289094 (diff) | |
| parent | fea7a08acb13524b47711625eebea40a0ede69a0 (diff) | |
| download | olio-linux-3.10-9db48aaf18d675ac41f550c9384154e0c00de2ef.tar.xz olio-linux-3.10-9db48aaf18d675ac41f550c9384154e0c00de2ef.zip  | |
Merge 3.6-rc3 into driver-core-next
This picks up the printk fixes in 3.6-rc3 that are needed in this branch.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
871 files changed, 10199 insertions, 6608 deletions
diff --git a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop index 814b01354c4..b31e782bd98 100644 --- a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop +++ b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop @@ -5,4 +5,15 @@ Contact:	"Ike Panhc <ike.pan@canonical.com>"  Description:  		Control the power of camera module. 1 means on, 0 means off. +What:		/sys/devices/platform/ideapad/fan_mode +Date:		June 2012 +KernelVersion:	3.6 +Contact:	"Maxim Mikityanskiy <maxtram95@gmail.com>" +Description: +		Change fan mode +		There are four available modes: +			* 0 -> Super Silent Mode +			* 1 -> Standard Mode +			* 2 -> Dust Cleaning +			* 4 -> Efficient Thermal Dissipation Mode diff --git a/Documentation/DocBook/filesystems.tmpl b/Documentation/DocBook/filesystems.tmpl index 3fca32c4192..25b58efd955 100644 --- a/Documentation/DocBook/filesystems.tmpl +++ b/Documentation/DocBook/filesystems.tmpl @@ -224,8 +224,8 @@ all your transactions.  </para>  <para> -Then at umount time , in your put_super() (2.4) or write_super() (2.5) -you can then call journal_destroy() to clean up your in-core journal object. +Then at umount time , in your put_super() you can then call journal_destroy() +to clean up your in-core journal object.  </para>  <para> diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml index 72039512790..701138f1209 100644 --- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml +++ b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml @@ -125,7 +125,7 @@ the structure refers to a radio tuner the  <constant>V4L2_TUNER_CAP_NORM</constant> flags can't be used.</para>  <para>If multiple frequency bands are supported, then  <structfield>capability</structfield> is the union of all -<structfield>capability></structfield> fields of each &v4l2-frequency-band;. +<structfield>capability</structfield> fields of each &v4l2-frequency-band;.  </para></entry>  	  </row>  	  <row> diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt index d156e1b5db1..da80c2ae091 100644 --- a/Documentation/devicetree/bindings/regulator/tps6586x.txt +++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt @@ -9,9 +9,9 @@ Required properties:  - regulators: list of regulators provided by this controller, must have    property "regulator-compatible" to match their hardware counterparts:    sm[0-2], ldo[0-9] and ldo_rtc -- sm0-supply: The input supply for the SM0. -- sm1-supply: The input supply for the SM1. -- sm2-supply: The input supply for the SM2. +- vin-sm0-supply: The input supply for the SM0. +- vin-sm1-supply: The input supply for the SM1. +- vin-sm2-supply: The input supply for the SM2.  - vinldo01-supply: The input supply for the LDO1 and LDO2  - vinldo23-supply: The input supply for the LDO2 and LDO3  - vinldo4-supply: The input supply for the LDO4 @@ -30,9 +30,9 @@ Example:  		#gpio-cells = <2>;  		gpio-controller; -		sm0-supply = <&some_reg>; -		sm1-supply = <&some_reg>; -		sm2-supply = <&some_reg>; +		vin-sm0-supply = <&some_reg>; +		vin-sm1-supply = <&some_reg>; +		vin-sm2-supply = <&some_reg>;  		vinldo01-supply = <...>;  		vinldo23-supply = <...>;  		vinldo4-supply = <...>; diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 0f103e39b4f..e540a24e5d0 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -114,7 +114,6 @@ prototypes:  	int (*drop_inode) (struct inode *);  	void (*evict_inode) (struct inode *);  	void (*put_super) (struct super_block *); -	void (*write_super) (struct super_block *);  	int (*sync_fs)(struct super_block *sb, int wait);  	int (*freeze_fs) (struct super_block *);  	int (*unfreeze_fs) (struct super_block *); @@ -136,7 +135,6 @@ write_inode:  drop_inode:				!!!inode->i_lock!!!  evict_inode:  put_super:		write -write_super:		read  sync_fs:		read  freeze_fs:		write  unfreeze_fs:		write diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 2bef2b3843d..0742feebc6e 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -94,9 +94,8 @@ protected.  ---  [mandatory] -BKL is also moved from around sb operations.  ->write_super() Is now called  -without BKL held.  BKL should have been shifted into individual fs sb_op -functions.  If you don't need it, remove it.   +BKL is also moved from around sb operations. BKL should have been shifted into +individual fs sb_op functions.  If you don't need it, remove it.  ---  [informational] diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index ead764b2728..de1e6c4dccf 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt @@ -137,6 +137,17 @@ errors=panic|continue|remount-ro  		 without doing anything or remount the partition in  		 read-only mode (default behavior). +discard       -- If set, issues discard/TRIM commands to the block +		 device when blocks are freed. This is useful for SSD devices +		 and sparse/thinly-provisoned LUNs. + +nfs           -- This option maintains an index (cache) of directory +		 inodes by i_logstart which is used by the nfs-related code to +		 improve look-ups. + +		 Enable this only if you want to export the FAT filesystem +		 over NFS +  <bool>: 0,1,yes,no,true,false  TODO diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 065aa2dc083..2ee133e030c 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -216,7 +216,6 @@ struct super_operations {          void (*drop_inode) (struct inode *);          void (*delete_inode) (struct inode *);          void (*put_super) (struct super_block *); -        void (*write_super) (struct super_block *);          int (*sync_fs)(struct super_block *sb, int wait);          int (*freeze_fs) (struct super_block *);          int (*unfreeze_fs) (struct super_block *); @@ -273,9 +272,6 @@ or bottom half).    put_super: called when the VFS wishes to free the superblock  	(i.e. unmount). This is called with the superblock lock held -  write_super: called when the VFS superblock needs to be written to -	disc. This method is optional -    sync_fs: called when VFS is writing out all dirty data associated with    	a superblock. The second parameter indicates whether the method  	should wait until the write out has been completed. Optional. diff --git a/Documentation/laptops/laptop-mode.txt b/Documentation/laptops/laptop-mode.txt index 0bf25eebce9..4ebbfc3f1c6 100644 --- a/Documentation/laptops/laptop-mode.txt +++ b/Documentation/laptops/laptop-mode.txt @@ -262,9 +262,9 @@ MINIMUM_BATTERY_MINUTES=10  #  # Allowed dirty background ratio, in percent.  Once DIRTY_RATIO has been -# exceeded, the kernel will wake pdflush which will then reduce the amount -# of dirty memory to dirty_background_ratio.  Set this nice and low, so once -# some writeout has commenced, we do a lot of it. +# exceeded, the kernel will wake flusher threads which will then reduce the +# amount of dirty memory to dirty_background_ratio.  Set this nice and low, +# so once some writeout has commenced, we do a lot of it.  #  #DIRTY_BACKGROUND_RATIO=5 @@ -384,9 +384,9 @@ CPU_MAXFREQ=${CPU_MAXFREQ:-'slowest'}  #  # Allowed dirty background ratio, in percent.  Once DIRTY_RATIO has been -# exceeded, the kernel will wake pdflush which will then reduce the amount -# of dirty memory to dirty_background_ratio.  Set this nice and low, so once -# some writeout has commenced, we do a lot of it. +# exceeded, the kernel will wake flusher threads which will then reduce the +# amount of dirty memory to dirty_background_ratio.  Set this nice and low, +# so once some writeout has commenced, we do a lot of it.  #  DIRTY_BACKGROUND_RATIO=${DIRTY_BACKGROUND_RATIO:-'5'} diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt index 8d022073e3e..2e9e0ae2cd4 100644 --- a/Documentation/networking/netconsole.txt +++ b/Documentation/networking/netconsole.txt @@ -51,8 +51,23 @@ Built-in netconsole starts immediately after the TCP stack is  initialized and attempts to bring up the supplied dev at the supplied  address. -The remote host can run either 'netcat -u -l -p <port>', -'nc -l -u <port>' or syslogd. +The remote host has several options to receive the kernel messages, +for example: + +1) syslogd + +2) netcat + +   On distributions using a BSD-based netcat version (e.g. Fedora, +   openSUSE and Ubuntu) the listening port must be specified without +   the -p switch: + +   'nc -u -l -p <port>' / 'nc -u -l <port>' or +   'netcat -u -l -p <port>' / 'netcat -u -l <port>' + +3) socat + +   'socat udp-recv:<port> -'  Dynamic reconfiguration:  ======================== diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index e40f4b4e197..1479aca2374 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -840,9 +840,9 @@ static unsigned long i2c_pin_configs[] = {  static struct pinctrl_map __initdata mapping[] = {  	PIN_MAP_MUX_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", "i2c0"), -	PIN_MAP_MUX_CONFIGS_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", i2c_grp_configs), -	PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0scl", i2c_pin_configs), -	PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0sda", i2c_pin_configs), +	PIN_MAP_CONFIGS_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", i2c_grp_configs), +	PIN_MAP_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0scl", i2c_pin_configs), +	PIN_MAP_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0sda", i2c_pin_configs),  };  Finally, some devices expect the mapping table to contain certain specific diff --git a/Documentation/security/Yama.txt b/Documentation/security/Yama.txt index e369de2d48c..dd908cf64ec 100644 --- a/Documentation/security/Yama.txt +++ b/Documentation/security/Yama.txt @@ -46,14 +46,13 @@ restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...)  so that any otherwise allowed process (even those in external pid namespaces)  may attach. -These restrictions do not change how ptrace via PTRACE_TRACEME operates. - -The sysctl settings are: +The sysctl settings (writable only with CAP_SYS_PTRACE) are:  0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other      process running under the same uid, as long as it is dumpable (i.e.      did not transition uids, start privileged, or have called -    prctl(PR_SET_DUMPABLE...) already). +    prctl(PR_SET_DUMPABLE...) already). Similarly, PTRACE_TRACEME is +    unchanged.  1 - restricted ptrace: a process must have a predefined relationship      with the inferior it wants to call PTRACE_ATTACH on. By default, @@ -61,12 +60,13 @@ The sysctl settings are:      classic criteria is also met. To change the relationship, an      inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare      an allowed debugger PID to call PTRACE_ATTACH on the inferior. +    Using PTRACE_TRACEME is unchanged.  2 - admin-only attach: only processes with CAP_SYS_PTRACE may use ptrace -    with PTRACE_ATTACH. +    with PTRACE_ATTACH, or through children calling PTRACE_TRACEME. -3 - no attach: no processes may use ptrace with PTRACE_ATTACH. Once set, -    this sysctl cannot be changed to a lower value. +3 - no attach: no processes may use ptrace with PTRACE_ATTACH nor via +    PTRACE_TRACEME. Once set, this sysctl value cannot be changed.  The original children-only logic was based on the restrictions in grsecurity. diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt index dcc2a94ae34..078701fdbd4 100644 --- a/Documentation/sysctl/vm.txt +++ b/Documentation/sysctl/vm.txt @@ -76,8 +76,8 @@ huge pages although processes will also directly compact memory as required.  dirty_background_bytes -Contains the amount of dirty memory at which the pdflush background writeback -daemon will start writeback. +Contains the amount of dirty memory at which the background kernel +flusher threads will start writeback.  Note: dirty_background_bytes is the counterpart of dirty_background_ratio. Only  one of them may be specified at a time. When one sysctl is written it is @@ -89,7 +89,7 @@ other appears as 0 when read.  dirty_background_ratio  Contains, as a percentage of total system memory, the number of pages at which -the pdflush background writeback daemon will start writing out dirty data. +the background kernel flusher threads will start writing out dirty data.  ============================================================== @@ -112,9 +112,9 @@ retained.  dirty_expire_centisecs  This tunable is used to define when dirty data is old enough to be eligible -for writeout by the pdflush daemons.  It is expressed in 100'ths of a second. -Data which has been dirty in-memory for longer than this interval will be -written out next time a pdflush daemon wakes up. +for writeout by the kernel flusher threads.  It is expressed in 100'ths +of a second.  Data which has been dirty in-memory for longer than this +interval will be written out next time a flusher thread wakes up.  ============================================================== @@ -128,7 +128,7 @@ data.  dirty_writeback_centisecs -The pdflush writeback daemons will periodically wake up and write `old' data +The kernel flusher threads will periodically wake up and write `old' data  out to disk.  This tunable expresses the interval between those wakeups, in  100'ths of a second. diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt index f8551b3879f..4ac359b7aa1 100644 --- a/Documentation/vm/hugetlbpage.txt +++ b/Documentation/vm/hugetlbpage.txt @@ -299,11 +299,17 @@ map_hugetlb.c.  *******************************************************************  /* - * hugepage-shm:  see Documentation/vm/hugepage-shm.c + * map_hugetlb: see tools/testing/selftests/vm/map_hugetlb.c   */  *******************************************************************  /* - * hugepage-mmap:  see Documentation/vm/hugepage-mmap.c + * hugepage-shm:  see tools/testing/selftests/vm/hugepage-shm.c + */ + +******************************************************************* + +/* + * hugepage-mmap:  see tools/testing/selftests/vm/hugepage-mmap.c   */ diff --git a/Documentation/w1/slaves/w1_therm b/Documentation/w1/slaves/w1_therm index 0403aaaba87..874a8ca93fe 100644 --- a/Documentation/w1/slaves/w1_therm +++ b/Documentation/w1/slaves/w1_therm @@ -3,6 +3,7 @@ Kernel driver w1_therm  Supported chips:    * Maxim ds18*20 based temperature sensors. +  * Maxim ds1825 based temperature sensors.  Author: Evgeniy Polyakov <johnpol@2ka.mipt.ru> @@ -15,6 +16,7 @@ supported family codes:  W1_THERM_DS18S20	0x10  W1_THERM_DS1822		0x22  W1_THERM_DS18B20	0x28 +W1_THERM_DS1825		0x3B  Support is provided through the sysfs w1_slave file.  Each open and  read sequence will initiate a temperature conversion then provide two diff --git a/MAINTAINERS b/MAINTAINERS index 94b823f71e9..fdc0119963e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -827,24 +827,24 @@ F:	arch/arm/mach-pxa/colibri-pxa270-income.c  ARM/INTEL IOP32X ARM ARCHITECTURE  M:	Lennert Buytenhek <kernel@wantstofly.org> -M:	Dan Williams <dan.j.williams@intel.com> +M:	Dan Williams <djbw@fb.com>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Maintained  ARM/INTEL IOP33X ARM ARCHITECTURE -M:	Dan Williams <dan.j.williams@intel.com> +M:	Dan Williams <djbw@fb.com>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Maintained  ARM/INTEL IOP13XX ARM ARCHITECTURE  M:	Lennert Buytenhek <kernel@wantstofly.org> -M:	Dan Williams <dan.j.williams@intel.com> +M:	Dan Williams <djbw@fb.com>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Maintained  ARM/INTEL IQ81342EX MACHINE SUPPORT  M:	Lennert Buytenhek <kernel@wantstofly.org> -M:	Dan Williams <dan.j.williams@intel.com> +M:	Dan Williams <djbw@fb.com>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Maintained @@ -869,7 +869,7 @@ F:	drivers/pcmcia/pxa2xx_stargate2.c  ARM/INTEL XSC3 (MANZANO) ARM CORE  M:	Lennert Buytenhek <kernel@wantstofly.org> -M:	Dan Williams <dan.j.williams@intel.com> +M:	Dan Williams <djbw@fb.com>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Maintained @@ -925,14 +925,14 @@ S:	Maintained  ARM/NOMADIK ARCHITECTURE  M:	Alessandro Rubini <rubini@unipv.it> -M:	Linus Walleij <linus.walleij@stericsson.com> +M:	Linus Walleij <linus.walleij@linaro.org>  M:	STEricsson <STEricsson_nomadik_linux@list.st.com>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Maintained  F:	arch/arm/mach-nomadik/  F:	arch/arm/plat-nomadik/  F:	drivers/i2c/busses/i2c-nomadik.c -T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git  ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT  M:	Nelson Castillo <arhuaco@freaks-unidos.net> @@ -1146,7 +1146,7 @@ F:	drivers/usb/host/ehci-w90x900.c  F:	drivers/video/nuc900fb.c  ARM/U300 MACHINE SUPPORT -M:	Linus Walleij <linus.walleij@stericsson.com> +M:	Linus Walleij <linus.walleij@linaro.org>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Supported  F:	arch/arm/mach-u300/ @@ -1161,15 +1161,20 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git  ARM/Ux500 ARM ARCHITECTURE  M:	Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> -M:	Linus Walleij <linus.walleij@stericsson.com> +M:	Linus Walleij <linus.walleij@linaro.org>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  S:	Maintained  F:	arch/arm/mach-ux500/ +F:	drivers/clocksource/clksrc-dbx500-prcmu.c  F:	drivers/dma/ste_dma40* +F:	drivers/hwspinlock/u8500_hsem.c  F:	drivers/mfd/abx500*  F:	drivers/mfd/ab8500* -F:	drivers/mfd/stmpe* +F:	drivers/mfd/dbx500* +F:	drivers/mfd/db8500* +F:	drivers/pinctrl/pinctrl-nomadik*  F:	drivers/rtc/rtc-ab8500.c +F:	drivers/rtc/rtc-pl031.c  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git  ARM/VFP SUPPORT @@ -1227,9 +1232,9 @@ S:	Maintained  F:	drivers/hwmon/asb100.c  ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API -M:	Dan Williams <dan.j.williams@intel.com> +M:	Dan Williams <djbw@fb.com>  W:	http://sourceforge.net/projects/xscaleiop -S:	Supported +S:	Maintained  F:	Documentation/crypto/async-tx-api.txt  F:	crypto/async_tx/  F:	drivers/dma/ @@ -2212,7 +2217,7 @@ S:	Maintained  F:	drivers/scsi/tmscsim.*  DC395x SCSI driver -M:	Oliver Neukum <oliver@neukum.name> +M:	Oliver Neukum <oliver@neukum.org>  M:	Ali Akcaagac <aliakc@web.de>  M:	Jamie Lenehan <lenehan@twibble.org>  W:	http://twibble.org/dist/dc395x/ @@ -2359,7 +2364,7 @@ T:	git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git  DMA GENERIC OFFLOAD ENGINE SUBSYSTEM  M:	Vinod Koul <vinod.koul@intel.com> -M:	Dan Williams <dan.j.williams@intel.com> +M:	Dan Williams <djbw@fb.com>  S:	Supported  F:	drivers/dma/  F:	include/linux/dma* @@ -3094,7 +3099,7 @@ F:	include/linux/gigaset_dev.h  GPIO SUBSYSTEM  M:	Grant Likely <grant.likely@secretlab.ca> -M:	Linus Walleij <linus.walleij@stericsson.com> +M:	Linus Walleij <linus.walleij@linaro.org>  S:	Maintained  T:	git git://git.secretlab.ca/git/linux-2.6.git  F:	Documentation/gpio.txt @@ -3547,7 +3552,6 @@ K:	\b(ABS|SYN)_MT_  INTEL C600 SERIES SAS CONTROLLER DRIVER  M:	Intel SCU Linux support <intel-linux-scu@intel.com> -M:	Dan Williams <dan.j.williams@intel.com>  M:	Dave Jiang <dave.jiang@intel.com>  M:	Ed Nadolski <edmund.nadolski@intel.com>  L:	linux-scsi@vger.kernel.org @@ -3590,8 +3594,8 @@ F:	arch/x86/kernel/microcode_core.c  F:	arch/x86/kernel/microcode_intel.c  INTEL I/OAT DMA DRIVER -M:	Dan Williams <dan.j.williams@intel.com> -S:	Supported +M:	Dan Williams <djbw@fb.com> +S:	Maintained  F:	drivers/dma/ioat*  INTEL IOMMU (VT-d) @@ -3603,8 +3607,8 @@ F:	drivers/iommu/intel-iommu.c  F:	include/linux/intel-iommu.h  INTEL IOP-ADMA DMA DRIVER -M:	Dan Williams <dan.j.williams@intel.com> -S:	Maintained +M:	Dan Williams <djbw@fb.com> +S:	Odd fixes  F:	drivers/dma/iop-adma.c  INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT @@ -4533,7 +4537,7 @@ S:	Supported  F:	arch/microblaze/  MICROTEK X6 SCANNER -M:	Oliver Neukum <oliver@neukum.name> +M:	Oliver Neukum <oliver@neukum.org>  S:	Maintained  F:	drivers/usb/image/microtek.* @@ -5329,14 +5333,15 @@ PIN CONTROL SUBSYSTEM  M:	Linus Walleij <linus.walleij@linaro.org>  S:	Maintained  F:	drivers/pinctrl/ +F:	include/linux/pinctrl/  PIN CONTROLLER - ST SPEAR -M:     Viresh Kumar <viresh.linux@gmail.com> +M:	Viresh Kumar <viresh.linux@gmail.com>  L:	spear-devel@list.st.com  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)  W:	http://www.st.com/spear  S:	Maintained -F:	driver/pinctrl/spear/ +F:	drivers/pinctrl/spear/  PKTCDVD DRIVER  M:	Peter Osterlund <petero2@telia.com> @@ -7071,7 +7076,7 @@ F:	include/linux/mtd/ubi.h  F:	include/mtd/ubi-user.h  USB ACM DRIVER -M:	Oliver Neukum <oliver@neukum.name> +M:	Oliver Neukum <oliver@neukum.org>  L:	linux-usb@vger.kernel.org  S:	Maintained  F:	Documentation/usb/acm.txt @@ -7092,7 +7097,7 @@ S:	Supported  F:	drivers/block/ub.c  USB CDC ETHERNET DRIVER -M:	Oliver Neukum <oliver@neukum.name> +M:	Oliver Neukum <oliver@neukum.org>  L:	linux-usb@vger.kernel.org  S:	Maintained  F:	drivers/net/usb/cdc_*.c @@ -7165,7 +7170,7 @@ F:	drivers/usb/host/isp116x*  F:	include/linux/usb/isp116x.h  USB KAWASAKI LSI DRIVER -M:	Oliver Neukum <oliver@neukum.name> +M:	Oliver Neukum <oliver@neukum.org>  L:	linux-usb@vger.kernel.org  S:	Maintained  F:	drivers/usb/serial/kl5kusb105.* @@ -7283,6 +7288,12 @@ W:	http://www.connecttech.com  S:	Supported  F:	drivers/usb/serial/whiteheat* +USB SMSC75XX ETHERNET DRIVER +M:	Steve Glendinning <steve.glendinning@shawell.net> +L:	netdev@vger.kernel.org +S:	Maintained +F:	drivers/net/usb/smsc75xx.* +  USB SMSC95XX ETHERNET DRIVER  M:	Steve Glendinning <steve.glendinning@shawell.net>  L:	netdev@vger.kernel.org @@ -7665,23 +7676,28 @@ S:	Supported  F:	Documentation/hwmon/wm83??  F:	arch/arm/mach-s3c64xx/mach-crag6410*  F:	drivers/clk/clk-wm83*.c +F:	drivers/extcon/extcon-arizona.c  F:	drivers/leds/leds-wm83*.c  F:	drivers/gpio/gpio-*wm*.c +F:	drivers/gpio/gpio-arizona.c  F:	drivers/hwmon/wm83??-hwmon.c  F:	drivers/input/misc/wm831x-on.c  F:	drivers/input/touchscreen/wm831x-ts.c  F:	drivers/input/touchscreen/wm97*.c -F:	drivers/mfd/wm8*.c +F:	drivers/mfd/arizona* +F:	drivers/mfd/wm*.c  F:	drivers/power/wm83*.c  F:	drivers/rtc/rtc-wm83*.c  F:	drivers/regulator/wm8*.c  F:	drivers/video/backlight/wm83*_bl.c  F:	drivers/watchdog/wm83*_wdt.c +F:	include/linux/mfd/arizona/  F:	include/linux/mfd/wm831x/  F:	include/linux/mfd/wm8350/  F:	include/linux/mfd/wm8400*  F:	include/linux/wm97xx.h  F:	include/sound/wm????.h +F:	sound/soc/codecs/arizona.?  F:	sound/soc/codecs/wm*  WORKQUEUE @@ -1,7 +1,7 @@  VERSION = 3  PATCHLEVEL = 6  SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc3  NAME = Saber-toothed Squirrel  # *DOCUMENTATION* diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index d5b9b5e645c..9944dedee5b 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig @@ -18,6 +18,8 @@ config ALPHA  	select ARCH_HAVE_NMI_SAFE_CMPXCHG  	select GENERIC_SMP_IDLE_THREAD  	select GENERIC_CMOS_UPDATE +	select GENERIC_STRNCPY_FROM_USER +	select GENERIC_STRNLEN_USER  	help  	  The Alpha is a 64-bit general-purpose processor designed and  	  marketed by the Digital Equipment Corporation of blessed memory, diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index 3bb7ffeae3b..c2cbe4fc391 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -14,8 +14,8 @@   */ -#define ATOMIC_INIT(i)		( (atomic_t) { (i) } ) -#define ATOMIC64_INIT(i)	( (atomic64_t) { (i) } ) +#define ATOMIC_INIT(i)		{ (i) } +#define ATOMIC64_INIT(i)	{ (i) }  #define atomic_read(v)		(*(volatile int *)&(v)->counter)  #define atomic64_read(v)	(*(volatile long *)&(v)->counter) diff --git a/arch/alpha/include/asm/fpu.h b/arch/alpha/include/asm/fpu.h index db00f7885fa..e477bcd5b94 100644 --- a/arch/alpha/include/asm/fpu.h +++ b/arch/alpha/include/asm/fpu.h @@ -1,7 +1,9 @@  #ifndef __ASM_ALPHA_FPU_H  #define __ASM_ALPHA_FPU_H +#ifdef __KERNEL__  #include <asm/special_insns.h> +#endif  /*   * Alpha floating-point control register defines: diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h index fd698a174f2..b87755a1955 100644 --- a/arch/alpha/include/asm/ptrace.h +++ b/arch/alpha/include/asm/ptrace.h @@ -76,7 +76,10 @@ struct switch_stack {  #define task_pt_regs(task) \    ((struct pt_regs *) (task_stack_page(task) + 2*PAGE_SIZE) - 1) -#define force_successful_syscall_return() (task_pt_regs(current)->r0 = 0) +#define current_pt_regs() \ +  ((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1) + +#define force_successful_syscall_return() (current_pt_regs()->r0 = 0)  #endif diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h index dcb221a4b5b..7d2f75be932 100644 --- a/arch/alpha/include/asm/socket.h +++ b/arch/alpha/include/asm/socket.h @@ -76,9 +76,11 @@  /* Instruct lower device to use last 4-bytes of skb data as FCS */  #define SO_NOFCS		43 +#ifdef __KERNEL__  /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we   * have to define SOCK_NONBLOCK to a different value here.   */  #define SOCK_NONBLOCK	0x40000000 +#endif /* __KERNEL__ */  #endif /* _ASM_SOCKET_H */ diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index b49ec2f8d6e..766fdfde2b7 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h @@ -433,36 +433,12 @@ clear_user(void __user *to, long len)  #undef __module_address  #undef __module_call -/* Returns: -EFAULT if exception before terminator, N if the entire -   buffer filled, else strlen.  */ +#define user_addr_max() \ +        (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) -extern long __strncpy_from_user(char *__to, const char __user *__from, long __to_len); - -extern inline long -strncpy_from_user(char *to, const char __user *from, long n) -{ -	long ret = -EFAULT; -	if (__access_ok((unsigned long)from, 0, get_fs())) -		ret = __strncpy_from_user(to, from, n); -	return ret; -} - -/* Returns: 0 if bad, string length+1 (memory size) of string if ok */ -extern long __strlen_user(const char __user *); - -extern inline long strlen_user(const char __user *str) -{ -	return access_ok(VERIFY_READ,str,0) ? __strlen_user(str) : 0; -} - -/* Returns: 0 if exception before NUL or reaching the supplied limit (N), - * a value greater than N if the limit would be exceeded, else strlen.  */ -extern long __strnlen_user(const char __user *, long); - -extern inline long strnlen_user(const char __user *str, long n) -{ -	return access_ok(VERIFY_READ,str,0) ? __strnlen_user(str, n) : 0; -} +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);  /*   * About the exception table: diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index 633b23b0664..a31a78eac9b 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h @@ -465,10 +465,12 @@  #define __NR_setns			501  #define __NR_accept4			502  #define __NR_sendmmsg			503 +#define __NR_process_vm_readv		504 +#define __NR_process_vm_writev		505  #ifdef __KERNEL__ -#define NR_SYSCALLS			504 +#define NR_SYSCALLS			506  #define __ARCH_WANT_OLD_READDIR  #define __ARCH_WANT_STAT64 diff --git a/arch/alpha/include/asm/word-at-a-time.h b/arch/alpha/include/asm/word-at-a-time.h new file mode 100644 index 00000000000..6b340d0f152 --- /dev/null +++ b/arch/alpha/include/asm/word-at-a-time.h @@ -0,0 +1,55 @@ +#ifndef _ASM_WORD_AT_A_TIME_H +#define _ASM_WORD_AT_A_TIME_H + +#include <asm/compiler.h> + +/* + * word-at-a-time interface for Alpha. + */ + +/* + * We do not use the word_at_a_time struct on Alpha, but it needs to be + * implemented to humour the generic code. + */ +struct word_at_a_time { +	const unsigned long unused; +}; + +#define WORD_AT_A_TIME_CONSTANTS { 0 } + +/* Return nonzero if val has a zero */ +static inline unsigned long has_zero(unsigned long val, unsigned long *bits, const struct word_at_a_time *c) +{ +	unsigned long zero_locations = __kernel_cmpbge(0, val); +	*bits = zero_locations; +	return zero_locations; +} + +static inline unsigned long prep_zero_mask(unsigned long val, unsigned long bits, const struct word_at_a_time *c) +{ +	return bits; +} + +#define create_zero_mask(bits) (bits) + +static inline unsigned long find_zero(unsigned long bits) +{ +#if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67) +	/* Simple if have CIX instructions */ +	return __kernel_cttz(bits); +#else +	unsigned long t1, t2, t3; +	/* Retain lowest set bit only */ +	bits &= -bits; +	/* Binary search for lowest set bit */ +	t1 = bits & 0xf0; +	t2 = bits & 0xcc; +	t3 = bits & 0xaa; +	if (t1) t1 = 4; +	if (t2) t2 = 2; +	if (t3) t3 = 1; +	return t1 + t2 + t3; +#endif +} + +#endif /* _ASM_WORD_AT_A_TIME_H */ diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index d96e742d4dc..15fa821d09c 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -52,7 +52,6 @@ EXPORT_SYMBOL(alpha_write_fp_reg_s);  /* entry.S */  EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(kernel_execve);  /* Networking helper routines. */  EXPORT_SYMBOL(csum_tcpudp_magic); @@ -74,8 +73,6 @@ EXPORT_SYMBOL(alpha_fp_emul);   */  EXPORT_SYMBOL(__copy_user);  EXPORT_SYMBOL(__do_clear_user); -EXPORT_SYMBOL(__strncpy_from_user); -EXPORT_SYMBOL(__strnlen_user);  /*    * SMP-specific symbols. diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 6d159cee5f2..ec0da0567ab 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -663,58 +663,6 @@ kernel_thread:  	br	ret_to_kernel  .end kernel_thread -/* - * kernel_execve(path, argv, envp) - */ -	.align	4 -	.globl	kernel_execve -	.ent	kernel_execve -kernel_execve: -	/* We can be called from a module.  */ -	ldgp	$gp, 0($27) -	lda	$sp, -(32+SIZEOF_PT_REGS+8)($sp) -	.frame	$sp, 32+SIZEOF_PT_REGS+8, $26, 0 -	stq	$26, 0($sp) -	stq	$16, 8($sp) -	stq	$17, 16($sp) -	stq	$18, 24($sp) -	.prologue 1 - -	lda	$16, 32($sp) -	lda	$17, 0 -	lda	$18, SIZEOF_PT_REGS -	bsr	$26, memset		!samegp - -	/* Avoid the HAE being gratuitously wrong, which would cause us -	   to do the whole turn off interrupts thing and restore it.  */ -	ldq	$2, alpha_mv+HAE_CACHE -	stq	$2, 152+32($sp) - -	ldq	$16, 8($sp) -	ldq	$17, 16($sp) -	ldq	$18, 24($sp) -	lda	$19, 32($sp) -	bsr	$26, do_execve		!samegp - -	ldq	$26, 0($sp) -	bne	$0, 1f			/* error! */ - -	/* Move the temporary pt_regs struct from its current location -	   to the top of the kernel stack frame.  See copy_thread for -	   details for a normal process.  */ -	lda	$16, 0x4000 - SIZEOF_PT_REGS($8) -	lda	$17, 32($sp) -	lda	$18, SIZEOF_PT_REGS -	bsr	$26, memmove		!samegp - -	/* Take that over as our new stack frame and visit userland!  */ -	lda	$sp, 0x4000 - SIZEOF_PT_REGS($8) -	br	$31, ret_from_sys_call - -1:	lda	$sp, 32+SIZEOF_PT_REGS+8($sp) -	ret -.end kernel_execve -  /*   * Special system calls.  Most of these are special in that they either @@ -797,115 +745,6 @@ sys_rt_sigreturn:  .end sys_rt_sigreturn  	.align	4 -	.globl	sys_sethae -	.ent	sys_sethae -sys_sethae: -	.prologue 0 -	stq	$16, 152($sp) -	ret -.end sys_sethae - -	.align	4 -	.globl	osf_getpriority -	.ent	osf_getpriority -osf_getpriority: -	lda	$sp, -16($sp) -	stq	$26, 0($sp) -	.prologue 0 - -	jsr	$26, sys_getpriority - -	ldq	$26, 0($sp) -	blt	$0, 1f - -	/* Return value is the unbiased priority, i.e. 20 - prio. -	   This does result in negative return values, so signal -	   no error by writing into the R0 slot.  */ -	lda	$1, 20 -	stq	$31, 16($sp) -	subl	$1, $0, $0 -	unop - -1:	lda	$sp, 16($sp) -	ret -.end osf_getpriority - -	.align	4 -	.globl	sys_getxuid -	.ent	sys_getxuid -sys_getxuid: -	.prologue 0 -	ldq	$2, TI_TASK($8) -	ldq	$3, TASK_CRED($2) -	ldl	$0, CRED_UID($3) -	ldl	$1, CRED_EUID($3) -	stq	$1, 80($sp) -	ret -.end sys_getxuid - -	.align	4 -	.globl	sys_getxgid -	.ent	sys_getxgid -sys_getxgid: -	.prologue 0 -	ldq	$2, TI_TASK($8) -	ldq	$3, TASK_CRED($2) -	ldl	$0, CRED_GID($3) -	ldl	$1, CRED_EGID($3) -	stq	$1, 80($sp) -	ret -.end sys_getxgid - -	.align	4 -	.globl	sys_getxpid -	.ent	sys_getxpid -sys_getxpid: -	.prologue 0 -	ldq	$2, TI_TASK($8) - -	/* See linux/kernel/timer.c sys_getppid for discussion -	   about this loop.  */ -	ldq	$3, TASK_GROUP_LEADER($2) -	ldq	$4, TASK_REAL_PARENT($3) -	ldl	$0, TASK_TGID($2) -1:	ldl	$1, TASK_TGID($4) -#ifdef CONFIG_SMP -	mov	$4, $5 -	mb -	ldq	$3, TASK_GROUP_LEADER($2) -	ldq	$4, TASK_REAL_PARENT($3) -	cmpeq	$4, $5, $5 -	beq	$5, 1b -#endif -	stq	$1, 80($sp) -	ret -.end sys_getxpid - -	.align	4 -	.globl	sys_alpha_pipe -	.ent	sys_alpha_pipe -sys_alpha_pipe: -	lda	$sp, -16($sp) -	stq	$26, 0($sp) -	.prologue 0 - -	mov	$31, $17 -	lda	$16, 8($sp) -	jsr	$26, do_pipe_flags - -	ldq	$26, 0($sp) -	bne	$0, 1f - -	/* The return values are in $0 and $20.  */ -	ldl	$1, 12($sp) -	ldl	$0, 8($sp) - -	stq	$1, 80+16($sp) -1:	lda	$sp, 16($sp) -	ret -.end sys_alpha_pipe - -	.align	4  	.globl	sys_execve  	.ent	sys_execve  sys_execve: diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 98a103621af..bc1acdda7a5 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -1404,3 +1404,52 @@ SYSCALL_DEFINE3(osf_writev, unsigned long, fd,  }  #endif + +SYSCALL_DEFINE2(osf_getpriority, int, which, int, who) +{ +	int prio = sys_getpriority(which, who); +	if (prio >= 0) { +		/* Return value is the unbiased priority, i.e. 20 - prio. +		   This does result in negative return values, so signal +		   no error */ +		force_successful_syscall_return(); +		prio = 20 - prio; +	} +	return prio; +} + +SYSCALL_DEFINE0(getxuid) +{ +	current_pt_regs()->r20 = sys_geteuid(); +	return sys_getuid(); +} + +SYSCALL_DEFINE0(getxgid) +{ +	current_pt_regs()->r20 = sys_getegid(); +	return sys_getgid(); +} + +SYSCALL_DEFINE0(getxpid) +{ +	current_pt_regs()->r20 = sys_getppid(); +	return sys_getpid(); +} + +SYSCALL_DEFINE0(alpha_pipe) +{ +	int fd[2]; +	int res = do_pipe_flags(fd, 0); +	if (!res) { +		/* The return values are in $0 and $20.  */ +		current_pt_regs()->r20 = fd[1]; +		res = fd[0]; +	} +	return res; +} + +SYSCALL_DEFINE1(sethae, unsigned long, val) +{ +	current_pt_regs()->hae = val; +	return 0; +} diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 153d3fce3e8..d6fde98b74b 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -455,3 +455,22 @@ get_wchan(struct task_struct *p)  	}  	return pc;  } + +int kernel_execve(const char *path, const char *const argv[], const char *const envp[]) +{ +	/* Avoid the HAE being gratuitously wrong, which would cause us +	   to do the whole turn off interrupts thing and restore it.  */ +	struct pt_regs regs = {.hae = alpha_mv.hae_cache}; +	int err = do_execve(path, argv, envp, ®s); +	if (!err) { +		struct pt_regs *p = current_pt_regs(); +		/* copy regs to normal position and off to userland we go... */ +		*p = regs; +		__asm__ __volatile__ ( +			"mov	%0, $sp;" +			"br	$31, ret_from_sys_call" +			: : "r"(p)); +	} +	return err; +} +EXPORT_SYMBOL(kernel_execve); diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S index 87835235f11..2ac6b45c3e0 100644 --- a/arch/alpha/kernel/systbls.S +++ b/arch/alpha/kernel/systbls.S @@ -111,7 +111,7 @@ sys_call_table:  	.quad sys_socket  	.quad sys_connect  	.quad sys_accept -	.quad osf_getpriority			/* 100 */ +	.quad sys_osf_getpriority			/* 100 */  	.quad sys_send  	.quad sys_recv  	.quad sys_sigreturn @@ -522,6 +522,8 @@ sys_call_table:  	.quad sys_setns  	.quad sys_accept4  	.quad sys_sendmmsg +	.quad sys_process_vm_readv +	.quad sys_process_vm_writev		/* 505 */  	.size sys_call_table, . - sys_call_table  	.type sys_call_table, @object diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index c0a83ab62b7..59660743237 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -31,8 +31,6 @@ lib-y =	__divqu.o __remqu.o __divlu.o __remlu.o \  	$(ev6-y)memchr.o \  	$(ev6-y)copy_user.o \  	$(ev6-y)clear_user.o \ -	$(ev6-y)strncpy_from_user.o \ -	$(ev67-y)strlen_user.o \  	$(ev6-y)csum_ipv6_magic.o \  	$(ev6-y)clear_page.o \  	$(ev6-y)copy_page.o \ diff --git a/arch/alpha/lib/ev6-strncpy_from_user.S b/arch/alpha/lib/ev6-strncpy_from_user.S deleted file mode 100644 index d2e28178cac..00000000000 --- a/arch/alpha/lib/ev6-strncpy_from_user.S +++ /dev/null @@ -1,424 +0,0 @@ -/* - * arch/alpha/lib/ev6-strncpy_from_user.S - * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com> - * - * Just like strncpy except in the return value: - * - * -EFAULT       if an exception occurs before the terminator is copied. - * N             if the buffer filled. - * - * Otherwise the length of the string is returned. - * - * Much of the information about 21264 scheduling/coding comes from: - *	Compiler Writer's Guide for the Alpha 21264 - *	abbreviated as 'CWG' in other comments here - *	ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html - * Scheduling notation: - *	E	- either cluster - *	U	- upper subcluster; U0 - subcluster U0; U1 - subcluster U1 - *	L	- lower subcluster; L0 - subcluster L0; L1 - subcluster L1 - * A bunch of instructions got moved and temp registers were changed - * to aid in scheduling.  Control flow was also re-arranged to eliminate - * branches, and to provide longer code sequences to enable better scheduling. - * A total rewrite (using byte load/stores for start & tail sequences) - * is desirable, but very difficult to do without a from-scratch rewrite. - * Save that for the future. - */ - - -#include <asm/errno.h> -#include <asm/regdef.h> - - -/* Allow an exception for an insn; exit if we get one.  */ -#define EX(x,y...)			\ -	99: x,##y;			\ -	.section __ex_table,"a";	\ -	.long 99b - .;			\ -	lda $31, $exception-99b($0); 	\ -	.previous - - -	.set noat -	.set noreorder -	.text - -	.globl __strncpy_from_user -	.ent __strncpy_from_user -	.frame $30, 0, $26 -	.prologue 0 - -	.align 4 -__strncpy_from_user: -	and	a0, 7, t3	# E : find dest misalignment -	beq	a2, $zerolength	# U : - -	/* Are source and destination co-aligned?  */ -	mov	a0, v0		# E : save the string start -	xor	a0, a1, t4	# E : -	EX( ldq_u t1, 0(a1) )	# L : Latency=3 load first quadword -	ldq_u	t0, 0(a0)	# L : load first (partial) aligned dest quadword - -	addq	a2, t3, a2	# E : bias count by dest misalignment -	subq	a2, 1, a3	# E : -	addq	zero, 1, t10	# E : -	and	t4, 7, t4	# E : misalignment between the two - -	and	a3, 7, t6	# E : number of tail bytes -	sll	t10, t6, t10	# E : t10 = bitmask of last count byte -	bne	t4, $unaligned	# U : -	lda	t2, -1		# E : build a mask against false zero - -	/* -	 * We are co-aligned; take care of a partial first word. -	 * On entry to this basic block: -	 * t0 == the first destination word for masking back in -	 * t1 == the first source word. -	 */ - -	srl	a3, 3, a2	# E : a2 = loop counter = (count - 1)/8 -	addq	a1, 8, a1	# E : -	mskqh	t2, a1, t2	# U :   detection in the src word -	nop - -	/* Create the 1st output word and detect 0's in the 1st input word.  */ -	mskqh	t1, a1, t3	# U : -	mskql	t0, a1, t0	# U : assemble the first output word -	ornot	t1, t2, t2	# E : -	nop - -	cmpbge	zero, t2, t8	# E : bits set iff null found -	or	t0, t3, t0	# E : -	beq	a2, $a_eoc	# U : -	bne	t8, $a_eos	# U : 2nd branch in a quad.  Bad. - -	/* On entry to this basic block: -	 * t0 == a source quad not containing a null. -	 * a0 - current aligned destination address -	 * a1 - current aligned source address -	 * a2 - count of quadwords to move. -	 * NOTE: Loop improvement - unrolling this is going to be -	 *	a huge win, since we're going to stall otherwise. -	 *	Fix this later.  For _really_ large copies, look -	 *	at using wh64 on a look-ahead basis.  See the code -	 *	in clear_user.S and copy_user.S. -	 * Presumably, since (a0) and (a1) do not overlap (by C definition) -	 * Lots of nops here: -	 *	- Separate loads from stores -	 *	- Keep it to 1 branch/quadpack so the branch predictor -	 *	  can train. -	 */ -$a_loop: -	stq_u	t0, 0(a0)	# L : -	addq	a0, 8, a0	# E : -	nop -	subq	a2, 1, a2	# E : - -	EX( ldq_u t0, 0(a1) )	# L : -	addq	a1, 8, a1	# E : -	cmpbge	zero, t0, t8	# E : Stall 2 cycles on t0 -	beq	a2, $a_eoc      # U : - -	beq	t8, $a_loop	# U : -	nop -	nop -	nop - -	/* Take care of the final (partial) word store.  At this point -	 * the end-of-count bit is set in t8 iff it applies. -	 * -	 * On entry to this basic block we have: -	 * t0 == the source word containing the null -	 * t8 == the cmpbge mask that found it. -	 */ -$a_eos: -	negq	t8, t12		# E : find low bit set -	and	t8, t12, t12	# E :  - -	/* We're doing a partial word store and so need to combine -	   our source and original destination words.  */ -	ldq_u	t1, 0(a0)	# L : -	subq	t12, 1, t6	# E : - -	or	t12, t6, t8	# E : -	zapnot	t0, t8, t0	# U : clear src bytes > null -	zap	t1, t8, t1	# U : clear dst bytes <= null -	or	t0, t1, t0	# E : - -	stq_u	t0, 0(a0)	# L : -	br	$finish_up	# L0 : -	nop -	nop - -	/* Add the end-of-count bit to the eos detection bitmask.  */ -	.align 4 -$a_eoc: -	or	t10, t8, t8 -	br	$a_eos -	nop -	nop - - -/* The source and destination are not co-aligned.  Align the destination -   and cope.  We have to be very careful about not reading too much and -   causing a SEGV.  */ - -	.align 4 -$u_head: -	/* We know just enough now to be able to assemble the first -	   full source word.  We can still find a zero at the end of it -	   that prevents us from outputting the whole thing. - -	   On entry to this basic block: -	   t0 == the first dest word, unmasked -	   t1 == the shifted low bits of the first source word -	   t6 == bytemask that is -1 in dest word bytes */ - -	EX( ldq_u t2, 8(a1) )	# L : load second src word -	addq	a1, 8, a1	# E : -	mskql	t0, a0, t0	# U : mask trailing garbage in dst -	extqh	t2, a1, t4	# U : - -	or	t1, t4, t1	# E : first aligned src word complete -	mskqh	t1, a0, t1	# U : mask leading garbage in src -	or	t0, t1, t0	# E : first output word complete -	or	t0, t6, t6	# E : mask original data for zero test - -	cmpbge	zero, t6, t8	# E : -	beq	a2, $u_eocfin	# U : -	bne	t8, $u_final	# U : bad news - 2nd branch in a quad -	lda	t6, -1		# E : mask out the bits we have - -	mskql	t6, a1, t6	# U :   already seen -	stq_u	t0, 0(a0)	# L : store first output word -	or      t6, t2, t2	# E : -	cmpbge	zero, t2, t8	# E : find nulls in second partial - -	addq	a0, 8, a0		# E : -	subq	a2, 1, a2		# E : -	bne	t8, $u_late_head_exit	# U : -	nop - -	/* Finally, we've got all the stupid leading edge cases taken care -	   of and we can set up to enter the main loop.  */ - -	extql	t2, a1, t1	# U : position hi-bits of lo word -	EX( ldq_u t2, 8(a1) )	# L : read next high-order source word -	addq	a1, 8, a1	# E : -	cmpbge	zero, t2, t8	# E : - -	beq	a2, $u_eoc	# U : -	bne	t8, $u_eos	# U : -	nop -	nop - -	/* Unaligned copy main loop.  In order to avoid reading too much, -	   the loop is structured to detect zeros in aligned source words. -	   This has, unfortunately, effectively pulled half of a loop -	   iteration out into the head and half into the tail, but it does -	   prevent nastiness from accumulating in the very thing we want -	   to run as fast as possible. - -	   On entry to this basic block: -	   t1 == the shifted high-order bits from the previous source word -	   t2 == the unshifted current source word - -	   We further know that t2 does not contain a null terminator.  */ - -	/* -	 * Extra nops here: -	 *	separate load quads from store quads -	 *	only one branch/quad to permit predictor training -	 */ - -	.align 4 -$u_loop: -	extqh	t2, a1, t0	# U : extract high bits for current word -	addq	a1, 8, a1	# E : -	extql	t2, a1, t3	# U : extract low bits for next time -	addq	a0, 8, a0	# E : - -	or	t0, t1, t0	# E : current dst word now complete -	EX( ldq_u t2, 0(a1) )	# L : load high word for next time -	subq	a2, 1, a2	# E : -	nop - -	stq_u	t0, -8(a0)	# L : save the current word -	mov	t3, t1		# E : -	cmpbge	zero, t2, t8	# E : test new word for eos -	beq	a2, $u_eoc	# U : - -	beq	t8, $u_loop	# U : -	nop -	nop -	nop - -	/* We've found a zero somewhere in the source word we just read. -	   If it resides in the lower half, we have one (probably partial) -	   word to write out, and if it resides in the upper half, we -	   have one full and one partial word left to write out. - -	   On entry to this basic block: -	   t1 == the shifted high-order bits from the previous source word -	   t2 == the unshifted current source word.  */ -	.align 4 -$u_eos: -	extqh	t2, a1, t0	# U : -	or	t0, t1, t0	# E : first (partial) source word complete -	cmpbge	zero, t0, t8	# E : is the null in this first bit? -	nop - -	bne	t8, $u_final	# U : -	stq_u	t0, 0(a0)	# L : the null was in the high-order bits -	addq	a0, 8, a0	# E : -	subq	a2, 1, a2	# E : - -	.align 4 -$u_late_head_exit: -	extql	t2, a1, t0	# U : -	cmpbge	zero, t0, t8	# E : -	or	t8, t10, t6	# E : -	cmoveq	a2, t6, t8	# E : - -	/* Take care of a final (probably partial) result word. -	   On entry to this basic block: -	   t0 == assembled source word -	   t8 == cmpbge mask that found the null.  */ -	.align 4 -$u_final: -	negq	t8, t6		# E : isolate low bit set -	and	t6, t8, t12	# E : -	ldq_u	t1, 0(a0)	# L : -	subq	t12, 1, t6	# E : - -	or	t6, t12, t8	# E : -	zapnot	t0, t8, t0	# U : kill source bytes > null -	zap	t1, t8, t1	# U : kill dest bytes <= null -	or	t0, t1, t0	# E : - -	stq_u	t0, 0(a0)	# E : -	br	$finish_up	# U : -	nop -	nop - -	.align 4 -$u_eoc:				# end-of-count -	extqh	t2, a1, t0	# U : -	or	t0, t1, t0	# E : -	cmpbge	zero, t0, t8	# E : -	nop - -	.align 4 -$u_eocfin:			# end-of-count, final word -	or	t10, t8, t8	# E : -	br	$u_final	# U : -	nop -	nop - -	/* Unaligned copy entry point.  */ -	.align 4 -$unaligned: - -	srl	a3, 3, a2	# U : a2 = loop counter = (count - 1)/8 -	and	a0, 7, t4	# E : find dest misalignment -	and	a1, 7, t5	# E : find src misalignment -	mov	zero, t0	# E : - -	/* Conditionally load the first destination word and a bytemask -	   with 0xff indicating that the destination byte is sacrosanct.  */ - -	mov	zero, t6	# E : -	beq	t4, 1f		# U : -	ldq_u	t0, 0(a0)	# L : -	lda	t6, -1		# E : - -	mskql	t6, a0, t6	# E : -	nop -	nop -	nop - -	.align 4 -1: -	subq	a1, t4, a1	# E : sub dest misalignment from src addr -	/* If source misalignment is larger than dest misalignment, we need -	   extra startup checks to avoid SEGV.  */ -	cmplt	t4, t5, t12	# E : -	extql	t1, a1, t1	# U : shift src into place -	lda	t2, -1		# E : for creating masks later - -	beq	t12, $u_head	# U : -	mskqh	t2, t5, t2	# U : begin src byte validity mask -	cmpbge	zero, t1, t8	# E : is there a zero? -	nop - -	extql	t2, a1, t2	# U : -	or	t8, t10, t5	# E : test for end-of-count too -	cmpbge	zero, t2, t3	# E : -	cmoveq	a2, t5, t8	# E : Latency=2, extra map slot - -	nop			# E : goes with cmov -	andnot	t8, t3, t8	# E : -	beq	t8, $u_head	# U : -	nop - -	/* At this point we've found a zero in the first partial word of -	   the source.  We need to isolate the valid source data and mask -	   it into the original destination data.  (Incidentally, we know -	   that we'll need at least one byte of that original dest word.) */ - -	ldq_u	t0, 0(a0)	# L : -	negq	t8, t6		# E : build bitmask of bytes <= zero -	mskqh	t1, t4, t1	# U : -	and	t6, t8, t12	# E : - -	subq	t12, 1, t6	# E : -	or	t6, t12, t8	# E : -	zapnot	t2, t8, t2	# U : prepare source word; mirror changes -	zapnot	t1, t8, t1	# U : to source validity mask - -	andnot	t0, t2, t0	# E : zero place for source to reside -	or	t0, t1, t0	# E : and put it there -	stq_u	t0, 0(a0)	# L : -	nop - -	.align 4 -$finish_up: -	zapnot	t0, t12, t4	# U : was last byte written null? -	and	t12, 0xf0, t3	# E : binary search for the address of the -	cmovne	t4, 1, t4	# E : Latency=2, extra map slot -	nop			# E : with cmovne - -	and	t12, 0xcc, t2	# E : last byte written -	and	t12, 0xaa, t1	# E : -	cmovne	t3, 4, t3	# E : Latency=2, extra map slot -	nop			# E : with cmovne - -	bic	a0, 7, t0 -	cmovne	t2, 2, t2	# E : Latency=2, extra map slot -	nop			# E : with cmovne -	nop - -	cmovne	t1, 1, t1	# E : Latency=2, extra map slot -	nop			# E : with cmovne -	addq	t0, t3, t0	# E : -	addq	t1, t2, t1	# E : - -	addq	t0, t1, t0	# E : -	addq	t0, t4, t0	# add one if we filled the buffer -	subq	t0, v0, v0	# find string length -	ret			# L0 : - -	.align 4 -$zerolength: -	nop -	nop -	nop -	clr	v0 - -$exception: -	nop -	nop -	nop -	ret - -	.end __strncpy_from_user diff --git a/arch/alpha/lib/ev67-strlen_user.S b/arch/alpha/lib/ev67-strlen_user.S deleted file mode 100644 index 57e0d77b81a..00000000000 --- a/arch/alpha/lib/ev67-strlen_user.S +++ /dev/null @@ -1,107 +0,0 @@ -/* - * arch/alpha/lib/ev67-strlen_user.S - * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com> - * - * Return the length of the string including the NULL terminator - * (strlen+1) or zero if an error occurred. - * - * In places where it is critical to limit the processing time, - * and the data is not trusted, strnlen_user() should be used. - * It will return a value greater than its second argument if - * that limit would be exceeded. This implementation is allowed - * to access memory beyond the limit, but will not cross a page - * boundary when doing so. - * - * Much of the information about 21264 scheduling/coding comes from: - *      Compiler Writer's Guide for the Alpha 21264 - *      abbreviated as 'CWG' in other comments here - *      ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html - * Scheduling notation: - *      E       - either cluster - *      U       - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 - *      L       - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 - * Try not to change the actual algorithm if possible for consistency. - */ - -#include <asm/regdef.h> - - -/* Allow an exception for an insn; exit if we get one.  */ -#define EX(x,y...)			\ -	99: x,##y;			\ -	.section __ex_table,"a";	\ -	.long 99b - .;			\ -	lda v0, $exception-99b(zero);	\ -	.previous - - -	.set noreorder -	.set noat -	.text - -	.globl __strlen_user -	.ent __strlen_user -	.frame sp, 0, ra - -	.align 4 -__strlen_user: -	ldah	a1, 32767(zero)	# do not use plain strlen_user() for strings -				# that might be almost 2 GB long; you should -				# be using strnlen_user() instead -	nop -	nop -	nop - -	.globl __strnlen_user - -	.align 4 -__strnlen_user: -	.prologue 0 -	EX( ldq_u t0, 0(a0) )	# L : load first quadword (a0 may be misaligned) -	lda     t1, -1(zero)	# E : - -	insqh   t1, a0, t1	# U : -	andnot  a0, 7, v0	# E : -	or      t1, t0, t0	# E : -	subq	a0, 1, a0	# E : get our +1 for the return  - -	cmpbge  zero, t0, t1	# E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0 -	subq	a1, 7, t2	# E : -	subq	a0, v0, t0	# E : -	bne     t1, $found	# U : - -	addq	t2, t0, t2	# E : -	addq	a1, 1, a1	# E : -	nop			# E : -	nop			# E : - -	.align 4 -$loop:	ble	t2, $limit	# U : -	EX( ldq t0, 8(v0) )	# L : -	nop			# E : -	nop			# E : - -	cmpbge  zero, t0, t1	# E : -	subq	t2, 8, t2	# E : -	addq    v0, 8, v0	# E : addr += 8 -	beq     t1, $loop	# U : - -$found: cttz	t1, t2		# U0 : -	addq	v0, t2, v0	# E : -	subq    v0, a0, v0	# E : -	ret			# L0 : - -$exception: -	nop -	nop -	nop -	ret - -	.align 4		# currently redundant -$limit: -	nop -	nop -	subq	a1, t2, v0 -	ret - -	.end __strlen_user diff --git a/arch/alpha/lib/strlen_user.S b/arch/alpha/lib/strlen_user.S deleted file mode 100644 index 508a18e9647..00000000000 --- a/arch/alpha/lib/strlen_user.S +++ /dev/null @@ -1,91 +0,0 @@ -/* - * arch/alpha/lib/strlen_user.S - * - * Return the length of the string including the NUL terminator - * (strlen+1) or zero if an error occurred. - * - * In places where it is critical to limit the processing time, - * and the data is not trusted, strnlen_user() should be used. - * It will return a value greater than its second argument if - * that limit would be exceeded. This implementation is allowed - * to access memory beyond the limit, but will not cross a page - * boundary when doing so. - */ - -#include <asm/regdef.h> - - -/* Allow an exception for an insn; exit if we get one.  */ -#define EX(x,y...)			\ -	99: x,##y;			\ -	.section __ex_table,"a";	\ -	.long 99b - .;			\ -	lda v0, $exception-99b(zero);	\ -	.previous - - -	.set noreorder -	.set noat -	.text - -	.globl __strlen_user -	.ent __strlen_user -	.frame sp, 0, ra - -	.align 3 -__strlen_user: -	ldah	a1, 32767(zero)	# do not use plain strlen_user() for strings -				# that might be almost 2 GB long; you should -				# be using strnlen_user() instead - -	.globl __strnlen_user - -	.align 3 -__strnlen_user: -	.prologue 0 - -	EX( ldq_u t0, 0(a0) )	# load first quadword (a0 may be misaligned) -	lda     t1, -1(zero) -	insqh   t1, a0, t1 -	andnot  a0, 7, v0 -	or      t1, t0, t0 -	subq	a0, 1, a0	# get our +1 for the return  -	cmpbge  zero, t0, t1	# t1 <- bitmask: bit i == 1 <==> i-th byte == 0 -	subq	a1, 7, t2 -	subq	a0, v0, t0 -	bne     t1, $found - -	addq	t2, t0, t2 -	addq	a1, 1, a1 - -	.align 3 -$loop:	ble	t2, $limit -	EX( ldq t0, 8(v0) ) -	subq	t2, 8, t2 -	addq    v0, 8, v0	# addr += 8 -	cmpbge  zero, t0, t1 -	beq     t1, $loop - -$found:	negq    t1, t2		# clear all but least set bit -	and     t1, t2, t1 - -	and     t1, 0xf0, t2	# binary search for that set bit -	and	t1, 0xcc, t3 -	and	t1, 0xaa, t4 -	cmovne	t2, 4, t2 -	cmovne	t3, 2, t3 -	cmovne	t4, 1, t4 -	addq	t2, t3, t2 -	addq	v0, t4, v0 -	addq	v0, t2, v0 -	nop			# dual issue next two on ev4 and ev5 -	subq    v0, a0, v0 -$exception: -	ret - -	.align 3		# currently redundant -$limit: -	subq	a1, t2, v0 -	ret - -	.end __strlen_user diff --git a/arch/alpha/lib/strncpy_from_user.S b/arch/alpha/lib/strncpy_from_user.S deleted file mode 100644 index 73ee21160ff..00000000000 --- a/arch/alpha/lib/strncpy_from_user.S +++ /dev/null @@ -1,339 +0,0 @@ -/* - * arch/alpha/lib/strncpy_from_user.S - * Contributed by Richard Henderson (rth@tamu.edu) - * - * Just like strncpy except in the return value: - * - * -EFAULT       if an exception occurs before the terminator is copied. - * N             if the buffer filled. - * - * Otherwise the length of the string is returned. - */ - - -#include <asm/errno.h> -#include <asm/regdef.h> - - -/* Allow an exception for an insn; exit if we get one.  */ -#define EX(x,y...)			\ -	99: x,##y;			\ -	.section __ex_table,"a";	\ -	.long 99b - .;			\ -	lda $31, $exception-99b($0); 	\ -	.previous - - -	.set noat -	.set noreorder -	.text - -	.globl __strncpy_from_user -	.ent __strncpy_from_user -	.frame $30, 0, $26 -	.prologue 0 - -	.align 3 -$aligned: -	/* On entry to this basic block: -	   t0 == the first destination word for masking back in -	   t1 == the first source word.  */ - -	/* Create the 1st output word and detect 0's in the 1st input word.  */ -	lda	t2, -1		# e1    : build a mask against false zero -	mskqh	t2, a1, t2	# e0    :   detection in the src word -	mskqh	t1, a1, t3	# e0    : -	ornot	t1, t2, t2	# .. e1 : -	mskql	t0, a1, t0	# e0    : assemble the first output word -	cmpbge	zero, t2, t8	# .. e1 : bits set iff null found -	or	t0, t3, t0	# e0    : -	beq	a2, $a_eoc	# .. e1 : -	bne	t8, $a_eos	# .. e1 : - -	/* On entry to this basic block: -	   t0 == a source word not containing a null.  */ - -$a_loop: -	stq_u	t0, 0(a0)	# e0    : -	addq	a0, 8, a0	# .. e1 : -	EX( ldq_u t0, 0(a1) )	# e0    : -	addq	a1, 8, a1	# .. e1 : -	subq	a2, 1, a2	# e0    : -	cmpbge	zero, t0, t8	# .. e1 (stall) -	beq	a2, $a_eoc      # e1    : -	beq	t8, $a_loop	# e1    : - -	/* Take care of the final (partial) word store.  At this point -	   the end-of-count bit is set in t8 iff it applies. - -	   On entry to this basic block we have: -	   t0 == the source word containing the null -	   t8 == the cmpbge mask that found it.  */ - -$a_eos: -	negq	t8, t12		# e0    : find low bit set -	and	t8, t12, t12	# e1 (stall) - -	/* For the sake of the cache, don't read a destination word -	   if we're not going to need it.  */ -	and	t12, 0x80, t6	# e0    : -	bne	t6, 1f		# .. e1 (zdb) - -	/* We're doing a partial word store and so need to combine -	   our source and original destination words.  */ -	ldq_u	t1, 0(a0)	# e0    : -	subq	t12, 1, t6	# .. e1 : -	or	t12, t6, t8	# e0    : -	unop			# -	zapnot	t0, t8, t0	# e0    : clear src bytes > null -	zap	t1, t8, t1	# .. e1 : clear dst bytes <= null -	or	t0, t1, t0	# e1    : - -1:	stq_u	t0, 0(a0) -	br	$finish_up - -	/* Add the end-of-count bit to the eos detection bitmask.  */ -$a_eoc: -	or	t10, t8, t8 -	br	$a_eos - -	/*** The Function Entry Point ***/ -	.align 3 -__strncpy_from_user: -	mov	a0, v0		# save the string start -	beq	a2, $zerolength - -	/* Are source and destination co-aligned?  */ -	xor	a0, a1, t1	# e0    : -	and	a0, 7, t0	# .. e1 : find dest misalignment -	and	t1, 7, t1	# e0    : -	addq	a2, t0, a2	# .. e1 : bias count by dest misalignment -	subq	a2, 1, a2	# e0    : -	and	a2, 7, t2	# e1    : -	srl	a2, 3, a2	# e0    : a2 = loop counter = (count - 1)/8 -	addq	zero, 1, t10	# .. e1 : -	sll	t10, t2, t10	# e0    : t10 = bitmask of last count byte -	bne	t1, $unaligned	# .. e1 : - -	/* We are co-aligned; take care of a partial first word.  */ - -	EX( ldq_u t1, 0(a1) )	# e0    : load first src word -	addq	a1, 8, a1	# .. e1 : - -	beq	t0, $aligned	# avoid loading dest word if not needed -	ldq_u	t0, 0(a0)	# e0    : -	br	$aligned	# .. e1 : - - -/* The source and destination are not co-aligned.  Align the destination -   and cope.  We have to be very careful about not reading too much and -   causing a SEGV.  */ - -	.align 3 -$u_head: -	/* We know just enough now to be able to assemble the first -	   full source word.  We can still find a zero at the end of it -	   that prevents us from outputting the whole thing. - -	   On entry to this basic block: -	   t0 == the first dest word, unmasked -	   t1 == the shifted low bits of the first source word -	   t6 == bytemask that is -1 in dest word bytes */ - -	EX( ldq_u t2, 8(a1) )	# e0    : load second src word -	addq	a1, 8, a1	# .. e1 : -	mskql	t0, a0, t0	# e0    : mask trailing garbage in dst -	extqh	t2, a1, t4	# e0    : -	or	t1, t4, t1	# e1    : first aligned src word complete -	mskqh	t1, a0, t1	# e0    : mask leading garbage in src -	or	t0, t1, t0	# e0    : first output word complete -	or	t0, t6, t6	# e1    : mask original data for zero test -	cmpbge	zero, t6, t8	# e0    : -	beq	a2, $u_eocfin	# .. e1 : -	bne	t8, $u_final	# e1    : - -	lda	t6, -1			# e1    : mask out the bits we have -	mskql	t6, a1, t6		# e0    :   already seen -	stq_u	t0, 0(a0)		# e0    : store first output word -	or      t6, t2, t2		# .. e1 : -	cmpbge	zero, t2, t8		# e0    : find nulls in second partial -	addq	a0, 8, a0		# .. e1 : -	subq	a2, 1, a2		# e0    : -	bne	t8, $u_late_head_exit	# .. e1 : - -	/* Finally, we've got all the stupid leading edge cases taken care -	   of and we can set up to enter the main loop.  */ - -	extql	t2, a1, t1	# e0    : position hi-bits of lo word -	EX( ldq_u t2, 8(a1) )	# .. e1 : read next high-order source word -	addq	a1, 8, a1	# e0    : -	cmpbge	zero, t2, t8	# e1 (stall) -	beq	a2, $u_eoc	# e1    : -	bne	t8, $u_eos	# e1    : - -	/* Unaligned copy main loop.  In order to avoid reading too much, -	   the loop is structured to detect zeros in aligned source words. -	   This has, unfortunately, effectively pulled half of a loop -	   iteration out into the head and half into the tail, but it does -	   prevent nastiness from accumulating in the very thing we want -	   to run as fast as possible. - -	   On entry to this basic block: -	   t1 == the shifted high-order bits from the previous source word -	   t2 == the unshifted current source word - -	   We further know that t2 does not contain a null terminator.  */ - -	.align 3 -$u_loop: -	extqh	t2, a1, t0	# e0    : extract high bits for current word -	addq	a1, 8, a1	# .. e1 : -	extql	t2, a1, t3	# e0    : extract low bits for next time -	addq	a0, 8, a0	# .. e1 : -	or	t0, t1, t0	# e0    : current dst word now complete -	EX( ldq_u t2, 0(a1) )	# .. e1 : load high word for next time -	stq_u	t0, -8(a0)	# e0    : save the current word -	mov	t3, t1		# .. e1 : -	subq	a2, 1, a2	# e0    : -	cmpbge	zero, t2, t8	# .. e1 : test new word for eos -	beq	a2, $u_eoc	# e1    : -	beq	t8, $u_loop	# e1    : - -	/* We've found a zero somewhere in the source word we just read. -	   If it resides in the lower half, we have one (probably partial) -	   word to write out, and if it resides in the upper half, we -	   have one full and one partial word left to write out. - -	   On entry to this basic block: -	   t1 == the shifted high-order bits from the previous source word -	   t2 == the unshifted current source word.  */ -$u_eos: -	extqh	t2, a1, t0	# e0    : -	or	t0, t1, t0	# e1    : first (partial) source word complete - -	cmpbge	zero, t0, t8	# e0    : is the null in this first bit? -	bne	t8, $u_final	# .. e1 (zdb) - -	stq_u	t0, 0(a0)	# e0    : the null was in the high-order bits -	addq	a0, 8, a0	# .. e1 : -	subq	a2, 1, a2	# e1    : - -$u_late_head_exit: -	extql	t2, a1, t0	# .. e0 : -	cmpbge	zero, t0, t8	# e0    : -	or	t8, t10, t6	# e1    : -	cmoveq	a2, t6, t8	# e0    : -	nop			# .. e1 : - -	/* Take care of a final (probably partial) result word. -	   On entry to this basic block: -	   t0 == assembled source word -	   t8 == cmpbge mask that found the null.  */ -$u_final: -	negq	t8, t6		# e0    : isolate low bit set -	and	t6, t8, t12	# e1    : - -	and	t12, 0x80, t6	# e0    : avoid dest word load if we can -	bne	t6, 1f		# .. e1 (zdb) - -	ldq_u	t1, 0(a0)	# e0    : -	subq	t12, 1, t6	# .. e1 : -	or	t6, t12, t8	# e0    : -	zapnot	t0, t8, t0	# .. e1 : kill source bytes > null -	zap	t1, t8, t1	# e0    : kill dest bytes <= null -	or	t0, t1, t0	# e1    : - -1:	stq_u	t0, 0(a0)	# e0    : -	br	$finish_up - -$u_eoc:				# end-of-count -	extqh	t2, a1, t0 -	or	t0, t1, t0 -	cmpbge	zero, t0, t8 - -$u_eocfin:			# end-of-count, final word -	or	t10, t8, t8 -	br	$u_final - -	/* Unaligned copy entry point.  */ -	.align 3 -$unaligned: - -	EX( ldq_u t1, 0(a1) )	# e0    : load first source word - -	and	a0, 7, t4	# .. e1 : find dest misalignment -	and	a1, 7, t5	# e0    : find src misalignment - -	/* Conditionally load the first destination word and a bytemask -	   with 0xff indicating that the destination byte is sacrosanct.  */ - -	mov	zero, t0	# .. e1 : -	mov	zero, t6	# e0    : -	beq	t4, 1f		# .. e1 : -	ldq_u	t0, 0(a0)	# e0    : -	lda	t6, -1		# .. e1 : -	mskql	t6, a0, t6	# e0    : -1: -	subq	a1, t4, a1	# .. e1 : sub dest misalignment from src addr - -	/* If source misalignment is larger than dest misalignment, we need -	   extra startup checks to avoid SEGV.  */ - -	cmplt	t4, t5, t12	# e1    : -	extql	t1, a1, t1	# .. e0 : shift src into place -	lda	t2, -1		# e0    : for creating masks later -	beq	t12, $u_head	# e1    : - -	mskqh	t2, t5, t2	# e0    : begin src byte validity mask -	cmpbge	zero, t1, t8	# .. e1 : is there a zero? -	extql	t2, a1, t2	# e0    : -	or	t8, t10, t5	# .. e1 : test for end-of-count too -	cmpbge	zero, t2, t3	# e0    : -	cmoveq	a2, t5, t8	# .. e1 : -	andnot	t8, t3, t8	# e0    : -	beq	t8, $u_head	# .. e1 (zdb) - -	/* At this point we've found a zero in the first partial word of -	   the source.  We need to isolate the valid source data and mask -	   it into the original destination data.  (Incidentally, we know -	   that we'll need at least one byte of that original dest word.) */ - -	ldq_u	t0, 0(a0)	# e0    : -	negq	t8, t6		# .. e1 : build bitmask of bytes <= zero -	mskqh	t1, t4, t1	# e0    : -	and	t6, t8, t12	# .. e1 : -	subq	t12, 1, t6	# e0    : -	or	t6, t12, t8	# e1    : - -	zapnot	t2, t8, t2	# e0    : prepare source word; mirror changes -	zapnot	t1, t8, t1	# .. e1 : to source validity mask - -	andnot	t0, t2, t0	# e0    : zero place for source to reside -	or	t0, t1, t0	# e1    : and put it there -	stq_u	t0, 0(a0)	# e0    : - -$finish_up: -	zapnot	t0, t12, t4	# was last byte written null? -	cmovne	t4, 1, t4 - -	and	t12, 0xf0, t3	# binary search for the address of the -	and	t12, 0xcc, t2	# last byte written -	and	t12, 0xaa, t1 -	bic	a0, 7, t0 -	cmovne	t3, 4, t3 -	cmovne	t2, 2, t2 -	cmovne	t1, 1, t1 -	addq	t0, t3, t0 -	addq	t1, t2, t1 -	addq	t0, t1, t0 -	addq	t0, t4, t0	# add one if we filled the buffer - -	subq	t0, v0, v0	# find string length -	ret - -$zerolength: -	clr	v0 -$exception: -	ret - -	.end __strncpy_from_user diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 5eecab1a84e..0c4132dd350 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c @@ -89,6 +89,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  	const struct exception_table_entry *fixup;  	int fault, si_code = SEGV_MAPERR;  	siginfo_t info; +	unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | +			      (cause > 0 ? FAULT_FLAG_WRITE : 0));  	/* As of EV6, a load into $31/$f31 is a prefetch, and never faults  	   (or is suppressed by the PALcode).  Support that for older CPUs @@ -114,6 +116,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  		goto vmalloc_fault;  #endif +retry:  	down_read(&mm->mmap_sem);  	vma = find_vma(mm, address);  	if (!vma) @@ -144,8 +147,11 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  	/* If for any reason at all we couldn't handle the fault,  	   make sure we exit gracefully rather than endlessly redo  	   the fault.  */ -	fault = handle_mm_fault(mm, vma, address, cause > 0 ? FAULT_FLAG_WRITE : 0); -	up_read(&mm->mmap_sem); +	fault = handle_mm_fault(mm, vma, address, flags); + +	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) +		return; +  	if (unlikely(fault & VM_FAULT_ERROR)) {  		if (fault & VM_FAULT_OOM)  			goto out_of_memory; @@ -153,10 +159,26 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  			goto do_sigbus;  		BUG();  	} -	if (fault & VM_FAULT_MAJOR) -		current->maj_flt++; -	else -		current->min_flt++; + +	if (flags & FAULT_FLAG_ALLOW_RETRY) { +		if (fault & VM_FAULT_MAJOR) +			current->maj_flt++; +		else +			current->min_flt++; +		if (fault & VM_FAULT_RETRY) { +			flags &= ~FAULT_FLAG_ALLOW_RETRY; + +			 /* No need to up_read(&mm->mmap_sem) as we would +			 * have already released it in __lock_page_or_retry +			 * in mm/filemap.c. +			 */ + +			goto retry; +		} +	} + +	up_read(&mm->mmap_sem); +  	return;  	/* Something tried to access memory that isn't in our memory map. @@ -186,12 +208,14 @@ do_page_fault(unsigned long address, unsigned long mmcsr,  	/* We ran out of memory, or some other thing happened to us that  	   made us unable to handle the page fault gracefully.  */   out_of_memory: +	up_read(&mm->mmap_sem);  	if (!user_mode(regs))  		goto no_context;  	pagefault_out_of_memory();  	return;   do_sigbus: +	up_read(&mm->mmap_sem);  	/* Send a sigbus, regardless of whether we were in kernel  	   or user mode.  */  	info.si_signo = SIGBUS; diff --git a/arch/alpha/oprofile/common.c b/arch/alpha/oprofile/common.c index a0a5d27aa21..b8ce18f485d 100644 --- a/arch/alpha/oprofile/common.c +++ b/arch/alpha/oprofile/common.c @@ -12,6 +12,7 @@  #include <linux/smp.h>  #include <linux/errno.h>  #include <asm/ptrace.h> +#include <asm/special_insns.h>  #include "op_impl.h" diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e91c7cdc6fe..6d6e18fee9f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -38,7 +38,6 @@ config ARM  	select HARDIRQS_SW_RESEND  	select GENERIC_IRQ_PROBE  	select GENERIC_IRQ_SHOW -	select GENERIC_IRQ_PROBE  	select ARCH_WANT_IPC_PARSE_VERSION  	select HARDIRQS_SW_RESEND  	select CPU_PM if (SUSPEND || CPU_IDLE) @@ -126,11 +125,6 @@ config TRACE_IRQFLAGS_SUPPORT  	bool  	default y -config GENERIC_LOCKBREAK -	bool -	default y -	depends on SMP && PREEMPT -  config RWSEM_GENERIC_SPINLOCK  	bool  	default y diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi index a874dbfb5ae..e6138310e5c 100644 --- a/arch/arm/boot/dts/imx23.dtsi +++ b/arch/arm/boot/dts/imx23.dtsi @@ -51,11 +51,11 @@  			dma-apbh@80004000 {  				compatible = "fsl,imx23-dma-apbh"; -				reg = <0x80004000 2000>; +				reg = <0x80004000 0x2000>;  			};  			ecc@80008000 { -				reg = <0x80008000 2000>; +				reg = <0x80008000 0x2000>;  				status = "disabled";  			}; @@ -63,7 +63,7 @@  				compatible = "fsl,imx23-gpmi-nand";  				#address-cells = <1>;  				#size-cells = <1>; -				reg = <0x8000c000 2000>, <0x8000a000 2000>; +				reg = <0x8000c000 0x2000>, <0x8000a000 0x2000>;  				reg-names = "gpmi-nand", "bch";  				interrupts = <13>, <56>;  				interrupt-names = "gpmi-dma", "bch"; @@ -72,14 +72,14 @@  			};  			ssp0: ssp@80010000 { -				reg = <0x80010000 2000>; +				reg = <0x80010000 0x2000>;  				interrupts = <15 14>;  				fsl,ssp-dma-channel = <1>;  				status = "disabled";  			};  			etm@80014000 { -				reg = <0x80014000 2000>; +				reg = <0x80014000 0x2000>;  				status = "disabled";  			}; @@ -87,7 +87,7 @@  				#address-cells = <1>;  				#size-cells = <0>;  				compatible = "fsl,imx23-pinctrl", "simple-bus"; -				reg = <0x80018000 2000>; +				reg = <0x80018000 0x2000>;  				gpio0: gpio@0 {  					compatible = "fsl,imx23-gpio", "fsl,mxs-gpio"; @@ -273,32 +273,32 @@  			};  			emi@80020000 { -				reg = <0x80020000 2000>; +				reg = <0x80020000 0x2000>;  				status = "disabled";  			};  			dma-apbx@80024000 {  				compatible = "fsl,imx23-dma-apbx"; -				reg = <0x80024000 2000>; +				reg = <0x80024000 0x2000>;  			};  			dcp@80028000 { -				reg = <0x80028000 2000>; +				reg = <0x80028000 0x2000>;  				status = "disabled";  			};  			pxp@8002a000 { -				reg = <0x8002a000 2000>; +				reg = <0x8002a000 0x2000>;  				status = "disabled";  			};  			ocotp@8002c000 { -				reg = <0x8002c000 2000>; +				reg = <0x8002c000 0x2000>;  				status = "disabled";  			};  			axi-ahb@8002e000 { -				reg = <0x8002e000 2000>; +				reg = <0x8002e000 0x2000>;  				status = "disabled";  			}; @@ -310,14 +310,14 @@  			};  			ssp1: ssp@80034000 { -				reg = <0x80034000 2000>; +				reg = <0x80034000 0x2000>;  				interrupts = <2 20>;  				fsl,ssp-dma-channel = <2>;  				status = "disabled";  			};  			tvenc@80038000 { -				reg = <0x80038000 2000>; +				reg = <0x80038000 0x2000>;  				status = "disabled";  			};                  }; @@ -330,37 +330,37 @@  			ranges;  			clkctl@80040000 { -				reg = <0x80040000 2000>; +				reg = <0x80040000 0x2000>;  				status = "disabled";  			};  			saif0: saif@80042000 { -				reg = <0x80042000 2000>; +				reg = <0x80042000 0x2000>;  				status = "disabled";  			};  			power@80044000 { -				reg = <0x80044000 2000>; +				reg = <0x80044000 0x2000>;  				status = "disabled";  			};  			saif1: saif@80046000 { -				reg = <0x80046000 2000>; +				reg = <0x80046000 0x2000>;  				status = "disabled";  			};  			audio-out@80048000 { -				reg = <0x80048000 2000>; +				reg = <0x80048000 0x2000>;  				status = "disabled";  			};  			audio-in@8004c000 { -				reg = <0x8004c000 2000>; +				reg = <0x8004c000 0x2000>;  				status = "disabled";  			};  			lradc@80050000 { -				reg = <0x80050000 2000>; +				reg = <0x80050000 0x2000>;  				status = "disabled";  			}; @@ -370,26 +370,26 @@  			};  			i2c@80058000 { -				reg = <0x80058000 2000>; +				reg = <0x80058000 0x2000>;  				status = "disabled";  			};  			rtc@8005c000 {  				compatible = "fsl,imx23-rtc", "fsl,stmp3xxx-rtc"; -				reg = <0x8005c000 2000>; +				reg = <0x8005c000 0x2000>;  				interrupts = <22>;  			};  			pwm: pwm@80064000 {  				compatible = "fsl,imx23-pwm"; -				reg = <0x80064000 2000>; +				reg = <0x80064000 0x2000>;  				#pwm-cells = <2>;  				fsl,pwm-number = <5>;  				status = "disabled";  			};  			timrot@80068000 { -				reg = <0x80068000 2000>; +				reg = <0x80068000 0x2000>;  				status = "disabled";  			}; @@ -429,7 +429,7 @@  		ranges;  		usbctrl@80080000 { -			reg = <0x80080000 0x10000>; +			reg = <0x80080000 0x40000>;  			status = "disabled";  		};  	}; diff --git a/arch/arm/boot/dts/imx27-3ds.dts b/arch/arm/boot/dts/imx27-3ds.dts index d3f8296e19e..0a8978a40ec 100644 --- a/arch/arm/boot/dts/imx27-3ds.dts +++ b/arch/arm/boot/dts/imx27-3ds.dts @@ -27,7 +27,7 @@  				status = "okay";  			}; -			uart@1000a000 { +			uart1: serial@1000a000 {  				fsl,uart-has-rtscts;  				status = "okay";  			}; diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi index 00bae3aad5a..5303ab680a3 100644 --- a/arch/arm/boot/dts/imx27.dtsi +++ b/arch/arm/boot/dts/imx27.dtsi @@ -19,6 +19,12 @@  		serial3 = &uart4;  		serial4 = &uart5;  		serial5 = &uart6; +		gpio0 = &gpio1; +		gpio1 = &gpio2; +		gpio2 = &gpio3; +		gpio3 = &gpio4; +		gpio4 = &gpio5; +		gpio5 = &gpio6;  	};  	avic: avic-interrupt-controller@e0000000 { diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index 787efac68da..3fa6d190fab 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -57,18 +57,18 @@  			};  			hsadc@80002000 { -				reg = <0x80002000 2000>; +				reg = <0x80002000 0x2000>;  				interrupts = <13 87>;  				status = "disabled";  			};  			dma-apbh@80004000 {  				compatible = "fsl,imx28-dma-apbh"; -				reg = <0x80004000 2000>; +				reg = <0x80004000 0x2000>;  			};  			perfmon@80006000 { -				reg = <0x80006000 800>; +				reg = <0x80006000 0x800>;  				interrupts = <27>;  				status = "disabled";  			}; @@ -77,7 +77,7 @@  				compatible = "fsl,imx28-gpmi-nand";  				#address-cells = <1>;  				#size-cells = <1>; -				reg = <0x8000c000 2000>, <0x8000a000 2000>; +				reg = <0x8000c000 0x2000>, <0x8000a000 0x2000>;  				reg-names = "gpmi-nand", "bch";  				interrupts = <88>, <41>;  				interrupt-names = "gpmi-dma", "bch"; @@ -86,28 +86,28 @@  			};  			ssp0: ssp@80010000 { -				reg = <0x80010000 2000>; +				reg = <0x80010000 0x2000>;  				interrupts = <96 82>;  				fsl,ssp-dma-channel = <0>;  				status = "disabled";  			};  			ssp1: ssp@80012000 { -				reg = <0x80012000 2000>; +				reg = <0x80012000 0x2000>;  				interrupts = <97 83>;  				fsl,ssp-dma-channel = <1>;  				status = "disabled";  			};  			ssp2: ssp@80014000 { -				reg = <0x80014000 2000>; +				reg = <0x80014000 0x2000>;  				interrupts = <98 84>;  				fsl,ssp-dma-channel = <2>;  				status = "disabled";  			};  			ssp3: ssp@80016000 { -				reg = <0x80016000 2000>; +				reg = <0x80016000 0x2000>;  				interrupts = <99 85>;  				fsl,ssp-dma-channel = <3>;  				status = "disabled"; @@ -117,7 +117,7 @@  				#address-cells = <1>;  				#size-cells = <0>;  				compatible = "fsl,imx28-pinctrl", "simple-bus"; -				reg = <0x80018000 2000>; +				reg = <0x80018000 0x2000>;  				gpio0: gpio@0 {  					compatible = "fsl,imx28-gpio", "fsl,mxs-gpio"; @@ -510,96 +510,96 @@  			};  			digctl@8001c000 { -				reg = <0x8001c000 2000>; +				reg = <0x8001c000 0x2000>;  				interrupts = <89>;  				status = "disabled";  			};  			etm@80022000 { -				reg = <0x80022000 2000>; +				reg = <0x80022000 0x2000>;  				status = "disabled";  			};  			dma-apbx@80024000 {  				compatible = "fsl,imx28-dma-apbx"; -				reg = <0x80024000 2000>; +				reg = <0x80024000 0x2000>;  			};  			dcp@80028000 { -				reg = <0x80028000 2000>; +				reg = <0x80028000 0x2000>;  				interrupts = <52 53 54>;  				status = "disabled";  			};  			pxp@8002a000 { -				reg = <0x8002a000 2000>; +				reg = <0x8002a000 0x2000>;  				interrupts = <39>;  				status = "disabled";  			};  			ocotp@8002c000 { -				reg = <0x8002c000 2000>; +				reg = <0x8002c000 0x2000>;  				status = "disabled";  			};  			axi-ahb@8002e000 { -				reg = <0x8002e000 2000>; +				reg = <0x8002e000 0x2000>;  				status = "disabled";  			};  			lcdif@80030000 {  				compatible = "fsl,imx28-lcdif"; -				reg = <0x80030000 2000>; +				reg = <0x80030000 0x2000>;  				interrupts = <38 86>;  				status = "disabled";  			};  			can0: can@80032000 {  				compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan"; -				reg = <0x80032000 2000>; +				reg = <0x80032000 0x2000>;  				interrupts = <8>;  				status = "disabled";  			};  			can1: can@80034000 {  				compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan"; -				reg = <0x80034000 2000>; +				reg = <0x80034000 0x2000>;  				interrupts = <9>;  				status = "disabled";  			};  			simdbg@8003c000 { -				reg = <0x8003c000 200>; +				reg = <0x8003c000 0x200>;  				status = "disabled";  			};  			simgpmisel@8003c200 { -				reg = <0x8003c200 100>; +				reg = <0x8003c200 0x100>;  				status = "disabled";  			};  			simsspsel@8003c300 { -				reg = <0x8003c300 100>; +				reg = <0x8003c300 0x100>;  				status = "disabled";  			};  			simmemsel@8003c400 { -				reg = <0x8003c400 100>; +				reg = <0x8003c400 0x100>;  				status = "disabled";  			};  			gpiomon@8003c500 { -				reg = <0x8003c500 100>; +				reg = <0x8003c500 0x100>;  				status = "disabled";  			};  			simenet@8003c700 { -				reg = <0x8003c700 100>; +				reg = <0x8003c700 0x100>;  				status = "disabled";  			};  			armjtag@8003c800 { -				reg = <0x8003c800 100>; +				reg = <0x8003c800 0x100>;  				status = "disabled";  			};                  }; @@ -612,45 +612,45 @@  			ranges;  			clkctl@80040000 { -				reg = <0x80040000 2000>; +				reg = <0x80040000 0x2000>;  				status = "disabled";  			};  			saif0: saif@80042000 {  				compatible = "fsl,imx28-saif"; -				reg = <0x80042000 2000>; +				reg = <0x80042000 0x2000>;  				interrupts = <59 80>;  				fsl,saif-dma-channel = <4>;  				status = "disabled";  			};  			power@80044000 { -				reg = <0x80044000 2000>; +				reg = <0x80044000 0x2000>;  				status = "disabled";  			};  			saif1: saif@80046000 {  				compatible = "fsl,imx28-saif"; -				reg = <0x80046000 2000>; +				reg = <0x80046000 0x2000>;  				interrupts = <58 81>;  				fsl,saif-dma-channel = <5>;  				status = "disabled";  			};  			lradc@80050000 { -				reg = <0x80050000 2000>; +				reg = <0x80050000 0x2000>;  				status = "disabled";  			};  			spdif@80054000 { -				reg = <0x80054000 2000>; +				reg = <0x80054000 0x2000>;  				interrupts = <45 66>;  				status = "disabled";  			};  			rtc@80056000 {  				compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc"; -				reg = <0x80056000 2000>; +				reg = <0x80056000 0x2000>;  				interrupts = <29>;  			}; @@ -658,7 +658,7 @@  				#address-cells = <1>;  				#size-cells = <0>;  				compatible = "fsl,imx28-i2c"; -				reg = <0x80058000 2000>; +				reg = <0x80058000 0x2000>;  				interrupts = <111 68>;  				clock-frequency = <100000>;  				status = "disabled"; @@ -668,7 +668,7 @@  				#address-cells = <1>;  				#size-cells = <0>;  				compatible = "fsl,imx28-i2c"; -				reg = <0x8005a000 2000>; +				reg = <0x8005a000 0x2000>;  				interrupts = <110 69>;  				clock-frequency = <100000>;  				status = "disabled"; @@ -676,14 +676,14 @@  			pwm: pwm@80064000 {  				compatible = "fsl,imx28-pwm", "fsl,imx23-pwm"; -				reg = <0x80064000 2000>; +				reg = <0x80064000 0x2000>;  				#pwm-cells = <2>;  				fsl,pwm-number = <8>;  				status = "disabled";  			};  			timrot@80068000 { -				reg = <0x80068000 2000>; +				reg = <0x80068000 0x2000>;  				status = "disabled";  			}; diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts index de065b5976e..cd86177a3ea 100644 --- a/arch/arm/boot/dts/imx51-babbage.dts +++ b/arch/arm/boot/dts/imx51-babbage.dts @@ -53,7 +53,7 @@  						spi-max-frequency = <6000000>;  						reg = <0>;  						interrupt-parent = <&gpio1>; -						interrupts = <8>; +						interrupts = <8 0x4>;  						regulators {  							sw1_reg: sw1 { diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi index 53cbaa3d4f9..aba28dc87fc 100644 --- a/arch/arm/boot/dts/imx51.dtsi +++ b/arch/arm/boot/dts/imx51.dtsi @@ -17,6 +17,10 @@  		serial0 = &uart1;  		serial1 = &uart2;  		serial2 = &uart3; +		gpio0 = &gpio1; +		gpio1 = &gpio2; +		gpio2 = &gpio3; +		gpio3 = &gpio4;  	};  	tzic: tz-interrupt-controller@e0000000 { diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts index 5b8eafcdbee..da895e93a99 100644 --- a/arch/arm/boot/dts/imx53-ard.dts +++ b/arch/arm/boot/dts/imx53-ard.dts @@ -64,12 +64,32 @@  			reg = <0xf4000000 0x2000000>;  			phy-mode = "mii";  			interrupt-parent = <&gpio2>; -			interrupts = <31>; +			interrupts = <31 0x8>;  			reg-io-width = <4>; +			/* +			 * VDD33A and VDDVARIO of LAN9220 are supplied by +			 * SW4_3V3 of LTC3589.  Before the regulator driver +			 * for this PMIC is available, we use a fixed dummy +			 * 3V3 regulator to get LAN9220 driver probing work. +			 */ +			vdd33a-supply = <®_3p3v>; +			vddvario-supply = <®_3p3v>;  			smsc,irq-push-pull;  		};  	}; +	regulators { +		compatible = "simple-bus"; + +		reg_3p3v: 3p3v { +			compatible = "regulator-fixed"; +			regulator-name = "3P3V"; +			regulator-min-microvolt = <3300000>; +			regulator-max-microvolt = <3300000>; +			regulator-always-on; +		}; +	}; +  	gpio-keys {  		compatible = "gpio-keys"; diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index fc79cdc4b4e..cd37165edce 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -19,6 +19,13 @@  		serial2 = &uart3;  		serial3 = &uart4;  		serial4 = &uart5; +		gpio0 = &gpio1; +		gpio1 = &gpio2; +		gpio2 = &gpio3; +		gpio3 = &gpio4; +		gpio4 = &gpio5; +		gpio5 = &gpio6; +		gpio6 = &gpio7;  	};  	tzic: tz-interrupt-controller@0fffc000 { diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts index d42e851ceb9..72f30f3e617 100644 --- a/arch/arm/boot/dts/imx6q-sabrelite.dts +++ b/arch/arm/boot/dts/imx6q-sabrelite.dts @@ -53,6 +53,7 @@  						fsl,pins = <  							   144  0x80000000	/* MX6Q_PAD_EIM_D22__GPIO_3_22 */  							   121  0x80000000	/* MX6Q_PAD_EIM_D19__GPIO_3_19 */ +							   953  0x80000000	/* MX6Q_PAD_GPIO_0__CCM_CLKO */  							   >;  					};  				}; diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 3d3c64b014e..fd57079f71a 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -19,6 +19,13 @@  		serial2 = &uart3;  		serial3 = &uart4;  		serial4 = &uart5; +		gpio0 = &gpio1; +		gpio1 = &gpio2; +		gpio2 = &gpio3; +		gpio3 = &gpio4; +		gpio4 = &gpio5; +		gpio5 = &gpio6; +		gpio6 = &gpio7;  	};  	cpus { diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index f725b9637b3..3c9f32f9b6b 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -192,6 +192,7 @@ CONFIG_RTC_DRV_MC13XXX=y  CONFIG_RTC_DRV_MXC=y  CONFIG_DMADEVICES=y  CONFIG_IMX_SDMA=y +CONFIG_MXS_DMA=y  CONFIG_COMMON_CLK_DEBUG=y  # CONFIG_IOMMU_SUPPORT is not set  CONFIG_EXT2_FS=y diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index ccdb6357fb7..4edcfb4e4de 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -34,7 +34,6 @@ CONFIG_NO_HZ=y  CONFIG_HIGH_RES_TIMERS=y  CONFIG_PREEMPT_VOLUNTARY=y  CONFIG_AEABI=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=65536  CONFIG_AUTO_ZRELADDR=y  CONFIG_FPE_NWFPE=y  CONFIG_NET=y diff --git a/arch/arm/configs/tct_hammer_defconfig b/arch/arm/configs/tct_hammer_defconfig index 1d24f8458be..71277a1591b 100644 --- a/arch/arm/configs/tct_hammer_defconfig +++ b/arch/arm/configs/tct_hammer_defconfig @@ -7,7 +7,7 @@ CONFIG_SYSFS_DEPRECATED_V2=y  CONFIG_BLK_DEV_INITRD=y  CONFIG_EXPERT=y  # CONFIG_KALLSYMS is not set -# CONFIG_BUG is not set +# CONFIG_BUGVERBOSE is not set  # CONFIG_ELF_CORE is not set  # CONFIG_SHMEM is not set  CONFIG_SLOB=y diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index f66626d71e7..41dc31f834c 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -195,6 +195,18 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)  #define pte_clear(mm,addr,ptep)	set_pte_ext(ptep, __pte(0), 0) +#define pte_none(pte)		(!pte_val(pte)) +#define pte_present(pte)	(pte_val(pte) & L_PTE_PRESENT) +#define pte_write(pte)		(!(pte_val(pte) & L_PTE_RDONLY)) +#define pte_dirty(pte)		(pte_val(pte) & L_PTE_DIRTY) +#define pte_young(pte)		(pte_val(pte) & L_PTE_YOUNG) +#define pte_exec(pte)		(!(pte_val(pte) & L_PTE_XN)) +#define pte_special(pte)	(0) + +#define pte_present_user(pte) \ +	((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ +	 (L_PTE_PRESENT | L_PTE_USER)) +  #if __LINUX_ARM_ARCH__ < 6  static inline void __sync_icache_dcache(pte_t pteval)  { @@ -206,25 +218,15 @@ extern void __sync_icache_dcache(pte_t pteval);  static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,  			      pte_t *ptep, pte_t pteval)  { -	if (addr >= TASK_SIZE) -		set_pte_ext(ptep, pteval, 0); -	else { +	unsigned long ext = 0; + +	if (addr < TASK_SIZE && pte_present_user(pteval)) {  		__sync_icache_dcache(pteval); -		set_pte_ext(ptep, pteval, PTE_EXT_NG); +		ext |= PTE_EXT_NG;  	} -} -#define pte_none(pte)		(!pte_val(pte)) -#define pte_present(pte)	(pte_val(pte) & L_PTE_PRESENT) -#define pte_write(pte)		(!(pte_val(pte) & L_PTE_RDONLY)) -#define pte_dirty(pte)		(pte_val(pte) & L_PTE_DIRTY) -#define pte_young(pte)		(pte_val(pte) & L_PTE_YOUNG) -#define pte_exec(pte)		(!(pte_val(pte) & L_PTE_XN)) -#define pte_special(pte)	(0) - -#define pte_present_user(pte) \ -	((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ -	 (L_PTE_PRESENT | L_PTE_USER)) +	set_pte_ext(ptep, pteval, ext); +}  #define PTE_BIT_FUNC(fn,op) \  static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } @@ -251,13 +253,13 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)   *   *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - *   <--------------- offset --------------------> <- type --> 0 0 0 + *   <--------------- offset ----------------------> < type -> 0 0 0   * - * This gives us up to 63 swap files and 32GB per swap file.  Note that + * This gives us up to 31 swap files and 64GB per swap file.  Note that   * the offset field is always non-zero.   */  #define __SWP_TYPE_SHIFT	3 -#define __SWP_TYPE_BITS		6 +#define __SWP_TYPE_BITS		5  #define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)  #define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index e3f75726343..05b8e82ec9f 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h @@ -10,5 +10,7 @@  extern void sched_clock_postinit(void);  extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); +extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, +		unsigned long rate);  #endif diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index 27d186abbc0..f4515393248 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c @@ -21,6 +21,8 @@ struct clock_data {  	u32 epoch_cyc_copy;  	u32 mult;  	u32 shift; +	bool suspended; +	bool needs_suspend;  };  static void sched_clock_poll(unsigned long wrap_ticks); @@ -49,6 +51,9 @@ static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask)  	u64 epoch_ns;  	u32 epoch_cyc; +	if (cd.suspended) +		return cd.epoch_ns; +  	/*  	 * Load the epoch_cyc and epoch_ns atomically.  We do this by  	 * ensuring that we always write epoch_cyc, epoch_ns and @@ -98,6 +103,13 @@ static void sched_clock_poll(unsigned long wrap_ticks)  	update_sched_clock();  } +void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, +		unsigned long rate) +{ +	setup_sched_clock(read, bits, rate); +	cd.needs_suspend = true; +} +  void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)  {  	unsigned long r, w; @@ -169,11 +181,23 @@ void __init sched_clock_postinit(void)  static int sched_clock_suspend(void)  {  	sched_clock_poll(sched_clock_timer.data); +	if (cd.needs_suspend) +		cd.suspended = true;  	return 0;  } +static void sched_clock_resume(void) +{ +	if (cd.needs_suspend) { +		cd.epoch_cyc = read_sched_clock(); +		cd.epoch_cyc_copy = cd.epoch_cyc; +		cd.suspended = false; +	} +} +  static struct syscore_ops sched_clock_ops = {  	.suspend = sched_clock_suspend, +	.resume = sched_clock_resume,  };  static int __init sched_clock_syscore_init(void) diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 198b08456e9..26c12c6440f 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -321,7 +321,7 @@ void store_cpu_topology(unsigned int cpuid)   * init_cpu_topology is called at boot when only one cpu is running   * which prevent simultaneous write access to cpu_topology array   */ -void init_cpu_topology(void) +void __init init_cpu_topology(void)  {  	unsigned int cpu; diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 2473fd1fd51..af72969820b 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -16,13 +16,30 @@ lib-y		:= backtrace.o changebit.o csumipv6.o csumpartial.o   \  		   call_with_stack.o  mmu-y	:= clear_user.o copy_page.o getuser.o putuser.o -mmu-y	+= copy_from_user.o copy_to_user.o + +# the code in uaccess.S is not preemption safe and +# probably faster on ARMv3 only +ifeq ($(CONFIG_PREEMPT),y) +  mmu-y	+= copy_from_user.o copy_to_user.o +else +ifneq ($(CONFIG_CPU_32v3),y) +  mmu-y	+= copy_from_user.o copy_to_user.o +else +  mmu-y	+= uaccess.o +endif +endif  # using lib_ here won't override already available weak symbols  obj-$(CONFIG_UACCESS_WITH_MEMCPY) += uaccess_with_memcpy.o -lib-$(CONFIG_MMU)		+= $(mmu-y) -lib-y				+= io-readsw-armv4.o io-writesw-armv4.o +lib-$(CONFIG_MMU) += $(mmu-y) + +ifeq ($(CONFIG_CPU_32v3),y) +  lib-y	+= io-readsw-armv3.o io-writesw-armv3.o +else +  lib-y	+= io-readsw-armv4.o io-writesw-armv4.o +endif +  lib-$(CONFIG_ARCH_RPC)		+= ecard.o io-acorn.o floppydma.o  lib-$(CONFIG_ARCH_SHARK)	+= io-shark.o diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S new file mode 100644 index 00000000000..88487c8c4f2 --- /dev/null +++ b/arch/arm/lib/io-readsw-armv3.S @@ -0,0 +1,106 @@ +/* + *  linux/arch/arm/lib/io-readsw-armv3.S + * + *  Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/linkage.h> +#include <asm/assembler.h> + +.Linsw_bad_alignment: +		adr	r0, .Linsw_bad_align_msg +		mov	r2, lr +		b	panic +.Linsw_bad_align_msg: +		.asciz	"insw: bad buffer alignment (0x%p, lr=0x%08lX)\n" +		.align + +.Linsw_align:	tst	r1, #1 +		bne	.Linsw_bad_alignment + +		ldr	r3, [r0] +		strb	r3, [r1], #1 +		mov	r3, r3, lsr #8 +		strb	r3, [r1], #1 + +		subs	r2, r2, #1 +		moveq	pc, lr + +ENTRY(__raw_readsw) +		teq	r2, #0		@ do we have to check for the zero len? +		moveq	pc, lr +		tst	r1, #3 +		bne	.Linsw_align + +.Linsw_aligned:	mov	ip, #0xff +		orr	ip, ip, ip, lsl #8 +		stmfd	sp!, {r4, r5, r6, lr} + +		subs	r2, r2, #8 +		bmi	.Lno_insw_8 + +.Linsw_8_lp:	ldr	r3, [r0] +		and	r3, r3, ip +		ldr	r4, [r0] +		orr	r3, r3, r4, lsl #16 + +		ldr	r4, [r0] +		and	r4, r4, ip +		ldr	r5, [r0] +		orr	r4, r4, r5, lsl #16 + +		ldr	r5, [r0] +		and	r5, r5, ip +		ldr	r6, [r0] +		orr	r5, r5, r6, lsl #16 + +		ldr	r6, [r0] +		and	r6, r6, ip +		ldr	lr, [r0] +		orr	r6, r6, lr, lsl #16 + +		stmia	r1!, {r3 - r6} + +		subs	r2, r2, #8 +		bpl	.Linsw_8_lp + +		tst	r2, #7 +		ldmeqfd	sp!, {r4, r5, r6, pc} + +.Lno_insw_8:	tst	r2, #4 +		beq	.Lno_insw_4 + +		ldr	r3, [r0] +		and	r3, r3, ip +		ldr	r4, [r0] +		orr	r3, r3, r4, lsl #16 + +		ldr	r4, [r0] +		and	r4, r4, ip +		ldr	r5, [r0] +		orr	r4, r4, r5, lsl #16 + +		stmia	r1!, {r3, r4} + +.Lno_insw_4:	tst	r2, #2 +		beq	.Lno_insw_2 + +		ldr	r3, [r0] +		and	r3, r3, ip +		ldr	r4, [r0] +		orr	r3, r3, r4, lsl #16 + +		str	r3, [r1], #4 + +.Lno_insw_2:	tst	r2, #1 +		ldrne	r3, [r0] +		strneb	r3, [r1], #1 +		movne	r3, r3, lsr #8 +		strneb	r3, [r1] + +		ldmfd	sp!, {r4, r5, r6, pc} + + diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S new file mode 100644 index 00000000000..49b800419e3 --- /dev/null +++ b/arch/arm/lib/io-writesw-armv3.S @@ -0,0 +1,126 @@ +/* + *  linux/arch/arm/lib/io-writesw-armv3.S + * + *  Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/linkage.h> +#include <asm/assembler.h> + +.Loutsw_bad_alignment: +		adr	r0, .Loutsw_bad_align_msg +		mov	r2, lr +		b	panic +.Loutsw_bad_align_msg: +		.asciz	"outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n" +		.align + +.Loutsw_align:	tst	r1, #1 +		bne	.Loutsw_bad_alignment + +		add	r1, r1, #2 + +		ldr	r3, [r1, #-4] +		mov	r3, r3, lsr #16 +		orr	r3, r3, r3, lsl #16 +		str	r3, [r0] +		subs	r2, r2, #1 +		moveq	pc, lr + +ENTRY(__raw_writesw) +		teq	r2, #0		@ do we have to check for the zero len? +		moveq	pc, lr +		tst	r1, #3 +		bne	.Loutsw_align + +		stmfd	sp!, {r4, r5, r6, lr} + +		subs	r2, r2, #8 +		bmi	.Lno_outsw_8 + +.Loutsw_8_lp:	ldmia	r1!, {r3, r4, r5, r6} + +		mov	ip, r3, lsl #16 +		orr	ip, ip, ip, lsr #16 +		str	ip, [r0] + +		mov	ip, r3, lsr #16 +		orr	ip, ip, ip, lsl #16 +		str	ip, [r0] + +		mov	ip, r4, lsl #16 +		orr	ip, ip, ip, lsr #16 +		str	ip, [r0] + +		mov	ip, r4, lsr #16 +		orr	ip, ip, ip, lsl #16 +		str	ip, [r0] + +		mov	ip, r5, lsl #16 +		orr	ip, ip, ip, lsr #16 +		str	ip, [r0] + +		mov	ip, r5, lsr #16 +		orr	ip, ip, ip, lsl #16 +		str	ip, [r0] + +		mov	ip, r6, lsl #16 +		orr	ip, ip, ip, lsr #16 +		str	ip, [r0] + +		mov	ip, r6, lsr #16 +		orr	ip, ip, ip, lsl #16 +		str	ip, [r0] + +		subs	r2, r2, #8 +		bpl	.Loutsw_8_lp + +		tst	r2, #7 +		ldmeqfd	sp!, {r4, r5, r6, pc} + +.Lno_outsw_8:	tst	r2, #4 +		beq	.Lno_outsw_4 + +		ldmia	r1!, {r3, r4} + +		mov	ip, r3, lsl #16 +		orr	ip, ip, ip, lsr #16 +		str	ip, [r0] + +		mov	ip, r3, lsr #16 +		orr	ip, ip, ip, lsl #16 +		str	ip, [r0] + +		mov	ip, r4, lsl #16 +		orr	ip, ip, ip, lsr #16 +		str	ip, [r0] + +		mov	ip, r4, lsr #16 +		orr	ip, ip, ip, lsl #16 +		str	ip, [r0] + +.Lno_outsw_4:	tst	r2, #2 +		beq	.Lno_outsw_2 + +		ldr	r3, [r1], #4 + +		mov	ip, r3, lsl #16 +		orr	ip, ip, ip, lsr #16 +		str	ip, [r0] + +		mov	ip, r3, lsr #16 +		orr	ip, ip, ip, lsl #16 +		str	ip, [r0] + +.Lno_outsw_2:	tst	r2, #1 + +		ldrne	r3, [r1] + +		movne	ip, r3, lsl #16 +		orrne	ip, ip, ip, lsr #16 +		strne	ip, [r0] + +		ldmfd	sp!, {r4, r5, r6, pc} diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S new file mode 100644 index 00000000000..5c908b1cb8e --- /dev/null +++ b/arch/arm/lib/uaccess.S @@ -0,0 +1,564 @@ +/* + *  linux/arch/arm/lib/uaccess.S + * + *  Copyright (C) 1995, 1996,1997,1998 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + *  Routines to block copy data to/from user memory + *   These are highly optimised both for the 4k page size + *   and for various alignments. + */ +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/errno.h> +#include <asm/domain.h> + +		.text + +#define PAGE_SHIFT 12 + +/* Prototype: int __copy_to_user(void *to, const char *from, size_t n) + * Purpose  : copy a block to user memory from kernel memory + * Params   : to   - user memory + *          : from - kernel memory + *          : n    - number of bytes to copy + * Returns  : Number of bytes NOT copied. + */ + +.Lc2u_dest_not_aligned: +		rsb	ip, ip, #4 +		cmp	ip, #2 +		ldrb	r3, [r1], #1 +USER(	TUSER(	strb)	r3, [r0], #1)			@ May fault +		ldrgeb	r3, [r1], #1 +USER(	TUSER(	strgeb) r3, [r0], #1)			@ May fault +		ldrgtb	r3, [r1], #1 +USER(	TUSER(	strgtb) r3, [r0], #1)			@ May fault +		sub	r2, r2, ip +		b	.Lc2u_dest_aligned + +ENTRY(__copy_to_user) +		stmfd	sp!, {r2, r4 - r7, lr} +		cmp	r2, #4 +		blt	.Lc2u_not_enough +		ands	ip, r0, #3 +		bne	.Lc2u_dest_not_aligned +.Lc2u_dest_aligned: + +		ands	ip, r1, #3 +		bne	.Lc2u_src_not_aligned +/* + * Seeing as there has to be at least 8 bytes to copy, we can + * copy one word, and force a user-mode page fault... + */ + +.Lc2u_0fupi:	subs	r2, r2, #4 +		addmi	ip, r2, #4 +		bmi	.Lc2u_0nowords +		ldr	r3, [r1], #4 +USER(	TUSER(	str)	r3, [r0], #4)			@ May fault +		mov	ip, r0, lsl #32 - PAGE_SHIFT	@ On each page, use a ld/st??t instruction +		rsb	ip, ip, #0 +		movs	ip, ip, lsr #32 - PAGE_SHIFT +		beq	.Lc2u_0fupi +/* + * ip = max no. of bytes to copy before needing another "strt" insn + */ +		cmp	r2, ip +		movlt	ip, r2 +		sub	r2, r2, ip +		subs	ip, ip, #32 +		blt	.Lc2u_0rem8lp + +.Lc2u_0cpy8lp:	ldmia	r1!, {r3 - r6} +		stmia	r0!, {r3 - r6}			@ Shouldnt fault +		ldmia	r1!, {r3 - r6} +		subs	ip, ip, #32 +		stmia	r0!, {r3 - r6}			@ Shouldnt fault +		bpl	.Lc2u_0cpy8lp + +.Lc2u_0rem8lp:	cmn	ip, #16 +		ldmgeia	r1!, {r3 - r6} +		stmgeia	r0!, {r3 - r6}			@ Shouldnt fault +		tst	ip, #8 +		ldmneia	r1!, {r3 - r4} +		stmneia	r0!, {r3 - r4}			@ Shouldnt fault +		tst	ip, #4 +		ldrne	r3, [r1], #4 +	TUSER(	strne) r3, [r0], #4			@ Shouldnt fault +		ands	ip, ip, #3 +		beq	.Lc2u_0fupi +.Lc2u_0nowords:	teq	ip, #0 +		beq	.Lc2u_finished +.Lc2u_nowords:	cmp	ip, #2 +		ldrb	r3, [r1], #1 +USER(	TUSER(	strb)	r3, [r0], #1)			@ May fault +		ldrgeb	r3, [r1], #1 +USER(	TUSER(	strgeb) r3, [r0], #1)			@ May fault +		ldrgtb	r3, [r1], #1 +USER(	TUSER(	strgtb) r3, [r0], #1)			@ May fault +		b	.Lc2u_finished + +.Lc2u_not_enough: +		movs	ip, r2 +		bne	.Lc2u_nowords +.Lc2u_finished:	mov	r0, #0 +		ldmfd	sp!, {r2, r4 - r7, pc} + +.Lc2u_src_not_aligned: +		bic	r1, r1, #3 +		ldr	r7, [r1], #4 +		cmp	ip, #2 +		bgt	.Lc2u_3fupi +		beq	.Lc2u_2fupi +.Lc2u_1fupi:	subs	r2, r2, #4 +		addmi	ip, r2, #4 +		bmi	.Lc2u_1nowords +		mov	r3, r7, pull #8 +		ldr	r7, [r1], #4 +		orr	r3, r3, r7, push #24 +USER(	TUSER(	str)	r3, [r0], #4)			@ May fault +		mov	ip, r0, lsl #32 - PAGE_SHIFT +		rsb	ip, ip, #0 +		movs	ip, ip, lsr #32 - PAGE_SHIFT +		beq	.Lc2u_1fupi +		cmp	r2, ip +		movlt	ip, r2 +		sub	r2, r2, ip +		subs	ip, ip, #16 +		blt	.Lc2u_1rem8lp + +.Lc2u_1cpy8lp:	mov	r3, r7, pull #8 +		ldmia	r1!, {r4 - r7} +		subs	ip, ip, #16 +		orr	r3, r3, r4, push #24 +		mov	r4, r4, pull #8 +		orr	r4, r4, r5, push #24 +		mov	r5, r5, pull #8 +		orr	r5, r5, r6, push #24 +		mov	r6, r6, pull #8 +		orr	r6, r6, r7, push #24 +		stmia	r0!, {r3 - r6}			@ Shouldnt fault +		bpl	.Lc2u_1cpy8lp + +.Lc2u_1rem8lp:	tst	ip, #8 +		movne	r3, r7, pull #8 +		ldmneia	r1!, {r4, r7} +		orrne	r3, r3, r4, push #24 +		movne	r4, r4, pull #8 +		orrne	r4, r4, r7, push #24 +		stmneia	r0!, {r3 - r4}			@ Shouldnt fault +		tst	ip, #4 +		movne	r3, r7, pull #8 +		ldrne	r7, [r1], #4 +		orrne	r3, r3, r7, push #24 +	TUSER(	strne) r3, [r0], #4			@ Shouldnt fault +		ands	ip, ip, #3 +		beq	.Lc2u_1fupi +.Lc2u_1nowords:	mov	r3, r7, get_byte_1 +		teq	ip, #0 +		beq	.Lc2u_finished +		cmp	ip, #2 +USER(	TUSER(	strb)	r3, [r0], #1)			@ May fault +		movge	r3, r7, get_byte_2 +USER(	TUSER(	strgeb) r3, [r0], #1)			@ May fault +		movgt	r3, r7, get_byte_3 +USER(	TUSER(	strgtb) r3, [r0], #1)			@ May fault +		b	.Lc2u_finished + +.Lc2u_2fupi:	subs	r2, r2, #4 +		addmi	ip, r2, #4 +		bmi	.Lc2u_2nowords +		mov	r3, r7, pull #16 +		ldr	r7, [r1], #4 +		orr	r3, r3, r7, push #16 +USER(	TUSER(	str)	r3, [r0], #4)			@ May fault +		mov	ip, r0, lsl #32 - PAGE_SHIFT +		rsb	ip, ip, #0 +		movs	ip, ip, lsr #32 - PAGE_SHIFT +		beq	.Lc2u_2fupi +		cmp	r2, ip +		movlt	ip, r2 +		sub	r2, r2, ip +		subs	ip, ip, #16 +		blt	.Lc2u_2rem8lp + +.Lc2u_2cpy8lp:	mov	r3, r7, pull #16 +		ldmia	r1!, {r4 - r7} +		subs	ip, ip, #16 +		orr	r3, r3, r4, push #16 +		mov	r4, r4, pull #16 +		orr	r4, r4, r5, push #16 +		mov	r5, r5, pull #16 +		orr	r5, r5, r6, push #16 +		mov	r6, r6, pull #16 +		orr	r6, r6, r7, push #16 +		stmia	r0!, {r3 - r6}			@ Shouldnt fault +		bpl	.Lc2u_2cpy8lp + +.Lc2u_2rem8lp:	tst	ip, #8 +		movne	r3, r7, pull #16 +		ldmneia	r1!, {r4, r7} +		orrne	r3, r3, r4, push #16 +		movne	r4, r4, pull #16 +		orrne	r4, r4, r7, push #16 +		stmneia	r0!, {r3 - r4}			@ Shouldnt fault +		tst	ip, #4 +		movne	r3, r7, pull #16 +		ldrne	r7, [r1], #4 +		orrne	r3, r3, r7, push #16 +	TUSER(	strne) r3, [r0], #4			@ Shouldnt fault +		ands	ip, ip, #3 +		beq	.Lc2u_2fupi +.Lc2u_2nowords:	mov	r3, r7, get_byte_2 +		teq	ip, #0 +		beq	.Lc2u_finished +		cmp	ip, #2 +USER(	TUSER(	strb)	r3, [r0], #1)			@ May fault +		movge	r3, r7, get_byte_3 +USER(	TUSER(	strgeb) r3, [r0], #1)			@ May fault +		ldrgtb	r3, [r1], #0 +USER(	TUSER(	strgtb) r3, [r0], #1)			@ May fault +		b	.Lc2u_finished + +.Lc2u_3fupi:	subs	r2, r2, #4 +		addmi	ip, r2, #4 +		bmi	.Lc2u_3nowords +		mov	r3, r7, pull #24 +		ldr	r7, [r1], #4 +		orr	r3, r3, r7, push #8 +USER(	TUSER(	str)	r3, [r0], #4)			@ May fault +		mov	ip, r0, lsl #32 - PAGE_SHIFT +		rsb	ip, ip, #0 +		movs	ip, ip, lsr #32 - PAGE_SHIFT +		beq	.Lc2u_3fupi +		cmp	r2, ip +		movlt	ip, r2 +		sub	r2, r2, ip +		subs	ip, ip, #16 +		blt	.Lc2u_3rem8lp + +.Lc2u_3cpy8lp:	mov	r3, r7, pull #24 +		ldmia	r1!, {r4 - r7} +		subs	ip, ip, #16 +		orr	r3, r3, r4, push #8 +		mov	r4, r4, pull #24 +		orr	r4, r4, r5, push #8 +		mov	r5, r5, pull #24 +		orr	r5, r5, r6, push #8 +		mov	r6, r6, pull #24 +		orr	r6, r6, r7, push #8 +		stmia	r0!, {r3 - r6}			@ Shouldnt fault +		bpl	.Lc2u_3cpy8lp + +.Lc2u_3rem8lp:	tst	ip, #8 +		movne	r3, r7, pull #24 +		ldmneia	r1!, {r4, r7} +		orrne	r3, r3, r4, push #8 +		movne	r4, r4, pull #24 +		orrne	r4, r4, r7, push #8 +		stmneia	r0!, {r3 - r4}			@ Shouldnt fault +		tst	ip, #4 +		movne	r3, r7, pull #24 +		ldrne	r7, [r1], #4 +		orrne	r3, r3, r7, push #8 +	TUSER(	strne) r3, [r0], #4			@ Shouldnt fault +		ands	ip, ip, #3 +		beq	.Lc2u_3fupi +.Lc2u_3nowords:	mov	r3, r7, get_byte_3 +		teq	ip, #0 +		beq	.Lc2u_finished +		cmp	ip, #2 +USER(	TUSER(	strb)	r3, [r0], #1)			@ May fault +		ldrgeb	r3, [r1], #1 +USER(	TUSER(	strgeb) r3, [r0], #1)			@ May fault +		ldrgtb	r3, [r1], #0 +USER(	TUSER(	strgtb) r3, [r0], #1)			@ May fault +		b	.Lc2u_finished +ENDPROC(__copy_to_user) + +		.pushsection .fixup,"ax" +		.align	0 +9001:		ldmfd	sp!, {r0, r4 - r7, pc} +		.popsection + +/* Prototype: unsigned long __copy_from_user(void *to,const void *from,unsigned long n); + * Purpose  : copy a block from user memory to kernel memory + * Params   : to   - kernel memory + *          : from - user memory + *          : n    - number of bytes to copy + * Returns  : Number of bytes NOT copied. + */ +.Lcfu_dest_not_aligned: +		rsb	ip, ip, #4 +		cmp	ip, #2 +USER(	TUSER(	ldrb)	r3, [r1], #1)			@ May fault +		strb	r3, [r0], #1 +USER(	TUSER(	ldrgeb) r3, [r1], #1)			@ May fault +		strgeb	r3, [r0], #1 +USER(	TUSER(	ldrgtb) r3, [r1], #1)			@ May fault +		strgtb	r3, [r0], #1 +		sub	r2, r2, ip +		b	.Lcfu_dest_aligned + +ENTRY(__copy_from_user) +		stmfd	sp!, {r0, r2, r4 - r7, lr} +		cmp	r2, #4 +		blt	.Lcfu_not_enough +		ands	ip, r0, #3 +		bne	.Lcfu_dest_not_aligned +.Lcfu_dest_aligned: +		ands	ip, r1, #3 +		bne	.Lcfu_src_not_aligned + +/* + * Seeing as there has to be at least 8 bytes to copy, we can + * copy one word, and force a user-mode page fault... + */ + +.Lcfu_0fupi:	subs	r2, r2, #4 +		addmi	ip, r2, #4 +		bmi	.Lcfu_0nowords +USER(	TUSER(	ldr)	r3, [r1], #4) +		str	r3, [r0], #4 +		mov	ip, r1, lsl #32 - PAGE_SHIFT	@ On each page, use a ld/st??t instruction +		rsb	ip, ip, #0 +		movs	ip, ip, lsr #32 - PAGE_SHIFT +		beq	.Lcfu_0fupi +/* + * ip = max no. of bytes to copy before needing another "strt" insn + */ +		cmp	r2, ip +		movlt	ip, r2 +		sub	r2, r2, ip +		subs	ip, ip, #32 +		blt	.Lcfu_0rem8lp + +.Lcfu_0cpy8lp:	ldmia	r1!, {r3 - r6}			@ Shouldnt fault +		stmia	r0!, {r3 - r6} +		ldmia	r1!, {r3 - r6}			@ Shouldnt fault +		subs	ip, ip, #32 +		stmia	r0!, {r3 - r6} +		bpl	.Lcfu_0cpy8lp + +.Lcfu_0rem8lp:	cmn	ip, #16 +		ldmgeia	r1!, {r3 - r6}			@ Shouldnt fault +		stmgeia	r0!, {r3 - r6} +		tst	ip, #8 +		ldmneia	r1!, {r3 - r4}			@ Shouldnt fault +		stmneia	r0!, {r3 - r4} +		tst	ip, #4 +	TUSER(	ldrne) r3, [r1], #4			@ Shouldnt fault +		strne	r3, [r0], #4 +		ands	ip, ip, #3 +		beq	.Lcfu_0fupi +.Lcfu_0nowords:	teq	ip, #0 +		beq	.Lcfu_finished +.Lcfu_nowords:	cmp	ip, #2 +USER(	TUSER(	ldrb)	r3, [r1], #1)			@ May fault +		strb	r3, [r0], #1 +USER(	TUSER(	ldrgeb) r3, [r1], #1)			@ May fault +		strgeb	r3, [r0], #1 +USER(	TUSER(	ldrgtb) r3, [r1], #1)			@ May fault +		strgtb	r3, [r0], #1 +		b	.Lcfu_finished + +.Lcfu_not_enough: +		movs	ip, r2 +		bne	.Lcfu_nowords +.Lcfu_finished:	mov	r0, #0 +		add	sp, sp, #8 +		ldmfd	sp!, {r4 - r7, pc} + +.Lcfu_src_not_aligned: +		bic	r1, r1, #3 +USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault +		cmp	ip, #2 +		bgt	.Lcfu_3fupi +		beq	.Lcfu_2fupi +.Lcfu_1fupi:	subs	r2, r2, #4 +		addmi	ip, r2, #4 +		bmi	.Lcfu_1nowords +		mov	r3, r7, pull #8 +USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault +		orr	r3, r3, r7, push #24 +		str	r3, [r0], #4 +		mov	ip, r1, lsl #32 - PAGE_SHIFT +		rsb	ip, ip, #0 +		movs	ip, ip, lsr #32 - PAGE_SHIFT +		beq	.Lcfu_1fupi +		cmp	r2, ip +		movlt	ip, r2 +		sub	r2, r2, ip +		subs	ip, ip, #16 +		blt	.Lcfu_1rem8lp + +.Lcfu_1cpy8lp:	mov	r3, r7, pull #8 +		ldmia	r1!, {r4 - r7}			@ Shouldnt fault +		subs	ip, ip, #16 +		orr	r3, r3, r4, push #24 +		mov	r4, r4, pull #8 +		orr	r4, r4, r5, push #24 +		mov	r5, r5, pull #8 +		orr	r5, r5, r6, push #24 +		mov	r6, r6, pull #8 +		orr	r6, r6, r7, push #24 +		stmia	r0!, {r3 - r6} +		bpl	.Lcfu_1cpy8lp + +.Lcfu_1rem8lp:	tst	ip, #8 +		movne	r3, r7, pull #8 +		ldmneia	r1!, {r4, r7}			@ Shouldnt fault +		orrne	r3, r3, r4, push #24 +		movne	r4, r4, pull #8 +		orrne	r4, r4, r7, push #24 +		stmneia	r0!, {r3 - r4} +		tst	ip, #4 +		movne	r3, r7, pull #8 +USER(	TUSER(	ldrne) r7, [r1], #4)			@ May fault +		orrne	r3, r3, r7, push #24 +		strne	r3, [r0], #4 +		ands	ip, ip, #3 +		beq	.Lcfu_1fupi +.Lcfu_1nowords:	mov	r3, r7, get_byte_1 +		teq	ip, #0 +		beq	.Lcfu_finished +		cmp	ip, #2 +		strb	r3, [r0], #1 +		movge	r3, r7, get_byte_2 +		strgeb	r3, [r0], #1 +		movgt	r3, r7, get_byte_3 +		strgtb	r3, [r0], #1 +		b	.Lcfu_finished + +.Lcfu_2fupi:	subs	r2, r2, #4 +		addmi	ip, r2, #4 +		bmi	.Lcfu_2nowords +		mov	r3, r7, pull #16 +USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault +		orr	r3, r3, r7, push #16 +		str	r3, [r0], #4 +		mov	ip, r1, lsl #32 - PAGE_SHIFT +		rsb	ip, ip, #0 +		movs	ip, ip, lsr #32 - PAGE_SHIFT +		beq	.Lcfu_2fupi +		cmp	r2, ip +		movlt	ip, r2 +		sub	r2, r2, ip +		subs	ip, ip, #16 +		blt	.Lcfu_2rem8lp + + +.Lcfu_2cpy8lp:	mov	r3, r7, pull #16 +		ldmia	r1!, {r4 - r7}			@ Shouldnt fault +		subs	ip, ip, #16 +		orr	r3, r3, r4, push #16 +		mov	r4, r4, pull #16 +		orr	r4, r4, r5, push #16 +		mov	r5, r5, pull #16 +		orr	r5, r5, r6, push #16 +		mov	r6, r6, pull #16 +		orr	r6, r6, r7, push #16 +		stmia	r0!, {r3 - r6} +		bpl	.Lcfu_2cpy8lp + +.Lcfu_2rem8lp:	tst	ip, #8 +		movne	r3, r7, pull #16 +		ldmneia	r1!, {r4, r7}			@ Shouldnt fault +		orrne	r3, r3, r4, push #16 +		movne	r4, r4, pull #16 +		orrne	r4, r4, r7, push #16 +		stmneia	r0!, {r3 - r4} +		tst	ip, #4 +		movne	r3, r7, pull #16 +USER(	TUSER(	ldrne) r7, [r1], #4)			@ May fault +		orrne	r3, r3, r7, push #16 +		strne	r3, [r0], #4 +		ands	ip, ip, #3 +		beq	.Lcfu_2fupi +.Lcfu_2nowords:	mov	r3, r7, get_byte_2 +		teq	ip, #0 +		beq	.Lcfu_finished +		cmp	ip, #2 +		strb	r3, [r0], #1 +		movge	r3, r7, get_byte_3 +		strgeb	r3, [r0], #1 +USER(	TUSER(	ldrgtb) r3, [r1], #0)			@ May fault +		strgtb	r3, [r0], #1 +		b	.Lcfu_finished + +.Lcfu_3fupi:	subs	r2, r2, #4 +		addmi	ip, r2, #4 +		bmi	.Lcfu_3nowords +		mov	r3, r7, pull #24 +USER(	TUSER(	ldr)	r7, [r1], #4)			@ May fault +		orr	r3, r3, r7, push #8 +		str	r3, [r0], #4 +		mov	ip, r1, lsl #32 - PAGE_SHIFT +		rsb	ip, ip, #0 +		movs	ip, ip, lsr #32 - PAGE_SHIFT +		beq	.Lcfu_3fupi +		cmp	r2, ip +		movlt	ip, r2 +		sub	r2, r2, ip +		subs	ip, ip, #16 +		blt	.Lcfu_3rem8lp + +.Lcfu_3cpy8lp:	mov	r3, r7, pull #24 +		ldmia	r1!, {r4 - r7}			@ Shouldnt fault +		orr	r3, r3, r4, push #8 +		mov	r4, r4, pull #24 +		orr	r4, r4, r5, push #8 +		mov	r5, r5, pull #24 +		orr	r5, r5, r6, push #8 +		mov	r6, r6, pull #24 +		orr	r6, r6, r7, push #8 +		stmia	r0!, {r3 - r6} +		subs	ip, ip, #16 +		bpl	.Lcfu_3cpy8lp + +.Lcfu_3rem8lp:	tst	ip, #8 +		movne	r3, r7, pull #24 +		ldmneia	r1!, {r4, r7}			@ Shouldnt fault +		orrne	r3, r3, r4, push #8 +		movne	r4, r4, pull #24 +		orrne	r4, r4, r7, push #8 +		stmneia	r0!, {r3 - r4} +		tst	ip, #4 +		movne	r3, r7, pull #24 +USER(	TUSER(	ldrne) r7, [r1], #4)			@ May fault +		orrne	r3, r3, r7, push #8 +		strne	r3, [r0], #4 +		ands	ip, ip, #3 +		beq	.Lcfu_3fupi +.Lcfu_3nowords:	mov	r3, r7, get_byte_3 +		teq	ip, #0 +		beq	.Lcfu_finished +		cmp	ip, #2 +		strb	r3, [r0], #1 +USER(	TUSER(	ldrgeb) r3, [r1], #1)			@ May fault +		strgeb	r3, [r0], #1 +USER(	TUSER(	ldrgtb) r3, [r1], #1)			@ May fault +		strgtb	r3, [r0], #1 +		b	.Lcfu_finished +ENDPROC(__copy_from_user) + +		.pushsection .fixup,"ax" +		.align	0 +		/* +		 * We took an exception.  r0 contains a pointer to +		 * the byte not copied. +		 */ +9001:		ldr	r2, [sp], #4			@ void *to +		sub	r2, r0, r2			@ bytes copied +		ldr	r1, [sp], #4			@ unsigned long count +		subs	r4, r1, r2			@ bytes left to copy +		movne	r1, r4 +		blne	__memzero +		mov	r0, r4 +		ldmfd	sp!, {r4 - r7, pc} +		.popsection + diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 5de69f2fcca..f6b9fc70161 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -162,38 +162,6 @@ static void __init davinci_ntosd2_map_io(void)  	dm644x_init();  } -/* - I2C initialization -*/ -static struct davinci_i2c_platform_data ntosd2_i2c_pdata = { -	.bus_freq	= 20 /* kHz */, -	.bus_delay	= 100 /* usec */, -}; - -static struct i2c_board_info __initdata ntosd2_i2c_info[] =  { -}; - -static	int ntosd2_init_i2c(void) -{ -	int	status; - -	davinci_init_i2c(&ntosd2_i2c_pdata); -	status = gpio_request(NTOSD2_MSP430_IRQ, ntosd2_i2c_info[0].type); -	if (status == 0) { -		status = gpio_direction_input(NTOSD2_MSP430_IRQ); -		if (status == 0) { -			status = gpio_to_irq(NTOSD2_MSP430_IRQ); -			if (status > 0) { -				ntosd2_i2c_info[0].irq = status; -				i2c_register_board_info(1, -					ntosd2_i2c_info, -					ARRAY_SIZE(ntosd2_i2c_info)); -			} -		} -	} -	return status; -} -  static struct davinci_mmc_config davinci_ntosd2_mmc_config = {  	.wires		= 4,  	.version	= MMC_CTLR_VERSION_1 @@ -218,7 +186,6 @@ static __init void davinci_ntosd2_init(void)  {  	struct clk *aemif_clk;  	struct davinci_soc_info *soc_info = &davinci_soc_info; -	int	status;  	aemif_clk = clk_get(NULL, "aemif");  	clk_enable(aemif_clk); @@ -242,12 +209,6 @@ static __init void davinci_ntosd2_init(void)  	platform_add_devices(davinci_ntosd2_devices,  				ARRAY_SIZE(davinci_ntosd2_devices)); -	/* Initialize I2C interface specific for this board */ -	status = ntosd2_init_i2c(); -	if (status < 0) -		pr_warning("davinci_ntosd2_init: msp430 irq setup failed:" -						"	 %d\n", status); -  	davinci_serial_init(&uart_config);  	dm644x_init_asp(&dm644x_ntosd2_snd_data); diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c index 373c3c00d24..c0bc83a7663 100644 --- a/arch/arm/mach-exynos/pm_domains.c +++ b/arch/arm/mach-exynos/pm_domains.c @@ -115,7 +115,7 @@ static __init int exynos_pm_dt_parse_domains(void)  }  #endif /* CONFIG_OF */ -static __init void exynos_pm_add_dev_to_genpd(struct platform_device *pdev, +static __init __maybe_unused void exynos_pm_add_dev_to_genpd(struct platform_device *pdev,  						struct exynos_pm_domain *pd)  {  	if (pdev->dev.bus) { diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c index 7aa6313fb16..f69ca468004 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/arch/arm/mach-imx/clk-imx27.c @@ -223,7 +223,7 @@ int __init mx27_clocks_init(unsigned long fref)  	clk_register_clkdev(clk[per3_gate], "per", "imx-fb.0");  	clk_register_clkdev(clk[lcdc_ipg_gate], "ipg", "imx-fb.0");  	clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx-fb.0"); -	clk_register_clkdev(clk[csi_ahb_gate], NULL, "mx2-camera.0"); +	clk_register_clkdev(clk[csi_ahb_gate], "ahb", "mx2-camera.0");  	clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");  	clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc");  	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc"); @@ -250,8 +250,10 @@ int __init mx27_clocks_init(unsigned long fref)  	clk_register_clkdev(clk[i2c2_ipg_gate], NULL, "imx-i2c.1");  	clk_register_clkdev(clk[owire_ipg_gate], NULL, "mxc_w1.0");  	clk_register_clkdev(clk[kpp_ipg_gate], NULL, "imx-keypad"); -	clk_register_clkdev(clk[emma_ahb_gate], "ahb", "imx-emma"); -	clk_register_clkdev(clk[emma_ipg_gate], "ipg", "imx-emma"); +	clk_register_clkdev(clk[emma_ahb_gate], "emma-ahb", "mx2-camera.0"); +	clk_register_clkdev(clk[emma_ipg_gate], "emma-ipg", "mx2-camera.0"); +	clk_register_clkdev(clk[emma_ahb_gate], "ahb", "m2m-emmaprp.0"); +	clk_register_clkdev(clk[emma_ipg_gate], "ipg", "m2m-emmaprp.0");  	clk_register_clkdev(clk[iim_ipg_gate], "iim", NULL);  	clk_register_clkdev(clk[gpio_ipg_gate], "gpio", NULL);  	clk_register_clkdev(clk[brom_ahb_gate], "brom", NULL); diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c index 8e19e70f90f..1253af2d997 100644 --- a/arch/arm/mach-imx/clk-imx31.c +++ b/arch/arm/mach-imx/clk-imx31.c @@ -130,7 +130,7 @@ int __init mx31_clocks_init(unsigned long fref)  	clk_register_clkdev(clk[nfc], NULL, "mxc_nand.0");  	clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core");  	clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb"); -	clk_register_clkdev(clk[kpp_gate], "kpp", NULL); +	clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad");  	clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.0");  	clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.0");  	clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0"); diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index f6086693ebd..4bdcaa97bd9 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c @@ -303,6 +303,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,  	clk_prepare_enable(clk[aips_tz2]); /* fec */  	clk_prepare_enable(clk[spba]);  	clk_prepare_enable(clk[emi_fast_gate]); /* fec */ +	clk_prepare_enable(clk[emi_slow_gate]); /* eim */  	clk_prepare_enable(clk[tmax1]);  	clk_prepare_enable(clk[tmax2]); /* esdhc2, fec */  	clk_prepare_enable(clk[tmax3]); /* esdhc1, esdhc4 */ diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index ebf680bebdf..3fa6c51390d 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -11,6 +11,7 @@  #include <linux/kernel.h>  #include <linux/init.h>  #include <linux/device.h> +#include <linux/export.h>  #include <linux/spinlock.h>  #include <linux/interrupt.h>  #include <linux/irq.h> diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 7b1055c8e0b..3b2267529f5 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -456,7 +456,7 @@ static void __init ap_init_timer(void)  	clk = clk_get_sys("ap_timer", NULL);  	BUG_ON(IS_ERR(clk)); -	clk_enable(clk); +	clk_prepare_enable(clk);  	rate = clk_get_rate(clk);  	writel(0, TIMER0_VA_BASE + TIMER_CTRL); diff --git a/arch/arm/mach-kirkwood/Makefile.boot b/arch/arm/mach-kirkwood/Makefile.boot index 2a576abf409..a5717558ee8 100644 --- a/arch/arm/mach-kirkwood/Makefile.boot +++ b/arch/arm/mach-kirkwood/Makefile.boot @@ -9,5 +9,5 @@ dtb-$(CONFIG_MACH_ICONNECT_DT) += kirkwood-iconnect.dtb  dtb-$(CONFIG_MACH_IB62X0_DT) += kirkwood-ib62x0.dtb  dtb-$(CONFIG_MACH_TS219_DT)	+= kirkwood-qnap-ts219.dtb  dtb-$(CONFIG_MACH_GOFLEXNET_DT) += kirkwood-goflexnet.dtb -dbt-$(CONFIG_MACH_LSXL_DT) += kirkwood-lschlv2.dtb -dbt-$(CONFIG_MACH_LSXL_DT) += kirkwood-lsxhl.dtb +dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lschlv2.dtb +dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lsxhl.dtb diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig index ccdf83b17cf..9a8bbda195b 100644 --- a/arch/arm/mach-mxs/Kconfig +++ b/arch/arm/mach-mxs/Kconfig @@ -2,9 +2,6 @@ if ARCH_MXS  source "arch/arm/mach-mxs/devices/Kconfig" -config MXS_OCOTP -	bool -  config SOC_IMX23  	bool  	select ARM_AMBA @@ -66,7 +63,6 @@ config MACH_MX28EVK  	select MXS_HAVE_PLATFORM_MXS_SAIF  	select MXS_HAVE_PLATFORM_MXS_I2C  	select MXS_HAVE_PLATFORM_RTC_STMP3XXX -	select MXS_OCOTP  	help  	  Include support for MX28EVK platform. This includes specific  	  configurations for the board and its peripherals. @@ -94,7 +90,6 @@ config MODULE_M28  	select MXS_HAVE_PLATFORM_MXS_I2C  	select MXS_HAVE_PLATFORM_MXS_MMC  	select MXS_HAVE_PLATFORM_MXSFB -	select MXS_OCOTP  config MODULE_APX4  	bool @@ -106,7 +101,6 @@ config MODULE_APX4  	select MXS_HAVE_PLATFORM_MXS_I2C  	select MXS_HAVE_PLATFORM_MXS_MMC  	select MXS_HAVE_PLATFORM_MXS_SAIF -	select MXS_OCOTP  config MACH_TX28  	bool "Ka-Ro TX28 module" diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile index e41590ccb43..fed3695a133 100644 --- a/arch/arm/mach-mxs/Makefile +++ b/arch/arm/mach-mxs/Makefile @@ -1,7 +1,6 @@  # Common support -obj-y := devices.o icoll.o iomux.o system.o timer.o mm.o +obj-y := devices.o icoll.o iomux.o ocotp.o system.o timer.o mm.o -obj-$(CONFIG_MXS_OCOTP) += ocotp.o  obj-$(CONFIG_PM) += pm.o  obj-$(CONFIG_MACH_MXS_DT) += mach-mxs.o diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 5905ed130e9..d89d87ae144 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -953,12 +953,12 @@ static struct i2c_board_info raumfeld_connector_i2c_board_info __initdata = {  static struct eeti_ts_platform_data eeti_ts_pdata = {  	.irq_active_high = 1, +	.irq_gpio = GPIO_TOUCH_IRQ,  };  static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = {  	.type	= "eeti_ts",  	.addr	= 0x0a, -	.irq	= PXA_GPIO_TO_IRQ(GPIO_TOUCH_IRQ),  	.platform_data = &eeti_ts_pdata,  }; diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig index e24961109b7..d56b0f7f2b2 100644 --- a/arch/arm/mach-s3c24xx/Kconfig +++ b/arch/arm/mach-s3c24xx/Kconfig @@ -483,7 +483,7 @@ config MACH_NEO1973_GTA02  	select I2C  	select POWER_SUPPLY  	select MACH_NEO1973 -	select S3C2410_PWM +	select S3C24XX_PWM  	select S3C_DEV_USB_HOST  	help  	   Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone @@ -493,7 +493,7 @@ config MACH_RX1950  	select S3C24XX_DCLK  	select PM_H1940 if PM  	select I2C -	select S3C2410_PWM +	select S3C24XX_PWM  	select S3C_DEV_NAND  	select S3C2410_IOTIMING if S3C2440_CPUFREQ  	select S3C2440_XTAL_16934400 diff --git a/arch/arm/mach-sa1100/leds-hackkit.c b/arch/arm/mach-sa1100/leds-hackkit.c index 6a2352436e6..f8e47235bab 100644 --- a/arch/arm/mach-sa1100/leds-hackkit.c +++ b/arch/arm/mach-sa1100/leds-hackkit.c @@ -10,6 +10,7 @@   * as cpu led, the green one is used as timer led.   */  #include <linux/init.h> +#include <linux/io.h>  #include <mach/hardware.h>  #include <asm/leds.h> diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c index 8fd387bf31f..b7344beec10 100644 --- a/arch/arm/mach-tegra/board-harmony-power.c +++ b/arch/arm/mach-tegra/board-harmony-power.c @@ -51,7 +51,7 @@ static struct regulator_init_data ldo0_data = {  	.consumer_supplies = tps658621_ldo0_supply,  }; -#define HARMONY_REGULATOR_INIT(_id, _name, _supply, _minmv, _maxmv)	\ +#define HARMONY_REGULATOR_INIT(_id, _name, _supply, _minmv, _maxmv, _on)\  	static struct regulator_init_data _id##_data = {		\  		.supply_regulator = _supply,				\  		.constraints = {					\ @@ -63,21 +63,22 @@ static struct regulator_init_data ldo0_data = {  			.valid_ops_mask = (REGULATOR_CHANGE_MODE |	\  					   REGULATOR_CHANGE_STATUS |	\  					   REGULATOR_CHANGE_VOLTAGE),	\ +			.always_on = _on,				\  		},							\  	} -HARMONY_REGULATOR_INIT(sm0,  "vdd_sm0",  "vdd_sys", 725, 1500); -HARMONY_REGULATOR_INIT(sm1,  "vdd_sm1",  "vdd_sys", 725, 1500); -HARMONY_REGULATOR_INIT(sm2,  "vdd_sm2",  "vdd_sys", 3000, 4550); -HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500); -HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500); -HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300); -HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475); -HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", NULL,	    1250, 3300); -HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300); -HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300); -HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300); -HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300); +HARMONY_REGULATOR_INIT(sm0,  "vdd_sm0",  "vdd_sys", 725, 1500, 1); +HARMONY_REGULATOR_INIT(sm1,  "vdd_sm1",  "vdd_sys", 725, 1500, 1); +HARMONY_REGULATOR_INIT(sm2,  "vdd_sm2",  "vdd_sys", 3000, 4550, 1); +HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500, 1); +HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500, 0); +HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300, 1); +HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475, 1); +HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", NULL,	    1250, 3300, 1); +HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300, 0); +HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300, 0); +HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300, 0); +HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300, 1);  #define TPS_REG(_id, _data)			\  	{					\ @@ -119,9 +120,10 @@ static struct i2c_board_info __initdata harmony_regulators[] = {  int __init harmony_regulator_init(void)  { +	regulator_register_always_on(0, "vdd_sys", +		NULL, 0, 5000000); +  	if (machine_is_harmony()) { -		regulator_register_always_on(0, "vdd_sys", -			NULL, 0, 5000000);  		i2c_register_board_info(3, harmony_regulators, 1);  	} else { /* Harmony, booted using device tree */  		struct device_node *np; diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index c2cdf6500f7..4e7d1182e8a 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -358,7 +358,7 @@ void __init dma_contiguous_remap(void)  		if (end > arm_lowmem_limit)  			end = arm_lowmem_limit;  		if (start >= end) -			return; +			continue;  		map.pfn = __phys_to_pfn(start);  		map.virtual = __phys_to_virt(start); @@ -423,7 +423,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)  	unsigned int pageno;  	unsigned long flags;  	void *ptr = NULL; -	size_t align; +	unsigned long align_mask;  	if (!pool->vaddr) {  		WARN(1, "coherent pool not initialised!\n"); @@ -435,11 +435,11 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)  	 * small, so align them to their order in pages, minimum is a page  	 * size. This helps reduce fragmentation of the DMA space.  	 */ -	align = PAGE_SIZE << get_order(size); +	align_mask = (1 << get_order(size)) - 1;  	spin_lock_irqsave(&pool->lock, flags);  	pageno = bitmap_find_next_zero_area(pool->bitmap, pool->nr_pages, -					    0, count, (1 << align) - 1); +					    0, count, align_mask);  	if (pageno < pool->nr_pages) {  		bitmap_set(pool->bitmap, pageno, count);  		ptr = pool->vaddr + PAGE_SIZE * pageno; @@ -648,12 +648,12 @@ 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 (__free_from_pool(cpu_addr, size)) { +		return;  	} else if (!IS_ENABLED(CONFIG_CMA)) {  		__dma_free_remap(cpu_addr, size);  		__dma_free_buffer(page, size);  	} else { -		if (__free_from_pool(cpu_addr, size)) -			return;  		/*  		 * Non-atomic allocations cannot be freed with IRQs disabled  		 */ diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 77458548e03..40ca11ed6e5 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -231,8 +231,6 @@ void __sync_icache_dcache(pte_t pteval)  	struct page *page;  	struct address_space *mapping; -	if (!pte_present_user(pteval)) -		return;  	if (cache_is_vipt_nonaliasing() && !pte_exec(pteval))  		/* only flush non-aliasing VIPT caches for exec mappings */  		return; diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S index c2021139cb5..ea94765acf9 100644 --- a/arch/arm/mm/tlb-v7.S +++ b/arch/arm/mm/tlb-v7.S @@ -38,10 +38,10 @@ ENTRY(v7wbi_flush_user_tlb_range)  	dsb  	mov	r0, r0, lsr #PAGE_SHIFT		@ align address  	mov	r1, r1, lsr #PAGE_SHIFT -#ifdef CONFIG_ARM_ERRATA_720789 -	mov	r3, #0 -#else  	asid	r3, r3				@ mask ASID +#ifdef CONFIG_ARM_ERRATA_720789 +	ALT_SMP(W(mov)	r3, #0	) +	ALT_UP(W(nop)		)  #endif  	orr	r0, r3, r0, lsl #PAGE_SHIFT	@ Create initial MVA  	mov	r1, r1, lsl #PAGE_SHIFT diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 7aca31c1df1..9c3b90c3538 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -403,7 +403,8 @@ config S5P_DEV_USB_EHCI  config S3C24XX_PWM  	bool "PWM device support" -	select HAVE_PWM +	select PWM +	select PWM_SAMSUNG  	help  	  Support for exporting the PWM timer blocks via the pwm device  	  system diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index fb849d044bd..c834b32af27 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -719,8 +719,10 @@ static int __init vfp_init(void)  			if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100)  				elf_hwcap |= HWCAP_NEON;  #endif +#ifdef CONFIG_VFPv3  			if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000)  				elf_hwcap |= HWCAP_VFPv4; +#endif  		}  	}  	return 0; diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index ada8f0fc71e..fb96e607adc 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -52,7 +52,6 @@ EXPORT_SYMBOL(reserved_mem_dcache_on);  #ifdef CONFIG_MTD_UCLINUX  extern struct map_info uclinux_ram_map;  unsigned long memory_mtd_end, memory_mtd_start, mtd_size; -unsigned long _ebss;  EXPORT_SYMBOL(memory_mtd_end);  EXPORT_SYMBOL(memory_mtd_start);  EXPORT_SYMBOL(mtd_size); diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig index 052f81a7623..983c859e40b 100644 --- a/arch/c6x/Kconfig +++ b/arch/c6x/Kconfig @@ -6,6 +6,7 @@  config C6X  	def_bool y  	select CLKDEV_LOOKUP +	select GENERIC_ATOMIC64  	select GENERIC_IRQ_SHOW  	select HAVE_ARCH_TRACEHOOK  	select HAVE_DMA_API_DEBUG diff --git a/arch/c6x/include/asm/cache.h b/arch/c6x/include/asm/cache.h index 6d521d96d94..09c5a0f5f4d 100644 --- a/arch/c6x/include/asm/cache.h +++ b/arch/c6x/include/asm/cache.h @@ -1,7 +1,7 @@  /*   *  Port on Texas Instruments TMS320C6x architecture   * - *  Copyright (C) 2005, 2006, 2009, 2010 Texas Instruments Incorporated + *  Copyright (C) 2005, 2006, 2009, 2010, 2012 Texas Instruments Incorporated   *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)   *   *  This program is free software; you can redistribute it and/or modify @@ -16,9 +16,14 @@  /*   * Cache line size   */ -#define L1D_CACHE_BYTES   64 -#define L1P_CACHE_BYTES   32 -#define L2_CACHE_BYTES	  128 +#define L1D_CACHE_SHIFT   6 +#define L1D_CACHE_BYTES   (1 << L1D_CACHE_SHIFT) + +#define L1P_CACHE_SHIFT   5 +#define L1P_CACHE_BYTES   (1 << L1P_CACHE_SHIFT) + +#define L2_CACHE_SHIFT    7 +#define L2_CACHE_BYTES    (1 << L2_CACHE_SHIFT)  /*   * L2 used as cache @@ -29,7 +34,8 @@   * For practical reasons the L1_CACHE_BYTES defines should not be smaller than   * the L2 line size   */ -#define L1_CACHE_BYTES        L2_CACHE_BYTES +#define L1_CACHE_SHIFT        L2_CACHE_SHIFT +#define L1_CACHE_BYTES        (1 << L1_CACHE_SHIFT)  #define L2_CACHE_ALIGN_LOW(x) \  	(((x) & ~(L2_CACHE_BYTES - 1))) diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig index 954d81e2e83..7913695b2fc 100644 --- a/arch/ia64/configs/generic_defconfig +++ b/arch/ia64/configs/generic_defconfig @@ -234,5 +234,4 @@ CONFIG_CRYPTO_PCBC=m  CONFIG_CRYPTO_MD5=y  # CONFIG_CRYPTO_ANSI_CPRNG is not set  CONFIG_CRC_T10DIF=y -CONFIG_MISC_DEVICES=y  CONFIG_INTEL_IOMMU=y diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig index 91c41ecfa6d..f8e91336542 100644 --- a/arch/ia64/configs/gensparse_defconfig +++ b/arch/ia64/configs/gensparse_defconfig @@ -209,4 +209,3 @@ CONFIG_MAGIC_SYSRQ=y  CONFIG_DEBUG_KERNEL=y  CONFIG_DEBUG_MUTEXES=y  CONFIG_CRYPTO_MD5=y -CONFIG_MISC_DEVICES=y diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 6f38b6120d9..440578850ae 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -497,7 +497,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)  	srat_num_cpus++;  } -void __init +int __init  acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)  {  	unsigned long paddr, size; @@ -512,7 +512,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)  	/* Ignore disabled entries */  	if (!(ma->flags & ACPI_SRAT_MEM_ENABLED)) -		return; +		return -1;  	/* record this node in proximity bitmap */  	pxm_bit_set(pxm); @@ -531,6 +531,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)  	p->size = size;  	p->nid = pxm;  	num_node_memblks++; +	return 0;  }  void __init acpi_numa_arch_fixup(void) diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 0b0f8b8c4a2..b22df9410dc 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -5,6 +5,7 @@ config M68K  	select HAVE_AOUT if MMU  	select HAVE_GENERIC_HARDIRQS  	select GENERIC_IRQ_SHOW +	select GENERIC_ATOMIC64  	select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS  	select GENERIC_CPU_DEVICES  	select GENERIC_STRNCPY_FROM_USER if MMU @@ -54,18 +55,6 @@ config ZONE_DMA  	bool  	default y -config CPU_HAS_NO_BITFIELDS -	bool - -config CPU_HAS_NO_MULDIV64 -	bool - -config CPU_HAS_ADDRESS_SPACES -	bool - -config FPU -	bool -  config HZ  	int  	default 1000 if CLEOPATRA diff --git a/arch/m68k/Kconfig.cpu b/arch/m68k/Kconfig.cpu index 43a9f8f1b8e..c4eb79edece 100644 --- a/arch/m68k/Kconfig.cpu +++ b/arch/m68k/Kconfig.cpu @@ -28,6 +28,7 @@ config COLDFIRE  	select CPU_HAS_NO_BITFIELDS  	select CPU_HAS_NO_MULDIV64  	select GENERIC_CSUM +	select HAVE_CLK  endchoice @@ -37,6 +38,7 @@ config M68000  	bool  	select CPU_HAS_NO_BITFIELDS  	select CPU_HAS_NO_MULDIV64 +	select CPU_HAS_NO_UNALIGNED  	select GENERIC_CSUM  	help  	  The Freescale (was Motorola) 68000 CPU is the first generation of @@ -48,6 +50,7 @@ config M68000  config MCPU32  	bool  	select CPU_HAS_NO_BITFIELDS +	select CPU_HAS_NO_UNALIGNED  	help  	  The Freescale (was then Motorola) CPU32 is a CPU core that is  	  based on the 68020 processor. For the most part it is used in @@ -56,7 +59,6 @@ config MCPU32  config M68020  	bool "68020 support"  	depends on MMU -	select GENERIC_ATOMIC64  	select CPU_HAS_ADDRESS_SPACES  	help  	  If you anticipate running this kernel on a computer with a MC68020 @@ -67,7 +69,6 @@ config M68020  config M68030  	bool "68030 support"  	depends on MMU && !MMU_SUN3 -	select GENERIC_ATOMIC64  	select CPU_HAS_ADDRESS_SPACES  	help  	  If you anticipate running this kernel on a computer with a MC68030 @@ -77,7 +78,6 @@ config M68030  config M68040  	bool "68040 support"  	depends on MMU && !MMU_SUN3 -	select GENERIC_ATOMIC64  	select CPU_HAS_ADDRESS_SPACES  	help  	  If you anticipate running this kernel on a computer with a MC68LC040 @@ -88,7 +88,6 @@ config M68040  config M68060  	bool "68060 support"  	depends on MMU && !MMU_SUN3 -	select GENERIC_ATOMIC64  	select CPU_HAS_ADDRESS_SPACES  	help  	  If you anticipate running this kernel on a computer with a MC68060 @@ -376,6 +375,18 @@ config NODES_SHIFT  	default "3"  	depends on !SINGLE_MEMORY_CHUNK +config CPU_HAS_NO_BITFIELDS +	bool + +config CPU_HAS_NO_MULDIV64 +	bool + +config CPU_HAS_NO_UNALIGNED +	bool + +config CPU_HAS_ADDRESS_SPACES +	bool +  config FPU  	bool diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c index 0a30406b944..f5565d6eeb8 100644 --- a/arch/m68k/apollo/config.c +++ b/arch/m68k/apollo/config.c @@ -177,8 +177,8 @@ irqreturn_t dn_timer_int(int irq, void *dev_id)  	timer_handler(irq, dev_id); -	x=*(volatile unsigned char *)(timer+3); -	x=*(volatile unsigned char *)(timer+5); +	x = *(volatile unsigned char *)(apollo_timer + 3); +	x = *(volatile unsigned char *)(apollo_timer + 5);  	return IRQ_HANDLED;  } @@ -186,17 +186,17 @@ irqreturn_t dn_timer_int(int irq, void *dev_id)  void dn_sched_init(irq_handler_t timer_routine)  {  	/* program timer 1 */ -	*(volatile unsigned char *)(timer+3)=0x01; -	*(volatile unsigned char *)(timer+1)=0x40; -	*(volatile unsigned char *)(timer+5)=0x09; -	*(volatile unsigned char *)(timer+7)=0xc4; +	*(volatile unsigned char *)(apollo_timer + 3) = 0x01; +	*(volatile unsigned char *)(apollo_timer + 1) = 0x40; +	*(volatile unsigned char *)(apollo_timer + 5) = 0x09; +	*(volatile unsigned char *)(apollo_timer + 7) = 0xc4;  	/* enable IRQ of PIC B */  	*(volatile unsigned char *)(pica+1)&=(~8);  #if 0 -	printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3)); -	printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3)); +	printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3)); +	printk("*(0x10803) %02x\n",*(volatile unsigned char *)(apollo_timer + 0x3));  #endif  	if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine)) diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index eafa2539a8e..a74e5d95c38 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -1,4 +1,29 @@  include include/asm-generic/Kbuild.asm  header-y += cachectl.h +generic-y += bitsperlong.h +generic-y += cputime.h +generic-y += device.h +generic-y += emergency-restart.h +generic-y += errno.h +generic-y += futex.h +generic-y += ioctl.h +generic-y += ipcbuf.h +generic-y += irq_regs.h +generic-y += kdebug.h +generic-y += kmap_types.h +generic-y += kvm_para.h +generic-y += local64.h +generic-y += local.h +generic-y += mman.h +generic-y += mutex.h +generic-y += percpu.h +generic-y += resource.h +generic-y += scatterlist.h +generic-y += sections.h +generic-y += siginfo.h +generic-y += statfs.h +generic-y += topology.h +generic-y += types.h  generic-y += word-at-a-time.h +generic-y += xor.h diff --git a/arch/m68k/include/asm/MC68332.h b/arch/m68k/include/asm/MC68332.h deleted file mode 100644 index 6bb8f02685a..00000000000 --- a/arch/m68k/include/asm/MC68332.h +++ /dev/null @@ -1,152 +0,0 @@ - -/* include/asm-m68knommu/MC68332.h: '332 control registers - * - * Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>, - * - */ - -#ifndef _MC68332_H_ -#define _MC68332_H_ - -#define BYTE_REF(addr) (*((volatile unsigned char*)addr)) -#define WORD_REF(addr) (*((volatile unsigned short*)addr)) - -#define PORTE_ADDR	0xfffa11 -#define PORTE	BYTE_REF(PORTE_ADDR) -#define DDRE_ADDR	0xfffa15 -#define DDRE	BYTE_REF(DDRE_ADDR) -#define PEPAR_ADDR	0xfffa17 -#define PEPAR	BYTE_REF(PEPAR_ADDR) - -#define PORTF_ADDR	0xfffa19 -#define PORTF	BYTE_REF(PORTF_ADDR) -#define DDRF_ADDR	0xfffa1d -#define DDRF	BYTE_REF(DDRF_ADDR) -#define PFPAR_ADDR	0xfffa1f -#define PFPAR	BYTE_REF(PFPAR_ADDR) - -#define PORTQS_ADDR	0xfffc15 -#define PORTQS	BYTE_REF(PORTQS_ADDR) -#define DDRQS_ADDR	0xfffc17 -#define DDRQS	BYTE_REF(DDRQS_ADDR) -#define PQSPAR_ADDR	0xfffc16 -#define PQSPAR	BYTE_REF(PQSPAR_ADDR) - -#define CSPAR0_ADDR 0xFFFA44 -#define CSPAR0 WORD_REF(CSPAR0_ADDR) -#define CSPAR1_ADDR 0xFFFA46 -#define CSPAR1 WORD_REF(CSPAR1_ADDR) -#define CSARBT_ADDR 0xFFFA48 -#define CSARBT WORD_REF(CSARBT_ADDR) -#define CSOPBT_ADDR 0xFFFA4A -#define CSOPBT WORD_REF(CSOPBT_ADDR) -#define CSBAR0_ADDR 0xFFFA4C -#define CSBAR0 WORD_REF(CSBAR0_ADDR) -#define CSOR0_ADDR 0xFFFA4E -#define CSOR0 WORD_REF(CSOR0_ADDR) -#define CSBAR1_ADDR 0xFFFA50 -#define CSBAR1 WORD_REF(CSBAR1_ADDR) -#define CSOR1_ADDR 0xFFFA52 -#define CSOR1 WORD_REF(CSOR1_ADDR) -#define CSBAR2_ADDR 0xFFFA54 -#define CSBAR2 WORD_REF(CSBAR2_ADDR) -#define CSOR2_ADDR 0xFFFA56 -#define CSOR2 WORD_REF(CSOR2_ADDR) -#define CSBAR3_ADDR 0xFFFA58 -#define CSBAR3 WORD_REF(CSBAR3_ADDR) -#define CSOR3_ADDR 0xFFFA5A -#define CSOR3 WORD_REF(CSOR3_ADDR) -#define CSBAR4_ADDR 0xFFFA5C -#define CSBAR4 WORD_REF(CSBAR4_ADDR) -#define CSOR4_ADDR 0xFFFA5E -#define CSOR4 WORD_REF(CSOR4_ADDR) -#define CSBAR5_ADDR 0xFFFA60 -#define CSBAR5 WORD_REF(CSBAR5_ADDR) -#define CSOR5_ADDR 0xFFFA62 -#define CSOR5 WORD_REF(CSOR5_ADDR) -#define CSBAR6_ADDR 0xFFFA64 -#define CSBAR6 WORD_REF(CSBAR6_ADDR) -#define CSOR6_ADDR 0xFFFA66 -#define CSOR6 WORD_REF(CSOR6_ADDR) -#define CSBAR7_ADDR 0xFFFA68 -#define CSBAR7 WORD_REF(CSBAR7_ADDR) -#define CSOR7_ADDR 0xFFFA6A -#define CSOR7 WORD_REF(CSOR7_ADDR) -#define CSBAR8_ADDR 0xFFFA6C -#define CSBAR8 WORD_REF(CSBAR8_ADDR) -#define CSOR8_ADDR 0xFFFA6E -#define CSOR8 WORD_REF(CSOR8_ADDR) -#define CSBAR9_ADDR 0xFFFA70 -#define CSBAR9 WORD_REF(CSBAR9_ADDR) -#define CSOR9_ADDR 0xFFFA72 -#define CSOR9 WORD_REF(CSOR9_ADDR) -#define CSBAR10_ADDR 0xFFFA74 -#define CSBAR10 WORD_REF(CSBAR10_ADDR) -#define CSOR10_ADDR 0xFFFA76 -#define CSOR10 WORD_REF(CSOR10_ADDR) - -#define CSOR_MODE_ASYNC	0x0000 -#define CSOR_MODE_SYNC	0x8000 -#define CSOR_MODE_MASK	0x8000 -#define CSOR_BYTE_DISABLE	0x0000 -#define CSOR_BYTE_UPPER		0x4000 -#define CSOR_BYTE_LOWER		0x2000 -#define CSOR_BYTE_BOTH		0x6000 -#define CSOR_BYTE_MASK		0x6000 -#define CSOR_RW_RSVD		0x0000 -#define CSOR_RW_READ		0x0800 -#define CSOR_RW_WRITE		0x1000 -#define CSOR_RW_BOTH		0x1800 -#define CSOR_RW_MASK		0x1800 -#define CSOR_STROBE_DS		0x0400 -#define CSOR_STROBE_AS		0x0000 -#define CSOR_STROBE_MASK	0x0400 -#define CSOR_DSACK_WAIT(x)	(wait << 6) -#define CSOR_DSACK_FTERM	(14 << 6) -#define CSOR_DSACK_EXTERNAL	(15 << 6) -#define CSOR_DSACK_MASK		0x03c0 -#define CSOR_SPACE_CPU		0x0000 -#define CSOR_SPACE_USER		0x0010 -#define CSOR_SPACE_SU		0x0020 -#define CSOR_SPACE_BOTH		0x0030 -#define CSOR_SPACE_MASK		0x0030 -#define CSOR_IPL_ALL		0x0000 -#define CSOR_IPL_PRIORITY(x)	(x << 1) -#define CSOR_IPL_MASK		0x000e -#define CSOR_AVEC_ON		0x0001 -#define CSOR_AVEC_OFF		0x0000 -#define CSOR_AVEC_MASK		0x0001 - -#define CSBAR_ADDR(x)		((addr >> 11) << 3)  -#define CSBAR_ADDR_MASK		0xfff8 -#define CSBAR_BLKSIZE_2K	0x0000 -#define CSBAR_BLKSIZE_8K	0x0001 -#define CSBAR_BLKSIZE_16K	0x0002 -#define CSBAR_BLKSIZE_64K	0x0003 -#define CSBAR_BLKSIZE_128K	0x0004 -#define CSBAR_BLKSIZE_256K	0x0005 -#define CSBAR_BLKSIZE_512K	0x0006 -#define CSBAR_BLKSIZE_1M	0x0007 -#define CSBAR_BLKSIZE_MASK	0x0007 - -#define CSPAR_DISC	0 -#define CSPAR_ALT	1 -#define CSPAR_CS8	2 -#define CSPAR_CS16	3 -#define CSPAR_MASK	3 - -#define CSPAR0_CSBOOT(x) (x << 0) -#define CSPAR0_CS0(x)	(x << 2) -#define CSPAR0_CS1(x)	(x << 4) -#define CSPAR0_CS2(x)	(x << 6) -#define CSPAR0_CS3(x)	(x << 8) -#define CSPAR0_CS4(x)	(x << 10) -#define CSPAR0_CS5(x)	(x << 12) - -#define CSPAR1_CS6(x)	(x << 0) -#define CSPAR1_CS7(x)	(x << 2) -#define CSPAR1_CS8(x)	(x << 4) -#define CSPAR1_CS9(x)	(x << 6) -#define CSPAR1_CS10(x)	(x << 8) - -#endif diff --git a/arch/m68k/include/asm/apollodma.h b/arch/m68k/include/asm/apollodma.h deleted file mode 100644 index 954adc851ad..00000000000 --- a/arch/m68k/include/asm/apollodma.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * linux/include/asm/dma.h: Defines for using and allocating dma channels. - * Written by Hennus Bergman, 1992. - * High DMA channel support & info by Hannu Savolainen - * and John Boyd, Nov. 1992. - */ - -#ifndef _ASM_APOLLO_DMA_H -#define _ASM_APOLLO_DMA_H - -#include <asm/apollohw.h>		/* need byte IO */ -#include <linux/spinlock.h>		/* And spinlocks */ -#include <linux/delay.h> - - -#define dma_outb(val,addr) (*((volatile unsigned char *)(addr+IO_BASE)) = (val)) -#define dma_inb(addr)	   (*((volatile unsigned char *)(addr+IO_BASE))) - -/* - * NOTES about DMA transfers: - * - *  controller 1: channels 0-3, byte operations, ports 00-1F - *  controller 2: channels 4-7, word operations, ports C0-DF - * - *  - ALL registers are 8 bits only, regardless of transfer size - *  - channel 4 is not used - cascades 1 into 2. - *  - channels 0-3 are byte - addresses/counts are for physical bytes - *  - channels 5-7 are word - addresses/counts are for physical words - *  - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries - *  - transfer count loaded to registers is 1 less than actual count - *  - controller 2 offsets are all even (2x offsets for controller 1) - *  - page registers for 5-7 don't use data bit 0, represent 128K pages - *  - page registers for 0-3 use bit 0, represent 64K pages - * - * DMA transfers are limited to the lower 16MB of _physical_ memory. - * Note that addresses loaded into registers must be _physical_ addresses, - * not logical addresses (which may differ if paging is active). - * - *  Address mapping for channels 0-3: - * - *   A23 ... A16 A15 ... A8  A7 ... A0    (Physical addresses) - *    |  ...  |   |  ... |   |  ... | - *    |  ...  |   |  ... |   |  ... | - *    |  ...  |   |  ... |   |  ... | - *   P7  ...  P0  A7 ... A0  A7 ... A0 - * |    Page    | Addr MSB | Addr LSB |   (DMA registers) - * - *  Address mapping for channels 5-7: - * - *   A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0    (Physical addresses) - *    |  ...  |   \   \   ... \  \  \  ... \  \ - *    |  ...  |    \   \   ... \  \  \  ... \  (not used) - *    |  ...  |     \   \   ... \  \  \  ... \ - *   P7  ...  P1 (0) A7 A6  ... A0 A7 A6 ... A0 - * |      Page      |  Addr MSB   |  Addr LSB  |   (DMA registers) - * - * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses - * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at - * the hardware level, so odd-byte transfers aren't possible). - * - * Transfer count (_not # bytes_) is limited to 64K, represented as actual - * count - 1 : 64K => 0xFFFF, 1 => 0x0000.  Thus, count is always 1 or more, - * and up to 128K bytes may be transferred on channels 5-7 in one operation. - * - */ - -#define MAX_DMA_CHANNELS	8 - -/* The maximum address that we can perform a DMA transfer to on this platform */#define MAX_DMA_ADDRESS      (PAGE_OFFSET+0x1000000) - -/* 8237 DMA controllers */ -#define IO_DMA1_BASE	0x10C00	/* 8 bit slave DMA, channels 0..3 */ -#define IO_DMA2_BASE	0x10D00	/* 16 bit master DMA, ch 4(=slave input)..7 */ - -/* DMA controller registers */ -#define DMA1_CMD_REG		(IO_DMA1_BASE+0x08) /* command register (w) */ -#define DMA1_STAT_REG		(IO_DMA1_BASE+0x08) /* status register (r) */ -#define DMA1_REQ_REG            (IO_DMA1_BASE+0x09) /* request register (w) */ -#define DMA1_MASK_REG		(IO_DMA1_BASE+0x0A) /* single-channel mask (w) */ -#define DMA1_MODE_REG		(IO_DMA1_BASE+0x0B) /* mode register (w) */ -#define DMA1_CLEAR_FF_REG	(IO_DMA1_BASE+0x0C) /* clear pointer flip-flop (w) */ -#define DMA1_TEMP_REG           (IO_DMA1_BASE+0x0D) /* Temporary Register (r) */ -#define DMA1_RESET_REG		(IO_DMA1_BASE+0x0D) /* Master Clear (w) */ -#define DMA1_CLR_MASK_REG       (IO_DMA1_BASE+0x0E) /* Clear Mask */ -#define DMA1_MASK_ALL_REG       (IO_DMA1_BASE+0x0F) /* all-channels mask (w) */ - -#define DMA2_CMD_REG		(IO_DMA2_BASE+0x10) /* command register (w) */ -#define DMA2_STAT_REG		(IO_DMA2_BASE+0x10) /* status register (r) */ -#define DMA2_REQ_REG            (IO_DMA2_BASE+0x12) /* request register (w) */ -#define DMA2_MASK_REG		(IO_DMA2_BASE+0x14) /* single-channel mask (w) */ -#define DMA2_MODE_REG		(IO_DMA2_BASE+0x16) /* mode register (w) */ -#define DMA2_CLEAR_FF_REG	(IO_DMA2_BASE+0x18) /* clear pointer flip-flop (w) */ -#define DMA2_TEMP_REG           (IO_DMA2_BASE+0x1A) /* Temporary Register (r) */ -#define DMA2_RESET_REG		(IO_DMA2_BASE+0x1A) /* Master Clear (w) */ -#define DMA2_CLR_MASK_REG       (IO_DMA2_BASE+0x1C) /* Clear Mask */ -#define DMA2_MASK_ALL_REG       (IO_DMA2_BASE+0x1E) /* all-channels mask (w) */ - -#define DMA_ADDR_0              (IO_DMA1_BASE+0x00) /* DMA address registers */ -#define DMA_ADDR_1              (IO_DMA1_BASE+0x02) -#define DMA_ADDR_2              (IO_DMA1_BASE+0x04) -#define DMA_ADDR_3              (IO_DMA1_BASE+0x06) -#define DMA_ADDR_4              (IO_DMA2_BASE+0x00) -#define DMA_ADDR_5              (IO_DMA2_BASE+0x04) -#define DMA_ADDR_6              (IO_DMA2_BASE+0x08) -#define DMA_ADDR_7              (IO_DMA2_BASE+0x0C) - -#define DMA_CNT_0               (IO_DMA1_BASE+0x01)   /* DMA count registers */ -#define DMA_CNT_1               (IO_DMA1_BASE+0x03) -#define DMA_CNT_2               (IO_DMA1_BASE+0x05) -#define DMA_CNT_3               (IO_DMA1_BASE+0x07) -#define DMA_CNT_4               (IO_DMA2_BASE+0x02) -#define DMA_CNT_5               (IO_DMA2_BASE+0x06) -#define DMA_CNT_6               (IO_DMA2_BASE+0x0A) -#define DMA_CNT_7               (IO_DMA2_BASE+0x0E) - -#define DMA_MODE_READ	0x44	/* I/O to memory, no autoinit, increment, single mode */ -#define DMA_MODE_WRITE	0x48	/* memory to I/O, no autoinit, increment, single mode */ -#define DMA_MODE_CASCADE 0xC0   /* pass thru DREQ->HRQ, DACK<-HLDA only */ - -#define DMA_AUTOINIT	0x10 - -#define DMA_8BIT 0 -#define DMA_16BIT 1 -#define DMA_BUSMASTER 2 - -extern spinlock_t  dma_spin_lock; - -static __inline__ unsigned long claim_dma_lock(void) -{ -	unsigned long flags; -	spin_lock_irqsave(&dma_spin_lock, flags); -	return flags; -} - -static __inline__ void release_dma_lock(unsigned long flags) -{ -	spin_unlock_irqrestore(&dma_spin_lock, flags); -} - -/* enable/disable a specific DMA channel */ -static __inline__ void enable_dma(unsigned int dmanr) -{ -	if (dmanr<=3) -		dma_outb(dmanr,  DMA1_MASK_REG); -	else -		dma_outb(dmanr & 3,  DMA2_MASK_REG); -} - -static __inline__ void disable_dma(unsigned int dmanr) -{ -	if (dmanr<=3) -		dma_outb(dmanr | 4,  DMA1_MASK_REG); -	else -		dma_outb((dmanr & 3) | 4,  DMA2_MASK_REG); -} - -/* Clear the 'DMA Pointer Flip Flop'. - * Write 0 for LSB/MSB, 1 for MSB/LSB access. - * Use this once to initialize the FF to a known state. - * After that, keep track of it. :-) - * --- In order to do that, the DMA routines below should --- - * --- only be used while holding the DMA lock ! --- - */ -static __inline__ void clear_dma_ff(unsigned int dmanr) -{ -	if (dmanr<=3) -		dma_outb(0,  DMA1_CLEAR_FF_REG); -	else -		dma_outb(0,  DMA2_CLEAR_FF_REG); -} - -/* set mode (above) for a specific DMA channel */ -static __inline__ void set_dma_mode(unsigned int dmanr, char mode) -{ -	if (dmanr<=3) -		dma_outb(mode | dmanr,  DMA1_MODE_REG); -	else -		dma_outb(mode | (dmanr&3),  DMA2_MODE_REG); -} - -/* Set transfer address & page bits for specific DMA channel. - * Assumes dma flipflop is clear. - */ -static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) -{ -	if (dmanr <= 3)  { -	    dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); -            dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); -	}  else  { -	    dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); -	    dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); -	} -} - - -/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for - * a specific DMA channel. - * You must ensure the parameters are valid. - * NOTE: from a manual: "the number of transfers is one more - * than the initial word count"! This is taken into account. - * Assumes dma flip-flop is clear. - * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. - */ -static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) -{ -        count--; -	if (dmanr <= 3)  { -	    dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); -	    dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); -        } else { -	    dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); -	    dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); -        } -} - - -/* Get DMA residue count. After a DMA transfer, this - * should return zero. Reading this while a DMA transfer is - * still in progress will return unpredictable results. - * If called before the channel has been used, it may return 1. - * Otherwise, it returns the number of _bytes_ left to transfer. - * - * Assumes DMA flip-flop is clear. - */ -static __inline__ int get_dma_residue(unsigned int dmanr) -{ -	unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE -					 : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; - -	/* using short to get 16-bit wrap around */ -	unsigned short count; - -	count = 1 + dma_inb(io_port); -	count += dma_inb(io_port) << 8; - -	return (dmanr<=3)? count : (count<<1); -} - - -/* These are in kernel/dma.c: */ -extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */ -extern void free_dma(unsigned int dmanr);	/* release it again */ - -/* These are in arch/m68k/apollo/dma.c: */ -extern unsigned short dma_map_page(unsigned long phys_addr,int count,int type); -extern void dma_unmap_page(unsigned short dma_addr); - -#endif /* _ASM_APOLLO_DMA_H */ diff --git a/arch/m68k/include/asm/apollohw.h b/arch/m68k/include/asm/apollohw.h index a1373b9aa28..635ef4f8901 100644 --- a/arch/m68k/include/asm/apollohw.h +++ b/arch/m68k/include/asm/apollohw.h @@ -98,7 +98,7 @@ extern u_long timer_physaddr;  #define cpuctrl (*(volatile unsigned int *)(IO_BASE + cpuctrl_physaddr))  #define pica (IO_BASE + pica_physaddr)  #define picb (IO_BASE + picb_physaddr) -#define timer (IO_BASE + timer_physaddr) +#define apollo_timer (IO_BASE + timer_physaddr)  #define addr_xlat_map ((unsigned short *)(IO_BASE + 0x17000))  #define isaIO2mem(x) (((((x) & 0x3f8)  << 7) | (((x) & 0xfc00) >> 6) | ((x) & 0x7)) + 0x40000 + IO_BASE) diff --git a/arch/m68k/include/asm/bitsperlong.h b/arch/m68k/include/asm/bitsperlong.h deleted file mode 100644 index 6dc0bb0c13b..00000000000 --- a/arch/m68k/include/asm/bitsperlong.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/bitsperlong.h> diff --git a/arch/m68k/include/asm/cputime.h b/arch/m68k/include/asm/cputime.h deleted file mode 100644 index c79c5e89230..00000000000 --- a/arch/m68k/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __M68K_CPUTIME_H -#define __M68K_CPUTIME_H - -#include <asm-generic/cputime.h> - -#endif /* __M68K_CPUTIME_H */ diff --git a/arch/m68k/include/asm/delay.h b/arch/m68k/include/asm/delay.h index 9c09becfd4c..12d8fe4f1d3 100644 --- a/arch/m68k/include/asm/delay.h +++ b/arch/m68k/include/asm/delay.h @@ -43,7 +43,7 @@ static inline void __delay(unsigned long loops)  extern void __bad_udelay(void); -#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) +#ifdef CONFIG_CPU_HAS_NO_MULDIV64  /*   * The simpler m68k and ColdFire processors do not have a 32*32->64   * multiply instruction. So we need to handle them a little differently. diff --git a/arch/m68k/include/asm/device.h b/arch/m68k/include/asm/device.h deleted file mode 100644 index d8f9872b0e2..00000000000 --- a/arch/m68k/include/asm/device.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Arch specific extensions to struct device - * - * This file is released under the GPLv2 - */ -#include <asm-generic/device.h> - diff --git a/arch/m68k/include/asm/emergency-restart.h b/arch/m68k/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c48e42..00000000000 --- a/arch/m68k/include/asm/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include <asm-generic/emergency-restart.h> - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/m68k/include/asm/errno.h b/arch/m68k/include/asm/errno.h deleted file mode 100644 index 0d4e188d6ef..00000000000 --- a/arch/m68k/include/asm/errno.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_ERRNO_H -#define _M68K_ERRNO_H - -#include <asm-generic/errno.h> - -#endif /* _M68K_ERRNO_H */ diff --git a/arch/m68k/include/asm/futex.h b/arch/m68k/include/asm/futex.h deleted file mode 100644 index 6a332a9f099..00000000000 --- a/arch/m68k/include/asm/futex.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#include <asm-generic/futex.h> - -#endif diff --git a/arch/m68k/include/asm/ioctl.h b/arch/m68k/include/asm/ioctl.h deleted file mode 100644 index b279fe06dfe..00000000000 --- a/arch/m68k/include/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/ioctl.h> diff --git a/arch/m68k/include/asm/ipcbuf.h b/arch/m68k/include/asm/ipcbuf.h deleted file mode 100644 index 84c7e51cb6d..00000000000 --- a/arch/m68k/include/asm/ipcbuf.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/ipcbuf.h> diff --git a/arch/m68k/include/asm/irq_regs.h b/arch/m68k/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b7027..00000000000 --- a/arch/m68k/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/irq_regs.h> diff --git a/arch/m68k/include/asm/kdebug.h b/arch/m68k/include/asm/kdebug.h deleted file mode 100644 index 6ece1b03766..00000000000 --- a/arch/m68k/include/asm/kdebug.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/kdebug.h> diff --git a/arch/m68k/include/asm/kmap_types.h b/arch/m68k/include/asm/kmap_types.h deleted file mode 100644 index 3413cc1390e..00000000000 --- a/arch/m68k/include/asm/kmap_types.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_M68K_KMAP_TYPES_H -#define __ASM_M68K_KMAP_TYPES_H - -#include <asm-generic/kmap_types.h> - -#endif	/* __ASM_M68K_KMAP_TYPES_H */ diff --git a/arch/m68k/include/asm/kvm_para.h b/arch/m68k/include/asm/kvm_para.h deleted file mode 100644 index 14fab8f0b95..00000000000 --- a/arch/m68k/include/asm/kvm_para.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/kvm_para.h> diff --git a/arch/m68k/include/asm/local.h b/arch/m68k/include/asm/local.h deleted file mode 100644 index 6c259263e1f..00000000000 --- a/arch/m68k/include/asm/local.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_M68K_LOCAL_H -#define _ASM_M68K_LOCAL_H - -#include <asm-generic/local.h> - -#endif /* _ASM_M68K_LOCAL_H */ diff --git a/arch/m68k/include/asm/local64.h b/arch/m68k/include/asm/local64.h deleted file mode 100644 index 36c93b5cc23..00000000000 --- a/arch/m68k/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/local64.h> diff --git a/arch/m68k/include/asm/mac_mouse.h b/arch/m68k/include/asm/mac_mouse.h deleted file mode 100644 index 39a5c292eae..00000000000 --- a/arch/m68k/include/asm/mac_mouse.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _ASM_MAC_MOUSE_H -#define _ASM_MAC_MOUSE_H - -/* - * linux/include/asm-m68k/mac_mouse.h - * header file for Macintosh ADB mouse driver - * 27-10-97 Michael Schmitz - * copied from: - * header file for Atari Mouse driver - * by Robert de Vries (robert@and.nl) on 19Jul93 - */ - -struct mouse_status { -	char		buttons; -	short		dx; -	short		dy; -	int		ready; -	int		active; -	wait_queue_head_t wait; -	struct fasync_struct *fasyncptr; -}; - -#endif diff --git a/arch/m68k/include/asm/mcfmbus.h b/arch/m68k/include/asm/mcfmbus.h deleted file mode 100644 index 319899c47a2..00000000000 --- a/arch/m68k/include/asm/mcfmbus.h +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************/ - -/* - *      mcfmbus.h -- Coldfire MBUS support defines. - * - *      (C) Copyright 1999, Martin Floeer (mfloeer@axcent.de)  - */ - -/****************************************************************************/ - - -#ifndef mcfmbus_h -#define mcfmbus_h - - -#define MCFMBUS_BASE		0x280 -#define MCFMBUS_IRQ_VECTOR	0x19 -#define MCFMBUS_IRQ		0x1 -#define MCFMBUS_CLK		0x3f -#define MCFMBUS_IRQ_LEVEL	0x07	/*IRQ Level 1*/ -#define MCFMBUS_ADDRESS		0x01 - - -/* -*	Define the 5307 MBUS register set addresses -*/ - -#define MCFMBUS_MADR	0x00 -#define MCFMBUS_MFDR	0x04 -#define MCFMBUS_MBCR	0x08 -#define MCFMBUS_MBSR	0x0C -#define MCFMBUS_MBDR	0x10 - - -#define MCFMBUS_MADR_ADDR(a)	(((a)&0x7F)<<0x01) /*Slave Address*/ - -#define MCFMBUS_MFDR_MBC(a)	((a)&0x3F)	   /*M-Bus Clock*/ - -/* -*	Define bit flags in Control Register -*/ - -#define MCFMBUS_MBCR_MEN           (0x80)  /* M-Bus Enable                 */ -#define MCFMBUS_MBCR_MIEN          (0x40)  /* M-Bus Interrupt Enable       */ -#define MCFMBUS_MBCR_MSTA          (0x20)  /* Master/Slave Mode Select Bit */ -#define MCFMBUS_MBCR_MTX           (0x10)  /* Transmit/Rcv Mode Select Bit */ -#define MCFMBUS_MBCR_TXAK          (0x08)  /* Transmit Acknowledge Enable  */ -#define MCFMBUS_MBCR_RSTA          (0x04)  /* Repeat Start                 */ - -/* -*	Define bit flags in Status Register -*/ - -#define MCFMBUS_MBSR_MCF           (0x80)  /* Data Transfer Complete       */ -#define MCFMBUS_MBSR_MAAS          (0x40)  /* Addressed as a Slave         */ -#define MCFMBUS_MBSR_MBB           (0x20)  /* Bus Busy                     */ -#define MCFMBUS_MBSR_MAL           (0x10)  /* Arbitration Lost             */ -#define MCFMBUS_MBSR_SRW           (0x04)  /* Slave Transmit               */ -#define MCFMBUS_MBSR_MIF           (0x02)  /* M-Bus Interrupt              */ -#define MCFMBUS_MBSR_RXAK          (0x01)  /* No Acknowledge Received      */ - -/* -*	Define bit flags in DATA I/O Register -*/ - -#define MCFMBUS_MBDR_READ          (0x01)  /* 1=read 0=write MBUS */ - -#define MBUSIOCSCLOCK		1 -#define MBUSIOCGCLOCK		2 -#define MBUSIOCSADDR			3 -#define MBUSIOCGADDR			4 -#define MBUSIOCSSLADDR			5 -#define MBUSIOCGSLADDR			6 -#define MBUSIOCSSUBADDR			7 -#define MBUSIOCGSUBADDR			8 - -#endif diff --git a/arch/m68k/include/asm/mman.h b/arch/m68k/include/asm/mman.h deleted file mode 100644 index 8eebf89f5ab..00000000000 --- a/arch/m68k/include/asm/mman.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/mman.h> diff --git a/arch/m68k/include/asm/mutex.h b/arch/m68k/include/asm/mutex.h deleted file mode 100644 index 458c1f7fbc1..00000000000 --- a/arch/m68k/include/asm/mutex.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Pull in the generic implementation for the mutex fastpath. - * - * TODO: implement optimized primitives instead, or leave the generic - * implementation in place, or pick the atomic_xchg() based generic - * implementation. (see asm-generic/mutex-xchg.h for details) - */ - -#include <asm-generic/mutex-dec.h> diff --git a/arch/m68k/include/asm/percpu.h b/arch/m68k/include/asm/percpu.h deleted file mode 100644 index 0859d048faf..00000000000 --- a/arch/m68k/include/asm/percpu.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_M68K_PERCPU_H -#define __ASM_M68K_PERCPU_H - -#include <asm-generic/percpu.h> - -#endif	/* __ASM_M68K_PERCPU_H */ diff --git a/arch/m68k/include/asm/resource.h b/arch/m68k/include/asm/resource.h deleted file mode 100644 index e7d35019f33..00000000000 --- a/arch/m68k/include/asm/resource.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_RESOURCE_H -#define _M68K_RESOURCE_H - -#include <asm-generic/resource.h> - -#endif /* _M68K_RESOURCE_H */ diff --git a/arch/m68k/include/asm/sbus.h b/arch/m68k/include/asm/sbus.h deleted file mode 100644 index bfe3ba147f2..00000000000 --- a/arch/m68k/include/asm/sbus.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * some sbus structures and macros to make usage of sbus drivers possible - */ - -#ifndef __M68K_SBUS_H -#define __M68K_SBUS_H - -struct sbus_dev { -	struct { -		unsigned int which_io; -		unsigned int phys_addr; -	} reg_addrs[1]; -}; - -/* sbus IO functions stolen from include/asm-sparc/io.h for the serial driver */ -/* No SBUS on the Sun3, kludge -- sam */ - -static inline void _sbus_writeb(unsigned char val, unsigned long addr) -{ -	*(volatile unsigned char *)addr = val; -} - -static inline unsigned char _sbus_readb(unsigned long addr) -{ -	return *(volatile unsigned char *)addr; -} - -static inline void _sbus_writel(unsigned long val, unsigned long addr) -{ -	*(volatile unsigned long *)addr = val; - -} - -extern inline unsigned long _sbus_readl(unsigned long addr) -{ -	return *(volatile unsigned long *)addr; -} - - -#define sbus_readb(a) _sbus_readb((unsigned long)a) -#define sbus_writeb(v, a) _sbus_writeb(v, (unsigned long)a) -#define sbus_readl(a) _sbus_readl((unsigned long)a) -#define sbus_writel(v, a) _sbus_writel(v, (unsigned long)a) - -#endif diff --git a/arch/m68k/include/asm/scatterlist.h b/arch/m68k/include/asm/scatterlist.h deleted file mode 100644 index 312505452a1..00000000000 --- a/arch/m68k/include/asm/scatterlist.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_SCATTERLIST_H -#define _M68K_SCATTERLIST_H - -#include <asm-generic/scatterlist.h> - -#endif /* !(_M68K_SCATTERLIST_H) */ diff --git a/arch/m68k/include/asm/sections.h b/arch/m68k/include/asm/sections.h deleted file mode 100644 index 5277e52715e..00000000000 --- a/arch/m68k/include/asm/sections.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _ASM_M68K_SECTIONS_H -#define _ASM_M68K_SECTIONS_H - -#include <asm-generic/sections.h> - -extern char _sbss[], _ebss[]; - -#endif /* _ASM_M68K_SECTIONS_H */ diff --git a/arch/m68k/include/asm/shm.h b/arch/m68k/include/asm/shm.h deleted file mode 100644 index fa56ec84a12..00000000000 --- a/arch/m68k/include/asm/shm.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _M68K_SHM_H -#define _M68K_SHM_H - - -/* format of page table entries that correspond to shared memory pages -   currently out in swap space (see also mm/swap.c): -   bits 0-1 (PAGE_PRESENT) is  = 0 -   bits 8..2 (SWP_TYPE) are = SHM_SWP_TYPE -   bits 31..9 are used like this: -   bits 15..9 (SHM_ID) the id of the shared memory segment -   bits 30..16 (SHM_IDX) the index of the page within the shared memory segment -                    (actually only bits 25..16 get used since SHMMAX is so low) -   bit 31 (SHM_READ_ONLY) flag whether the page belongs to a read-only attach -*/ -/* on the m68k both bits 0 and 1 must be zero */ -/* format on the sun3 is similar, but bits 30, 31 are set to zero and all -   others are reduced by 2. --m */ - -#ifndef CONFIG_SUN3 -#define SHM_ID_SHIFT	9 -#else -#define SHM_ID_SHIFT	7 -#endif -#define _SHM_ID_BITS	7 -#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1) - -#define SHM_IDX_SHIFT	(SHM_ID_SHIFT+_SHM_ID_BITS) -#define _SHM_IDX_BITS	15 -#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1) - -#endif /* _M68K_SHM_H */ diff --git a/arch/m68k/include/asm/siginfo.h b/arch/m68k/include/asm/siginfo.h deleted file mode 100644 index 851d3d784b5..00000000000 --- a/arch/m68k/include/asm/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_SIGINFO_H -#define _M68K_SIGINFO_H - -#include <asm-generic/siginfo.h> - -#endif diff --git a/arch/m68k/include/asm/statfs.h b/arch/m68k/include/asm/statfs.h deleted file mode 100644 index 08d93f14e06..00000000000 --- a/arch/m68k/include/asm/statfs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _M68K_STATFS_H -#define _M68K_STATFS_H - -#include <asm-generic/statfs.h> - -#endif /* _M68K_STATFS_H */ diff --git a/arch/m68k/include/asm/topology.h b/arch/m68k/include/asm/topology.h deleted file mode 100644 index ca173e9f26f..00000000000 --- a/arch/m68k/include/asm/topology.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_M68K_TOPOLOGY_H -#define _ASM_M68K_TOPOLOGY_H - -#include <asm-generic/topology.h> - -#endif /* _ASM_M68K_TOPOLOGY_H */ diff --git a/arch/m68k/include/asm/types.h b/arch/m68k/include/asm/types.h deleted file mode 100644 index 89705adcbd5..00000000000 --- a/arch/m68k/include/asm/types.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _M68K_TYPES_H -#define _M68K_TYPES_H - -/* - * This file is never included by application software unless - * explicitly requested (e.g., via linux/types.h) in which case the - * application is Linux specific so (user-) name space pollution is - * not a major issue.  However, for interoperability, libraries still - * need to be careful to avoid a name clashes. - */ -#include <asm-generic/int-ll64.h> - -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -#ifdef __KERNEL__ - -#define BITS_PER_LONG 32 - -#endif /* __KERNEL__ */ - -#endif /* _M68K_TYPES_H */ diff --git a/arch/m68k/include/asm/unaligned.h b/arch/m68k/include/asm/unaligned.h index f4043ae63db..2b3ca0bf7a0 100644 --- a/arch/m68k/include/asm/unaligned.h +++ b/arch/m68k/include/asm/unaligned.h @@ -2,7 +2,7 @@  #define _ASM_M68K_UNALIGNED_H -#if defined(CONFIG_COLDFIRE) || defined(CONFIG_M68000) +#ifdef CONFIG_CPU_HAS_NO_UNALIGNED  #include <linux/unaligned/be_struct.h>  #include <linux/unaligned/le_byteshift.h>  #include <linux/unaligned/generic.h> @@ -12,7 +12,7 @@  #else  /* - * The m68k can do unaligned accesses itself.  + * The m68k can do unaligned accesses itself.   */  #include <linux/unaligned/access_ok.h>  #include <linux/unaligned/generic.h> diff --git a/arch/m68k/include/asm/xor.h b/arch/m68k/include/asm/xor.h deleted file mode 100644 index c82eb12a5b1..00000000000 --- a/arch/m68k/include/asm/xor.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/xor.h> diff --git a/arch/m68k/kernel/setup_no.c b/arch/m68k/kernel/setup_no.c index 7dc186b7a85..71fb29938db 100644 --- a/arch/m68k/kernel/setup_no.c +++ b/arch/m68k/kernel/setup_no.c @@ -218,13 +218,10 @@ void __init setup_arch(char **cmdline_p)  	printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)\n");  #endif -	pr_debug("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " -		 "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext, -		 (int) &_sdata, (int) &_edata, -		 (int) &_sbss, (int) &_ebss); -	pr_debug("MEMORY -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x\n ", -		 (int) &_ebss, (int) memory_start, -		 (int) memory_start, (int) memory_end); +	pr_debug("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n", +		 _stext, _etext, _sdata, _edata, __bss_start, __bss_stop); +	pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n ", +		 __bss_stop, memory_start, memory_start, memory_end);  	/* Keep a copy of command line */  	*cmdline_p = &command_line[0]; diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 8623f8dc16f..9a5932ec368 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -479,9 +479,13 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,  			goto bad_access;  		} -		mem_value = *mem; +		/* +		 * No need to check for EFAULT; we know that the page is +		 * present and writable. +		 */ +		__get_user(mem_value, mem);  		if (mem_value == oldval) -			*mem = newval; +			__put_user(newval, mem);  		pte_unmap_unlock(pte, ptl);  		up_read(&mm->mmap_sem); diff --git a/arch/m68k/kernel/vmlinux-nommu.lds b/arch/m68k/kernel/vmlinux-nommu.lds index 40e02d9c38b..06a763f49fd 100644 --- a/arch/m68k/kernel/vmlinux-nommu.lds +++ b/arch/m68k/kernel/vmlinux-nommu.lds @@ -78,9 +78,7 @@ SECTIONS {  		__init_end = .;  	} -	_sbss = .;  	BSS_SECTION(0, 0, 0) -	_ebss = .;  	_end = .; diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index 63407c83682..d0993594f55 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds @@ -31,9 +31,7 @@ SECTIONS    RW_DATA_SECTION(16, PAGE_SIZE, THREAD_SIZE) -  _sbss = .;    BSS_SECTION(0, 0, 0) -  _ebss = .;    _edata = .;			/* End of data section */ diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index ad0f46d64c0..8080469ee6c 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds @@ -44,9 +44,7 @@ __init_begin = .;  	. = ALIGN(PAGE_SIZE);  	__init_end = .; -  _sbss = .;    BSS_SECTION(0, 0, 0) -  _ebss = .;    _end = . ; diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c index 79e928a525d..ee5f0b1b5c5 100644 --- a/arch/m68k/lib/muldi3.c +++ b/arch/m68k/lib/muldi3.c @@ -19,7 +19,7 @@ along with GNU CC; see the file COPYING.  If not, write to  the Free Software Foundation, 59 Temple Place - Suite 330,  Boston, MA 02111-1307, USA.  */ -#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE) +#ifdef CONFIG_CPU_HAS_NO_MULDIV64  #define SI_TYPE_SIZE 32  #define __BITS4 (SI_TYPE_SIZE / 4) diff --git a/arch/m68k/mm/init_mm.c b/arch/m68k/mm/init_mm.c index f77f258dce3..282f9de6896 100644 --- a/arch/m68k/mm/init_mm.c +++ b/arch/m68k/mm/init_mm.c @@ -104,7 +104,7 @@ void __init print_memmap(void)  		MLK_ROUNDUP(__init_begin, __init_end),  		MLK_ROUNDUP(_stext, _etext),  		MLK_ROUNDUP(_sdata, _edata), -		MLK_ROUNDUP(_sbss, _ebss)); +		MLK_ROUNDUP(__bss_start, __bss_stop));  }  void __init mem_init(void) diff --git a/arch/m68k/mm/init_no.c b/arch/m68k/mm/init_no.c index 345ec0d83e3..688e3664aea 100644 --- a/arch/m68k/mm/init_no.c +++ b/arch/m68k/mm/init_no.c @@ -91,7 +91,7 @@ void __init mem_init(void)  	totalram_pages = free_all_bootmem();  	codek = (_etext - _stext) >> 10; -	datak = (_ebss - _sdata) >> 10; +	datak = (__bss_stop - _sdata) >> 10;  	initk = (__init_begin - __init_end) >> 10;  	tmp = nr_free_pages() << PAGE_SHIFT; diff --git a/arch/m68k/platform/68328/head-de2.S b/arch/m68k/platform/68328/head-de2.S index f632fdcb93e..537d3245b53 100644 --- a/arch/m68k/platform/68328/head-de2.S +++ b/arch/m68k/platform/68328/head-de2.S @@ -60,8 +60,8 @@ _start:   *	Move ROM filesystem above bss :-)   */ -	moveal	#_sbss, %a0			/* romfs at the start of bss */ -	moveal	#_ebss, %a1			/* Set up destination  */ +	moveal	#__bss_start, %a0		/* romfs at the start of bss */ +	moveal	#__bss_stop, %a1		/* Set up destination  */  	movel	%a0, %a2			/* Copy of bss start */  	movel	8(%a0), %d1			/* Get size of ROMFS */ @@ -84,8 +84,8 @@ _start:   * Initialize BSS segment to 0   */ -	lea	_sbss, %a0 -	lea	_ebss, %a1 +	lea	__bss_start, %a0 +	lea	__bss_stop, %a1  	/* Copy 0 to %a0 until %a0 == %a1 */  2:	cmpal	%a0, %a1 diff --git a/arch/m68k/platform/68328/head-pilot.S b/arch/m68k/platform/68328/head-pilot.S index 2ebfd642081..45a9dad29e3 100644 --- a/arch/m68k/platform/68328/head-pilot.S +++ b/arch/m68k/platform/68328/head-pilot.S @@ -110,7 +110,7 @@ L0:  	movel	#CONFIG_VECTORBASE, %d7  	addl	#16, %d7  	moveal	%d7, %a0 -	moveal	#_ebss, %a1 +	moveal	#__bss_stop, %a1  	lea	%a1@(512), %a2  	DBG_PUTC('C') @@ -138,8 +138,8 @@ LD1:  	DBG_PUTC('E') -	moveal	#_sbss, %a0 -	moveal	#_ebss, %a1 +	moveal	#__bss_start, %a0 +	moveal	#__bss_stop, %a1  	/* Copy 0 to %a0 until %a0 == %a1 */  L1: @@ -150,7 +150,7 @@ L1:  	DBG_PUTC('F')  	/* Copy command line from end of bss to command line */ -	moveal	#_ebss, %a0 +	moveal	#__bss_stop, %a0  	moveal	#command_line, %a1  	lea	%a1@(512), %a2 @@ -165,7 +165,7 @@ L3:  	movel	#_sdata, %d0	  	movel	%d0, _rambase	 -	movel	#_ebss,	%d0 +	movel	#__bss_stop, %d0  	movel	%d0, _ramstart  	movel	%a4, %d0 diff --git a/arch/m68k/platform/68328/head-ram.S b/arch/m68k/platform/68328/head-ram.S index 7f1aeeacb21..5189ef92609 100644 --- a/arch/m68k/platform/68328/head-ram.S +++ b/arch/m68k/platform/68328/head-ram.S @@ -76,8 +76,8 @@ pclp3:  	beq	pclp3  #endif /* DEBUG */  	moveal	#0x007ffff0, %ssp -	moveal	#_sbss, %a0 -	moveal	#_ebss, %a1 +	moveal	#__bss_start, %a0 +	moveal	#__bss_stop, %a1  	/* Copy 0 to %a0 until %a0 >= %a1 */  L1: diff --git a/arch/m68k/platform/68328/head-rom.S b/arch/m68k/platform/68328/head-rom.S index a5ff96d0295..3dff98ba2e9 100644 --- a/arch/m68k/platform/68328/head-rom.S +++ b/arch/m68k/platform/68328/head-rom.S @@ -59,8 +59,8 @@ _stext:	movew	#0x2700,%sr  	cmpal	%a1, %a2  	bhi	1b -	moveal	#_sbss, %a0 -	moveal	#_ebss, %a1 +	moveal	#__bss_start, %a0 +	moveal	#__bss_stop, %a1  	/* Copy 0 to %a0 until %a0 == %a1 */  1: @@ -70,7 +70,7 @@ _stext:	movew	#0x2700,%sr          movel   #_sdata, %d0              movel   %d0, _rambase         -        movel   #_ebss, %d0 +        movel   #__bss_stop, %d0          movel   %d0, _ramstart  	movel	#RAMEND-CONFIG_MEMORY_RESERVE*0x100000, %d0  	movel	%d0, _ramend diff --git a/arch/m68k/platform/68360/head-ram.S b/arch/m68k/platform/68360/head-ram.S index 8eb94fb6b97..acd213170d8 100644 --- a/arch/m68k/platform/68360/head-ram.S +++ b/arch/m68k/platform/68360/head-ram.S @@ -219,8 +219,8 @@ LD1:  	cmp.l	#_edata, %a1  	blt     LD1 -	moveal	#_sbss, %a0 -	moveal	#_ebss, %a1 +	moveal	#__bss_start, %a0 +	moveal	#__bss_stop, %a1  	/* Copy 0 to %a0 until %a0 == %a1 */  L1: @@ -234,7 +234,7 @@ load_quicc:  store_ram_size:  	/* Set ram size information */  	move.l	#_sdata, _rambase -	move.l	#_ebss, _ramstart +	move.l	#__bss_stop, _ramstart  	move.l	#RAMEND, %d0  	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/  	move.l	%d0, _ramend			/* Different from RAMEND.*/ diff --git a/arch/m68k/platform/68360/head-rom.S b/arch/m68k/platform/68360/head-rom.S index 97510e55b80..dfc756d9988 100644 --- a/arch/m68k/platform/68360/head-rom.S +++ b/arch/m68k/platform/68360/head-rom.S @@ -13,7 +13,7 @@   */  .global _stext -.global _sbss +.global __bss_start  .global _start  .global _rambase @@ -229,8 +229,8 @@ LD1:  	cmp.l	#_edata, %a1  	blt	LD1 -	moveal	#_sbss, %a0 -	moveal	#_ebss, %a1 +	moveal	#__bss_start, %a0 +	moveal	#__bss_stop, %a1  	/* Copy 0 to %a0 until %a0 == %a1 */  L1: @@ -244,7 +244,7 @@ load_quicc:  store_ram_size:  	/* Set ram size information */  	move.l	#_sdata, _rambase -	move.l	#_ebss, _ramstart +	move.l	#__bss_stop, _ramstart  	move.l	#RAMEND, %d0  	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/  	move.l	%d0, _ramend			/* Different from RAMEND.*/ diff --git a/arch/m68k/platform/coldfire/head.S b/arch/m68k/platform/coldfire/head.S index 4e0c9eb3bd1..b88f5716f35 100644 --- a/arch/m68k/platform/coldfire/head.S +++ b/arch/m68k/platform/coldfire/head.S @@ -230,8 +230,8 @@ _vstart:  	/*  	 *	Move ROM filesystem above bss :-)  	 */ -	lea	_sbss,%a0			/* get start of bss */ -	lea	_ebss,%a1			/* set up destination  */ +	lea	__bss_start,%a0			/* get start of bss */ +	lea	__bss_stop,%a1			/* set up destination  */  	movel	%a0,%a2				/* copy of bss start */  	movel	8(%a0),%d0			/* get size of ROMFS */ @@ -249,7 +249,7 @@ _copy_romfs:  	bne	_copy_romfs  #else /* CONFIG_ROMFS_FS */ -	lea	_ebss,%a1 +	lea	__bss_stop,%a1  	movel	%a1,_ramstart  #endif /* CONFIG_ROMFS_FS */ @@ -257,8 +257,8 @@ _copy_romfs:  	/*  	 *	Zero out the bss region.  	 */ -	lea	_sbss,%a0			/* get start of bss */ -	lea	_ebss,%a1			/* get end of bss */ +	lea	__bss_start,%a0			/* get start of bss */ +	lea	__bss_stop,%a1			/* get end of bss */  	clrl	%d0				/* set value */  _clear_bss:  	movel	%d0,(%a0)+			/* clear each word */ diff --git a/arch/m68k/sun3/prom/init.c b/arch/m68k/sun3/prom/init.c index d8e6349336b..eeba067d565 100644 --- a/arch/m68k/sun3/prom/init.c +++ b/arch/m68k/sun3/prom/init.c @@ -22,57 +22,13 @@ int prom_root_node;  struct linux_nodeops *prom_nodeops;  /* You must call prom_init() before you attempt to use any of the - * routines in the prom library.  It returns 0 on success, 1 on - * failure.  It gets passed the pointer to the PROM vector. + * routines in the prom library. + * It gets passed the pointer to the PROM vector.   */ -extern void prom_meminit(void); -extern void prom_ranges_init(void); -  void __init prom_init(struct linux_romvec *rp)  {  	romvec = rp; -#ifndef CONFIG_SUN3 -	switch(romvec->pv_romvers) { -	case 0: -		prom_vers = PROM_V0; -		break; -	case 2: -		prom_vers = PROM_V2; -		break; -	case 3: -		prom_vers = PROM_V3; -		break; -	case 4: -		prom_vers = PROM_P1275; -		prom_printf("PROMLIB: Sun IEEE Prom not supported yet\n"); -		prom_halt(); -		break; -	default: -		prom_printf("PROMLIB: Bad PROM version %d\n", -			    romvec->pv_romvers); -		prom_halt(); -		break; -	}; - -	prom_rev = romvec->pv_plugin_revision; -	prom_prev = romvec->pv_printrev; -	prom_nodeops = romvec->pv_nodeops; - -	prom_root_node = prom_getsibling(0); -	if((prom_root_node == 0) || (prom_root_node == -1)) -		prom_halt(); - -	if((((unsigned long) prom_nodeops) == 0) || -	   (((unsigned long) prom_nodeops) == -1)) -		prom_halt(); - -	prom_meminit(); - -	prom_ranges_init(); -#endif -//	printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n", -//	       romvec->pv_romvers, prom_rev);  	/* Initialization successful. */  	return; diff --git a/arch/microblaze/include/asm/sections.h b/arch/microblaze/include/asm/sections.h index 4487e150b45..c07ed5d2a82 100644 --- a/arch/microblaze/include/asm/sections.h +++ b/arch/microblaze/include/asm/sections.h @@ -18,10 +18,6 @@ extern char _ssbss[], _esbss[];  extern unsigned long __ivt_start[], __ivt_end[];  extern char _etext[], _stext[]; -#  ifdef CONFIG_MTD_UCLINUX -extern char *_ebss; -#  endif -  extern u32 _fdt_start[], _fdt_end[];  # endif /* !__ASSEMBLY__ */ diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index bb4907c828d..2b25bcf05c0 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -21,9 +21,6 @@  #include <linux/ftrace.h>  #include <linux/uaccess.h> -extern char *_ebss; -EXPORT_SYMBOL_GPL(_ebss); -  #ifdef CONFIG_FUNCTION_TRACER  extern void _mcount(void);  EXPORT_SYMBOL(_mcount); diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 16d8dfd9094..4da971d4392 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c @@ -121,7 +121,7 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,  	/* Move ROMFS out of BSS before clearing it */  	if (romfs_size > 0) { -		memmove(&_ebss, (int *)romfs_base, romfs_size); +		memmove(&__bss_stop, (int *)romfs_base, romfs_size);  		klimit += romfs_size;  	}  #endif @@ -165,7 +165,7 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,  	BUG_ON(romfs_size < 0); /* What else can we do? */  	printk("Moved 0x%08x bytes from 0x%08x to 0x%08x\n", -			romfs_size, romfs_base, (unsigned)&_ebss); +			romfs_size, romfs_base, (unsigned)&__bss_stop);  	printk("New klimit: 0x%08x\n", (unsigned)klimit);  #endif diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index 109e9d86ade..936d01a689d 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -131,7 +131,6 @@ SECTIONS {  			*(COMMON)  		. = ALIGN (4) ;  		__bss_stop = . ; -		_ebss = . ;  	}  	. = ALIGN(PAGE_SIZE);  	_end = .; diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 76de6b68487..107610e01a2 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -124,6 +124,7 @@ config S390  	select GENERIC_TIME_VSYSCALL  	select GENERIC_CLOCKEVENTS  	select KTIME_SCALAR if 32BIT +	select HAVE_ARCH_SECCOMP_FILTER  config SCHED_OMIT_FRAME_POINTER  	def_bool y diff --git a/arch/s390/include/asm/sparsemem.h b/arch/s390/include/asm/sparsemem.h index 0fb34027d3f..a60d085ddb4 100644 --- a/arch/s390/include/asm/sparsemem.h +++ b/arch/s390/include/asm/sparsemem.h @@ -4,13 +4,11 @@  #ifdef CONFIG_64BIT  #define SECTION_SIZE_BITS	28 -#define MAX_PHYSADDR_BITS	46  #define MAX_PHYSMEM_BITS	46  #else  #define SECTION_SIZE_BITS	25 -#define MAX_PHYSADDR_BITS	31  #define MAX_PHYSMEM_BITS	31  #endif /* CONFIG_64BIT */ diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index fb214dd9b7e..fe7b99759e1 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h @@ -12,6 +12,7 @@  #ifndef _ASM_SYSCALL_H  #define _ASM_SYSCALL_H	1 +#include <linux/audit.h>  #include <linux/sched.h>  #include <linux/err.h>  #include <asm/ptrace.h> @@ -87,4 +88,13 @@ static inline void syscall_set_arguments(struct task_struct *task,  		regs->orig_gpr2 = args[0];  } +static inline int syscall_get_arch(struct task_struct *task, +				   struct pt_regs *regs) +{ +#ifdef CONFIG_COMPAT +	if (test_tsk_thread_flag(task, TIF_31BIT)) +		return AUDIT_ARCH_S390; +#endif +	return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; +}  #endif	/* _ASM_SYSCALL_H */ diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index d1225089a4b..f606d935f49 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -620,7 +620,6 @@ asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg)  		return -EFAULT;  	if (a.offset & ~PAGE_MASK)  		return -EINVAL; -	a.addr = (unsigned long) compat_ptr(a.addr);  	return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd,  			      a.offset >> PAGE_SHIFT);  } @@ -631,7 +630,6 @@ asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg)  	if (copy_from_user(&a, arg, sizeof(a)))  		return -EFAULT; -	a.addr = (unsigned long) compat_ptr(a.addr);  	return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);  } diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index e835d6d5b7f..2d82cfcbce5 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1635,7 +1635,7 @@ ENTRY(compat_sys_process_vm_readv_wrapper)  	llgfr	%r6,%r6			# unsigned long  	llgf	%r0,164(%r15)		# unsigned long  	stg	%r0,160(%r15) -	jg	sys_process_vm_readv +	jg	compat_sys_process_vm_readv  ENTRY(compat_sys_process_vm_writev_wrapper)  	lgfr	%r2,%r2			# compat_pid_t @@ -1645,4 +1645,4 @@ ENTRY(compat_sys_process_vm_writev_wrapper)  	llgfr	%r6,%r6			# unsigned long  	llgf	%r0,164(%r15)		# unsigned long  	stg	%r0,160(%r15) -	jg	sys_process_vm_writev +	jg	compat_sys_process_vm_writev diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index f4eb37680b9..e4be113fbac 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -719,7 +719,11 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)  	long ret = 0;  	/* Do the secure computing check first. */ -	secure_computing_strict(regs->gprs[2]); +	if (secure_computing(regs->gprs[2])) { +		/* seccomp failures shouldn't expose any additional code. */ +		ret = -1; +		goto out; +	}  	/*  	 * The sysc_tracesys code in entry.S stored the system @@ -745,6 +749,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)  			    regs->gprs[2], regs->orig_gpr2,  			    regs->gprs[3], regs->gprs[4],  			    regs->gprs[5]); +out:  	return ret ?: regs->gprs[2];  } diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index b4a29eee41b..d0964d22adb 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -81,11 +81,12 @@ SYSCALL_DEFINE1(s390_personality, unsigned int, personality)  {  	unsigned int ret; -	if (current->personality == PER_LINUX32 && personality == PER_LINUX) -		personality = PER_LINUX32; +	if (personality(current->personality) == PER_LINUX32 && +	    personality(personality) == PER_LINUX) +		personality |= PER_LINUX32;  	ret = sys_personality(personality); -	if (ret == PER_LINUX32) -		ret = PER_LINUX; +	if (personality(ret) == PER_LINUX32) +		ret &= ~PER_LINUX32;  	return ret;  } diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 4c171f13b0e..b2256562314 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -335,7 +335,7 @@ static int dmae_irq_init(void)  	for (n = 0; n < NR_DMAE; n++) {  		int i = request_irq(get_dma_error_irq(n), dma_err, -				    IRQF_SHARED, dmae_name[n], NULL); +				    IRQF_SHARED, dmae_name[n], (void *)dmae_name[n]);  		if (unlikely(i < 0)) {  			printk(KERN_ERR "%s request_irq fail\n", dmae_name[n]);  			return i; diff --git a/arch/sh/include/asm/sections.h b/arch/sh/include/asm/sections.h index 4a5350037c8..1b6199740e9 100644 --- a/arch/sh/include/asm/sections.h +++ b/arch/sh/include/asm/sections.h @@ -6,7 +6,6 @@  extern long __nosave_begin, __nosave_end;  extern long __machvec_start, __machvec_end;  extern char __uncached_start, __uncached_end; -extern char _ebss[];  extern char __start_eh_frame[], __stop_eh_frame[];  #endif /* __ASM_SH_SECTIONS_H */ diff --git a/arch/sh/include/cpu-sh2a/cpu/sh7269.h b/arch/sh/include/cpu-sh2a/cpu/sh7269.h index 48d14498e77..2a0ca8780f0 100644 --- a/arch/sh/include/cpu-sh2a/cpu/sh7269.h +++ b/arch/sh/include/cpu-sh2a/cpu/sh7269.h @@ -183,18 +183,30 @@ enum {  	GPIO_FN_DV_DATA1, GPIO_FN_DV_DATA0,  	GPIO_FN_LCD_CLK, GPIO_FN_LCD_EXTCLK,  	GPIO_FN_LCD_VSYNC, GPIO_FN_LCD_HSYNC, GPIO_FN_LCD_DE, -	GPIO_FN_LCD_DATA23, GPIO_FN_LCD_DATA22, -	GPIO_FN_LCD_DATA21, GPIO_FN_LCD_DATA20, -	GPIO_FN_LCD_DATA19, GPIO_FN_LCD_DATA18, -	GPIO_FN_LCD_DATA17, GPIO_FN_LCD_DATA16, -	GPIO_FN_LCD_DATA15, GPIO_FN_LCD_DATA14, -	GPIO_FN_LCD_DATA13, GPIO_FN_LCD_DATA12, -	GPIO_FN_LCD_DATA11, GPIO_FN_LCD_DATA10, -	GPIO_FN_LCD_DATA9, GPIO_FN_LCD_DATA8, -	GPIO_FN_LCD_DATA7, GPIO_FN_LCD_DATA6, -	GPIO_FN_LCD_DATA5, GPIO_FN_LCD_DATA4, -	GPIO_FN_LCD_DATA3, GPIO_FN_LCD_DATA2, -	GPIO_FN_LCD_DATA1, GPIO_FN_LCD_DATA0, +	GPIO_FN_LCD_DATA23_PG23, GPIO_FN_LCD_DATA22_PG22, +	GPIO_FN_LCD_DATA21_PG21, GPIO_FN_LCD_DATA20_PG20, +	GPIO_FN_LCD_DATA19_PG19, GPIO_FN_LCD_DATA18_PG18, +	GPIO_FN_LCD_DATA17_PG17, GPIO_FN_LCD_DATA16_PG16, +	GPIO_FN_LCD_DATA15_PG15, GPIO_FN_LCD_DATA14_PG14, +	GPIO_FN_LCD_DATA13_PG13, GPIO_FN_LCD_DATA12_PG12, +	GPIO_FN_LCD_DATA11_PG11, GPIO_FN_LCD_DATA10_PG10, +	GPIO_FN_LCD_DATA9_PG9, GPIO_FN_LCD_DATA8_PG8, +	GPIO_FN_LCD_DATA7_PG7, GPIO_FN_LCD_DATA6_PG6, +	GPIO_FN_LCD_DATA5_PG5, GPIO_FN_LCD_DATA4_PG4, +	GPIO_FN_LCD_DATA3_PG3, GPIO_FN_LCD_DATA2_PG2, +	GPIO_FN_LCD_DATA1_PG1, GPIO_FN_LCD_DATA0_PG0, +	GPIO_FN_LCD_DATA23_PJ23, GPIO_FN_LCD_DATA22_PJ22, +	GPIO_FN_LCD_DATA21_PJ21, GPIO_FN_LCD_DATA20_PJ20, +	GPIO_FN_LCD_DATA19_PJ19, GPIO_FN_LCD_DATA18_PJ18, +	GPIO_FN_LCD_DATA17_PJ17, GPIO_FN_LCD_DATA16_PJ16, +	GPIO_FN_LCD_DATA15_PJ15, GPIO_FN_LCD_DATA14_PJ14, +	GPIO_FN_LCD_DATA13_PJ13, GPIO_FN_LCD_DATA12_PJ12, +	GPIO_FN_LCD_DATA11_PJ11, GPIO_FN_LCD_DATA10_PJ10, +	GPIO_FN_LCD_DATA9_PJ9, GPIO_FN_LCD_DATA8_PJ8, +	GPIO_FN_LCD_DATA7_PJ7, GPIO_FN_LCD_DATA6_PJ6, +	GPIO_FN_LCD_DATA5_PJ5, GPIO_FN_LCD_DATA4_PJ4, +	GPIO_FN_LCD_DATA3_PJ3, GPIO_FN_LCD_DATA2_PJ2, +	GPIO_FN_LCD_DATA1_PJ1, GPIO_FN_LCD_DATA0_PJ0,  	GPIO_FN_LCD_M_DISP,  }; diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c index f25127c46ec..039e4587dd9 100644 --- a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c +++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c @@ -758,12 +758,22 @@ enum {  	DV_DATA3_MARK, DV_DATA2_MARK, DV_DATA1_MARK, DV_DATA0_MARK,  	LCD_CLK_MARK, LCD_EXTCLK_MARK,  	LCD_VSYNC_MARK, LCD_HSYNC_MARK, LCD_DE_MARK, -	LCD_DATA23_MARK, LCD_DATA22_MARK, LCD_DATA21_MARK, LCD_DATA20_MARK, -	LCD_DATA19_MARK, LCD_DATA18_MARK, LCD_DATA17_MARK, LCD_DATA16_MARK, -	LCD_DATA15_MARK, LCD_DATA14_MARK, LCD_DATA13_MARK, LCD_DATA12_MARK, -	LCD_DATA11_MARK, LCD_DATA10_MARK, LCD_DATA9_MARK, LCD_DATA8_MARK, -	LCD_DATA7_MARK, LCD_DATA6_MARK, LCD_DATA5_MARK, LCD_DATA4_MARK, -	LCD_DATA3_MARK, LCD_DATA2_MARK, LCD_DATA1_MARK, LCD_DATA0_MARK, +	LCD_DATA23_PG23_MARK, LCD_DATA22_PG22_MARK, LCD_DATA21_PG21_MARK, +	LCD_DATA20_PG20_MARK, LCD_DATA19_PG19_MARK, LCD_DATA18_PG18_MARK, +	LCD_DATA17_PG17_MARK, LCD_DATA16_PG16_MARK, LCD_DATA15_PG15_MARK, +	LCD_DATA14_PG14_MARK, LCD_DATA13_PG13_MARK, LCD_DATA12_PG12_MARK, +	LCD_DATA11_PG11_MARK, LCD_DATA10_PG10_MARK, LCD_DATA9_PG9_MARK, +	LCD_DATA8_PG8_MARK, LCD_DATA7_PG7_MARK, LCD_DATA6_PG6_MARK, +	LCD_DATA5_PG5_MARK, LCD_DATA4_PG4_MARK, LCD_DATA3_PG3_MARK, +	LCD_DATA2_PG2_MARK, LCD_DATA1_PG1_MARK, LCD_DATA0_PG0_MARK, +	LCD_DATA23_PJ23_MARK, LCD_DATA22_PJ22_MARK, LCD_DATA21_PJ21_MARK, +	LCD_DATA20_PJ20_MARK, LCD_DATA19_PJ19_MARK, LCD_DATA18_PJ18_MARK, +	LCD_DATA17_PJ17_MARK, LCD_DATA16_PJ16_MARK, LCD_DATA15_PJ15_MARK, +	LCD_DATA14_PJ14_MARK, LCD_DATA13_PJ13_MARK, LCD_DATA12_PJ12_MARK, +	LCD_DATA11_PJ11_MARK, LCD_DATA10_PJ10_MARK, LCD_DATA9_PJ9_MARK, +	LCD_DATA8_PJ8_MARK, LCD_DATA7_PJ7_MARK, LCD_DATA6_PJ6_MARK, +	LCD_DATA5_PJ5_MARK, LCD_DATA4_PJ4_MARK, LCD_DATA3_PJ3_MARK, +	LCD_DATA2_PJ2_MARK, LCD_DATA1_PJ1_MARK, LCD_DATA0_PJ0_MARK,  	LCD_TCON6_MARK, LCD_TCON5_MARK, LCD_TCON4_MARK,  	LCD_TCON3_MARK, LCD_TCON2_MARK, LCD_TCON1_MARK, LCD_TCON0_MARK,  	LCD_M_DISP_MARK, @@ -1036,6 +1046,7 @@ static pinmux_enum_t pinmux_data[] = {  	PINMUX_DATA(PF1_DATA, PF1MD_000),  	PINMUX_DATA(BACK_MARK, PF1MD_001), +	PINMUX_DATA(SSL10_MARK, PF1MD_011),  	PINMUX_DATA(TIOC4B_MARK, PF1MD_100),  	PINMUX_DATA(DACK0_MARK, PF1MD_101), @@ -1049,47 +1060,50 @@ static pinmux_enum_t pinmux_data[] = {  	PINMUX_DATA(PG27_DATA, PG27MD_00),  	PINMUX_DATA(LCD_TCON2_MARK, PG27MD_10),  	PINMUX_DATA(LCD_EXTCLK_MARK, PG27MD_11), +	PINMUX_DATA(LCD_DE_MARK, PG27MD_11),  	PINMUX_DATA(PG26_DATA, PG26MD_00),  	PINMUX_DATA(LCD_TCON1_MARK, PG26MD_10), +	PINMUX_DATA(LCD_HSYNC_MARK, PG26MD_10),  	PINMUX_DATA(PG25_DATA, PG25MD_00),  	PINMUX_DATA(LCD_TCON0_MARK, PG25MD_10), +	PINMUX_DATA(LCD_VSYNC_MARK, PG25MD_10),  	PINMUX_DATA(PG24_DATA, PG24MD_00),  	PINMUX_DATA(LCD_CLK_MARK, PG24MD_10),  	PINMUX_DATA(PG23_DATA, PG23MD_000), -	PINMUX_DATA(LCD_DATA23_MARK, PG23MD_010), +	PINMUX_DATA(LCD_DATA23_PG23_MARK, PG23MD_010),  	PINMUX_DATA(LCD_TCON6_MARK, PG23MD_011),  	PINMUX_DATA(TXD5_MARK, PG23MD_100),  	PINMUX_DATA(PG22_DATA, PG22MD_000), -	PINMUX_DATA(LCD_DATA22_MARK, PG22MD_010), +	PINMUX_DATA(LCD_DATA22_PG22_MARK, PG22MD_010),  	PINMUX_DATA(LCD_TCON5_MARK, PG22MD_011),  	PINMUX_DATA(RXD5_MARK, PG22MD_100),  	PINMUX_DATA(PG21_DATA, PG21MD_000),  	PINMUX_DATA(DV_DATA7_MARK, PG21MD_001), -	PINMUX_DATA(LCD_DATA21_MARK, PG21MD_010), +	PINMUX_DATA(LCD_DATA21_PG21_MARK, PG21MD_010),  	PINMUX_DATA(LCD_TCON4_MARK, PG21MD_011),  	PINMUX_DATA(TXD4_MARK, PG21MD_100),  	PINMUX_DATA(PG20_DATA, PG20MD_000),  	PINMUX_DATA(DV_DATA6_MARK, PG20MD_001), -	PINMUX_DATA(LCD_DATA20_MARK, PG21MD_010), +	PINMUX_DATA(LCD_DATA20_PG20_MARK, PG21MD_010),  	PINMUX_DATA(LCD_TCON3_MARK, PG20MD_011),  	PINMUX_DATA(RXD4_MARK, PG20MD_100),  	PINMUX_DATA(PG19_DATA, PG19MD_000),  	PINMUX_DATA(DV_DATA5_MARK, PG19MD_001), -	PINMUX_DATA(LCD_DATA19_MARK, PG19MD_010), +	PINMUX_DATA(LCD_DATA19_PG19_MARK, PG19MD_010),  	PINMUX_DATA(SPDIF_OUT_MARK, PG19MD_011),  	PINMUX_DATA(SCK5_MARK, PG19MD_100),  	PINMUX_DATA(PG18_DATA, PG18MD_000),  	PINMUX_DATA(DV_DATA4_MARK, PG18MD_001), -	PINMUX_DATA(LCD_DATA18_MARK, PG18MD_010), +	PINMUX_DATA(LCD_DATA18_PG18_MARK, PG18MD_010),  	PINMUX_DATA(SPDIF_IN_MARK, PG18MD_011),  	PINMUX_DATA(SCK4_MARK, PG18MD_100), @@ -1097,103 +1111,103 @@ static pinmux_enum_t pinmux_data[] = {  // we're going with 2 bits  	PINMUX_DATA(PG17_DATA, PG17MD_00),  	PINMUX_DATA(WE3ICIOWRAHDQMUU_MARK, PG17MD_01), -	PINMUX_DATA(LCD_DATA17_MARK, PG17MD_10), +	PINMUX_DATA(LCD_DATA17_PG17_MARK, PG17MD_10),  // TODO hardware manual has PG16 3 bits wide in reg picture and 2 bits in description  // we're going with 2 bits  	PINMUX_DATA(PG16_DATA, PG16MD_00),  	PINMUX_DATA(WE2ICIORDDQMUL_MARK, PG16MD_01), -	PINMUX_DATA(LCD_DATA16_MARK, PG16MD_10), +	PINMUX_DATA(LCD_DATA16_PG16_MARK, PG16MD_10),  	PINMUX_DATA(PG15_DATA, PG15MD_00),  	PINMUX_DATA(D31_MARK, PG15MD_01), -	PINMUX_DATA(LCD_DATA15_MARK, PG15MD_10), +	PINMUX_DATA(LCD_DATA15_PG15_MARK, PG15MD_10),  	PINMUX_DATA(PINT7_PG_MARK, PG15MD_11),  	PINMUX_DATA(PG14_DATA, PG14MD_00),  	PINMUX_DATA(D30_MARK, PG14MD_01), -	PINMUX_DATA(LCD_DATA14_MARK, PG14MD_10), +	PINMUX_DATA(LCD_DATA14_PG14_MARK, PG14MD_10),  	PINMUX_DATA(PINT6_PG_MARK, PG14MD_11),  	PINMUX_DATA(PG13_DATA, PG13MD_00),  	PINMUX_DATA(D29_MARK, PG13MD_01), -	PINMUX_DATA(LCD_DATA13_MARK, PG13MD_10), +	PINMUX_DATA(LCD_DATA13_PG13_MARK, PG13MD_10),  	PINMUX_DATA(PINT5_PG_MARK, PG13MD_11),  	PINMUX_DATA(PG12_DATA, PG12MD_00),  	PINMUX_DATA(D28_MARK, PG12MD_01), -	PINMUX_DATA(LCD_DATA12_MARK, PG12MD_10), +	PINMUX_DATA(LCD_DATA12_PG12_MARK, PG12MD_10),  	PINMUX_DATA(PINT4_PG_MARK, PG12MD_11),  	PINMUX_DATA(PG11_DATA, PG11MD_000),  	PINMUX_DATA(D27_MARK, PG11MD_001), -	PINMUX_DATA(LCD_DATA11_MARK, PG11MD_010), +	PINMUX_DATA(LCD_DATA11_PG11_MARK, PG11MD_010),  	PINMUX_DATA(PINT3_PG_MARK, PG11MD_011),  	PINMUX_DATA(TIOC3D_MARK, PG11MD_100),  	PINMUX_DATA(PG10_DATA, PG10MD_000),  	PINMUX_DATA(D26_MARK, PG10MD_001), -	PINMUX_DATA(LCD_DATA10_MARK, PG10MD_010), +	PINMUX_DATA(LCD_DATA10_PG10_MARK, PG10MD_010),  	PINMUX_DATA(PINT2_PG_MARK, PG10MD_011),  	PINMUX_DATA(TIOC3C_MARK, PG10MD_100),  	PINMUX_DATA(PG9_DATA, PG9MD_000),  	PINMUX_DATA(D25_MARK, PG9MD_001), -	PINMUX_DATA(LCD_DATA9_MARK, PG9MD_010), +	PINMUX_DATA(LCD_DATA9_PG9_MARK, PG9MD_010),  	PINMUX_DATA(PINT1_PG_MARK, PG9MD_011),  	PINMUX_DATA(TIOC3B_MARK, PG9MD_100),  	PINMUX_DATA(PG8_DATA, PG8MD_000),  	PINMUX_DATA(D24_MARK, PG8MD_001), -	PINMUX_DATA(LCD_DATA8_MARK, PG8MD_010), +	PINMUX_DATA(LCD_DATA8_PG8_MARK, PG8MD_010),  	PINMUX_DATA(PINT0_PG_MARK, PG8MD_011),  	PINMUX_DATA(TIOC3A_MARK, PG8MD_100),  	PINMUX_DATA(PG7_DATA, PG7MD_000),  	PINMUX_DATA(D23_MARK, PG7MD_001), -	PINMUX_DATA(LCD_DATA7_MARK, PG7MD_010), +	PINMUX_DATA(LCD_DATA7_PG7_MARK, PG7MD_010),  	PINMUX_DATA(IRQ7_PG_MARK, PG7MD_011),  	PINMUX_DATA(TIOC2B_MARK, PG7MD_100),  	PINMUX_DATA(PG6_DATA, PG6MD_000),  	PINMUX_DATA(D22_MARK, PG6MD_001), -	PINMUX_DATA(LCD_DATA6_MARK, PG6MD_010), +	PINMUX_DATA(LCD_DATA6_PG6_MARK, PG6MD_010),  	PINMUX_DATA(IRQ6_PG_MARK, PG6MD_011),  	PINMUX_DATA(TIOC2A_MARK, PG6MD_100),  	PINMUX_DATA(PG5_DATA, PG5MD_000),  	PINMUX_DATA(D21_MARK, PG5MD_001), -	PINMUX_DATA(LCD_DATA5_MARK, PG5MD_010), +	PINMUX_DATA(LCD_DATA5_PG5_MARK, PG5MD_010),  	PINMUX_DATA(IRQ5_PG_MARK, PG5MD_011),  	PINMUX_DATA(TIOC1B_MARK, PG5MD_100),  	PINMUX_DATA(PG4_DATA, PG4MD_000),  	PINMUX_DATA(D20_MARK, PG4MD_001), -	PINMUX_DATA(LCD_DATA4_MARK, PG4MD_010), +	PINMUX_DATA(LCD_DATA4_PG4_MARK, PG4MD_010),  	PINMUX_DATA(IRQ4_PG_MARK, PG4MD_011),  	PINMUX_DATA(TIOC1A_MARK, PG4MD_100),  	PINMUX_DATA(PG3_DATA, PG3MD_000),  	PINMUX_DATA(D19_MARK, PG3MD_001), -	PINMUX_DATA(LCD_DATA3_MARK, PG3MD_010), +	PINMUX_DATA(LCD_DATA3_PG3_MARK, PG3MD_010),  	PINMUX_DATA(IRQ3_PG_MARK, PG3MD_011),  	PINMUX_DATA(TIOC0D_MARK, PG3MD_100),  	PINMUX_DATA(PG2_DATA, PG2MD_000),  	PINMUX_DATA(D18_MARK, PG2MD_001), -	PINMUX_DATA(LCD_DATA2_MARK, PG2MD_010), +	PINMUX_DATA(LCD_DATA2_PG2_MARK, PG2MD_010),  	PINMUX_DATA(IRQ2_PG_MARK, PG2MD_011),  	PINMUX_DATA(TIOC0C_MARK, PG2MD_100),  	PINMUX_DATA(PG1_DATA, PG1MD_000),  	PINMUX_DATA(D17_MARK, PG1MD_001), -	PINMUX_DATA(LCD_DATA1_MARK, PG1MD_010), +	PINMUX_DATA(LCD_DATA1_PG1_MARK, PG1MD_010),  	PINMUX_DATA(IRQ1_PG_MARK, PG1MD_011),  	PINMUX_DATA(TIOC0B_MARK, PG1MD_100),  	PINMUX_DATA(PG0_DATA, PG0MD_000),  	PINMUX_DATA(D16_MARK, PG0MD_001), -	PINMUX_DATA(LCD_DATA0_MARK, PG0MD_010), +	PINMUX_DATA(LCD_DATA0_PG0_MARK, PG0MD_010),  	PINMUX_DATA(IRQ0_PG_MARK, PG0MD_011),  	PINMUX_DATA(TIOC0A_MARK, PG0MD_100), @@ -1275,14 +1289,14 @@ static pinmux_enum_t pinmux_data[] = {  	PINMUX_DATA(PJ23_DATA, PJ23MD_000),  	PINMUX_DATA(DV_DATA23_MARK, PJ23MD_001), -	PINMUX_DATA(LCD_DATA23_MARK, PJ23MD_010), +	PINMUX_DATA(LCD_DATA23_PJ23_MARK, PJ23MD_010),  	PINMUX_DATA(LCD_TCON6_MARK, PJ23MD_011),  	PINMUX_DATA(IRQ3_PJ_MARK, PJ23MD_100),  	PINMUX_DATA(CTX1_MARK, PJ23MD_101),  	PINMUX_DATA(PJ22_DATA, PJ22MD_000),  	PINMUX_DATA(DV_DATA22_MARK, PJ22MD_001), -	PINMUX_DATA(LCD_DATA22_MARK, PJ22MD_010), +	PINMUX_DATA(LCD_DATA22_PJ22_MARK, PJ22MD_010),  	PINMUX_DATA(LCD_TCON5_MARK, PJ22MD_011),  	PINMUX_DATA(IRQ2_PJ_MARK, PJ22MD_100),  	PINMUX_DATA(CRX1_MARK, PJ22MD_101), @@ -1290,14 +1304,14 @@ static pinmux_enum_t pinmux_data[] = {  	PINMUX_DATA(PJ21_DATA, PJ21MD_000),  	PINMUX_DATA(DV_DATA21_MARK, PJ21MD_001), -	PINMUX_DATA(LCD_DATA21_MARK, PJ21MD_010), +	PINMUX_DATA(LCD_DATA21_PJ21_MARK, PJ21MD_010),  	PINMUX_DATA(LCD_TCON4_MARK, PJ21MD_011),  	PINMUX_DATA(IRQ1_PJ_MARK, PJ21MD_100),  	PINMUX_DATA(CTX2_MARK, PJ21MD_101),  	PINMUX_DATA(PJ20_DATA, PJ20MD_000),  	PINMUX_DATA(DV_DATA20_MARK, PJ20MD_001), -	PINMUX_DATA(LCD_DATA20_MARK, PJ20MD_010), +	PINMUX_DATA(LCD_DATA20_PJ20_MARK, PJ20MD_010),  	PINMUX_DATA(LCD_TCON3_MARK, PJ20MD_011),  	PINMUX_DATA(IRQ0_PJ_MARK, PJ20MD_100),  	PINMUX_DATA(CRX2_MARK, PJ20MD_101), @@ -1305,7 +1319,7 @@ static pinmux_enum_t pinmux_data[] = {  	PINMUX_DATA(PJ19_DATA, PJ19MD_000),  	PINMUX_DATA(DV_DATA19_MARK, PJ19MD_001), -	PINMUX_DATA(LCD_DATA19_MARK, PJ19MD_010), +	PINMUX_DATA(LCD_DATA19_PJ19_MARK, PJ19MD_010),  	PINMUX_DATA(MISO0_PJ19_MARK, PJ19MD_011),  	PINMUX_DATA(TIOC0D_MARK, PJ19MD_100),  	PINMUX_DATA(SIOFRXD_MARK, PJ19MD_101), @@ -1313,126 +1327,126 @@ static pinmux_enum_t pinmux_data[] = {  	PINMUX_DATA(PJ18_DATA, PJ18MD_000),  	PINMUX_DATA(DV_DATA18_MARK, PJ18MD_001), -	PINMUX_DATA(LCD_DATA18_MARK, PJ18MD_010), +	PINMUX_DATA(LCD_DATA18_PJ18_MARK, PJ18MD_010),  	PINMUX_DATA(MOSI0_PJ18_MARK, PJ18MD_011),  	PINMUX_DATA(TIOC0C_MARK, PJ18MD_100),  	PINMUX_DATA(SIOFTXD_MARK, PJ18MD_101),  	PINMUX_DATA(PJ17_DATA, PJ17MD_000),  	PINMUX_DATA(DV_DATA17_MARK, PJ17MD_001), -	PINMUX_DATA(LCD_DATA17_MARK, PJ17MD_010), +	PINMUX_DATA(LCD_DATA17_PJ17_MARK, PJ17MD_010),  	PINMUX_DATA(SSL00_PJ17_MARK, PJ17MD_011),  	PINMUX_DATA(TIOC0B_MARK, PJ17MD_100),  	PINMUX_DATA(SIOFSYNC_MARK, PJ17MD_101),  	PINMUX_DATA(PJ16_DATA, PJ16MD_000),  	PINMUX_DATA(DV_DATA16_MARK, PJ16MD_001), -	PINMUX_DATA(LCD_DATA16_MARK, PJ16MD_010), +	PINMUX_DATA(LCD_DATA16_PJ16_MARK, PJ16MD_010),  	PINMUX_DATA(RSPCK0_PJ16_MARK, PJ16MD_011),  	PINMUX_DATA(TIOC0A_MARK, PJ16MD_100),  	PINMUX_DATA(SIOFSCK_MARK, PJ16MD_101),  	PINMUX_DATA(PJ15_DATA, PJ15MD_000),  	PINMUX_DATA(DV_DATA15_MARK, PJ15MD_001), -	PINMUX_DATA(LCD_DATA15_MARK, PJ15MD_010), +	PINMUX_DATA(LCD_DATA15_PJ15_MARK, PJ15MD_010),  	PINMUX_DATA(PINT7_PJ_MARK, PJ15MD_011),  	PINMUX_DATA(PWM2H_MARK, PJ15MD_100),  	PINMUX_DATA(TXD7_MARK, PJ15MD_101),  	PINMUX_DATA(PJ14_DATA, PJ14MD_000),  	PINMUX_DATA(DV_DATA14_MARK, PJ14MD_001), -	PINMUX_DATA(LCD_DATA14_MARK, PJ14MD_010), +	PINMUX_DATA(LCD_DATA14_PJ14_MARK, PJ14MD_010),  	PINMUX_DATA(PINT6_PJ_MARK, PJ14MD_011),  	PINMUX_DATA(PWM2G_MARK, PJ14MD_100),  	PINMUX_DATA(TXD6_MARK, PJ14MD_101),  	PINMUX_DATA(PJ13_DATA, PJ13MD_000),  	PINMUX_DATA(DV_DATA13_MARK, PJ13MD_001), -	PINMUX_DATA(LCD_DATA13_MARK, PJ13MD_010), +	PINMUX_DATA(LCD_DATA13_PJ13_MARK, PJ13MD_010),  	PINMUX_DATA(PINT5_PJ_MARK, PJ13MD_011),  	PINMUX_DATA(PWM2F_MARK, PJ13MD_100),  	PINMUX_DATA(TXD5_MARK, PJ13MD_101),  	PINMUX_DATA(PJ12_DATA, PJ12MD_000),  	PINMUX_DATA(DV_DATA12_MARK, PJ12MD_001), -	PINMUX_DATA(LCD_DATA12_MARK, PJ12MD_010), +	PINMUX_DATA(LCD_DATA12_PJ12_MARK, PJ12MD_010),  	PINMUX_DATA(PINT4_PJ_MARK, PJ12MD_011),  	PINMUX_DATA(PWM2E_MARK, PJ12MD_100),  	PINMUX_DATA(SCK7_MARK, PJ12MD_101),  	PINMUX_DATA(PJ11_DATA, PJ11MD_000),  	PINMUX_DATA(DV_DATA11_MARK, PJ11MD_001), -	PINMUX_DATA(LCD_DATA11_MARK, PJ11MD_010), +	PINMUX_DATA(LCD_DATA11_PJ11_MARK, PJ11MD_010),  	PINMUX_DATA(PINT3_PJ_MARK, PJ11MD_011),  	PINMUX_DATA(PWM2D_MARK, PJ11MD_100),  	PINMUX_DATA(SCK6_MARK, PJ11MD_101),  	PINMUX_DATA(PJ10_DATA, PJ10MD_000),  	PINMUX_DATA(DV_DATA10_MARK, PJ10MD_001), -	PINMUX_DATA(LCD_DATA10_MARK, PJ10MD_010), +	PINMUX_DATA(LCD_DATA10_PJ10_MARK, PJ10MD_010),  	PINMUX_DATA(PINT2_PJ_MARK, PJ10MD_011),  	PINMUX_DATA(PWM2C_MARK, PJ10MD_100),  	PINMUX_DATA(SCK5_MARK, PJ10MD_101),  	PINMUX_DATA(PJ9_DATA, PJ9MD_000),  	PINMUX_DATA(DV_DATA9_MARK, PJ9MD_001), -	PINMUX_DATA(LCD_DATA9_MARK, PJ9MD_010), +	PINMUX_DATA(LCD_DATA9_PJ9_MARK, PJ9MD_010),  	PINMUX_DATA(PINT1_PJ_MARK, PJ9MD_011),  	PINMUX_DATA(PWM2B_MARK, PJ9MD_100),  	PINMUX_DATA(RTS5_MARK, PJ9MD_101),  	PINMUX_DATA(PJ8_DATA, PJ8MD_000),  	PINMUX_DATA(DV_DATA8_MARK, PJ8MD_001), -	PINMUX_DATA(LCD_DATA8_MARK, PJ8MD_010), +	PINMUX_DATA(LCD_DATA8_PJ8_MARK, PJ8MD_010),  	PINMUX_DATA(PINT0_PJ_MARK, PJ8MD_011),  	PINMUX_DATA(PWM2A_MARK, PJ8MD_100),  	PINMUX_DATA(CTS5_MARK, PJ8MD_101),  	PINMUX_DATA(PJ7_DATA, PJ7MD_000),  	PINMUX_DATA(DV_DATA7_MARK, PJ7MD_001), -	PINMUX_DATA(LCD_DATA7_MARK, PJ7MD_010), +	PINMUX_DATA(LCD_DATA7_PJ7_MARK, PJ7MD_010),  	PINMUX_DATA(SD_D2_MARK, PJ7MD_011),  	PINMUX_DATA(PWM1H_MARK, PJ7MD_100),  	PINMUX_DATA(PJ6_DATA, PJ6MD_000),  	PINMUX_DATA(DV_DATA6_MARK, PJ6MD_001), -	PINMUX_DATA(LCD_DATA6_MARK, PJ6MD_010), +	PINMUX_DATA(LCD_DATA6_PJ6_MARK, PJ6MD_010),  	PINMUX_DATA(SD_D3_MARK, PJ6MD_011),  	PINMUX_DATA(PWM1G_MARK, PJ6MD_100),  	PINMUX_DATA(PJ5_DATA, PJ5MD_000),  	PINMUX_DATA(DV_DATA5_MARK, PJ5MD_001), -	PINMUX_DATA(LCD_DATA5_MARK, PJ5MD_010), +	PINMUX_DATA(LCD_DATA5_PJ5_MARK, PJ5MD_010),  	PINMUX_DATA(SD_CMD_MARK, PJ5MD_011),  	PINMUX_DATA(PWM1F_MARK, PJ5MD_100),  	PINMUX_DATA(PJ4_DATA, PJ4MD_000),  	PINMUX_DATA(DV_DATA4_MARK, PJ4MD_001), -	PINMUX_DATA(LCD_DATA4_MARK, PJ4MD_010), +	PINMUX_DATA(LCD_DATA4_PJ4_MARK, PJ4MD_010),  	PINMUX_DATA(SD_CLK_MARK, PJ4MD_011),  	PINMUX_DATA(PWM1E_MARK, PJ4MD_100),  	PINMUX_DATA(PJ3_DATA, PJ3MD_000),  	PINMUX_DATA(DV_DATA3_MARK, PJ3MD_001), -	PINMUX_DATA(LCD_DATA3_MARK, PJ3MD_010), +	PINMUX_DATA(LCD_DATA3_PJ3_MARK, PJ3MD_010),  	PINMUX_DATA(SD_D0_MARK, PJ3MD_011),  	PINMUX_DATA(PWM1D_MARK, PJ3MD_100),  	PINMUX_DATA(PJ2_DATA, PJ2MD_000),  	PINMUX_DATA(DV_DATA2_MARK, PJ2MD_001), -	PINMUX_DATA(LCD_DATA2_MARK, PJ2MD_010), +	PINMUX_DATA(LCD_DATA2_PJ2_MARK, PJ2MD_010),  	PINMUX_DATA(SD_D1_MARK, PJ2MD_011),  	PINMUX_DATA(PWM1C_MARK, PJ2MD_100),  	PINMUX_DATA(PJ1_DATA, PJ1MD_000),  	PINMUX_DATA(DV_DATA1_MARK, PJ1MD_001), -	PINMUX_DATA(LCD_DATA1_MARK, PJ1MD_010), +	PINMUX_DATA(LCD_DATA1_PJ1_MARK, PJ1MD_010),  	PINMUX_DATA(SD_WP_MARK, PJ1MD_011),  	PINMUX_DATA(PWM1B_MARK, PJ1MD_100),  	PINMUX_DATA(PJ0_DATA, PJ0MD_000),  	PINMUX_DATA(DV_DATA0_MARK, PJ0MD_001), -	PINMUX_DATA(LCD_DATA0_MARK, PJ0MD_010), +	PINMUX_DATA(LCD_DATA0_PJ0_MARK, PJ0MD_010),  	PINMUX_DATA(SD_CD_MARK, PJ0MD_011),  	PINMUX_DATA(PWM1A_MARK, PJ0MD_100),  }; @@ -1877,30 +1891,55 @@ static struct pinmux_gpio pinmux_gpios[] = {  	PINMUX_GPIO(GPIO_FN_LCD_HSYNC, LCD_HSYNC_MARK),  	PINMUX_GPIO(GPIO_FN_LCD_DE, LCD_DE_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA23, LCD_DATA23_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA22, LCD_DATA22_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA21, LCD_DATA21_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA20, LCD_DATA20_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA19, LCD_DATA19_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA18, LCD_DATA18_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA17, LCD_DATA17_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA16, LCD_DATA16_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK), -	PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA23_PG23, LCD_DATA23_PG23_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA22_PG22, LCD_DATA22_PG22_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA21_PG21, LCD_DATA21_PG21_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA20_PG20, LCD_DATA20_PG20_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA19_PG19, LCD_DATA19_PG19_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA18_PG18, LCD_DATA18_PG18_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA17_PG17, LCD_DATA17_PG17_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA16_PG16, LCD_DATA16_PG16_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA15_PG15, LCD_DATA15_PG15_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA14_PG14, LCD_DATA14_PG14_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA13_PG13, LCD_DATA13_PG13_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA12_PG12, LCD_DATA12_PG12_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA11_PG11, LCD_DATA11_PG11_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA10_PG10, LCD_DATA10_PG10_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA9_PG9, LCD_DATA9_PG9_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA8_PG8, LCD_DATA8_PG8_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA7_PG7, LCD_DATA7_PG7_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA6_PG6, LCD_DATA6_PG6_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA5_PG5, LCD_DATA5_PG5_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA4_PG4, LCD_DATA4_PG4_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA3_PG3, LCD_DATA3_PG3_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA2_PG2, LCD_DATA2_PG2_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA1_PG1, LCD_DATA1_PG1_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA0_PG0, LCD_DATA0_PG0_MARK), + +	PINMUX_GPIO(GPIO_FN_LCD_DATA23_PJ23, LCD_DATA23_PJ23_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA22_PJ22, LCD_DATA22_PJ22_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA21_PJ21, LCD_DATA21_PJ21_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA20_PJ20, LCD_DATA20_PJ20_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA19_PJ19, LCD_DATA19_PJ19_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA18_PJ18, LCD_DATA18_PJ18_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA17_PJ17, LCD_DATA17_PJ17_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA16_PJ16, LCD_DATA16_PJ16_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA15_PJ15, LCD_DATA15_PJ15_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA14_PJ14, LCD_DATA14_PJ14_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA13_PJ13, LCD_DATA13_PJ13_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA12_PJ12, LCD_DATA12_PJ12_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA11_PJ11, LCD_DATA11_PJ11_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA10_PJ10, LCD_DATA10_PJ10_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA9_PJ9, LCD_DATA9_PJ9_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA8_PJ8, LCD_DATA8_PJ8_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA7_PJ7, LCD_DATA7_PJ7_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA6_PJ6, LCD_DATA6_PJ6_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA5_PJ5, LCD_DATA5_PJ5_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA4_PJ4, LCD_DATA4_PJ4_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA3_PJ3, LCD_DATA3_PJ3_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA2_PJ2, LCD_DATA2_PJ2_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA1_PJ1, LCD_DATA1_PJ1_MARK), +	PINMUX_GPIO(GPIO_FN_LCD_DATA0_PJ0, LCD_DATA0_PJ0_MARK),  	PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK),  }; diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 7b57bf1dc85..ebe7a7d9721 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -273,7 +273,7 @@ void __init setup_arch(char **cmdline_p)  	data_resource.start = virt_to_phys(_etext);  	data_resource.end = virt_to_phys(_edata)-1;  	bss_resource.start = virt_to_phys(__bss_start); -	bss_resource.end = virt_to_phys(_ebss)-1; +	bss_resource.end = virt_to_phys(__bss_stop)-1;  #ifdef CONFIG_CMDLINE_OVERWRITE  	strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line)); diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 3896f26efa4..2a0a596ebf6 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -19,7 +19,6 @@ EXPORT_SYMBOL(csum_partial);  EXPORT_SYMBOL(csum_partial_copy_generic);  EXPORT_SYMBOL(copy_page);  EXPORT_SYMBOL(__clear_user); -EXPORT_SYMBOL(_ebss);  EXPORT_SYMBOL(empty_zero_page);  #define DECLARE_EXPORT(name)		\ diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index c98905f71e2..db88cbf9eaf 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -78,7 +78,6 @@ SECTIONS  	. = ALIGN(PAGE_SIZE);  	__init_end = .;  	BSS_SECTION(0, PAGE_SIZE, 4) -	_ebss = .;			/* uClinux MTD sucks */  	_end = . ;  	STABS_DEBUG diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index 84a57761f17..60164e65d66 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S @@ -39,7 +39,7 @@   *   * Make sure the stack pointer contains a valid address. Valid   * addresses for kernel stacks are anywhere after the bss - * (after _ebss) and anywhere in init_thread_union (init_stack). + * (after __bss_stop) and anywhere in init_thread_union (init_stack).   */  #define STACK_CHECK()					\  	mov	#(THREAD_SIZE >> 10), r0;		\ @@ -60,7 +60,7 @@  	cmp/hi	r2, r1;					\  	bf	stack_panic;				\  							\ -	/* If sp > _ebss then we're OK. */		\ +	/* If sp > __bss_stop then we're OK. */		\  	mov.l	.L_ebss, r1;				\  	cmp/hi	r1, r15;				\  	bt	1f;					\ @@ -70,7 +70,7 @@  	cmp/hs	r1, r15;				\  	bf	stack_panic;				\  							\ -	/* If sp > init_stack && sp < _ebss, not OK. */	\ +	/* If sp > init_stack && sp < __bss_stop, not OK. */	\  	add	r0, r1;					\  	cmp/hs	r1, r15;				\  	bt	stack_panic;				\ @@ -292,8 +292,6 @@ stack_panic:  	 nop  	.align 2 -.L_ebss: -	.long	_ebss  .L_init_thread_union:  	.long	init_thread_union  .Lpanic: diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 0dc1f578608..11c6c9603e7 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -502,12 +502,12 @@ SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality)  {  	int ret; -	if (current->personality == PER_LINUX32 && -	    personality == PER_LINUX) -		personality = PER_LINUX32; +	if (personality(current->personality) == PER_LINUX32 && +	    personality(personality) == PER_LINUX) +		personality |= PER_LINUX32;  	ret = sys_personality(personality); -	if (ret == PER_LINUX32) -		ret = PER_LINUX; +	if (personality(ret) == PER_LINUX32) +		ret &= ~PER_LINUX32;  	return ret;  } diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 6026fdd1b2e..d58edf5fefd 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -2020,6 +2020,9 @@ EXPORT_SYMBOL(_PAGE_CACHE);  #ifdef CONFIG_SPARSEMEM_VMEMMAP  unsigned long vmemmap_table[VMEMMAP_SIZE]; +static long __meminitdata addr_start, addr_end; +static int __meminitdata node_start; +  int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)  {  	unsigned long vstart = (unsigned long) start; @@ -2050,15 +2053,30 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)  			*vmem_pp = pte_base | __pa(block); -			printk(KERN_INFO "[%p-%p] page_structs=%lu " -			       "node=%d entry=%lu/%lu\n", start, block, nr, -			       node, -			       addr >> VMEMMAP_CHUNK_SHIFT, -			       VMEMMAP_SIZE); +			/* check to see if we have contiguous blocks */ +			if (addr_end != addr || node_start != node) { +				if (addr_start) +					printk(KERN_DEBUG " [%lx-%lx] on node %d\n", +					       addr_start, addr_end-1, node_start); +				addr_start = addr; +				node_start = node; +			} +			addr_end = addr + VMEMMAP_CHUNK;  		}  	}  	return 0;  } + +void __meminit vmemmap_populate_print_last(void) +{ +	if (addr_start) { +		printk(KERN_DEBUG " [%lx-%lx] on node %d\n", +		       addr_start, addr_end-1, node_start); +		addr_start = 0; +		addr_end = 0; +		node_start = 0; +	} +}  #endif /* CONFIG_SPARSEMEM_VMEMMAP */  static void prot_init_common(unsigned long page_none, diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ba2657c4921..8ec3a1aa4ab 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1527,7 +1527,7 @@ config SECCOMP  	  If unsure, say Y. Only embedded should say N here.  config CC_STACKPROTECTOR -	bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" +	bool "Enable -fstack-protector buffer overflow detection"  	---help---  	  This option turns on the -fstack-protector GCC feature. This  	  feature puts, at the beginning of functions, a canary value on diff --git a/arch/x86/Makefile b/arch/x86/Makefile index b0c5276861e..682e9c210ba 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -27,6 +27,10 @@ ifeq ($(CONFIG_X86_32),y)          KBUILD_CFLAGS += -msoft-float -mregparm=3 -freg-struct-return +        # Never want PIC in a 32-bit kernel, prevent breakage with GCC built +        # with nonstandard options +        KBUILD_CFLAGS += -fno-pic +          # prevent gcc from keeping the stack 16 byte aligned          KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 5a747dd884d..f7535bedc33 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -57,7 +57,7 @@ KBUILD_CFLAGS	:= $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \  		   -Wall -Wstrict-prototypes \  		   -march=i386 -mregparm=3 \  		   -include $(srctree)/$(src)/code16gcc.h \ -		   -fno-strict-aliasing -fomit-frame-pointer \ +		   -fno-strict-aliasing -fomit-frame-pointer -fno-pic \  		   $(call cc-option, -ffreestanding) \  		   $(call cc-option, -fno-toplevel-reorder,\  			$(call cc-option, -fno-unit-at-a-time)) \ diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 441520e4174..a3ac52b29cb 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -33,6 +33,14 @@  #define MCI_STATUS_PCC   (1ULL<<57)  /* processor context corrupt */  #define MCI_STATUS_S	 (1ULL<<56)  /* Signaled machine check */  #define MCI_STATUS_AR	 (1ULL<<55)  /* Action required */ +#define MCACOD		  0xffff     /* MCA Error Code */ + +/* Architecturally defined codes from SDM Vol. 3B Chapter 15 */ +#define MCACOD_SCRUB	0x00C0	/* 0xC0-0xCF Memory Scrubbing */ +#define MCACOD_SCRUBMSK	0xfff0 +#define MCACOD_L3WB	0x017A	/* L3 Explicit Writeback */ +#define MCACOD_DATA	0x0134	/* Data Load */ +#define MCACOD_INSTR	0x0150	/* Instruction Fetch */  /* MCi_MISC register defines */  #define MCI_MISC_ADDR_LSB(m)	((m) & 0x3f) diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index dab39350e51..cb4e43bce98 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -196,11 +196,16 @@ static inline u32 get_ibs_caps(void) { return 0; }  extern void perf_events_lapic_init(void);  /* - * Abuse bit 3 of the cpu eflags register to indicate proper PEBS IP fixups. - * This flag is otherwise unused and ABI specified to be 0, so nobody should - * care what we do with it. + * Abuse bits {3,5} of the cpu eflags register. These flags are otherwise + * unused and ABI specified to be 0, so nobody should care what we do with + * them. + * + * EXACT - the IP points to the exact instruction that triggered the + *         event (HW bugs exempt). + * VM    - original X86_VM_MASK; see set_linear_ip().   */  #define PERF_EFLAGS_EXACT	(1UL << 3) +#define PERF_EFLAGS_VM		(1UL << 5)  struct pt_regs;  extern unsigned long perf_instruction_pointer(struct pt_regs *regs); diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 95bf99de905..1b8e5a03d94 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -25,10 +25,6 @@ unsigned long acpi_realmode_flags;  static char temp_stack[4096];  #endif -asmlinkage void acpi_enter_s3(void) -{ -	acpi_enter_sleep_state(3, wake_sleep_flags); -}  /**   * acpi_suspend_lowlevel - save kernel state   * diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index 5653a5791ec..67f59f8c695 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -2,7 +2,6 @@   *	Variables and functions used by the code in sleep.c   */ -#include <linux/linkage.h>  #include <asm/realmode.h>  extern unsigned long saved_video_mode; @@ -11,7 +10,6 @@ extern long saved_magic;  extern int wakeup_pmode_return;  extern u8 wake_sleep_flags; -extern asmlinkage void acpi_enter_s3(void);  extern unsigned long acpi_copy_wakeup_routine(unsigned long);  extern void wakeup_long64(void); diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S index 72610839f03..13ab720573e 100644 --- a/arch/x86/kernel/acpi/wakeup_32.S +++ b/arch/x86/kernel/acpi/wakeup_32.S @@ -74,7 +74,9 @@ restore_registers:  ENTRY(do_suspend_lowlevel)  	call	save_processor_state  	call	save_registers -	call	acpi_enter_s3 +	pushl	$3 +	call	acpi_enter_sleep_state +	addl	$4, %esp  #	In case of S3 failure, we'll emerge here.  Jump  # 	to ret_point to recover diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S index 014d1d28c39..8ea5164cbd0 100644 --- a/arch/x86/kernel/acpi/wakeup_64.S +++ b/arch/x86/kernel/acpi/wakeup_64.S @@ -71,7 +71,9 @@ ENTRY(do_suspend_lowlevel)  	movq	%rsi, saved_rsi  	addq	$8, %rsp -	call	acpi_enter_s3 +	movl	$3, %edi +	xorl	%eax, %eax +	call	acpi_enter_sleep_state  	/* in case something went wrong, restore the machine status and go on */  	jmp	resume_point diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 931280ff829..afb7ff79a29 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -224,7 +224,7 @@ void __init arch_init_ideal_nops(void)  			ideal_nops = intel_nops;  #endif  		} - +		break;  	default:  #ifdef CONFIG_X86_64  		ideal_nops = k8_nops; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 406eee78468..c265593ec2c 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1204,7 +1204,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; @@ -1212,7 +1212,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) @@ -1356,6 +1356,16 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,  	if (!IO_APIC_IRQ(irq))  		return; +	/* +	 * For legacy irqs, cfg->domain starts with cpu 0. Now that IO-APIC +	 * can handle this irq and the apic driver is finialized at this point, +	 * update the cfg->domain. +	 */ +	if (irq < legacy_pic->nr_legacy_irqs && +	    cpumask_equal(cfg->domain, cpumask_of(0))) +		apic->vector_allocation_domain(0, cfg->domain, +					       apic->target_cpus()); +  	if (assign_irq_vector(irq, cfg, apic->target_cpus()))  		return; diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 46d8786d655..a5fbc3c5fcc 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -144,6 +144,8 @@ static int __init x86_xsave_setup(char *s)  {  	setup_clear_cpu_cap(X86_FEATURE_XSAVE);  	setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT); +	setup_clear_cpu_cap(X86_FEATURE_AVX); +	setup_clear_cpu_cap(X86_FEATURE_AVX2);  	return 1;  }  __setup("noxsave", x86_xsave_setup); diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c index 413c2ced887..13017626f9a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c @@ -55,13 +55,6 @@ static struct severity {  #define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S)  #define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR)  #define	MCI_ADDR (MCI_STATUS_ADDRV|MCI_STATUS_MISCV) -#define MCACOD 0xffff -/* Architecturally defined codes from SDM Vol. 3B Chapter 15 */ -#define MCACOD_SCRUB	0x00C0	/* 0xC0-0xCF Memory Scrubbing */ -#define MCACOD_SCRUBMSK	0xfff0 -#define MCACOD_L3WB	0x017A	/* L3 Explicit Writeback */ -#define MCACOD_DATA	0x0134	/* Data Load */ -#define MCACOD_INSTR	0x0150	/* Instruction Fetch */  	MCESEV(  		NO, "Invalid", diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 5e095f873e3..292d0258311 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -103,6 +103,8 @@ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = {  static DEFINE_PER_CPU(struct work_struct, mce_work); +static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs); +  /*   * CPU/chipset specific EDAC code can register a notifier call here to print   * MCE errors in a human-readable form. @@ -650,14 +652,18 @@ EXPORT_SYMBOL_GPL(machine_check_poll);   * Do a quick check if any of the events requires a panic.   * This decides if we keep the events around or clear them.   */ -static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp) +static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp, +			  struct pt_regs *regs)  {  	int i, ret = 0;  	for (i = 0; i < banks; i++) {  		m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i)); -		if (m->status & MCI_STATUS_VAL) +		if (m->status & MCI_STATUS_VAL) {  			__set_bit(i, validp); +			if (quirk_no_way_out) +				quirk_no_way_out(i, m, regs); +		}  		if (mce_severity(m, tolerant, msg) >= MCE_PANIC_SEVERITY)  			ret = 1;  	} @@ -1040,7 +1046,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)  	*final = m;  	memset(valid_banks, 0, sizeof(valid_banks)); -	no_way_out = mce_no_way_out(&m, &msg, valid_banks); +	no_way_out = mce_no_way_out(&m, &msg, valid_banks, regs);  	barrier(); @@ -1418,6 +1424,34 @@ static void __mcheck_cpu_init_generic(void)  	}  } +/* + * During IFU recovery Sandy Bridge -EP4S processors set the RIPV and + * EIPV bits in MCG_STATUS to zero on the affected logical processor (SDM + * Vol 3B Table 15-20). But this confuses both the code that determines + * whether the machine check occurred in kernel or user mode, and also + * the severity assessment code. Pretend that EIPV was set, and take the + * ip/cs values from the pt_regs that mce_gather_info() ignored earlier. + */ +static void quirk_sandybridge_ifu(int bank, struct mce *m, struct pt_regs *regs) +{ +	if (bank != 0) +		return; +	if ((m->mcgstatus & (MCG_STATUS_EIPV|MCG_STATUS_RIPV)) != 0) +		return; +	if ((m->status & (MCI_STATUS_OVER|MCI_STATUS_UC| +		          MCI_STATUS_EN|MCI_STATUS_MISCV|MCI_STATUS_ADDRV| +			  MCI_STATUS_PCC|MCI_STATUS_S|MCI_STATUS_AR| +			  MCACOD)) != +			 (MCI_STATUS_UC|MCI_STATUS_EN| +			  MCI_STATUS_MISCV|MCI_STATUS_ADDRV|MCI_STATUS_S| +			  MCI_STATUS_AR|MCACOD_INSTR)) +		return; + +	m->mcgstatus |= MCG_STATUS_EIPV; +	m->ip = regs->ip; +	m->cs = regs->cs; +} +  /* Add per CPU specific workarounds here */  static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)  { @@ -1515,6 +1549,9 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)  		 */  		if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0)  			mce_bootlog = 0; + +		if (c->x86 == 6 && c->x86_model == 45) +			quirk_no_way_out = quirk_sandybridge_ifu;  	}  	if (monarch_timeout < 0)  		monarch_timeout = 0; diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 29557aa06dd..915b876edd1 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -32,6 +32,8 @@  #include <asm/smp.h>  #include <asm/alternative.h>  #include <asm/timer.h> +#include <asm/desc.h> +#include <asm/ldt.h>  #include "perf_event.h" @@ -1738,6 +1740,29 @@ valid_user_frame(const void __user *fp, unsigned long size)  	return (__range_not_ok(fp, size, TASK_SIZE) == 0);  } +static unsigned long get_segment_base(unsigned int segment) +{ +	struct desc_struct *desc; +	int idx = segment >> 3; + +	if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) { +		if (idx > LDT_ENTRIES) +			return 0; + +		if (idx > current->active_mm->context.size) +			return 0; + +		desc = current->active_mm->context.ldt; +	} else { +		if (idx > GDT_ENTRIES) +			return 0; + +		desc = __this_cpu_ptr(&gdt_page.gdt[0]); +	} + +	return get_desc_base(desc + idx); +} +  #ifdef CONFIG_COMPAT  #include <asm/compat.h> @@ -1746,13 +1771,17 @@ static inline int  perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)  {  	/* 32-bit process in 64-bit kernel. */ +	unsigned long ss_base, cs_base;  	struct stack_frame_ia32 frame;  	const void __user *fp;  	if (!test_thread_flag(TIF_IA32))  		return 0; -	fp = compat_ptr(regs->bp); +	cs_base = get_segment_base(regs->cs); +	ss_base = get_segment_base(regs->ss); + +	fp = compat_ptr(ss_base + regs->bp);  	while (entry->nr < PERF_MAX_STACK_DEPTH) {  		unsigned long bytes;  		frame.next_frame     = 0; @@ -1765,8 +1794,8 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)  		if (!valid_user_frame(fp, sizeof(frame)))  			break; -		perf_callchain_store(entry, frame.return_address); -		fp = compat_ptr(frame.next_frame); +		perf_callchain_store(entry, cs_base + frame.return_address); +		fp = compat_ptr(ss_base + frame.next_frame);  	}  	return 1;  } @@ -1789,6 +1818,12 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)  		return;  	} +	/* +	 * We don't know what to do with VM86 stacks.. ignore them for now. +	 */ +	if (regs->flags & (X86_VM_MASK | PERF_EFLAGS_VM)) +		return; +  	fp = (void __user *)regs->bp;  	perf_callchain_store(entry, regs->ip); @@ -1816,16 +1851,50 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)  	}  } -unsigned long perf_instruction_pointer(struct pt_regs *regs) +/* + * Deal with code segment offsets for the various execution modes: + * + *   VM86 - the good olde 16 bit days, where the linear address is + *          20 bits and we use regs->ip + 0x10 * regs->cs. + * + *   IA32 - Where we need to look at GDT/LDT segment descriptor tables + *          to figure out what the 32bit base address is. + * + *    X32 - has TIF_X32 set, but is running in x86_64 + * + * X86_64 - CS,DS,SS,ES are all zero based. + */ +static unsigned long code_segment_base(struct pt_regs *regs)  { -	unsigned long ip; +	/* +	 * If we are in VM86 mode, add the segment offset to convert to a +	 * linear address. +	 */ +	if (regs->flags & X86_VM_MASK) +		return 0x10 * regs->cs; + +	/* +	 * For IA32 we look at the GDT/LDT segment base to convert the +	 * effective IP to a linear address. +	 */ +#ifdef CONFIG_X86_32 +	if (user_mode(regs) && regs->cs != __USER_CS) +		return get_segment_base(regs->cs); +#else +	if (test_thread_flag(TIF_IA32)) { +		if (user_mode(regs) && regs->cs != __USER32_CS) +			return get_segment_base(regs->cs); +	} +#endif +	return 0; +} +unsigned long perf_instruction_pointer(struct pt_regs *regs) +{  	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) -		ip = perf_guest_cbs->get_guest_ip(); -	else -		ip = instruction_pointer(regs); +		return perf_guest_cbs->get_guest_ip(); -	return ip; +	return regs->ip + code_segment_base(regs);  }  unsigned long perf_misc_flags(struct pt_regs *regs) @@ -1838,7 +1907,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs)  		else  			misc |= PERF_RECORD_MISC_GUEST_KERNEL;  	} else { -		if (!kernel_ip(regs->ip)) +		if (user_mode(regs))  			misc |= PERF_RECORD_MISC_USER;  		else  			misc |= PERF_RECORD_MISC_KERNEL; diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 821d53b696d..6605a81ba33 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -516,6 +516,26 @@ static inline bool kernel_ip(unsigned long ip)  #endif  } +/* + * Not all PMUs provide the right context information to place the reported IP + * into full context. Specifically segment registers are typically not + * supplied. + * + * Assuming the address is a linear address (it is for IBS), we fake the CS and + * vm86 mode using the known zero-based code segment and 'fix up' the registers + * to reflect this. + * + * Intel PEBS/LBR appear to typically provide the effective address, nothing + * much we can do about that but pray and treat it like a linear address. + */ +static inline void set_linear_ip(struct pt_regs *regs, unsigned long ip) +{ +	regs->cs = kernel_ip(ip) ? __KERNEL_CS : __USER_CS; +	if (regs->flags & X86_VM_MASK) +		regs->flags ^= (PERF_EFLAGS_VM | X86_VM_MASK); +	regs->ip = ip; +} +  #ifdef CONFIG_CPU_SUP_AMD  int amd_pmu_init(void); diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index da9bcdcd985..7bfb5bec863 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -13,6 +13,8 @@  #include <asm/apic.h> +#include "perf_event.h" +  static u32 ibs_caps;  #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD) @@ -536,7 +538,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)  	if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) {  		regs.flags &= ~PERF_EFLAGS_EXACT;  	} else { -		instruction_pointer_set(®s, ibs_data.regs[1]); +		set_linear_ip(®s, ibs_data.regs[1]);  		regs.flags |= PERF_EFLAGS_EXACT;  	} diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 382366977d4..7f2739e03e7 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -1522,8 +1522,16 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr)  	arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;  	arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask;  	arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask; +	/* +	 * If PMU counter has PEBS enabled it is not enough to disable counter +	 * on a guest entry since PEBS memory write can overshoot guest entry +	 * and corrupt guest memory. Disabling PEBS solves the problem. +	 */ +	arr[1].msr = MSR_IA32_PEBS_ENABLE; +	arr[1].host = cpuc->pebs_enabled; +	arr[1].guest = 0; -	*nr = 1; +	*nr = 2;  	return arr;  } diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 629ae0b7ad9..e38d97bf425 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -499,7 +499,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)  	 * We sampled a branch insn, rewind using the LBR stack  	 */  	if (ip == to) { -		regs->ip = from; +		set_linear_ip(regs, from);  		return 1;  	} @@ -529,7 +529,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)  	} while (to < ip);  	if (to == ip) { -		regs->ip = old_to; +		set_linear_ip(regs, old_to);  		return 1;  	} @@ -569,7 +569,8 @@ static void __intel_pmu_pebs_event(struct perf_event *event,  	 * A possible PERF_SAMPLE_REGS will have to transfer all regs.  	 */  	regs = *iregs; -	regs.ip = pebs->ip; +	regs.flags = pebs->flags; +	set_linear_ip(®s, pebs->ip);  	regs.bp = pebs->bp;  	regs.sp = pebs->sp; diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 7563fda9f03..0a5571080e7 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -796,7 +796,6 @@ static struct intel_uncore_type *nhm_msr_uncores[] = {  DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5");  DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7"); -DEFINE_UNCORE_FORMAT_ATTR(mm_cfg, mm_cfg, "config:63");  DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63");  DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63"); @@ -902,16 +901,21 @@ static struct attribute_group nhmex_uncore_cbox_format_group = {  	.attrs = nhmex_uncore_cbox_formats_attr,  }; +/* msr offset for each instance of cbox */ +static unsigned nhmex_cbox_msr_offsets[] = { +	0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0, +}; +  static struct intel_uncore_type nhmex_uncore_cbox = {  	.name			= "cbox",  	.num_counters		= 6, -	.num_boxes		= 8, +	.num_boxes		= 10,  	.perf_ctr_bits		= 48,  	.event_ctl		= NHMEX_C0_MSR_PMON_EV_SEL0,  	.perf_ctr		= NHMEX_C0_MSR_PMON_CTR0,  	.event_mask		= NHMEX_PMON_RAW_EVENT_MASK,  	.box_ctl		= NHMEX_C0_MSR_PMON_GLOBAL_CTL, -	.msr_offset		= NHMEX_C_MSR_OFFSET, +	.msr_offsets		= nhmex_cbox_msr_offsets,  	.pair_ctr_ctl		= 1,  	.ops			= &nhmex_uncore_ops,  	.format_group		= &nhmex_uncore_cbox_format_group @@ -1032,24 +1036,22 @@ static struct intel_uncore_type nhmex_uncore_bbox = {  static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)  { -	struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; -	struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; +	struct hw_perf_event *hwc = &event->hw; +	struct hw_perf_event_extra *reg1 = &hwc->extra_reg; +	struct hw_perf_event_extra *reg2 = &hwc->branch_reg; -	if (event->attr.config & NHMEX_S_PMON_MM_CFG_EN) { -		reg1->config = event->attr.config1; -		reg2->config = event->attr.config2; -	} else { -		reg1->config = ~0ULL; -		reg2->config = ~0ULL; -	} +	/* only TO_R_PROG_EV event uses the match/mask register */ +	if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) != +	    NHMEX_S_EVENT_TO_R_PROG_EV) +		return 0;  	if (box->pmu->pmu_idx == 0)  		reg1->reg = NHMEX_S0_MSR_MM_CFG;  	else  		reg1->reg = NHMEX_S1_MSR_MM_CFG; -  	reg1->idx = 0; - +	reg1->config = event->attr.config1; +	reg2->config = event->attr.config2;  	return 0;  } @@ -1059,8 +1061,8 @@ static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct per  	struct hw_perf_event_extra *reg1 = &hwc->extra_reg;  	struct hw_perf_event_extra *reg2 = &hwc->branch_reg; -	wrmsrl(reg1->reg, 0); -	if (reg1->config != ~0ULL || reg2->config != ~0ULL) { +	if (reg1->idx != EXTRA_REG_NONE) { +		wrmsrl(reg1->reg, 0);  		wrmsrl(reg1->reg + 1, reg1->config);  		wrmsrl(reg1->reg + 2, reg2->config);  		wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN); @@ -1074,7 +1076,6 @@ static struct attribute *nhmex_uncore_sbox_formats_attr[] = {  	&format_attr_edge.attr,  	&format_attr_inv.attr,  	&format_attr_thresh8.attr, -	&format_attr_mm_cfg.attr,  	&format_attr_match.attr,  	&format_attr_mask.attr,  	NULL, @@ -1142,6 +1143,9 @@ static struct extra_reg nhmex_uncore_mbox_extra_regs[] = {  	EVENT_EXTRA_END  }; +/* Nehalem-EX or Westmere-EX ? */ +bool uncore_nhmex; +  static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config)  {  	struct intel_uncore_extra_reg *er; @@ -1171,18 +1175,29 @@ static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64  		return false;  	/* mask of the shared fields */ -	mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; +	if (uncore_nhmex) +		mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK; +	else +		mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK;  	er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];  	raw_spin_lock_irqsave(&er->lock, flags);  	/* add mask of the non-shared field if it's in use */ -	if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) -		mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +	if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) { +		if (uncore_nhmex) +			mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +		else +			mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +	}  	if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) {  		atomic_add(1 << (idx * 8), &er->ref); -		mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | -			NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +		if (uncore_nhmex) +			mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK | +				NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +		else +			mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK | +				WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);  		er->config &= ~mask;  		er->config |= (config & mask);  		ret = true; @@ -1216,7 +1231,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)  	/* get the non-shared control bits and shift them */  	idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC; -	config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +	if (uncore_nhmex) +		config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx); +	else +		config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);  	if (new_idx > orig_idx) {  		idx = new_idx - orig_idx;  		config <<= 3 * idx; @@ -1226,6 +1244,10 @@ u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)  	}  	/* add the shared control bits back */ +	if (uncore_nhmex) +		config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config; +	else +		config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;  	config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;  	if (modify) {  		/* adjust the main event selector */ @@ -1264,7 +1286,8 @@ again:  	}  	/* for the match/mask registers */ -	if ((uncore_box_is_fake(box) || !reg2->alloc) && +	if (reg2->idx != EXTRA_REG_NONE && +	    (uncore_box_is_fake(box) || !reg2->alloc) &&  	    !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config))  		goto fail; @@ -1278,7 +1301,8 @@ again:  		if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8))  			nhmex_mbox_alter_er(event, idx[0], true);  		reg1->alloc |= alloc; -		reg2->alloc = 1; +		if (reg2->idx != EXTRA_REG_NONE) +			reg2->alloc = 1;  	}  	return NULL;  fail: @@ -1342,9 +1366,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event  	struct extra_reg *er;  	unsigned msr;  	int reg_idx = 0; - -	if (WARN_ON_ONCE(reg1->idx != -1)) -		return -EINVAL;  	/*  	 * The mbox events may require 2 extra MSRs at the most. But only  	 * the lower 32 bits in these MSRs are significant, so we can use @@ -1355,11 +1376,6 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event  			continue;  		if (event->attr.config1 & ~er->valid_mask)  			return -EINVAL; -		if (er->idx == __BITS_VALUE(reg1->idx, 0, 8) || -		    er->idx == __BITS_VALUE(reg1->idx, 1, 8)) -			continue; -		if (WARN_ON_ONCE(reg_idx >= 2)) -			return -EINVAL;  		msr = er->msr + type->msr_offset * box->pmu->pmu_idx;  		if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff)) @@ -1368,6 +1384,8 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event  		/* always use the 32~63 bits to pass the PLD config */  		if (er->idx == EXTRA_REG_NHMEX_M_PLD)  			reg_idx = 1; +		else if (WARN_ON_ONCE(reg_idx > 0)) +			return -EINVAL;  		reg1->idx &= ~(0xff << (reg_idx * 8));  		reg1->reg &= ~(0xffff << (reg_idx * 16)); @@ -1376,17 +1394,21 @@ static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event  		reg1->config = event->attr.config1;  		reg_idx++;  	} -	/* use config2 to pass the filter config */ -	reg2->idx = EXTRA_REG_NHMEX_M_FILTER; -	if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) -		reg2->config = event->attr.config2; -	else -		reg2->config = ~0ULL; -	if (box->pmu->pmu_idx == 0) -		reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; -	else -		reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; - +	/* +	 * The mbox only provides ability to perform address matching +	 * for the PLD events. +	 */ +	if (reg_idx == 2) { +		reg2->idx = EXTRA_REG_NHMEX_M_FILTER; +		if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN) +			reg2->config = event->attr.config2; +		else +			reg2->config = ~0ULL; +		if (box->pmu->pmu_idx == 0) +			reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG; +		else +			reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG; +	}  	return 0;  } @@ -1422,34 +1444,36 @@ static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct per  		wrmsrl(__BITS_VALUE(reg1->reg, 1, 16),  			nhmex_mbox_shared_reg_config(box, idx)); -	wrmsrl(reg2->reg, 0); -	if (reg2->config != ~0ULL) { -		wrmsrl(reg2->reg + 1, -			reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); -		wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & -			(reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); -		wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); +	if (reg2->idx != EXTRA_REG_NONE) { +		wrmsrl(reg2->reg, 0); +		if (reg2->config != ~0ULL) { +			wrmsrl(reg2->reg + 1, +				reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK); +			wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK & +				(reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT)); +			wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN); +		}  	}  	wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);  } -DEFINE_UNCORE_FORMAT_ATTR(count_mode,	count_mode,	"config:2-3"); -DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode,	"config:4-5"); -DEFINE_UNCORE_FORMAT_ATTR(wrap_mode,	wrap_mode,	"config:6"); -DEFINE_UNCORE_FORMAT_ATTR(flag_mode,	flag_mode,	"config:7"); -DEFINE_UNCORE_FORMAT_ATTR(inc_sel,	inc_sel,	"config:9-13"); -DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel,	set_flag_sel,	"config:19-21"); -DEFINE_UNCORE_FORMAT_ATTR(filter_cfg,	filter_cfg,	"config2:63"); -DEFINE_UNCORE_FORMAT_ATTR(filter_match,	filter_match,	"config2:0-33"); -DEFINE_UNCORE_FORMAT_ATTR(filter_mask,	filter_mask,	"config2:34-61"); -DEFINE_UNCORE_FORMAT_ATTR(dsp,		dsp,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(thr,		thr,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(fvc,		fvc,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(pgt,		pgt,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(map,		map,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(iss,		iss,		"config1:0-31"); -DEFINE_UNCORE_FORMAT_ATTR(pld,		pld,		"config1:32-63"); +DEFINE_UNCORE_FORMAT_ATTR(count_mode,		count_mode,	"config:2-3"); +DEFINE_UNCORE_FORMAT_ATTR(storage_mode,		storage_mode,	"config:4-5"); +DEFINE_UNCORE_FORMAT_ATTR(wrap_mode,		wrap_mode,	"config:6"); +DEFINE_UNCORE_FORMAT_ATTR(flag_mode,		flag_mode,	"config:7"); +DEFINE_UNCORE_FORMAT_ATTR(inc_sel,		inc_sel,	"config:9-13"); +DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel,		set_flag_sel,	"config:19-21"); +DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en,	filter_cfg_en,	"config2:63"); +DEFINE_UNCORE_FORMAT_ATTR(filter_match,		filter_match,	"config2:0-33"); +DEFINE_UNCORE_FORMAT_ATTR(filter_mask,		filter_mask,	"config2:34-61"); +DEFINE_UNCORE_FORMAT_ATTR(dsp,			dsp,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(thr,			thr,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(fvc,			fvc,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(pgt,			pgt,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(map,			map,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(iss,			iss,		"config1:0-31"); +DEFINE_UNCORE_FORMAT_ATTR(pld,			pld,		"config1:32-63");  static struct attribute *nhmex_uncore_mbox_formats_attr[] = {  	&format_attr_count_mode.attr, @@ -1458,7 +1482,7 @@ static struct attribute *nhmex_uncore_mbox_formats_attr[] = {  	&format_attr_flag_mode.attr,  	&format_attr_inc_sel.attr,  	&format_attr_set_flag_sel.attr, -	&format_attr_filter_cfg.attr, +	&format_attr_filter_cfg_en.attr,  	&format_attr_filter_match.attr,  	&format_attr_filter_mask.attr,  	&format_attr_dsp.attr, @@ -1482,6 +1506,12 @@ static struct uncore_event_desc nhmex_uncore_mbox_events[] = {  	{ /* end: all zeroes */ },  }; +static struct uncore_event_desc wsmex_uncore_mbox_events[] = { +	INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"), +	INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"), +	{ /* end: all zeroes */ }, +}; +  static struct intel_uncore_ops nhmex_uncore_mbox_ops = {  	NHMEX_UNCORE_OPS_COMMON_INIT(),  	.enable_event	= nhmex_mbox_msr_enable_event, @@ -1513,7 +1543,7 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)  	struct hw_perf_event_extra *reg1 = &hwc->extra_reg;  	int port; -	/* adjust the main event selector */ +	/* adjust the main event selector and extra register index */  	if (reg1->idx % 2) {  		reg1->idx--;  		hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT; @@ -1522,29 +1552,17 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)  		hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;  	} -	/* adjust address or config of extra register */ +	/* adjust extra register config */  	port = reg1->idx / 6 + box->pmu->pmu_idx * 4;  	switch (reg1->idx % 6) { -	case 0: -		reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); -		break; -	case 1: -		reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); -		break;  	case 2: -		/* the 8~15 bits to the 0~7 bits */ +		/* shift the 8~15 bits to the 0~7 bits */  		reg1->config >>= 8;  		break;  	case 3: -		/* the 0~7 bits to the 8~15 bits */ +		/* shift the 0~7 bits to the 8~15 bits */  		reg1->config <<= 8;  		break; -	case 4: -		reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); -		break; -	case 5: -		reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); -		break;  	};  } @@ -1671,7 +1689,7 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event  	struct hw_perf_event *hwc = &event->hw;  	struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;  	struct hw_perf_event_extra *reg2 = &event->hw.branch_reg; -	int port, idx; +	int idx;  	idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >>  		NHMEX_R_PMON_CTL_EV_SEL_SHIFT; @@ -1681,27 +1699,11 @@ static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event  	reg1->idx = idx;  	reg1->config = event->attr.config1; -	port = idx / 6 + box->pmu->pmu_idx * 4; -	idx %= 6; -	switch (idx) { -	case 0: -		reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG0(port); -		break; -	case 1: -		reg1->reg = NHMEX_R_MSR_PORTN_IPERF_CFG1(port); -		break; -	case 2: -	case 3: -		reg1->reg = NHMEX_R_MSR_PORTN_QLX_CFG(port); -		break; +	switch (idx % 6) {  	case 4:  	case 5: -		if (idx == 4) -			reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port); -		else -			reg1->reg = NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port); -		reg2->config = event->attr.config2;  		hwc->config |= event->attr.config & (~0ULL << 32); +		reg2->config = event->attr.config2;  		break;  	};  	return 0; @@ -1727,28 +1729,34 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per  	struct hw_perf_event *hwc = &event->hw;  	struct hw_perf_event_extra *reg1 = &hwc->extra_reg;  	struct hw_perf_event_extra *reg2 = &hwc->branch_reg; -	int idx, er_idx; +	int idx, port; -	idx = reg1->idx % 6; -	er_idx = idx; -	if (er_idx > 2) -		er_idx--; -	er_idx += (reg1->idx / 6) * 5; +	idx = reg1->idx; +	port = idx / 6 + box->pmu->pmu_idx * 4; -	switch (idx) { +	switch (idx % 6) {  	case 0: +		wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config); +		break;  	case 1: -		wrmsrl(reg1->reg, reg1->config); +		wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config);  		break;  	case 2:  	case 3: -		wrmsrl(reg1->reg, nhmex_rbox_shared_reg_config(box, er_idx)); +		wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port), +			nhmex_rbox_shared_reg_config(box, 2 + (idx / 6) * 5));  		break;  	case 4: +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port), +			hwc->config >> 32); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config); +		break;  	case 5: -		wrmsrl(reg1->reg, reg1->config); -		wrmsrl(reg1->reg + 1, hwc->config >> 32); -		wrmsrl(reg1->reg + 2, reg2->config); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port), +			hwc->config >> 32); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config); +		wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config);  		break;  	}; @@ -1756,8 +1764,8 @@ static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct per  		(hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK));  } -DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config:32-63"); -DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config1:0-63"); +DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63"); +DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63");  DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63");  DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15");  DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31"); @@ -2303,6 +2311,7 @@ int uncore_pmu_event_init(struct perf_event *event)  	event->hw.idx = -1;  	event->hw.last_tag = ~0ULL;  	event->hw.extra_reg.idx = EXTRA_REG_NONE; +	event->hw.branch_reg.idx = EXTRA_REG_NONE;  	if (event->attr.config == UNCORE_FIXED_EVENT) {  		/* no fixed counter */ @@ -2373,7 +2382,7 @@ static void __init uncore_type_exit(struct intel_uncore_type *type)  	type->attr_groups[1] = NULL;  } -static void uncore_types_exit(struct intel_uncore_type **types) +static void __init uncore_types_exit(struct intel_uncore_type **types)  {  	int i;  	for (i = 0; types[i]; i++) @@ -2814,7 +2823,13 @@ static int __init uncore_cpu_init(void)  			snbep_uncore_cbox.num_boxes = max_cores;  		msr_uncores = snbep_msr_uncores;  		break; -	case 46: +	case 46: /* Nehalem-EX */ +		uncore_nhmex = true; +	case 47: /* Westmere-EX aka. Xeon E7 */ +		if (!uncore_nhmex) +			nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events; +		if (nhmex_uncore_cbox.num_boxes > max_cores) +			nhmex_uncore_cbox.num_boxes = max_cores;  		msr_uncores = nhmex_msr_uncores;  		break;  	default: diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h index f3851892e07..5b81c1856aa 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h @@ -5,7 +5,7 @@  #include "perf_event.h"  #define UNCORE_PMU_NAME_LEN		32 -#define UNCORE_PMU_HRTIMER_INTERVAL	(60 * NSEC_PER_SEC) +#define UNCORE_PMU_HRTIMER_INTERVAL	(60LL * NSEC_PER_SEC)  #define UNCORE_FIXED_EVENT		0xff  #define UNCORE_PMC_IDX_MAX_GENERIC	8 @@ -230,6 +230,7 @@  #define NHMEX_S1_MSR_MASK			0xe5a  #define NHMEX_S_PMON_MM_CFG_EN			(0x1ULL << 63) +#define NHMEX_S_EVENT_TO_R_PROG_EV		0  /* NHM-EX Mbox */  #define NHMEX_M0_MSR_GLOBAL_CTL			0xca0 @@ -275,18 +276,12 @@  		 NHMEX_M_PMON_CTL_INC_SEL_MASK |	\  		 NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK) - -#define NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK	0x1f -#define NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK	(0x7 << 5) -#define NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK	(0x7 << 8) -#define NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR	(1 << 23) -#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK			\ -		(NHMEX_M_PMON_ZDP_CTL_FVC_FVID_MASK |	\ -		 NHMEX_M_PMON_ZDP_CTL_FVC_BCMD_MASK |	\ -		 NHMEX_M_PMON_ZDP_CTL_FVC_RSP_MASK  |	\ -		 NHMEX_M_PMON_ZDP_CTL_FVC_PBOX_INIT_ERR) +#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK		(((1 << 11) - 1) | (1 << 23))  #define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n)	(0x7 << (11 + 3 * (n))) +#define WSMEX_M_PMON_ZDP_CTL_FVC_MASK		(((1 << 12) - 1) | (1 << 24)) +#define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n)	(0x7 << (12 + 3 * (n))) +  /*   * use the 9~13 bits to select event If the 7th bit is not set,   * otherwise use the 19~21 bits to select event. @@ -368,6 +363,7 @@ struct intel_uncore_type {  	unsigned num_shared_regs:8;  	unsigned single_fixed:1;  	unsigned pair_ctr_ctl:1; +	unsigned *msr_offsets;  	struct event_constraint unconstrainted;  	struct event_constraint *constraints;  	struct intel_uncore_pmu *pmus; @@ -485,29 +481,31 @@ unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx)  	return idx * 8 + box->pmu->type->perf_ctr;  } -static inline -unsigned uncore_msr_box_ctl(struct intel_uncore_box *box) +static inline unsigned uncore_msr_box_offset(struct intel_uncore_box *box) +{ +	struct intel_uncore_pmu *pmu = box->pmu; +	return pmu->type->msr_offsets ? +		pmu->type->msr_offsets[pmu->pmu_idx] : +		pmu->type->msr_offset * pmu->pmu_idx; +} + +static inline unsigned uncore_msr_box_ctl(struct intel_uncore_box *box)  {  	if (!box->pmu->type->box_ctl)  		return 0; -	return box->pmu->type->box_ctl + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +	return box->pmu->type->box_ctl + uncore_msr_box_offset(box);  } -static inline -unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box) +static inline unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box)  {  	if (!box->pmu->type->fixed_ctl)  		return 0; -	return box->pmu->type->fixed_ctl + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +	return box->pmu->type->fixed_ctl + uncore_msr_box_offset(box);  } -static inline -unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box) +static inline unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box)  { -	return box->pmu->type->fixed_ctr + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +	return box->pmu->type->fixed_ctr + uncore_msr_box_offset(box);  }  static inline @@ -515,7 +513,7 @@ unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)  {  	return box->pmu->type->event_ctl +  		(box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +		uncore_msr_box_offset(box);  }  static inline @@ -523,7 +521,7 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)  {  	return box->pmu->type->perf_ctr +  		(box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) + -		box->pmu->type->msr_offset * box->pmu->pmu_idx; +		uncore_msr_box_offset(box);  }  static inline diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 1f5f1d5d2a0..7ad683d7864 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -328,6 +328,7 @@ void fixup_irqs(void)  				chip->irq_retrigger(data);  			raw_spin_unlock(&desc->lock);  		} +		__this_cpu_write(vector_irq[vector], -1);  	}  }  #endif diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c index 1d5d31ea686..dc1404bf8e4 100644 --- a/arch/x86/kernel/kdebugfs.c +++ b/arch/x86/kernel/kdebugfs.c @@ -107,7 +107,7 @@ static int __init create_setup_data_nodes(struct dentry *parent)  {  	struct setup_data_node *node;  	struct setup_data *data; -	int error = -ENOMEM; +	int error;  	struct dentry *d;  	struct page *pg;  	u64 pa_data; @@ -121,8 +121,10 @@ static int __init create_setup_data_nodes(struct dentry *parent)  	while (pa_data) {  		node = kmalloc(sizeof(*node), GFP_KERNEL); -		if (!node) +		if (!node) { +			error = -ENOMEM;  			goto err_dir; +		}  		pg = pfn_to_page((pa_data+sizeof(*data)-1) >> PAGE_SHIFT);  		if (PageHighMem(pg)) { diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c index 1df8fb9e1d5..e498b18f010 100644 --- a/arch/x86/kvm/i8259.c +++ b/arch/x86/kvm/i8259.c @@ -316,6 +316,11 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)  	addr &= 1;  	if (addr == 0) {  		if (val & 0x10) { +			u8 edge_irr = s->irr & ~s->elcr; +			int i; +			bool found; +			struct kvm_vcpu *vcpu; +  			s->init4 = val & 1;  			s->last_irr = 0;  			s->irr &= s->elcr; @@ -333,6 +338,18 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)  			if (val & 0x08)  				pr_pic_unimpl(  					"level sensitive irq not supported"); + +			kvm_for_each_vcpu(i, vcpu, s->pics_state->kvm) +				if (kvm_apic_accept_pic_intr(vcpu)) { +					found = true; +					break; +				} + + +			if (found) +				for (irq = 0; irq < PIC_NUM_PINS/2; irq++) +					if (edge_irr & (1 << irq)) +						pic_clear_isr(s, irq);  		} else if (val & 0x08) {  			if (val & 0x04)  				s->poll = 1; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c39b60707e0..c00f03de1b7 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1488,13 +1488,6 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx)  		loadsegment(ds, vmx->host_state.ds_sel);  		loadsegment(es, vmx->host_state.es_sel);  	} -#else -	/* -	 * The sysexit path does not restore ds/es, so we must set them to -	 * a reasonable value ourselves. -	 */ -	loadsegment(ds, __USER_DS); -	loadsegment(es, __USER_DS);  #endif  	reload_tss();  #ifdef CONFIG_X86_64 @@ -6370,6 +6363,19 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)  #endif  	      ); +#ifndef CONFIG_X86_64 +	/* +	 * The sysexit path does not restore ds/es, so we must set them to +	 * a reasonable value ourselves. +	 * +	 * We can't defer this to vmx_load_host_state() since that function +	 * may be executed in interrupt context, which saves and restore segments +	 * around it, nullifying its effect. +	 */ +	loadsegment(ds, __USER_DS); +	loadsegment(es, __USER_DS); +#endif +  	vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)  				  | (1 << VCPU_EXREG_RFLAGS)  				  | (1 << VCPU_EXREG_CPL) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 59b59508ff0..42bce48f692 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -925,6 +925,10 @@ static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock)  	 */  	getboottime(&boot); +	if (kvm->arch.kvmclock_offset) { +		struct timespec ts = ns_to_timespec(kvm->arch.kvmclock_offset); +		boot = timespec_sub(boot, ts); +	}  	wc.sec = boot.tv_sec;  	wc.nsec = boot.tv_nsec;  	wc.version = version; diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index f6679a7fb8c..b91e4851242 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -56,9 +56,16 @@ static int vma_shareable(struct vm_area_struct *vma, unsigned long addr)  }  /* - * search for a shareable pmd page for hugetlb. + * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc() + * and returns the corresponding pte. While this is not necessary for the + * !shared pmd case because we can allocate the pmd later as well, it makes the + * code much cleaner. pmd allocation is essential for the shared case because + * pud has to be populated inside the same i_mmap_mutex section - otherwise + * racing tasks could either miss the sharing (see huge_pte_offset) or select a + * bad pmd for sharing.   */ -static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) +static pte_t * +huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)  {  	struct vm_area_struct *vma = find_vma(mm, addr);  	struct address_space *mapping = vma->vm_file->f_mapping; @@ -68,9 +75,10 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)  	struct vm_area_struct *svma;  	unsigned long saddr;  	pte_t *spte = NULL; +	pte_t *pte;  	if (!vma_shareable(vma, addr)) -		return; +		return (pte_t *)pmd_alloc(mm, pud, addr);  	mutex_lock(&mapping->i_mmap_mutex);  	vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) { @@ -97,7 +105,9 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)  		put_page(virt_to_page(spte));  	spin_unlock(&mm->page_table_lock);  out: +	pte = (pte_t *)pmd_alloc(mm, pud, addr);  	mutex_unlock(&mapping->i_mmap_mutex); +	return pte;  }  /* @@ -142,8 +152,9 @@ pte_t *huge_pte_alloc(struct mm_struct *mm,  		} else {  			BUG_ON(sz != PMD_SIZE);  			if (pud_none(*pud)) -				huge_pmd_share(mm, addr, pud); -			pte = (pte_t *) pmd_alloc(mm, pud, addr); +				pte = huge_pmd_share(mm, addr, pud); +			else +				pte = (pte_t *)pmd_alloc(mm, pud, addr);  		}  	}  	BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte)); diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 931930a9616..a718e0d2350 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -919,13 +919,11 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,  	/*  	 * On success we use clflush, when the CPU supports it to -	 * avoid the wbindv. If the CPU does not support it, in the -	 * error case, and during early boot (for EFI) we fall back -	 * to cpa_flush_all (which uses wbinvd): +	 * avoid the wbindv. If the CPU does not support it and in the +	 * error case we fall back to cpa_flush_all (which uses +	 * wbindv):  	 */ -	if (early_boot_irqs_disabled) -		__cpa_flush_all((void *)(long)cache); -	else if (!ret && cpu_has_clflush) { +	if (!ret && cpu_has_clflush) {  		if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {  			cpa_flush_array(addr, numpages, cache,  					cpa.flags, pages); diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c index 4599c3e8bcb..4ddf497ca65 100644 --- a/arch/x86/mm/srat.c +++ b/arch/x86/mm/srat.c @@ -142,23 +142,23 @@ static inline int save_add_info(void) {return 0;}  #endif  /* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ -void __init +int __init  acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)  {  	u64 start, end;  	int node, pxm;  	if (srat_disabled()) -		return; +		return -1;  	if (ma->header.length != sizeof(struct acpi_srat_mem_affinity)) {  		bad_srat(); -		return; +		return -1;  	}  	if ((ma->flags & ACPI_SRAT_MEM_ENABLED) == 0) -		return; +		return -1;  	if ((ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && !save_add_info()) -		return; +		return -1;  	start = ma->base_address;  	end = start + ma->length;  	pxm = ma->proximity_domain; @@ -168,12 +168,12 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)  	if (node < 0) {  		printk(KERN_ERR "SRAT: Too many proximity domains.\n");  		bad_srat(); -		return; +		return -1;  	}  	if (numa_add_memblk(node, start, end) < 0) {  		bad_srat(); -		return; +		return -1;  	}  	node_set(node, numa_nodes_parsed); @@ -181,6 +181,7 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)  	printk(KERN_INFO "SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]\n",  	       node, pxm,  	       (unsigned long long) start, (unsigned long long) end - 1); +	return 0;  }  void __init acpi_numa_arch_fixup(void) {} diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 2dc29f51e75..92660edaa1e 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -234,7 +234,22 @@ static efi_status_t __init phys_efi_set_virtual_address_map(  	return status;  } -static int efi_set_rtc_mmss(unsigned long nowtime) +static efi_status_t __init phys_efi_get_time(efi_time_t *tm, +					     efi_time_cap_t *tc) +{ +	unsigned long flags; +	efi_status_t status; + +	spin_lock_irqsave(&rtc_lock, flags); +	efi_call_phys_prelog(); +	status = efi_call_phys2(efi_phys.get_time, virt_to_phys(tm), +				virt_to_phys(tc)); +	efi_call_phys_epilog(); +	spin_unlock_irqrestore(&rtc_lock, flags); +	return status; +} + +int efi_set_rtc_mmss(unsigned long nowtime)  {  	int real_seconds, real_minutes;  	efi_status_t 	status; @@ -263,7 +278,7 @@ static int efi_set_rtc_mmss(unsigned long nowtime)  	return 0;  } -static unsigned long efi_get_time(void) +unsigned long efi_get_time(void)  {  	efi_status_t status;  	efi_time_t eft; @@ -606,13 +621,18 @@ static int __init efi_runtime_init(void)  	}  	/*  	 * We will only need *early* access to the following -	 * EFI runtime service before set_virtual_address_map +	 * two EFI runtime services before set_virtual_address_map  	 * is invoked.  	 */ +	efi_phys.get_time = (efi_get_time_t *)runtime->get_time;  	efi_phys.set_virtual_address_map =  		(efi_set_virtual_address_map_t *)  		runtime->set_virtual_address_map; - +	/* +	 * Make efi_get_time can be called before entering +	 * virtual mode. +	 */ +	efi.get_time = phys_efi_get_time;  	early_iounmap(runtime, sizeof(efi_runtime_services_t));  	return 0; @@ -700,10 +720,12 @@ void __init efi_init(void)  		efi_enabled = 0;  		return;  	} +#ifdef CONFIG_X86_32  	if (efi_native) {  		x86_platform.get_wallclock = efi_get_time;  		x86_platform.set_wallclock = efi_set_rtc_mmss;  	} +#endif  #if EFI_DEBUG  	print_efi_memmap(); diff --git a/arch/x86/realmode/rm/Makefile b/arch/x86/realmode/rm/Makefile index b2d534cab25..88692871823 100644 --- a/arch/x86/realmode/rm/Makefile +++ b/arch/x86/realmode/rm/Makefile @@ -72,7 +72,7 @@ KBUILD_CFLAGS	:= $(LINUXINCLUDE) -m32 -g -Os -D_SETUP -D__KERNEL__ -D_WAKEUP \  		   -Wall -Wstrict-prototypes \  		   -march=i386 -mregparm=3 \  		   -include $(srctree)/$(src)/../../boot/code16gcc.h \ -		   -fno-strict-aliasing -fomit-frame-pointer \ +		   -fno-strict-aliasing -fomit-frame-pointer -fno-pic \  		   $(call cc-option, -ffreestanding) \  		   $(call cc-option, -fno-toplevel-reorder,\  			$(call cc-option, -fno-unit-at-a-time)) \ diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index 51171aeff0d..a582bfed95b 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl @@ -60,8 +60,8 @@  51	common	getsockname		sys_getsockname  52	common	getpeername		sys_getpeername  53	common	socketpair		sys_socketpair -54	common	setsockopt		sys_setsockopt -55	common	getsockopt		sys_getsockopt +54	64	setsockopt		sys_setsockopt +55	64	getsockopt		sys_getsockopt  56	common	clone			stub_clone  57	common	fork			stub_fork  58	common	vfork			stub_vfork @@ -318,7 +318,7 @@  309	common	getcpu			sys_getcpu  310	64	process_vm_readv	sys_process_vm_readv  311	64	process_vm_writev	sys_process_vm_writev -312	64	kcmp			sys_kcmp +312	common	kcmp			sys_kcmp  #  # x32-specific system call numbers start at 512 to avoid cache impact @@ -353,3 +353,5 @@  538	x32	sendmmsg		compat_sys_sendmmsg  539	x32	process_vm_readv	compat_sys_process_vm_readv  540	x32	process_vm_writev	compat_sys_process_vm_writev +541	x32	setsockopt		compat_sys_setsockopt +542	x32	getsockopt		compat_sys_getsockopt diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 64effdc6da9..b2e91d40a4c 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -194,6 +194,11 @@ RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID   * boundary violation will require three middle nodes. */  RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3); +/* When we populate back during bootup, the amount of pages can vary. The + * max we have is seen is 395979, but that does not mean it can't be more. + * But some machines can have 3GB I/O holes even. So lets reserve enough + * for 4GB of I/O and E820 holes. */ +RESERVE_BRK(p2m_populated, PMD_SIZE * 4);  static inline unsigned p2m_top_index(unsigned long pfn)  {  	BUG_ON(pfn >= MAX_P2M_PFN); diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index ac7034129f3..d5fdd36190c 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -69,7 +69,9 @@ static const struct acpi_device_id ac_device_ids[] = {  };  MODULE_DEVICE_TABLE(acpi, ac_device_ids); +#ifdef CONFIG_PM_SLEEP  static int acpi_ac_resume(struct device *dev); +#endif  static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);  static struct acpi_driver acpi_ac_driver = { @@ -313,6 +315,7 @@ static int acpi_ac_add(struct acpi_device *device)  	return result;  } +#ifdef CONFIG_PM_SLEEP  static int acpi_ac_resume(struct device *dev)  {  	struct acpi_ac *ac; @@ -332,6 +335,7 @@ static int acpi_ac_resume(struct device *dev)  		kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);  	return 0;  } +#endif  static int acpi_ac_remove(struct acpi_device *device, int type)  { diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 5ccb99ae3a6..5de4ec72766 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -83,22 +83,22 @@ acpi_status acpi_hw_clear_acpi_status(void);  /*   * hwsleep - sleep/wake support (Legacy sleep registers)   */ -acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags); +acpi_status acpi_hw_legacy_sleep(u8 sleep_state); -acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags); +acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state); -acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags); +acpi_status acpi_hw_legacy_wake(u8 sleep_state);  /*   * hwesleep - sleep/wake support (Extended FADT-V5 sleep registers)   */  void acpi_hw_execute_sleep_method(char *method_name, u32 integer_argument); -acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags); +acpi_status acpi_hw_extended_sleep(u8 sleep_state); -acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags); +acpi_status acpi_hw_extended_wake_prep(u8 sleep_state); -acpi_status acpi_hw_extended_wake(u8 sleep_state, u8 flags); +acpi_status acpi_hw_extended_wake(u8 sleep_state);  /*   * hwvalid - Port I/O with validation diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 48518dac534..94996f9ae3a 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -90,7 +90,6 @@ void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument)   * FUNCTION:    acpi_hw_extended_sleep   *   * PARAMETERS:  sleep_state         - Which sleep state to enter - *              flags               - ACPI_EXECUTE_GTS to run optional method   *   * RETURN:      Status   * @@ -100,7 +99,7 @@ void acpi_hw_execute_sleep_method(char *method_pathname, u32 integer_argument)   *   ******************************************************************************/ -acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags) +acpi_status acpi_hw_extended_sleep(u8 sleep_state)  {  	acpi_status status;  	u8 sleep_type_value; @@ -125,12 +124,6 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags)  	acpi_gbl_system_awake_and_running = FALSE; -	/* Optionally execute _GTS (Going To Sleep) */ - -	if (flags & ACPI_EXECUTE_GTS) { -		acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state); -	} -  	/* Flush caches, as per ACPI specification */  	ACPI_FLUSH_CPU_CACHE(); @@ -172,7 +165,6 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags)   * FUNCTION:    acpi_hw_extended_wake_prep   *   * PARAMETERS:  sleep_state         - Which sleep state we just exited - *              flags               - ACPI_EXECUTE_BFS to run optional method   *   * RETURN:      Status   * @@ -181,7 +173,7 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state, u8 flags)   *   ******************************************************************************/ -acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags) +acpi_status acpi_hw_extended_wake_prep(u8 sleep_state)  {  	acpi_status status;  	u8 sleep_type_value; @@ -200,11 +192,6 @@ acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags)  				 &acpi_gbl_FADT.sleep_control);  	} -	/* Optionally execute _BFS (Back From Sleep) */ - -	if (flags & ACPI_EXECUTE_BFS) { -		acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state); -	}  	return_ACPI_STATUS(AE_OK);  } @@ -222,7 +209,7 @@ acpi_status acpi_hw_extended_wake_prep(u8 sleep_state, u8 flags)   *   ******************************************************************************/ -acpi_status acpi_hw_extended_wake(u8 sleep_state, u8 flags) +acpi_status acpi_hw_extended_wake(u8 sleep_state)  {  	ACPI_FUNCTION_TRACE(hw_extended_wake); diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 9960fe9ef53..3fddde056a5 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -56,7 +56,6 @@ ACPI_MODULE_NAME("hwsleep")   * FUNCTION:    acpi_hw_legacy_sleep   *   * PARAMETERS:  sleep_state         - Which sleep state to enter - *              flags               - ACPI_EXECUTE_GTS to run optional method   *   * RETURN:      Status   * @@ -64,7 +63,7 @@ ACPI_MODULE_NAME("hwsleep")   *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED   *   ******************************************************************************/ -acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags) +acpi_status acpi_hw_legacy_sleep(u8 sleep_state)  {  	struct acpi_bit_register_info *sleep_type_reg_info;  	struct acpi_bit_register_info *sleep_enable_reg_info; @@ -110,12 +109,6 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags)  		return_ACPI_STATUS(status);  	} -	/* Optionally execute _GTS (Going To Sleep) */ - -	if (flags & ACPI_EXECUTE_GTS) { -		acpi_hw_execute_sleep_method(METHOD_PATHNAME__GTS, sleep_state); -	} -  	/* Get current value of PM1A control */  	status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, @@ -214,7 +207,6 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags)   * FUNCTION:    acpi_hw_legacy_wake_prep   *   * PARAMETERS:  sleep_state         - Which sleep state we just exited - *              flags               - ACPI_EXECUTE_BFS to run optional method   *   * RETURN:      Status   * @@ -224,7 +216,7 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags)   *   ******************************************************************************/ -acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags) +acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state)  {  	acpi_status status;  	struct acpi_bit_register_info *sleep_type_reg_info; @@ -275,11 +267,6 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags)  		}  	} -	/* Optionally execute _BFS (Back From Sleep) */ - -	if (flags & ACPI_EXECUTE_BFS) { -		acpi_hw_execute_sleep_method(METHOD_PATHNAME__BFS, sleep_state); -	}  	return_ACPI_STATUS(status);  } @@ -288,7 +275,6 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags)   * FUNCTION:    acpi_hw_legacy_wake   *   * PARAMETERS:  sleep_state         - Which sleep state we just exited - *              flags               - Reserved, set to zero   *   * RETURN:      Status   * @@ -297,7 +283,7 @@ acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state, u8 flags)   *   ******************************************************************************/ -acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags) +acpi_status acpi_hw_legacy_wake(u8 sleep_state)  {  	acpi_status status; diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index f8684bfe790..1f165a750ae 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -50,7 +50,7 @@ ACPI_MODULE_NAME("hwxfsleep")  /* Local prototypes */  static acpi_status -acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id); +acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);  /*   * Dispatch table used to efficiently branch to the various sleep @@ -235,7 +235,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)   *   ******************************************************************************/  static acpi_status -acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id) +acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)  {  	acpi_status status;  	struct acpi_sleep_functions *sleep_functions = @@ -248,11 +248,11 @@ acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id)  	 * use the extended sleep registers  	 */  	if (acpi_gbl_reduced_hardware || acpi_gbl_FADT.sleep_control.address) { -		status = sleep_functions->extended_function(sleep_state, flags); +		status = sleep_functions->extended_function(sleep_state);  	} else {  		/* Legacy sleep */ -		status = sleep_functions->legacy_function(sleep_state, flags); +		status = sleep_functions->legacy_function(sleep_state);  	}  	return (status); @@ -262,7 +262,7 @@ acpi_hw_sleep_dispatch(u8 sleep_state, u8 flags, u32 function_id)  	 * For the case where reduced-hardware-only code is being generated,  	 * we know that only the extended sleep registers are available  	 */ -	status = sleep_functions->extended_function(sleep_state, flags); +	status = sleep_functions->extended_function(sleep_state);  	return (status);  #endif				/* !ACPI_REDUCED_HARDWARE */ @@ -349,7 +349,6 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)   * FUNCTION:    acpi_enter_sleep_state   *   * PARAMETERS:  sleep_state         - Which sleep state to enter - *              flags               - ACPI_EXECUTE_GTS to run optional method   *   * RETURN:      Status   * @@ -357,7 +356,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)   *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED   *   ******************************************************************************/ -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state, u8 flags) +acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)  {  	acpi_status status; @@ -371,7 +370,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state, u8 flags)  	}  	status = -	    acpi_hw_sleep_dispatch(sleep_state, flags, ACPI_SLEEP_FUNCTION_ID); +	    acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);  	return_ACPI_STATUS(status);  } @@ -391,14 +390,14 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)   *              Called with interrupts DISABLED.   *   ******************************************************************************/ -acpi_status acpi_leave_sleep_state_prep(u8 sleep_state, u8 flags) +acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)  {  	acpi_status status;  	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);  	status = -	    acpi_hw_sleep_dispatch(sleep_state, flags, +	    acpi_hw_sleep_dispatch(sleep_state,  				   ACPI_WAKE_PREP_FUNCTION_ID);  	return_ACPI_STATUS(status);  } @@ -423,8 +422,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)  	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state); - -	status = acpi_hw_sleep_dispatch(sleep_state, 0, ACPI_WAKE_FUNCTION_ID); +	status = acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_FUNCTION_ID);  	return_ACPI_STATUS(status);  } diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index ea4c6d52605..29e51bc0138 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -387,6 +387,7 @@ acpi_get_table_with_size(char *signature,  	return (AE_NOT_FOUND);  } +ACPI_EXPORT_SYMBOL(acpi_get_table_with_size)  acpi_status  acpi_get_table(char *signature, diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index ff2c876ec41..45e3e1759fb 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1052,6 +1052,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)  	return 0;  } +#ifdef CONFIG_PM_SLEEP  /* this is needed to learn about changes made in suspended state */  static int acpi_battery_resume(struct device *dev)  { @@ -1068,6 +1069,7 @@ static int acpi_battery_resume(struct device *dev)  	acpi_battery_update(battery);  	return 0;  } +#endif  static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume); diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 79d4c22f7a6..314a3b84bbc 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -78,7 +78,9 @@ static int acpi_button_add(struct acpi_device *device);  static int acpi_button_remove(struct acpi_device *device, int type);  static void acpi_button_notify(struct acpi_device *device, u32 event); +#ifdef CONFIG_PM_SLEEP  static int acpi_button_resume(struct device *dev); +#endif  static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);  static struct acpi_driver acpi_button_driver = { @@ -310,6 +312,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)  	}  } +#ifdef CONFIG_PM_SLEEP  static int acpi_button_resume(struct device *dev)  {  	struct acpi_device *device = to_acpi_device(dev); @@ -319,6 +322,7 @@ static int acpi_button_resume(struct device *dev)  		return acpi_lid_send_state(device);  	return 0;  } +#endif  static int acpi_button_add(struct acpi_device *device)  { diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 669d9ee80d1..bc36a476f1a 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -53,8 +53,10 @@ static const struct acpi_device_id fan_device_ids[] = {  };  MODULE_DEVICE_TABLE(acpi, fan_device_ids); +#ifdef CONFIG_PM_SLEEP  static int acpi_fan_suspend(struct device *dev);  static int acpi_fan_resume(struct device *dev); +#endif  static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume);  static struct acpi_driver acpi_fan_driver = { @@ -184,6 +186,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type)  	return 0;  } +#ifdef CONFIG_PM_SLEEP  static int acpi_fan_suspend(struct device *dev)  {  	if (!dev) @@ -207,6 +210,7 @@ static int acpi_fan_resume(struct device *dev)  	return result;  } +#endif  static int __init acpi_fan_init(void)  { diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index e56f3be7b07..cb31298ca68 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -237,6 +237,8 @@ acpi_parse_processor_affinity(struct acpi_subtable_header *header,  	return 0;  } +static int __initdata parsed_numa_memblks; +  static int __init  acpi_parse_memory_affinity(struct acpi_subtable_header * header,  			   const unsigned long end) @@ -250,8 +252,8 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header,  	acpi_table_print_srat_entry(header);  	/* let architecture-dependent part to do it */ -	acpi_numa_memory_affinity_init(memory_affinity); - +	if (!acpi_numa_memory_affinity_init(memory_affinity)) +		parsed_numa_memblks++;  	return 0;  } @@ -304,8 +306,10 @@ int __init acpi_numa_init(void)  	acpi_numa_arch_fixup(); -	if (cnt <= 0) -		return cnt ?: -ENOENT; +	if (cnt < 0) +		return cnt; +	else if (!parsed_numa_memblks) +		return -ENOENT;  	return 0;  } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index ec54014c321..72a2c98bc42 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -573,8 +573,15 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)  			OSC_CLOCK_PWR_CAPABILITY_SUPPORT;  	if (pci_msi_enabled())  		flags |= OSC_MSI_SUPPORT; -	if (flags != base_flags) -		acpi_pci_osc_support(root, flags); +	if (flags != base_flags) { +		status = acpi_pci_osc_support(root, flags); +		if (ACPI_FAILURE(status)) { +			dev_info(root->bus->bridge, "ACPI _OSC support " +				"notification failed, disabling PCIe ASPM\n"); +			pcie_no_aspm(); +			flags = base_flags; +		} +	}  	if (!pcie_ports_disabled  	    && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 215ecd09740..fc180341462 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -67,7 +67,9 @@ static const struct acpi_device_id power_device_ids[] = {  };  MODULE_DEVICE_TABLE(acpi, power_device_ids); +#ifdef CONFIG_PM_SLEEP  static int acpi_power_resume(struct device *dev); +#endif  static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume);  static struct acpi_driver acpi_power_driver = { @@ -775,6 +777,7 @@ static int acpi_power_remove(struct acpi_device *device, int type)  	return 0;  } +#ifdef CONFIG_PM_SLEEP  static int acpi_power_resume(struct device *dev)  {  	int result = 0, state; @@ -803,6 +806,7 @@ static int acpi_power_resume(struct device *dev)  	return result;  } +#endif  int __init acpi_power_init(void)  { diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index ff8e04f2fab..bfc31cb0dd3 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -437,7 +437,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,  		/* Normal CPU soft online event */  		} else {  			acpi_processor_ppc_has_changed(pr, 0); -			acpi_processor_cst_has_changed(pr); +			acpi_processor_hotplug(pr);  			acpi_processor_reevaluate_tstate(pr, action);  			acpi_processor_tstate_has_changed(pr);  		} diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index c0b9aa5faf4..ff0740e0a9c 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -988,6 +988,7 @@ static void acpi_sbs_rmdirs(void)  #endif  } +#ifdef CONFIG_PM_SLEEP  static int acpi_sbs_resume(struct device *dev)  {  	struct acpi_sbs *sbs; @@ -997,6 +998,7 @@ static int acpi_sbs_resume(struct device *dev)  	acpi_sbs_callback(sbs);  	return 0;  } +#endif  static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 7a7a9c92924..fdcdbb65291 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -28,36 +28,7 @@  #include "internal.h"  #include "sleep.h" -u8 wake_sleep_flags = ACPI_NO_OPTIONAL_METHODS; -static unsigned int gts, bfs; -static int set_param_wake_flag(const char *val, struct kernel_param *kp) -{ -	int ret = param_set_int(val, kp); - -	if (ret) -		return ret; - -	if (kp->arg == (const char *)>s) { -		if (gts) -			wake_sleep_flags |= ACPI_EXECUTE_GTS; -		else -			wake_sleep_flags &= ~ACPI_EXECUTE_GTS; -	} -	if (kp->arg == (const char *)&bfs) { -		if (bfs) -			wake_sleep_flags |= ACPI_EXECUTE_BFS; -		else -			wake_sleep_flags &= ~ACPI_EXECUTE_BFS; -	} -	return ret; -} -module_param_call(gts, set_param_wake_flag, param_get_int, >s, 0644); -module_param_call(bfs, set_param_wake_flag, param_get_int, &bfs, 0644); -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)  { @@ -110,6 +81,7 @@ static int acpi_sleep_prepare(u32 acpi_state)  #ifdef CONFIG_ACPI_SLEEP  static u32 acpi_target_sleep_state = ACPI_STATE_S0; +static bool pwr_btn_event_pending;  /*   * The ACPI specification wants us to save NVS memory regions during hibernation @@ -305,7 +277,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state)  	switch (acpi_state) {  	case ACPI_STATE_S1:  		barrier(); -		status = acpi_enter_sleep_state(acpi_state, wake_sleep_flags); +		status = acpi_enter_sleep_state(acpi_state);  		break;  	case ACPI_STATE_S3: @@ -319,8 +291,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state)  	/* This violates the spec but is required for bug compatibility. */  	acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); -	/* Reprogram control registers and execute _BFS */ -	acpi_leave_sleep_state_prep(acpi_state, wake_sleep_flags); +	/* Reprogram control registers */ +	acpi_leave_sleep_state_prep(acpi_state);  	/* ACPI 3.0 specs (P62) says that it's the responsibility  	 * of the OSPM to clear the status bit [ implying that the @@ -603,9 +575,9 @@ static int acpi_hibernation_enter(void)  	ACPI_FLUSH_CPU_CACHE();  	/* This shouldn't return.  If it returns, we have a problem */ -	status = acpi_enter_sleep_state(ACPI_STATE_S4, wake_sleep_flags); -	/* Reprogram control registers and execute _BFS */ -	acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); +	status = acpi_enter_sleep_state(ACPI_STATE_S4); +	/* Reprogram control registers */ +	acpi_leave_sleep_state_prep(ACPI_STATE_S4);  	return ACPI_SUCCESS(status) ? 0 : -EFAULT;  } @@ -617,8 +589,8 @@ static void acpi_hibernation_leave(void)  	 * enable it here.  	 */  	acpi_enable(); -	/* Reprogram control registers and execute _BFS */ -	acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); +	/* Reprogram control registers */ +	acpi_leave_sleep_state_prep(ACPI_STATE_S4);  	/* Check the hardware signature */  	if (facs && s4_hardware_signature != facs->hardware_signature) {  		printk(KERN_EMERG "ACPI: Hardware changed while hibernated, " @@ -892,33 +864,7 @@ static void acpi_power_off(void)  	/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */  	printk(KERN_DEBUG "%s called\n", __func__);  	local_irq_disable(); -	acpi_enter_sleep_state(ACPI_STATE_S5, wake_sleep_flags); -} - -/* - * ACPI 2.0 created the optional _GTS and _BFS, - * but industry adoption has been neither rapid nor broad. - * - * Linux gets into trouble when it executes poorly validated - * paths through the BIOS, so disable _GTS and _BFS by default, - * but do speak up and offer the option to enable them. - */ -static void __init acpi_gts_bfs_check(void) -{ -	acpi_handle dummy; - -	if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__GTS, &dummy))) -	{ -		printk(KERN_NOTICE PREFIX "BIOS offers _GTS\n"); -		printk(KERN_NOTICE PREFIX "If \"acpi.gts=1\" improves suspend, " -			"please notify linux-acpi@vger.kernel.org\n"); -	} -	if (ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, METHOD_PATHNAME__BFS, &dummy))) -	{ -		printk(KERN_NOTICE PREFIX "BIOS offers _BFS\n"); -		printk(KERN_NOTICE PREFIX "If \"acpi.bfs=1\" improves resume, " -			"please notify linux-acpi@vger.kernel.org\n"); -	} +	acpi_enter_sleep_state(ACPI_STATE_S5);  }  int __init acpi_sleep_init(void) @@ -979,6 +925,5 @@ int __init acpi_sleep_init(void)  	 * object can also be evaluated when the system enters S5.  	 */  	register_reboot_notifier(&tts_notifier); -	acpi_gts_bfs_check();  	return 0;  } diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 240a2440097..7c3f98ba4af 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -173,7 +173,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp)  {  	int result = 0; -	if (!strncmp(val, "enable", strlen("enable"))) { +	if (!strncmp(val, "enable", sizeof("enable") - 1)) {  		result = acpi_debug_trace(trace_method_name, trace_debug_level,  					  trace_debug_layer, 0);  		if (result) @@ -181,7 +181,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp)  		goto exit;  	} -	if (!strncmp(val, "disable", strlen("disable"))) { +	if (!strncmp(val, "disable", sizeof("disable") - 1)) {  		int name = 0;  		result = acpi_debug_trace((char *)&name, trace_debug_level,  					  trace_debug_layer, 0); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 9fe90e9fecb..edda74a4340 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -106,7 +106,9 @@ static const struct acpi_device_id  thermal_device_ids[] = {  };  MODULE_DEVICE_TABLE(acpi, thermal_device_ids); +#ifdef CONFIG_PM_SLEEP  static int acpi_thermal_resume(struct device *dev); +#endif  static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);  static struct acpi_driver acpi_thermal_driver = { @@ -1041,6 +1043,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)  	return 0;  } +#ifdef CONFIG_PM_SLEEP  static int acpi_thermal_resume(struct device *dev)  {  	struct acpi_thermal *tz; @@ -1075,6 +1078,7 @@ static int acpi_thermal_resume(struct device *dev)  	return AE_OK;  } +#endif  static int thermal_act(const struct dmi_system_id *d) { diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index d4386019af5..96cce6d5319 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -2362,7 +2362,7 @@ static int __devinit ia_init(struct atm_dev *dev)  	{    		printk(DEV_LABEL " (itf %d): can't set up page mapping\n",    			    dev->number);   -		return error;   +		return -ENOMEM;  	}    	IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n",    			dev->number, iadev->pci->revision, base, iadev->irq);) diff --git a/drivers/base/core.c b/drivers/base/core.c index c8fe4a56386..91478bd3541 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1869,6 +1869,7 @@ int __dev_printk(const char *level, const struct device *dev,  		 struct va_format *vaf)  {  	char dict[128]; +	const char *level_extra = "";  	size_t dictlen = 0;  	const char *subsys; @@ -1915,10 +1916,14 @@ int __dev_printk(const char *level, const struct device *dev,  				    "DEVICE=+%s:%s", subsys, dev_name(dev));  	}  skip: +	if (level[2]) +		level_extra = &level[2]; /* skip past KERN_SOH "L" */ +  	return printk_emit(0, level[1] - '0',  			   dictlen ? dict : NULL, dictlen, -			   "%s %s: %pV", -			   dev_driver_string(dev), dev_name(dev), vaf); +			   "%s %s: %s%pV", +			   dev_driver_string(dev), dev_name(dev), +			   level_extra, vaf);  }  EXPORT_SYMBOL(__dev_printk); diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 869d7ff2227..eb78e9640c4 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -169,8 +169,7 @@ void pm_clk_init(struct device *dev)   */  int pm_clk_create(struct device *dev)  { -	int ret = dev_pm_get_subsys_data(dev); -	return ret < 0 ? ret : 0; +	return dev_pm_get_subsys_data(dev);  }  /** diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index a14085cc613..39c32529b83 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -24,7 +24,6 @@  int dev_pm_get_subsys_data(struct device *dev)  {  	struct pm_subsys_data *psd; -	int ret = 0;  	psd = kzalloc(sizeof(*psd), GFP_KERNEL);  	if (!psd) @@ -40,7 +39,6 @@ int dev_pm_get_subsys_data(struct device *dev)  		dev->power.subsys_data = psd;  		pm_clk_init(dev);  		psd = NULL; -		ret = 1;  	}  	spin_unlock_irq(&dev->power.lock); @@ -48,7 +46,7 @@ int dev_pm_get_subsys_data(struct device *dev)  	/* kfree() verifies that its argument is nonzero. */  	kfree(psd); -	return ret; +	return 0;  }  EXPORT_SYMBOL_GPL(dev_pm_get_subsys_data); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 59894873a3b..7d9c1cb1c39 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -147,6 +147,8 @@ static int rpm_check_suspend_allowed(struct device *dev)  	    || (dev->power.request_pending  			&& dev->power.request == RPM_REQ_RESUME))  		retval = -EAGAIN; +	else if (__dev_pm_qos_read_value(dev) < 0) +		retval = -EPERM;  	else if (dev->power.runtime_status == RPM_SUSPENDED)  		retval = 1; @@ -388,7 +390,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)  		goto repeat;  	} -	dev->power.deferred_resume = false;  	if (dev->power.no_callbacks)  		goto no_callback;	/* Assume success. */ @@ -403,12 +404,6 @@ static int rpm_suspend(struct device *dev, int rpmflags)  		goto out;  	} -	if (__dev_pm_qos_read_value(dev) < 0) { -		/* Negative PM QoS constraint means "never suspend". */ -		retval = -EPERM; -		goto out; -	} -  	__update_runtime_status(dev, RPM_SUSPENDING);  	if (dev->pm_domain) @@ -440,6 +435,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)  	wake_up_all(&dev->power.wait_queue);  	if (dev->power.deferred_resume) { +		dev->power.deferred_resume = false;  		rpm_resume(dev, 0);  		retval = -EAGAIN;  		goto out; @@ -584,6 +580,7 @@ static int rpm_resume(struct device *dev, int rpmflags)  		    || dev->parent->power.runtime_status == RPM_ACTIVE) {  			atomic_inc(&dev->parent->power.child_count);  			spin_unlock(&dev->parent->power.lock); +			retval = 1;  			goto no_callback;	/* Assume success. */  		}  		spin_unlock(&dev->parent->power.lock); @@ -664,7 +661,7 @@ static int rpm_resume(struct device *dev, int rpmflags)  	}  	wake_up_all(&dev->power.wait_queue); -	if (!retval) +	if (retval >= 0)  		rpm_idle(dev, RPM_ASYNC);   out: diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 11b32d2642d..a6e5672c67e 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -272,6 +272,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },  	{ 0, },  }; diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 26823d97fd9..9ea4627dc0c 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -507,7 +507,9 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus)  		/* for these chips OTP is always available */  		present = true;  		break; - +	case BCMA_CHIP_ID_BCM43228: +		present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT; +		break;  	default:  		present = false;  		break; diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index acda773b372..38aa6dda6b8 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -763,16 +763,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout,  		{  			case CMD_TARGET_STATUS:  				/* Pass it up to the upper layers... */ -				if( ei->ScsiStatus) -                		{ -#if 0 -                    			printk(KERN_WARNING "cciss: cmd %p " -						"has SCSI Status = %x\n", -						c, ei->ScsiStatus); -#endif -					cmd->result |= (ei->ScsiStatus << 1); -                		} -				else {  /* scsi status is zero??? How??? */ +				if (!ei->ScsiStatus) {  	/* Ordinarily, this case should never happen, but there is a bug  	   in some released firmware revisions that allows it to happen diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 2e0e7fc1dbb..dbe6135a2ab 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3537,9 +3537,9 @@ static void drbd_cleanup(void)  }  /** - * drbd_congested() - Callback for pdflush + * drbd_congested() - Callback for the flusher thread   * @congested_data:	User data - * @bdi_bits:		Bits pdflush is currently interested in + * @bdi_bits:		Bits the BDI flusher thread is currently interested in   *   * Returns 1<<BDI_async_congested and/or 1<<BDI_sync_congested if we are congested.   */ diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 10308cd8a7e..11f36e50213 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -79,6 +79,7 @@ static struct usb_device_id ath3k_table[] = {  	{ USB_DEVICE(0x13d3, 0x3362) },  	{ USB_DEVICE(0x0CF3, 0xE004) },  	{ USB_DEVICE(0x0930, 0x0219) }, +	{ USB_DEVICE(0x0489, 0xe057) },  	/* Atheros AR5BBU12 with sflash firmware */  	{ USB_DEVICE(0x0489, 0xE02C) }, @@ -104,6 +105,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {  	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },  	/* Atheros AR5BBU22 with sflash firmware */  	{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e2722141103..cef3bac1a54 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -98,6 +98,7 @@ static struct usb_device_id btusb_table[] = {  	{ USB_DEVICE(0x0a5c, 0x21e6) },  	{ USB_DEVICE(0x0a5c, 0x21e8) },  	{ USB_DEVICE(0x0a5c, 0x21f3) }, +	{ USB_DEVICE(0x0a5c, 0x21f4) },  	{ USB_DEVICE(0x413c, 0x8197) },  	/* Foxconn - Hon Hai */ @@ -133,6 +134,7 @@ static struct usb_device_id blacklist_table[] = {  	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },  	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, +	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },  	/* Atheros AR5BBU12 with sflash firmware */  	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 57226424690..6ec0fff79bc 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -64,6 +64,7 @@  #define I830_PTE_SYSTEM_CACHED  0x00000006  /* GT PTE cache control fields */  #define GEN6_PTE_UNCACHED	0x00000002 +#define HSW_PTE_UNCACHED	0x00000000  #define GEN6_PTE_LLC		0x00000004  #define GEN6_PTE_LLC_MLC	0x00000006  #define GEN6_PTE_GFDT		0x00000008 @@ -239,16 +240,45 @@  #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG		0x016A  #define PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB		0x0F00 /* VLV1 */  #define PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG		0x0F30 -#define PCI_DEVICE_ID_INTEL_HASWELL_HB				0x0400 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_HASWELL_HB			0x0400 /* Desktop */  #define PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG		0x0402  #define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG		0x0412 -#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB			0x0404 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG	0x0422 +#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB		0x0404 /* Mobile */  #define PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG		0x0406  #define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG		0x0416 -#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB			0x0408 /* Server */ +#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG	0x0426 +#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB		0x0408 /* Server */  #define PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG		0x040a  #define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG		0x041a -#define PCI_DEVICE_ID_INTEL_HASWELL_SDV		0x0c16 /* SDV */ -#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB			0x0c04 +#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG	0x042a +#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB		0x0c04 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG	0x0C02 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG	0x0C12 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG	0x0C22 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG	0x0C06 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG	0x0C16 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG	0x0C26 +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG	0x0C0A +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG	0x0C1A +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG	0x0C2A +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG	0x0A02 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG	0x0A12 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG	0x0A22 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG	0x0A06 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG	0x0A16 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG	0x0A26 +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG	0x0A0A +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG	0x0A1A +#define PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG	0x0A2A +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG	0x0D12 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG	0x0D22 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG	0x0D32 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG	0x0D16 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG	0x0D26 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG	0x0D36 +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG	0x0D1A +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG	0x0D2A +#define PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG	0x0D3A  #endif diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 9ed92ef5829..58e32f7c322 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1156,6 +1156,30 @@ static bool gen6_check_flags(unsigned int flags)  	return true;  } +static void haswell_write_entry(dma_addr_t addr, unsigned int entry, +				unsigned int flags) +{ +	unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; +	unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; +	u32 pte_flags; + +	if (type_mask == AGP_USER_MEMORY) +		pte_flags = HSW_PTE_UNCACHED | I810_PTE_VALID; +	else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { +		pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; +		if (gfdt) +			pte_flags |= GEN6_PTE_GFDT; +	} else { /* set 'normal'/'cached' to LLC by default */ +		pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; +		if (gfdt) +			pte_flags |= GEN6_PTE_GFDT; +	} + +	/* gen6 has bit11-4 for physical addr bit39-32 */ +	addr |= (addr >> 28) & 0xff0; +	writel(addr | pte_flags, intel_private.gtt + entry); +} +  static void gen6_write_entry(dma_addr_t addr, unsigned int entry,  			     unsigned int flags)  { @@ -1382,6 +1406,15 @@ static const struct intel_gtt_driver sandybridge_gtt_driver = {  	.check_flags = gen6_check_flags,  	.chipset_flush = i9xx_chipset_flush,  }; +static const struct intel_gtt_driver haswell_gtt_driver = { +	.gen = 6, +	.setup = i9xx_setup, +	.cleanup = gen6_cleanup, +	.write_entry = haswell_write_entry, +	.dma_mask_size = 40, +	.check_flags = gen6_check_flags, +	.chipset_flush = i9xx_chipset_flush, +};  static const struct intel_gtt_driver valleyview_gtt_driver = {  	.gen = 7,  	.setup = i9xx_setup, @@ -1499,19 +1532,77 @@ static const struct intel_gtt_driver_description {  	{ PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG,  	    "ValleyView", &valleyview_gtt_driver },  	{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG, -	    "Haswell", &sandybridge_gtt_driver }, +	    "Haswell", &haswell_gtt_driver },  	{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG, -	    "Haswell", &sandybridge_gtt_driver }, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver },  	{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG, -	    "Haswell", &sandybridge_gtt_driver }, +	    "Haswell", &haswell_gtt_driver },  	{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG, -	    "Haswell", &sandybridge_gtt_driver }, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver },  	{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG, -	    "Haswell", &sandybridge_gtt_driver }, +	    "Haswell", &haswell_gtt_driver },  	{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG, -	    "Haswell", &sandybridge_gtt_driver }, -	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV, -	    "Haswell", &sandybridge_gtt_driver }, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT1_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_D_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT1_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_M_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT1_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV_S_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT1_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_D_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT1_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_M_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT1_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_ULT_S_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT1_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_D_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT1_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_M_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT1_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_IG, +	    "Haswell", &haswell_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_CRW_S_GT2_PLUS_IG, +	    "Haswell", &haswell_gtt_driver },  	{ 0, NULL, NULL }  }; diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index d706bd0e9e8..4fbdceb6f77 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -160,7 +160,7 @@ static int __exit omap_rng_remove(struct platform_device *pdev)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int omap_rng_suspend(struct device *dev)  { diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 89682fa8801..c4be3519a58 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -807,6 +807,7 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,  MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");  #endif +#ifdef CONFIG_PM_SLEEP  static int tpm_tis_resume(struct device *dev)  {  	struct tpm_chip *chip = dev_get_drvdata(dev); @@ -816,6 +817,7 @@ static int tpm_tis_resume(struct device *dev)  	return tpm_pm_resume(dev);  } +#endif  static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index 540795cd076..d9279385304 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c @@ -53,7 +53,7 @@ static struct cs5535_mfgpt_timer *cs5535_event_clock;  #define MFGPT_PERIODIC (MFGPT_HZ / HZ)  /* - * The MFPGT timers on the CS5536 provide us with suitable timers to use + * The MFGPT timers on the CS5536 provide us with suitable timers to use   * as clock event sources - not as good as a HPET or APIC, but certainly   * better than the PIT.  This isn't a general purpose MFGPT driver, but   * a simplified one designed specifically to act as a clock event source. @@ -144,7 +144,7 @@ static int __init cs5535_mfgpt_init(void)  	timer = cs5535_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);  	if (!timer) { -		printk(KERN_ERR DRV_NAME ": Could not allocate MFPGT timer\n"); +		printk(KERN_ERR DRV_NAME ": Could not allocate MFGPT timer\n");  		return -ENODEV;  	}  	cs5535_event_clock = timer; diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index cdc02ac8f41..503996a94a6 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -454,6 +454,7 @@ static int __init pcc_cpufreq_probe(void)  					mem_resource->address_length);  	if (pcch_virt_addr == NULL) {  		pr_debug("probe: could not map shared mem region\n"); +		ret = -ENOMEM;  		goto out_free;  	}  	pcch_hdr = pcch_virt_addr; diff --git a/drivers/cpuidle/coupled.c b/drivers/cpuidle/coupled.c index 2c9bf269223..3265844839b 100644 --- a/drivers/cpuidle/coupled.c +++ b/drivers/cpuidle/coupled.c @@ -678,10 +678,22 @@ static int cpuidle_coupled_cpu_notify(struct notifier_block *nb,  	int cpu = (unsigned long)hcpu;  	struct cpuidle_device *dev; +	switch (action & ~CPU_TASKS_FROZEN) { +	case CPU_UP_PREPARE: +	case CPU_DOWN_PREPARE: +	case CPU_ONLINE: +	case CPU_DEAD: +	case CPU_UP_CANCELED: +	case CPU_DOWN_FAILED: +		break; +	default: +		return NOTIFY_OK; +	} +  	mutex_lock(&cpuidle_lock);  	dev = per_cpu(cpuidle_devices, cpu); -	if (!dev->coupled) +	if (!dev || !dev->coupled)  		goto out;  	switch (action & ~CPU_TASKS_FROZEN) { diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index fcfeb3cd8d3..5084975d793 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -172,7 +172,8 @@ struct imxdma_engine {  	struct device_dma_parameters	dma_parms;  	struct dma_device		dma_device;  	void __iomem			*base; -	struct clk			*dma_clk; +	struct clk			*dma_ahb; +	struct clk			*dma_ipg;  	spinlock_t			lock;  	struct imx_dma_2d_config	slots_2d[IMX_DMA_2D_SLOTS];  	struct imxdma_channel		channel[IMX_DMA_CHANNELS]; @@ -976,10 +977,20 @@ static int __init imxdma_probe(struct platform_device *pdev)  		return 0;  	} -	imxdma->dma_clk = clk_get(NULL, "dma"); -	if (IS_ERR(imxdma->dma_clk)) -		return PTR_ERR(imxdma->dma_clk); -	clk_enable(imxdma->dma_clk); +	imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg"); +	if (IS_ERR(imxdma->dma_ipg)) { +		ret = PTR_ERR(imxdma->dma_ipg); +		goto err_clk; +	} + +	imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb"); +	if (IS_ERR(imxdma->dma_ahb)) { +		ret = PTR_ERR(imxdma->dma_ahb); +		goto err_clk; +	} + +	clk_prepare_enable(imxdma->dma_ipg); +	clk_prepare_enable(imxdma->dma_ahb);  	/* reset DMA module */  	imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR); @@ -988,16 +999,14 @@ static int __init imxdma_probe(struct platform_device *pdev)  		ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma);  		if (ret) {  			dev_warn(imxdma->dev, "Can't register IRQ for DMA\n"); -			kfree(imxdma); -			return ret; +			goto err_enable;  		}  		ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma);  		if (ret) {  			dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n");  			free_irq(MX1_DMA_INT, NULL); -			kfree(imxdma); -			return ret; +			goto err_enable;  		}  	} @@ -1094,7 +1103,10 @@ err_init:  		free_irq(MX1_DMA_INT, NULL);  		free_irq(MX1_DMA_ERR, NULL);  	} - +err_enable: +	clk_disable_unprepare(imxdma->dma_ipg); +	clk_disable_unprepare(imxdma->dma_ahb); +err_clk:  	kfree(imxdma);  	return ret;  } @@ -1114,7 +1126,9 @@ static int __exit imxdma_remove(struct platform_device *pdev)  		free_irq(MX1_DMA_ERR, NULL);  	} -        kfree(imxdma); +	clk_disable_unprepare(imxdma->dma_ipg); +	clk_disable_unprepare(imxdma->dma_ahb); +	kfree(imxdma);          return 0;  } diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index d52dbc6c54a..24acd711e03 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -1119,15 +1119,21 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(  static int tegra_dma_alloc_chan_resources(struct dma_chan *dc)  {  	struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); +	struct tegra_dma *tdma = tdc->tdma; +	int ret;  	dma_cookie_init(&tdc->dma_chan);  	tdc->config_init = false; -	return 0; +	ret = clk_prepare_enable(tdma->dma_clk); +	if (ret < 0) +		dev_err(tdc2dev(tdc), "clk_prepare_enable failed: %d\n", ret); +	return ret;  }  static void tegra_dma_free_chan_resources(struct dma_chan *dc)  {  	struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); +	struct tegra_dma *tdma = tdc->tdma;  	struct tegra_dma_desc *dma_desc;  	struct tegra_dma_sg_req *sg_req; @@ -1163,6 +1169,7 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)  		list_del(&sg_req->node);  		kfree(sg_req);  	} +	clk_disable_unprepare(tdma->dma_clk);  }  /* Tegra20 specific DMA controller information */ @@ -1255,6 +1262,13 @@ static int __devinit tegra_dma_probe(struct platform_device *pdev)  		}  	} +	/* Enable clock before accessing registers */ +	ret = clk_prepare_enable(tdma->dma_clk); +	if (ret < 0) { +		dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); +		goto err_pm_disable; +	} +  	/* Reset DMA controller */  	tegra_periph_reset_assert(tdma->dma_clk);  	udelay(2); @@ -1265,6 +1279,8 @@ static int __devinit tegra_dma_probe(struct platform_device *pdev)  	tdma_write(tdma, TEGRA_APBDMA_CONTROL, 0);  	tdma_write(tdma, TEGRA_APBDMA_IRQ_MASK_SET, 0xFFFFFFFFul); +	clk_disable_unprepare(tdma->dma_clk); +  	INIT_LIST_HEAD(&tdma->dma_dev.channels);  	for (i = 0; i < cdata->nr_channels; i++) {  		struct tegra_dma_channel *tdc = &tdma->channels[i]; diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index fe3db45fa83..3cc152e690b 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -107,7 +107,8 @@ static int __devinit gpio_extcon_probe(struct platform_device *pdev)  	if (ret < 0)  		return ret; -	ret = gpio_request_one(extcon_data->gpio, GPIOF_DIR_IN, pdev->name); +	ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN, +				    pdev->name);  	if (ret < 0)  		goto err; diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c index 150d9768811..ae37181798b 100644 --- a/drivers/gpio/gpio-em.c +++ b/drivers/gpio/gpio-em.c @@ -266,7 +266,7 @@ static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p)  	return 0;  } -static void __devexit em_gio_irq_domain_cleanup(struct em_gio_priv *p) +static void em_gio_irq_domain_cleanup(struct em_gio_priv *p)  {  	struct gpio_em_config *pdata = p->pdev->dev.platform_data; diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c index a1c8754f52c..202a99207b7 100644 --- a/drivers/gpio/gpio-langwell.c +++ b/drivers/gpio/gpio-langwell.c @@ -339,7 +339,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,  	resource_size_t start, len;  	struct lnw_gpio *lnw;  	u32 gpio_base; -	int retval = 0; +	int retval;  	int ngpio = id->driver_data;  	retval = pci_enable_device(pdev); @@ -357,6 +357,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,  	base = ioremap_nocache(start, len);  	if (!base) {  		dev_err(&pdev->dev, "error mapping bar1\n"); +		retval = -EFAULT;  		goto err3;  	}  	gpio_base = *((u32 *)base + 1); @@ -381,8 +382,10 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,  	lnw->domain = irq_domain_add_linear(pdev->dev.of_node, ngpio,  					    &lnw_gpio_irq_ops, lnw); -	if (!lnw->domain) +	if (!lnw->domain) { +		retval = -ENOMEM;  		goto err3; +	}  	lnw->reg_base = base;  	lnw->chip.label = dev_name(&pdev->dev); diff --git a/drivers/gpio/gpio-msic.c b/drivers/gpio/gpio-msic.c index 71a838f4450..b3898628586 100644 --- a/drivers/gpio/gpio-msic.c +++ b/drivers/gpio/gpio-msic.c @@ -99,7 +99,7 @@ static int msic_gpio_to_oreg(unsigned offset)  	if (offset < 20)  		return INTEL_MSIC_GPIO0HV0CTLO - offset + 16; -	return INTEL_MSIC_GPIO1HV0CTLO + offset + 20; +	return INTEL_MSIC_GPIO1HV0CTLO - offset + 20;  }  static int msic_gpio_direction_input(struct gpio_chip *chip, unsigned offset) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 4db460b6ecf..80f44bb64a8 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -465,9 +465,8 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)  		goto out_iounmap;  	port->bgc.gc.to_irq = mxc_gpio_to_irq; -	port->bgc.gc.base = pdev->id * 32; -	port->bgc.dir = port->bgc.read_reg(port->bgc.reg_dir); -	port->bgc.data = port->bgc.read_reg(port->bgc.reg_set); +	port->bgc.gc.base = (pdev->id < 0) ? of_alias_get_id(np, "gpio") * 32 : +					     pdev->id * 32;  	err = gpiochip_add(&port->bgc.gc);  	if (err) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index 58a6a63a6ec..9cac88a65f7 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -62,6 +62,7 @@ int pxa_last_gpio;  #ifdef CONFIG_OF  static struct irq_domain *domain; +static struct device_node *pxa_gpio_of_node;  #endif  struct pxa_gpio_chip { @@ -277,6 +278,24 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)  				(value ? GPSR_OFFSET : GPCR_OFFSET));  } +#ifdef CONFIG_OF_GPIO +static int pxa_gpio_of_xlate(struct gpio_chip *gc, +			     const struct of_phandle_args *gpiospec, +			     u32 *flags) +{ +	if (gpiospec->args[0] > pxa_last_gpio) +		return -EINVAL; + +	if (gc != &pxa_gpio_chips[gpiospec->args[0] / 32].chip) +		return -EINVAL; + +	if (flags) +		*flags = gpiospec->args[1]; + +	return gpiospec->args[0] % 32; +} +#endif +  static int __devinit pxa_init_gpio_chip(int gpio_end,  					int (*set_wake)(unsigned int, unsigned int))  { @@ -304,6 +323,11 @@ static int __devinit pxa_init_gpio_chip(int gpio_end,  		c->get = pxa_gpio_get;  		c->set = pxa_gpio_set;  		c->to_irq = pxa_gpio_to_irq; +#ifdef CONFIG_OF_GPIO +		c->of_node = pxa_gpio_of_node; +		c->of_xlate = pxa_gpio_of_xlate; +		c->of_gpio_n_cells = 2; +#endif  		/* number of GPIOs on last bank may be less than 32 */  		c->ngpio = (gpio + 31 > gpio_end) ? (gpio_end - gpio + 1) : 32; @@ -488,6 +512,7 @@ static int pxa_gpio_nums(void)  	return count;  } +#ifdef CONFIG_OF  static struct of_device_id pxa_gpio_dt_ids[] = {  	{ .compatible = "mrvl,pxa-gpio" },  	{ .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO }, @@ -505,9 +530,9 @@ static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq,  const struct irq_domain_ops pxa_irq_domain_ops = {  	.map	= pxa_irq_domain_map, +	.xlate	= irq_domain_xlate_twocell,  }; -#ifdef CONFIG_OF  static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)  {  	int ret, nr_banks, nr_gpios, irq_base; @@ -545,6 +570,7 @@ static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)  	}  	domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0,  				       &pxa_irq_domain_ops, NULL); +	pxa_gpio_of_node = np;  	return 0;  err:  	iounmap(gpio_reg_base); @@ -653,7 +679,7 @@ static struct platform_driver pxa_gpio_driver = {  	.probe		= pxa_gpio_probe,  	.driver		= {  		.name	= "pxa-gpio", -		.of_match_table = pxa_gpio_dt_ids, +		.of_match_table = of_match_ptr(pxa_gpio_dt_ids),  	},  }; diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 92f7b2bb79d..ba126cc0407 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -2454,12 +2454,6 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = {  		},  	}, {  		.chip	= { -			.base	= EXYNOS5_GPC4(0), -			.ngpio	= EXYNOS5_GPIO_C4_NR, -			.label	= "GPC4", -		}, -	}, { -		.chip	= {  			.base	= EXYNOS5_GPD0(0),  			.ngpio	= EXYNOS5_GPIO_D0_NR,  			.label	= "GPD0", @@ -2513,6 +2507,12 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = {  			.label	= "GPY6",  		},  	}, { +		.chip	= { +			.base	= EXYNOS5_GPC4(0), +			.ngpio	= EXYNOS5_GPIO_C4_NR, +			.label	= "GPC4", +		}, +	}, {  		.config	= &samsung_gpio_cfgs[9],  		.irq_base = IRQ_EINT(0),  		.chip	= { @@ -2836,7 +2836,7 @@ static __init void exynos5_gpiolib_init(void)  	}  	/* need to set base address for gpc4 */ -	exynos5_gpios_1[11].base = gpio_base1 + 0x2E0; +	exynos5_gpios_1[20].base = gpio_base1 + 0x2E0;  	/* need to set base address for gpx */  	chip = &exynos5_gpios_1[21]; diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 424dce8e3f3..8707d4572a0 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -241,7 +241,8 @@ static int __devinit sch_gpio_probe(struct platform_device *pdev)  			break;  		default: -			return -ENODEV; +			err = -ENODEV; +			goto err_sch_gpio_core;  	}  	sch_gpio_core.dev = &pdev->dev; diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 23120c00a88..90e28081712 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -22,6 +22,7 @@ menuconfig DRM  config DRM_USB  	tristate  	depends on DRM +	depends on USB_ARCH_HAS_HCD  	select USB  config DRM_KMS_HELPER diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 66d4a28ad5a..0303935d10e 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -119,7 +119,7 @@ static int edid_load(struct drm_connector *connector, char *name,  {  	const struct firmware *fw;  	struct platform_device *pdev; -	u8 *fwdata = NULL, *edid; +	u8 *fwdata = NULL, *edid, *new_edid;  	int fwsize, expected;  	int builtin = 0, err = 0;  	int i, valid_extensions = 0; @@ -195,12 +195,14 @@ static int edid_load(struct drm_connector *connector, char *name,  		    "\"%s\" for connector \"%s\"\n", valid_extensions,  		    edid[0x7e], name, connector_name);  		edid[0x7e] = valid_extensions; -		edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, +		new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,  		    GFP_KERNEL); -		if (edid == NULL) { +		if (new_edid == NULL) {  			err = -ENOMEM; +			kfree(edid);  			goto relfw_out;  		} +		edid = new_edid;  	}  	connector->display_info.raw_edid = edid; diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index b7adb4a967f..28637c181b1 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -706,9 +706,6 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)  	p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);  	p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);  	p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal); - -	p->crtc_hadjusted = false; -	p->crtc_vadjusted = false;  }  EXPORT_SYMBOL(drm_mode_set_crtcinfo); diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index 371c695322d..da457b18eaa 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c @@ -89,7 +89,7 @@ static const struct file_operations drm_proc_fops = {   * Create a given set of proc files represented by an array of   * gdm_proc_lists in the given root directory.   */ -int drm_proc_create_files(struct drm_info_list *files, int count, +static int drm_proc_create_files(struct drm_info_list *files, int count,  			  struct proc_dir_entry *root, struct drm_minor *minor)  {  	struct drm_device *dev = minor->dev; @@ -172,7 +172,7 @@ int drm_proc_init(struct drm_minor *minor, int minor_id,  	return 0;  } -int drm_proc_remove_files(struct drm_info_list *files, int count, +static int drm_proc_remove_files(struct drm_info_list *files, int count,  			  struct drm_minor *minor)  {  	struct list_head *pos, *q; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ed22612bc84..a24ffbe97c0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -346,11 +346,40 @@ static const struct pci_device_id pciidlist[] = {		/* aka */  	INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */  	INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */  	INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */ +	INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT2 desktop */  	INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */  	INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */ +	INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT2 server */  	INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */  	INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ -	INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */ +	INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */ +	INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */ +	INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */ +	INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT2 desktop */ +	INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */ +	INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */ +	INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT2 server */ +	INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */ +	INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */ +	INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT2 mobile */ +	INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */ +	INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */ +	INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT2 desktop */ +	INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */ +	INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */ +	INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT2 server */ +	INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */ +	INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */ +	INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */ +	INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT1 desktop */ +	INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */ +	INTEL_VGA_DEVICE(0x0D32, &intel_haswell_d_info), /* CRW GT2 desktop */ +	INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT1 server */ +	INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */ +	INTEL_VGA_DEVICE(0x0D3A, &intel_haswell_d_info), /* CRW GT2 server */ +	INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT1 mobile */ +	INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */ +	INTEL_VGA_DEVICE(0x0D36, &intel_haswell_m_info), /* CRW GT2 mobile */  	INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),  	INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),  	INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5c4657a54f9..489e2b162b2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2365,6 +2365,10 @@ int i915_gpu_idle(struct drm_device *dev)  	/* Flush everything onto the inactive list. */  	for_each_ring(ring, dev_priv, i) { +		ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); +		if (ret) +			return ret; +  		ret = i915_ring_idle(ring);  		if (ret)  			return ret; @@ -2372,10 +2376,6 @@ int i915_gpu_idle(struct drm_device *dev)  		/* Is the device fubar? */  		if (WARN_ON(!list_empty(&ring->gpu_write_list)))  			return -EBUSY; - -		ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); -		if (ret) -			return ret;  	}  	return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index da8b01fb1bf..a9d58d72bb4 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -451,7 +451,6 @@ int i915_switch_context(struct intel_ring_buffer *ring,  	struct drm_i915_file_private *file_priv = NULL;  	struct i915_hw_context *to;  	struct drm_i915_gem_object *from_obj = ring->last_context_obj; -	int ret;  	if (dev_priv->hw_contexts_disabled)  		return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 5af631e788c..ff2819ea081 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -291,6 +291,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  	target_i915_obj = to_intel_bo(target_obj);  	target_offset = target_i915_obj->gtt_offset; +	/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and +	 * pipe_control writes because the gpu doesn't properly redirect them +	 * through the ppgtt for non_secure batchbuffers. */ +	if (unlikely(IS_GEN6(dev) && +	    reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && +	    !target_i915_obj->has_global_gtt_mapping)) { +		i915_gem_gtt_bind_object(target_i915_obj, +					 target_i915_obj->cache_level); +	} +  	/* The target buffer should have appeared before us in the  	 * exec_object list, so it should have a GTT space bound by now.  	 */ @@ -399,16 +409,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  		io_mapping_unmap_atomic(reloc_page);  	} -	/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and -	 * pipe_control writes because the gpu doesn't properly redirect them -	 * through the ppgtt for non_secure batchbuffers. */ -	if (unlikely(IS_GEN6(dev) && -	    reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && -	    !target_i915_obj->has_global_gtt_mapping)) { -		i915_gem_gtt_bind_object(target_i915_obj, -					 target_i915_obj->cache_level); -	} -  	/* and update the user's relocation entry */  	reloc->presumed_offset = target_offset; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9fd25a43553..d9a5372ec56 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -261,7 +261,10 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,  		pte_flags |= GEN6_PTE_CACHE_LLC;  		break;  	case I915_CACHE_NONE: -		pte_flags |= GEN6_PTE_UNCACHED; +		if (IS_HASWELL(dev)) +			pte_flags |= HSW_PTE_UNCACHED; +		else +			pte_flags |= GEN6_PTE_UNCACHED;  		break;  	default:  		BUG(); @@ -361,7 +364,8 @@ int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)  	struct drm_device *dev = obj->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; -	if (dev_priv->mm.gtt->needs_dmar) +	/* don't map imported dma buf objects */ +	if (dev_priv->mm.gtt->needs_dmar && !obj->sg_table)  		return intel_gtt_map_memory(obj->pages,  					    obj->base.size >> PAGE_SHIFT,  					    &obj->sg_list, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index acc99b21e0b..28725ce5b82 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -115,6 +115,7 @@  #define GEN6_PTE_VALID			(1 << 0)  #define GEN6_PTE_UNCACHED		(1 << 1) +#define HSW_PTE_UNCACHED		(0)  #define GEN6_PTE_CACHE_LLC		(2 << 1)  #define GEN6_PTE_CACHE_LLC_MLC		(3 << 1)  #define GEN6_PTE_CACHE_BITS		(3 << 1) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 2f5388af8df..7631807a278 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -32,6 +32,7 @@  #include "intel_drv.h"  #include "i915_drv.h" +#ifdef CONFIG_PM  static u32 calc_residency(struct drm_device *dev, const u32 reg)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -224,3 +225,14 @@ void i915_teardown_sysfs(struct drm_device *dev)  	device_remove_bin_file(&dev->primary->kdev,  &dpf_attrs);  	sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);  } +#else +void i915_setup_sysfs(struct drm_device *dev) +{ +	return; +} + +void i915_teardown_sysfs(struct drm_device *dev) +{ +	return; +} +#endif /* CONFIG_PM */ diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 7ed4a41c396..23bdc8cd145 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -326,6 +326,36 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)  	return ret;  } +static struct edid *intel_crt_get_edid(struct drm_connector *connector, +				struct i2c_adapter *i2c) +{ +	struct edid *edid; + +	edid = drm_get_edid(connector, i2c); + +	if (!edid && !intel_gmbus_is_forced_bit(i2c)) { +		DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n"); +		intel_gmbus_force_bit(i2c, true); +		edid = drm_get_edid(connector, i2c); +		intel_gmbus_force_bit(i2c, false); +	} + +	return edid; +} + +/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */ +static int intel_crt_ddc_get_modes(struct drm_connector *connector, +				struct i2c_adapter *adapter) +{ +	struct edid *edid; + +	edid = intel_crt_get_edid(connector, adapter); +	if (!edid) +		return 0; + +	return intel_connector_update_modes(connector, edid); +} +  static bool intel_crt_detect_ddc(struct drm_connector *connector)  {  	struct intel_crt *crt = intel_attached_crt(connector); @@ -336,7 +366,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)  	BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);  	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); -	edid = drm_get_edid(connector, i2c); +	edid = intel_crt_get_edid(connector, i2c);  	if (edid) {  		bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL; @@ -544,13 +574,13 @@ static int intel_crt_get_modes(struct drm_connector *connector)  	struct i2c_adapter *i2c;  	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); -	ret = intel_ddc_get_modes(connector, i2c); +	ret = intel_crt_ddc_get_modes(connector, i2c);  	if (ret || !IS_G4X(dev))  		return ret;  	/* Try to probe digital port for output in DVI-I -> VGA mode. */  	i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB); -	return intel_ddc_get_modes(connector, i2c); +	return intel_crt_ddc_get_modes(connector, i2c);  }  static int intel_crt_set_property(struct drm_connector *connector, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f6159765f1e..a69a3d0d3ac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -869,6 +869,7 @@ intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,  	unsigned long bestppm, ppm, absppm;  	int dotclk, flag; +	flag = 0;  	dotclk = target * 1000;  	bestppm = 1000000;  	ppm = absppm = 0; @@ -3753,17 +3754,6 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  			continue;  		} -		if (intel_encoder->type == INTEL_OUTPUT_EDP) { -			/* Use VBT settings if we have an eDP panel */ -			unsigned int edp_bpc = dev_priv->edp.bpp / 3; - -			if (edp_bpc < display_bpc) { -				DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); -				display_bpc = edp_bpc; -			} -			continue; -		} -  		/* Not one of the known troublemakers, check the EDID */  		list_for_each_entry(connector, &dev->mode_config.connector_list,  				    head) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0a56b9ab0f5..a6c426afaa7 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1174,10 +1174,14 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp)  	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");  	pp = ironlake_get_pp_control(dev_priv); -	pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); +	/* We need to switch off panel power _and_ force vdd, for otherwise some +	 * panels get very unhappy and cease to work. */ +	pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);  	I915_WRITE(PCH_PP_CONTROL, pp);  	POSTING_READ(PCH_PP_CONTROL); +	intel_dp->want_panel_vdd = false; +  	ironlake_wait_panel_off(intel_dp);  } @@ -1287,11 +1291,9 @@ static void intel_dp_prepare(struct drm_encoder *encoder)  	 * ensure that we have vdd while we switch off the panel. */  	ironlake_edp_panel_vdd_on(intel_dp);  	ironlake_edp_backlight_off(intel_dp); -	ironlake_edp_panel_off(intel_dp); -  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); +	ironlake_edp_panel_off(intel_dp);  	intel_dp_link_down(intel_dp); -	ironlake_edp_panel_vdd_off(intel_dp, false);  }  static void intel_dp_commit(struct drm_encoder *encoder) @@ -1326,11 +1328,9 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)  		/* Switching the panel off requires vdd. */  		ironlake_edp_panel_vdd_on(intel_dp);  		ironlake_edp_backlight_off(intel_dp); -		ironlake_edp_panel_off(intel_dp); -  		intel_dp_sink_dpms(intel_dp, mode); +		ironlake_edp_panel_off(intel_dp);  		intel_dp_link_down(intel_dp); -		ironlake_edp_panel_vdd_off(intel_dp, false);  		if (is_cpu_edp(intel_dp))  			ironlake_edp_pll_off(encoder); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 84353559441..cd54cf88a28 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -46,15 +46,16 @@  })  #define wait_for_atomic_us(COND, US) ({ \ -	int i, ret__ = -ETIMEDOUT;	\ -	for (i = 0; i < (US); i++) {	\ -		if ((COND)) {		\ -			ret__ = 0;	\ -			break;		\ -		}			\ -		udelay(1);		\ -	}				\ -	ret__;				\ +	unsigned long timeout__ = jiffies + usecs_to_jiffies(US);	\ +	int ret__ = 0;							\ +	while (!(COND)) {						\ +		if (time_after(jiffies, timeout__)) {			\ +			ret__ = -ETIMEDOUT;				\ +			break;						\ +		}							\ +		cpu_relax();						\ +	}								\ +	ret__;								\  })  #define wait_for(COND, MS) _wait_for(COND, MS, 1) @@ -341,6 +342,8 @@ struct intel_fbc_work {  	int interval;  }; +int intel_connector_update_modes(struct drm_connector *connector, +				struct edid *edid);  int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);  extern void intel_attach_force_audio_property(struct drm_connector *connector); @@ -380,7 +383,6 @@ extern void intel_pch_panel_fitting(struct drm_device *dev,  				    const struct drm_display_mode *mode,  				    struct drm_display_mode *adjusted_mode);  extern u32 intel_panel_get_max_backlight(struct drm_device *dev); -extern u32 intel_panel_get_backlight(struct drm_device *dev);  extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);  extern int intel_panel_setup_backlight(struct drm_device *dev);  extern void intel_panel_enable_backlight(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 1991a4408cf..b9755f6378d 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -486,9 +486,6 @@ int intel_setup_gmbus(struct drm_device *dev)  		bus->dev_priv = dev_priv;  		bus->adapter.algo = &gmbus_algorithm; -		ret = i2c_add_adapter(&bus->adapter); -		if (ret) -			goto err;  		/* By default use a conservative clock rate */  		bus->reg0 = port | GMBUS_RATE_100KHZ; @@ -498,6 +495,10 @@ int intel_setup_gmbus(struct drm_device *dev)  			bus->force_bit = true;  		intel_gpio_setup(bus, port); + +		ret = i2c_add_adapter(&bus->adapter); +		if (ret) +			goto err;  	}  	intel_i2c_reset(dev_priv->dev); @@ -540,9 +541,6 @@ void intel_teardown_gmbus(struct drm_device *dev)  	struct drm_i915_private *dev_priv = dev->dev_private;  	int i; -	if (dev_priv->gmbus == NULL) -		return; -  	for (i = 0; i < GMBUS_NUM_PORTS; i++) {  		struct intel_gmbus *bus = &dev_priv->gmbus[i];  		i2c_del_adapter(&bus->adapter); diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index 45848b9b670..29b72593fbb 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -33,6 +33,25 @@  #include "i915_drv.h"  /** + * intel_connector_update_modes - update connector from edid + * @connector: DRM connector device to use + * @edid: previously read EDID information + */ +int intel_connector_update_modes(struct drm_connector *connector, +				struct edid *edid) +{ +	int ret; + +	drm_mode_connector_update_edid_property(connector, edid); +	ret = drm_add_edid_modes(connector, edid); +	drm_edid_to_eld(connector, edid); +	connector->display_info.raw_edid = NULL; +	kfree(edid); + +	return ret; +} + +/**   * intel_ddc_get_modes - get modelist from monitor   * @connector: DRM connector device to use   * @adapter: i2c adapter @@ -43,18 +62,12 @@ int intel_ddc_get_modes(struct drm_connector *connector,  			struct i2c_adapter *adapter)  {  	struct edid *edid; -	int ret = 0;  	edid = drm_get_edid(connector, adapter); -	if (edid) { -		drm_mode_connector_update_edid_property(connector, edid); -		ret = drm_add_edid_modes(connector, edid); -		drm_edid_to_eld(connector, edid); -		connector->display_info.raw_edid = NULL; -		kfree(edid); -	} +	if (!edid) +		return 0; -	return ret; +	return intel_connector_update_modes(connector, edid);  }  static const struct drm_prop_enum_list force_audio_names[] = { diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 10c7d39034e..3df4f5fa892 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -213,7 +213,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val)  	return val;  } -u32 intel_panel_get_backlight(struct drm_device *dev) +static u32 intel_panel_get_backlight(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	u32 val; @@ -311,9 +311,6 @@ void intel_panel_enable_backlight(struct drm_device *dev,  	if (dev_priv->backlight_level == 0)  		dev_priv->backlight_level = intel_panel_get_max_backlight(dev); -	dev_priv->backlight_enabled = true; -	intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); -  	if (INTEL_INFO(dev)->gen >= 4) {  		uint32_t reg, tmp; @@ -326,7 +323,7 @@ void intel_panel_enable_backlight(struct drm_device *dev,  		 * we don't track the backlight dpms state, hence check whether  		 * we have to do anything first. */  		if (tmp & BLM_PWM_ENABLE) -			return; +			goto set_level;  		if (dev_priv->num_pipe == 3)  			tmp &= ~BLM_PIPE_SELECT_IVB; @@ -347,6 +344,14 @@ void intel_panel_enable_backlight(struct drm_device *dev,  			I915_WRITE(BLC_PWM_PCH_CTL1, tmp);  		}  	} + +set_level: +	/* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. +	 * BLC_PWM_CPU_CTL may be cleared to zero automatically when these +	 * registers are set. +	 */ +	dev_priv->backlight_enabled = true; +	intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);  }  static void intel_panel_init_backlight(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 94aabcaa3a6..1881c8c83f0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2441,17 +2441,10 @@ static void gen6_enable_rps(struct drm_device *dev)  		   dev_priv->max_delay << 24 |  		   dev_priv->min_delay << 16); -	if (IS_HASWELL(dev)) { -		I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); -		I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); -		I915_WRITE(GEN6_RP_UP_EI, 66000); -		I915_WRITE(GEN6_RP_DOWN_EI, 350000); -	} else { -		I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); -		I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); -		I915_WRITE(GEN6_RP_UP_EI, 100000); -		I915_WRITE(GEN6_RP_DOWN_EI, 5000000); -	} +	I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); +	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); +	I915_WRITE(GEN6_RP_UP_EI, 66000); +	I915_WRITE(GEN6_RP_DOWN_EI, 350000);  	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);  	I915_WRITE(GEN6_RP_CONTROL, @@ -3963,6 +3956,7 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)  		DRM_ERROR("Force wake wait timed out\n");  	I915_WRITE_NOTRACE(FORCEWAKE, 1); +	POSTING_READ(FORCEWAKE);  	if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))  		DRM_ERROR("Force wake wait timed out\n"); @@ -3983,6 +3977,7 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)  		DRM_ERROR("Force wake wait timed out\n");  	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); +	POSTING_READ(FORCEWAKE_MT);  	if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))  		DRM_ERROR("Force wake wait timed out\n"); @@ -4018,14 +4013,14 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)  static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)  {  	I915_WRITE_NOTRACE(FORCEWAKE, 0); -	/* The below doubles as a POSTING_READ */ +	POSTING_READ(FORCEWAKE);  	gen6_gt_check_fifodbg(dev_priv);  }  static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)  {  	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); -	/* The below doubles as a POSTING_READ */ +	POSTING_READ(FORCEWAKE_MT);  	gen6_gt_check_fifodbg(dev_priv);  } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index bf0195a96d5..e2a73b38abe 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -227,31 +227,36 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring,  	 * number of bits based on the write domains has little performance  	 * impact.  	 */ -	flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; -	flags |= PIPE_CONTROL_TLB_INVALIDATE; -	flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; -	flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; -	flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; -	flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; -	flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; -	flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; -	/* -	 * Ensure that any following seqno writes only happen when the render -	 * cache is indeed flushed (but only if the caller actually wants that). -	 */ -	if (flush_domains) +	if (flush_domains) { +		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; +		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; +		/* +		 * Ensure that any following seqno writes only happen +		 * when the render cache is indeed flushed. +		 */  		flags |= PIPE_CONTROL_CS_STALL; +	} +	if (invalidate_domains) { +		flags |= PIPE_CONTROL_TLB_INVALIDATE; +		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; +		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; +		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; +		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; +		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; +		/* +		 * TLB invalidate requires a post-sync write. +		 */ +		flags |= PIPE_CONTROL_QW_WRITE; +	} -	ret = intel_ring_begin(ring, 6); +	ret = intel_ring_begin(ring, 4);  	if (ret)  		return ret; -	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); +	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));  	intel_ring_emit(ring, flags);  	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); -	intel_ring_emit(ring, 0); /* lower dword */ -	intel_ring_emit(ring, 0); /* uppwer dword */ -	intel_ring_emit(ring, MI_NOOP); +	intel_ring_emit(ring, 0);  	intel_ring_advance(ring);  	return 0; @@ -289,8 +294,6 @@ static int init_ring_common(struct intel_ring_buffer *ring)  	I915_WRITE_HEAD(ring, 0);  	ring->write_tail(ring, 0); -	/* Initialize the ring. */ -	I915_WRITE_START(ring, obj->gtt_offset);  	head = I915_READ_HEAD(ring) & HEAD_ADDR;  	/* G45 ring initialization fails to reset head to zero */ @@ -316,6 +319,11 @@ static int init_ring_common(struct intel_ring_buffer *ring)  		}  	} +	/* Initialize the ring. This must happen _after_ we've cleared the ring +	 * registers with the above sequence (the readback of the HEAD registers +	 * also enforces ordering), otherwise the hw might lose the new ring +	 * register values. */ +	I915_WRITE_START(ring, obj->gtt_offset);  	I915_WRITE_CTL(ring,  			((ring->size - PAGE_SIZE) & RING_NR_PAGES)  			| RING_VALID); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 26a6a4d0d07..d81bb0bf288 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -444,13 +444,16 @@ static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd,  	struct i2c_msg *msgs;  	int i, ret = true; +        /* Would be simpler to allocate both in one go ? */          	buf = (u8 *)kzalloc(args_len * 2 + 2, GFP_KERNEL);  	if (!buf)  		return false;  	msgs = kcalloc(args_len + 3, sizeof(*msgs), GFP_KERNEL); -	if (!msgs) +	if (!msgs) { +	        kfree(buf);  		return false; +        }  	intel_sdvo_debug_write(intel_sdvo, cmd, args, args_len); @@ -1689,6 +1692,7 @@ static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)  	edid = intel_sdvo_get_edid(connector);  	if (edid != NULL && edid->input & DRM_EDID_INPUT_DIGITAL)  		has_audio = drm_detect_monitor_audio(edid); +	kfree(edid);  	return has_audio;  } diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index a4d7c500c97..b69642d5d85 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -468,10 +468,11 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)  {  	unsigned int vcomax, vcomin, pllreffreq;  	unsigned int delta, tmpdelta; -	unsigned int testr, testn, testm, testo; +	int testr, testn, testm, testo;  	unsigned int p, m, n; -	unsigned int computed; +	unsigned int computed, vco;  	int tmp; +	const unsigned int m_div_val[] = { 1, 2, 4, 8 };  	m = n = p = 0;  	vcomax = 1488000; @@ -490,12 +491,13 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)  				if (delta == 0)  					break;  				for (testo = 5; testo < 33; testo++) { -					computed = pllreffreq * (testn + 1) / +					vco = pllreffreq * (testn + 1) /  						(testr + 1); -					if (computed < vcomin) +					if (vco < vcomin)  						continue; -					if (computed > vcomax) +					if (vco > vcomax)  						continue; +					computed = vco / (m_div_val[testm] * (testo + 1));  					if (computed > clock)  						tmpdelta = computed - clock;  					else diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index fc841e87b34..26ebffebe71 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -211,11 +211,6 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,  	return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);  } -static int nouveau_dsm_init(void) -{ -	return 0; -} -  static int nouveau_dsm_get_client_id(struct pci_dev *pdev)  {  	/* easy option one - intel vendor ID means Integrated */ @@ -232,7 +227,6 @@ static int nouveau_dsm_get_client_id(struct pci_dev *pdev)  static struct vga_switcheroo_handler nouveau_dsm_handler = {  	.switchto = nouveau_dsm_switchto,  	.power_state = nouveau_dsm_power_state, -	.init = nouveau_dsm_init,  	.get_client_id = nouveau_dsm_get_client_id,  }; diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index 77e564667b5..240cf962c99 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -229,7 +229,7 @@ nouveau_i2c_init(struct drm_device *dev)  			}  			break;  		case 6: /* NV50- DP AUX */ -			port->drive = entry[0]; +			port->drive = entry[0] & 0x0f;  			port->sense = port->drive;  			port->adapter.algo = &nouveau_dp_i2c_algo;  			break; diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 1cdfd6e757c..1866dbb4997 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -731,7 +731,6 @@ nouveau_card_init(struct drm_device *dev)  			case 0xa3:  			case 0xa5:  			case 0xa8: -			case 0xaf:  				nva3_copy_create(dev);  				break;  			} diff --git a/drivers/gpu/drm/nouveau/nv84_fifo.c b/drivers/gpu/drm/nouveau/nv84_fifo.c index cc82d799fc3..c564c5e4c30 100644 --- a/drivers/gpu/drm/nouveau/nv84_fifo.c +++ b/drivers/gpu/drm/nouveau/nv84_fifo.c @@ -117,17 +117,22 @@ nv84_fifo_context_del(struct nouveau_channel *chan, int engine)  	struct drm_device *dev = chan->dev;  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	unsigned long flags; +	u32 save;  	/* remove channel from playlist, will context switch if active */  	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);  	nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000);  	nv50_fifo_playlist_update(dev); +	save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); +  	/* tell any engines on this channel to unload their contexts */  	nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12);  	if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff))  		NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); +	nv_wr32(dev, 0x002520, save); +  	nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000);  	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); @@ -184,10 +189,13 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend)  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct nv84_fifo_priv *priv = nv_engine(dev, engine);  	int i; +	u32 save;  	/* set playlist length to zero, fifo will unload context */  	nv_wr32(dev, 0x0032ec, 0); +	save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); +  	/* tell all connected engines to unload their contexts */  	for (i = 0; i < priv->base.channels; i++) {  		struct nouveau_channel *chan = dev_priv->channels.ptr[i]; @@ -199,6 +207,7 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend)  		}  	} +	nv_wr32(dev, 0x002520, save);  	nv_wr32(dev, 0x002140, 0);  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index 7c95c44e288..4e712b10ebd 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -557,7 +557,7 @@ prog_mem(struct drm_device *dev, struct nvc0_pm_state *info)  	nouveau_mem_exec(&exec, info->perflvl);  	if (dev_priv->chipset < 0xd0) -		nv_wr32(dev, 0x611200, 0x00003300); +		nv_wr32(dev, 0x611200, 0x00003330);  	else  		nv_wr32(dev, 0x62c000, 0x03030300);  } diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index d0d60e1e7f9..dac525b2994 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -790,7 +790,7 @@ nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);  	int ch = EVO_CURS(nv_crtc->index); -	evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x); +	evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff));  	evo_piow(crtc->dev, ch, 0x0080, 0x00000000);  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nve0_fifo.c b/drivers/gpu/drm/nouveau/nve0_fifo.c index 1855ecbd843..e98d144e6eb 100644 --- a/drivers/gpu/drm/nouveau/nve0_fifo.c +++ b/drivers/gpu/drm/nouveau/nve0_fifo.c @@ -294,6 +294,25 @@ nve0_fifo_isr_vm_fault(struct drm_device *dev, int unit)  	printk(" on channel 0x%010llx\n", (u64)inst << 12);  } +static int +nve0_fifo_page_flip(struct drm_device *dev, u32 chid) +{ +	struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); +	struct drm_nouveau_private *dev_priv = dev->dev_private; +	struct nouveau_channel *chan = NULL; +	unsigned long flags; +	int ret = -EINVAL; + +	spin_lock_irqsave(&dev_priv->channels.lock, flags); +	if (likely(chid >= 0 && chid < priv->base.channels)) { +		chan = dev_priv->channels.ptr[chid]; +		if (likely(chan)) +			ret = nouveau_finish_page_flip(chan, NULL); +	} +	spin_unlock_irqrestore(&dev_priv->channels.lock, flags); +	return ret; +} +  static void  nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)  { @@ -303,11 +322,21 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)  	u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f;  	u32 subc = (addr & 0x00070000);  	u32 mthd = (addr & 0x00003ffc); +	u32 show = stat; + +	if (stat & 0x00200000) { +		if (mthd == 0x0054) { +			if (!nve0_fifo_page_flip(dev, chid)) +				show &= ~0x00200000; +		} +	} -	NV_INFO(dev, "PSUBFIFO %d:", unit); -	nouveau_bitfield_print(nve0_fifo_subfifo_intr, stat); -	NV_INFO(dev, "PSUBFIFO %d: ch %d subc %d mthd 0x%04x data 0x%08x\n", -		unit, chid, subc, mthd, data); +	if (show) { +		NV_INFO(dev, "PFIFO%d:", unit); +		nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); +		NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", +			unit, chid, subc, mthd, data); +	}  	nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008);  	nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 9e6f76fec52..f4d4505fe83 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -259,7 +259,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)  		/* adjust pm to dpms changes BEFORE enabling crtcs */  		radeon_pm_compute_clocks(rdev);  		/* disable crtc pair power gating before programming */ -		if (ASIC_IS_DCE6(rdev)) +		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)  			atombios_powergate_crtc(crtc, ATOM_DISABLE);  		atombios_enable_crtc(crtc, ATOM_ENABLE);  		if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) @@ -279,7 +279,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)  		atombios_enable_crtc(crtc, ATOM_DISABLE);  		radeon_crtc->enabled = false;  		/* power gating is per-pair */ -		if (ASIC_IS_DCE6(rdev)) { +		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) {  			struct drm_crtc *other_crtc;  			struct radeon_crtc *other_radeon_crtc;  			list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { @@ -444,11 +444,28 @@ union atom_enable_ss {  static void atombios_crtc_program_ss(struct radeon_device *rdev,  				     int enable,  				     int pll_id, +				     int crtc_id,  				     struct radeon_atom_ss *ss)  { +	unsigned i;  	int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);  	union atom_enable_ss args; +	if (!enable) { +		for (i = 0; i < rdev->num_crtc; i++) { +			if (rdev->mode_info.crtcs[i] && +			    rdev->mode_info.crtcs[i]->enabled && +			    i != crtc_id && +			    pll_id == rdev->mode_info.crtcs[i]->pll_id) { +				/* one other crtc is using this pll don't turn +				 * off spread spectrum as it might turn off +				 * display on active crtc +				 */ +				return; +			} +		} +	} +  	memset(&args, 0, sizeof(args));  	if (ASIC_IS_DCE5(rdev)) { @@ -1028,7 +1045,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode  		radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,  					  &ref_div, &post_div); -	atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss); +	atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);  	atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,  				  encoder_mode, radeon_encoder->encoder_id, mode->clock, @@ -1051,7 +1068,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode  			ss.step = step_size;  		} -		atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss); +		atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);  	}  } @@ -1531,12 +1548,12 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)  				 * crtc virtual pixel clock.  				 */  				if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { -					if (ASIC_IS_DCE5(rdev)) -						return ATOM_DCPLL; +					if (rdev->clock.dp_extclk) +						return ATOM_PPLL_INVALID;  					else if (ASIC_IS_DCE6(rdev))  						return ATOM_PPLL0; -					else if (rdev->clock.dp_extclk) -						return ATOM_PPLL_INVALID; +					else if (ASIC_IS_DCE5(rdev)) +						return ATOM_DCPLL;  				}  			}  		} @@ -1572,11 +1589,11 @@ void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev)  								   ASIC_INTERNAL_SS_ON_DCPLL,  								   rdev->clock.default_dispclk);  		if (ss_enabled) -			atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss); +			atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss);  		/* XXX: DCE5, make sure voltage, dispclk is high enough */  		atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk);  		if (ss_enabled) -			atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss); +			atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss);  	}  } @@ -1635,18 +1652,28 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,  static void atombios_crtc_prepare(struct drm_crtc *crtc)  {  	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); +	struct drm_device *dev = crtc->dev; +	struct radeon_device *rdev = dev->dev_private; +	radeon_crtc->in_mode_set = true;  	/* pick pll */  	radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); +	/* disable crtc pair power gating before programming */ +	if (ASIC_IS_DCE6(rdev)) +		atombios_powergate_crtc(crtc, ATOM_DISABLE); +  	atombios_lock_crtc(crtc, ATOM_ENABLE);  	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);  }  static void atombios_crtc_commit(struct drm_crtc *crtc)  { +	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); +  	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);  	atombios_lock_crtc(crtc, ATOM_DISABLE); +	radeon_crtc->in_mode_set = false;  }  static void atombios_crtc_disable(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e585a3b947e..e93b80a6d4e 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1229,24 +1229,8 @@ void evergreen_agp_enable(struct radeon_device *rdev)  void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)  { -	save->vga_control[0] = RREG32(D1VGA_CONTROL); -	save->vga_control[1] = RREG32(D2VGA_CONTROL);  	save->vga_render_control = RREG32(VGA_RENDER_CONTROL);  	save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); -	save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); -	save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); -	if (rdev->num_crtc >= 4) { -		save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); -		save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); -		save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); -		save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); -	} -	if (rdev->num_crtc >= 6) { -		save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); -		save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); -		save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); -		save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); -	}  	/* Stop all video */  	WREG32(VGA_RENDER_CONTROL, 0); @@ -1357,47 +1341,6 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s  	/* Unlock host access */  	WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);  	mdelay(1); -	/* Restore video state */ -	WREG32(D1VGA_CONTROL, save->vga_control[0]); -	WREG32(D2VGA_CONTROL, save->vga_control[1]); -	if (rdev->num_crtc >= 4) { -		WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); -		WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); -	} -	if (rdev->num_crtc >= 6) { -		WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); -		WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); -	} -	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); -	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); -	if (rdev->num_crtc >= 4) { -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); -	} -	if (rdev->num_crtc >= 6) { -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); -	} -	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); -	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); -	if (rdev->num_crtc >= 4) { -		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); -		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); -	} -	if (rdev->num_crtc >= 6) { -		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); -		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); -	} -	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); -	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -	if (rdev->num_crtc >= 4) { -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -	} -	if (rdev->num_crtc >= 6) { -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -	}  	WREG32(VGA_RENDER_CONTROL, save->vga_render_control);  } @@ -1986,10 +1929,18 @@ static void evergreen_gpu_init(struct radeon_device *rdev)  	if (rdev->flags & RADEON_IS_IGP)  		rdev->config.evergreen.tile_config |= 1 << 4;  	else { -		if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) -			rdev->config.evergreen.tile_config |= 1 << 4; -		else +		switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { +		case 0: /* four banks */  			rdev->config.evergreen.tile_config |= 0 << 4; +			break; +		case 1: /* eight banks */ +			rdev->config.evergreen.tile_config |= 1 << 4; +			break; +		case 2: /* sixteen banks */ +		default: +			rdev->config.evergreen.tile_config |= 2 << 4; +			break; +		}  	}  	rdev->config.evergreen.tile_config |= 0 << 8;  	rdev->config.evergreen.tile_config |= diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index c16554122cc..e44a62a07fe 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -788,6 +788,13 @@ static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p,  	case V_030000_SQ_TEX_DIM_1D_ARRAY:  	case V_030000_SQ_TEX_DIM_2D_ARRAY:  		depth = 1; +		break; +	case V_030000_SQ_TEX_DIM_2D_MSAA: +	case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA: +		surf.nsamples = 1 << llevel; +		llevel = 0; +		depth = 1; +		break;  	case V_030000_SQ_TEX_DIM_3D:  		break;  	default: @@ -961,13 +968,15 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p)  	if (track->db_dirty) {  		/* Check stencil buffer */ -		if (G_028800_STENCIL_ENABLE(track->db_depth_control)) { +		if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID && +		    G_028800_STENCIL_ENABLE(track->db_depth_control)) {  			r = evergreen_cs_track_validate_stencil(p);  			if (r)  				return r;  		}  		/* Check depth buffer */ -		if (G_028800_Z_ENABLE(track->db_depth_control)) { +		if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID && +		    G_028800_Z_ENABLE(track->db_depth_control)) {  			r = evergreen_cs_track_validate_depth(p);  			if (r)  				return r; diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index d3bd098e4e1..79347855d9b 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -1277,6 +1277,8 @@  #define   S_028044_FORMAT(x)                           (((x) & 0x1) << 0)  #define   G_028044_FORMAT(x)                           (((x) >> 0) & 0x1)  #define   C_028044_FORMAT                              0xFFFFFFFE +#define	    V_028044_STENCIL_INVALID			0 +#define	    V_028044_STENCIL_8				1  #define   G_028044_TILE_SPLIT(x)                       (((x) >> 8) & 0x7)  #define DB_Z_READ_BASE					0x28048  #define DB_STENCIL_READ_BASE				0x2804c diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 9945d86d900..853800e8582 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -574,10 +574,18 @@ static void cayman_gpu_init(struct radeon_device *rdev)  	if (rdev->flags & RADEON_IS_IGP)  		rdev->config.cayman.tile_config |= 1 << 4;  	else { -		if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) -			rdev->config.cayman.tile_config |= 1 << 4; -		else +		switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { +		case 0: /* four banks */  			rdev->config.cayman.tile_config |= 0 << 4; +			break; +		case 1: /* eight banks */ +			rdev->config.cayman.tile_config |= 1 << 4; +			break; +		case 2: /* sixteen banks */ +		default: +			rdev->config.cayman.tile_config |= 2 << 4; +			break; +		}  	}  	rdev->config.cayman.tile_config |=  		((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 637280f541a..d79c639ae73 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3789,3 +3789,23 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)  		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);  	}  } + +/** + * r600_get_gpu_clock - return GPU clock counter snapshot + * + * @rdev: radeon_device pointer + * + * Fetches a GPU clock counter snapshot (R6xx-cayman). + * Returns the 64 bit clock counter snapshot. + */ +uint64_t r600_get_gpu_clock(struct radeon_device *rdev) +{ +	uint64_t clock; + +	mutex_lock(&rdev->gpu_clock_mutex); +	WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); +	clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | +	        ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); +	mutex_unlock(&rdev->gpu_clock_mutex); +	return clock; +} diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index ca87f7afaf2..ab74e6b149e 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -47,13 +47,17 @@ struct r600_cs_track {  	u32			npipes;  	/* value we track */  	u32			sq_config; +	u32			log_nsamples;  	u32			nsamples;  	u32			cb_color_base_last[8];  	struct radeon_bo	*cb_color_bo[8];  	u64			cb_color_bo_mc[8]; -	u32			cb_color_bo_offset[8]; -	struct radeon_bo	*cb_color_frag_bo[8]; /* unused */ -	struct radeon_bo	*cb_color_tile_bo[8]; /* unused */ +	u64			cb_color_bo_offset[8]; +	struct radeon_bo	*cb_color_frag_bo[8]; +	u64			cb_color_frag_offset[8]; +	struct radeon_bo	*cb_color_tile_bo[8]; +	u64			cb_color_tile_offset[8]; +	u32			cb_color_mask[8];  	u32			cb_color_info[8];  	u32			cb_color_view[8];  	u32			cb_color_size_idx[8]; /* unused */ @@ -349,10 +353,6 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  	unsigned array_mode;  	u32 format; -	if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { -		dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); -		return -EINVAL; -	}  	size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];  	format = G_0280A0_FORMAT(track->cb_color_info[i]);  	if (!r600_fmt_is_valid_color(format)) { @@ -420,7 +420,8 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  	}  	/* check offset */ -	tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * r600_fmt_get_blocksize(format); +	tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * +	      r600_fmt_get_blocksize(format) * track->nsamples;  	switch (array_mode) {  	default:  	case V_0280A0_ARRAY_LINEAR_GENERAL: @@ -441,7 +442,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  			 * broken userspace.  			 */  		} else { -			dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big (%d %d) (%d %d %d)\n", +			dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n",  				 __func__, i, array_mode,  				 track->cb_color_bo_offset[i], tmp,  				 radeon_bo_size(track->cb_color_bo[i]), @@ -458,6 +459,51 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  	tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |  		S_028060_SLICE_TILE_MAX(slice_tile_max - 1);  	ib[track->cb_color_size_idx[i]] = tmp; + +	/* FMASK/CMASK */ +	switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) { +	case V_0280A0_TILE_DISABLE: +		break; +	case V_0280A0_FRAG_ENABLE: +		if (track->nsamples > 1) { +			uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]); +			/* the tile size is 8x8, but the size is in units of bits. +			 * for bytes, do just * 8. */ +			uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1); + +			if (bytes + track->cb_color_frag_offset[i] > +			    radeon_bo_size(track->cb_color_frag_bo[i])) { +				dev_warn(p->dev, "%s FMASK_TILE_MAX too large " +					 "(tile_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n", +					 __func__, tile_max, bytes, +					 track->cb_color_frag_offset[i], +					 radeon_bo_size(track->cb_color_frag_bo[i])); +				return -EINVAL; +			} +		} +		/* fall through */ +	case V_0280A0_CLEAR_ENABLE: +	{ +		uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]); +		/* One block = 128x128 pixels, one 8x8 tile has 4 bits.. +		 * (128*128) / (8*8) / 2 = 128 bytes per block. */ +		uint32_t bytes = (block_max + 1) * 128; + +		if (bytes + track->cb_color_tile_offset[i] > +		    radeon_bo_size(track->cb_color_tile_bo[i])) { +			dev_warn(p->dev, "%s CMASK_BLOCK_MAX too large " +				 "(block_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n", +				 __func__, block_max, bytes, +				 track->cb_color_tile_offset[i], +				 radeon_bo_size(track->cb_color_tile_bo[i])); +			return -EINVAL; +		} +		break; +	} +	default: +		dev_warn(p->dev, "%s invalid tile mode\n", __func__); +		return -EINVAL; +	}  	return 0;  } @@ -566,7 +612,7 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p)  		ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;  		nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; -		tmp = ntiles * bpe * 64 * nviews; +		tmp = ntiles * bpe * 64 * nviews * track->nsamples;  		if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {  			dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",  					array_mode, @@ -764,8 +810,10 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)  	}  	/* Check depth buffer */ -	if (track->db_dirty && (G_028800_STENCIL_ENABLE(track->db_depth_control) || -		G_028800_Z_ENABLE(track->db_depth_control))) { +	if (track->db_dirty && +	    G_028010_FORMAT(track->db_depth_info) != V_028010_DEPTH_INVALID && +	    (G_028800_STENCIL_ENABLE(track->db_depth_control) || +	     G_028800_Z_ENABLE(track->db_depth_control))) {  		r = r600_cs_track_validate_db(p);  		if (r)  			return r; @@ -1229,6 +1277,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  		break;  	case R_028C04_PA_SC_AA_CONFIG:  		tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx)); +		track->log_nsamples = tmp;  		track->nsamples = 1 << tmp;  		track->cb_dirty = true;  		break; @@ -1310,16 +1359,21 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  				dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);  				return -EINVAL;  			} -			ib[idx] = track->cb_color_base_last[tmp];  			track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; +			track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp]; +			ib[idx] = track->cb_color_base_last[tmp];  		} else {  			r = r600_cs_packet_next_reloc(p, &reloc);  			if (r) {  				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);  				return -EINVAL;  			} -			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);  			track->cb_color_frag_bo[tmp] = reloc->robj; +			track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8; +			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +		} +		if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { +			track->cb_dirty = true;  		}  		break;  	case R_0280C0_CB_COLOR0_TILE: @@ -1336,16 +1390,35 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  				dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);  				return -EINVAL;  			} -			ib[idx] = track->cb_color_base_last[tmp];  			track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; +			track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp]; +			ib[idx] = track->cb_color_base_last[tmp];  		} else {  			r = r600_cs_packet_next_reloc(p, &reloc);  			if (r) {  				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);  				return -EINVAL;  			} -			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);  			track->cb_color_tile_bo[tmp] = reloc->robj; +			track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8; +			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +		} +		if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { +			track->cb_dirty = true; +		} +		break; +	case R_028100_CB_COLOR0_MASK: +	case R_028104_CB_COLOR1_MASK: +	case R_028108_CB_COLOR2_MASK: +	case R_02810C_CB_COLOR3_MASK: +	case R_028110_CB_COLOR4_MASK: +	case R_028114_CB_COLOR5_MASK: +	case R_028118_CB_COLOR6_MASK: +	case R_02811C_CB_COLOR7_MASK: +		tmp = (reg - R_028100_CB_COLOR0_MASK) / 4; +		track->cb_color_mask[tmp] = ib[idx]; +		if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { +			track->cb_dirty = true;  		}  		break;  	case CB_COLOR0_BASE: @@ -1490,7 +1563,7 @@ unsigned r600_mip_minify(unsigned size, unsigned level)  }  static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, -			      unsigned w0, unsigned h0, unsigned d0, unsigned format, +			      unsigned w0, unsigned h0, unsigned d0, unsigned nsamples, unsigned format,  			      unsigned block_align, unsigned height_align, unsigned base_align,  			      unsigned *l0_size, unsigned *mipmap_size)  { @@ -1518,7 +1591,7 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,  		depth = r600_mip_minify(d0, i); -		size = nbx * nby * blocksize; +		size = nbx * nby * blocksize * nsamples;  		if (nfaces)  			size *= nfaces;  		else @@ -1557,13 +1630,14 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  					      u32 tiling_flags)  {  	struct r600_cs_track *track = p->track; -	u32 nfaces, llevel, blevel, w0, h0, d0; -	u32 word0, word1, l0_size, mipmap_size, word2, word3; +	u32 dim, nfaces, llevel, blevel, w0, h0, d0; +	u32 word0, word1, l0_size, mipmap_size, word2, word3, word4, word5;  	u32 height_align, pitch, pitch_align, depth_align; -	u32 array, barray, larray; +	u32 barray, larray;  	u64 base_align;  	struct array_mode_checker array_check;  	u32 format; +	bool is_array;  	/* on legacy kernel we don't perform advanced check */  	if (p->rdev == NULL) @@ -1581,12 +1655,28 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);  	}  	word1 = radeon_get_ib_value(p, idx + 1); +	word2 = radeon_get_ib_value(p, idx + 2) << 8; +	word3 = radeon_get_ib_value(p, idx + 3) << 8; +	word4 = radeon_get_ib_value(p, idx + 4); +	word5 = radeon_get_ib_value(p, idx + 5); +	dim = G_038000_DIM(word0);  	w0 = G_038000_TEX_WIDTH(word0) + 1; +	pitch = (G_038000_PITCH(word0) + 1) * 8;  	h0 = G_038004_TEX_HEIGHT(word1) + 1;  	d0 = G_038004_TEX_DEPTH(word1); +	format = G_038004_DATA_FORMAT(word1); +	blevel = G_038010_BASE_LEVEL(word4); +	llevel = G_038014_LAST_LEVEL(word5); +	/* pitch in texels */ +	array_check.array_mode = G_038000_TILE_MODE(word0); +	array_check.group_size = track->group_size; +	array_check.nbanks = track->nbanks; +	array_check.npipes = track->npipes; +	array_check.nsamples = 1; +	array_check.blocksize = r600_fmt_get_blocksize(format);  	nfaces = 1; -	array = 0; -	switch (G_038000_DIM(word0)) { +	is_array = false; +	switch (dim) {  	case V_038000_SQ_TEX_DIM_1D:  	case V_038000_SQ_TEX_DIM_2D:  	case V_038000_SQ_TEX_DIM_3D: @@ -1599,29 +1689,25 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  		break;  	case V_038000_SQ_TEX_DIM_1D_ARRAY:  	case V_038000_SQ_TEX_DIM_2D_ARRAY: -		array = 1; +		is_array = true;  		break; -	case V_038000_SQ_TEX_DIM_2D_MSAA:  	case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: +		is_array = true; +		/* fall through */ +	case V_038000_SQ_TEX_DIM_2D_MSAA: +		array_check.nsamples = 1 << llevel; +		llevel = 0; +		break;  	default:  		dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));  		return -EINVAL;  	} -	format = G_038004_DATA_FORMAT(word1);  	if (!r600_fmt_is_valid_texture(format, p->family)) {  		dev_warn(p->dev, "%s:%d texture invalid format %d\n",  			 __func__, __LINE__, format);  		return -EINVAL;  	} -	/* pitch in texels */ -	pitch = (G_038000_PITCH(word0) + 1) * 8; -	array_check.array_mode = G_038000_TILE_MODE(word0); -	array_check.group_size = track->group_size; -	array_check.nbanks = track->nbanks; -	array_check.npipes = track->npipes; -	array_check.nsamples = 1; -	array_check.blocksize = r600_fmt_get_blocksize(format);  	if (r600_get_array_mode_alignment(&array_check,  					  &pitch_align, &height_align, &depth_align, &base_align)) {  		dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", @@ -1647,24 +1733,17 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  		return -EINVAL;  	} -	word2 = radeon_get_ib_value(p, idx + 2) << 8; -	word3 = radeon_get_ib_value(p, idx + 3) << 8; - -	word0 = radeon_get_ib_value(p, idx + 4); -	word1 = radeon_get_ib_value(p, idx + 5); -	blevel = G_038010_BASE_LEVEL(word0); -	llevel = G_038014_LAST_LEVEL(word1);  	if (blevel > llevel) {  		dev_warn(p->dev, "texture blevel %d > llevel %d\n",  			 blevel, llevel);  	} -	if (array == 1) { -		barray = G_038014_BASE_ARRAY(word1); -		larray = G_038014_LAST_ARRAY(word1); +	if (is_array) { +		barray = G_038014_BASE_ARRAY(word5); +		larray = G_038014_LAST_ARRAY(word5);  		nfaces = larray - barray + 1;  	} -	r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format, +	r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format,  			  pitch_align, height_align, base_align,  			  &l0_size, &mipmap_size);  	/* using get ib will give us the offset into the texture bo */ @@ -1677,7 +1756,6 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  		return -EINVAL;  	}  	/* using get ib will give us the offset into the mipmap bo */ -	word3 = radeon_get_ib_value(p, idx + 3) << 8;  	if ((mipmap_size + word3) > radeon_bo_size(mipmap)) {  		/*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",  		  w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/ diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 4b116ae75fc..bdb69a63062 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -92,6 +92,20 @@  #define R_028094_CB_COLOR5_VIEW                      0x028094  #define R_028098_CB_COLOR6_VIEW                      0x028098  #define R_02809C_CB_COLOR7_VIEW                      0x02809C +#define R_028100_CB_COLOR0_MASK                      0x028100 +#define   S_028100_CMASK_BLOCK_MAX(x)                  (((x) & 0xFFF) << 0) +#define   G_028100_CMASK_BLOCK_MAX(x)                  (((x) >> 0) & 0xFFF) +#define   C_028100_CMASK_BLOCK_MAX                     0xFFFFF000 +#define   S_028100_FMASK_TILE_MAX(x)                   (((x) & 0xFFFFF) << 12) +#define   G_028100_FMASK_TILE_MAX(x)                   (((x) >> 12) & 0xFFFFF) +#define   C_028100_FMASK_TILE_MAX                      0x00000FFF +#define R_028104_CB_COLOR1_MASK                      0x028104 +#define R_028108_CB_COLOR2_MASK                      0x028108 +#define R_02810C_CB_COLOR3_MASK                      0x02810C +#define R_028110_CB_COLOR4_MASK                      0x028110 +#define R_028114_CB_COLOR5_MASK                      0x028114 +#define R_028118_CB_COLOR6_MASK                      0x028118 +#define R_02811C_CB_COLOR7_MASK                      0x02811C  #define CB_COLOR0_INFO                                  0x280a0  #	define CB_FORMAT(x)				((x) << 2)  #       define CB_ARRAY_MODE(x)                         ((x) << 8) @@ -602,6 +616,9 @@  #define RLC_HB_WPTR                                       0x3f1c  #define RLC_HB_WPTR_LSB_ADDR                              0x3f14  #define RLC_HB_WPTR_MSB_ADDR                              0x3f18 +#define RLC_GPU_CLOCK_COUNT_LSB				  0x3f38 +#define RLC_GPU_CLOCK_COUNT_MSB				  0x3f3c +#define RLC_CAPTURE_GPU_CLOCK_COUNT			  0x3f40  #define RLC_MC_CNTL                                       0x3f44  #define RLC_UCODE_CNTL                                    0x3f48  #define RLC_UCODE_ADDR                                    0x3f2c @@ -1397,6 +1414,9 @@  #define   S_0280A0_TILE_MODE(x)                        (((x) & 0x3) << 18)  #define   G_0280A0_TILE_MODE(x)                        (((x) >> 18) & 0x3)  #define   C_0280A0_TILE_MODE                           0xFFF3FFFF +#define     V_0280A0_TILE_DISABLE			0 +#define     V_0280A0_CLEAR_ENABLE			1 +#define     V_0280A0_FRAG_ENABLE			2  #define   S_0280A0_BLEND_CLAMP(x)                      (((x) & 0x1) << 20)  #define   G_0280A0_BLEND_CLAMP(x)                      (((x) >> 20) & 0x1)  #define   C_0280A0_BLEND_CLAMP                         0xFFEFFFFF diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5431af29240..59a15315ae9 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -142,21 +142,6 @@ struct radeon_device;  /*   * BIOS.   */ -#define ATRM_BIOS_PAGE 4096 - -#if defined(CONFIG_VGA_SWITCHEROO) -bool radeon_atrm_supported(struct pci_dev *pdev); -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len); -#else -static inline bool radeon_atrm_supported(struct pci_dev *pdev) -{ -	return false; -} - -static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len){ -	return -EINVAL; -} -#endif  bool radeon_get_bios(struct radeon_device *rdev);  /* @@ -300,6 +285,7 @@ struct radeon_bo_va {  	uint64_t			soffset;  	uint64_t			eoffset;  	uint32_t			flags; +	struct radeon_fence		*fence;  	bool				valid;  }; @@ -1533,6 +1519,7 @@ struct radeon_device {  	unsigned 		debugfs_count;  	/* virtual memory */  	struct radeon_vm_manager	vm_manager; +	struct mutex			gpu_clock_mutex;  };  int radeon_device_init(struct radeon_device *rdev, @@ -1733,11 +1720,11 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);  #define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev))  #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev))  #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) -#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pflip.pre_page_flip((rdev), (crtc)) -#define radeon_page_flip(rdev, crtc, base) rdev->asic->pflip.page_flip((rdev), (crtc), (base)) -#define radeon_post_page_flip(rdev, crtc) rdev->asic->pflip.post_page_flip((rdev), (crtc)) -#define radeon_wait_for_vblank(rdev, crtc) rdev->asic->display.wait_for_vblank((rdev), (crtc)) -#define radeon_mc_wait_for_idle(rdev) rdev->asic->mc_wait_for_idle((rdev)) +#define radeon_pre_page_flip(rdev, crtc) (rdev)->asic->pflip.pre_page_flip((rdev), (crtc)) +#define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) +#define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) +#define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) +#define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))  /* Common functions */  /* AGP */ diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index f4af2431043..18c38d14c8c 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -255,13 +255,10 @@ extern int rs690_mc_wait_for_idle(struct radeon_device *rdev);   * rv515   */  struct rv515_mc_save { -	u32 d1vga_control; -	u32 d2vga_control;  	u32 vga_render_control;  	u32 vga_hdp_control; -	u32 d1crtc_control; -	u32 d2crtc_control;  }; +  int rv515_init(struct radeon_device *rdev);  void rv515_fini(struct radeon_device *rdev);  uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); @@ -371,6 +368,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,  			unsigned num_gpu_pages,  			struct radeon_sa_bo *vb);  int r600_mc_wait_for_idle(struct radeon_device *rdev); +uint64_t r600_get_gpu_clock(struct radeon_device *rdev);  /*   * rv770,rv730,rv710,rv740 @@ -389,11 +387,10 @@ void r700_cp_fini(struct radeon_device *rdev);   * evergreen   */  struct evergreen_mc_save { -	u32 vga_control[6];  	u32 vga_render_control;  	u32 vga_hdp_control; -	u32 crtc_control[6];  }; +  void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev);  int evergreen_init(struct radeon_device *rdev);  void evergreen_fini(struct radeon_device *rdev); @@ -472,5 +469,6 @@ int si_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id);  void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm);  void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm);  int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); +uint64_t si_get_gpu_clock(struct radeon_device *rdev);  #endif diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index b1e3820df36..d67d4f3eb6f 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -452,7 +452,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,  	}  	/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ -	if ((dev->pdev->device == 0x9802) && +	if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) &&  	    (dev->pdev->subsystem_vendor == 0x1734) &&  	    (dev->pdev->subsystem_device == 0x11bd)) {  		if (*connector_type == DRM_MODE_CONNECTOR_VGA) { @@ -1263,6 +1263,8 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)  union igp_info {  	struct _ATOM_INTEGRATED_SYSTEM_INFO info;  	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; +	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; +	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;  };  bool radeon_atombios_sideport_present(struct radeon_device *rdev) @@ -1390,27 +1392,50 @@ static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev,  	struct radeon_mode_info *mode_info = &rdev->mode_info;  	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);  	u16 data_offset, size; -	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info; +	union igp_info *igp_info;  	u8 frev, crev;  	u16 percentage = 0, rate = 0;  	/* get any igp specific overrides */  	if (atom_parse_data_header(mode_info->atom_context, index, &size,  				   &frev, &crev, &data_offset)) { -		igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *) +		igp_info = (union igp_info *)  			(mode_info->atom_context->bios + data_offset); -		switch (id) { -		case ASIC_INTERNAL_SS_ON_TMDS: -			percentage = le16_to_cpu(igp_info->usDVISSPercentage); -			rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz); +		switch (crev) { +		case 6: +			switch (id) { +			case ASIC_INTERNAL_SS_ON_TMDS: +				percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage); +				rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz); +				break; +			case ASIC_INTERNAL_SS_ON_HDMI: +				percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage); +				rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz); +				break; +			case ASIC_INTERNAL_SS_ON_LVDS: +				percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage); +				rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz); +				break; +			}  			break; -		case ASIC_INTERNAL_SS_ON_HDMI: -			percentage = le16_to_cpu(igp_info->usHDMISSPercentage); -			rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz); +		case 7: +			switch (id) { +			case ASIC_INTERNAL_SS_ON_TMDS: +				percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage); +				rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz); +				break; +			case ASIC_INTERNAL_SS_ON_HDMI: +				percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage); +				rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz); +				break; +			case ASIC_INTERNAL_SS_ON_LVDS: +				percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage); +				rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz); +				break; +			}  			break; -		case ASIC_INTERNAL_SS_ON_LVDS: -			percentage = le16_to_cpu(igp_info->usLvdsSSPercentage); -			rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz); +		default: +			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);  			break;  		}  		if (percentage) diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 98724fcb008..2a2cf0b88a2 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -30,57 +30,8 @@ static struct radeon_atpx_priv {  	/* handle for device - and atpx */  	acpi_handle dhandle;  	acpi_handle atpx_handle; -	acpi_handle atrm_handle;  } radeon_atpx_priv; -/* retrieve the ROM in 4k blocks */ -static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, -			    int offset, int len) -{ -	acpi_status status; -	union acpi_object atrm_arg_elements[2], *obj; -	struct acpi_object_list atrm_arg; -	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; - -	atrm_arg.count = 2; -	atrm_arg.pointer = &atrm_arg_elements[0]; - -	atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; -	atrm_arg_elements[0].integer.value = offset; - -	atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; -	atrm_arg_elements[1].integer.value = len; - -	status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); -	if (ACPI_FAILURE(status)) { -		printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); -		return -ENODEV; -	} - -	obj = (union acpi_object *)buffer.pointer; -	memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); -	len = obj->buffer.length; -	kfree(buffer.pointer); -	return len; -} - -bool radeon_atrm_supported(struct pci_dev *pdev) -{ -	/* get the discrete ROM only via ATRM */ -	if (!radeon_atpx_priv.atpx_detected) -		return false; - -	if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) -		return false; -	return true; -} - - -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) -{ -	return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len); -} -  static int radeon_atpx_get_version(acpi_handle handle)  {  	acpi_status status; @@ -198,7 +149,7 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,  static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)  { -	acpi_handle dhandle, atpx_handle, atrm_handle; +	acpi_handle dhandle, atpx_handle;  	acpi_status status;  	dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); @@ -209,13 +160,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)  	if (ACPI_FAILURE(status))  		return false; -	status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); -	if (ACPI_FAILURE(status)) -		return false; -  	radeon_atpx_priv.dhandle = dhandle;  	radeon_atpx_priv.atpx_handle = atpx_handle; -	radeon_atpx_priv.atrm_handle = atrm_handle;  	return true;  } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 501f4881e5a..d306cc8fdea 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,6 +32,7 @@  #include <linux/vga_switcheroo.h>  #include <linux/slab.h> +#include <linux/acpi.h>  /*   * BIOS.   */ @@ -98,16 +99,81 @@ static bool radeon_read_bios(struct radeon_device *rdev)  	return true;  } +#ifdef CONFIG_ACPI  /* ATRM is used to get the BIOS on the discrete cards in   * dual-gpu systems.   */ +/* retrieve the ROM in 4k blocks */ +#define ATRM_BIOS_PAGE 4096 +/** + * radeon_atrm_call - fetch a chunk of the vbios + * + * @atrm_handle: acpi ATRM handle + * @bios: vbios image pointer + * @offset: offset of vbios image data to fetch + * @len: length of vbios image data to fetch + * + * Executes ATRM to fetch a chunk of the discrete + * vbios image on PX systems (all asics). + * Returns the length of the buffer fetched. + */ +static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, +			    int offset, int len) +{ +	acpi_status status; +	union acpi_object atrm_arg_elements[2], *obj; +	struct acpi_object_list atrm_arg; +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + +	atrm_arg.count = 2; +	atrm_arg.pointer = &atrm_arg_elements[0]; + +	atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; +	atrm_arg_elements[0].integer.value = offset; + +	atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; +	atrm_arg_elements[1].integer.value = len; + +	status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); +	if (ACPI_FAILURE(status)) { +		printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); +		return -ENODEV; +	} + +	obj = (union acpi_object *)buffer.pointer; +	memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); +	len = obj->buffer.length; +	kfree(buffer.pointer); +	return len; +} +  static bool radeon_atrm_get_bios(struct radeon_device *rdev)  {  	int ret;  	int size = 256 * 1024;  	int i; +	struct pci_dev *pdev = NULL; +	acpi_handle dhandle, atrm_handle; +	acpi_status status; +	bool found = false; + +	/* ATRM is for the discrete card only */ +	if (rdev->flags & RADEON_IS_IGP) +		return false; -	if (!radeon_atrm_supported(rdev->pdev)) +	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { +		dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); +		if (!dhandle) +			continue; + +		status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); +		if (!ACPI_FAILURE(status)) { +			found = true; +			break; +		} +	} + +	if (!found)  		return false;  	rdev->bios = kmalloc(size, GFP_KERNEL); @@ -117,9 +183,10 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)  	}  	for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { -		ret = radeon_atrm_get_bios_chunk(rdev->bios, -						 (i * ATRM_BIOS_PAGE), -						 ATRM_BIOS_PAGE); +		ret = radeon_atrm_call(atrm_handle, +				       rdev->bios, +				       (i * ATRM_BIOS_PAGE), +				       ATRM_BIOS_PAGE);  		if (ret < ATRM_BIOS_PAGE)  			break;  	} @@ -130,6 +197,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)  	}  	return true;  } +#else +static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ +	return false; +} +#endif  static bool ni_read_disabled_bios(struct radeon_device *rdev)  { @@ -476,6 +549,61 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev)  		return legacy_read_disabled_bios(rdev);  } +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ +	bool ret = false; +	struct acpi_table_header *hdr; +	acpi_size tbl_size; +	UEFI_ACPI_VFCT *vfct; +	GOP_VBIOS_CONTENT *vbios; +	VFCT_IMAGE_HEADER *vhdr; + +	if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size))) +		return false; +	if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { +		DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); +		goto out_unmap; +	} + +	vfct = (UEFI_ACPI_VFCT *)hdr; +	if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { +		DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); +		goto out_unmap; +	} + +	vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); +	vhdr = &vbios->VbiosHeader; +	DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", +			vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, +			vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + +	if (vhdr->PCIBus != rdev->pdev->bus->number || +	    vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || +	    vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || +	    vhdr->VendorID != rdev->pdev->vendor || +	    vhdr->DeviceID != rdev->pdev->device) { +		DRM_INFO("ACPI VFCT table is not for this card\n"); +		goto out_unmap; +	}; + +	if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { +		DRM_ERROR("ACPI VFCT image truncated\n"); +		goto out_unmap; +	} + +	rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); +	ret = !!rdev->bios; + +out_unmap: +	return ret; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ +	return false; +} +#endif  bool radeon_get_bios(struct radeon_device *rdev)  { @@ -484,6 +612,8 @@ bool radeon_get_bios(struct radeon_device *rdev)  	r = radeon_atrm_get_bios(rdev);  	if (r == false) +		r = radeon_acpi_vfct_bios(rdev); +	if (r == false)  		r = igp_read_bios_from_vram(rdev);  	if (r == false)  		r = radeon_read_bios(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 576f4f6919f..f75247d42ff 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -719,6 +719,34 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde  	return i2c;  } +static struct radeon_i2c_bus_rec radeon_combios_get_i2c_info_from_table(struct radeon_device *rdev) +{ +	struct drm_device *dev = rdev->ddev; +	struct radeon_i2c_bus_rec i2c; +	u16 offset; +	u8 id, blocks, clk, data; +	int i; + +	i2c.valid = false; + +	offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); +	if (offset) { +		blocks = RBIOS8(offset + 2); +		for (i = 0; i < blocks; i++) { +			id = RBIOS8(offset + 3 + (i * 5) + 0); +			if (id == 136) { +				clk = RBIOS8(offset + 3 + (i * 5) + 3); +				data = RBIOS8(offset + 3 + (i * 5) + 4); +				/* gpiopad */ +				i2c = combios_setup_i2c_bus(rdev, DDC_MONID, +							    (1 << clk), (1 << data)); +				break; +			} +		} +	} +	return i2c; +} +  void radeon_combios_i2c_init(struct radeon_device *rdev)  {  	struct drm_device *dev = rdev->ddev; @@ -755,30 +783,14 @@ void radeon_combios_i2c_init(struct radeon_device *rdev)  	} else if (rdev->family == CHIP_RS300 ||  		   rdev->family == CHIP_RS400 ||  		   rdev->family == CHIP_RS480) { -		u16 offset; -		u8 id, blocks, clk, data; -		int i; -  		/* 0x68 */  		i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);  		rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); -		offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); -		if (offset) { -			blocks = RBIOS8(offset + 2); -			for (i = 0; i < blocks; i++) { -				id = RBIOS8(offset + 3 + (i * 5) + 0); -				if (id == 136) { -					clk = RBIOS8(offset + 3 + (i * 5) + 3); -					data = RBIOS8(offset + 3 + (i * 5) + 4); -					/* gpiopad */ -					i2c = combios_setup_i2c_bus(rdev, DDC_MONID, -								    (1 << clk), (1 << data)); -					rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); -					break; -				} -			} -		} +		/* gpiopad */ +		i2c = radeon_combios_get_i2c_info_from_table(rdev); +		if (i2c.valid) +			rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK");  	} else if ((rdev->family == CHIP_R200) ||  		   (rdev->family >= CHIP_R300)) {  		/* 0x68 */ @@ -2321,7 +2333,10 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)  			connector = (tmp >> 12) & 0xf;  			ddc_type = (tmp >> 8) & 0xf; -			ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); +			if (ddc_type == 5) +				ddc_i2c = radeon_combios_get_i2c_info_from_table(rdev); +			else +				ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0);  			switch (connector) {  			case CONNECTOR_PROPRIETARY_LEGACY: diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 8a4c49ef0cc..b4a0db24f4d 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -278,6 +278,30 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)  	return 0;  } +static void radeon_bo_vm_fence_va(struct radeon_cs_parser *parser, +				  struct radeon_fence *fence) +{ +	struct radeon_fpriv *fpriv = parser->filp->driver_priv; +	struct radeon_vm *vm = &fpriv->vm; +	struct radeon_bo_list *lobj; + +	if (parser->chunk_ib_idx == -1) { +		return; +	} +	if ((parser->cs_flags & RADEON_CS_USE_VM) == 0) { +		return; +	} + +	list_for_each_entry(lobj, &parser->validated, tv.head) { +		struct radeon_bo_va *bo_va; +		struct radeon_bo *rbo = lobj->bo; + +		bo_va = radeon_bo_va(rbo, vm); +		radeon_fence_unref(&bo_va->fence); +		bo_va->fence = radeon_fence_ref(fence); +	} +} +  /**   * cs_parser_fini() - clean parser states   * @parser:	parser structure holding parsing context. @@ -290,11 +314,14 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)  {  	unsigned i; -	if (!error) +	if (!error) { +		/* fence all bo va before ttm_eu_fence_buffer_objects so bo are still reserved */ +		radeon_bo_vm_fence_va(parser, parser->ib.fence);  		ttm_eu_fence_buffer_objects(&parser->validated,  					    parser->ib.fence); -	else +	} else {  		ttm_eu_backoff_reservation(&parser->validated); +	}  	if (parser->relocs != NULL) {  		for (i = 0; i < parser->nrelocs; i++) { @@ -388,7 +415,6 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,  	if (parser->chunk_ib_idx == -1)  		return 0; -  	if ((parser->cs_flags & RADEON_CS_USE_VM) == 0)  		return 0; diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 711e95ad39b..8794744cdf1 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -67,7 +67,8 @@ static void radeon_hide_cursor(struct drm_crtc *crtc)  	if (ASIC_IS_DCE4(rdev)) {  		WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); -		WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); +		WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | +		       EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));  	} else if (ASIC_IS_AVIVO(rdev)) {  		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);  		WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); @@ -94,7 +95,8 @@ static void radeon_show_cursor(struct drm_crtc *crtc)  	if (ASIC_IS_DCE4(rdev)) {  		WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);  		WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | -		       EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); +		       EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | +		       EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));  	} else if (ASIC_IS_AVIVO(rdev)) {  		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);  		WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 742af8244e8..d2e243867ac 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1009,6 +1009,7 @@ int radeon_device_init(struct radeon_device *rdev,  	atomic_set(&rdev->ih.lock, 0);  	mutex_init(&rdev->gem.mutex);  	mutex_init(&rdev->pm.mutex); +	mutex_init(&rdev->gpu_clock_mutex);  	init_rwsem(&rdev->pm.mclk_lock);  	init_rwsem(&rdev->exclusive_lock);  	init_waitqueue_head(&rdev->irq.vblank_queue); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dcea6f01ae4..27d22d709c9 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -59,9 +59,13 @@   *   2.15.0 - add max_pipes query   *   2.16.0 - fix evergreen 2D tiled surface calculation   *   2.17.0 - add STRMOUT_BASE_UPDATE for r7xx + *   2.18.0 - r600-eg: allow "invalid" DB formats + *   2.19.0 - r600-eg: MSAA textures + *   2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query + *   2.21.0 - r600-r700: FMASK and CMASK   */  #define KMS_DRIVER_MAJOR	2 -#define KMS_DRIVER_MINOR	17 +#define KMS_DRIVER_MINOR	21  #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/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index b3720054614..bb3b7fe05cc 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -814,7 +814,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,  		return -EINVAL;  	} -	if (bo_va->valid) +	if (bo_va->valid && mem)  		return 0;  	ngpu_pages = radeon_bo_ngpu_pages(bo); @@ -859,11 +859,27 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,  		     struct radeon_bo *bo)  {  	struct radeon_bo_va *bo_va; +	int r;  	bo_va = radeon_bo_va(bo, vm);  	if (bo_va == NULL)  		return 0; +	/* wait for va use to end */ +	while (bo_va->fence) { +		r = radeon_fence_wait(bo_va->fence, false); +		if (r) { +			DRM_ERROR("error while waiting for fence: %d\n", r); +		} +		if (r == -EDEADLK) { +			r = radeon_gpu_reset(rdev); +			if (!r) +				continue; +		} +		break; +	} +	radeon_fence_unref(&bo_va->fence); +  	mutex_lock(&rdev->vm_manager.lock);  	mutex_lock(&vm->mutex);  	radeon_vm_bo_update_pte(rdev, vm, bo, NULL); @@ -934,7 +950,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)  }  /** - * radeon_vm_init - tear down a vm instance + * radeon_vm_fini - tear down a vm instance   *   * @rdev: radeon_device pointer   * @vm: requested vm @@ -952,12 +968,15 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)  	radeon_vm_unbind_locked(rdev, vm);  	mutex_unlock(&rdev->vm_manager.lock); -	/* remove all bo */ +	/* remove all bo at this point non are busy any more because unbind +	 * waited for the last vm fence to signal +	 */  	r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);  	if (!r) {  		bo_va = radeon_bo_va(rdev->ring_tmp_bo.bo, vm);  		list_del_init(&bo_va->bo_list);  		list_del_init(&bo_va->vm_list); +		radeon_fence_unref(&bo_va->fence);  		radeon_bo_unreserve(rdev->ring_tmp_bo.bo);  		kfree(bo_va);  	} @@ -969,6 +988,7 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)  		r = radeon_bo_reserve(bo_va->bo, false);  		if (!r) {  			list_del_init(&bo_va->bo_list); +			radeon_fence_unref(&bo_va->fence);  			radeon_bo_unreserve(bo_va->bo);  			kfree(bo_va);  		} diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 84d04524573..1b57b0058ad 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -134,25 +134,16 @@ void radeon_gem_object_close(struct drm_gem_object *obj,  	struct radeon_device *rdev = rbo->rdev;  	struct radeon_fpriv *fpriv = file_priv->driver_priv;  	struct radeon_vm *vm = &fpriv->vm; -	struct radeon_bo_va *bo_va, *tmp;  	if (rdev->family < CHIP_CAYMAN) {  		return;  	}  	if (radeon_bo_reserve(rbo, false)) { +		dev_err(rdev->dev, "leaking bo va because we fail to reserve bo\n");  		return;  	} -	list_for_each_entry_safe(bo_va, tmp, &rbo->va, bo_list) { -		if (bo_va->vm == vm) { -			/* remove from this vm address space */ -			mutex_lock(&vm->mutex); -			list_del(&bo_va->vm_list); -			mutex_unlock(&vm->mutex); -			list_del(&bo_va->bo_list); -			kfree(bo_va); -		} -	} +	radeon_vm_bo_rmv(rdev, vm, rbo);  	radeon_bo_unreserve(rbo);  } diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 1d73f16b5d9..414b4acf694 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -29,6 +29,7 @@  #include "drm_sarea.h"  #include "radeon.h"  #include "radeon_drm.h" +#include "radeon_asic.h"  #include <linux/vga_switcheroo.h>  #include <linux/slab.h> @@ -167,17 +168,39 @@ static void radeon_set_filp_rights(struct drm_device *dev,  int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  {  	struct radeon_device *rdev = dev->dev_private; -	struct drm_radeon_info *info; +	struct drm_radeon_info *info = data;  	struct radeon_mode_info *minfo = &rdev->mode_info; -	uint32_t *value_ptr; -	uint32_t value; +	uint32_t value, *value_ptr; +	uint64_t value64, *value_ptr64;  	struct drm_crtc *crtc;  	int i, found; -	info = data; +	/* TIMESTAMP is a 64-bit value, needs special handling. */ +	if (info->request == RADEON_INFO_TIMESTAMP) { +		if (rdev->family >= CHIP_R600) { +			value_ptr64 = (uint64_t*)((unsigned long)info->value); +			if (rdev->family >= CHIP_TAHITI) { +				value64 = si_get_gpu_clock(rdev); +			} else { +				value64 = r600_get_gpu_clock(rdev); +			} + +			if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) { +				DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); +				return -EFAULT; +			} +			return 0; +		} else { +			DRM_DEBUG_KMS("timestamp is r6xx+ only!\n"); +			return -EINVAL; +		} +	} +  	value_ptr = (uint32_t *)((unsigned long)info->value); -	if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) +	if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) { +		DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);  		return -EFAULT; +	}  	switch (info->request) {  	case RADEON_INFO_DEVICE_ID: @@ -337,7 +360,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  		return -EINVAL;  	}  	if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { -		DRM_ERROR("copy_to_user\n"); +		DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);  		return -EFAULT;  	}  	return 0; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index d5fd615897e..94b4a1c1289 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,  static void radeon_crtc_prepare(struct drm_crtc *crtc)  { +	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);  	struct drm_device *dev = crtc->dev;  	struct drm_crtc *crtci; +	radeon_crtc->in_mode_set = true;  	/*  	* The hardware wedges sometimes if you reconfigure one CRTC  	* whilst another is running (see fdo bug #24611). @@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc)  static void radeon_crtc_commit(struct drm_crtc *crtc)  { +	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);  	struct drm_device *dev = crtc->dev;  	struct drm_crtc *crtci; @@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)  		if (crtci->enabled)  			radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);  	} +	radeon_crtc->in_mode_set = false;  }  static const struct drm_crtc_helper_funcs legacy_helper_funcs = { diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index f380d59c576..d56978949f3 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -275,6 +275,7 @@ struct radeon_crtc {  	u16 lut_r[256], lut_g[256], lut_b[256];  	bool enabled;  	bool can_tile; +	bool in_mode_set;  	uint32_t crtc_offset;  	struct drm_gem_object *cursor_bo;  	uint64_t cursor_addr; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 1f1a4c803c1..9024e722283 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -52,11 +52,7 @@ void radeon_bo_clear_va(struct radeon_bo *bo)  	list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) {  		/* remove from all vm address space */ -		mutex_lock(&bo_va->vm->mutex); -		list_del(&bo_va->vm_list); -		mutex_unlock(&bo_va->vm->mutex); -		list_del(&bo_va->bo_list); -		kfree(bo_va); +		radeon_vm_bo_rmv(bo->rdev, bo_va->vm, bo);  	}  } @@ -136,6 +132,7 @@ int radeon_bo_create(struct radeon_device *rdev,  	acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,  				       sizeof(struct radeon_bo)); +retry:  	bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);  	if (bo == NULL)  		return -ENOMEM; @@ -149,8 +146,6 @@ int radeon_bo_create(struct radeon_device *rdev,  	bo->surface_reg = -1;  	INIT_LIST_HEAD(&bo->list);  	INIT_LIST_HEAD(&bo->va); - -retry:  	radeon_ttm_placement_from_domain(bo, domain);  	/* Kernel allocation are uninterruptible */  	down_read(&rdev->pm.mclk_lock); diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index ec79b375043..43c431a2686 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -706,6 +706,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig  	if (radeon_debugfs_ring_init(rdev, ring)) {  		DRM_ERROR("Failed to register debugfs file for rings !\n");  	} +	radeon_ring_lockup_update(ring);  	return 0;  } diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 5e659b034d9..f93e45d869f 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -744,14 +744,6 @@ r600 0x9400  0x00028C38 CB_CLRCMP_DST  0x00028C3C CB_CLRCMP_MSK  0x00028C34 CB_CLRCMP_SRC -0x00028100 CB_COLOR0_MASK -0x00028104 CB_COLOR1_MASK -0x00028108 CB_COLOR2_MASK -0x0002810C CB_COLOR3_MASK -0x00028110 CB_COLOR4_MASK -0x00028114 CB_COLOR5_MASK -0x00028118 CB_COLOR6_MASK -0x0002811C CB_COLOR7_MASK  0x00028808 CB_COLOR_CONTROL  0x0002842C CB_FOG_BLUE  0x00028428 CB_FOG_GREEN diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index a12fbcc8ccb..aa8ef491ef3 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -281,12 +281,8 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev)  void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)  { -	save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL); -	save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL);  	save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL);  	save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); -	save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL); -	save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL);  	/* Stop all video */  	WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); @@ -311,15 +307,6 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)  	/* Unlock host access */  	WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);  	mdelay(1); -	/* Restore video state */ -	WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); -	WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); -	WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); -	WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); -	WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control); -	WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control); -	WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); -	WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);  	WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);  } diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index c053f819377..0139e227e3c 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1639,11 +1639,19 @@ static void si_gpu_init(struct radeon_device *rdev)  		/* XXX what about 12? */  		rdev->config.si.tile_config |= (3 << 0);  		break; -	} -	if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) -		rdev->config.si.tile_config |= 1 << 4; -	else +	}	 +	switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { +	case 0: /* four banks */  		rdev->config.si.tile_config |= 0 << 4; +		break; +	case 1: /* eight banks */ +		rdev->config.si.tile_config |= 1 << 4; +		break; +	case 2: /* sixteen banks */ +	default: +		rdev->config.si.tile_config |= 2 << 4; +		break; +	}  	rdev->config.si.tile_config |=  		((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;  	rdev->config.si.tile_config |= @@ -3960,3 +3968,22 @@ void si_fini(struct radeon_device *rdev)  	rdev->bios = NULL;  } +/** + * si_get_gpu_clock - return GPU clock counter snapshot + * + * @rdev: radeon_device pointer + * + * Fetches a GPU clock counter snapshot (SI). + * Returns the 64 bit clock counter snapshot. + */ +uint64_t si_get_gpu_clock(struct radeon_device *rdev) +{ +	uint64_t clock; + +	mutex_lock(&rdev->gpu_clock_mutex); +	WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); +	clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | +	        ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); +	mutex_unlock(&rdev->gpu_clock_mutex); +	return clock; +} diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 7869089e876..ef4815c27b1 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -698,6 +698,9 @@  #define RLC_UCODE_ADDR                                    0xC32C  #define RLC_UCODE_DATA                                    0xC330 +#define RLC_GPU_CLOCK_COUNT_LSB                           0xC338 +#define RLC_GPU_CLOCK_COUNT_MSB                           0xC33C +#define RLC_CAPTURE_GPU_CLOCK_COUNT                       0xC340  #define RLC_MC_CNTL                                       0xC344  #define RLC_UCODE_CNTL                                    0xC348 diff --git a/drivers/gpu/drm/udl/Kconfig b/drivers/gpu/drm/udl/Kconfig index 0b5e096d39a..56e0bf31d42 100644 --- a/drivers/gpu/drm/udl/Kconfig +++ b/drivers/gpu/drm/udl/Kconfig @@ -1,6 +1,7 @@  config DRM_UDL  	tristate "DisplayLink"  	depends on DRM && EXPERIMENTAL +	depends on USB_ARCH_HAS_HCD  	select DRM_USB  	select FB_SYS_FILLRECT  	select FB_SYS_COPYAREA diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 7bd65bdd15a..291ecc14558 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -308,7 +308,7 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,  	/* need to attach */  	attach = dma_buf_attach(dma_buf, dev->dev);  	if (IS_ERR(attach)) -		return ERR_PTR(PTR_ERR(attach)); +		return ERR_CAST(attach);  	sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);  	if (IS_ERR(sg)) { diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index f5dd89e891d..9159d48d1df 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -354,8 +354,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc,  static void udl_crtc_disable(struct drm_crtc *crtc)  { - - +	udl_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);  }  static void udl_crtc_destroy(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 6b0078ffa76..c50724bd30f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1688,15 +1688,19 @@ int vmw_du_page_flip(struct drm_crtc *crtc,  	struct vmw_private *dev_priv = vmw_priv(crtc->dev);  	struct drm_framebuffer *old_fb = crtc->fb;  	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); -	struct drm_file *file_priv = event->base.file_priv; +	struct drm_file *file_priv ;  	struct vmw_fence_obj *fence = NULL;  	struct drm_clip_rect clips;  	int ret; +	if (event == NULL) +		return -EINVAL; +  	/* require ScreenObject support for page flipping */  	if (!dev_priv->sou_priv)  		return -ENOSYS; +	file_priv = event->base.file_priv;  	if (!vmw_kms_screen_object_flippable(dev_priv, crtc))  		return -EINVAL; diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 5b3c7d135dc..e25cf31faab 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -70,27 +70,12 @@ static struct vgasr_priv vgasr_priv = {  	.clients = LIST_HEAD_INIT(vgasr_priv.clients),  }; -int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) -{ -	mutex_lock(&vgasr_mutex); -	if (vgasr_priv.handler) { -		mutex_unlock(&vgasr_mutex); -		return -EINVAL; -	} - -	vgasr_priv.handler = handler; -	mutex_unlock(&vgasr_mutex); -	return 0; -} -EXPORT_SYMBOL(vga_switcheroo_register_handler); - -void vga_switcheroo_unregister_handler(void) +static bool vga_switcheroo_ready(void)  { -	mutex_lock(&vgasr_mutex); -	vgasr_priv.handler = NULL; -	mutex_unlock(&vgasr_mutex); +	/* we're ready if we get two clients + handler */ +	return !vgasr_priv.active && +	       vgasr_priv.registered_clients == 2 && vgasr_priv.handler;  } -EXPORT_SYMBOL(vga_switcheroo_unregister_handler);  static void vga_switcheroo_enable(void)  { @@ -98,7 +83,8 @@ static void vga_switcheroo_enable(void)  	struct vga_switcheroo_client *client;  	/* call the handler to init */ -	vgasr_priv.handler->init(); +	if (vgasr_priv.handler->init) +		vgasr_priv.handler->init();  	list_for_each_entry(client, &vgasr_priv.clients, list) {  		if (client->id != -1) @@ -113,6 +99,37 @@ static void vga_switcheroo_enable(void)  	vgasr_priv.active = true;  } +int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler) +{ +	mutex_lock(&vgasr_mutex); +	if (vgasr_priv.handler) { +		mutex_unlock(&vgasr_mutex); +		return -EINVAL; +	} + +	vgasr_priv.handler = handler; +	if (vga_switcheroo_ready()) { +		printk(KERN_INFO "vga_switcheroo: enabled\n"); +		vga_switcheroo_enable(); +	} +	mutex_unlock(&vgasr_mutex); +	return 0; +} +EXPORT_SYMBOL(vga_switcheroo_register_handler); + +void vga_switcheroo_unregister_handler(void) +{ +	mutex_lock(&vgasr_mutex); +	vgasr_priv.handler = NULL; +	if (vgasr_priv.active) { +		pr_info("vga_switcheroo: disabled\n"); +		vga_switcheroo_debugfs_fini(&vgasr_priv); +		vgasr_priv.active = false; +	} +	mutex_unlock(&vgasr_mutex); +} +EXPORT_SYMBOL(vga_switcheroo_unregister_handler); +  static int register_client(struct pci_dev *pdev,  			   const struct vga_switcheroo_client_ops *ops,  			   int id, bool active) @@ -134,9 +151,7 @@ static int register_client(struct pci_dev *pdev,  	if (client_is_vga(client))  		vgasr_priv.registered_clients++; -	/* if we get two clients + handler */ -	if (!vgasr_priv.active && -	    vgasr_priv.registered_clients == 2 && vgasr_priv.handler) { +	if (vga_switcheroo_ready()) {  		printk(KERN_INFO "vga_switcheroo: enabled\n");  		vga_switcheroo_enable();  	} diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index faa16f80db9..0fa356fe82c 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -196,7 +196,7 @@ struct tjmax {  	int tjmax;  }; -static struct tjmax __cpuinitconst tjmax_table[] = { +static const struct tjmax __cpuinitconst tjmax_table[] = {  	{ "CPU D410", 100000 },  	{ "CPU D425", 100000 },  	{ "CPU D510", 100000 }, diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index ab4825205a9..5b1a6a66644 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -1206,7 +1206,7 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,  	int err = -ENODEV;  	u16 val; -	static const __initdata char *names[] = { +	static __initconst char *const names[] = {  		"W83627HF",  		"W83627THF",  		"W83697HF", diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c index aedb94f34bf..dae3ddfe761 100644 --- a/drivers/i2c/busses/i2c-diolan-u2c.c +++ b/drivers/i2c/busses/i2c-diolan-u2c.c @@ -405,6 +405,7 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,  			}  		}  	} +	ret = num;  abort:  	sret = diolan_i2c_stop(dev);  	if (sret < 0 && ret >= 0) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 5e6f1eed4f8..61b00edacb0 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -350,10 +350,6 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev)  	i2c_clk = clk_get_rate(dev->clk); -	/* fallback to std. mode if machine has not provided it */ -	if (dev->cfg.clk_freq == 0) -		dev->cfg.clk_freq = 100000; -  	/*  	 * The spec says, in case of std. mode the divider is  	 * 2 whereas it is 3 for fast and fastplus mode of @@ -911,20 +907,32 @@ static const struct i2c_algorithm nmk_i2c_algo = {  	.functionality	= nmk_i2c_functionality  }; +static struct nmk_i2c_controller u8500_i2c = { +	/* +	 * Slave data setup time; 250ns, 100ns, and 10ns, which +	 * is 14, 6 and 2 respectively for a 48Mhz i2c clock. +	 */ +	.slsu           = 0xe, +	.tft            = 1,      /* Tx FIFO threshold */ +	.rft            = 8,      /* Rx FIFO threshold */ +	.clk_freq       = 400000, /* fast mode operation */ +	.timeout        = 200,    /* Slave response timeout(ms) */ +	.sm             = I2C_FREQ_MODE_FAST, +}; +  static atomic_t adapter_id = ATOMIC_INIT(0);  static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)  {  	int ret = 0; -	struct nmk_i2c_controller *pdata = -			adev->dev.platform_data; +	struct nmk_i2c_controller *pdata = adev->dev.platform_data;  	struct nmk_i2c_dev	*dev;  	struct i2c_adapter *adap; -	if (!pdata) { -		dev_warn(&adev->dev, "no platform data\n"); -		return -ENODEV; -	} +	if (!pdata) +		/* No i2c configuration found, using the default. */ +		pdata = &u8500_i2c; +  	dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL);  	if (!dev) {  		dev_err(&adev->dev, "cannot allocate memory\n"); diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 6849635b268..5d19a49803c 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -584,7 +584,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)  	r = pm_runtime_get_sync(dev->dev);  	if (IS_ERR_VALUE(r)) -		return r; +		goto out;  	r = omap_i2c_wait_for_bb(dev);  	if (r < 0) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 66eb53fac20..9a08c57bc93 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -712,7 +712,7 @@ static int __devexit tegra_i2c_remove(struct platform_device *pdev)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int tegra_i2c_suspend(struct device *dev)  {  	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index f559088869f..e8726177d10 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -606,8 +606,9 @@ static int __init intel_idle_init(void)  	intel_idle_cpuidle_driver_init();  	retval = cpuidle_register_driver(&intel_idle_driver);  	if (retval) { +		struct cpuidle_driver *drv = cpuidle_get_driver();  		printk(KERN_DEBUG PREFIX "intel_idle yielding to %s", -			cpuidle_get_driver()->name); +			drv ? drv->name : "none");  		return retval;  	} diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 59fbb3ae40e..e35bb8f6fe7 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -129,7 +129,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)  {  	struct adf4350_platform_data *pdata = st->pdata;  	u64 tmp; -	u32 div_gcd, prescaler; +	u32 div_gcd, prescaler, chspc;  	u16 mdiv, r_cnt = 0;  	u8 band_sel_div; @@ -158,14 +158,20 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)  	if (pdata->ref_div_factor)  		r_cnt = pdata->ref_div_factor - 1; -	do  { -		r_cnt = adf4350_tune_r_cnt(st, r_cnt); +	chspc = st->chspc; -		st->r1_mod = st->fpfd / st->chspc; -		while (st->r1_mod > ADF4350_MAX_MODULUS) { -			r_cnt = adf4350_tune_r_cnt(st, r_cnt); -			st->r1_mod = st->fpfd / st->chspc; -		} +	do  { +		do { +			do { +				r_cnt = adf4350_tune_r_cnt(st, r_cnt); +				st->r1_mod = st->fpfd / chspc; +				if (r_cnt > ADF4350_MAX_R_CNT) { +					/* try higher spacing values */ +					chspc++; +					r_cnt = 0; +				} +			} while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); +		} while (r_cnt == 0);  		tmp = freq * (u64)st->r1_mod + (st->fpfd > 1);  		do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ @@ -194,7 +200,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq)  	st->regs[ADF4350_REG0] = ADF4350_REG0_INT(st->r0_int) |  				 ADF4350_REG0_FRACT(st->r0_fract); -	st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(0) | +	st->regs[ADF4350_REG1] = ADF4350_REG1_PHASE(1) |  				 ADF4350_REG1_MOD(st->r1_mod) |  				 prescaler; diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c index 1cbb449b319..9a99f43094f 100644 --- a/drivers/iio/light/adjd_s311.c +++ b/drivers/iio/light/adjd_s311.c @@ -271,9 +271,10 @@ static int adjd_s311_update_scan_mode(struct iio_dev *indio_dev,  	const unsigned long *scan_mask)  {  	struct adjd_s311_data *data = iio_priv(indio_dev); -	data->buffer = krealloc(data->buffer, indio_dev->scan_bytes, -				GFP_KERNEL); -	if (!data->buffer) + +	kfree(data->buffer); +	data->buffer = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); +	if (data->buffer == NULL)  		return -ENOMEM;  	return 0; diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c index c3e7bac1312..e45712a921c 100644 --- a/drivers/iio/light/lm3533-als.c +++ b/drivers/iio/light/lm3533-als.c @@ -404,7 +404,7 @@ out:  	return ret;  } -static int show_thresh_either_en(struct device *dev, +static ssize_t show_thresh_either_en(struct device *dev,  					struct device_attribute *attr,  					char *buf)  { @@ -424,7 +424,7 @@ static int show_thresh_either_en(struct device *dev,  	return scnprintf(buf, PAGE_SIZE, "%u\n", enable);  } -static int store_thresh_either_en(struct device *dev, +static ssize_t store_thresh_either_en(struct device *dev,  					struct device_attribute *attr,  					const char *buf, size_t len)  { diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 6bf85042289..055ed59838d 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -267,6 +267,7 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,  	if (!uevent)  		return event->event == RDMA_CM_EVENT_CONNECT_REQUEST; +	mutex_lock(&ctx->file->mut);  	uevent->cm_id = cm_id;  	ucma_set_event_context(ctx, event, uevent);  	uevent->resp.event = event->event; @@ -277,7 +278,6 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,  		ucma_copy_conn_event(&uevent->resp.param.conn,  				     &event->param.conn); -	mutex_lock(&ctx->file->mut);  	if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) {  		if (!ctx->backlog) {  			ret = -ENOMEM; diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 8c81992fa6d..e4a73158fc7 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -439,7 +439,7 @@ static int c2_rnic_close(struct c2_dev *c2dev)  /*   * Called by c2_probe to initialize the RNIC. This principally - * involves initalizing the various limits and resouce pools that + * involves initializing the various limits and resource pools that   * comprise the RNIC instance.   */  int __devinit c2_rnic_init(struct c2_dev *c2dev) diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index 77b6b182778..aaf88ef9409 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -1680,7 +1680,7 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)   * T3A does 3 things when a TERM is received:   * 1) send up a CPL_RDMA_TERMINATE message with the TERM packet   * 2) generate an async event on the QP with the TERMINATE opcode - * 3) post a TERMINATE opcde cqe into the associated CQ. + * 3) post a TERMINATE opcode cqe into the associated CQ.   *   * For (1), we save the message in the qp for later consumer consumption.   * For (2), we move the QP into TERMINATE, post a QP event and disconnect. diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index c27141fef1a..9c2ae7efd00 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -125,6 +125,7 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl)  {  	struct ib_ah *new_ah;  	struct ib_ah_attr ah_attr; +	unsigned long flags;  	if (!dev->send_agent[port_num - 1][0])  		return; @@ -139,11 +140,11 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl)  	if (IS_ERR(new_ah))  		return; -	spin_lock(&dev->sm_lock); +	spin_lock_irqsave(&dev->sm_lock, flags);  	if (dev->sm_ah[port_num - 1])  		ib_destroy_ah(dev->sm_ah[port_num - 1]);  	dev->sm_ah[port_num - 1] = new_ah; -	spin_unlock(&dev->sm_lock); +	spin_unlock_irqrestore(&dev->sm_lock, flags);  }  /* @@ -197,13 +198,15 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad,  static void node_desc_override(struct ib_device *dev,  			       struct ib_mad *mad)  { +	unsigned long flags; +  	if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED ||  	     mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) &&  	    mad->mad_hdr.method == IB_MGMT_METHOD_GET_RESP &&  	    mad->mad_hdr.attr_id == IB_SMP_ATTR_NODE_DESC) { -		spin_lock(&to_mdev(dev)->sm_lock); +		spin_lock_irqsave(&to_mdev(dev)->sm_lock, flags);  		memcpy(((struct ib_smp *) mad)->data, dev->node_desc, 64); -		spin_unlock(&to_mdev(dev)->sm_lock); +		spin_unlock_irqrestore(&to_mdev(dev)->sm_lock, flags);  	}  } @@ -213,6 +216,7 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma  	struct ib_mad_send_buf *send_buf;  	struct ib_mad_agent *agent = dev->send_agent[port_num - 1][qpn];  	int ret; +	unsigned long flags;  	if (agent) {  		send_buf = ib_create_send_mad(agent, qpn, 0, 0, IB_MGMT_MAD_HDR, @@ -225,13 +229,13 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma  		 * wrong following the IB spec strictly, but we know  		 * it's OK for our devices).  		 */ -		spin_lock(&dev->sm_lock); +		spin_lock_irqsave(&dev->sm_lock, flags);  		memcpy(send_buf->mad, mad, sizeof *mad);  		if ((send_buf->ah = dev->sm_ah[port_num - 1]))  			ret = ib_post_send_mad(send_buf, NULL);  		else  			ret = -EINVAL; -		spin_unlock(&dev->sm_lock); +		spin_unlock_irqrestore(&dev->sm_lock, flags);  		if (ret)  			ib_free_send_mad(send_buf); diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index fe2088cfa6e..cc05579ebce 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -423,6 +423,7 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,  				 struct ib_device_modify *props)  {  	struct mlx4_cmd_mailbox *mailbox; +	unsigned long flags;  	if (mask & ~IB_DEVICE_MODIFY_NODE_DESC)  		return -EOPNOTSUPP; @@ -430,9 +431,9 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,  	if (!(mask & IB_DEVICE_MODIFY_NODE_DESC))  		return 0; -	spin_lock(&to_mdev(ibdev)->sm_lock); +	spin_lock_irqsave(&to_mdev(ibdev)->sm_lock, flags);  	memcpy(ibdev->node_desc, props->node_desc, 64); -	spin_unlock(&to_mdev(ibdev)->sm_lock); +	spin_unlock_irqrestore(&to_mdev(ibdev)->sm_lock, flags);  	/*  	 * If possible, pass node desc to FW, so it can generate diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index a6d8ea060ea..f585eddef4b 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1407,6 +1407,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,  	struct mlx4_wqe_mlx_seg *mlx = wqe;  	struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;  	struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah); +	struct net_device *ndev;  	union ib_gid sgid;  	u16 pkey;  	int send_size; @@ -1483,7 +1484,10 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,  		memcpy(sqp->ud_header.eth.dmac_h, ah->av.eth.mac, 6);  		/* FIXME: cache smac value? */ -		smac = to_mdev(sqp->qp.ibqp.device)->iboe.netdevs[sqp->qp.port - 1]->dev_addr; +		ndev = to_mdev(sqp->qp.ibqp.device)->iboe.netdevs[sqp->qp.port - 1]; +		if (!ndev) +			return -ENODEV; +		smac = ndev->dev_addr;  		memcpy(sqp->ud_header.eth.smac_h, smac, 6);  		if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6))  			mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK); diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index 5a044526e4f..c4e0131f1b5 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -161,7 +161,7 @@ static void ocrdma_add_default_sgid(struct ocrdma_dev *dev)  	ocrdma_get_guid(dev, &sgid->raw[8]);  } -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +#if IS_ENABLED(CONFIG_VLAN_8021Q)  static void ocrdma_add_vlan_sgids(struct ocrdma_dev *dev)  {  	struct net_device *netdev, *tmp; @@ -202,14 +202,13 @@ static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev)  	return 0;  } -#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_VLAN_8021Q) +#if IS_ENABLED(CONFIG_IPV6)  static int ocrdma_inet6addr_event(struct notifier_block *notifier,  				  unsigned long event, void *ptr)  {  	struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; -	struct net_device *event_netdev = ifa->idev->dev; -	struct net_device *netdev = NULL; +	struct net_device *netdev = ifa->idev->dev;  	struct ib_event gid_event;  	struct ocrdma_dev *dev;  	bool found = false; @@ -217,11 +216,12 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier,  	bool is_vlan = false;  	u16 vid = 0; -	netdev = vlan_dev_real_dev(event_netdev); -	if (netdev != event_netdev) { -		is_vlan = true; -		vid = vlan_dev_vlan_id(event_netdev); +	is_vlan = netdev->priv_flags & IFF_802_1Q_VLAN; +	if (is_vlan) { +		vid = vlan_dev_vlan_id(netdev); +		netdev = vlan_dev_real_dev(netdev);  	} +  	rcu_read_lock();  	list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) {  		if (dev->nic_info.netdev == netdev) { diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 0d7280af99b..3f6b21e9dc1 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -6346,8 +6346,10 @@ static int qib_init_7322_variables(struct qib_devdata *dd)  			dd->piobcnt4k * dd->align4k;  		dd->piovl15base	= ioremap_nocache(vl15off,  						  NUM_VL15_BUFS * dd->align4k); -		if (!dd->piovl15base) +		if (!dd->piovl15base) { +			ret = -ENOMEM;  			goto bail; +		}  	}  	qib_7322_set_baseaddrs(dd); /* set chip access pointers now */ diff --git a/drivers/infiniband/hw/qib/qib_sd7220.c b/drivers/infiniband/hw/qib/qib_sd7220.c index a322d5171a2..50a8a0d4fe6 100644 --- a/drivers/infiniband/hw/qib/qib_sd7220.c +++ b/drivers/infiniband/hw/qib/qib_sd7220.c @@ -372,7 +372,7 @@ static void qib_sd_trimdone_monitor(struct qib_devdata *dd,  		/* Read CTRL reg for each channel to check TRIMDONE */  		if (baduns & (1 << chn)) {  			qib_dev_err(dd, -				"Reseting TRIMDONE on chn %d (%s)\n", +				"Resetting TRIMDONE on chn %d (%s)\n",  				chn, where);  			ret = qib_sd7220_reg_mod(dd, IB_7220_SERDES,  				IB_CTRL2(chn), 0x10, 0x10); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 95ecf4eadf5..24683fda8e2 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -1271,12 +1271,15 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path  void ipoib_cm_destroy_tx(struct ipoib_cm_tx *tx)  {  	struct ipoib_dev_priv *priv = netdev_priv(tx->dev); +	unsigned long flags;  	if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) { +		spin_lock_irqsave(&priv->lock, flags);  		list_move(&tx->list, &priv->cm.reap_list);  		queue_work(ipoib_workqueue, &priv->cm.reap_task);  		ipoib_dbg(priv, "Reap connection for gid %pI6\n",  			  tx->neigh->daddr + 4);  		tx->neigh = NULL; +		spin_unlock_irqrestore(&priv->lock, flags);  	}  } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 97920b77a5d..3e2085a3ee4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1052,7 +1052,7 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh)  	for (n = rcu_dereference_protected(*np,  					    lockdep_is_held(&ntbl->rwlock));  	     n != NULL; -	     n = rcu_dereference_protected(neigh->hnext, +	     n = rcu_dereference_protected(*np,  					lockdep_is_held(&ntbl->rwlock))) {  		if (n == neigh) {  			/* found */ diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index bcbf22ee0aa..1b5b0c73005 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -586,24 +586,62 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,  			scmnd->sc_data_direction);  } -static void srp_remove_req(struct srp_target_port *target, -			   struct srp_request *req, s32 req_lim_delta) +/** + * srp_claim_req - Take ownership of the scmnd associated with a request. + * @target: SRP target port. + * @req: SRP request. + * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take + *         ownership of @req->scmnd if it equals @scmnd. + * + * Return value: + * Either NULL or a pointer to the SCSI command the caller became owner of. + */ +static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target, +				       struct srp_request *req, +				       struct scsi_cmnd *scmnd) +{ +	unsigned long flags; + +	spin_lock_irqsave(&target->lock, flags); +	if (!scmnd) { +		scmnd = req->scmnd; +		req->scmnd = NULL; +	} else if (req->scmnd == scmnd) { +		req->scmnd = NULL; +	} else { +		scmnd = NULL; +	} +	spin_unlock_irqrestore(&target->lock, flags); + +	return scmnd; +} + +/** + * srp_free_req() - Unmap data and add request to the free request list. + */ +static void srp_free_req(struct srp_target_port *target, +			 struct srp_request *req, struct scsi_cmnd *scmnd, +			 s32 req_lim_delta)  {  	unsigned long flags; -	srp_unmap_data(req->scmnd, target, req); +	srp_unmap_data(scmnd, target, req); +  	spin_lock_irqsave(&target->lock, flags);  	target->req_lim += req_lim_delta; -	req->scmnd = NULL;  	list_add_tail(&req->list, &target->free_reqs);  	spin_unlock_irqrestore(&target->lock, flags);  }  static void srp_reset_req(struct srp_target_port *target, struct srp_request *req)  { -	req->scmnd->result = DID_RESET << 16; -	req->scmnd->scsi_done(req->scmnd); -	srp_remove_req(target, req, 0); +	struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); + +	if (scmnd) { +		scmnd->result = DID_RESET << 16; +		scmnd->scsi_done(scmnd); +		srp_free_req(target, req, scmnd, 0); +	}  }  static int srp_reconnect_target(struct srp_target_port *target) @@ -1073,11 +1111,18 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)  		complete(&target->tsk_mgmt_done);  	} else {  		req = &target->req_ring[rsp->tag]; -		scmnd = req->scmnd; -		if (!scmnd) +		scmnd = srp_claim_req(target, req, NULL); +		if (!scmnd) {  			shost_printk(KERN_ERR, target->scsi_host,  				     "Null scmnd for RSP w/tag %016llx\n",  				     (unsigned long long) rsp->tag); + +			spin_lock_irqsave(&target->lock, flags); +			target->req_lim += be32_to_cpu(rsp->req_lim_delta); +			spin_unlock_irqrestore(&target->lock, flags); + +			return; +		}  		scmnd->result = rsp->status;  		if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { @@ -1092,7 +1137,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)  		else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER))  			scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); -		srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta)); +		srp_free_req(target, req, scmnd, +			     be32_to_cpu(rsp->req_lim_delta)); +  		scmnd->host_scribble = NULL;  		scmnd->scsi_done(scmnd);  	} @@ -1631,25 +1678,17 @@ static int srp_abort(struct scsi_cmnd *scmnd)  {  	struct srp_target_port *target = host_to_target(scmnd->device->host);  	struct srp_request *req = (struct srp_request *) scmnd->host_scribble; -	int ret = SUCCESS;  	shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); -	if (!req || target->qp_in_error) +	if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd))  		return FAILED; -	if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, -			      SRP_TSK_ABORT_TASK)) -		return FAILED; - -	if (req->scmnd) { -		if (!target->tsk_mgmt_status) { -			srp_remove_req(target, req, 0); -			scmnd->result = DID_ABORT << 16; -		} else -			ret = FAILED; -	} +	srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, +			  SRP_TSK_ABORT_TASK); +	srp_free_req(target, req, scmnd, 0); +	scmnd->result = DID_ABORT << 16; -	return ret; +	return SUCCESS;  }  static int srp_reset_device(struct scsi_cmnd *scmnd) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 7a0ce8d4288..9e1449f8c6a 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1469,7 +1469,7 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,   *   * XXX: what is now target_execute_cmd used to be asynchronous, and unmapping   * the data that has been transferred via IB RDMA had to be postponed until the - * check_stop_free() callback.  None of this is nessecary anymore and needs to + * check_stop_free() callback.  None of this is necessary anymore and needs to   * be cleaned up.   */  static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch, diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 503c7096ed3..908407efc67 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -48,7 +48,7 @@ struct eeti_ts_priv {  	struct input_dev *input;  	struct work_struct work;  	struct mutex mutex; -	int irq, irq_active_high; +	int irq_gpio, irq, irq_active_high;  };  #define EETI_TS_BITDEPTH	(11) @@ -62,7 +62,7 @@ struct eeti_ts_priv {  static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv)  { -	return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; +	return gpio_get_value(priv->irq_gpio) == priv->irq_active_high;  }  static void eeti_ts_read(struct work_struct *work) @@ -157,7 +157,7 @@ static void eeti_ts_close(struct input_dev *dev)  static int __devinit eeti_ts_probe(struct i2c_client *client,  				   const struct i2c_device_id *idp)  { -	struct eeti_ts_platform_data *pdata; +	struct eeti_ts_platform_data *pdata = client->dev.platform_data;  	struct eeti_ts_priv *priv;  	struct input_dev *input;  	unsigned int irq_flags; @@ -199,9 +199,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,  	priv->client = client;  	priv->input = input; -	priv->irq = client->irq; +	priv->irq_gpio = pdata->irq_gpio; +	priv->irq = gpio_to_irq(pdata->irq_gpio); -	pdata = client->dev.platform_data; +	err = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); +	if (err < 0) +		goto err1;  	if (pdata)  		priv->irq_active_high = pdata->irq_active_high; @@ -215,13 +218,13 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,  	err = input_register_device(input);  	if (err) -		goto err1; +		goto err2;  	err = request_irq(priv->irq, eeti_ts_isr, irq_flags,  			  client->name, priv);  	if (err) {  		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); -		goto err2; +		goto err3;  	}  	/* @@ -233,9 +236,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,  	device_init_wakeup(&client->dev, 0);  	return 0; -err2: +err3:  	input_unregister_device(input);  	input = NULL; /* so we dont try to free it below */ +err2: +	gpio_free(pdata->irq_gpio);  err1:  	input_free_device(input);  	kfree(priv); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 6d1cbdfc9b2..b64502dfa9f 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -296,8 +296,13 @@ static int iommu_init_device(struct device *dev)  	} else  		dma_pdev = pci_dev_get(pdev); +	/* Account for quirked devices */  	swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); +	/* +	 * If it's a multifunction device that does not support our +	 * required ACS flags, add to the same group as function 0. +	 */  	if (dma_pdev->multifunction &&  	    !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS))  		swap_pci_ref(&dma_pdev, @@ -305,14 +310,28 @@ static int iommu_init_device(struct device *dev)  					  PCI_DEVFN(PCI_SLOT(dma_pdev->devfn),  					  0))); +	/* +	 * Devices on the root bus go through the iommu.  If that's not us, +	 * find the next upstream device and test ACS up to the root bus. +	 * Finding the next device may require skipping virtual buses. +	 */  	while (!pci_is_root_bus(dma_pdev->bus)) { -		if (pci_acs_path_enabled(dma_pdev->bus->self, -					 NULL, REQ_ACS_FLAGS)) +		struct pci_bus *bus = dma_pdev->bus; + +		while (!bus->self) { +			if (!pci_is_root_bus(bus)) +				bus = bus->parent; +			else +				goto root_bus; +		} + +		if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))  			break; -		swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); +		swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));  	} +root_bus:  	group = iommu_group_get(&dma_pdev->dev);  	pci_dev_put(dma_pdev);  	if (!group) { diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 500e7f15f5c..18a89b760aa 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1111,7 +1111,7 @@ static void print_iommu_info(void)  		if (iommu->cap & (1 << IOMMU_CAP_EFR)) {  			pr_info("AMD-Vi:  Extended features: "); -			for (i = 0; ARRAY_SIZE(feat_str); ++i) { +			for (i = 0; i < ARRAY_SIZE(feat_str); ++i) {  				if (iommu_feature(iommu, (1ULL << i)))  					pr_cont(" %s", feat_str[i]);  			} @@ -1131,9 +1131,6 @@ static int __init amd_iommu_init_pci(void)  			break;  	} -	/* Make sure ACS will be enabled */ -	pci_request_acs(); -  	ret = amd_iommu_init_devices();  	print_iommu_info(); @@ -1652,6 +1649,9 @@ static bool detect_ivrs(void)  	early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size); +	/* Make sure ACS will be enabled during PCI probe */ +	pci_request_acs(); +  	return true;  } diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 45350ff5e93..80bad32aa46 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -732,9 +732,9 @@ static int exynos_iommu_domain_init(struct iommu_domain *domain)  	spin_lock_init(&priv->pgtablelock);  	INIT_LIST_HEAD(&priv->clients); -	dom->geometry.aperture_start = 0; -	dom->geometry.aperture_end   = ~0UL; -	dom->geometry.force_aperture = true; +	domain->geometry.aperture_start = 0; +	domain->geometry.aperture_end   = ~0UL; +	domain->geometry.force_aperture = true;  	domain->priv = priv;  	return 0; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 7469b534664..2297ec193eb 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2008,6 +2008,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)  	if (!drhd) {  		printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n",  			pci_name(pdev)); +		free_domain_mem(domain);  		return NULL;  	}  	iommu = drhd->iommu; @@ -4124,8 +4125,13 @@ static int intel_iommu_add_device(struct device *dev)  	} else  		dma_pdev = pci_dev_get(pdev); +	/* Account for quirked devices */  	swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); +	/* +	 * If it's a multifunction device that does not support our +	 * required ACS flags, add to the same group as function 0. +	 */  	if (dma_pdev->multifunction &&  	    !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS))  		swap_pci_ref(&dma_pdev, @@ -4133,14 +4139,28 @@ static int intel_iommu_add_device(struct device *dev)  					  PCI_DEVFN(PCI_SLOT(dma_pdev->devfn),  					  0))); +	/* +	 * Devices on the root bus go through the iommu.  If that's not us, +	 * find the next upstream device and test ACS up to the root bus. +	 * Finding the next device may require skipping virtual buses. +	 */  	while (!pci_is_root_bus(dma_pdev->bus)) { -		if (pci_acs_path_enabled(dma_pdev->bus->self, -					 NULL, REQ_ACS_FLAGS)) +		struct pci_bus *bus = dma_pdev->bus; + +		while (!bus->self) { +			if (!pci_is_root_bus(bus)) +				bus = bus->parent; +			else +				goto root_bus; +		} + +		if (pci_acs_path_enabled(bus->self, NULL, REQ_ACS_FLAGS))  			break; -		swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); +		swap_pci_ref(&dma_pdev, pci_dev_get(bus->self));  	} +root_bus:  	group = iommu_group_get(&dma_pdev->dev);  	pci_dev_put(dma_pdev);  	if (!group) { diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index e0b18f3ae9a..af8904de1d4 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -736,6 +736,7 @@ int __init parse_ioapics_under_ir(void)  {  	struct dmar_drhd_unit *drhd;  	int ir_supported = 0; +	int ioapic_idx;  	for_each_drhd_unit(drhd) {  		struct intel_iommu *iommu = drhd->iommu; @@ -748,13 +749,20 @@ int __init parse_ioapics_under_ir(void)  		}  	} -	if (ir_supported && ir_ioapic_num != nr_ioapics) { -		printk(KERN_WARNING -		       "Not all IO-APIC's listed under remapping hardware\n"); -		return -1; +	if (!ir_supported) +		return 0; + +	for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { +		int ioapic_id = mpc_ioapic_id(ioapic_idx); +		if (!map_ioapic_to_ir(ioapic_id)) { +			pr_err(FW_BUG "ioapic %d has no mapping iommu, " +			       "interrupt remapping will be disabled\n", +			       ioapic_id); +			return -1; +		}  	} -	return ir_supported; +	return 1;  }  int __init ir_dev_scope_init(void) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 4ba325ab626..2a4bb36bc68 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -799,14 +799,14 @@ static void smmu_iommu_detach_dev(struct iommu_domain *domain,  			goto out;  		}  	} -	dev_err(smmu->dev, "Couldn't find %s\n", dev_name(c->dev)); +	dev_err(smmu->dev, "Couldn't find %s\n", dev_name(dev));  out:  	spin_unlock(&as->client_lock);  }  static int smmu_iommu_domain_init(struct iommu_domain *domain)  { -	int i, err = -ENODEV; +	int i, err = -EAGAIN;  	unsigned long flags;  	struct smmu_as *as;  	struct smmu_device *smmu = smmu_handle; @@ -814,11 +814,14 @@ static int smmu_iommu_domain_init(struct iommu_domain *domain)  	/* Look for a free AS with lock held */  	for  (i = 0; i < smmu->num_as; i++) {  		as = &smmu->as[i]; -		if (!as->pdir_page) { -			err = alloc_pdir(as); -			if (!err) -				goto found; -		} + +		if (as->pdir_page) +			continue; + +		err = alloc_pdir(as); +		if (!err) +			goto found; +  		if (err != -EAGAIN)  			break;  	} diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 5405ec644db..baf2686aa8e 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -16,7 +16,6 @@  #include <linux/sched.h>  #include "isdnloop.h" -static char *revision = "$Revision: 1.11.6.7 $";  static char *isdnloop_id = "loop0";  MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card"); @@ -1494,17 +1493,6 @@ isdnloop_addcard(char *id1)  static int __init  isdnloop_init(void)  { -	char *p; -	char rev[10]; - -	if ((p = strchr(revision, ':'))) { -		strcpy(rev, p + 1); -		p = strchr(rev, '$'); -		*p = 0; -	} else -		strcpy(rev, " ??? "); -	printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev); -  	if (isdnloop_id)  		return (isdnloop_addcard(isdnloop_id)); diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 0dc8abca140..949cabb88f1 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -2222,7 +2222,7 @@ create_l2(struct mISDNchannel *ch, u_int protocol, u_long options, int tei,  	InitWin(l2);  	l2->l2m.fsm = &l2fsm;  	if (test_bit(FLG_LAPB, &l2->flag) || -	    test_bit(FLG_PTP, &l2->flag) || +	    test_bit(FLG_FIXED_TEI, &l2->flag) ||  	    test_bit(FLG_LAPD_NET, &l2->flag))  		l2->l2m.state = ST_L2_4;  	else diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 6157cbbf411..363975b3c92 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -224,7 +224,7 @@ void led_trigger_event(struct led_trigger *trig,  		struct led_classdev *led_cdev;  		led_cdev = list_entry(entry, struct led_classdev, trig_list); -		led_set_brightness(led_cdev, brightness); +		__led_set_brightness(led_cdev, brightness);  	}  	read_unlock(&trig->leddev_list_lock);  } diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c index 53bd136f1ef..0ade6ebfc91 100644 --- a/drivers/leds/leds-lp8788.c +++ b/drivers/leds/leds-lp8788.c @@ -63,7 +63,7 @@ static int lp8788_led_init_device(struct lp8788_led *led,  	/* scale configuration */  	addr = LP8788_ISINK_CTRL;  	mask = 1 << (cfg->num + LP8788_ISINK_SCALE_OFFSET); -	val = cfg->scale << cfg->num; +	val = cfg->scale << (cfg->num + LP8788_ISINK_SCALE_OFFSET);  	ret = lp8788_update_bits(led->lp, addr, mask, val);  	if (ret)  		return ret; diff --git a/drivers/leds/leds-renesas-tpu.c b/drivers/leds/leds-renesas-tpu.c index 9ee12c28059..771ea067e68 100644 --- a/drivers/leds/leds-renesas-tpu.c +++ b/drivers/leds/leds-renesas-tpu.c @@ -247,7 +247,7 @@ static int __devinit r_tpu_probe(struct platform_device *pdev)  	if (!cfg) {  		dev_err(&pdev->dev, "missing platform data\n"); -		goto err0; +		return -ENODEV;  	}  	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); diff --git a/drivers/md/md.c b/drivers/md/md.c index fcd098794d3..3f6203a4c7e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1108,8 +1108,11 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor  			ret = 0;  	}  	rdev->sectors = rdev->sb_start; -	/* Limit to 4TB as metadata cannot record more than that */ -	if (rdev->sectors >= (2ULL << 32)) +	/* Limit to 4TB as metadata cannot record more than that. +	 * (not needed for Linear and RAID0 as metadata doesn't +	 * record this size) +	 */ +	if (rdev->sectors >= (2ULL << 32) && sb->level >= 1)  		rdev->sectors = (2ULL << 32) - 2;  	if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1) @@ -1400,7 +1403,7 @@ super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)  	/* Limit to 4TB as metadata cannot record more than that.  	 * 4TB == 2^32 KB, or 2*2^32 sectors.  	 */ -	if (num_sectors >= (2ULL << 32)) +	if (num_sectors >= (2ULL << 32) && rdev->mddev->level >= 1)  		num_sectors = (2ULL << 32) - 2;  	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,  		       rdev->sb_page); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index de5ed6fd880..1c2eb38f3c5 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -659,7 +659,11 @@ static int raid10_mergeable_bvec(struct request_queue *q,  		max = biovec->bv_len;  	if (mddev->merge_check_needed) { -		struct r10bio r10_bio; +		struct { +			struct r10bio r10_bio; +			struct r10dev devs[conf->copies]; +		} on_stack; +		struct r10bio *r10_bio = &on_stack.r10_bio;  		int s;  		if (conf->reshape_progress != MaxSector) {  			/* Cannot give any guidance during reshape */ @@ -667,18 +671,18 @@ static int raid10_mergeable_bvec(struct request_queue *q,  				return biovec->bv_len;  			return 0;  		} -		r10_bio.sector = sector; -		raid10_find_phys(conf, &r10_bio); +		r10_bio->sector = sector; +		raid10_find_phys(conf, r10_bio);  		rcu_read_lock();  		for (s = 0; s < conf->copies; s++) { -			int disk = r10_bio.devs[s].devnum; +			int disk = r10_bio->devs[s].devnum;  			struct md_rdev *rdev = rcu_dereference(  				conf->mirrors[disk].rdev);  			if (rdev && !test_bit(Faulty, &rdev->flags)) {  				struct request_queue *q =  					bdev_get_queue(rdev->bdev);  				if (q->merge_bvec_fn) { -					bvm->bi_sector = r10_bio.devs[s].addr +					bvm->bi_sector = r10_bio->devs[s].addr  						+ rdev->data_offset;  					bvm->bi_bdev = rdev->bdev;  					max = min(max, q->merge_bvec_fn( @@ -690,7 +694,7 @@ static int raid10_mergeable_bvec(struct request_queue *q,  				struct request_queue *q =  					bdev_get_queue(rdev->bdev);  				if (q->merge_bvec_fn) { -					bvm->bi_sector = r10_bio.devs[s].addr +					bvm->bi_sector = r10_bio->devs[s].addr  						+ rdev->data_offset;  					bvm->bi_bdev = rdev->bdev;  					max = min(max, q->merge_bvec_fn( @@ -4414,14 +4418,18 @@ static int handle_reshape_read_error(struct mddev *mddev,  {  	/* Use sync reads to get the blocks from somewhere else */  	int sectors = r10_bio->sectors; -	struct r10bio r10b;  	struct r10conf *conf = mddev->private; +	struct { +		struct r10bio r10_bio; +		struct r10dev devs[conf->copies]; +	} on_stack; +	struct r10bio *r10b = &on_stack.r10_bio;  	int slot = 0;  	int idx = 0;  	struct bio_vec *bvec = r10_bio->master_bio->bi_io_vec; -	r10b.sector = r10_bio->sector; -	__raid10_find_phys(&conf->prev, &r10b); +	r10b->sector = r10_bio->sector; +	__raid10_find_phys(&conf->prev, r10b);  	while (sectors) {  		int s = sectors; @@ -4432,7 +4440,7 @@ static int handle_reshape_read_error(struct mddev *mddev,  			s = PAGE_SIZE >> 9;  		while (!success) { -			int d = r10b.devs[slot].devnum; +			int d = r10b->devs[slot].devnum;  			struct md_rdev *rdev = conf->mirrors[d].rdev;  			sector_t addr;  			if (rdev == NULL || @@ -4440,7 +4448,7 @@ static int handle_reshape_read_error(struct mddev *mddev,  			    !test_bit(In_sync, &rdev->flags))  				goto failed; -			addr = r10b.devs[slot].addr + idx * PAGE_SIZE; +			addr = r10b->devs[slot].addr + idx * PAGE_SIZE;  			success = sync_page_io(rdev,  					       addr,  					       s << 9, diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 007c2c68dd8..1054cf60234 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h @@ -110,7 +110,7 @@ struct r10bio {  	 * We choose the number when they are allocated.  	 * We sometimes need an extra bio to write to the replacement.  	 */ -	struct { +	struct r10dev {  		struct bio	*bio;  		union {  			struct bio	*repl_bio; /* used for resync and diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 664e460f247..aac622200e9 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -481,7 +481,7 @@ static int smsusb_resume(struct usb_interface *intf)  	return 0;  } -static const struct usb_device_id smsusb_id_table[] __devinitconst = { +static const struct usb_device_id smsusb_id_table[] = {  	{ USB_DEVICE(0x187f, 0x0010),  		.driver_info = SMS1XXX_BOARD_SIANO_STELLAR },  	{ USB_DEVICE(0x187f, 0x0100), diff --git a/drivers/media/radio/radio-shark.c b/drivers/media/radio/radio-shark.c index d0b6bb50763..72ded29728b 100644 --- a/drivers/media/radio/radio-shark.c +++ b/drivers/media/radio/radio-shark.c @@ -35,6 +35,11 @@  #include <media/v4l2-device.h>  #include <sound/tea575x-tuner.h> +#if defined(CONFIG_LEDS_CLASS) || \ +    (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK_MODULE)) +#define SHARK_USE_LEDS 1 +#endif +  /*   * Version Information   */ @@ -56,44 +61,18 @@ MODULE_LICENSE("GPL");  enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS }; -static void shark_led_set_blue(struct led_classdev *led_cdev, -			       enum led_brightness value); -static void shark_led_set_blue_pulse(struct led_classdev *led_cdev, -				     enum led_brightness value); -static void shark_led_set_red(struct led_classdev *led_cdev, -			      enum led_brightness value); - -static const struct led_classdev shark_led_templates[NO_LEDS] = { -	[BLUE_LED] = { -		.name		= "%s:blue:", -		.brightness	= LED_OFF, -		.max_brightness = 127, -		.brightness_set = shark_led_set_blue, -	}, -	[BLUE_PULSE_LED] = { -		.name		= "%s:blue-pulse:", -		.brightness	= LED_OFF, -		.max_brightness = 255, -		.brightness_set = shark_led_set_blue_pulse, -	}, -	[RED_LED] = { -		.name		= "%s:red:", -		.brightness	= LED_OFF, -		.max_brightness = 1, -		.brightness_set = shark_led_set_red, -	}, -}; -  struct shark_device {  	struct usb_device *usbdev;  	struct v4l2_device v4l2_dev;  	struct snd_tea575x tea; +#ifdef SHARK_USE_LEDS  	struct work_struct led_work;  	struct led_classdev leds[NO_LEDS];  	char led_names[NO_LEDS][32];  	atomic_t brightness[NO_LEDS];  	unsigned long brightness_new; +#endif  	u8 *transfer_buffer;  	u32 last_val; @@ -175,20 +154,13 @@ static struct snd_tea575x_ops shark_tea_ops = {  	.read_val  = shark_read_val,  }; +#ifdef SHARK_USE_LEDS  static void shark_led_work(struct work_struct *work)  {  	struct shark_device *shark =  		container_of(work, struct shark_device, led_work);  	int i, res, brightness, actual_len; -	/* -	 * We use the v4l2_dev lock and registered bit to ensure the device -	 * does not get unplugged and unreffed while we're running. -	 */ -	mutex_lock(&shark->tea.mutex); -	if (!video_is_registered(&shark->tea.vd)) -		goto leave; -  	for (i = 0; i < 3; i++) {  		if (!test_and_clear_bit(i, &shark->brightness_new))  			continue; @@ -208,8 +180,6 @@ static void shark_led_work(struct work_struct *work)  			v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n",  				 shark->led_names[i], res);  	} -leave: -	mutex_unlock(&shark->tea.mutex);  }  static void shark_led_set_blue(struct led_classdev *led_cdev, @@ -245,19 +215,78 @@ static void shark_led_set_red(struct led_classdev *led_cdev,  	schedule_work(&shark->led_work);  } +static const struct led_classdev shark_led_templates[NO_LEDS] = { +	[BLUE_LED] = { +		.name		= "%s:blue:", +		.brightness	= LED_OFF, +		.max_brightness = 127, +		.brightness_set = shark_led_set_blue, +	}, +	[BLUE_PULSE_LED] = { +		.name		= "%s:blue-pulse:", +		.brightness	= LED_OFF, +		.max_brightness = 255, +		.brightness_set = shark_led_set_blue_pulse, +	}, +	[RED_LED] = { +		.name		= "%s:red:", +		.brightness	= LED_OFF, +		.max_brightness = 1, +		.brightness_set = shark_led_set_red, +	}, +}; + +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ +	int i, retval; + +	INIT_WORK(&shark->led_work, shark_led_work); +	for (i = 0; i < NO_LEDS; i++) { +		shark->leds[i] = shark_led_templates[i]; +		snprintf(shark->led_names[i], sizeof(shark->led_names[0]), +			 shark->leds[i].name, shark->v4l2_dev.name); +		shark->leds[i].name = shark->led_names[i]; +		retval = led_classdev_register(dev, &shark->leds[i]); +		if (retval) { +			v4l2_err(&shark->v4l2_dev, +				 "couldn't register led: %s\n", +				 shark->led_names[i]); +			return retval; +		} +	} +	return 0; +} + +static void shark_unregister_leds(struct shark_device *shark) +{ +	int i; + +	for (i = 0; i < NO_LEDS; i++) +		led_classdev_unregister(&shark->leds[i]); + +	cancel_work_sync(&shark->led_work); +} +#else +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ +	v4l2_warn(&shark->v4l2_dev, +		  "CONFIG_LED_CLASS not enabled, LED support disabled\n"); +	return 0; +} +static inline void shark_unregister_leds(struct shark_device *shark) { } +#endif +  static void usb_shark_disconnect(struct usb_interface *intf)  {  	struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);  	struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); -	int i;  	mutex_lock(&shark->tea.mutex);  	v4l2_device_disconnect(&shark->v4l2_dev);  	snd_tea575x_exit(&shark->tea);  	mutex_unlock(&shark->tea.mutex); -	for (i = 0; i < NO_LEDS; i++) -		led_classdev_unregister(&shark->leds[i]); +	shark_unregister_leds(shark);  	v4l2_device_put(&shark->v4l2_dev);  } @@ -266,7 +295,6 @@ static void usb_shark_release(struct v4l2_device *v4l2_dev)  {  	struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); -	cancel_work_sync(&shark->led_work);  	v4l2_device_unregister(&shark->v4l2_dev);  	kfree(shark->transfer_buffer);  	kfree(shark); @@ -276,7 +304,7 @@ static int usb_shark_probe(struct usb_interface *intf,  			   const struct usb_device_id *id)  {  	struct shark_device *shark; -	int i, retval = -ENOMEM; +	int retval = -ENOMEM;  	shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);  	if (!shark) @@ -286,17 +314,13 @@ static int usb_shark_probe(struct usb_interface *intf,  	if (!shark->transfer_buffer)  		goto err_alloc_buffer; -	/* -	 * Work around a bug in usbhid/hid-core.c, where it leaves a dangling -	 * pointer in intfdata causing v4l2-device.c to not set it. Which -	 * results in usb_shark_disconnect() referencing the dangling pointer -	 * -	 * REMOVE (as soon as the above bug is fixed, patch submitted) -	 */ -	usb_set_intfdata(intf, NULL); +	v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); + +	retval = shark_register_leds(shark, &intf->dev); +	if (retval) +		goto err_reg_leds;  	shark->v4l2_dev.release = usb_shark_release; -	v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance);  	retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev);  	if (retval) {  		v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n"); @@ -320,32 +344,13 @@ static int usb_shark_probe(struct usb_interface *intf,  		goto err_init_tea;  	} -	INIT_WORK(&shark->led_work, shark_led_work); -	for (i = 0; i < NO_LEDS; i++) { -		shark->leds[i] = shark_led_templates[i]; -		snprintf(shark->led_names[i], sizeof(shark->led_names[0]), -			 shark->leds[i].name, shark->v4l2_dev.name); -		shark->leds[i].name = shark->led_names[i]; -		/* -		 * We don't fail the probe if we fail to register the leds, -		 * because once we've called snd_tea575x_init, the /dev/radio0 -		 * node may be opened from userspace holding a reference to us! -		 * -		 * Note we cannot register the leds first instead as -		 * shark_led_work depends on the v4l2 mutex and registered bit. -		 */ -		retval = led_classdev_register(&intf->dev, &shark->leds[i]); -		if (retval) -			v4l2_err(&shark->v4l2_dev, -				 "couldn't register led: %s\n", -				 shark->led_names[i]); -	} -  	return 0;  err_init_tea:  	v4l2_device_unregister(&shark->v4l2_dev);  err_reg_dev: +	shark_unregister_leds(shark); +err_reg_leds:  	kfree(shark->transfer_buffer);  err_alloc_buffer:  	kfree(shark); diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c index b9575de3e7e..7b4efdfaae2 100644 --- a/drivers/media/radio/radio-shark2.c +++ b/drivers/media/radio/radio-shark2.c @@ -35,6 +35,11 @@  #include <media/v4l2-device.h>  #include "radio-tea5777.h" +#if defined(CONFIG_LEDS_CLASS) || \ +    (defined(CONFIG_LEDS_CLASS_MODULE) && defined(CONFIG_RADIO_SHARK2_MODULE)) +#define SHARK_USE_LEDS 1 +#endif +  MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");  MODULE_DESCRIPTION("Griffin radioSHARK2, USB radio receiver driver");  MODULE_LICENSE("GPL"); @@ -43,7 +48,6 @@ static int debug;  module_param(debug, int, 0);  MODULE_PARM_DESC(debug, "Debug level (0-1)"); -  #define SHARK_IN_EP		0x83  #define SHARK_OUT_EP		0x05 @@ -54,36 +58,18 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");  enum { BLUE_LED, RED_LED, NO_LEDS }; -static void shark_led_set_blue(struct led_classdev *led_cdev, -			       enum led_brightness value); -static void shark_led_set_red(struct led_classdev *led_cdev, -			      enum led_brightness value); - -static const struct led_classdev shark_led_templates[NO_LEDS] = { -	[BLUE_LED] = { -		.name		= "%s:blue:", -		.brightness	= LED_OFF, -		.max_brightness = 127, -		.brightness_set = shark_led_set_blue, -	}, -	[RED_LED] = { -		.name		= "%s:red:", -		.brightness	= LED_OFF, -		.max_brightness = 1, -		.brightness_set = shark_led_set_red, -	}, -}; -  struct shark_device {  	struct usb_device *usbdev;  	struct v4l2_device v4l2_dev;  	struct radio_tea5777 tea; +#ifdef SHARK_USE_LEDS  	struct work_struct led_work;  	struct led_classdev leds[NO_LEDS];  	char led_names[NO_LEDS][32];  	atomic_t brightness[NO_LEDS];  	unsigned long brightness_new; +#endif  	u8 *transfer_buffer;  }; @@ -161,18 +147,12 @@ static struct radio_tea5777_ops shark_tea_ops = {  	.read_reg  = shark_read_reg,  }; +#ifdef SHARK_USE_LEDS  static void shark_led_work(struct work_struct *work)  {  	struct shark_device *shark =  		container_of(work, struct shark_device, led_work);  	int i, res, brightness, actual_len; -	/* -	 * We use the v4l2_dev lock and registered bit to ensure the device -	 * does not get unplugged and unreffed while we're running. -	 */ -	mutex_lock(&shark->tea.mutex); -	if (!video_is_registered(&shark->tea.vd)) -		goto leave;  	for (i = 0; i < 2; i++) {  		if (!test_and_clear_bit(i, &shark->brightness_new)) @@ -191,8 +171,6 @@ static void shark_led_work(struct work_struct *work)  			v4l2_err(&shark->v4l2_dev, "set LED %s error: %d\n",  				 shark->led_names[i], res);  	} -leave: -	mutex_unlock(&shark->tea.mutex);  }  static void shark_led_set_blue(struct led_classdev *led_cdev, @@ -217,19 +195,72 @@ static void shark_led_set_red(struct led_classdev *led_cdev,  	schedule_work(&shark->led_work);  } +static const struct led_classdev shark_led_templates[NO_LEDS] = { +	[BLUE_LED] = { +		.name		= "%s:blue:", +		.brightness	= LED_OFF, +		.max_brightness = 127, +		.brightness_set = shark_led_set_blue, +	}, +	[RED_LED] = { +		.name		= "%s:red:", +		.brightness	= LED_OFF, +		.max_brightness = 1, +		.brightness_set = shark_led_set_red, +	}, +}; + +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ +	int i, retval; + +	INIT_WORK(&shark->led_work, shark_led_work); +	for (i = 0; i < NO_LEDS; i++) { +		shark->leds[i] = shark_led_templates[i]; +		snprintf(shark->led_names[i], sizeof(shark->led_names[0]), +			 shark->leds[i].name, shark->v4l2_dev.name); +		shark->leds[i].name = shark->led_names[i]; +		retval = led_classdev_register(dev, &shark->leds[i]); +		if (retval) { +			v4l2_err(&shark->v4l2_dev, +				 "couldn't register led: %s\n", +				 shark->led_names[i]); +			return retval; +		} +	} +	return 0; +} + +static void shark_unregister_leds(struct shark_device *shark) +{ +	int i; + +	for (i = 0; i < NO_LEDS; i++) +		led_classdev_unregister(&shark->leds[i]); + +	cancel_work_sync(&shark->led_work); +} +#else +static int shark_register_leds(struct shark_device *shark, struct device *dev) +{ +	v4l2_warn(&shark->v4l2_dev, +		  "CONFIG_LED_CLASS not enabled, LED support disabled\n"); +	return 0; +} +static inline void shark_unregister_leds(struct shark_device *shark) { } +#endif +  static void usb_shark_disconnect(struct usb_interface *intf)  {  	struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);  	struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); -	int i;  	mutex_lock(&shark->tea.mutex);  	v4l2_device_disconnect(&shark->v4l2_dev);  	radio_tea5777_exit(&shark->tea);  	mutex_unlock(&shark->tea.mutex); -	for (i = 0; i < NO_LEDS; i++) -		led_classdev_unregister(&shark->leds[i]); +	shark_unregister_leds(shark);  	v4l2_device_put(&shark->v4l2_dev);  } @@ -238,7 +269,6 @@ static void usb_shark_release(struct v4l2_device *v4l2_dev)  {  	struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev); -	cancel_work_sync(&shark->led_work);  	v4l2_device_unregister(&shark->v4l2_dev);  	kfree(shark->transfer_buffer);  	kfree(shark); @@ -248,7 +278,7 @@ static int usb_shark_probe(struct usb_interface *intf,  			   const struct usb_device_id *id)  {  	struct shark_device *shark; -	int i, retval = -ENOMEM; +	int retval = -ENOMEM;  	shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);  	if (!shark) @@ -258,17 +288,13 @@ static int usb_shark_probe(struct usb_interface *intf,  	if (!shark->transfer_buffer)  		goto err_alloc_buffer; -	/* -	 * Work around a bug in usbhid/hid-core.c, where it leaves a dangling -	 * pointer in intfdata causing v4l2-device.c to not set it. Which -	 * results in usb_shark_disconnect() referencing the dangling pointer -	 * -	 * REMOVE (as soon as the above bug is fixed, patch submitted) -	 */ -	usb_set_intfdata(intf, NULL); +	v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance); + +	retval = shark_register_leds(shark, &intf->dev); +	if (retval) +		goto err_reg_leds;  	shark->v4l2_dev.release = usb_shark_release; -	v4l2_device_set_name(&shark->v4l2_dev, DRV_NAME, &shark_instance);  	retval = v4l2_device_register(&intf->dev, &shark->v4l2_dev);  	if (retval) {  		v4l2_err(&shark->v4l2_dev, "couldn't register v4l2_device\n"); @@ -292,32 +318,13 @@ static int usb_shark_probe(struct usb_interface *intf,  		goto err_init_tea;  	} -	INIT_WORK(&shark->led_work, shark_led_work); -	for (i = 0; i < NO_LEDS; i++) { -		shark->leds[i] = shark_led_templates[i]; -		snprintf(shark->led_names[i], sizeof(shark->led_names[0]), -			 shark->leds[i].name, shark->v4l2_dev.name); -		shark->leds[i].name = shark->led_names[i]; -		/* -		 * We don't fail the probe if we fail to register the leds, -		 * because once we've called radio_tea5777_init, the /dev/radio0 -		 * node may be opened from userspace holding a reference to us! -		 * -		 * Note we cannot register the leds first instead as -		 * shark_led_work depends on the v4l2 mutex and registered bit. -		 */ -		retval = led_classdev_register(&intf->dev, &shark->leds[i]); -		if (retval) -			v4l2_err(&shark->v4l2_dev, -				 "couldn't register led: %s\n", -				 shark->led_names[i]); -	} -  	return 0;  err_init_tea:  	v4l2_device_unregister(&shark->v4l2_dev);  err_reg_dev: +	shark_unregister_leds(shark); +err_reg_leds:  	kfree(shark->transfer_buffer);  err_alloc_buffer:  	kfree(shark); diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 9e38132afec..9bb65e170d9 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -151,6 +151,7 @@ static const struct v4l2_frequency_band bands[] = {  		.index = 0,  		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |  			    V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | +			    V4L2_TUNER_CAP_FREQ_BANDS |  			    V4L2_TUNER_CAP_HWSEEK_BOUNDED |  			    V4L2_TUNER_CAP_HWSEEK_WRAP,  		.rangelow   =  87500 * 16, @@ -162,6 +163,7 @@ static const struct v4l2_frequency_band bands[] = {  		.index = 1,  		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |  			    V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | +			    V4L2_TUNER_CAP_FREQ_BANDS |  			    V4L2_TUNER_CAP_HWSEEK_BOUNDED |  			    V4L2_TUNER_CAP_HWSEEK_WRAP,  		.rangelow   =  76000 * 16, @@ -173,6 +175,7 @@ static const struct v4l2_frequency_band bands[] = {  		.index = 2,  		.capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |  			    V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO | +			    V4L2_TUNER_CAP_FREQ_BANDS |  			    V4L2_TUNER_CAP_HWSEEK_BOUNDED |  			    V4L2_TUNER_CAP_HWSEEK_WRAP,  		.rangelow   =  76000 * 16, diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 643a6ff7c5d..f867f04cccc 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -225,8 +225,9 @@ int si470x_vidioc_querycap(struct file *file, void *priv,  {  	strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));  	strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card)); -	capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | -		V4L2_CAP_TUNER | V4L2_CAP_RADIO; +	capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE | +		V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE; +	capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;  	return 0;  } diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index 146be4263ea..be076f7181e 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -531,7 +531,7 @@ int si470x_vidioc_querycap(struct file *file, void *priv,  	strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));  	usb_make_path(radio->usbdev, capability->bus_info,  			sizeof(capability->bus_info)); -	capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | +	capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_READWRITE |  		V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_RDS_CAPTURE;  	capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;  	return 0; diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 5180390be7a..8be57634ba6 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -261,6 +261,7 @@ config IR_WINBOND_CIR  config IR_IGUANA  	tristate "IguanaWorks USB IR Transceiver" +	depends on USB_ARCH_HAS_HCD  	depends on RC_CORE  	select USB  	---help--- diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c index cf9d9fca5b8..234777116e5 100644 --- a/drivers/media/video/gspca/jl2005bcd.c +++ b/drivers/media/video/gspca/jl2005bcd.c @@ -512,7 +512,7 @@ static const struct sd_desc sd_desc = {  };  /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = {  	{USB_DEVICE(0x0979, 0x0227)},  	{}  }; diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 969bb5a4cd9..bab01c86c31 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -579,7 +579,7 @@ static const struct sd_desc sd_desc = {  };  /* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = {  	{USB_DEVICE(0x06e1, 0xa190)},  /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505  	{USB_DEVICE(0x0733, 0x0430)}, */ diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 7efe9ad7acc..0b91a5cd38e 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -431,7 +431,7 @@ static int vidioc_querycap(struct file *file, void *priv,  	strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);  	strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);  	strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info)); -	cap->capabilities = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING; +	cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;  	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;  	return 0;  } diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index d2e6f82ecfa..560a65aa703 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -403,7 +403,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev)  	dev_dbg(pcdev->icd->parent, "Activate device\n"); -	clk_enable(pcdev->clk); +	clk_prepare_enable(pcdev->clk);  	/* enable CSI before doing anything else */  	__raw_writel(csicr1, pcdev->base + CSICR1); @@ -422,7 +422,7 @@ static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)  	/* Disable all CSI interface */  	__raw_writel(0x00, pcdev->base + CSICR1); -	clk_disable(pcdev->clk); +	clk_disable_unprepare(pcdev->clk);  }  /* diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 637bde8aca2..ac175406e58 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -272,7 +272,7 @@ struct mx2_camera_dev {  	struct device		*dev;  	struct soc_camera_host	soc_host;  	struct soc_camera_device *icd; -	struct clk		*clk_csi, *clk_emma; +	struct clk		*clk_csi, *clk_emma_ahb, *clk_emma_ipg;  	unsigned int		irq_csi, irq_emma;  	void __iomem		*base_csi, *base_emma; @@ -407,7 +407,7 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)  {  	unsigned long flags; -	clk_disable(pcdev->clk_csi); +	clk_disable_unprepare(pcdev->clk_csi);  	writel(0, pcdev->base_csi + CSICR1);  	if (cpu_is_mx27()) {  		writel(0, pcdev->base_emma + PRP_CNTL); @@ -435,7 +435,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)  	if (pcdev->icd)  		return -EBUSY; -	ret = clk_enable(pcdev->clk_csi); +	ret = clk_prepare_enable(pcdev->clk_csi);  	if (ret < 0)  		return ret; @@ -1633,23 +1633,34 @@ static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev)  		goto exit_iounmap;  	} -	pcdev->clk_emma = clk_get(NULL, "emma"); -	if (IS_ERR(pcdev->clk_emma)) { -		err = PTR_ERR(pcdev->clk_emma); +	pcdev->clk_emma_ipg = clk_get(pcdev->dev, "emma-ipg"); +	if (IS_ERR(pcdev->clk_emma_ipg)) { +		err = PTR_ERR(pcdev->clk_emma_ipg);  		goto exit_free_irq;  	} -	clk_enable(pcdev->clk_emma); +	clk_prepare_enable(pcdev->clk_emma_ipg); + +	pcdev->clk_emma_ahb = clk_get(pcdev->dev, "emma-ahb"); +	if (IS_ERR(pcdev->clk_emma_ahb)) { +		err = PTR_ERR(pcdev->clk_emma_ahb); +		goto exit_clk_emma_ipg_put; +	} + +	clk_prepare_enable(pcdev->clk_emma_ahb);  	err = mx27_camera_emma_prp_reset(pcdev);  	if (err) -		goto exit_clk_emma_put; +		goto exit_clk_emma_ahb_put;  	return err; -exit_clk_emma_put: -	clk_disable(pcdev->clk_emma); -	clk_put(pcdev->clk_emma); +exit_clk_emma_ahb_put: +	clk_disable_unprepare(pcdev->clk_emma_ahb); +	clk_put(pcdev->clk_emma_ahb); +exit_clk_emma_ipg_put: +	clk_disable_unprepare(pcdev->clk_emma_ipg); +	clk_put(pcdev->clk_emma_ipg);  exit_free_irq:  	free_irq(pcdev->irq_emma, pcdev);  exit_iounmap: @@ -1685,7 +1696,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)  		goto exit;  	} -	pcdev->clk_csi = clk_get(&pdev->dev, NULL); +	pcdev->clk_csi = clk_get(&pdev->dev, "ahb");  	if (IS_ERR(pcdev->clk_csi)) {  		dev_err(&pdev->dev, "Could not get csi clock\n");  		err = PTR_ERR(pcdev->clk_csi); @@ -1785,8 +1796,10 @@ exit_free_emma:  eallocctx:  	if (cpu_is_mx27()) {  		free_irq(pcdev->irq_emma, pcdev); -		clk_disable(pcdev->clk_emma); -		clk_put(pcdev->clk_emma); +		clk_disable_unprepare(pcdev->clk_emma_ipg); +		clk_put(pcdev->clk_emma_ipg); +		clk_disable_unprepare(pcdev->clk_emma_ahb); +		clk_put(pcdev->clk_emma_ahb);  		iounmap(pcdev->base_emma);  		release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma));  	} @@ -1825,8 +1838,10 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev)  	iounmap(pcdev->base_csi);  	if (cpu_is_mx27()) { -		clk_disable(pcdev->clk_emma); -		clk_put(pcdev->clk_emma); +		clk_disable_unprepare(pcdev->clk_emma_ipg); +		clk_put(pcdev->clk_emma_ipg); +		clk_disable_unprepare(pcdev->clk_emma_ahb); +		clk_put(pcdev->clk_emma_ahb);  		iounmap(pcdev->base_emma);  		res = pcdev->res_emma;  		release_mem_region(res->start, resource_size(res)); diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index f13643d3135..af2297dd49c 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c @@ -61,15 +61,9 @@  #define MAX_VIDEO_MEM 16 -enum csi_buffer_state { -	CSI_BUF_NEEDS_INIT, -	CSI_BUF_PREPARED, -}; -  struct mx3_camera_buffer {  	/* common v4l buffer stuff -- must be first */  	struct vb2_buffer			vb; -	enum csi_buffer_state			state;  	struct list_head			queue;  	/* One descriptot per scatterlist (per frame) */ @@ -285,7 +279,7 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)  		goto error;  	} -	if (buf->state == CSI_BUF_NEEDS_INIT) { +	if (!buf->txd) {  		sg_dma_address(sg)	= vb2_dma_contig_plane_dma_addr(vb, 0);  		sg_dma_len(sg)		= new_size; @@ -298,7 +292,6 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb)  		txd->callback_param	= txd;  		txd->callback		= mx3_cam_dma_done; -		buf->state		= CSI_BUF_PREPARED;  		buf->txd		= txd;  	} else {  		txd = buf->txd; @@ -385,7 +378,6 @@ static void mx3_videobuf_release(struct vb2_buffer *vb)  	/* Doesn't hurt also if the list is empty */  	list_del_init(&buf->queue); -	buf->state = CSI_BUF_NEEDS_INIT;  	if (txd) {  		buf->txd = NULL; @@ -405,13 +397,13 @@ static int mx3_videobuf_init(struct vb2_buffer *vb)  	struct mx3_camera_dev *mx3_cam = ici->priv;  	struct mx3_camera_buffer *buf = to_mx3_vb(vb); -	/* This is for locking debugging only */ -	INIT_LIST_HEAD(&buf->queue); -	sg_init_table(&buf->sg, 1); +	if (!buf->txd) { +		/* This is for locking debugging only */ +		INIT_LIST_HEAD(&buf->queue); +		sg_init_table(&buf->sg, 1); -	buf->state = CSI_BUF_NEEDS_INIT; - -	mx3_cam->buf_total += vb2_plane_size(vb, 0); +		mx3_cam->buf_total += vb2_plane_size(vb, 0); +	}  	return 0;  } diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index b03ffecb743..1bde255e45d 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -171,7 +171,8 @@ static int soc_camera_try_fmt(struct soc_camera_device *icd,  	dev_dbg(icd->pdev, "TRY_FMT(%c%c%c%c, %ux%u)\n",  		pixfmtstr(pix->pixelformat), pix->width, pix->height); -	if (!(ici->capabilities & SOCAM_HOST_CAP_STRIDE)) { +	if (pix->pixelformat != V4L2_PIX_FMT_JPEG && +	    !(ici->capabilities & SOCAM_HOST_CAP_STRIDE)) {  		pix->bytesperline = 0;  		pix->sizeimage = 0;  	} diff --git a/drivers/media/video/soc_mediabus.c b/drivers/media/video/soc_mediabus.c index 89dce097a82..a397812635d 100644 --- a/drivers/media/video/soc_mediabus.c +++ b/drivers/media/video/soc_mediabus.c @@ -378,6 +378,9 @@ EXPORT_SYMBOL(soc_mbus_samples_per_pixel);  s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)  { +	if (mf->fourcc == V4L2_PIX_FMT_JPEG) +		return 0; +  	if (mf->layout != SOC_MBUS_LAYOUT_PACKED)  		return width * mf->bits_per_sample / 8; @@ -400,6 +403,9 @@ EXPORT_SYMBOL(soc_mbus_bytes_per_line);  s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf,  			u32 bytes_per_line, u32 height)  { +	if (mf->fourcc == V4L2_PIX_FMT_JPEG) +		return 0; +  	if (mf->layout == SOC_MBUS_LAYOUT_PACKED)  		return bytes_per_line * height; diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 9288fbd5001..5577381b5bf 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -338,6 +338,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,  	if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) {  		buf->error = 0;  		buf->state = UVC_BUF_STATE_QUEUED; +		buf->bytesused = 0;  		vb2_set_plane_payload(&buf->buf, 0, 0);  		return buf;  	} diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index c3b7b5f59b3..6bc47fc82fe 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c @@ -402,8 +402,10 @@ static void v4l_print_hw_freq_seek(const void *arg, bool write_only)  {  	const struct v4l2_hw_freq_seek *p = arg; -	pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u\n", -		p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing); +	pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, " +		"rangelow=%u, rangehigh=%u\n", +		p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing, +		p->rangelow, p->rangehigh);  }  static void v4l_print_requestbuffers(const void *arg, bool write_only) @@ -1853,6 +1855,8 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,  			.type = type,  		}; +		if (p->index) +			return -EINVAL;  		err = ops->vidioc_g_tuner(file, fh, &t);  		if (err)  			return err; @@ -1870,6 +1874,8 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,  		if (type != V4L2_TUNER_RADIO)  			return -EINVAL; +		if (p->index) +			return -EINVAL;  		err = ops->vidioc_g_modulator(file, fh, &m);  		if (err)  			return err; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d1facef28a6..b1a146205c0 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -395,7 +395,8 @@ config MFD_TC6387XB  config MFD_TC6393XB  	bool "Support Toshiba TC6393XB" -	depends on GPIOLIB && ARM && HAVE_CLK +	depends on ARM && HAVE_CLK +	select GPIOLIB  	select MFD_CORE  	select MFD_TMIO  	help diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 383421bf576..683e18a2332 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -925,6 +925,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,  			goto out;  	} +	ret = 0;  	if (pdata->leds) {  		int i; diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 43a76c41cfc..db662e2dcfa 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -202,7 +202,7 @@ static void pcap_isr_work(struct work_struct *work)  		}  		local_irq_enable();  		ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr); -	} while (gpio_get_value(irq_to_gpio(pcap->spi->irq))); +	} while (gpio_get_value(pdata->gpio));  }  static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc) diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index c6ffbbe5a6c..d78c05e693f 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -1253,7 +1253,7 @@ static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,  			if (dev->wd_timeout)  				*slots -= mei_data2slots(MEI_START_WD_DATA_SIZE);  			else -				*slots -= mei_data2slots(MEI_START_WD_DATA_SIZE); +				*slots -= mei_data2slots(MEI_WD_PARAMS_SIZE);  		}  	}  	if (dev->stop) diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 09233020886..7422c765284 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -925,6 +925,27 @@ static struct miscdevice  mei_misc_device = {  };  /** + * mei_quirk_probe - probe for devices that doesn't valid ME interface + * @pdev: PCI device structure + * @ent: entry into pci_device_table + * + * returns true if ME Interface is valid, false otherwise + */ +static bool __devinit mei_quirk_probe(struct pci_dev *pdev, +				const struct pci_device_id *ent) +{ +	u32 reg; +	if (ent->device == MEI_DEV_ID_PBG_1) { +		pci_read_config_dword(pdev, 0x48, ®); +		/* make sure that bit 9 is up and bit 10 is down */ +		if ((reg & 0x600) == 0x200) { +			dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); +			return false; +		} +	} +	return true; +} +/**   * mei_probe - Device Initialization Routine   *   * @pdev: PCI device structure @@ -939,6 +960,12 @@ static int __devinit mei_probe(struct pci_dev *pdev,  	int err;  	mutex_lock(&mei_mutex); + +	if (!mei_quirk_probe(pdev, ent)) { +		err = -ENODEV; +		goto end; +	} +  	if (mei_device) {  		err = -EEXIST;  		goto end; diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 87b251ab6ec..b9e2000969f 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -18,6 +18,8 @@  #include <linux/interrupt.h>  #include <linux/delay.h>  #include <linux/device.h> +#include <linux/cpu.h> +#include <linux/module.h>  #include <linux/err.h>  #include <linux/slab.h>  #include <asm/uv/uv_hub.h> @@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv;  					 XPC_NOTIFY_MSG_SIZE_UV)  #define XPC_NOTIFY_IRQ_NAME		"xpc_notify" +static int xpc_mq_node = -1; +  static struct xpc_gru_mq_uv *xpc_activate_mq_uv;  static struct xpc_gru_mq_uv *xpc_notify_mq_uv; @@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)  #if defined CONFIG_X86_64  	mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset,  			UV_AFFINITY_CPU); -	if (mq->irq < 0) { -		dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", -			-mq->irq); +	if (mq->irq < 0)  		return mq->irq; -	}  	mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); @@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,  	mq->mmr_blade = uv_cpu_to_blade_id(cpu);  	nid = cpu_to_node(cpu); -	page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, -				pg_order); +	page = alloc_pages_exact_node(nid, +				      GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, +				      pg_order);  	if (page == NULL) {  		dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "  			"bytes of memory on nid=%d for GRU mq\n", mq_size, nid); @@ -1731,9 +1733,50 @@ static struct xpc_arch_operations xpc_arch_ops_uv = {  	.notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv,  }; +static int +xpc_init_mq_node(int nid) +{ +	int cpu; + +	get_online_cpus(); + +	for_each_cpu(cpu, cpumask_of_node(nid)) { +		xpc_activate_mq_uv = +			xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid, +					     XPC_ACTIVATE_IRQ_NAME, +					     xpc_handle_activate_IRQ_uv); +		if (!IS_ERR(xpc_activate_mq_uv)) +			break; +	} +	if (IS_ERR(xpc_activate_mq_uv)) { +		put_online_cpus(); +		return PTR_ERR(xpc_activate_mq_uv); +	} + +	for_each_cpu(cpu, cpumask_of_node(nid)) { +		xpc_notify_mq_uv = +			xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid, +					     XPC_NOTIFY_IRQ_NAME, +					     xpc_handle_notify_IRQ_uv); +		if (!IS_ERR(xpc_notify_mq_uv)) +			break; +	} +	if (IS_ERR(xpc_notify_mq_uv)) { +		xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); +		put_online_cpus(); +		return PTR_ERR(xpc_notify_mq_uv); +	} + +	put_online_cpus(); +	return 0; +} +  int  xpc_init_uv(void)  { +	int nid; +	int ret = 0; +  	xpc_arch_ops = xpc_arch_ops_uv;  	if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { @@ -1742,21 +1785,21 @@ xpc_init_uv(void)  		return -E2BIG;  	} -	xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0, -						  XPC_ACTIVATE_IRQ_NAME, -						  xpc_handle_activate_IRQ_uv); -	if (IS_ERR(xpc_activate_mq_uv)) -		return PTR_ERR(xpc_activate_mq_uv); +	if (xpc_mq_node < 0) +		for_each_online_node(nid) { +			ret = xpc_init_mq_node(nid); -	xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0, -						XPC_NOTIFY_IRQ_NAME, -						xpc_handle_notify_IRQ_uv); -	if (IS_ERR(xpc_notify_mq_uv)) { -		xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); -		return PTR_ERR(xpc_notify_mq_uv); -	} +			if (!ret) +				break; +		} +	else +		ret = xpc_init_mq_node(xpc_mq_node); -	return 0; +	if (ret < 0) +		dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n", +			-ret); + +	return ret;  }  void @@ -1765,3 +1808,6 @@ xpc_exit_uv(void)  	xpc_destroy_gru_mq_uv(xpc_notify_mq_uv);  	xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);  } + +module_param(xpc_mq_node, int, 0); +MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues."); diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c index 1ff460a8e9c..93b4d67cc4a 100644 --- a/drivers/misc/ti-st/st_ll.c +++ b/drivers/misc/ti-st/st_ll.c @@ -87,7 +87,7 @@ static void ll_device_want_to_wakeup(struct st_data_s *st_data)  	/* communicate to platform about chip wakeup */  	kim_data = st_data->kim_data;  	pdata = kim_data->kim_pdev->dev.platform_data; -	if (pdata->chip_asleep) +	if (pdata->chip_awake)  		pdata->chip_awake(NULL);  } diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c index cfff454f628..c3bb304eca0 100644 --- a/drivers/mtd/maps/uclinux.c +++ b/drivers/mtd/maps/uclinux.c @@ -19,14 +19,13 @@  #include <linux/mtd/map.h>  #include <linux/mtd/partitions.h>  #include <asm/io.h> +#include <asm/sections.h>  /****************************************************************************/ -extern char _ebss; -  struct map_info uclinux_ram_map = {  	.name = "RAM", -	.phys = (unsigned long)&_ebss, +	.phys = (unsigned long)__bss_stop,  	.size = 0,  }; diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 31bb7e5b504..8ca417614c5 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -480,7 +480,7 @@ config MTD_NAND_NANDSIM  config MTD_NAND_GPMI_NAND          bool "GPMI NAND Flash Controller driver" -        depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28 || SOC_IMX6Q) +        depends on MTD_NAND && MXS_DMA          help  	 Enables NAND Flash support for IMX23 or IMX28.  	 The GPMI controller is very powerful, with the help of BCH diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index e9309b3659e..ac4fd756eda 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1245,7 +1245,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)  			goto out_release_mem_region;  		} else {  			struct dma_slave_config cfg; -			int rc;  			memset(&cfg, 0, sizeof(cfg));  			cfg.src_addr = info->phys_base; @@ -1254,10 +1253,10 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)  			cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;  			cfg.src_maxburst = 16;  			cfg.dst_maxburst = 16; -			rc = dmaengine_slave_config(info->dma, &cfg); -			if (rc) { +			err = dmaengine_slave_config(info->dma, &cfg); +			if (err) {  				dev_err(&pdev->dev, "DMA engine slave config failed: %d\n", -					rc); +					err);  				goto out_release_mem_region;  			}  			info->nand.read_buf   = omap_read_buf_dma_pref; diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index 545c09ed907..cff6f023c03 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -996,9 +996,7 @@ static int __init cops_module_init(void)  		printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",  			cardname);  	cops_dev = cops_probe(-1); -	if (IS_ERR(cops_dev)) -		return PTR_ERR(cops_dev); -        return 0; +	return PTR_RET(cops_dev);  }  static void __exit cops_module_exit(void) diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c index 0910dce3996..b5782cdf0bc 100644 --- a/drivers/net/appletalk/ltpc.c +++ b/drivers/net/appletalk/ltpc.c @@ -1243,9 +1243,7 @@ static int __init ltpc_module_init(void)  		       "ltpc: Autoprobing is not recommended for modules\n");  	dev_ltpc = ltpc_probe(); -	if (IS_ERR(dev_ltpc)) -		return PTR_ERR(dev_ltpc); -	return 0; +	return PTR_RET(dev_ltpc);  }  module_init(ltpc_module_init);  #endif diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6fae5f3ec7f..d688a8af432 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -398,7 +398,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,  		     sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping));  	skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping; -	if (unlikely(netpoll_tx_running(slave_dev))) +	if (unlikely(netpoll_tx_running(bond->dev)))  		bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb);  	else  		dev_queue_xmit(skb); @@ -1235,12 +1235,12 @@ static inline int slave_enable_netpoll(struct slave *slave)  	struct netpoll *np;  	int err = 0; -	np = kzalloc(sizeof(*np), GFP_KERNEL); +	np = kzalloc(sizeof(*np), GFP_ATOMIC);  	err = -ENOMEM;  	if (!np)  		goto out; -	err = __netpoll_setup(np, slave->dev); +	err = __netpoll_setup(np, slave->dev, GFP_ATOMIC);  	if (err) {  		kfree(np);  		goto out; @@ -1257,9 +1257,7 @@ static inline void slave_disable_netpoll(struct slave *slave)  		return;  	slave->np = NULL; -	synchronize_rcu_bh(); -	__netpoll_cleanup(np); -	kfree(np); +	__netpoll_free_rcu(np);  }  static inline bool slave_dev_support_netpoll(struct net_device *slave_dev)  { @@ -1292,7 +1290,7 @@ static void bond_netpoll_cleanup(struct net_device *bond_dev)  	read_unlock(&bond->lock);  } -static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) +static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp)  {  	struct bonding *bond = netdev_priv(dev);  	struct slave *slave; diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index f0c8bd54ce2..021d69c5d9b 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -1712,7 +1712,7 @@ e100_set_network_leds(int active)  static void  e100_netpoll(struct net_device* netdev)  { -	e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL); +	e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev);  }  #endif diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 77bcd4cb4ff..463b9ec57d8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1278,7 +1278,7 @@ struct bnx2x {  #define BNX2X_FW_RX_ALIGN_START	(1UL << BNX2X_RX_ALIGN_SHIFT)  #define BNX2X_FW_RX_ALIGN_END					\ -	max(1UL << BNX2X_RX_ALIGN_SHIFT, 			\ +	max_t(u64, 1UL << BNX2X_RX_ALIGN_SHIFT,			\  	    SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))  #define BNX2X_PXP_DRAM_ALIGN		(BNX2X_RX_ALIGN_SHIFT - 5) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index dd451c3dd83..02b5a343b19 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -4041,20 +4041,6 @@ static bool bnx2x_get_load_status(struct bnx2x *bp, int engine)  	return val != 0;  } -/* - * Reset the load status for the current engine. - */ -static void bnx2x_clear_load_status(struct bnx2x *bp) -{ -	u32 val; -	u32 mask = (BP_PATH(bp) ? BNX2X_PATH1_LOAD_CNT_MASK : -		    BNX2X_PATH0_LOAD_CNT_MASK); -	bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); -	val = REG_RD(bp, BNX2X_RECOVERY_GLOB_REG); -	REG_WR(bp, BNX2X_RECOVERY_GLOB_REG, val & (~mask)); -	bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RECOVERY_REG); -} -  static void _print_next_block(int idx, const char *blk)  {  	pr_cont("%s%s", idx ? ", " : "", blk); @@ -9384,32 +9370,24 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)  	return rc;  } -static bool __devinit bnx2x_can_flr(struct bnx2x *bp) -{ -	int pos; -	u32 cap; -	struct pci_dev *dev = bp->pdev; - -	pos = pci_pcie_cap(dev); -	if (!pos) -		return false; - -	pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap); -	if (!(cap & PCI_EXP_DEVCAP_FLR)) -		return false; - -	return true; -} -  static int __devinit bnx2x_do_flr(struct bnx2x *bp)  {  	int i, pos;  	u16 status;  	struct pci_dev *dev = bp->pdev; -	/* probe the capability first */ -	if (bnx2x_can_flr(bp)) -		return -ENOTTY; + +	if (CHIP_IS_E1x(bp)) { +		BNX2X_DEV_INFO("FLR not supported in E1/E1H\n"); +		return -EINVAL; +	} + +	/* only bootcode REQ_BC_VER_4_INITIATE_FLR and onwards support flr */ +	if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) { +		BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n", +			  bp->common.bc_ver); +		return -EINVAL; +	}  	pos = pci_pcie_cap(dev);  	if (!pos) @@ -9429,12 +9407,8 @@ static int __devinit bnx2x_do_flr(struct bnx2x *bp)  		"transaction is not cleared; proceeding with reset anyway\n");  clear: -	if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) { -		BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n", -			  bp->common.bc_ver); -		return -EINVAL; -	} +	BNX2X_DEV_INFO("Initiating FLR\n");  	bnx2x_fw_command(bp, DRV_MSG_CODE_INITIATE_FLR, 0);  	return 0; @@ -9454,8 +9428,21 @@ static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)  	 * the one required, then FLR will be sufficient to clean any residue  	 * left by previous driver  	 */ -	if (bnx2x_test_firmware_version(bp, false) && bnx2x_can_flr(bp)) -		return bnx2x_do_flr(bp); +	rc = bnx2x_test_firmware_version(bp, false); + +	if (!rc) { +		/* fw version is good */ +		BNX2X_DEV_INFO("FW version matches our own. Attempting FLR\n"); +		rc = bnx2x_do_flr(bp); +	} + +	if (!rc) { +		/* FLR was performed */ +		BNX2X_DEV_INFO("FLR successful\n"); +		return 0; +	} + +	BNX2X_DEV_INFO("Could not FLR\n");  	/* Close the MCP request, return failure*/  	rc = bnx2x_prev_mcp_done(bp); @@ -11427,9 +11414,6 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,  	if (!chip_is_e1x)  		REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_TARGET_READ, 1); -	/* Reset the load counter */ -	bnx2x_clear_load_status(bp); -  	dev->watchdog_timeo = TX_TIMEOUT;  	dev->netdev_ops = &bnx2x_netdev_ops; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 734fd87cd99..62f754bd0df 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -2485,6 +2485,7 @@ static int bnx2x_mcast_enqueue_cmd(struct bnx2x *bp,  		break;  	default: +		kfree(new_cmd);  		BNX2X_ERR("Unknown command: %d\n", cmd);  		return -EINVAL;  	} diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index c60de89b666..90a903d83d8 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1948,7 +1948,7 @@ static int be_rx_cqs_create(struct be_adapter *adapter)  	if (adapter->num_rx_qs != MAX_RX_QS)  		dev_info(&adapter->pdev->dev, -			"Created only %d receive queues", adapter->num_rx_qs); +			"Created only %d receive queues\n", adapter->num_rx_qs);  	return 0;  } diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index 0f2d1a71090..15145330940 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -174,8 +174,10 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)  	new_bus->phy_mask = ~0;  	new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); -	if (!new_bus->irq) +	if (!new_bus->irq) { +		ret = -ENOMEM;  		goto out_unmap_regs; +	}  	new_bus->parent = &ofdev->dev;  	dev_set_drvdata(&ofdev->dev, new_bus); diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index 55bb867258e..cdf702a5948 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -137,8 +137,10 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)  	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);  	fec->fecp = ioremap(res.start, resource_size(&res)); -	if (!fec->fecp) +	if (!fec->fecp) { +		ret = -ENOMEM;  		goto out_fec; +	}  	if (get_bus_freq) {  		clock = get_bus_freq(ofdev->dev.of_node); @@ -172,8 +174,10 @@ static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)  	new_bus->phy_mask = ~0;  	new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); -	if (!new_bus->irq) +	if (!new_bus->irq) { +		ret = -ENOMEM;  		goto out_unmap_regs; +	}  	new_bus->parent = &ofdev->dev;  	dev_set_drvdata(&ofdev->dev, new_bus); diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index 0b3bade957f..080c89093fe 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -999,7 +999,7 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)   **/  static s32 e1000_reset_hw_82571(struct e1000_hw *hw)  { -	u32 ctrl, ctrl_ext, eecd; +	u32 ctrl, ctrl_ext, eecd, tctl;  	s32 ret_val;  	/* @@ -1014,7 +1014,9 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)  	ew32(IMC, 0xffffffff);  	ew32(RCTL, 0); -	ew32(TCTL, E1000_TCTL_PSP); +	tctl = er32(TCTL); +	tctl &= ~E1000_TCTL_EN; +	ew32(TCTL, tctl);  	e1e_flush();  	usleep_range(10000, 20000); @@ -1601,10 +1603,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)  			 * auto-negotiation in the TXCW register and disable  			 * forced link in the Device Control register in an  			 * attempt to auto-negotiate with our link partner. -			 * If the partner code word is null, stop forcing -			 * and restart auto negotiation.  			 */ -			if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW))  { +			if (rxcw & E1000_RXCW_C) {  				/* Enable autoneg, and unforce link up */  				ew32(TXCW, mac->txcw);  				ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 95b245310f1..46c3b1f9ff8 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -178,6 +178,24 @@ static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo)  	pr_info("%-15s %08x %08x\n", rname, regs[0], regs[1]);  } +static void e1000e_dump_ps_pages(struct e1000_adapter *adapter, +				 struct e1000_buffer *bi) +{ +	int i; +	struct e1000_ps_page *ps_page; + +	for (i = 0; i < adapter->rx_ps_pages; i++) { +		ps_page = &bi->ps_pages[i]; + +		if (ps_page->page) { +			pr_info("packet dump for ps_page %d:\n", i); +			print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, +				       16, 1, page_address(ps_page->page), +				       PAGE_SIZE, true); +		} +	} +} +  /*   * e1000e_dump - Print registers, Tx-ring and Rx-ring   */ @@ -299,10 +317,10 @@ static void e1000e_dump(struct e1000_adapter *adapter)  			(unsigned long long)buffer_info->time_stamp,  			buffer_info->skb, next_desc); -		if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) +		if (netif_msg_pktdata(adapter) && buffer_info->skb)  			print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, -				       16, 1, phys_to_virt(buffer_info->dma), -				       buffer_info->length, true); +				       16, 1, buffer_info->skb->data, +				       buffer_info->skb->len, true);  	}  	/* Print Rx Ring Summary */ @@ -381,10 +399,8 @@ rx_ring_summary:  					buffer_info->skb, next_desc);  				if (netif_msg_pktdata(adapter)) -					print_hex_dump(KERN_INFO, "", -						DUMP_PREFIX_ADDRESS, 16, 1, -						phys_to_virt(buffer_info->dma), -						adapter->rx_ps_bsize0, true); +					e1000e_dump_ps_pages(adapter, +							     buffer_info);  			}  		}  		break; @@ -444,12 +460,12 @@ rx_ring_summary:  					(unsigned long long)buffer_info->dma,  					buffer_info->skb, next_desc); -				if (netif_msg_pktdata(adapter)) +				if (netif_msg_pktdata(adapter) && +				    buffer_info->skb)  					print_hex_dump(KERN_INFO, "",  						       DUMP_PREFIX_ADDRESS, 16,  						       1, -						       phys_to_virt -						       (buffer_info->dma), +						       buffer_info->skb->data,  						       adapter->rx_buffer_len,  						       true);  			} diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index 5e84eaac48c..ba994fb4cec 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c @@ -254,6 +254,14 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)  	 */  	size += NVM_WORD_SIZE_BASE_SHIFT; +	/* +	 * Check for invalid size +	 */ +	if ((hw->mac.type == e1000_82576) && (size > 15)) { +		pr_notice("The NVM size is not valid, defaulting to 32K\n"); +		size = 15; +	} +  	nvm->word_size = 1 << size;  	if (hw->mac.type < e1000_i210) {  		nvm->opcode_bits        = 8; @@ -281,14 +289,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)  	} else  		nvm->type = e1000_nvm_flash_hw; -	/* -	 * Check for invalid size -	 */ -	if ((hw->mac.type == e1000_82576) && (size > 15)) { -		pr_notice("The NVM size is not valid, defaulting to 32K\n"); -		size = 15; -	} -  	/* NVM Function Pointers */  	switch (hw->mac.type) {  	case e1000_82580: diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h index 10efcd88dca..28394bea525 100644 --- a/drivers/net/ethernet/intel/igb/e1000_regs.h +++ b/drivers/net/ethernet/intel/igb/e1000_regs.h @@ -156,8 +156,12 @@  				    : (0x0E018 + ((_n) * 0x40)))  #define E1000_TXDCTL(_n)  ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) \  				    : (0x0E028 + ((_n) * 0x40))) -#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8)) -#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8)) +#define E1000_RXCTL(_n)	  ((_n) < 4 ? (0x02814 + ((_n) * 0x100)) : \ +				      (0x0C014 + ((_n) * 0x40))) +#define E1000_DCA_RXCTRL(_n)	E1000_RXCTL(_n) +#define E1000_TXCTL(_n)   ((_n) < 4 ? (0x03814 + ((_n) * 0x100)) : \ +				      (0x0E014 + ((_n) * 0x40))) +#define E1000_DCA_TXCTRL(_n) E1000_TXCTL(_n)  #define E1000_TDWBAL(_n)  ((_n) < 4 ? (0x03838 + ((_n) * 0x100)) \  				    : (0x0E038 + ((_n) * 0x40)))  #define E1000_TDWBAH(_n)  ((_n) < 4 ? (0x0383C + ((_n) * 0x100)) \ diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index a19c84cad0e..70591117051 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -209,8 +209,8 @@ static int igb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)  	/* When SoL/IDER sessions are active, autoneg/speed/duplex  	 * cannot be changed */  	if (igb_check_reset_block(hw)) { -		dev_err(&adapter->pdev->dev, "Cannot change link " -			"characteristics when SoL/IDER is active.\n"); +		dev_err(&adapter->pdev->dev, +			"Cannot change link characteristics when SoL/IDER is active.\n");  		return -EINVAL;  	} @@ -1089,8 +1089,8 @@ static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data,  		wr32(reg, (_test[pat] & write));  		val = rd32(reg) & mask;  		if (val != (_test[pat] & write & mask)) { -			dev_err(&adapter->pdev->dev, "pattern test reg %04X " -				"failed: got 0x%08X expected 0x%08X\n", +			dev_err(&adapter->pdev->dev, +				"pattern test reg %04X failed: got 0x%08X expected 0x%08X\n",  				reg, val, (_test[pat] & write & mask));  			*data = reg;  			return 1; @@ -1108,8 +1108,8 @@ static bool reg_set_and_check(struct igb_adapter *adapter, u64 *data,  	wr32(reg, write & mask);  	val = rd32(reg);  	if ((write & mask) != (val & mask)) { -		dev_err(&adapter->pdev->dev, "set/check reg %04X test failed:" -			" got 0x%08X expected 0x%08X\n", reg, +		dev_err(&adapter->pdev->dev, +			"set/check reg %04X test failed: got 0x%08X expected 0x%08X\n", reg,  			(val & mask), (write & mask));  		*data = reg;  		return 1; @@ -1171,8 +1171,9 @@ static int igb_reg_test(struct igb_adapter *adapter, u64 *data)  	wr32(E1000_STATUS, toggle);  	after = rd32(E1000_STATUS) & toggle;  	if (value != after) { -		dev_err(&adapter->pdev->dev, "failed STATUS register test " -			"got: 0x%08X expected: 0x%08X\n", after, value); +		dev_err(&adapter->pdev->dev, +			"failed STATUS register test got: 0x%08X expected: 0x%08X\n", +			after, value);  		*data = 1;  		return 1;  	} @@ -1497,6 +1498,9 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)  		break;  	} +	/* add small delay to avoid loopback test failure */ +	msleep(50); +  	/* force 1000, set loopback */  	igb_write_phy_reg(hw, PHY_CONTROL, 0x4140); @@ -1777,16 +1781,14 @@ static int igb_loopback_test(struct igb_adapter *adapter, u64 *data)  	 * sessions are active */  	if (igb_check_reset_block(&adapter->hw)) {  		dev_err(&adapter->pdev->dev, -			"Cannot do PHY loopback test " -			"when SoL/IDER is active.\n"); +			"Cannot do PHY loopback test when SoL/IDER is active.\n");  		*data = 0;  		goto out;  	}  	if ((adapter->hw.mac.type == e1000_i210) -		|| (adapter->hw.mac.type == e1000_i210)) { +		|| (adapter->hw.mac.type == e1000_i211)) {  		dev_err(&adapter->pdev->dev, -			"Loopback test not supported " -			"on this part at this time.\n"); +			"Loopback test not supported on this part at this time.\n");  		*data = 0;  		goto out;  	} diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index b7c2d505057..48cc4fb1a30 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -462,10 +462,10 @@ static void igb_dump(struct igb_adapter *adapter)  				(u64)buffer_info->time_stamp,  				buffer_info->skb, next_desc); -			if (netif_msg_pktdata(adapter) && buffer_info->dma != 0) +			if (netif_msg_pktdata(adapter) && buffer_info->skb)  				print_hex_dump(KERN_INFO, "",  					DUMP_PREFIX_ADDRESS, -					16, 1, phys_to_virt(buffer_info->dma), +					16, 1, buffer_info->skb->data,  					buffer_info->length, true);  		}  	} @@ -547,18 +547,17 @@ rx_ring_summary:  					(u64)buffer_info->dma,  					buffer_info->skb, next_desc); -				if (netif_msg_pktdata(adapter)) { +				if (netif_msg_pktdata(adapter) && +				    buffer_info->dma && buffer_info->skb) {  					print_hex_dump(KERN_INFO, "", -						DUMP_PREFIX_ADDRESS, -						16, 1, -						phys_to_virt(buffer_info->dma), -						IGB_RX_HDR_LEN, true); +						  DUMP_PREFIX_ADDRESS, +						  16, 1, buffer_info->skb->data, +						  IGB_RX_HDR_LEN, true);  					print_hex_dump(KERN_INFO, "",  					  DUMP_PREFIX_ADDRESS,  					  16, 1, -					  phys_to_virt( -					    buffer_info->page_dma + -					    buffer_info->page_offset), +					  page_address(buffer_info->page) + +						      buffer_info->page_offset,  					  PAGE_SIZE/2, true);  				}  			} diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 50fc137501d..18bf08c9d7a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -804,12 +804,13 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,  	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {  		/* Set KX4/KX/KR support according to speed requested */  		autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP); -		if (speed & IXGBE_LINK_SPEED_10GB_FULL) +		if (speed & IXGBE_LINK_SPEED_10GB_FULL) {  			if (orig_autoc & IXGBE_AUTOC_KX4_SUPP)  				autoc |= IXGBE_AUTOC_KX4_SUPP;  			if ((orig_autoc & IXGBE_AUTOC_KR_SUPP) &&  			    (hw->phy.smart_speed_active == false))  				autoc |= IXGBE_AUTOC_KR_SUPP; +		}  		if (speed & IXGBE_LINK_SPEED_1GB_FULL)  			autoc |= IXGBE_AUTOC_KX_SUPP;  	} else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) && diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index f32e7030077..5aba5ecdf1e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -614,8 +614,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud  		/* If source MAC is equal to our own MAC and not performing  		 * the selftest or flb disabled - drop the packet */  		if (s_mac == priv->mac && -			(!(dev->features & NETIF_F_LOOPBACK) || -			 !priv->validate_loopback)) +		    !((dev->features & NETIF_F_LOOPBACK) || +		      priv->validate_loopback))  			goto next;  		/* diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 019d856b133..10bba09c44e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -164,7 +164,6 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,  	ring->cons = 0xffffffff;  	ring->last_nr_txbb = 1;  	ring->poll_cnt = 0; -	ring->blocked = 0;  	memset(ring->tx_info, 0, ring->size * sizeof(struct mlx4_en_tx_info));  	memset(ring->buf, 0, ring->buf_size); @@ -365,14 +364,13 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)  	ring->cons += txbbs_skipped;  	netdev_tx_completed_queue(ring->tx_queue, packets, bytes); -	/* Wakeup Tx queue if this ring stopped it */ -	if (unlikely(ring->blocked)) { -		if ((u32) (ring->prod - ring->cons) <= -		     ring->size - HEADROOM - MAX_DESC_TXBBS) { -			ring->blocked = 0; -			netif_tx_wake_queue(ring->tx_queue); -			priv->port_stats.wake_queue++; -		} +	/* +	 * Wakeup Tx queue if this stopped, and at least 1 packet +	 * was completed +	 */ +	if (netif_tx_queue_stopped(ring->tx_queue) && txbbs_skipped > 0) { +		netif_tx_wake_queue(ring->tx_queue); +		priv->port_stats.wake_queue++;  	}  } @@ -592,7 +590,6 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)  		     ring->size - HEADROOM - MAX_DESC_TXBBS)) {  		/* every full Tx ring stops queue */  		netif_tx_stop_queue(ring->tx_queue); -		ring->blocked = 1;  		priv->port_stats.queue_stopped++;  		return NETDEV_TX_BUSY; diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c index 88b7b3e75ab..daf41792366 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -358,13 +358,14 @@ void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,  }  int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			u64 virt, int obj_size,	int nobj, int reserved, +			u64 virt, int obj_size,	u32 nobj, int reserved,  			int use_lowmem, int use_coherent)  {  	int obj_per_chunk;  	int num_icm;  	unsigned chunk_size;  	int i; +	u64 size;  	obj_per_chunk = MLX4_TABLE_CHUNK_SIZE / obj_size;  	num_icm = (nobj + obj_per_chunk - 1) / obj_per_chunk; @@ -380,10 +381,12 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,  	table->coherent = use_coherent;  	mutex_init(&table->mutex); +	size = (u64) nobj * obj_size;  	for (i = 0; i * MLX4_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) {  		chunk_size = MLX4_TABLE_CHUNK_SIZE; -		if ((i + 1) * MLX4_TABLE_CHUNK_SIZE > nobj * obj_size) -			chunk_size = PAGE_ALIGN(nobj * obj_size - i * MLX4_TABLE_CHUNK_SIZE); +		if ((i + 1) * MLX4_TABLE_CHUNK_SIZE > size) +			chunk_size = PAGE_ALIGN(size - +					i * MLX4_TABLE_CHUNK_SIZE);  		table->icm[i] = mlx4_alloc_icm(dev, chunk_size >> PAGE_SHIFT,  					       (use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) | diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.h b/drivers/net/ethernet/mellanox/mlx4/icm.h index 19e4efc0b34..a67744f5350 100644 --- a/drivers/net/ethernet/mellanox/mlx4/icm.h +++ b/drivers/net/ethernet/mellanox/mlx4/icm.h @@ -78,7 +78,7 @@ int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,  void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,  			  int start, int end);  int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table, -			u64 virt, int obj_size,	int nobj, int reserved, +			u64 virt, int obj_size,	u32 nobj, int reserved,  			int use_lowmem, int use_coherent);  void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table);  void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 48d0e90194c..827b72dfce9 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -157,9 +157,6 @@ int mlx4_check_port_params(struct mlx4_dev *dev,  					 "on this HCA, aborting.\n");  				return -EINVAL;  			} -			if (port_type[i] == MLX4_PORT_TYPE_ETH && -			    port_type[i + 1] == MLX4_PORT_TYPE_IB) -				return -EINVAL;  		}  	} diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c index 4ec3835e1bc..a018ea2a43d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -432,8 +432,10 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,  			if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {  				/* Entry already exists, add to duplicates */  				dqp = kmalloc(sizeof *dqp, GFP_KERNEL); -				if (!dqp) +				if (!dqp) { +					err = -ENOMEM;  					goto out_mailbox; +				}  				dqp->qpn = qpn;  				list_add_tail(&dqp->list, &entry->duplicates);  				found = true; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index 59ebc033963..4d9df8f2a12 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -249,7 +249,7 @@ struct mlx4_bitmap {  struct mlx4_buddy {  	unsigned long	      **bits;  	unsigned int	       *num_free; -	int			max_order; +	u32			max_order;  	spinlock_t		lock;  }; @@ -258,7 +258,7 @@ struct mlx4_icm;  struct mlx4_icm_table {  	u64			virt;  	int			num_icm; -	int			num_obj; +	u32			num_obj;  	int			obj_size;  	int			lowmem;  	int			coherent; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 5f1ab105deb..9d27e42264e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -248,7 +248,6 @@ struct mlx4_en_tx_ring {  	u32 doorbell_qpn;  	void *buf;  	u16 poll_cnt; -	int blocked;  	struct mlx4_en_tx_info *tx_info;  	u8 *bounce_buf;  	u32 last_nr_txbb; diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index af55b7ce534..c202d3ad2a0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -37,6 +37,7 @@  #include <linux/export.h>  #include <linux/slab.h>  #include <linux/kernel.h> +#include <linux/vmalloc.h>  #include <linux/mlx4/cmd.h> @@ -120,7 +121,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)  	buddy->max_order = max_order;  	spin_lock_init(&buddy->lock); -	buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *), +	buddy->bits = kcalloc(buddy->max_order + 1, sizeof (long *),  			      GFP_KERNEL);  	buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free,  				  GFP_KERNEL); @@ -129,10 +130,12 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)  	for (i = 0; i <= buddy->max_order; ++i) {  		s = BITS_TO_LONGS(1 << (buddy->max_order - i)); -		buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL); -		if (!buddy->bits[i]) -			goto err_out_free; -		bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i)); +		buddy->bits[i] = kcalloc(s, sizeof (long), GFP_KERNEL | __GFP_NOWARN); +		if (!buddy->bits[i]) { +			buddy->bits[i] = vzalloc(s * sizeof(long)); +			if (!buddy->bits[i]) +				goto err_out_free; +		}  	}  	set_bit(0, buddy->bits[buddy->max_order]); @@ -142,7 +145,10 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)  err_out_free:  	for (i = 0; i <= buddy->max_order; ++i) -		kfree(buddy->bits[i]); +		if (buddy->bits[i] && is_vmalloc_addr(buddy->bits[i])) +			vfree(buddy->bits[i]); +		else +			kfree(buddy->bits[i]);  err_out:  	kfree(buddy->bits); @@ -156,7 +162,10 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)  	int i;  	for (i = 0; i <= buddy->max_order; ++i) -		kfree(buddy->bits[i]); +		if (is_vmalloc_addr(buddy->bits[i])) +			vfree(buddy->bits[i]); +		else +			kfree(buddy->bits[i]);  	kfree(buddy->bits);  	kfree(buddy->num_free); @@ -668,7 +677,7 @@ int mlx4_init_mr_table(struct mlx4_dev *dev)  		return err;  	err = mlx4_buddy_init(&mr_table->mtt_buddy, -			      ilog2(dev->caps.num_mtts / +			      ilog2((u32)dev->caps.num_mtts /  			      (1 << log_mtts_per_seg)));  	if (err)  		goto err_buddy; @@ -678,7 +687,7 @@ int mlx4_init_mr_table(struct mlx4_dev *dev)  			mlx4_alloc_mtt_range(dev,  					     fls(dev->caps.reserved_mtts - 1));  		if (priv->reserved_mtts < 0) { -			mlx4_warn(dev, "MTT table of order %d is too small.\n", +			mlx4_warn(dev, "MTT table of order %u is too small.\n",  				  mr_table->mtt_buddy.max_order);  			err = -ENOMEM;  			goto err_reserve_mtts; diff --git a/drivers/net/ethernet/mellanox/mlx4/profile.c b/drivers/net/ethernet/mellanox/mlx4/profile.c index 9ee4725363d..8e0c3cc2a1e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/profile.c +++ b/drivers/net/ethernet/mellanox/mlx4/profile.c @@ -76,7 +76,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,  		u64 size;  		u64 start;  		int type; -		int num; +		u32 num;  		int log_num;  	}; @@ -105,7 +105,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,  	si_meminfo(&si);  	request->num_mtt =  		roundup_pow_of_two(max_t(unsigned, request->num_mtt, -					 min(1UL << 31, +					 min(1UL << (31 - log_mtts_per_seg),  					     si.totalram >> (log_mtts_per_seg - 1))));  	profile[MLX4_RES_QP].size     = dev_cap->qpc_entry_sz; diff --git a/drivers/net/ethernet/mellanox/mlx4/sense.c b/drivers/net/ethernet/mellanox/mlx4/sense.c index 80249829352..34ee09bae36 100644 --- a/drivers/net/ethernet/mellanox/mlx4/sense.c +++ b/drivers/net/ethernet/mellanox/mlx4/sense.c @@ -81,20 +81,6 @@ void mlx4_do_sense_ports(struct mlx4_dev *dev,  	}  	/* -	 * Adjust port configuration: -	 * If port 1 sensed nothing and port 2 is IB, set both as IB -	 * If port 2 sensed nothing and port 1 is Eth, set both as Eth -	 */ -	if (stype[0] == MLX4_PORT_TYPE_ETH) { -		for (i = 1; i < dev->caps.num_ports; i++) -			stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_ETH; -	} -	if (stype[dev->caps.num_ports - 1] == MLX4_PORT_TYPE_IB) { -		for (i = 0; i < dev->caps.num_ports - 1; i++) -			stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_IB; -	} - -	/*  	 * If sensed nothing, remain in current configuration.  	 */  	for (i = 0; i < dev->caps.num_ports; i++) diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 4069edab229..53743f7a2ca 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -346,28 +346,15 @@ static phy_interface_t lpc_phy_interface_mode(struct device *dev)  						   "phy-mode", NULL);  		if (mode && !strcmp(mode, "mii"))  			return PHY_INTERFACE_MODE_MII; -		return PHY_INTERFACE_MODE_RMII;  	} - -	/* non-DT */ -#ifdef CONFIG_ARCH_LPC32XX_MII_SUPPORT -	return PHY_INTERFACE_MODE_MII; -#else  	return PHY_INTERFACE_MODE_RMII; -#endif  }  static bool use_iram_for_net(struct device *dev)  {  	if (dev && dev->of_node)  		return of_property_read_bool(dev->of_node, "use-iram"); - -	/* non-DT */ -#ifdef CONFIG_ARCH_LPC32XX_IRAM_FOR_NET -	return true; -#else  	return false; -#endif  }  /* Receive Status information word */ diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig index 46df3a04030..24c2305d794 100644 --- a/drivers/net/ethernet/renesas/Kconfig +++ b/drivers/net/ethernet/renesas/Kconfig @@ -8,7 +8,7 @@ config SH_ETH  		(CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \  		 CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \  		 CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \ -		 CPU_SUBTYPE_SH7757 || ARCH_R8A7740) +		 CPU_SUBTYPE_SH7757 || ARCH_R8A7740 || ARCH_R8A7779)  	select CRC32  	select NET_CORE  	select MII @@ -18,4 +18,4 @@ config SH_ETH  	  Renesas SuperH Ethernet device driver.  	  This driver supporting CPUs are:  		- SH7619, SH7710, SH7712, SH7724, SH7734, SH7763, SH7757, -		  and R8A7740. +		  R8A7740 and R8A7779. diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index af0b867a6cf..bad8f2eec9b 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -78,7 +78,7 @@ static void sh_eth_select_mii(struct net_device *ndev)  #endif  /* There is CPU dependent code */ -#if defined(CONFIG_CPU_SUBTYPE_SH7724) +#if defined(CONFIG_CPU_SUBTYPE_SH7724) || defined(CONFIG_ARCH_R8A7779)  #define SH_ETH_RESET_DEFAULT	1  static void sh_eth_set_duplex(struct net_device *ndev)  { @@ -93,13 +93,18 @@ static void sh_eth_set_duplex(struct net_device *ndev)  static void sh_eth_set_rate(struct net_device *ndev)  {  	struct sh_eth_private *mdp = netdev_priv(ndev); +	unsigned int bits = ECMR_RTM; + +#if defined(CONFIG_ARCH_R8A7779) +	bits |= ECMR_ELB; +#endif  	switch (mdp->speed) {  	case 10: /* 10BASE */ -		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR); +		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~bits, ECMR);  		break;  	case 100:/* 100BASE */ -		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR); +		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | bits, ECMR);  		break;  	default:  		break; diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 70554a1b2b0..65a8d49106a 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1503,6 +1503,11 @@ static int efx_probe_all(struct efx_nic *efx)  		goto fail2;  	} +	BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT); +	if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) { +		rc = -EINVAL; +		goto fail3; +	}  	efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE;  	rc = efx_probe_filters(efx); @@ -2070,6 +2075,7 @@ static int efx_register_netdev(struct efx_nic *efx)  	net_dev->irq = efx->pci_dev->irq;  	net_dev->netdev_ops = &efx_netdev_ops;  	SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); +	net_dev->gso_max_segs = EFX_TSO_MAX_SEGS;  	rtnl_lock(); diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index be8f9158a71..70755c97251 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -30,6 +30,7 @@ extern netdev_tx_t  efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);  extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);  extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc); +extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx);  /* RX */  extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); @@ -52,10 +53,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);  #define EFX_MAX_EVQ_SIZE 16384UL  #define EFX_MIN_EVQ_SIZE 512UL -/* The smallest [rt]xq_entries that the driver supports. Callers of - * efx_wake_queue() assume that they can subsequently send at least one - * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ -#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) +/* Maximum number of TCP segments we support for soft-TSO */ +#define EFX_TSO_MAX_SEGS	100 + +/* The smallest [rt]xq_entries that the driver supports.  RX minimum + * is a bit arbitrary.  For TX, we must have space for at least 2 + * TSO skbs. + */ +#define EFX_RXQ_MIN_ENT		128U +#define EFX_TXQ_MIN_ENT(efx)	(2 * efx_tx_max_skb_descs(efx))  /* Filters */  extern int efx_probe_filters(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 10536f93b56..8cba2df82b1 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -680,21 +680,27 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev,  				     struct ethtool_ringparam *ring)  {  	struct efx_nic *efx = netdev_priv(net_dev); +	u32 txq_entries;  	if (ring->rx_mini_pending || ring->rx_jumbo_pending ||  	    ring->rx_pending > EFX_MAX_DMAQ_SIZE ||  	    ring->tx_pending > EFX_MAX_DMAQ_SIZE)  		return -EINVAL; -	if (ring->rx_pending < EFX_MIN_RING_SIZE || -	    ring->tx_pending < EFX_MIN_RING_SIZE) { +	if (ring->rx_pending < EFX_RXQ_MIN_ENT) {  		netif_err(efx, drv, efx->net_dev, -			  "TX and RX queues cannot be smaller than %ld\n", -			  EFX_MIN_RING_SIZE); +			  "RX queues cannot be smaller than %u\n", +			  EFX_RXQ_MIN_ENT);  		return -EINVAL;  	} -	return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending); +	txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx)); +	if (txq_entries != ring->tx_pending) +		netif_warn(efx, drv, efx->net_dev, +			   "increasing TX queue size to minimum of %u\n", +			   txq_entries); + +	return efx_realloc_channels(efx, ring->rx_pending, txq_entries);  }  static int efx_ethtool_set_pauseparam(struct net_device *net_dev, diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 9b225a7769f..18713436b44 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -119,6 +119,25 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr)  	return len;  } +unsigned int efx_tx_max_skb_descs(struct efx_nic *efx) +{ +	/* Header and payload descriptor for each output segment, plus +	 * one for every input fragment boundary within a segment +	 */ +	unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; + +	/* Possibly one more per segment for the alignment workaround */ +	if (EFX_WORKAROUND_5391(efx)) +		max_descs += EFX_TSO_MAX_SEGS; + +	/* Possibly more for PCIe page boundaries within input fragments */ +	if (PAGE_SIZE > EFX_PAGE_SIZE) +		max_descs += max_t(unsigned int, MAX_SKB_FRAGS, +				   DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE)); + +	return max_descs; +} +  /*   * Add a socket buffer to a TX queue   * diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index fd8882f9602..c136162e647 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -2077,7 +2077,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,  		goto error_netdev_register;  	} -	priv->stmmac_clk = clk_get(priv->device, NULL); +	priv->stmmac_clk = clk_get(priv->device, STMMAC_RESOURCE_NAME);  	if (IS_ERR(priv->stmmac_clk)) {  		pr_warning("%s: warning: cannot get CSR clock\n", __func__);  		goto error_clk_get; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index cd01ee7ecef..b93245c1199 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -74,7 +74,7 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,   * the necessary resources and invokes the main to init   * the net device, register the mdio bus etc.   */ -static int stmmac_pltfr_probe(struct platform_device *pdev) +static int __devinit stmmac_pltfr_probe(struct platform_device *pdev)  {  	int ret = 0;  	struct resource *res; diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index 3b5c4571b55..d15c888e9df 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -538,11 +538,12 @@ EXPORT_SYMBOL_GPL(cpdma_chan_create);  int cpdma_chan_destroy(struct cpdma_chan *chan)  { -	struct cpdma_ctlr *ctlr = chan->ctlr; +	struct cpdma_ctlr *ctlr;  	unsigned long flags;  	if (!chan)  		return -EINVAL; +	ctlr = chan->ctlr;  	spin_lock_irqsave(&ctlr->lock, flags);  	if (chan->state != CPDMA_STATE_IDLE) diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index 482648fcf0b..98934bdf6ac 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1003,6 +1003,7 @@ static int ixp4xx_nway_reset(struct net_device *dev)  }  int ixp46x_phc_index = -1; +EXPORT_SYMBOL_GPL(ixp46x_phc_index);  static int ixp4xx_get_ts_info(struct net_device *dev,  			      struct ethtool_ts_info *info) diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 6cee2917eb0..4a1a5f58fa7 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -383,13 +383,6 @@ int netvsc_device_remove(struct hv_device *device)  	unsigned long flags;  	net_device = hv_get_drvdata(device); -	spin_lock_irqsave(&device->channel->inbound_lock, flags); -	net_device->destroy = true; -	spin_unlock_irqrestore(&device->channel->inbound_lock, flags); - -	/* Wait for all send completions */ -	wait_event(net_device->wait_drain, -		   atomic_read(&net_device->num_outstanding_sends) == 0);  	netvsc_disconnect_vsp(net_device); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index e5d6146937f..1e88a109593 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -718,6 +718,9 @@ static void rndis_filter_halt_device(struct rndis_device *dev)  {  	struct rndis_request *request;  	struct rndis_halt_request *halt; +	struct netvsc_device *nvdev = dev->net_dev; +	struct hv_device *hdev = nvdev->dev; +	ulong flags;  	/* Attempt to do a rndis device halt */  	request = get_rndis_request(dev, RNDIS_MSG_HALT, @@ -735,6 +738,14 @@ static void rndis_filter_halt_device(struct rndis_device *dev)  	dev->state = RNDIS_DEV_UNINITIALIZED;  cleanup: +	spin_lock_irqsave(&hdev->channel->inbound_lock, flags); +	nvdev->destroy = true; +	spin_unlock_irqrestore(&hdev->channel->inbound_lock, flags); + +	/* Wait for all send completions */ +	wait_event(nvdev->wait_drain, +		atomic_read(&nvdev->num_outstanding_sends) == 0); +  	if (request)  		put_rndis_request(dev, request);  	return; diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c index a561ae44a9a..c6a0299aa9f 100644 --- a/drivers/net/irda/bfin_sir.c +++ b/drivers/net/irda/bfin_sir.c @@ -158,7 +158,7 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed)  	/* If not add the 'RPOLC', we can't catch the receive interrupt.  	 * It's related with the HW layout and the IR transiver.  	 */ -	val |= IREN | RPOLC; +	val |= UMOD_IRDA | RPOLC;  	UART_PUT_GCTL(port, val);  	return ret;  } @@ -432,7 +432,7 @@ static void bfin_sir_shutdown(struct bfin_sir_port *port, struct net_device *dev  	bfin_sir_stop_rx(port);  	val = UART_GET_GCTL(port); -	val &= ~(UCEN | IREN | RPOLC); +	val &= ~(UCEN | UMOD_MASK | RPOLC);  	UART_PUT_GCTL(port, val);  #ifdef CONFIG_SIR_BFIN_DMA @@ -518,10 +518,10 @@ static void bfin_sir_send_work(struct work_struct *work)  	 * reset all the UART.  	 */  	val = UART_GET_GCTL(port); -	val &= ~(IREN | RPOLC); +	val &= ~(UMOD_MASK | RPOLC);  	UART_PUT_GCTL(port, val);  	SSYNC(); -	val |= IREN | RPOLC; +	val |= UMOD_IRDA | RPOLC;  	UART_PUT_GCTL(port, val);  	SSYNC();  	/* bfin_sir_set_speed(port, self->speed); */ diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c index 824e2a93fe8..5f3aeac3f86 100644 --- a/drivers/net/irda/ks959-sir.c +++ b/drivers/net/irda/ks959-sir.c @@ -542,6 +542,7 @@ static int ks959_net_open(struct net_device *netdev)  	sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);  	kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);  	if (!kingsun->irlap) { +		err = -ENOMEM;  		dev_err(&kingsun->usbdev->dev, "irlap_open failed\n");  		goto free_mem;  	} diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c index 5a278ab83c2..2d4b6a1ab20 100644 --- a/drivers/net/irda/ksdazzle-sir.c +++ b/drivers/net/irda/ksdazzle-sir.c @@ -436,6 +436,7 @@ static int ksdazzle_net_open(struct net_device *netdev)  	sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);  	kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);  	if (!kingsun->irlap) { +		err = -ENOMEM;  		dev_err(&kingsun->usbdev->dev, "irlap_open failed\n");  		goto free_mem;  	} diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 0737bd4d166..0f0f9ce3a77 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -94,7 +94,8 @@ static int get_slot(struct macvlan_dev *vlan, struct macvtap_queue *q)  	int i;  	for (i = 0; i < MAX_MACVTAP_QUEUES; i++) { -		if (rcu_dereference(vlan->taps[i]) == q) +		if (rcu_dereference_protected(vlan->taps[i], +					      lockdep_is_held(&macvtap_lock)) == q)  			return i;  	} diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index f9347ea3d38..b3321129a83 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -640,15 +640,9 @@ static int netconsole_netdev_event(struct notifier_block *this,  				 * rtnl_lock already held  				 */  				if (nt->np.dev) { -					spin_unlock_irqrestore( -							      &target_list_lock, -							      flags);  					__netpoll_cleanup(&nt->np); -					spin_lock_irqsave(&target_list_lock, -							  flags);  					dev_put(nt->np.dev);  					nt->np.dev = NULL; -					netconsole_target_put(nt);  				}  				nt->enabled = 0;  				stopped = true; diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c index e0cc4ef33de..eefe49e8713 100644 --- a/drivers/net/phy/mdio-mux-gpio.c +++ b/drivers/net/phy/mdio-mux-gpio.c @@ -101,7 +101,6 @@ err:  		n--;  		gpio_free(s->gpio[n]);  	} -	devm_kfree(&pdev->dev, s);  	return r;  } diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c index 5c120189ec8..4d4d25efc1e 100644 --- a/drivers/net/phy/mdio-mux.c +++ b/drivers/net/phy/mdio-mux.c @@ -132,7 +132,7 @@ int mdio_mux_init(struct device *dev,  	pb->mii_bus = parent_bus;  	ret_val = -ENODEV; -	for_each_child_of_node(dev->of_node, child_bus_node) { +	for_each_available_child_of_node(dev->of_node, child_bus_node) {  		u32 v;  		r = of_property_read_u32(child_bus_node, "reg", &v); diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 1c98321b56c..162464fe86b 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -189,7 +189,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)  	if (sk_pppox(po)->sk_state & PPPOX_DEAD)  		goto tx_error; -	rt = ip_route_output_ports(&init_net, &fl4, NULL, +	rt = ip_route_output_ports(sock_net(sk), &fl4, NULL,  				   opt->dst_addr.sin_addr.s_addr,  				   opt->src_addr.sin_addr.s_addr,  				   0, 0, IPPROTO_GRE, @@ -468,7 +468,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,  	po->chan.private = sk;  	po->chan.ops = &pptp_chan_ops; -	rt = ip_route_output_ports(&init_net, &fl4, sk, +	rt = ip_route_output_ports(sock_net(sk), &fl4, sk,  				   opt->dst_addr.sin_addr.s_addr,  				   opt->src_addr.sin_addr.s_addr,  				   0, 0, diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 87707ab3943..341b65dbbcd 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -795,16 +795,17 @@ static void team_port_leave(struct team *team, struct team_port *port)  }  #ifdef CONFIG_NET_POLL_CONTROLLER -static int team_port_enable_netpoll(struct team *team, struct team_port *port) +static int team_port_enable_netpoll(struct team *team, struct team_port *port, +				    gfp_t gfp)  {  	struct netpoll *np;  	int err; -	np = kzalloc(sizeof(*np), GFP_KERNEL); +	np = kzalloc(sizeof(*np), gfp);  	if (!np)  		return -ENOMEM; -	err = __netpoll_setup(np, port->dev); +	err = __netpoll_setup(np, port->dev, gfp);  	if (err) {  		kfree(np);  		return err; @@ -833,7 +834,8 @@ static struct netpoll_info *team_netpoll_info(struct team *team)  }  #else -static int team_port_enable_netpoll(struct team *team, struct team_port *port) +static int team_port_enable_netpoll(struct team *team, struct team_port *port, +				    gfp_t gfp)  {  	return 0;  } @@ -913,7 +915,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev)  	}  	if (team_netpoll_info(team)) { -		err = team_port_enable_netpoll(team, port); +		err = team_port_enable_netpoll(team, port, GFP_KERNEL);  		if (err) {  			netdev_err(dev, "Failed to enable netpoll on device %s\n",  				   portname); @@ -1443,7 +1445,7 @@ static void team_netpoll_cleanup(struct net_device *dev)  }  static int team_netpoll_setup(struct net_device *dev, -			      struct netpoll_info *npifo) +			      struct netpoll_info *npifo, gfp_t gfp)  {  	struct team *team = netdev_priv(dev);  	struct team_port *port; @@ -1451,7 +1453,7 @@ static int team_netpoll_setup(struct net_device *dev,  	mutex_lock(&team->lock);  	list_for_each_entry(port, &team->port_list, list) { -		err = team_port_enable_netpoll(team, port); +		err = team_port_enable_netpoll(team, port, gfp);  		if (err) {  			__team_netpoll_cleanup(team);  			break; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 926d4db5cb3..3a16d4fdaa0 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -187,7 +187,6 @@ static void __tun_detach(struct tun_struct *tun)  	netif_tx_lock_bh(tun->dev);  	netif_carrier_off(tun->dev);  	tun->tfile = NULL; -	tun->socket.file = NULL;  	netif_tx_unlock_bh(tun->dev);  	/* Drop read queue */ diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 64610048ce8..7d78669000d 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -232,6 +232,7 @@ static int usbpn_open(struct net_device *dev)  		struct urb *req = usb_alloc_urb(0, GFP_KERNEL);  		if (!req || rx_submit(pnd, req, GFP_KERNEL | __GFP_COLD)) { +			usb_free_urb(req);  			usbpn_close(dev);  			return -ENOMEM;  		} diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index f4ce5957df3..4cd582a4f62 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1225,6 +1225,26 @@ static const struct usb_device_id cdc_devs[] = {  	  .driver_info = (unsigned long) &wwan_info,  	}, +	/* Dell branded MBM devices like DW5550 */ +	{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO +		| USB_DEVICE_ID_MATCH_VENDOR, +	  .idVendor = 0x413c, +	  .bInterfaceClass = USB_CLASS_COMM, +	  .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, +	  .bInterfaceProtocol = USB_CDC_PROTO_NONE, +	  .driver_info = (unsigned long) &wwan_info, +	}, + +	/* Toshiba branded MBM devices */ +	{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO +		| USB_DEVICE_ID_MATCH_VENDOR, +	  .idVendor = 0x0930, +	  .bInterfaceClass = USB_CLASS_COMM, +	  .bInterfaceSubClass = USB_CDC_SUBCLASS_NCM, +	  .bInterfaceProtocol = USB_CDC_PROTO_NONE, +	  .driver_info = (unsigned long) &wwan_info, +	}, +  	/* Generic CDC-NCM devices */  	{ USB_INTERFACE_INFO(USB_CLASS_COMM,  		USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 2ea126a16d7..328397c6673 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -247,30 +247,12 @@ err:   */  static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf)  { -	int rv;  	struct qmi_wwan_state *info = (void *)&dev->data; -	/* ZTE makes devices where the interface descriptors and endpoint -	 * configurations of two or more interfaces are identical, even -	 * though the functions are completely different.  If set, then -	 * driver_info->data is a bitmap of acceptable interface numbers -	 * allowing us to bind to one such interface without binding to -	 * all of them -	 */ -	if (dev->driver_info->data && -	    !test_bit(intf->cur_altsetting->desc.bInterfaceNumber, &dev->driver_info->data)) { -		dev_info(&intf->dev, "not on our whitelist - ignored"); -		rv = -ENODEV; -		goto err; -	} -  	/*  control and data is shared */  	info->control = intf;  	info->data = intf; -	rv = qmi_wwan_register_subdriver(dev); - -err: -	return rv; +	return qmi_wwan_register_subdriver(dev);  }  static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf) @@ -356,214 +338,64 @@ static const struct driver_info	qmi_wwan_shared = {  	.manage_power	= qmi_wwan_manage_power,  }; -static const struct driver_info	qmi_wwan_force_int0 = { -	.description	= "Qualcomm WWAN/QMI device", -	.flags		= FLAG_WWAN, -	.bind		= qmi_wwan_bind_shared, -	.unbind		= qmi_wwan_unbind, -	.manage_power	= qmi_wwan_manage_power, -	.data		= BIT(0), /* interface whitelist bitmap */ -}; - -static const struct driver_info	qmi_wwan_force_int1 = { -	.description	= "Qualcomm WWAN/QMI device", -	.flags		= FLAG_WWAN, -	.bind		= qmi_wwan_bind_shared, -	.unbind		= qmi_wwan_unbind, -	.manage_power	= qmi_wwan_manage_power, -	.data		= BIT(1), /* interface whitelist bitmap */ -}; - -static const struct driver_info qmi_wwan_force_int2 = { -	.description	= "Qualcomm WWAN/QMI device", -	.flags		= FLAG_WWAN, -	.bind		= qmi_wwan_bind_shared, -	.unbind		= qmi_wwan_unbind, -	.manage_power	= qmi_wwan_manage_power, -	.data		= BIT(2), /* interface whitelist bitmap */ -}; - -static const struct driver_info	qmi_wwan_force_int3 = { -	.description	= "Qualcomm WWAN/QMI device", -	.flags		= FLAG_WWAN, -	.bind		= qmi_wwan_bind_shared, -	.unbind		= qmi_wwan_unbind, -	.manage_power	= qmi_wwan_manage_power, -	.data		= BIT(3), /* interface whitelist bitmap */ -}; - -static const struct driver_info	qmi_wwan_force_int4 = { -	.description	= "Qualcomm WWAN/QMI device", -	.flags		= FLAG_WWAN, -	.bind		= qmi_wwan_bind_shared, -	.unbind		= qmi_wwan_unbind, -	.manage_power	= qmi_wwan_manage_power, -	.data		= BIT(4), /* interface whitelist bitmap */ -}; - -/* Sierra Wireless provide equally useless interface descriptors - * Devices in QMI mode can be switched between two different - * configurations: - *   a) USB interface #8 is QMI/wwan - *   b) USB interfaces #8, #19 and #20 are QMI/wwan - * - * Both configurations provide a number of other interfaces (serial++), - * some of which have the same endpoint configuration as we expect, so - * a whitelist or blacklist is necessary. - * - * FIXME: The below whitelist should include BIT(20).  It does not - * because I cannot get it to work... - */ -static const struct driver_info	qmi_wwan_sierra = { -	.description	= "Sierra Wireless wwan/QMI device", -	.flags		= FLAG_WWAN, -	.bind		= qmi_wwan_bind_shared, -	.unbind		= qmi_wwan_unbind, -	.manage_power	= qmi_wwan_manage_power, -	.data		= BIT(8) | BIT(19), /* interface whitelist bitmap */ -}; -  #define HUAWEI_VENDOR_ID	0x12D1 +/* map QMI/wwan function by a fixed interface number */ +#define QMI_FIXED_INTF(vend, prod, num) \ +	USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ +	.driver_info = (unsigned long)&qmi_wwan_shared +  /* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */  #define QMI_GOBI1K_DEVICE(vend, prod) \ -	USB_DEVICE(vend, prod), \ -	.driver_info = (unsigned long)&qmi_wwan_force_int3 +	QMI_FIXED_INTF(vend, prod, 3) -/* Gobi 2000 and Gobi 3000 QMI/wwan interface number is 0 according to qcserial */ +/* Gobi 2000/3000 QMI/wwan interface number is 0 according to qcserial */  #define QMI_GOBI_DEVICE(vend, prod) \ -	USB_DEVICE(vend, prod), \ -	.driver_info = (unsigned long)&qmi_wwan_force_int0 +	QMI_FIXED_INTF(vend, prod, 0)  static const struct usb_device_id products[] = { +	/* 1. CDC ECM like devices match on the control interface */  	{	/* Huawei E392, E398 and possibly others sharing both device id and more... */ -		.match_flags        = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = HUAWEI_VENDOR_ID, -		.bInterfaceClass    = USB_CLASS_VENDOR_SPEC, -		.bInterfaceSubClass = 1, -		.bInterfaceProtocol = 9, /* CDC Ethernet *control* interface */ +		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 9),  		.driver_info        = (unsigned long)&qmi_wwan_info,  	},  	{	/* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ -		.match_flags        = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = HUAWEI_VENDOR_ID, -		.bInterfaceClass    = USB_CLASS_VENDOR_SPEC, -		.bInterfaceSubClass = 1, -		.bInterfaceProtocol = 57, /* CDC Ethernet *control* interface */ +		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57),  		.driver_info        = (unsigned long)&qmi_wwan_info,  	}, -	{	/* Huawei E392, E398 and possibly others in "Windows mode" -		 * using a combined control and data interface without any CDC -		 * functional descriptors -		 */ -		.match_flags        = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = HUAWEI_VENDOR_ID, -		.bInterfaceClass    = USB_CLASS_VENDOR_SPEC, -		.bInterfaceSubClass = 1, -		.bInterfaceProtocol = 17, + +	/* 2. Combined interface devices matching on class+protocol */ +	{	/* Huawei E392, E398 and possibly others in "Windows mode" */ +		USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),  		.driver_info        = (unsigned long)&qmi_wwan_shared,  	},  	{	/* Pantech UML290 */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x106c, -		.idProduct          = 0x3718, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xf0, -		.bInterfaceProtocol = 0xff, +		USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),  		.driver_info        = (unsigned long)&qmi_wwan_shared,  	}, -	{	/* ZTE MF820D */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x19d2, -		.idProduct          = 0x0167, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_force_int4, -	}, -	{	/* ZTE MF821D */ -		.match_flags        = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x19d2, -		.idProduct          = 0x0326, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_force_int4, -	}, -	{	/* ZTE (Vodafone) K3520-Z */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x19d2, -		.idProduct          = 0x0055, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_force_int1, -	}, -	{	/* ZTE (Vodafone) K3565-Z */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x19d2, -		.idProduct          = 0x0063, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_force_int4, -	}, -	{	/* ZTE (Vodafone) K3570-Z */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x19d2, -		.idProduct          = 0x1008, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_force_int4, -	}, -	{	/* ZTE (Vodafone) K3571-Z */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x19d2, -		.idProduct          = 0x1010, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_force_int4, -	}, -	{	/* ZTE (Vodafone) K3765-Z */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x19d2, -		.idProduct          = 0x2002, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_force_int4, -	}, -	{	/* ZTE (Vodafone) K4505-Z */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x19d2, -		.idProduct          = 0x0104, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_force_int4, -	}, -	{	/* ZTE MF60 */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x19d2, -		.idProduct          = 0x1402, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_force_int2, -	}, -	{	/* Sierra Wireless MC77xx in QMI mode */ -		.match_flags	    = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, -		.idVendor           = 0x1199, -		.idProduct          = 0x68a2, -		.bInterfaceClass    = 0xff, -		.bInterfaceSubClass = 0xff, -		.bInterfaceProtocol = 0xff, -		.driver_info        = (unsigned long)&qmi_wwan_sierra, +	{	/* Pantech UML290 - newer firmware */ +		USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), +		.driver_info        = (unsigned long)&qmi_wwan_shared,  	}, -	/* Gobi 1000 devices */ +	/* 3. Combined interface devices matching on interface number */ +	{QMI_FIXED_INTF(0x19d2, 0x0055, 1)},	/* ZTE (Vodafone) K3520-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x0063, 4)},	/* ZTE (Vodafone) K3565-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x0104, 4)},	/* ZTE (Vodafone) K4505-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x0167, 4)},	/* ZTE MF820D */ +	{QMI_FIXED_INTF(0x19d2, 0x0326, 4)},	/* ZTE MF821D */ +	{QMI_FIXED_INTF(0x19d2, 0x1008, 4)},	/* ZTE (Vodafone) K3570-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x1010, 4)},	/* ZTE (Vodafone) K3571-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x1018, 3)},	/* ZTE (Vodafone) K5006-Z */ +	{QMI_FIXED_INTF(0x19d2, 0x1402, 2)},	/* ZTE MF60 */ +	{QMI_FIXED_INTF(0x19d2, 0x2002, 4)},	/* ZTE (Vodafone) K3765-Z */ +	{QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */ +	{QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */ +	{QMI_FIXED_INTF(0x1199, 0x68a2, 8)},	/* Sierra Wireless MC7710 in QMI mode */ +	{QMI_FIXED_INTF(0x1199, 0x68a2, 19)},	/* Sierra Wireless MC7710 in QMI mode */ +	{QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */ + +	/* 4. Gobi 1000 devices */  	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */  	{QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */  	{QMI_GOBI1K_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Mobile Broadband Module */ @@ -579,7 +411,7 @@ static const struct usb_device_id products[] = {  	{QMI_GOBI1K_DEVICE(0x05c6, 0x9222)},	/* Generic Gobi Modem device */  	{QMI_GOBI1K_DEVICE(0x05c6, 0x9009)},	/* Generic Gobi Modem device */ -	/* Gobi 2000 and 3000 devices */ +	/* 5. Gobi 2000 and 3000 devices */  	{QMI_GOBI_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */  	{QMI_GOBI_DEVICE(0x05c6, 0x920b)},	/* Generic Gobi 2000 Modem device */  	{QMI_GOBI_DEVICE(0x05c6, 0x9225)},	/* Sony Gobi 2000 Modem device (N0279, VU730) */ @@ -589,6 +421,8 @@ static const struct usb_device_id products[] = {  	{QMI_GOBI_DEVICE(0x05c6, 0x9265)},	/* Asus Gobi 2000 Modem device (VR305) */  	{QMI_GOBI_DEVICE(0x05c6, 0x9235)},	/* Top Global Gobi 2000 Modem device (VR306) */  	{QMI_GOBI_DEVICE(0x05c6, 0x9275)},	/* iRex Technologies Gobi 2000 Modem device (VR307) */ +	{QMI_GOBI_DEVICE(0x1199, 0x68a5)},	/* Sierra Wireless Modem */ +	{QMI_GOBI_DEVICE(0x1199, 0x68a9)},	/* Sierra Wireless Modem */  	{QMI_GOBI_DEVICE(0x1199, 0x9001)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */  	{QMI_GOBI_DEVICE(0x1199, 0x9002)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */  	{QMI_GOBI_DEVICE(0x1199, 0x9003)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */ @@ -600,11 +434,14 @@ static const struct usb_device_id products[] = {  	{QMI_GOBI_DEVICE(0x1199, 0x9009)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */  	{QMI_GOBI_DEVICE(0x1199, 0x900a)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */  	{QMI_GOBI_DEVICE(0x1199, 0x9011)},	/* Sierra Wireless Gobi 2000 Modem device (MC8305) */ +	{QMI_FIXED_INTF(0x1199, 0x9011, 5)},	/* alternate interface number!? */  	{QMI_GOBI_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */  	{QMI_GOBI_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */  	{QMI_GOBI_DEVICE(0x1199, 0x9013)},	/* Sierra Wireless Gobi 3000 Modem device (MC8355) */  	{QMI_GOBI_DEVICE(0x1199, 0x9015)},	/* Sierra Wireless Gobi 3000 Modem device */  	{QMI_GOBI_DEVICE(0x1199, 0x9019)},	/* Sierra Wireless Gobi 3000 Modem device */ +	{QMI_GOBI_DEVICE(0x1199, 0x901b)},	/* Sierra Wireless MC7770 */ +  	{ }					/* END */  };  MODULE_DEVICE_TABLE(usb, products); diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index d75d1f56bec..7be49ea60b6 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -68,15 +68,8 @@ static	atomic_t iface_counter = ATOMIC_INIT(0);   */  #define SIERRA_NET_USBCTL_BUF_LEN	1024 -/* list of interface numbers - used for constructing interface lists */ -struct sierra_net_iface_info { -	const u32 infolen;	/* number of interface numbers on list */ -	const u8  *ifaceinfo;	/* pointer to the array holding the numbers */ -}; -  struct sierra_net_info_data {  	u16 rx_urb_size; -	struct sierra_net_iface_info whitelist;  };  /* Private data structure */ @@ -637,21 +630,6 @@ static int sierra_net_change_mtu(struct net_device *net, int new_mtu)  	return usbnet_change_mtu(net, new_mtu);  } -static int is_whitelisted(const u8 ifnum, -			const struct sierra_net_iface_info *whitelist) -{ -	if (whitelist) { -		const u8 *list = whitelist->ifaceinfo; -		int i; - -		for (i = 0; i < whitelist->infolen; i++) { -			if (list[i] == ifnum) -				return 1; -		} -	} -	return 0; -} -  static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)  {  	int result = 0; @@ -706,11 +684,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)  	dev_dbg(&dev->udev->dev, "%s", __func__);  	ifacenum = intf->cur_altsetting->desc.bInterfaceNumber; -	/* We only accept certain interfaces */ -	if (!is_whitelisted(ifacenum, &data->whitelist)) { -		dev_dbg(&dev->udev->dev, "Ignoring interface: %d", ifacenum); -		return -ENODEV; -	}  	numendpoints = intf->cur_altsetting->desc.bNumEndpoints;  	/* We have three endpoints, bulk in and out, and a status */  	if (numendpoints != 3) { @@ -945,13 +918,8 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb,  	return NULL;  } -static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 };  static const struct sierra_net_info_data sierra_net_info_data_direct_ip = {  	.rx_urb_size = 8 * 1024, -	.whitelist = { -		.infolen = ARRAY_SIZE(sierra_net_ifnum_list), -		.ifaceinfo = sierra_net_ifnum_list -	}  };  static const struct driver_info sierra_net_info_direct_ip = { @@ -965,15 +933,19 @@ static const struct driver_info sierra_net_info_direct_ip = {  	.data = (unsigned long)&sierra_net_info_data_direct_ip,  }; +#define DIRECT_IP_DEVICE(vend, prod) \ +	{USB_DEVICE_INTERFACE_NUMBER(vend, prod, 7), \ +	.driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ +	{USB_DEVICE_INTERFACE_NUMBER(vend, prod, 10), \ +	.driver_info = (unsigned long)&sierra_net_info_direct_ip}, \ +	{USB_DEVICE_INTERFACE_NUMBER(vend, prod, 11), \ +	.driver_info = (unsigned long)&sierra_net_info_direct_ip} +  static const struct usb_device_id products[] = { -	{USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ -	.driver_info = (unsigned long) &sierra_net_info_direct_ip}, -	{USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ -	.driver_info = (unsigned long) &sierra_net_info_direct_ip}, -	{USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ -	.driver_info = (unsigned long) &sierra_net_info_direct_ip}, -	{USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ -	.driver_info = (unsigned long) &sierra_net_info_direct_ip}, +	DIRECT_IP_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ +	DIRECT_IP_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ +	DIRECT_IP_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ +	DIRECT_IP_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */  	{}, /* last item */  }; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 93e0cfb739b..ce9d4f2c977 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -3019,6 +3019,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,  	netdev->watchdog_timeo = 5 * HZ;  	INIT_WORK(&adapter->work, vmxnet3_reset_work); +	set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);  	if (adapter->intr.type == VMXNET3_IT_MSIX) {  		int i; @@ -3043,7 +3044,6 @@ vmxnet3_probe_device(struct pci_dev *pdev,  		goto err_register;  	} -	set_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);  	vmxnet3_check_link(adapter, false);  	atomic_inc(&devices_found);  	return 0; diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c index 9eb6479306d..ef36cafd44b 100644 --- a/drivers/net/wan/dscc4.c +++ b/drivers/net/wan/dscc4.c @@ -774,14 +774,15 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev,  	}  	/* Global interrupt queue */  	writel((u32)(((IRQ_RING_SIZE >> 5) - 1) << 20), ioaddr + IQLENR1); + +	rc = -ENOMEM; +  	priv->iqcfg = (__le32 *) pci_alloc_consistent(pdev,  		IRQ_RING_SIZE*sizeof(__le32), &priv->iqcfg_dma);  	if (!priv->iqcfg)  		goto err_free_irq_5;  	writel(priv->iqcfg_dma, ioaddr + IQCFG); -	rc = -ENOMEM; -  	/*  	 * SCC 0-3 private rx/tx irq structures  	 * IQRX/TXi needs to be set soon. Learned it the hard way... diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index 283237f6f07..def12b38cbf 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -326,8 +326,10 @@ int i2400m_barker_db_init(const char *_options)  		unsigned barker;  		options_orig = kstrdup(_options, GFP_KERNEL); -		if (options_orig == NULL) +		if (options_orig == NULL) { +			result = -ENOMEM;  			goto error_parse; +		}  		options = options_orig;  		while ((token = strsep(&options, ",")) != NULL) { diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index efc162e0b51..88b8d64c90f 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -342,7 +342,7 @@ static int at76_dfu_get_status(struct usb_device *udev,  	return ret;  } -static u8 at76_dfu_get_state(struct usb_device *udev, u8 *state) +static int at76_dfu_get_state(struct usb_device *udev, u8 *state)  {  	int ret; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 8c4c040a47b..2aab20ee9f3 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -2056,9 +2056,7 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)  void  ath5k_beacon_config(struct ath5k_hw *ah)  { -	unsigned long flags; - -	spin_lock_irqsave(&ah->block, flags); +	spin_lock_bh(&ah->block);  	ah->bmisscount = 0;  	ah->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); @@ -2085,7 +2083,7 @@ ath5k_beacon_config(struct ath5k_hw *ah)  	ath5k_hw_set_imr(ah, ah->imask);  	mmiowb(); -	spin_unlock_irqrestore(&ah->block, flags); +	spin_unlock_bh(&ah->block);  }  static void ath5k_tasklet_beacon(unsigned long data) diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 260e7dc7f75..d56453e43d7 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -254,7 +254,6 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	struct ath5k_vif *avf = (void *)vif->drv_priv;  	struct ath5k_hw *ah = hw->priv;  	struct ath_common *common = ath5k_hw_common(ah); -	unsigned long flags;  	mutex_lock(&ah->lock); @@ -300,9 +299,9 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	}  	if (changes & BSS_CHANGED_BEACON) { -		spin_lock_irqsave(&ah->block, flags); +		spin_lock_bh(&ah->block);  		ath5k_beacon_update(hw, vif); -		spin_unlock_irqrestore(&ah->block, flags); +		spin_unlock_bh(&ah->block);  	}  	if (changes & BSS_CHANGED_BEACON_ENABLED) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index cfa91ab7acf..60b6a9daff7 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -730,6 +730,7 @@ int ath9k_hw_init(struct ath_hw *ah)  	case AR9300_DEVID_QCA955X:  	case AR9300_DEVID_AR9580:  	case AR9300_DEVID_AR9462: +	case AR9485_DEVID_AR1111:  		break;  	default:  		if (common->bus_ops->ath_bus_type == ATH_USB) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index dd0c146d81d..ce7332c64ef 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -49,6 +49,7 @@  #define AR9300_DEVID_AR9462	0x0034  #define AR9300_DEVID_AR9330	0x0035  #define AR9300_DEVID_QCA955X	0x0038 +#define AR9485_DEVID_AR1111	0x0037  #define AR5416_AR9100_DEVID	0x000b diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 7990cd55599..b42be910a83 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -773,15 +773,10 @@ bool ath9k_hw_intrpend(struct ath_hw *ah)  }  EXPORT_SYMBOL(ath9k_hw_intrpend); -void ath9k_hw_disable_interrupts(struct ath_hw *ah) +void ath9k_hw_kill_interrupts(struct ath_hw *ah)  {  	struct ath_common *common = ath9k_hw_common(ah); -	if (!(ah->imask & ATH9K_INT_GLOBAL)) -		atomic_set(&ah->intr_ref_cnt, -1); -	else -		atomic_dec(&ah->intr_ref_cnt); -  	ath_dbg(common, INTERRUPT, "disable IER\n");  	REG_WRITE(ah, AR_IER, AR_IER_DISABLE);  	(void) REG_READ(ah, AR_IER); @@ -793,6 +788,17 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah)  		(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);  	}  } +EXPORT_SYMBOL(ath9k_hw_kill_interrupts); + +void ath9k_hw_disable_interrupts(struct ath_hw *ah) +{ +	if (!(ah->imask & ATH9K_INT_GLOBAL)) +		atomic_set(&ah->intr_ref_cnt, -1); +	else +		atomic_dec(&ah->intr_ref_cnt); + +	ath9k_hw_kill_interrupts(ah); +}  EXPORT_SYMBOL(ath9k_hw_disable_interrupts);  void ath9k_hw_enable_interrupts(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 0eba36dca6f..4a745e68dd9 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -738,6 +738,7 @@ bool ath9k_hw_intrpend(struct ath_hw *ah);  void ath9k_hw_set_interrupts(struct ath_hw *ah);  void ath9k_hw_enable_interrupts(struct ath_hw *ah);  void ath9k_hw_disable_interrupts(struct ath_hw *ah); +void ath9k_hw_kill_interrupts(struct ath_hw *ah);  void ar9002_hw_attach_mac_ops(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6049d8b8285..a22df749b8d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -462,8 +462,10 @@ irqreturn_t ath_isr(int irq, void *dev)  	if (!ath9k_hw_intrpend(ah))  		return IRQ_NONE; -	if(test_bit(SC_OP_HW_RESET, &sc->sc_flags)) +	if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) { +		ath9k_hw_kill_interrupts(ah);  		return IRQ_HANDLED; +	}  	/*  	 * Figure out the reason(s) for the interrupt.  Note diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 87b89d55e63..a978984d78a 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -37,6 +37,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {  	{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E  AR9485 */  	{ PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E  AR9580 */  	{ PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E  AR9462 */ +	{ PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E  AR1111/AR9485 */  	{ 0 }  }; @@ -320,6 +321,7 @@ static int ath_pci_suspend(struct device *device)  	 * Otherwise the chip never moved to full sleep,  	 * when no interface is up.  	 */ +	ath9k_stop_btcoex(sc);  	ath9k_hw_disable(sc->sc_ah);  	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 12aca02228c..4480c0cc655 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1044,7 +1044,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  	struct ieee80211_hw *hw = sc->hw;  	struct ieee80211_hdr *hdr;  	int retval; -	bool decrypt_error = false;  	struct ath_rx_status rs;  	enum ath9k_rx_qtype qtype;  	bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); @@ -1066,6 +1065,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)  	tsf_lower = tsf & 0xffffffff;  	do { +		bool decrypt_error = false;  		/* If handling rx interrupt and flush is in progress => exit */  		if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0))  			break; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b80352b308d..a140165dfee 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2719,32 +2719,37 @@ static int b43_gpio_init(struct b43_wldev *dev)  	if (dev->dev->chip_id == 0x4301) {  		mask |= 0x0060;  		set |= 0x0060; +	} else if (dev->dev->chip_id == 0x5354) { +		/* Don't allow overtaking buttons GPIOs */ +		set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */  	} -	if (dev->dev->chip_id == 0x5354) -		set &= 0xff02; +  	if (0 /* FIXME: conditional unknown */ ) {  		b43_write16(dev, B43_MMIO_GPIO_MASK,  			    b43_read16(dev, B43_MMIO_GPIO_MASK)  			    | 0x0100); -		mask |= 0x0180; -		set |= 0x0180; +		/* BT Coexistance Input */ +		mask |= 0x0080; +		set |= 0x0080; +		/* BT Coexistance Out */ +		mask |= 0x0100; +		set |= 0x0100;  	}  	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL) { +		/* PA is controlled by gpio 9, let ucode handle it */  		b43_write16(dev, B43_MMIO_GPIO_MASK,  			    b43_read16(dev, B43_MMIO_GPIO_MASK)  			    | 0x0200);  		mask |= 0x0200;  		set |= 0x0200;  	} -	if (dev->dev->core_rev >= 2) -		mask |= 0x0010;	/* FIXME: This is redundant. */  	switch (dev->dev->bus_type) {  #ifdef CONFIG_B43_BCMA  	case B43_BUS_BCMA:  		bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL,  				(bcma_cc_read32(&dev->dev->bdev->bus->drv_cc, -					BCMA_CC_GPIOCTL) & mask) | set); +					BCMA_CC_GPIOCTL) & ~mask) | set);  		break;  #endif  #ifdef CONFIG_B43_SSB @@ -2753,7 +2758,7 @@ static int b43_gpio_init(struct b43_wldev *dev)  		if (gpiodev)  			ssb_write32(gpiodev, B43_GPIO_CONTROL,  				    (ssb_read32(gpiodev, B43_GPIO_CONTROL) -				    & mask) | set); +				    & ~mask) | set);  		break;  #endif  	} diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 9a4c63f927c..7ed7d757702 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -382,9 +382,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,  {  	struct brcms_c_info *wlc = wlc_cm->wlc;  	struct ieee80211_channel *ch = wlc->pub->ieee_hw->conf.channel; -	const struct ieee80211_reg_rule *reg_rule;  	struct txpwr_limits txpwr; -	int ret;  	brcms_c_channel_reg_limits(wlc_cm, chanspec, &txpwr); @@ -393,8 +391,7 @@ brcms_c_channel_set_chanspec(struct brcms_cm_info *wlc_cm, u16 chanspec,  	);  	/* set or restore gmode as required by regulatory */ -	ret = freq_reg_info(wlc->wiphy, ch->center_freq, 0, ®_rule); -	if (!ret && (reg_rule->flags & NL80211_RRF_NO_OFDM)) +	if (ch->flags & IEEE80211_CHAN_NO_OFDM)  		brcms_c_set_gmode(wlc, GMODE_LEGACY_B, false);  	else  		brcms_c_set_gmode(wlc, wlc->protection->gmode_user, false); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 9e79d47e077..192ad5c1fcc 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -121,7 +121,8 @@ static struct ieee80211_channel brcms_2ghz_chantable[] = {  		 IEEE80211_CHAN_NO_HT40PLUS),  	CHAN2GHZ(14, 2484,  		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS | -		 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) +		 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS | +		 IEEE80211_CHAN_NO_OFDM)  };  static struct ieee80211_channel brcms_5ghz_nphy_chantable[] = { diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 6fddd2785e6..a82f46c10f5 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c @@ -707,11 +707,14 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,   */  static bool rs_use_green(struct ieee80211_sta *sta)  { -	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; -	struct iwl_rxon_context *ctx = sta_priv->ctx; - -	return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && -		!(ctx->ht.non_gf_sta_present); +	/* +	 * There's a bug somewhere in this code that causes the +	 * scaling to get stuck because GF+SGI can't be combined +	 * in SISO rates. Until we find that bug, disable GF, it +	 * has only limited benefit and we still interoperate with +	 * GF APs since we can always receive GF transmissions. +	 */ +	return false;  }  /** diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index eb5de800ed9..1c10b542ab2 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -1254,6 +1254,7 @@ static int lbs_associate(struct lbs_private *priv,  			netif_tx_wake_all_queues(priv->dev);  	} +	kfree(cmd);  done:  	lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);  	return ret; diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 76caebaa439..e970897f6ab 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -1314,6 +1314,7 @@ static void if_sdio_remove(struct sdio_func *func)  		kfree(packet);  	} +	kfree(card);  	lbs_deb_leave(LBS_DEB_SDIO);  } diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 58048189bd2..fe1ea43c514 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -571,7 +571,10 @@ static int lbs_thread(void *data)  			netdev_info(dev, "Timeout submitting command 0x%04x\n",  				    le16_to_cpu(cmdnode->cmdbuf->command));  			lbs_complete_command(priv, cmdnode, -ETIMEDOUT); -			if (priv->reset_card) + +			/* Reset card, but only when it isn't in the process +			 * of being shutdown anyway. */ +			if (!dev->dismantle && priv->reset_card)  				priv->reset_card(priv);  		}  		priv->cmd_timed_out = 0; diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 7f207b6e955..effb044a8a9 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -42,7 +42,7 @@ MODULE_FIRMWARE("isl3887usb");   * whenever you add a new device.   */ -static struct usb_device_id p54u_table[] __devinitdata = { +static struct usb_device_id p54u_table[] = {  	/* Version 1 devices (pci chip + net2280) */  	{USB_DEVICE(0x0411, 0x0050)},	/* Buffalo WLI2-USB2-G54 */  	{USB_DEVICE(0x045e, 0x00c2)},	/* Microsoft MN-710 */ diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 241162e8111..7a4ae9ee1c6 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1803,6 +1803,7 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev,  						struct cfg80211_pmksa *pmksa,  						int max_pmkids)  { +	struct ndis_80211_pmkid *new_pmkids;  	int i, err, newlen;  	unsigned int count; @@ -1833,11 +1834,12 @@ static struct ndis_80211_pmkid *update_pmkid(struct usbnet *usbdev,  	/* add new pmkid */  	newlen = sizeof(*pmkids) + (count + 1) * sizeof(pmkids->bssid_info[0]); -	pmkids = krealloc(pmkids, newlen, GFP_KERNEL); -	if (!pmkids) { +	new_pmkids = krealloc(pmkids, newlen, GFP_KERNEL); +	if (!new_pmkids) {  		err = -ENOMEM;  		goto error;  	} +	pmkids = new_pmkids;  	pmkids->length = cpu_to_le32(newlen);  	pmkids->bssid_info_count = cpu_to_le32(count + 1); diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 88455b1b9fe..cb8c2aca54e 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -221,6 +221,67 @@ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,  	mutex_unlock(&rt2x00dev->csr_mutex);  } +static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; +	int i, count; + +	rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +	if (rt2x00_get_field32(reg, WLAN_EN)) +		return 0; + +	rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); +	rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); +	rt2x00_set_field32(®, WLAN_CLK_EN, 0); +	rt2x00_set_field32(®, WLAN_EN, 1); +	rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + +	udelay(REGISTER_BUSY_DELAY); + +	count = 0; +	do { +		/* +		 * Check PLL_LD & XTAL_RDY. +		 */ +		for (i = 0; i < REGISTER_BUSY_COUNT; i++) { +			rt2800_register_read(rt2x00dev, CMB_CTRL, ®); +			if (rt2x00_get_field32(reg, PLL_LD) && +			    rt2x00_get_field32(reg, XTAL_RDY)) +				break; +			udelay(REGISTER_BUSY_DELAY); +		} + +		if (i >= REGISTER_BUSY_COUNT) { + +			if (count >= 10) +				return -EIO; + +			rt2800_register_write(rt2x00dev, 0x58, 0x018); +			udelay(REGISTER_BUSY_DELAY); +			rt2800_register_write(rt2x00dev, 0x58, 0x418); +			udelay(REGISTER_BUSY_DELAY); +			rt2800_register_write(rt2x00dev, 0x58, 0x618); +			udelay(REGISTER_BUSY_DELAY); +			count++; +		} else { +			count = 0; +		} + +		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +		rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); +		rt2x00_set_field32(®, WLAN_CLK_EN, 1); +		rt2x00_set_field32(®, WLAN_RESET, 1); +		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); +		udelay(10); +		rt2x00_set_field32(®, WLAN_RESET, 0); +		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); +		udelay(10); +		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); +	} while (count != 0); + +	return 0; +} +  void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,  			const u8 command, const u8 token,  			const u8 arg0, const u8 arg1) @@ -400,6 +461,13 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,  {  	unsigned int i;  	u32 reg; +	int retval; + +	if (rt2x00_rt(rt2x00dev, RT3290)) { +		retval = rt2800_enable_wlan_rt3290(rt2x00dev); +		if (retval) +			return -EBUSY; +	}  	/*  	 * If driver doesn't wake up firmware here, diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 235376e9cb0..98aa426a356 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -980,66 +980,6 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	return rt2800_validate_eeprom(rt2x00dev);  } -static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) -{ -	u32 reg; -	int i, count; - -	rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); -	if (rt2x00_get_field32(reg, WLAN_EN)) -		return 0; - -	rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); -	rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); -	rt2x00_set_field32(®, WLAN_CLK_EN, 0); -	rt2x00_set_field32(®, WLAN_EN, 1); -	rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); - -	udelay(REGISTER_BUSY_DELAY); - -	count = 0; -	do { -		/* -		 * Check PLL_LD & XTAL_RDY. -		 */ -		for (i = 0; i < REGISTER_BUSY_COUNT; i++) { -			rt2800_register_read(rt2x00dev, CMB_CTRL, ®); -			if (rt2x00_get_field32(reg, PLL_LD) && -			    rt2x00_get_field32(reg, XTAL_RDY)) -				break; -			udelay(REGISTER_BUSY_DELAY); -		} - -		if (i >= REGISTER_BUSY_COUNT) { - -			if (count >= 10) -				return -EIO; - -			rt2800_register_write(rt2x00dev, 0x58, 0x018); -			udelay(REGISTER_BUSY_DELAY); -			rt2800_register_write(rt2x00dev, 0x58, 0x418); -			udelay(REGISTER_BUSY_DELAY); -			rt2800_register_write(rt2x00dev, 0x58, 0x618); -			udelay(REGISTER_BUSY_DELAY); -			count++; -		} else { -			count = 0; -		} - -		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); -		rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); -		rt2x00_set_field32(®, WLAN_CLK_EN, 1); -		rt2x00_set_field32(®, WLAN_RESET, 1); -		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); -		udelay(10); -		rt2x00_set_field32(®, WLAN_RESET, 0); -		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); -		udelay(10); -		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); -	} while (count != 0); - -	return 0; -}  static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; @@ -1063,17 +1003,6 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* -	 * In probe phase call rt2800_enable_wlan_rt3290 to enable wlan -	 * clk for rt3290. That avoid the MCU fail in start phase. -	 */ -	if (rt2x00_rt(rt2x00dev, RT3290)) { -		retval = rt2800_enable_wlan_rt3290(rt2x00dev); - -		if (retval) -			return retval; -	} - -	/*  	 * This device has multiple filters for control frames  	 * and has a separate filter for PS Poll frames.  	 */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index f32259686b4..3f7bc5cadf9 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2243,8 +2243,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)  static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)  { -	struct ieee80211_conf conf = { .flags = 0 }; -	struct rt2x00lib_conf libconf = { .conf = &conf }; +	struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf };  	rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);  } diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 71a30b02608..533024095c4 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -44,7 +44,7 @@ MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");  MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver");  MODULE_LICENSE("GPL"); -static struct usb_device_id rtl8187_table[] __devinitdata = { +static struct usb_device_id rtl8187_table[] = {  	/* Asus */  	{USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187},  	/* Belkin */ diff --git a/drivers/of/base.c b/drivers/of/base.c index c181b94abc3..d4a1c9a043e 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -364,6 +364,33 @@ struct device_node *of_get_next_child(const struct device_node *node,  EXPORT_SYMBOL(of_get_next_child);  /** + *	of_get_next_available_child - Find the next available child node + *	@node:	parent node + *	@prev:	previous child of the parent node, or NULL to get first + * + *      This function is like of_get_next_child(), except that it + *      automatically skips any disabled nodes (i.e. status = "disabled"). + */ +struct device_node *of_get_next_available_child(const struct device_node *node, +	struct device_node *prev) +{ +	struct device_node *next; + +	read_lock(&devtree_lock); +	next = prev ? prev->sibling : node->child; +	for (; next; next = next->sibling) { +		if (!of_device_is_available(next)) +			continue; +		if (of_node_get(next)) +			break; +	} +	of_node_put(prev); +	read_unlock(&devtree_lock); +	return next; +} +EXPORT_SYMBOL(of_get_next_available_child); + +/**   *	of_find_node_by_path - Find a node matching a full OF path   *	@path:	The full path to match   * diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index fbf7b26c7c8..c5792d622dc 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -266,8 +266,8 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)  	}  	if (!error) -		dev_printk(KERN_INFO, &dev->dev, -				"power state changed by ACPI to D%d\n", state); +		dev_info(&dev->dev, "power state changed by ACPI to %s\n", +			 pci_power_name(state));  	return error;  } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 185be370334..5270f1a9932 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -959,6 +959,13 @@ static int pci_pm_poweroff_noirq(struct device *dev)  	if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))  		pci_prepare_to_sleep(pci_dev); +	/* +	 * The reason for doing this here is the same as for the analogous code +	 * in pci_pm_suspend_noirq(). +	 */ +	if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) +		pci_write_config_word(pci_dev, PCI_COMMAND, 0); +  	return 0;  } diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index fb7f3bebdc6..dc5c126e398 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -657,11 +657,7 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev)  	if (p != NULL)  		return ERR_PTR(-EBUSY); -	p = create_pinctrl(dev); -	if (IS_ERR(p)) -		return p; - -	return p; +	return create_pinctrl(dev);  }  /** @@ -738,11 +734,8 @@ static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p,  			dev_dbg(p->dev, "using pinctrl dummy state (%s)\n",  				name);  			state = create_state(p, name); -			if (IS_ERR(state)) -				return state; -		} else { -			return ERR_PTR(-ENODEV); -		} +		} else +			state = ERR_PTR(-ENODEV);  	}  	return state; diff --git a/drivers/pinctrl/pinctrl-imx23.c b/drivers/pinctrl/pinctrl-imx23.c index 75d3eff9429..3674d877ed7 100644 --- a/drivers/pinctrl/pinctrl-imx23.c +++ b/drivers/pinctrl/pinctrl-imx23.c @@ -292,7 +292,7 @@ static int __init imx23_pinctrl_init(void)  {  	return platform_driver_register(&imx23_pinctrl_driver);  } -arch_initcall(imx23_pinctrl_init); +postcore_initcall(imx23_pinctrl_init);  static void __exit imx23_pinctrl_exit(void)  { diff --git a/drivers/pinctrl/pinctrl-imx28.c b/drivers/pinctrl/pinctrl-imx28.c index b973026811a..0f5b2122b1b 100644 --- a/drivers/pinctrl/pinctrl-imx28.c +++ b/drivers/pinctrl/pinctrl-imx28.c @@ -408,7 +408,7 @@ static int __init imx28_pinctrl_init(void)  {  	return platform_driver_register(&imx28_pinctrl_driver);  } -arch_initcall(imx28_pinctrl_init); +postcore_initcall(imx28_pinctrl_init);  static void __exit imx28_pinctrl_exit(void)  { diff --git a/drivers/pinctrl/pinctrl-imx51.c b/drivers/pinctrl/pinctrl-imx51.c index 689b3c88dd2..9fd02162a3c 100644 --- a/drivers/pinctrl/pinctrl-imx51.c +++ b/drivers/pinctrl/pinctrl-imx51.c @@ -974,7 +974,7 @@ static struct imx_pin_reg imx51_pin_regs[] = {  	IMX_PIN_REG(MX51_PAD_EIM_DA13, NO_PAD, 0x050, 0, 0x000, 0), /* MX51_PAD_EIM_DA13__EIM_DA13 */  	IMX_PIN_REG(MX51_PAD_EIM_DA14, NO_PAD, 0x054, 0, 0x000, 0), /* MX51_PAD_EIM_DA14__EIM_DA14 */  	IMX_PIN_REG(MX51_PAD_EIM_DA15, NO_PAD, 0x058, 0, 0x000, 0), /* MX51_PAD_EIM_DA15__EIM_DA15 */ -	IMX_PIN_REG(MX51_PAD_SD2_CMD, NO_PAD, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */ +	IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 2, 0x91c, 3), /* MX51_PAD_SD2_CMD__CSPI_MOSI */  	IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 1, 0x9b0, 2), /* MX51_PAD_SD2_CMD__I2C1_SCL */  	IMX_PIN_REG(MX51_PAD_SD2_CMD, 0x7bc, 0x3b4, 0, 0x000, 0), /* MX51_PAD_SD2_CMD__SD2_CMD */  	IMX_PIN_REG(MX51_PAD_SD2_CLK, 0x7c0, 0x3b8, 2, 0x914, 3), /* MX51_PAD_SD2_CLK__CSPI_SCLK */ diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c index 6f99769c673..a39fb7a6fc5 100644 --- a/drivers/pinctrl/pinctrl-nomadik-db8500.c +++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c @@ -505,6 +505,8 @@ static const unsigned kp_b_1_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1,  	DB8500_PIN_J3, DB8500_PIN_H2, DB8500_PIN_J2, DB8500_PIN_H1,  	DB8500_PIN_F4, DB8500_PIN_E3, DB8500_PIN_E4, DB8500_PIN_D2,  	DB8500_PIN_C1, DB8500_PIN_D3, DB8500_PIN_C2, DB8500_PIN_D5 }; +static const unsigned kp_b_2_pins[] = { DB8500_PIN_F3, DB8500_PIN_F1, +	DB8500_PIN_G3, DB8500_PIN_G2, DB8500_PIN_F4, DB8500_PIN_E3};  static const unsigned sm_b_1_pins[] = { DB8500_PIN_C6, DB8500_PIN_B3,  	DB8500_PIN_C4, DB8500_PIN_E6, DB8500_PIN_A3, DB8500_PIN_B6,  	DB8500_PIN_D6, DB8500_PIN_B7, DB8500_PIN_D7, DB8500_PIN_D8, @@ -662,6 +664,7 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {  	DB8500_PIN_GROUP(spi3_b_1, NMK_GPIO_ALT_B),  	DB8500_PIN_GROUP(msp1txrx_b_1, NMK_GPIO_ALT_B),  	DB8500_PIN_GROUP(kp_b_1, NMK_GPIO_ALT_B), +	DB8500_PIN_GROUP(kp_b_2, NMK_GPIO_ALT_B),  	DB8500_PIN_GROUP(sm_b_1, NMK_GPIO_ALT_B),  	DB8500_PIN_GROUP(smcs0_b_1, NMK_GPIO_ALT_B),  	DB8500_PIN_GROUP(smcs1_b_1, NMK_GPIO_ALT_B), @@ -751,7 +754,7 @@ DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1");  DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1");  DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1",  	"lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1"); -DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_c_1", "kp_oc1_1"); +DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1");  DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1");  DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1");  DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1"); @@ -766,7 +769,7 @@ DB8500_FUNC_GROUPS(ipgpio, "ipgpio0_a_1", "ipgpio1_a_1", "ipgpio7_b_1",  DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1");  DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1");  DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1dir_a_1"); -DB8500_FUNC_GROUPS(hsi, "hsir1_a_1", "hsit1_a_1", "hsit_a_2"); +DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");  DB8500_FUNC_GROUPS(clkout, "clkout_a_1", "clkout_a_2", "clkout_c_1");  DB8500_FUNC_GROUPS(usb, "usb_a_1");  DB8500_FUNC_GROUPS(trig, "trig_b_1"); diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 53b0d49a7a1..3dde6537adb 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -1292,7 +1292,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)  						NOMADIK_GPIO_TO_IRQ(pdata->first_gpio),  						0, &nmk_gpio_irq_simple_ops, nmk_chip);  	if (!nmk_chip->domain) { -		pr_err("%s: Failed to create irqdomain\n", np->full_name); +		dev_err(&dev->dev, "failed to create irqdomain\n");  		ret = -ENOSYS;  		goto out;  	} @@ -1731,7 +1731,6 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)  	for (i = 0; i < npct->soc->gpio_num_ranges; i++) {  		if (!nmk_gpio_chips[i]) {  			dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i); -			devm_kfree(&pdev->dev, npct);  			return -EPROBE_DEFER;  		}  		npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip; diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index 2aae8a8978e..7fca6ce5952 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -1217,7 +1217,6 @@ out_no_rsc_remap:  	iounmap(spmx->gpio_virtbase);  out_no_gpio_remap:  	platform_set_drvdata(pdev, NULL); -	devm_kfree(&pdev->dev, spmx);  	return ret;  } diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c index a7ad8c112d9..309f5b9a70e 100644 --- a/drivers/pinctrl/pinctrl-u300.c +++ b/drivers/pinctrl/pinctrl-u300.c @@ -1121,10 +1121,8 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)  	upmx->dev = &pdev->dev;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		ret = -ENOENT; -		goto out_no_resource; -	} +	if (!res) +		return -ENOENT;  	upmx->phybase = res->start;  	upmx->physize = resource_size(res); @@ -1165,8 +1163,6 @@ out_no_remap:  	platform_set_drvdata(pdev, NULL);  out_no_memregion:  	release_mem_region(upmx->phybase, upmx->physize); -out_no_resource: -	devm_kfree(&pdev->dev, upmx);  	return ret;  } diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 2a262f5c5c0..c86bae828c2 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -289,6 +289,7 @@ config IDEAPAD_LAPTOP  	tristate "Lenovo IdeaPad Laptop Extras"  	depends on ACPI  	depends on RFKILL && INPUT +	depends on SERIO_I8042  	select INPUT_SPARSEKMAP  	help  	  This is a driver for the rfkill switches on Lenovo IdeaPad netbooks. @@ -758,8 +759,11 @@ config SAMSUNG_Q10  config APPLE_GMUX  	tristate "Apple Gmux Driver" +	depends on ACPI  	depends on PNP -	select BACKLIGHT_CLASS_DEVICE +	depends on BACKLIGHT_CLASS_DEVICE +	depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE +	depends on ACPI_VIDEO=n || ACPI_VIDEO  	---help---  	  This driver provides support for the gmux device found on many  	  Apple laptops, which controls the display mux for the hybrid diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index 905fa01ac8d..dfb1a92ce94 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -2,6 +2,7 @@   *  Gmux driver for Apple laptops   *   *  Copyright (C) Canonical Ltd. <seth.forshee@canonical.com> + *  Copyright (C) 2010-2012 Andreas Heider <andreas@meetr.de>   *   *  This program is free software; you can redistribute it and/or modify   *  it under the terms of the GNU General Public License version 2 as @@ -18,16 +19,30 @@  #include <linux/pnp.h>  #include <linux/apple_bl.h>  #include <linux/slab.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/vga_switcheroo.h>  #include <acpi/video.h>  #include <asm/io.h>  struct apple_gmux_data {  	unsigned long iostart;  	unsigned long iolen; +	bool indexed; +	struct mutex index_lock;  	struct backlight_device *bdev; + +	/* switcheroo data */ +	acpi_handle dhandle; +	int gpe; +	enum vga_switcheroo_client_id resume_client_id; +	enum vga_switcheroo_state power_state; +	struct completion powerchange_done;  }; +static struct apple_gmux_data *apple_gmux_data; +  /*   * gmux port offsets. Many of these are not yet used, but may be in the   * future, and it's useful to have them documented here anyhow. @@ -45,6 +60,9 @@ struct apple_gmux_data {  #define GMUX_PORT_DISCRETE_POWER	0x50  #define GMUX_PORT_MAX_BRIGHTNESS	0x70  #define GMUX_PORT_BRIGHTNESS		0x74 +#define GMUX_PORT_VALUE			0xc2 +#define GMUX_PORT_READ			0xd0 +#define GMUX_PORT_WRITE			0xd4  #define GMUX_MIN_IO_LEN			(GMUX_PORT_BRIGHTNESS + 4) @@ -59,22 +77,172 @@ struct apple_gmux_data {  #define GMUX_BRIGHTNESS_MASK		0x00ffffff  #define GMUX_MAX_BRIGHTNESS		GMUX_BRIGHTNESS_MASK -static inline u8 gmux_read8(struct apple_gmux_data *gmux_data, int port) +static u8 gmux_pio_read8(struct apple_gmux_data *gmux_data, int port)  {  	return inb(gmux_data->iostart + port);  } -static inline void gmux_write8(struct apple_gmux_data *gmux_data, int port, +static void gmux_pio_write8(struct apple_gmux_data *gmux_data, int port,  			       u8 val)  {  	outb(val, gmux_data->iostart + port);  } -static inline u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) +static u32 gmux_pio_read32(struct apple_gmux_data *gmux_data, int port)  {  	return inl(gmux_data->iostart + port);  } +static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port, +			     u32 val) +{ +	int i; +	u8 tmpval; + +	for (i = 0; i < 4; i++) { +		tmpval = (val >> (i * 8)) & 0xff; +		outb(tmpval, port + i); +	} +} + +static int gmux_index_wait_ready(struct apple_gmux_data *gmux_data) +{ +	int i = 200; +	u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + +	while (i && (gwr & 0x01)) { +		inb(gmux_data->iostart + GMUX_PORT_READ); +		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); +		udelay(100); +		i--; +	} + +	return !!i; +} + +static int gmux_index_wait_complete(struct apple_gmux_data *gmux_data) +{ +	int i = 200; +	u8 gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); + +	while (i && !(gwr & 0x01)) { +		gwr = inb(gmux_data->iostart + GMUX_PORT_WRITE); +		udelay(100); +		i--; +	} + +	if (gwr & 0x01) +		inb(gmux_data->iostart + GMUX_PORT_READ); + +	return !!i; +} + +static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port) +{ +	u8 val; + +	mutex_lock(&gmux_data->index_lock); +	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); +	gmux_index_wait_ready(gmux_data); +	val = inb(gmux_data->iostart + GMUX_PORT_VALUE); +	mutex_unlock(&gmux_data->index_lock); + +	return val; +} + +static void gmux_index_write8(struct apple_gmux_data *gmux_data, int port, +			      u8 val) +{ +	mutex_lock(&gmux_data->index_lock); +	outb(val, gmux_data->iostart + GMUX_PORT_VALUE); +	gmux_index_wait_ready(gmux_data); +	outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); +	gmux_index_wait_complete(gmux_data); +	mutex_unlock(&gmux_data->index_lock); +} + +static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port) +{ +	u32 val; + +	mutex_lock(&gmux_data->index_lock); +	outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ); +	gmux_index_wait_ready(gmux_data); +	val = inl(gmux_data->iostart + GMUX_PORT_VALUE); +	mutex_unlock(&gmux_data->index_lock); + +	return val; +} + +static void gmux_index_write32(struct apple_gmux_data *gmux_data, int port, +			       u32 val) +{ +	int i; +	u8 tmpval; + +	mutex_lock(&gmux_data->index_lock); + +	for (i = 0; i < 4; i++) { +		tmpval = (val >> (i * 8)) & 0xff; +		outb(tmpval, gmux_data->iostart + GMUX_PORT_VALUE + i); +	} + +	gmux_index_wait_ready(gmux_data); +	outb(port & 0xff, gmux_data->iostart + GMUX_PORT_WRITE); +	gmux_index_wait_complete(gmux_data); +	mutex_unlock(&gmux_data->index_lock); +} + +static u8 gmux_read8(struct apple_gmux_data *gmux_data, int port) +{ +	if (gmux_data->indexed) +		return gmux_index_read8(gmux_data, port); +	else +		return gmux_pio_read8(gmux_data, port); +} + +static void gmux_write8(struct apple_gmux_data *gmux_data, int port, u8 val) +{ +	if (gmux_data->indexed) +		gmux_index_write8(gmux_data, port, val); +	else +		gmux_pio_write8(gmux_data, port, val); +} + +static u32 gmux_read32(struct apple_gmux_data *gmux_data, int port) +{ +	if (gmux_data->indexed) +		return gmux_index_read32(gmux_data, port); +	else +		return gmux_pio_read32(gmux_data, port); +} + +static void gmux_write32(struct apple_gmux_data *gmux_data, int port, +			     u32 val) +{ +	if (gmux_data->indexed) +		gmux_index_write32(gmux_data, port, val); +	else +		gmux_pio_write32(gmux_data, port, val); +} + +static bool gmux_is_indexed(struct apple_gmux_data *gmux_data) +{ +	u16 val; + +	outb(0xaa, gmux_data->iostart + 0xcc); +	outb(0x55, gmux_data->iostart + 0xcd); +	outb(0x00, gmux_data->iostart + 0xce); + +	val = inb(gmux_data->iostart + 0xcc) | +		(inb(gmux_data->iostart + 0xcd) << 8); + +	if (val == 0x55aa) +		return true; + +	return false; +} +  static int gmux_get_brightness(struct backlight_device *bd)  {  	struct apple_gmux_data *gmux_data = bl_get_data(bd); @@ -90,16 +258,7 @@ static int gmux_update_status(struct backlight_device *bd)  	if (bd->props.state & BL_CORE_SUSPENDED)  		return 0; -	/* -	 * Older gmux versions require writing out lower bytes first then -	 * setting the upper byte to 0 to flush the values. Newer versions -	 * accept a single u32 write, but the old method also works, so we -	 * just use the old method for all gmux versions. -	 */ -	gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS, brightness); -	gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 1, brightness >> 8); -	gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 2, brightness >> 16); -	gmux_write8(gmux_data, GMUX_PORT_BRIGHTNESS + 3, 0); +	gmux_write32(gmux_data, GMUX_PORT_BRIGHTNESS, brightness);  	return 0;  } @@ -110,6 +269,146 @@ static const struct backlight_ops gmux_bl_ops = {  	.update_status = gmux_update_status,  }; +static int gmux_switchto(enum vga_switcheroo_client_id id) +{ +	if (id == VGA_SWITCHEROO_IGD) { +		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1); +		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2); +		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2); +	} else { +		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2); +		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3); +		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3); +	} + +	return 0; +} + +static int gmux_set_discrete_state(struct apple_gmux_data *gmux_data, +				   enum vga_switcheroo_state state) +{ +	INIT_COMPLETION(gmux_data->powerchange_done); + +	if (state == VGA_SWITCHEROO_ON) { +		gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); +		gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 3); +		pr_debug("Discrete card powered up\n"); +	} else { +		gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 1); +		gmux_write8(gmux_data, GMUX_PORT_DISCRETE_POWER, 0); +		pr_debug("Discrete card powered down\n"); +	} + +	gmux_data->power_state = state; + +	if (gmux_data->gpe >= 0 && +	    !wait_for_completion_interruptible_timeout(&gmux_data->powerchange_done, +						       msecs_to_jiffies(200))) +		pr_warn("Timeout waiting for gmux switch to complete\n"); + +	return 0; +} + +static int gmux_set_power_state(enum vga_switcheroo_client_id id, +				enum vga_switcheroo_state state) +{ +	if (id == VGA_SWITCHEROO_IGD) +		return 0; + +	return gmux_set_discrete_state(apple_gmux_data, state); +} + +static int gmux_get_client_id(struct pci_dev *pdev) +{ +	/* +	 * Early Macbook Pros with switchable graphics use nvidia +	 * integrated graphics. Hardcode that the 9400M is integrated. +	 */ +	if (pdev->vendor == PCI_VENDOR_ID_INTEL) +		return VGA_SWITCHEROO_IGD; +	else if (pdev->vendor == PCI_VENDOR_ID_NVIDIA && +		 pdev->device == 0x0863) +		return VGA_SWITCHEROO_IGD; +	else +		return VGA_SWITCHEROO_DIS; +} + +static enum vga_switcheroo_client_id +gmux_active_client(struct apple_gmux_data *gmux_data) +{ +	if (gmux_read8(gmux_data, GMUX_PORT_SWITCH_DISPLAY) == 2) +		return VGA_SWITCHEROO_IGD; + +	return VGA_SWITCHEROO_DIS; +} + +static struct vga_switcheroo_handler gmux_handler = { +	.switchto = gmux_switchto, +	.power_state = gmux_set_power_state, +	.get_client_id = gmux_get_client_id, +}; + +static inline void gmux_disable_interrupts(struct apple_gmux_data *gmux_data) +{ +	gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, +		    GMUX_INTERRUPT_DISABLE); +} + +static inline void gmux_enable_interrupts(struct apple_gmux_data *gmux_data) +{ +	gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_ENABLE, +		    GMUX_INTERRUPT_ENABLE); +} + +static inline u8 gmux_interrupt_get_status(struct apple_gmux_data *gmux_data) +{ +	return gmux_read8(gmux_data, GMUX_PORT_INTERRUPT_STATUS); +} + +static void gmux_clear_interrupts(struct apple_gmux_data *gmux_data) +{ +	u8 status; + +	/* to clear interrupts write back current status */ +	status = gmux_interrupt_get_status(gmux_data); +	gmux_write8(gmux_data, GMUX_PORT_INTERRUPT_STATUS, status); +} + +static void gmux_notify_handler(acpi_handle device, u32 value, void *context) +{ +	u8 status; +	struct pnp_dev *pnp = (struct pnp_dev *)context; +	struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); + +	status = gmux_interrupt_get_status(gmux_data); +	gmux_disable_interrupts(gmux_data); +	pr_debug("Notify handler called: status %d\n", status); + +	gmux_clear_interrupts(gmux_data); +	gmux_enable_interrupts(gmux_data); + +	if (status & GMUX_INTERRUPT_STATUS_POWER) +		complete(&gmux_data->powerchange_done); +} + +static int gmux_suspend(struct pnp_dev *pnp, pm_message_t state) +{ +	struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); +	gmux_data->resume_client_id = gmux_active_client(gmux_data); +	gmux_disable_interrupts(gmux_data); +	return 0; +} + +static int gmux_resume(struct pnp_dev *pnp) +{ +	struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); +	gmux_enable_interrupts(gmux_data); +	gmux_switchto(gmux_data->resume_client_id); +	if (gmux_data->power_state == VGA_SWITCHEROO_OFF) +		gmux_set_discrete_state(gmux_data, gmux_data->power_state); +	return 0; +} +  static int __devinit gmux_probe(struct pnp_dev *pnp,  				const struct pnp_device_id *id)  { @@ -119,6 +418,11 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,  	struct backlight_device *bdev;  	u8 ver_major, ver_minor, ver_release;  	int ret = -ENXIO; +	acpi_status status; +	unsigned long long gpe; + +	if (apple_gmux_data) +		return -EBUSY;  	gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL);  	if (!gmux_data) @@ -147,22 +451,29 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,  	}  	/* -	 * On some machines the gmux is in ACPI even thought the machine -	 * doesn't really have a gmux. Check for invalid version information -	 * to detect this. +	 * Invalid version information may indicate either that the gmux +	 * device isn't present or that it's a new one that uses indexed +	 * io  	 */ +  	ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR);  	ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR);  	ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);  	if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { -		pr_info("gmux device not present\n"); -		ret = -ENODEV; -		goto err_release; +		if (gmux_is_indexed(gmux_data)) { +			mutex_init(&gmux_data->index_lock); +			gmux_data->indexed = true; +		} else { +			pr_info("gmux device not present\n"); +			ret = -ENODEV; +			goto err_release; +		} +		pr_info("Found indexed gmux\n"); +	} else { +		pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, +			ver_release);  	} -	pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor, -		ver_release); -  	memset(&props, 0, sizeof(props));  	props.type = BACKLIGHT_PLATFORM;  	props.max_brightness = gmux_read32(gmux_data, GMUX_PORT_MAX_BRIGHTNESS); @@ -194,13 +505,67 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,  	 * Disable the other backlight choices.  	 */  	acpi_video_dmi_promote_vendor(); -#ifdef CONFIG_ACPI_VIDEO +#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE)  	acpi_video_unregister();  #endif  	apple_bl_unregister(); +	gmux_data->power_state = VGA_SWITCHEROO_ON; + +	gmux_data->dhandle = DEVICE_ACPI_HANDLE(&pnp->dev); +	if (!gmux_data->dhandle) { +		pr_err("Cannot find acpi handle for pnp device %s\n", +		       dev_name(&pnp->dev)); +		ret = -ENODEV; +		goto err_notify; +	} + +	status = acpi_evaluate_integer(gmux_data->dhandle, "GMGP", NULL, &gpe); +	if (ACPI_SUCCESS(status)) { +		gmux_data->gpe = (int)gpe; + +		status = acpi_install_notify_handler(gmux_data->dhandle, +						     ACPI_DEVICE_NOTIFY, +						     &gmux_notify_handler, pnp); +		if (ACPI_FAILURE(status)) { +			pr_err("Install notify handler failed: %s\n", +			       acpi_format_exception(status)); +			ret = -ENODEV; +			goto err_notify; +		} + +		status = acpi_enable_gpe(NULL, gmux_data->gpe); +		if (ACPI_FAILURE(status)) { +			pr_err("Cannot enable gpe: %s\n", +			       acpi_format_exception(status)); +			goto err_enable_gpe; +		} +	} else { +		pr_warn("No GPE found for gmux\n"); +		gmux_data->gpe = -1; +	} + +	if (vga_switcheroo_register_handler(&gmux_handler)) { +		ret = -ENODEV; +		goto err_register_handler; +	} + +	init_completion(&gmux_data->powerchange_done); +	apple_gmux_data = gmux_data; +	gmux_enable_interrupts(gmux_data); +  	return 0; +err_register_handler: +	if (gmux_data->gpe >= 0) +		acpi_disable_gpe(NULL, gmux_data->gpe); +err_enable_gpe: +	if (gmux_data->gpe >= 0) +		acpi_remove_notify_handler(gmux_data->dhandle, +					   ACPI_DEVICE_NOTIFY, +					   &gmux_notify_handler); +err_notify: +	backlight_device_unregister(bdev);  err_release:  	release_region(gmux_data->iostart, gmux_data->iolen);  err_free: @@ -212,12 +577,23 @@ static void __devexit gmux_remove(struct pnp_dev *pnp)  {  	struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp); +	vga_switcheroo_unregister_handler(); +	gmux_disable_interrupts(gmux_data); +	if (gmux_data->gpe >= 0) { +		acpi_disable_gpe(NULL, gmux_data->gpe); +		acpi_remove_notify_handler(gmux_data->dhandle, +					   ACPI_DEVICE_NOTIFY, +					   &gmux_notify_handler); +	} +  	backlight_device_unregister(gmux_data->bdev); +  	release_region(gmux_data->iostart, gmux_data->iolen); +	apple_gmux_data = NULL;  	kfree(gmux_data);  	acpi_video_dmi_demote_vendor(); -#ifdef CONFIG_ACPI_VIDEO +#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE)  	acpi_video_register();  #endif  	apple_bl_register(); @@ -233,6 +609,8 @@ static struct pnp_driver gmux_pnp_driver = {  	.probe		= gmux_probe,  	.remove		= __devexit_p(gmux_remove),  	.id_table	= gmux_device_ids, +	.suspend	= gmux_suspend, +	.resume		= gmux_resume  };  static int __init apple_gmux_init(void) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index c7a36f6b058..2eb9fe8e8ef 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -101,6 +101,7 @@ MODULE_LICENSE("GPL");  #define ASUS_WMI_DEVID_WIRELESS_LED	0x00010002  #define ASUS_WMI_DEVID_CWAP		0x00010003  #define ASUS_WMI_DEVID_WLAN		0x00010011 +#define ASUS_WMI_DEVID_WLAN_LED		0x00010012  #define ASUS_WMI_DEVID_BLUETOOTH	0x00010013  #define ASUS_WMI_DEVID_GPS		0x00010015  #define ASUS_WMI_DEVID_WIMAX		0x00010017 @@ -731,8 +732,21 @@ static int asus_rfkill_set(void *data, bool blocked)  {  	struct asus_rfkill *priv = data;  	u32 ctrl_param = !blocked; +	u32 dev_id = priv->dev_id; -	return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL); +	/* +	 * If the user bit is set, BIOS can't set and record the wlan status, +	 * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED +	 * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN). +	 * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED +	 * while setting the wlan status through WMI. +	 * This is also the behavior that windows app will do. +	 */ +	if ((dev_id == ASUS_WMI_DEVID_WLAN) && +	     priv->asus->driver->wlan_ctrl_by_user) +		dev_id = ASUS_WMI_DEVID_WLAN_LED; + +	return asus_wmi_set_devstate(dev_id, ctrl_param, NULL);  }  static void asus_rfkill_query(struct rfkill *rfkill, void *data) @@ -1653,6 +1667,7 @@ static int asus_wmi_add(struct platform_device *pdev)  	struct asus_wmi *asus;  	acpi_status status;  	int err; +	u32 result;  	asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);  	if (!asus) @@ -1711,6 +1726,10 @@ static int asus_wmi_add(struct platform_device *pdev)  	if (err)  		goto fail_debugfs; +	asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result); +	if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT)) +		asus->driver->wlan_ctrl_by_user = 1; +  	return 0;  fail_debugfs: diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index 9c1da8b81be..4c9bd38bb0a 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -46,6 +46,7 @@ struct quirk_entry {  struct asus_wmi_driver {  	int			brightness;  	int			panel_power; +	int			wlan_ctrl_by_user;  	const char		*name;  	struct module		*owner; diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c index 2ca7dd1ab3e..c87ff16873f 100644 --- a/drivers/platform/x86/classmate-laptop.c +++ b/drivers/platform/x86/classmate-laptop.c @@ -350,6 +350,7 @@ static void cmpc_accel_idev_init_v4(struct input_dev *inputdev)  	inputdev->close = cmpc_accel_close_v4;  } +#ifdef CONFIG_PM_SLEEP  static int cmpc_accel_suspend_v4(struct device *dev)  {  	struct input_dev *inputdev; @@ -384,6 +385,7 @@ static int cmpc_accel_resume_v4(struct device *dev)  	return 0;  } +#endif  static int cmpc_accel_add_v4(struct acpi_device *acpi)  { @@ -723,8 +725,10 @@ static void cmpc_tablet_handler(struct acpi_device *dev, u32 event)  	struct input_dev *inputdev = dev_get_drvdata(&dev->dev);  	if (event == 0x81) { -		if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) +		if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) {  			input_report_switch(inputdev, SW_TABLET_MODE, !val); +			input_sync(inputdev); +		}  	}  } @@ -737,8 +741,10 @@ static void cmpc_tablet_idev_init(struct input_dev *inputdev)  	set_bit(SW_TABLET_MODE, inputdev->swbit);  	acpi = to_acpi_device(inputdev->dev.parent); -	if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) +	if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) {  		input_report_switch(inputdev, SW_TABLET_MODE, !val); +		input_sync(inputdev); +	}  }  static int cmpc_tablet_add(struct acpi_device *acpi) @@ -752,15 +758,19 @@ static int cmpc_tablet_remove(struct acpi_device *acpi, int type)  	return cmpc_remove_acpi_notify_device(acpi);  } +#ifdef CONFIG_PM_SLEEP  static int cmpc_tablet_resume(struct device *dev)  {  	struct input_dev *inputdev = dev_get_drvdata(dev);  	unsigned long long val = 0; -	if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val))) +	if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val))) {  		input_report_switch(inputdev, SW_TABLET_MODE, !val); +		input_sync(inputdev); +	}  	return 0;  } +#endif  static SIMPLE_DEV_PM_OPS(cmpc_tablet_pm, NULL, cmpc_tablet_resume); diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 4e96e8c0b60..927c33af67e 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -211,7 +211,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {  		.ident = "Dell Inspiron 5420",  		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5420"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5420"),  		},  		.driver_data = &quirk_dell_vostro_v130,  	}, @@ -220,7 +220,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {  		.ident = "Dell Inspiron 5520",  		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5520"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5520"),  		},  		.driver_data = &quirk_dell_vostro_v130,  	}, @@ -229,7 +229,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {  		.ident = "Dell Inspiron 5720",  		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 5720"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5720"),  		},  		.driver_data = &quirk_dell_vostro_v130,  	}, @@ -238,7 +238,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {  		.ident = "Dell Inspiron 7420",  		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7420"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7420"),  		},  		.driver_data = &quirk_dell_vostro_v130,  	}, @@ -247,7 +247,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {  		.ident = "Dell Inspiron 7520",  		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7520"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7520"),  		},  		.driver_data = &quirk_dell_vostro_v130,  	}, @@ -256,7 +256,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = {  		.ident = "Dell Inspiron 7720",  		.matches = {  			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), -			DMI_MATCH(DMI_PRODUCT_NAME, "Isnpiron 7720"), +			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7720"),  		},  		.driver_data = &quirk_dell_vostro_v130,  	}, diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c index d2e41735a47..7acae3f85f3 100644 --- a/drivers/platform/x86/fujitsu-tablet.c +++ b/drivers/platform/x86/fujitsu-tablet.c @@ -440,11 +440,13 @@ static int __devexit acpi_fujitsu_remove(struct acpi_device *adev, int type)  	return 0;  } +#ifdef CONFIG_PM_SLEEP  static int acpi_fujitsu_resume(struct device *dev)  {  	fujitsu_reset();  	return 0;  } +#endif  static SIMPLE_DEV_PM_OPS(acpi_fujitsu_pm, NULL, acpi_fujitsu_resume); diff --git a/drivers/platform/x86/hdaps.c b/drivers/platform/x86/hdaps.c index d9ab6f64dce..777c7e3dda5 100644 --- a/drivers/platform/x86/hdaps.c +++ b/drivers/platform/x86/hdaps.c @@ -305,10 +305,12 @@ static int hdaps_probe(struct platform_device *dev)  	return 0;  } +#ifdef CONFIG_PM_SLEEP  static int hdaps_resume(struct device *dev)  {  	return hdaps_device_init();  } +#endif  static SIMPLE_DEV_PM_OPS(hdaps_pm, NULL, hdaps_resume); diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index f4d91154ad6..6b9af989632 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -352,7 +352,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int lis3lv02d_suspend(struct device *dev)  {  	/* make sure the device is off when we suspend */ diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 17f6dfd8dbf..dae7abe1d71 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -36,6 +36,7 @@  #include <linux/fb.h>  #include <linux/debugfs.h>  #include <linux/seq_file.h> +#include <linux/i8042.h>  #define IDEAPAD_RFKILL_DEV_NUM	(3) @@ -63,8 +64,11 @@ enum {  	VPCCMD_R_3G,  	VPCCMD_W_3G,  	VPCCMD_R_ODD, /* 0x21 */ -	VPCCMD_R_RF = 0x23, +	VPCCMD_W_FAN, +	VPCCMD_R_RF,  	VPCCMD_W_RF, +	VPCCMD_R_FAN = 0x2B, +	VPCCMD_R_SPECIAL_BUTTONS = 0x31,  	VPCCMD_W_BL_POWER = 0x33,  }; @@ -356,14 +360,46 @@ static ssize_t store_ideapad_cam(struct device *dev,  		return -EINVAL;  	ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state);  	if (ret < 0) -		return ret; +		return -EIO;  	return count;  }  static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam); +static ssize_t show_ideapad_fan(struct device *dev, +				struct device_attribute *attr, +				char *buf) +{ +	unsigned long result; + +	if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result)) +		return sprintf(buf, "-1\n"); +	return sprintf(buf, "%lu\n", result); +} + +static ssize_t store_ideapad_fan(struct device *dev, +				 struct device_attribute *attr, +				 const char *buf, size_t count) +{ +	int ret, state; + +	if (!count) +		return 0; +	if (sscanf(buf, "%i", &state) != 1) +		return -EINVAL; +	if (state < 0 || state > 4 || state == 3) +		return -EINVAL; +	ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state); +	if (ret < 0) +		return -EIO; +	return count; +} + +static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan); +  static struct attribute *ideapad_attributes[] = {  	&dev_attr_camera_power.attr, +	&dev_attr_fan_mode.attr,  	NULL  }; @@ -377,7 +413,10 @@ static umode_t ideapad_is_visible(struct kobject *kobj,  	if (attr == &dev_attr_camera_power.attr)  		supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg)); -	else +	else if (attr == &dev_attr_fan_mode.attr) { +		unsigned long value; +		supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value); +	} else  		supported = true;  	return supported ? attr->mode : 0; @@ -518,9 +557,15 @@ static void ideapad_platform_exit(struct ideapad_private *priv)   */  static const struct key_entry ideapad_keymap[] = {  	{ KE_KEY, 6,  { KEY_SWITCHVIDEOMODE } }, +	{ KE_KEY, 7,  { KEY_CAMERA } }, +	{ KE_KEY, 11, { KEY_F16 } },  	{ KE_KEY, 13, { KEY_WLAN } },  	{ KE_KEY, 16, { KEY_PROG1 } },  	{ KE_KEY, 17, { KEY_PROG2 } }, +	{ KE_KEY, 64, { KEY_PROG3 } }, +	{ KE_KEY, 65, { KEY_PROG4 } }, +	{ KE_KEY, 66, { KEY_TOUCHPAD_OFF } }, +	{ KE_KEY, 67, { KEY_TOUCHPAD_ON } },  	{ KE_END, 0 },  }; @@ -587,6 +632,28 @@ static void ideapad_input_novokey(struct ideapad_private *priv)  		ideapad_input_report(priv, 16);  } +static void ideapad_check_special_buttons(struct ideapad_private *priv) +{ +	unsigned long bit, value; + +	read_ec_data(ideapad_handle, VPCCMD_R_SPECIAL_BUTTONS, &value); + +	for (bit = 0; bit < 16; bit++) { +		if (test_bit(bit, &value)) { +			switch (bit) { +			case 6: +				/* Thermal Management button */ +				ideapad_input_report(priv, 65); +				break; +			case 1: +				/* OneKey Theater button */ +				ideapad_input_report(priv, 64); +				break; +			} +		} +	} +} +  /*   * backlight   */ @@ -691,6 +758,24 @@ static const struct acpi_device_id ideapad_device_ids[] = {  };  MODULE_DEVICE_TABLE(acpi, ideapad_device_ids); +static void ideapad_sync_touchpad_state(struct acpi_device *adevice) +{ +	struct ideapad_private *priv = dev_get_drvdata(&adevice->dev); +	unsigned long value; + +	/* Without reading from EC touchpad LED doesn't switch state */ +	if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) { +		/* Some IdeaPads don't really turn off touchpad - they only +		 * switch the LED state. We (de)activate KBC AUX port to turn +		 * touchpad off and on. We send KEY_TOUCHPAD_OFF and +		 * KEY_TOUCHPAD_ON to not to get out of sync with LED */ +		unsigned char param; +		i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE : +			      I8042_CMD_AUX_DISABLE); +		ideapad_input_report(priv, value ? 67 : 66); +	} +} +  static int __devinit ideapad_acpi_add(struct acpi_device *adevice)  {  	int ret, i; @@ -727,6 +812,7 @@ static int __devinit ideapad_acpi_add(struct acpi_device *adevice)  			priv->rfk[i] = NULL;  	}  	ideapad_sync_rfk_state(priv); +	ideapad_sync_touchpad_state(adevice);  	if (!acpi_video_backlight_support()) {  		ret = ideapad_backlight_init(priv); @@ -785,9 +871,14 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)  				ideapad_sync_rfk_state(priv);  				break;  			case 13: +			case 11: +			case 7:  			case 6:  				ideapad_input_report(priv, vpc_bit);  				break; +			case 5: +				ideapad_sync_touchpad_state(adevice); +				break;  			case 4:  				ideapad_backlight_notify_brightness(priv);  				break; @@ -797,6 +888,9 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)  			case 2:  				ideapad_backlight_notify_power(priv);  				break; +			case 0: +				ideapad_check_special_buttons(priv); +				break;  			default:  				pr_info("Unknown event: %lu\n", vpc_bit);  			} @@ -804,6 +898,15 @@ static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)  	}  } +static int ideapad_acpi_resume(struct device *device) +{ +	ideapad_sync_rfk_state(ideapad_priv); +	ideapad_sync_touchpad_state(to_acpi_device(device)); +	return 0; +} + +static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume); +  static struct acpi_driver ideapad_acpi_driver = {  	.name = "ideapad_acpi",  	.class = "IdeaPad", @@ -811,6 +914,7 @@ static struct acpi_driver ideapad_acpi_driver = {  	.ops.add = ideapad_acpi_add,  	.ops.remove = ideapad_acpi_remove,  	.ops.notify = ideapad_acpi_notify, +	.drv.pm = &ideapad_pm,  	.owner = THIS_MODULE,  }; diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c index f6444184431..2111dbb7e1e 100644 --- a/drivers/platform/x86/msi-laptop.c +++ b/drivers/platform/x86/msi-laptop.c @@ -85,7 +85,9 @@  #define MSI_STANDARD_EC_TOUCHPAD_ADDRESS	0xe4  #define MSI_STANDARD_EC_TOUCHPAD_MASK		(1 << 4) +#ifdef CONFIG_PM_SLEEP  static int msi_laptop_resume(struct device *device); +#endif  static SIMPLE_DEV_PM_OPS(msi_laptop_pm, NULL, msi_laptop_resume);  #define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS	0x2f @@ -753,6 +755,7 @@ err_bluetooth:  	return retval;  } +#ifdef CONFIG_PM_SLEEP  static int msi_laptop_resume(struct device *device)  {  	u8 data; @@ -773,6 +776,7 @@ static int msi_laptop_resume(struct device *device)  	return 0;  } +#endif  static int __init msi_laptop_input_setup(void)  { diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index 24480074bcf..8e8caa767d6 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -188,7 +188,9 @@ static const struct acpi_device_id pcc_device_ids[] = {  };  MODULE_DEVICE_TABLE(acpi, pcc_device_ids); +#ifdef CONFIG_PM_SLEEP  static int acpi_pcc_hotkey_resume(struct device *dev); +#endif  static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume);  static struct acpi_driver acpi_pcc_driver = { @@ -540,6 +542,7 @@ static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)  /* kernel module interface */ +#ifdef CONFIG_PM_SLEEP  static int acpi_pcc_hotkey_resume(struct device *dev)  {  	struct pcc_acpi *pcc; @@ -556,6 +559,7 @@ static int acpi_pcc_hotkey_resume(struct device *dev)  	return acpi_pcc_write_sset(pcc, SINF_STICKY_KEY, pcc->sticky_mode);  } +#endif  static int acpi_pcc_hotkey_add(struct acpi_device *device)  { diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 9363969ad07..daaddec68de 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -140,7 +140,10 @@ MODULE_PARM_DESC(kbd_backlight_timeout,  		 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "  		 "(default: 0)"); +#ifdef CONFIG_PM_SLEEP  static void sony_nc_kbd_backlight_resume(void); +static void sony_nc_thermal_resume(void); +#endif  static int sony_nc_kbd_backlight_setup(struct platform_device *pd,  		unsigned int handle);  static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd); @@ -151,7 +154,6 @@ static void sony_nc_battery_care_cleanup(struct platform_device *pd);  static int sony_nc_thermal_setup(struct platform_device *pd);  static void sony_nc_thermal_cleanup(struct platform_device *pd); -static void sony_nc_thermal_resume(void);  static int sony_nc_lid_resume_setup(struct platform_device *pd);  static void sony_nc_lid_resume_cleanup(struct platform_device *pd); @@ -1431,6 +1433,7 @@ static void sony_nc_function_cleanup(struct platform_device *pd)  	sony_nc_handles_cleanup(pd);  } +#ifdef CONFIG_PM_SLEEP  static void sony_nc_function_resume(void)  {  	unsigned int i, result, bitmask, arg; @@ -1508,6 +1511,7 @@ static int sony_nc_resume(struct device *dev)  	return 0;  } +#endif  static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume); @@ -1872,6 +1876,7 @@ static void sony_nc_kbd_backlight_cleanup(struct platform_device *pd)  	}  } +#ifdef CONFIG_PM_SLEEP  static void sony_nc_kbd_backlight_resume(void)  {  	int ignore = 0; @@ -1888,6 +1893,7 @@ static void sony_nc_kbd_backlight_resume(void)  				(kbdbl_ctl->base + 0x200) |  				(kbdbl_ctl->timeout << 0x10), &ignore);  } +#endif  struct battery_care_control {  	struct device_attribute attrs[2]; @@ -2210,6 +2216,7 @@ static void sony_nc_thermal_cleanup(struct platform_device *pd)  	}  } +#ifdef CONFIG_PM_SLEEP  static void sony_nc_thermal_resume(void)  {  	unsigned int status = sony_nc_thermal_mode_get(); @@ -2217,6 +2224,7 @@ static void sony_nc_thermal_resume(void)  	if (status != th_handle->mode)  		sony_nc_thermal_mode_set(th_handle->mode);  } +#endif  /* resume on LID open */  struct snc_lid_resume_control { @@ -4287,6 +4295,7 @@ err_free_resources:  	return result;  } +#ifdef CONFIG_PM_SLEEP  static int sony_pic_suspend(struct device *dev)  {  	if (sony_pic_disable(to_acpi_device(dev))) @@ -4300,6 +4309,7 @@ static int sony_pic_resume(struct device *dev)  			spic_dev.cur_ioport, spic_dev.cur_irq);  	return 0;  } +#endif  static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume); diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e7f73287636..80e37794931 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -922,6 +922,7 @@ static struct input_dev *tpacpi_inputdev;  static struct mutex tpacpi_inputdev_send_mutex;  static LIST_HEAD(tpacpi_all_drivers); +#ifdef CONFIG_PM_SLEEP  static int tpacpi_suspend_handler(struct device *dev)  {  	struct ibm_struct *ibm, *itmp; @@ -949,6 +950,7 @@ static int tpacpi_resume_handler(struct device *dev)  	return 0;  } +#endif  static SIMPLE_DEV_PM_OPS(tpacpi_pm,  			 tpacpi_suspend_handler, tpacpi_resume_handler); @@ -8662,6 +8664,13 @@ static int __must_check __init get_thinkpad_model_data(  		tp->model_str = kstrdup(s, GFP_KERNEL);  		if (!tp->model_str)  			return -ENOMEM; +	} else { +		s = dmi_get_system_info(DMI_BIOS_VENDOR); +		if (s && !(strnicmp(s, "Lenovo", 6))) { +			tp->model_str = kstrdup(s, GFP_KERNEL); +			if (!tp->model_str) +				return -ENOMEM; +		}  	}  	s = dmi_get_system_info(DMI_PRODUCT_NAME); diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index c13ba5bac93..5f1256d5e93 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1296,6 +1296,7 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)  	}  } +#ifdef CONFIG_PM_SLEEP  static int toshiba_acpi_suspend(struct device *device)  {  	struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device)); @@ -1317,6 +1318,7 @@ static int toshiba_acpi_resume(struct device *device)  	return 0;  } +#endif  static SIMPLE_DEV_PM_OPS(toshiba_acpi_pm,  			 toshiba_acpi_suspend, toshiba_acpi_resume); diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c index 715a43cb5e3..5e5d6317d69 100644 --- a/drivers/platform/x86/toshiba_bluetooth.c +++ b/drivers/platform/x86/toshiba_bluetooth.c @@ -41,7 +41,9 @@ static const struct acpi_device_id bt_device_ids[] = {  };  MODULE_DEVICE_TABLE(acpi, bt_device_ids); +#ifdef CONFIG_PM_SLEEP  static int toshiba_bt_resume(struct device *dev); +#endif  static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume);  static struct acpi_driver toshiba_bt_rfkill_driver = { @@ -90,10 +92,12 @@ static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)  	toshiba_bluetooth_enable(device->handle);  } +#ifdef CONFIG_PM_SLEEP  static int toshiba_bt_resume(struct device *dev)  {  	return toshiba_bluetooth_enable(to_acpi_device(dev)->handle);  } +#endif  static int toshiba_bt_rfkill_add(struct acpi_device *device)  { diff --git a/drivers/platform/x86/xo15-ebook.c b/drivers/platform/x86/xo15-ebook.c index 849c07c13bf..38ba39d7ca7 100644 --- a/drivers/platform/x86/xo15-ebook.c +++ b/drivers/platform/x86/xo15-ebook.c @@ -77,10 +77,12 @@ static void ebook_switch_notify(struct acpi_device *device, u32 event)  	}  } +#ifdef CONFIG_PM_SLEEP  static int ebook_switch_resume(struct device *dev)  {  	return ebook_send_state(to_acpi_device(dev));  } +#endif  static SIMPLE_DEV_PM_OPS(ebook_switch_pm, NULL, ebook_switch_resume); diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 8fc3808d7a3..90c5c7357a5 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -1,12 +1,31 @@  menuconfig PWM -	bool "PWM Support" +	bool "Pulse-Width Modulation (PWM) Support"  	depends on !MACH_JZ4740 && !PUV3_PWM  	help -	  This enables PWM support through the generic PWM framework. -	  You only need to enable this, if you also want to enable -	  one or more of the PWM drivers below. +	  Generic Pulse-Width Modulation (PWM) support. -	  If unsure, say N. +	  In Pulse-Width Modulation, a variation of the width of pulses +	  in a rectangular pulse signal is used as a means to alter the +	  average power of the signal. Applications include efficient +	  power delivery and voltage regulation. In computer systems, +	  PWMs are commonly used to control fans or the brightness of +	  display backlights. + +	  This framework provides a generic interface to PWM devices +	  within the Linux kernel. On the driver side it provides an API +	  to register and unregister a PWM chip, an abstraction of a PWM +	  controller, that supports one or more PWM devices. Client +	  drivers can request PWM devices and use the generic framework +	  to configure as well as enable and disable them. + +	  This generic framework replaces the legacy PWM framework which +	  allows only a single driver implementing the required API. Not +	  all legacy implementations have been ported to the framework +	  yet. The framework provides an API that is backward compatible +	  with the legacy framework so that existing client drivers +	  continue to work as expected. + +	  If unsure, say no.  if PWM diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index ecb76909e94..c6e05078d3a 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -129,8 +129,8 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)  	return 0;  } -static struct pwm_device *of_pwm_simple_xlate(struct pwm_chip *pc, -					      const struct of_phandle_args *args) +static struct pwm_device * +of_pwm_simple_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)  {  	struct pwm_device *pwm; @@ -149,7 +149,7 @@ static struct pwm_device *of_pwm_simple_xlate(struct pwm_chip *pc,  	return pwm;  } -void of_pwmchip_add(struct pwm_chip *chip) +static void of_pwmchip_add(struct pwm_chip *chip)  {  	if (!chip->dev || !chip->dev->of_node)  		return; @@ -162,7 +162,7 @@ void of_pwmchip_add(struct pwm_chip *chip)  	of_node_get(chip->dev->of_node);  } -void of_pwmchip_remove(struct pwm_chip *chip) +static void of_pwmchip_remove(struct pwm_chip *chip)  {  	if (chip->dev && chip->dev->of_node)  		of_node_put(chip->dev->of_node); @@ -527,7 +527,7 @@ void __init pwm_add_table(struct pwm_lookup *table, size_t num)  struct pwm_device *pwm_get(struct device *dev, const char *con_id)  {  	struct pwm_device *pwm = ERR_PTR(-EPROBE_DEFER); -	const char *dev_id = dev ? dev_name(dev): NULL; +	const char *dev_id = dev ? dev_name(dev) : NULL;  	struct pwm_chip *chip = NULL;  	unsigned int index = 0;  	unsigned int best = 0; @@ -609,7 +609,7 @@ void pwm_put(struct pwm_device *pwm)  	mutex_lock(&pwm_lock);  	if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) { -		pr_warning("PWM device already freed\n"); +		pr_warn("PWM device already freed\n");  		goto out;  	} diff --git a/drivers/pwm/pwm-samsung.c b/drivers/pwm/pwm-samsung.c index d10386528c9..e5187c0ade9 100644 --- a/drivers/pwm/pwm-samsung.c +++ b/drivers/pwm/pwm-samsung.c @@ -225,6 +225,7 @@ static int s3c_pwm_probe(struct platform_device *pdev)  	/* calculate base of control bits in TCON */  	s3c->tcon_base = id == 0 ? 0 : (id * 4) + 4; +	s3c->chip.dev = &pdev->dev;  	s3c->chip.ops = &s3c_pwm_ops;  	s3c->chip.base = -1;  	s3c->chip.npwm = 1; diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index 02ce18d5e49..057465e0553 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -187,10 +187,8 @@ static int tegra_pwm_probe(struct platform_device *pdev)  	}  	pwm->mmio_base = devm_request_and_ioremap(&pdev->dev, r); -	if (!pwm->mmio_base) { -		dev_err(&pdev->dev, "failed to ioremap() region\n"); +	if (!pwm->mmio_base)  		return -EADDRNOTAVAIL; -	}  	platform_set_drvdata(pdev, pwm); diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c index 3c2ad284ee3..0b66d0f2592 100644 --- a/drivers/pwm/pwm-tiecap.c +++ b/drivers/pwm/pwm-tiecap.c @@ -192,10 +192,8 @@ static int __devinit ecap_pwm_probe(struct platform_device *pdev)  	}  	pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r); -	if (!pc->mmio_base) { -		dev_err(&pdev->dev, "failed to ioremap() registers\n"); +	if (!pc->mmio_base)  		return -EADDRNOTAVAIL; -	}  	ret = pwmchip_add(&pc->chip);  	if (ret < 0) { diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index 010d232cb0c..c3756d1be19 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -371,10 +371,8 @@ static int __devinit ehrpwm_pwm_probe(struct platform_device *pdev)  	}  	pc->mmio_base = devm_request_and_ioremap(&pdev->dev, r); -	if (!pc->mmio_base) { -		dev_err(&pdev->dev, "failed to ioremap() registers\n"); +	if (!pc->mmio_base)  		return  -EADDRNOTAVAIL; -	}  	ret = pwmchip_add(&pc->chip);  	if (ret < 0) { diff --git a/drivers/pwm/pwm-vt8500.c b/drivers/pwm/pwm-vt8500.c index 548021439f0..ad14389b714 100644 --- a/drivers/pwm/pwm-vt8500.c +++ b/drivers/pwm/pwm-vt8500.c @@ -41,7 +41,7 @@ static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask)  		cpu_relax();  	if (unlikely(!loops)) -		pr_warning("Waiting for status bits 0x%x to clear timed out\n", +		pr_warn("Waiting for status bits 0x%x to clear timed out\n",  			   bitmask);  } diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 722246cf20a..5d44252b734 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -435,6 +435,9 @@ static void tsi721_db_dpc(struct work_struct *work)  				" info %4.4x\n", DBELL_SID(idb.bytes),  				DBELL_TID(idb.bytes), DBELL_INF(idb.bytes));  		} + +		wr_ptr = ioread32(priv->regs + +				  TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE;  	}  	iowrite32(rd_ptr & (IDB_QSIZE - 1), @@ -445,6 +448,10 @@ static void tsi721_db_dpc(struct work_struct *work)  	regval |= TSI721_SR_CHINT_IDBQRCV;  	iowrite32(regval,  		priv->regs + TSI721_SR_CHINTE(IDB_QUEUE)); + +	wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; +	if (wr_ptr != rd_ptr) +		schedule_work(&priv->idb_work);  }  /** @@ -2212,7 +2219,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev,  				  const struct pci_device_id *id)  {  	struct tsi721_device *priv; -	int i, cap; +	int cap;  	int err;  	u32 regval; @@ -2232,12 +2239,15 @@ static int __devinit tsi721_probe(struct pci_dev *pdev,  	priv->pdev = pdev;  #ifdef DEBUG +	{ +	int i;  	for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {  		dev_dbg(&pdev->dev, "res[%d] @ 0x%llx (0x%lx, 0x%lx)\n",  			i, (unsigned long long)pci_resource_start(pdev, i),  			(unsigned long)pci_resource_len(pdev, i),  			pci_resource_flags(pdev, i));  	} +	}  #endif  	/*  	 * Verify BAR configuration diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 182b553059c..c151fd5d8c9 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -486,6 +486,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {  		.id   = AB3100_BUCK,  		.ops  = ®ulator_ops_variable_sleepable,  		.n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages), +		.volt_table = ldo_e_buck_typ_voltages,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE,  		.enable_time = 1000, diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index e9c2085f9df..ce0fe72a428 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -64,14 +64,15 @@ static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)  static int anatop_get_voltage_sel(struct regulator_dev *reg)  {  	struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); -	u32 val; +	u32 val, mask;  	if (!anatop_reg->control_reg)  		return -ENOTSUPP;  	val = anatop_read_reg(anatop_reg->mfd, anatop_reg->control_reg); -	val = (val & ((1 << anatop_reg->vol_bit_width) - 1)) >> +	mask = ((1 << anatop_reg->vol_bit_width) - 1) <<  		anatop_reg->vol_bit_shift; +	val = (val & mask) >> anatop_reg->vol_bit_shift;  	return val - anatop_reg->min_bit_val;  } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f092588a078..48385318175 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3217,7 +3217,7 @@ regulator_register(const struct regulator_desc *regulator_desc,  	dev_set_drvdata(&rdev->dev, rdev); -	if (config->ena_gpio) { +	if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) {  		ret = gpio_request_one(config->ena_gpio,  				       GPIOF_DIR_OUT | config->ena_gpio_flags,  				       rdev_get_name(rdev)); diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 34b67bee932..8b5944f2d7d 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -57,16 +57,17 @@ static int gpio_regulator_get_value(struct regulator_dev *dev)  	return -EINVAL;  } -static int gpio_regulator_set_value(struct regulator_dev *dev, -					int min, int max, unsigned *selector) +static int gpio_regulator_set_voltage(struct regulator_dev *dev, +					int min_uV, int max_uV, +					unsigned *selector)  {  	struct gpio_regulator_data *data = rdev_get_drvdata(dev);  	int ptr, target = 0, 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 >= min_uV && +		    data->states[ptr].value <= max_uV) {  			target = data->states[ptr].gpios;  			best_val = data->states[ptr].value;  			if (selector) @@ -85,13 +86,6 @@ static int gpio_regulator_set_value(struct regulator_dev *dev,  	return 0;  } -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); -} -  static int gpio_regulator_list_voltage(struct regulator_dev *dev,  				      unsigned selector)  { @@ -106,7 +100,27 @@ 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); +	struct gpio_regulator_data *data = rdev_get_drvdata(dev); +	int ptr, target = 0, state, best_val = 0; + +	for (ptr = 0; ptr < data->nr_states; ptr++) +		if (data->states[ptr].value > best_val && +		    data->states[ptr].value >= min_uA && +		    data->states[ptr].value <= max_uA) { +			target = data->states[ptr].gpios; +			best_val = data->states[ptr].value; +		} + +	if (best_val == 0) +		return -EINVAL; + +	for (ptr = 0; ptr < data->nr_gpios; ptr++) { +		state = (target & (1 << ptr)) >> ptr; +		gpio_set_value(data->gpios[ptr].gpio, state); +	} +	data->state = target; + +	return 0;  }  static struct regulator_ops gpio_regulator_voltage_ops = { diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 17d19fbbc49..46c7e88f838 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -486,9 +486,12 @@ static int palmas_map_voltage_ldo(struct regulator_dev *rdev,  {  	int ret, voltage; -	ret = ((min_uV - 900000) / 50000) + 1; -	if (ret < 0) -		return ret; +	if (min_uV == 0) +		return 0; + +	if (min_uV < 900000) +		min_uV = 900000; +	ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1;  	/* Map back into a voltage to verify we're still in bounds */  	voltage = palmas_list_voltage_ldo(rdev, ret); @@ -586,7 +589,7 @@ static int palmas_ldo_init(struct palmas *palmas, int id,  	addr = palmas_regs_info[id].ctrl_addr; -	ret = palmas_smps_read(palmas, addr, ®); +	ret = palmas_ldo_read(palmas, addr, ®);  	if (ret)  		return ret; @@ -596,7 +599,7 @@ static int palmas_ldo_init(struct palmas *palmas, int id,  	if (reg_init->mode_sleep)  		reg |= PALMAS_LDO1_CTRL_MODE_SLEEP; -	ret = palmas_smps_write(palmas, addr, reg); +	ret = palmas_ldo_write(palmas, addr, reg);  	if (ret)  		return ret; @@ -630,7 +633,7 @@ static __devinit int palmas_probe(struct platform_device *pdev)  	ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, ®);  	if (ret) -		goto err_unregister_regulator; +		return ret;  	if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN)  		pmic->smps123 = 1; @@ -676,7 +679,9 @@ static __devinit int palmas_probe(struct platform_device *pdev)  		case PALMAS_REG_SMPS10:  			pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;  			pmic->desc[id].ops = &palmas_ops_smps10; -			pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL; +			pmic->desc[id].vsel_reg = +					PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, +							PALMAS_SMPS10_CTRL);  			pmic->desc[id].vsel_mask = SMPS10_VSEL;  			pmic->desc[id].enable_reg =  					PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE, @@ -778,8 +783,10 @@ static __devinit int palmas_probe(struct platform_device *pdev)  			reg_init = pdata->reg_init[id];  			if (reg_init) {  				ret = palmas_ldo_init(palmas, id, reg_init); -				if (ret) +				if (ret) { +					regulator_unregister(pmic->rdev[id]);  					goto err_unregister_regulator; +				}  			}  		}  	} diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index e6da90ab515..19241fc3005 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -240,14 +240,16 @@ static struct tps6586x_regulator tps6586x_regulator[] = {  	TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),  	TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),  	TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), -	TPS6586X_LDO(SM_2, "sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), +	TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),  	TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,  					ENB, 3, VCC2, 6),  	TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,  					END, 3, VCC1, 6), -	TPS6586X_DVM(SM_0, "sm0", dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2), -	TPS6586X_DVM(SM_1, "sm1", dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0), +	TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1, +					ENB, 1, VCC1, 2), +	TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0, +					ENB, 0, VCC1, 0),  };  /* diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 242fe90dc56..77a71a5c17c 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1037,7 +1037,7 @@ TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300);  TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300);  TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300);  TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); -TWL4030_FIXED_LDO(VINTANA2, 0x3f, 1500, 11, 100, 0x08); +TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08);  TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08);  TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08);  TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08); @@ -1048,7 +1048,6 @@ TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0);  TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0);  TWL6030_FIXED_LDO(V1V8, 0x16, 1800, 0);  TWL6030_FIXED_LDO(V2V1, 0x1c, 2100, 0); -TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0);  TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34);  TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10);  TWL6025_ADJUSTABLE_SMPS(VIO, 0x16); @@ -1117,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = {  	TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6),  	TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN),  	TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB), -	TWLFIXED_OF_MATCH("ti,twl4030-vintana2", VINTANA2), +	TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1),  	TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG),  	TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5),  	TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8), diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index eb415bd7649..9592b936b71 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -582,6 +582,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer)  void rtc_update_irq(struct rtc_device *rtc,  		unsigned long num, unsigned long events)  { +	pm_stay_awake(rtc->dev.parent);  	schedule_work(&rtc->irqwork);  }  EXPORT_SYMBOL_GPL(rtc_update_irq); @@ -844,6 +845,7 @@ void rtc_timer_do_work(struct work_struct *work)  	mutex_lock(&rtc->ops_lock);  again: +	pm_relax(rtc->dev.parent);  	__rtc_read_time(rtc, &tm);  	now = rtc_tm_to_ktime(tm);  	while ((next = timerqueue_getnext(&rtc->timerqueue))) { diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 132333d7540..4267789ca99 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -568,7 +568,6 @@ static irqreturn_t cmos_interrupt(int irq, void *p)  		hpet_mask_rtc_irq_bit(RTC_AIE);  		CMOS_READ(RTC_INTR_FLAGS); -		pm_wakeup_event(cmos_rtc.dev, 0);  	}  	spin_unlock(&rtc_lock); diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 836118795c0..13e4df63974 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -43,6 +43,7 @@  #include <linux/rtc.h>  #include <linux/spi/spi.h>  #include <linux/module.h> +#include <linux/sysfs.h>  #define DRV_VERSION "0.6" @@ -292,6 +293,7 @@ static int __devinit pcf2123_probe(struct spi_device *spi)  	pdata->rtc = rtc;  	for (i = 0; i < 16; i++) { +		sysfs_attr_init(&pdata->regs[i].attr.attr);  		sprintf(pdata->regs[i].name, "%1x", i);  		pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR;  		pdata->regs[i].attr.attr.name = pdata->regs[i].name; diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 77074ccd285..fd5c7af04ae 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -122,9 +122,12 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)  	tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK);  	tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK);  	if (!pdata->rtc_24h) { -		tm->tm_hour %= 12; -		if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) +		if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) { +			tm->tm_hour -= 20; +			tm->tm_hour %= 12;  			tm->tm_hour += 12; +		} else +			tm->tm_hour %= 12;  	}  	tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK);  	tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK); diff --git a/drivers/s390/char/sclp_sdias.c b/drivers/s390/char/sclp_sdias.c index 6a6f76bf6e3..b1032931a1c 100644 --- a/drivers/s390/char/sclp_sdias.c +++ b/drivers/s390/char/sclp_sdias.c @@ -242,11 +242,13 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks)  	switch (sdias_evbuf.event_status) {  		case EVSTATE_ALL_STORED:  			TRACE("all stored\n"); +			break;  		case EVSTATE_PART_STORED:  			TRACE("part stored: %i\n", sdias_evbuf.blk_cnt);  			break;  		case EVSTATE_NO_DATA:  			TRACE("no data\n"); +			/* fall through */  		default:  			pr_err("Error from SCLP while copying hsa. "  			       "Event status = %x\n", diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index 2374468615e..32c26d795ed 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -324,8 +324,16 @@ int __init register_intc_controller(struct intc_desc *desc)  		res = irq_create_identity_mapping(d->domain, irq);  		if (unlikely(res)) { -			pr_err("can't get irq_desc for %d\n", irq); -			continue; +			if (res == -EEXIST) { +				res = irq_domain_associate(d->domain, irq, irq); +				if (unlikely(res)) { +					pr_err("domain association failure\n"); +					continue; +				} +			} else { +				pr_err("can't identity map IRQ %d\n", irq); +				continue; +			}  		}  		intc_irq_xlate_set(irq, vect->enum_id, d); @@ -345,8 +353,19 @@ int __init register_intc_controller(struct intc_desc *desc)  			 */  			res = irq_create_identity_mapping(d->domain, irq2);  			if (unlikely(res)) { -				pr_err("can't get irq_desc for %d\n", irq2); -				continue; +				if (res == -EEXIST) { +					res = irq_domain_associate(d->domain, +								   irq, irq); +					if (unlikely(res)) { +						pr_err("domain association " +						       "failure\n"); +						continue; +					} +				} else { +					pr_err("can't identity map IRQ %d\n", +					       irq); +					continue; +				}  			}  			vect2->enum_id = 0; diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 6e25ef1bce9..ea0aaa3f13d 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -438,7 +438,7 @@ out:  static int __devexit bcm63xx_spi_remove(struct platform_device *pdev)  { -	struct spi_master *master = platform_get_drvdata(pdev); +	struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));  	struct bcm63xx_spi *bs = spi_master_get_devdata(master);  	spi_unregister_master(master); @@ -452,6 +452,8 @@ static int __devexit bcm63xx_spi_remove(struct platform_device *pdev)  	platform_set_drvdata(pdev, 0); +	spi_master_put(master); +  	return 0;  } diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index b2d4b9e4e01..764bfee7592 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -533,7 +533,6 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev)  	iounmap(mcfqspi->iobase);  	release_mem_region(res->start, resource_size(res));  	spi_unregister_master(master); -	spi_master_put(master);  	return 0;  } @@ -541,7 +540,7 @@ static int __devexit mcfqspi_remove(struct platform_device *pdev)  #ifdef CONFIG_PM_SLEEP  static int mcfqspi_suspend(struct device *dev)  { -	struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); +	struct spi_master *master = dev_get_drvdata(dev);  	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);  	spi_master_suspend(master); @@ -553,7 +552,7 @@ static int mcfqspi_suspend(struct device *dev)  static int mcfqspi_resume(struct device *dev)  { -	struct spi_master *master = spi_master_get(dev_get_drvdata(dev)); +	struct spi_master *master = dev_get_drvdata(dev);  	struct mcfqspi *mcfqspi = spi_master_get_devdata(master);  	spi_master_resume(master); diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index bc4778175e3..b2fb141da37 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1228,18 +1228,16 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev)  	status = spi_register_master(master);  	if (status < 0) -		goto err_spi_register; +		goto disable_pm;  	return status; -err_spi_register: -	spi_master_put(master);  disable_pm:  	pm_runtime_disable(&pdev->dev);  dma_chnl_free:  	kfree(mcspi->dma_channels);  free_master: -	kfree(master); +	spi_master_put(master);  	platform_set_drvdata(pdev, NULL);  	return status;  } diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index aab518ec2bb..6abbe23c39b 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2053,7 +2053,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)  	printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",  	       adev->res.start, pl022->virtbase); -	pm_runtime_enable(dev);  	pm_runtime_resume(dev);  	pl022->clk = clk_get(&adev->dev, NULL); diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 646a7657fe6..d1c8441f638 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -826,7 +826,7 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(  				struct spi_device *spi)  {  	struct s3c64xx_spi_csinfo *cs; -	struct device_node *slave_np, *data_np; +	struct device_node *slave_np, *data_np = NULL;  	u32 fb_delay = 0;  	slave_np = spi->dev.of_node; @@ -1479,40 +1479,40 @@ static const struct dev_pm_ops s3c64xx_spi_pm = {  			   s3c64xx_spi_runtime_resume, NULL)  }; -struct s3c64xx_spi_port_config s3c2443_spi_port_config = { +static struct s3c64xx_spi_port_config s3c2443_spi_port_config = {  	.fifo_lvl_mask	= { 0x7f },  	.rx_lvl_offset	= 13,  	.tx_st_done	= 21,  	.high_speed	= true,  }; -struct s3c64xx_spi_port_config s3c6410_spi_port_config = { +static struct s3c64xx_spi_port_config s3c6410_spi_port_config = {  	.fifo_lvl_mask	= { 0x7f, 0x7F },  	.rx_lvl_offset	= 13,  	.tx_st_done	= 21,  }; -struct s3c64xx_spi_port_config s5p64x0_spi_port_config = { +static struct s3c64xx_spi_port_config s5p64x0_spi_port_config = {  	.fifo_lvl_mask	= { 0x1ff, 0x7F },  	.rx_lvl_offset	= 15,  	.tx_st_done	= 25,  }; -struct s3c64xx_spi_port_config s5pc100_spi_port_config = { +static struct s3c64xx_spi_port_config s5pc100_spi_port_config = {  	.fifo_lvl_mask	= { 0x7f, 0x7F },  	.rx_lvl_offset	= 13,  	.tx_st_done	= 21,  	.high_speed	= true,  }; -struct s3c64xx_spi_port_config s5pv210_spi_port_config = { +static struct s3c64xx_spi_port_config s5pv210_spi_port_config = {  	.fifo_lvl_mask	= { 0x1ff, 0x7F },  	.rx_lvl_offset	= 15,  	.tx_st_done	= 25,  	.high_speed	= true,  }; -struct s3c64xx_spi_port_config exynos4_spi_port_config = { +static struct s3c64xx_spi_port_config exynos4_spi_port_config = {  	.fifo_lvl_mask	= { 0x1ff, 0x7F, 0x7F },  	.rx_lvl_offset	= 15,  	.tx_st_done	= 25, diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index c0fdb00783e..2359151af7e 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -168,7 +168,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)  			dev->board_ptr = comedi_recognize(driv, it->board_name);  			if (dev->board_ptr)  				break; -		} else if (strcmp(driv->driver_name, it->board_name)) +		} else if (strcmp(driv->driver_name, it->board_name) == 0)  			break;  		module_put(driv->module);  	} diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 31986608eaf..6b4d0d68e63 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1349,9 +1349,6 @@ static struct pci_dev *pci1710_find_pci_dev(struct comedi_device *dev,  		}  		if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH)  			continue; -		if (pci_is_enabled(pcidev)) -			continue; -  		if (strcmp(this_board->name, DRV_NAME) == 0) {  			for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {  				if (pcidev->device == boardtypes[i].device_id) { diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index da5ee69d2c9..dfde0f6328d 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -301,8 +301,6 @@ static struct pci_dev *pci1723_find_pci_dev(struct comedi_device *dev,  		}  		if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH)  			continue; -		if (pci_is_enabled(pcidev)) -			continue;  		return pcidev;  	}  	dev_err(dev->class_dev, diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 97f06dc8e48..2d4cb7f638b 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1064,8 +1064,6 @@ static struct pci_dev *pci_dio_find_pci_dev(struct comedi_device *dev,  			    slot != PCI_SLOT(pcidev->devfn))  				continue;  		} -		if (pci_is_enabled(pcidev)) -			continue;  		for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {  			if (boardtypes[i].vendor_id != pcidev->vendor)  				continue; diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index ef28385c148..cad559a1a73 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -718,7 +718,8 @@ static struct pci_dev *daqboard2000_find_pci_dev(struct comedi_device *dev,  				continue;  		}  		if (pcidev->vendor != PCI_VENDOR_ID_IOTECH || -		    pcidev->device != 0x0409) +		    pcidev->device != 0x0409 || +		    pcidev->subsystem_device != PCI_VENDOR_ID_IOTECH)  			continue;  		for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { @@ -739,6 +740,7 @@ static int daqboard2000_attach(struct comedi_device *dev,  {  	struct pci_dev *pcidev;  	struct comedi_subdevice *s; +	resource_size_t pci_base;  	void *aux_data;  	unsigned int aux_len;  	int result; @@ -758,11 +760,12 @@ static int daqboard2000_attach(struct comedi_device *dev,  			"failed to enable PCI device and request regions\n");  		return -EIO;  	} -	dev->iobase = pci_resource_start(pcidev, 2); +	dev->iobase = 1;	/* the "detach" needs this */ -	devpriv->plx = -	    ioremap(pci_resource_start(pcidev, 0), DAQBOARD2000_PLX_SIZE); -	devpriv->daq = ioremap(dev->iobase, DAQBOARD2000_DAQ_SIZE); +	pci_base = pci_resource_start(pcidev, 0); +	devpriv->plx = ioremap(pci_base, DAQBOARD2000_PLX_SIZE); +	pci_base = pci_resource_start(pcidev, 2); +	devpriv->daq = ioremap(pci_base, DAQBOARD2000_DAQ_SIZE);  	if (!devpriv->plx || !devpriv->daq)  		return -ENOMEM; @@ -799,8 +802,6 @@ static int daqboard2000_attach(struct comedi_device *dev,  	   printk("Interrupt after is: %x\n", interrupt);  	 */ -	dev->iobase = (unsigned long)devpriv->daq; -  	dev->board_name = this_board->name;  	s = dev->subdevices + 0; @@ -824,7 +825,7 @@ static int daqboard2000_attach(struct comedi_device *dev,  	s = dev->subdevices + 2;  	result = subdev_8255_init(dev, s, daqboard2000_8255_cb, -				  (unsigned long)(dev->iobase + 0x40)); +				  (unsigned long)(devpriv->daq + 0x40));  out:  	return result; diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index a6fe6c9be87..3476cda0fff 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -804,6 +804,7 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)  {  	struct pci_dev *pcidev;  	struct comedi_subdevice *s; +	resource_size_t pci_base;  	int ret = 0;  	dev_dbg(dev->class_dev, "dt3000:\n"); @@ -820,9 +821,10 @@ static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)  	ret = comedi_pci_enable(pcidev, "dt3000");  	if (ret < 0)  		return ret; +	dev->iobase = 1;	/* the "detach" needs this */ -	dev->iobase = pci_resource_start(pcidev, 0); -	devpriv->io_addr = ioremap(dev->iobase, DT3000_SIZE); +	pci_base  = pci_resource_start(pcidev, 0); +	devpriv->io_addr = ioremap(pci_base, DT3000_SIZE);  	if (!devpriv->io_addr)  		return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 112fdc3e9c6..5aa8be1e7b9 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1619,9 +1619,8 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)  	struct rtdPrivate *devpriv;  	struct pci_dev *pcidev;  	struct comedi_subdevice *s; +	resource_size_t pci_base;  	int ret; -	resource_size_t physLas1;	/* data area */ -	resource_size_t physLcfg;	/* PLX9080 */  #ifdef USE_DMA  	int index;  #endif @@ -1655,20 +1654,15 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)  		printk(KERN_INFO "Failed to enable PCI device and request regions.\n");  		return ret;  	} +	dev->iobase = 1;	/* the "detach" needs this */ -	/* -	 * Initialize base addresses -	 */ -	/* Get the physical address from PCI config */ -	dev->iobase = pci_resource_start(pcidev, LAS0_PCIINDEX); -	physLas1 = pci_resource_start(pcidev, LAS1_PCIINDEX); -	physLcfg = pci_resource_start(pcidev, LCFG_PCIINDEX); -	/* Now have the kernel map this into memory */ -	/* ASSUME page aligned */ -	devpriv->las0 = ioremap_nocache(dev->iobase, LAS0_PCISIZE); -	devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE); -	devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE); - +	/* Initialize the base addresses */ +	pci_base = pci_resource_start(pcidev, LAS0_PCIINDEX); +	devpriv->las0 = ioremap_nocache(pci_base, LAS0_PCISIZE); +	pci_base = pci_resource_start(pcidev, LAS1_PCIINDEX); +	devpriv->las1 = ioremap_nocache(pci_base, LAS1_PCISIZE); +	pci_base = pci_resource_start(pcidev, LCFG_PCIINDEX); +	devpriv->lcfg = ioremap_nocache(pci_base, LCFG_PCISIZE);  	if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg)  		return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 848c7ec0697..11ee83681da 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -102,6 +102,7 @@ sampling rate. If you sample two channels you get 4kHz and so on.  #define BULK_TIMEOUT 1000  /* constants for "firmware" upload and download */ +#define FIRMWARE "usbdux_firmware.bin"  #define USBDUXSUB_FIRMWARE 0xA0  #define VENDOR_DIR_IN  0xC0  #define VENDOR_DIR_OUT 0x40 @@ -2791,7 +2792,7 @@ static int usbdux_usb_probe(struct usb_interface *uinterf,  	ret = request_firmware_nowait(THIS_MODULE,  				      FW_ACTION_HOTPLUG, -				      "usbdux_firmware.bin", +				      FIRMWARE,  				      &udev->dev,  				      GFP_KERNEL,  				      usbduxsub + index, @@ -2850,3 +2851,4 @@ module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver);  MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");  MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com");  MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FIRMWARE); diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index d9911588c10..8eb41257c6c 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -57,6 +57,7 @@  /*   * constants for "firmware" upload and download   */ +#define FIRMWARE		"usbduxfast_firmware.bin"  #define USBDUXFASTSUB_FIRMWARE	0xA0  #define VENDOR_DIR_IN		0xC0  #define VENDOR_DIR_OUT		0x40 @@ -1706,7 +1707,7 @@ static int usbduxfast_usb_probe(struct usb_interface *uinterf,  	ret = request_firmware_nowait(THIS_MODULE,  				      FW_ACTION_HOTPLUG, -				      "usbduxfast_firmware.bin", +				      FIRMWARE,  				      &udev->dev,  				      GFP_KERNEL,  				      usbduxfastsub + index, @@ -1774,3 +1775,4 @@ module_comedi_usb_driver(usbduxfast_driver, usbduxfast_usb_driver);  MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");  MODULE_DESCRIPTION("USB-DUXfast, BerndPorr@f2s.com");  MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FIRMWARE); diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 543e604791e..f54ab8c2fcf 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -63,6 +63,7 @@ Status: testing  #define BULK_TIMEOUT 1000  /* constants for "firmware" upload and download */ +#define FIRMWARE "usbduxsigma_firmware.bin"  #define USBDUXSUB_FIRMWARE 0xA0  #define VENDOR_DIR_IN  0xC0  #define VENDOR_DIR_OUT 0x40 @@ -2780,7 +2781,7 @@ static int usbduxsigma_usb_probe(struct usb_interface *uinterf,  	ret = request_firmware_nowait(THIS_MODULE,  				      FW_ACTION_HOTPLUG, -				      "usbduxsigma_firmware.bin", +				      FIRMWARE,  				      &udev->dev,  				      GFP_KERNEL,  				      usbduxsub + index, @@ -2845,3 +2846,4 @@ module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver);  MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");  MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com");  MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(FIRMWARE); diff --git a/drivers/staging/csr/Kconfig b/drivers/staging/csr/Kconfig index cee8d48d2af..ad2a1096e92 100644 --- a/drivers/staging/csr/Kconfig +++ b/drivers/staging/csr/Kconfig @@ -1,6 +1,6 @@  config CSR_WIFI  	tristate "CSR wireless driver" -	depends on MMC && CFG80211_WEXT +	depends on MMC && CFG80211_WEXT && INET  	select WIRELESS_EXT  	select WEXT_PRIV  	help diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 22c3923d55e..095837285f4 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -754,7 +754,7 @@ static ssize_t ad7192_set(struct device *dev,  		else  			st->mode &= ~AD7192_MODE_ACX; -		ad7192_write_reg(st, AD7192_REG_GPOCON, 3, st->mode); +		ad7192_write_reg(st, AD7192_REG_MODE, 3, st->mode);  		break;  	default:  		ret = -EINVAL; @@ -798,6 +798,11 @@ static const struct attribute_group ad7195_attribute_group = {  	.attrs = ad7195_attributes,  }; +static unsigned int ad7192_get_temp_scale(bool unipolar) +{ +	return unipolar ? 2815 * 2 : 2815; +} +  static int ad7192_read_raw(struct iio_dev *indio_dev,  			   struct iio_chan_spec const *chan,  			   int *val, @@ -824,19 +829,6 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,  		*val = (smpl >> chan->scan_type.shift) &  			((1 << (chan->scan_type.realbits)) - 1); -		switch (chan->type) { -		case IIO_VOLTAGE: -			if (!unipolar) -				*val -= (1 << (chan->scan_type.realbits - 1)); -			break; -		case IIO_TEMP: -			*val -= 0x800000; -			*val /= 2815; /* temp Kelvin */ -			*val -= 273; /* temp Celsius */ -			break; -		default: -			return -EINVAL; -		}  		return IIO_VAL_INT;  	case IIO_CHAN_INFO_SCALE: @@ -848,11 +840,21 @@ static int ad7192_read_raw(struct iio_dev *indio_dev,  			mutex_unlock(&indio_dev->mlock);  			return IIO_VAL_INT_PLUS_NANO;  		case IIO_TEMP: -			*val =  1000; -			return IIO_VAL_INT; +			*val = 0; +			*val2 = 1000000000 / ad7192_get_temp_scale(unipolar); +			return IIO_VAL_INT_PLUS_NANO;  		default:  			return -EINVAL;  		} +	case IIO_CHAN_INFO_OFFSET: +		if (!unipolar) +			*val = -(1 << (chan->scan_type.realbits - 1)); +		else +			*val = 0; +		/* Kelvin to Celsius */ +		if (chan->type == IIO_TEMP) +			*val -= 273 * ad7192_get_temp_scale(unipolar); +		return IIO_VAL_INT;  	}  	return -EINVAL; @@ -890,7 +892,7 @@ static int ad7192_write_raw(struct iio_dev *indio_dev,  				}  				ret = 0;  			} - +		break;  	default:  		ret = -EINVAL;  	} @@ -942,20 +944,22 @@ static const struct iio_info ad7195_info = {  	  .channel = _chan,						\  	  .channel2 = _chan2,						\  	  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |			\ -	  IIO_CHAN_INFO_SCALE_SHARED_BIT,				\ +	  IIO_CHAN_INFO_SCALE_SHARED_BIT |				\ +	  IIO_CHAN_INFO_OFFSET_SHARED_BIT,				\  	  .address = _address,						\  	  .scan_index = _si,						\ -	  .scan_type =  IIO_ST('s', 24, 32, 0)} +	  .scan_type =  IIO_ST('u', 24, 32, 0)}  #define AD7192_CHAN(_chan, _address, _si)				\  	{ .type = IIO_VOLTAGE,						\  	  .indexed = 1,							\  	  .channel = _chan,						\  	  .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |			\ -	  IIO_CHAN_INFO_SCALE_SHARED_BIT,				\ +	  IIO_CHAN_INFO_SCALE_SHARED_BIT |				\ +	  IIO_CHAN_INFO_OFFSET_SHARED_BIT,				\  	  .address = _address,						\  	  .scan_index = _si,						\ -	  .scan_type =  IIO_ST('s', 24, 32, 0)} +	  .scan_type =  IIO_ST('u', 24, 32, 0)}  #define AD7192_CHAN_TEMP(_chan, _address, _si)				\  	{ .type = IIO_TEMP,						\ @@ -965,7 +969,7 @@ static const struct iio_info ad7195_info = {  	  IIO_CHAN_INFO_SCALE_SEPARATE_BIT,				\  	  .address = _address,						\  	  .scan_index = _si,						\ -	  .scan_type =  IIO_ST('s', 24, 32, 0)} +	  .scan_type =  IIO_ST('u', 24, 32, 0)}  static struct iio_chan_spec ad7192_channels[] = {  	AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0), diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index fd1d855ff57..506016f0159 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -76,7 +76,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p)  	struct iio_dev *indio_dev = pf->indio_dev;  	struct ad7298_state *st = iio_priv(indio_dev);  	struct iio_buffer *ring = indio_dev->buffer; -	s64 time_ns; +	s64 time_ns = 0;  	__u16 buf[16];  	int b_sent, i; diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c index 1ece2ac8de5..19ee49c95de 100644 --- a/drivers/staging/iio/adc/ad7780.c +++ b/drivers/staging/iio/adc/ad7780.c @@ -131,9 +131,10 @@ static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {  			.indexed = 1,  			.channel = 0,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_type = { -				.sign = 's', +				.sign = 'u',  				.realbits = 24,  				.storagebits = 32,  				.shift = 8, @@ -146,9 +147,10 @@ static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {  			.indexed = 1,  			.channel = 0,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_type = { -				.sign = 's', +				.sign = 'u',  				.realbits = 20,  				.storagebits = 32,  				.shift = 12, diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c index 76fdd7145fc..112e2b7b5bc 100644 --- a/drivers/staging/iio/adc/ad7793.c +++ b/drivers/staging/iio/adc/ad7793.c @@ -563,8 +563,9 @@ static ssize_t ad7793_show_scale_available(struct device *dev,  	return len;  } -static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available, -			     S_IRUGO, ad7793_show_scale_available, NULL, 0); +static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, +		in_voltage-voltage_scale_available, S_IRUGO, +		ad7793_show_scale_available, NULL, 0);  static struct attribute *ad7793_attributes[] = {  	&iio_dev_attr_sampling_frequency.dev_attr.attr, @@ -604,9 +605,6 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,  		*val = (smpl >> chan->scan_type.shift) &  			((1 << (chan->scan_type.realbits)) - 1); -		if (!unipolar) -			*val -= (1 << (chan->scan_type.realbits - 1)); -  		return IIO_VAL_INT;  	case IIO_CHAN_INFO_SCALE: @@ -620,25 +618,38 @@ static int ad7793_read_raw(struct iio_dev *indio_dev,  				return IIO_VAL_INT_PLUS_NANO;  			} else {  				/* 1170mV / 2^23 * 6 */ -				scale_uv = (1170ULL * 100000000ULL * 6ULL) -					>> (chan->scan_type.realbits - -					    (unipolar ? 0 : 1)); +				scale_uv = (1170ULL * 100000000ULL * 6ULL);  			}  			break;  		case IIO_TEMP: -			/* Always uses unity gain and internal ref */ -			scale_uv = (2500ULL * 100000000ULL) -				>> (chan->scan_type.realbits - -				(unipolar ? 0 : 1)); +				/* 1170mV / 0.81 mV/C / 2^23 */ +				scale_uv = 1444444444444ULL;  			break;  		default:  			return -EINVAL;  		} -		*val2 = do_div(scale_uv, 100000000) * 10; -		*val =  scale_uv; - +		scale_uv >>= (chan->scan_type.realbits - (unipolar ? 0 : 1)); +		*val = 0; +		*val2 = scale_uv;  		return IIO_VAL_INT_PLUS_NANO; +	case IIO_CHAN_INFO_OFFSET: +		if (!unipolar) +			*val = -(1 << (chan->scan_type.realbits - 1)); +		else +			*val = 0; + +		/* Kelvin to Celsius */ +		if (chan->type == IIO_TEMP) { +			unsigned long long offset; +			unsigned int shift; + +			shift = chan->scan_type.realbits - (unipolar ? 0 : 1); +			offset = 273ULL << shift; +			do_div(offset, 1444); +			*val -= offset; +		} +		return IIO_VAL_INT;  	}  	return -EINVAL;  } @@ -676,7 +687,7 @@ static int ad7793_write_raw(struct iio_dev *indio_dev,  				}  				ret = 0;  			} - +		break;  	default:  		ret = -EINVAL;  	} @@ -720,9 +731,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel2 = 0,  			.address = AD7793_CH_AIN1P_AIN1M,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 0, -			.scan_type = IIO_ST('s', 24, 32, 0) +			.scan_type = IIO_ST('u', 24, 32, 0)  		},  		.channel[1] = {  			.type = IIO_VOLTAGE, @@ -732,9 +744,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel2 = 1,  			.address = AD7793_CH_AIN2P_AIN2M,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 1, -			.scan_type = IIO_ST('s', 24, 32, 0) +			.scan_type = IIO_ST('u', 24, 32, 0)  		},  		.channel[2] = {  			.type = IIO_VOLTAGE, @@ -744,9 +757,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel2 = 2,  			.address = AD7793_CH_AIN3P_AIN3M,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 2, -			.scan_type = IIO_ST('s', 24, 32, 0) +			.scan_type = IIO_ST('u', 24, 32, 0)  		},  		.channel[3] = {  			.type = IIO_VOLTAGE, @@ -757,9 +771,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel2 = 2,  			.address = AD7793_CH_AIN1M_AIN1M,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 3, -			.scan_type = IIO_ST('s', 24, 32, 0) +			.scan_type = IIO_ST('u', 24, 32, 0)  		},  		.channel[4] = {  			.type = IIO_TEMP, @@ -769,7 +784,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |  			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,  			.scan_index = 4, -			.scan_type = IIO_ST('s', 24, 32, 0), +			.scan_type = IIO_ST('u', 24, 32, 0),  		},  		.channel[5] = {  			.type = IIO_VOLTAGE, @@ -778,9 +793,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel = 4,  			.address = AD7793_CH_AVDD_MONITOR,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SEPARATE_BIT, +			IIO_CHAN_INFO_SCALE_SEPARATE_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 5, -			.scan_type = IIO_ST('s', 24, 32, 0), +			.scan_type = IIO_ST('u', 24, 32, 0),  		},  		.channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),  	}, @@ -793,9 +809,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel2 = 0,  			.address = AD7793_CH_AIN1P_AIN1M,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 0, -			.scan_type = IIO_ST('s', 16, 32, 0) +			.scan_type = IIO_ST('u', 16, 32, 0)  		},  		.channel[1] = {  			.type = IIO_VOLTAGE, @@ -805,9 +822,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel2 = 1,  			.address = AD7793_CH_AIN2P_AIN2M,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 1, -			.scan_type = IIO_ST('s', 16, 32, 0) +			.scan_type = IIO_ST('u', 16, 32, 0)  		},  		.channel[2] = {  			.type = IIO_VOLTAGE, @@ -817,9 +835,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel2 = 2,  			.address = AD7793_CH_AIN3P_AIN3M,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 2, -			.scan_type = IIO_ST('s', 16, 32, 0) +			.scan_type = IIO_ST('u', 16, 32, 0)  		},  		.channel[3] = {  			.type = IIO_VOLTAGE, @@ -830,9 +849,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel2 = 2,  			.address = AD7793_CH_AIN1M_AIN1M,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SHARED_BIT, +			IIO_CHAN_INFO_SCALE_SHARED_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 3, -			.scan_type = IIO_ST('s', 16, 32, 0) +			.scan_type = IIO_ST('u', 16, 32, 0)  		},  		.channel[4] = {  			.type = IIO_TEMP, @@ -842,7 +862,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |  			IIO_CHAN_INFO_SCALE_SEPARATE_BIT,  			.scan_index = 4, -			.scan_type = IIO_ST('s', 16, 32, 0), +			.scan_type = IIO_ST('u', 16, 32, 0),  		},  		.channel[5] = {  			.type = IIO_VOLTAGE, @@ -851,9 +871,10 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {  			.channel = 4,  			.address = AD7793_CH_AVDD_MONITOR,  			.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | -			IIO_CHAN_INFO_SCALE_SEPARATE_BIT, +			IIO_CHAN_INFO_SCALE_SEPARATE_BIT | +			IIO_CHAN_INFO_OFFSET_SHARED_BIT,  			.scan_index = 5, -			.scan_type = IIO_ST('s', 16, 32, 0), +			.scan_type = IIO_ST('u', 16, 32, 0),  		},  		.channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6),  	}, @@ -901,7 +922,7 @@ static int __devinit ad7793_probe(struct spi_device *spi)  	else if (voltage_uv)  		st->int_vref_mv = voltage_uv / 1000;  	else -		st->int_vref_mv = 2500; /* Build-in ref */ +		st->int_vref_mv = 1170; /* Build-in ref */  	spi_set_drvdata(spi, indio_dev);  	st->spi = spi; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index b06fd5b723f..d536756549e 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -189,7 +189,7 @@ DEVICE_PARAM(b80211hEnable, "802.11h mode");  // Static vars definitions  // -static struct usb_device_id vt6656_table[] __devinitdata = { +static struct usb_device_id vt6656_table[] = {  	{USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)},  	{}  }; diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index ef360547ece..0ca857ac473 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -25,7 +25,7 @@ MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");  MODULE_LICENSE("GPL");  MODULE_VERSION("0.1"); -static const struct usb_device_id wb35_table[] __devinitconst = { +static const struct usb_device_id wb35_table[] = {  	{ USB_DEVICE(0x0416, 0x0035) },  	{ USB_DEVICE(0x18E8, 0x6201) },  	{ USB_DEVICE(0x18E8, 0x6206) }, diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 6e32ff6f2fa..5552fa7426b 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -673,8 +673,15 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)  	struct scsi_device *sd = pdv->pdv_sd;  	int result;  	struct pscsi_plugin_task *pt = cmd->priv; -	unsigned char *cdb = &pt->pscsi_cdb[0]; +	unsigned char *cdb; +	/* +	 * Special case for REPORT_LUNs handling where pscsi_plugin_task has +	 * not been allocated because TCM is handling the emulation directly. +	 */ +	if (!pt) +		return 0; +	cdb = &pt->pscsi_cdb[0];  	result = pt->pscsi_result;  	/*  	 * Hack to make sure that Write-Protect modepage is set if R/O mode is diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 0eaae23d12b..4de3186dc44 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1165,8 +1165,6 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)  			" 0x%02x\n", cmd->se_tfo->get_fabric_name(),  				cmd->data_length, size, cmd->t_task_cdb[0]); -		cmd->cmd_spdtl = size; -  		if (cmd->data_direction == DMA_TO_DEVICE) {  			pr_err("Rejecting underflow/overflow"  					" WRITE data\n"); @@ -2294,9 +2292,9 @@ transport_generic_get_mem(struct se_cmd *cmd)  	return 0;  out: -	while (i >= 0) { -		__free_page(sg_page(&cmd->t_data_sg[i])); +	while (i > 0) {  		i--; +		__free_page(sg_page(&cmd->t_data_sg[i]));  	}  	kfree(cmd->t_data_sg);  	cmd->t_data_sg = NULL; @@ -2323,9 +2321,12 @@ int transport_generic_new_cmd(struct se_cmd *cmd)  		if (ret < 0)  			goto out_fail;  	} - -	/* Workaround for handling zero-length control CDBs */ -	if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->data_length) { +	/* +	 * If this command doesn't have any payload and we don't have to call +	 * into the fabric for data transfers, go ahead and complete it right +	 * away. +	 */ +	if (!cmd->data_length) {  		spin_lock_irq(&cmd->t_state_lock);  		cmd->t_state = TRANSPORT_COMPLETE;  		cmd->transport_state |= CMD_T_ACTIVE; diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index c5eb3c33c3d..eea69358ced 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h @@ -131,6 +131,7 @@ extern struct list_head ft_lport_list;  extern struct mutex ft_lport_lock;  extern struct fc4_prov ft_prov;  extern struct target_fabric_configfs *ft_configfs; +extern unsigned int ft_debug_logging;  /*   * Fabric methods. diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index b9cb5006177..823e6922249 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -48,7 +48,7 @@  /*   * Dump cmd state for debugging.   */ -void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) +static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller)  {  	struct fc_exch *ep;  	struct fc_seq *sp; @@ -80,6 +80,12 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)  	}  } +void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) +{ +	if (unlikely(ft_debug_logging)) +		_ft_dump_cmd(cmd, caller); +} +  static void ft_free_cmd(struct ft_cmd *cmd)  {  	struct fc_frame *fp; diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 87901fa74dd..3c9e5b57caa 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -456,7 +456,9 @@ static void ft_prlo(struct fc_rport_priv *rdata)  	struct ft_tport *tport;  	mutex_lock(&ft_lport_lock); -	tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]); +	tport = rcu_dereference_protected(rdata->local_port->prov[FC_TYPE_FCP], +					  lockdep_is_held(&ft_lport_lock)); +  	if (!tport) {  		mutex_unlock(&ft_lport_lock);  		return; diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 070b442c1f8..4720b4ba096 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -160,10 +160,12 @@ config SERIAL_KS8695_CONSOLE  config SERIAL_CLPS711X  	tristate "CLPS711X serial port support" -	depends on ARM && ARCH_CLPS711X +	depends on ARCH_CLPS711X  	select SERIAL_CORE +	default y  	help -	  ::: To be written ::: +	  This enables the driver for the on-chip UARTs of the Cirrus +	  Logic EP711x/EP721x/EP731x processors.  config SERIAL_CLPS711X_CONSOLE  	bool "Support for console on CLPS711X serial port" @@ -173,9 +175,7 @@ config SERIAL_CLPS711X_CONSOLE  	  Even if you say Y here, the currently visible virtual console  	  (/dev/tty0) will still be used as the system console by default, but  	  you can alter that using a kernel command line option such as -	  "console=ttyCL1". (Try "man bootparam" or see the documentation of -	  your boot loader (lilo or loadlin) about how to pass options to the -	  kernel at boot time.) +	  "console=ttyCL1".  config SERIAL_SAMSUNG  	tristate "Samsung SoC serial support" diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 144cd3987d4..3ad079ffd04 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1331,7 +1331,7 @@ static const struct spi_device_id ifx_id_table[] = {  MODULE_DEVICE_TABLE(spi, ifx_id_table);  /* spi operations */ -static const struct spi_driver ifx_spi_driver = { +static struct spi_driver ifx_spi_driver = {  	.driver = {  		.name = DRVNAME,  		.pm = &ifx_spi_pm, diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 2e341b81ff8..3a667eed63d 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -73,6 +73,7 @@  #define AUART_CTRL0_CLKGATE			(1 << 30)  #define AUART_CTRL2_CTSEN			(1 << 15) +#define AUART_CTRL2_RTSEN			(1 << 14)  #define AUART_CTRL2_RTS				(1 << 11)  #define AUART_CTRL2_RXE				(1 << 9)  #define AUART_CTRL2_TXE				(1 << 8) @@ -259,9 +260,12 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)  	u32 ctrl = readl(u->membase + AUART_CTRL2); -	ctrl &= ~AUART_CTRL2_RTS; -	if (mctrl & TIOCM_RTS) -		ctrl |= AUART_CTRL2_RTS; +	ctrl &= ~AUART_CTRL2_RTSEN; +	if (mctrl & TIOCM_RTS) { +		if (u->state->port.flags & ASYNC_CTS_FLOW) +			ctrl |= AUART_CTRL2_RTSEN; +	} +  	s->ctrl = mctrl;  	writel(ctrl, u->membase + AUART_CTRL2);  } @@ -359,9 +363,9 @@ static void mxs_auart_settermios(struct uart_port *u,  	/* figure out the hardware flow control settings */  	if (cflag & CRTSCTS) -		ctrl2 |= AUART_CTRL2_CTSEN; +		ctrl2 |= AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN;  	else -		ctrl2 &= ~AUART_CTRL2_CTSEN; +		ctrl2 &= ~(AUART_CTRL2_CTSEN | AUART_CTRL2_RTSEN);  	/* set baud rate */  	baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk); diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 654755a990d..333c8d012b0 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1348,10 +1348,16 @@ static int pmz_verify_port(struct uart_port *port, struct serial_struct *ser)  static int pmz_poll_get_char(struct uart_port *port)  {  	struct uart_pmac_port *uap = (struct uart_pmac_port *)port; +	int tries = 2; -	while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) -		udelay(5); -	return read_zsdata(uap); +	while (tries) { +		if ((read_zsreg(uap, R0) & Rx_CH_AV) != 0) +			return read_zsdata(uap); +		if (tries--) +			udelay(5); +	} + +	return NO_POLL_CHAR;  }  static void pmz_poll_put_char(struct uart_port *port, unsigned char c) diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index a7773a3e02b..7065df6036c 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -13,7 +13,7 @@ config USB_ARCH_HAS_OHCI  	default y if PXA3xx  	default y if ARCH_EP93XX  	default y if ARCH_AT91 -	default y if ARCH_PNX4008 && I2C +	default y if ARCH_PNX4008  	default y if MFD_TC6393XB  	default y if ARCH_W90X900  	default y if ARCH_DAVINCI_DA8XX diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index 8337fb5d988..47e499c9c0b 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig @@ -1,9 +1,9 @@  config USB_CHIPIDEA  	tristate "ChipIdea Highspeed Dual Role Controller" -	depends on USB +	depends on USB || USB_GADGET  	help -          Say Y here if your system has a dual role high speed USB -          controller based on ChipIdea silicon IP. Currently, only the +	  Say Y here if your system has a dual role high speed USB +	  controller based on ChipIdea silicon IP. Currently, only the  	  peripheral mode is supported.  	  When compiled dynamically, the module will be called ci-hdrc.ko. @@ -12,7 +12,7 @@ if USB_CHIPIDEA  config USB_CHIPIDEA_UDC  	bool "ChipIdea device controller" -	depends on USB_GADGET +	depends on USB_GADGET=y || USB_GADGET=USB_CHIPIDEA  	select USB_GADGET_DUALSPEED  	help  	  Say Y here to enable device controller functionality of the @@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC  config USB_CHIPIDEA_HOST  	bool "ChipIdea host controller" +	depends on USB=y || USB=USB_CHIPIDEA  	select USB_EHCI_ROOT_HUB_TT  	help  	  Say Y here to enable host controller functionality of the diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 56d6bf66848..f763ed7ba91 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1104,7 +1104,8 @@ skip_normal_probe:  	} -	if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) +	if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || +	    control_interface->cur_altsetting->desc.bNumEndpoints == 0)  		return -EINVAL;  	epctrl = &control_interface->cur_altsetting->endpoint[0].desc; diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index ee0ebacf822..89dcf155d57 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -450,7 +450,7 @@ static int dbgp_ehci_startup(void)  	writel(FLAG_CF, &ehci_regs->configured_flag);  	/* Wait until the controller is no longer halted */ -	loop = 10; +	loop = 1000;  	do {  		status = readl(&ehci_regs->status);  		if (!(status & STS_HALT)) diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 90e82e288eb..0e523092615 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -669,6 +669,8 @@ static int eth_stop(struct net_device *net)  	spin_lock_irqsave(&dev->lock, flags);  	if (dev->port_usb) {  		struct gether	*link = dev->port_usb; +		const struct usb_endpoint_descriptor *in; +		const struct usb_endpoint_descriptor *out;  		if (link->close)  			link->close(link); @@ -682,10 +684,14 @@ static int eth_stop(struct net_device *net)  		 * their own pace; the network stack can handle old packets.  		 * For the moment we leave this here, since it works.  		 */ +		in = link->in_ep->desc; +		out = link->out_ep->desc;  		usb_ep_disable(link->in_ep);  		usb_ep_disable(link->out_ep);  		if (netif_carrier_ok(net)) {  			DBG(dev, "host still using in/out endpoints\n"); +			link->in_ep->desc = in; +			link->out_ep->desc = out;  			usb_ep_enable(link->in_ep);  			usb_ep_enable(link->out_ep);  		} diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index bb55eb4a7d4..d7fe287d067 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -56,15 +56,6 @@  #define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8  #define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0 -/* Errata i693 */ -static struct clk	*utmi_p1_fck; -static struct clk	*utmi_p2_fck; -static struct clk	*xclk60mhsp1_ck; -static struct clk	*xclk60mhsp2_ck; -static struct clk	*usbhost_p1_fck; -static struct clk	*usbhost_p2_fck; -static struct clk	*init_60m_fclk; -  /*-------------------------------------------------------------------------*/  static const struct hc_driver ehci_omap_hc_driver; @@ -80,40 +71,6 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)  	return __raw_readl(base + reg);  } -/* Erratum i693 workaround sequence */ -static void omap_ehci_erratum_i693(struct ehci_hcd *ehci) -{ -	int ret = 0; - -	/* Switch to the internal 60 MHz clock */ -	ret = clk_set_parent(utmi_p1_fck, init_60m_fclk); -	if (ret != 0) -		ehci_err(ehci, "init_60m_fclk set parent" -			"failed error:%d\n", ret); - -	ret = clk_set_parent(utmi_p2_fck, init_60m_fclk); -	if (ret != 0) -		ehci_err(ehci, "init_60m_fclk set parent" -			"failed error:%d\n", ret); - -	clk_enable(usbhost_p1_fck); -	clk_enable(usbhost_p2_fck); - -	/* Wait 1ms and switch back to the external clock */ -	mdelay(1); -	ret = clk_set_parent(utmi_p1_fck, xclk60mhsp1_ck); -	if (ret != 0) -		ehci_err(ehci, "xclk60mhsp1_ck set parent" -			"failed error:%d\n", ret); - -	ret = clk_set_parent(utmi_p2_fck, xclk60mhsp2_ck); -	if (ret != 0) -		ehci_err(ehci, "xclk60mhsp2_ck set parent" -			"failed error:%d\n", ret); - -	clk_disable(usbhost_p1_fck); -	clk_disable(usbhost_p2_fck); -}  static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port)  { @@ -195,50 +152,6 @@ static int omap_ehci_init(struct usb_hcd *hcd)  	return rc;  } -static int omap_ehci_hub_control( -	struct usb_hcd	*hcd, -	u16		typeReq, -	u16		wValue, -	u16		wIndex, -	char		*buf, -	u16		wLength -) -{ -	struct ehci_hcd	*ehci = hcd_to_ehci(hcd); -	u32 __iomem *status_reg = &ehci->regs->port_status[ -				(wIndex & 0xff) - 1]; -	u32		temp; -	unsigned long	flags; -	int		retval = 0; - -	spin_lock_irqsave(&ehci->lock, flags); - -	if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { -		temp = ehci_readl(ehci, status_reg); -		if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { -			retval = -EPIPE; -			goto done; -		} - -		temp &= ~PORT_WKCONN_E; -		temp |= PORT_WKDISC_E | PORT_WKOC_E; -		ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); - -		omap_ehci_erratum_i693(ehci); - -		set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); -		goto done; -	} - -	spin_unlock_irqrestore(&ehci->lock, flags); - -	/* Handle the hub control events here */ -	return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); -done: -	spin_unlock_irqrestore(&ehci->lock, flags); -	return retval; -} -  static void disable_put_regulator(  		struct ehci_hcd_omap_platform_data *pdata)  { @@ -351,79 +264,9 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)  		goto err_pm_runtime;  	} -	/* get clocks */ -	utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); -	if (IS_ERR(utmi_p1_fck)) { -		ret = PTR_ERR(utmi_p1_fck); -		dev_err(dev, "utmi_p1_gfclk failed error:%d\n",	ret); -		goto err_add_hcd; -	} - -	xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); -	if (IS_ERR(xclk60mhsp1_ck)) { -		ret = PTR_ERR(xclk60mhsp1_ck); -		dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); -		goto err_utmi_p1_fck; -	} - -	utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); -	if (IS_ERR(utmi_p2_fck)) { -		ret = PTR_ERR(utmi_p2_fck); -		dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); -		goto err_xclk60mhsp1_ck; -	} - -	xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); -	if (IS_ERR(xclk60mhsp2_ck)) { -		ret = PTR_ERR(xclk60mhsp2_ck); -		dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); -		goto err_utmi_p2_fck; -	} - -	usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); -	if (IS_ERR(usbhost_p1_fck)) { -		ret = PTR_ERR(usbhost_p1_fck); -		dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); -		goto err_xclk60mhsp2_ck; -	} - -	usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); -	if (IS_ERR(usbhost_p2_fck)) { -		ret = PTR_ERR(usbhost_p2_fck); -		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); -		goto err_usbhost_p1_fck; -	} - -	init_60m_fclk = clk_get(dev, "init_60m_fclk"); -	if (IS_ERR(init_60m_fclk)) { -		ret = PTR_ERR(init_60m_fclk); -		dev_err(dev, "init_60m_fclk failed error:%d\n", ret); -		goto err_usbhost_p2_fck; -	}  	return 0; -err_usbhost_p2_fck: -	clk_put(usbhost_p2_fck); - -err_usbhost_p1_fck: -	clk_put(usbhost_p1_fck); - -err_xclk60mhsp2_ck: -	clk_put(xclk60mhsp2_ck); - -err_utmi_p2_fck: -	clk_put(utmi_p2_fck); - -err_xclk60mhsp1_ck: -	clk_put(xclk60mhsp1_ck); - -err_utmi_p1_fck: -	clk_put(utmi_p1_fck); - -err_add_hcd: -	usb_remove_hcd(hcd); -  err_pm_runtime:  	disable_put_regulator(pdata);  	pm_runtime_put_sync(dev); @@ -454,14 +297,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)  	iounmap(hcd->regs);  	usb_put_hcd(hcd); -	clk_put(utmi_p1_fck); -	clk_put(utmi_p2_fck); -	clk_put(xclk60mhsp1_ck); -	clk_put(xclk60mhsp2_ck); -	clk_put(usbhost_p1_fck); -	clk_put(usbhost_p2_fck); -	clk_put(init_60m_fclk); -  	pm_runtime_put_sync(dev);  	pm_runtime_disable(dev); @@ -532,7 +367,7 @@ static const struct hc_driver ehci_omap_hc_driver = {  	 * root hub support  	 */  	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= omap_ehci_hub_control, +	.hub_control		= ehci_hub_control,  	.bus_suspend		= ehci_bus_suspend,  	.bus_resume		= ehci_bus_resume, diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c index 58c96bd50d2..0c9e43cfaff 100644 --- a/drivers/usb/host/ehci-sead3.c +++ b/drivers/usb/host/ehci-sead3.c @@ -40,7 +40,7 @@ static int ehci_sead3_setup(struct usb_hcd *hcd)  	ehci->need_io_watchdog = 0;  	/* Set burst length to 16 words. */ -	ehci_writel(ehci, 0x1010, &ehci->regs->reserved[1]); +	ehci_writel(ehci, 0x1010, &ehci->regs->reserved1[1]);  	return ret;  } diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 950e95efa38..26dedb30ad0 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -799,11 +799,12 @@ static int tegra_ehci_remove(struct platform_device *pdev)  #endif  	usb_remove_hcd(hcd); -	usb_put_hcd(hcd);  	tegra_usb_phy_close(tegra->phy);  	iounmap(hcd->regs); +	usb_put_hcd(hcd); +  	clk_disable_unprepare(tegra->clk);  	clk_put(tegra->clk); diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 2ed112d3e15..256326322cf 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -543,12 +543,12 @@ static void postproc_ep(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep)  			    usb_pipein(urb->pipe) ? "IN" : "OUT", ep->nextpid,  			    short_ok ? "" : "not_",  			    PTD_GET_COUNT(ptd), ep->maxpacket, len); +			/* save the data underrun error code for later and +			 * proceed with the status stage +			 */ +			urb->actual_length += PTD_GET_COUNT(ptd);  			if (usb_pipecontrol(urb->pipe)) {  				ep->nextpid = USB_PID_ACK; -				/* save the data underrun error code for later and -				 * proceed with the status stage -				 */ -				urb->actual_length += PTD_GET_COUNT(ptd);  				BUG_ON(urb->actual_length > urb->transfer_buffer_length);  				if (urb->status == -EINPROGRESS) diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index e7d75d29598..f8b2d91851f 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -403,8 +403,6 @@ err0:  static inline void  usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)  { -	struct ohci_hcd		*ohci = hcd_to_ohci (hcd); -  	usb_remove_hcd(hcd);  	if (!IS_ERR_OR_NULL(hcd->phy)) {  		(void) otg_set_host(hcd->phy->otg, 0); diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index df0828cb2aa..c5e9e4a76f1 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -800,6 +800,13 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)  }  EXPORT_SYMBOL_GPL(usb_enable_xhci_ports); +void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) +{ +	pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0); +	pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0); +} +EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); +  /**   * PCI Quirks for xHCI.   * diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index b1002a8ef96..ef004a5de20 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -10,6 +10,7 @@ void usb_amd_quirk_pll_disable(void);  void usb_amd_quirk_pll_enable(void);  bool usb_is_intel_switchable_xhci(struct pci_dev *pdev);  void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); +void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);  #else  static inline void usb_amd_quirk_pll_disable(void) {}  static inline void usb_amd_quirk_pll_enable(void) {} diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 18b231b0c5d..9bfd4ca1153 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -94,11 +94,21 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)  		xhci->quirks |= XHCI_EP_LIMIT_QUIRK;  		xhci->limit_active_eps = 64;  		xhci->quirks |= XHCI_SW_BW_CHECKING; +		/* +		 * PPT desktop boards DH77EB and DH77DF will power back on after +		 * a few seconds of being shutdown.  The fix for this is to +		 * switch the ports from xHCI to EHCI on shutdown.  We can't use +		 * DMI information to find those particular boards (since each +		 * vendor will change the board name), so we have to key off all +		 * PPT chipsets. +		 */ +		xhci->quirks |= XHCI_SPURIOUS_REBOOT;  	}  	if (pdev->vendor == PCI_VENDOR_ID_ETRON &&  			pdev->device == PCI_DEVICE_ID_ASROCK_P67) {  		xhci->quirks |= XHCI_RESET_ON_RESUME;  		xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); +		xhci->quirks |= XHCI_TRUST_TX_LENGTH;  	}  	if (pdev->vendor == PCI_VENDOR_ID_VIA)  		xhci->quirks |= XHCI_RESET_ON_RESUME; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 8275645889d..643c2f3f3e7 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -145,29 +145,37 @@ static void next_trb(struct xhci_hcd *xhci,   */  static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)  { -	union xhci_trb *next;  	unsigned long long addr;  	ring->deq_updates++; -	/* If this is not event ring, there is one more usable TRB */ +	/* +	 * If this is not event ring, and the dequeue pointer +	 * is not on a link TRB, there is one more usable TRB +	 */  	if (ring->type != TYPE_EVENT &&  			!last_trb(xhci, ring, ring->deq_seg, ring->dequeue))  		ring->num_trbs_free++; -	next = ++(ring->dequeue); -	/* Update the dequeue pointer further if that was a link TRB or we're at -	 * the end of an event ring segment (which doesn't have link TRBS) -	 */ -	while (last_trb(xhci, ring, ring->deq_seg, next)) { -		if (ring->type == TYPE_EVENT &&	last_trb_on_last_seg(xhci, -				ring, ring->deq_seg, next)) { -			ring->cycle_state = (ring->cycle_state ? 0 : 1); +	do { +		/* +		 * Update the dequeue pointer further if that was a link TRB or +		 * we're at the end of an event ring segment (which doesn't have +		 * link TRBS) +		 */ +		if (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)) { +			if (ring->type == TYPE_EVENT && +					last_trb_on_last_seg(xhci, ring, +						ring->deq_seg, ring->dequeue)) { +				ring->cycle_state = (ring->cycle_state ? 0 : 1); +			} +			ring->deq_seg = ring->deq_seg->next; +			ring->dequeue = ring->deq_seg->trbs; +		} else { +			ring->dequeue++;  		} -		ring->deq_seg = ring->deq_seg->next; -		ring->dequeue = ring->deq_seg->trbs; -		next = ring->dequeue; -	} +	} while (last_trb(xhci, ring, ring->deq_seg, ring->dequeue)); +  	addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);  } @@ -2073,8 +2081,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,  		if (xhci->quirks & XHCI_TRUST_TX_LENGTH)  			trb_comp_code = COMP_SHORT_TX;  		else -			xhci_warn(xhci, "WARN Successful completion on short TX: " -					"needs XHCI_TRUST_TX_LENGTH quirk?\n"); +			xhci_warn_ratelimited(xhci, +					"WARN Successful completion on short TX: needs XHCI_TRUST_TX_LENGTH quirk?\n");  	case COMP_SHORT_TX:  		break;  	case COMP_STOP: diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7648b2d4b26..c59d5b5b6c7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -166,7 +166,7 @@ int xhci_reset(struct xhci_hcd *xhci)  	xhci_writel(xhci, command, &xhci->op_regs->command);  	ret = handshake(xhci, &xhci->op_regs->command, -			CMD_RESET, 0, 250 * 1000); +			CMD_RESET, 0, 10 * 1000 * 1000);  	if (ret)  		return ret; @@ -175,7 +175,8 @@ int xhci_reset(struct xhci_hcd *xhci)  	 * xHCI cannot write to any doorbells or operational registers other  	 * than status until the "Controller Not Ready" flag is cleared.  	 */ -	ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); +	ret = handshake(xhci, &xhci->op_regs->status, +			STS_CNR, 0, 10 * 1000 * 1000);  	for (i = 0; i < 2; ++i) {  		xhci->bus_state[i].port_c_suspend = 0; @@ -658,6 +659,9 @@ void xhci_shutdown(struct usb_hcd *hcd)  {  	struct xhci_hcd *xhci = hcd_to_xhci(hcd); +	if (xhci->quirks && XHCI_SPURIOUS_REBOOT) +		usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); +  	spin_lock_irq(&xhci->lock);  	xhci_halt(xhci);  	spin_unlock_irq(&xhci->lock); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 55c0785810c..c713256297a 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1494,6 +1494,7 @@ struct xhci_hcd {  #define XHCI_TRUST_TX_LENGTH	(1 << 10)  #define XHCI_LPM_SUPPORT	(1 << 11)  #define XHCI_INTEL_HOST		(1 << 12) +#define XHCI_SPURIOUS_REBOOT	(1 << 13)  	unsigned int		num_active_eps;  	unsigned int		limit_active_eps;  	/* There are two roothubs to keep track of bus suspend info for */ @@ -1537,6 +1538,8 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)  	dev_err(xhci_to_hcd(xhci)->self.controller , fmt , ## args)  #define xhci_warn(xhci, fmt, args...) \  	dev_warn(xhci_to_hcd(xhci)->self.controller , fmt , ## args) +#define xhci_warn_ratelimited(xhci, fmt, args...) \ +	dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args)  /* TODO: copied from ehci.h - can be refactored? */  /* xHCI spec says all registers are little endian */ diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index ff08015b230..ae794b90766 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -232,7 +232,7 @@ wraperr:  	return err;  } -static const struct usb_device_id id_table[] __devinitconst = { +static const struct usb_device_id id_table[] = {  	{ USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) },  	{ }                                             /* Terminating entry */  }; diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index ef0c3f9f094..6259f0d9932 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -8,7 +8,7 @@ config USB_MUSB_HDRC  	tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'  	depends on USB && USB_GADGET  	select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN) -	select NOP_USB_XCEIV if (SOC_OMAPTI81XX || SOC_OMAPAM33XX) +	select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX)  	select TWL4030_USB if MACH_OMAP_3430SDP  	select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA  	select USB_OTG_UTILS @@ -57,7 +57,7 @@ config USB_MUSB_AM35X  config USB_MUSB_DSPS  	tristate "TI DSPS platforms" -	depends on SOC_OMAPTI81XX || SOC_OMAPAM33XX +	depends on SOC_TI81XX || SOC_AM33XX  config USB_MUSB_BLACKFIN  	tristate "Blackfin" diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 217808d9fbe..494772fc9e2 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -479,9 +479,9 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)  		ret = -ENODEV;  		goto err0;  	} -	strcpy((u8 *)res->name, "mc");  	res->parent = NULL;  	resources[1] = *res; +	resources[1].name = "mc";  	/* allocate the child platform device */  	musb = platform_device_alloc("musb-hdrc", -1); @@ -566,27 +566,28 @@ static int __devinit dsps_probe(struct platform_device *pdev)  	}  	platform_set_drvdata(pdev, glue); -	/* create the child platform device for first instances of musb */ -	ret = dsps_create_musb_pdev(glue, 0); -	if (ret != 0) { -		dev_err(&pdev->dev, "failed to create child pdev\n"); -		goto err2; -	} -  	/* enable the usbss clocks */  	pm_runtime_enable(&pdev->dev);  	ret = pm_runtime_get_sync(&pdev->dev);  	if (ret < 0) {  		dev_err(&pdev->dev, "pm_runtime_get_sync FAILED"); +		goto err2; +	} + +	/* create the child platform device for first instances of musb */ +	ret = dsps_create_musb_pdev(glue, 0); +	if (ret != 0) { +		dev_err(&pdev->dev, "failed to create child pdev\n");  		goto err3;  	}  	return 0;  err3: -	pm_runtime_disable(&pdev->dev); +	pm_runtime_put(&pdev->dev);  err2: +	pm_runtime_disable(&pdev->dev);  	kfree(glue->wrp);  err1:  	kfree(glue); diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 8c9bb1ad306..681da06170c 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -603,12 +603,12 @@ static int usbhsc_resume(struct device *dev)  	struct usbhs_priv *priv = dev_get_drvdata(dev);  	struct platform_device *pdev = usbhs_priv_to_pdev(priv); -	usbhs_platform_call(priv, phy_reset, pdev); -  	if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))  		usbhsc_power_ctrl(priv, 1); -	usbhsc_hotplug(priv); +	usbhs_platform_call(priv, phy_reset, pdev); + +	usbhsc_drvcllbck_notify_hotplug(pdev);  	return 0;  } diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 1834cf50888..9b69a132329 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -1266,6 +1266,12 @@ static int usbhsh_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,  	return ret;  } +static int usbhsh_bus_nop(struct usb_hcd *hcd) +{ +	/* nothing to do */ +	return 0; +} +  static struct hc_driver usbhsh_driver = {  	.description =		usbhsh_hcd_name,  	.hcd_priv_size =	sizeof(struct usbhsh_hpriv), @@ -1290,6 +1296,8 @@ static struct hc_driver usbhsh_driver = {  	 */  	.hub_status_data =	usbhsh_hub_status_data,  	.hub_control =		usbhsh_hub_control, +	.bus_suspend =		usbhsh_bus_nop, +	.bus_resume =		usbhsh_bus_nop,  };  /* diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index f398d1e3447..c15f2e7cefc 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -61,18 +61,23 @@ static int usb_serial_device_probe(struct device *dev)  		goto exit;  	} +	/* make sure suspend/resume doesn't race against port_probe */ +	retval = usb_autopm_get_interface(port->serial->interface); +	if (retval) +		goto exit; +  	driver = port->serial->type;  	if (driver->port_probe) {  		retval = driver->port_probe(port);  		if (retval) -			goto exit; +			goto exit_with_autopm;  	}  	retval = device_create_file(dev, &dev_attr_port_number);  	if (retval) {  		if (driver->port_remove)  			retval = driver->port_remove(port); -		goto exit; +		goto exit_with_autopm;  	}  	minor = port->number; @@ -81,6 +86,8 @@ static int usb_serial_device_probe(struct device *dev)  		 "%s converter now attached to ttyUSB%d\n",  		 driver->description, minor); +exit_with_autopm: +	usb_autopm_put_interface(port->serial->interface);  exit:  	return retval;  } @@ -96,6 +103,9 @@ static int usb_serial_device_remove(struct device *dev)  	if (!port)  		return -ENODEV; +	/* make sure suspend/resume doesn't race against port_remove */ +	usb_autopm_get_interface(port->serial->interface); +  	device_remove_file(&port->dev, &dev_attr_port_number);  	driver = port->serial->type; @@ -107,6 +117,7 @@ static int usb_serial_device_remove(struct device *dev)  	dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",  		 driver->description, minor); +	usb_autopm_put_interface(port->serial->interface);  	return retval;  } diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index bc912e5a3be..5620db6469e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -811,6 +811,7 @@ static struct usb_device_id id_table_combined [] = {  	{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },  	{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },  	{ USB_DEVICE(PI_VID, PI_E861_PID) }, +	{ USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },  	{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },  	{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),  		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5661c7e2d41..5dd96ca6c38 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -795,6 +795,13 @@  #define PI_E861_PID         0x1008  /* E-861 piezo controller USB connection */  /* + * Kondo Kagaku Co.Ltd. + * http://www.kondo-robot.com/EN + */ +#define KONDO_VID 		0x165c +#define KONDO_USB_SERIAL_PID	0x0002 + +/*   * Bayer Ascensia Contour blood glucose meter USB-converter cable.   * http://winglucofacts.com/cables/   */ diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 5811d34b6c6..2cb30c53583 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -227,7 +227,6 @@ static void ipw_release(struct usb_serial *serial)  {  	struct usb_wwan_intf_private *data = usb_get_serial_data(serial); -	usb_wwan_release(serial);  	usb_set_serial_data(serial, NULL);  	kfree(data);  } @@ -309,12 +308,12 @@ static struct usb_serial_driver ipw_device = {  	.description =		"IPWireless converter",  	.id_table =		id_table,  	.num_ports =		1, -	.disconnect =		usb_wwan_disconnect,  	.open =			ipw_open,  	.close =		ipw_close,  	.probe =		ipw_probe,  	.attach =		usb_wwan_startup,  	.release =		ipw_release, +	.port_remove =		usb_wwan_port_remove,  	.dtr_rts =		ipw_dtr_rts,  	.write =		usb_wwan_write,  }; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 57eca244842..2f6da1e89bf 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -82,8 +82,7 @@   * Defines used for sending commands to port   */ -#define WAIT_FOR_EVER   (HZ * 0)	/* timeout urb is wait for ever */ -#define MOS_WDR_TIMEOUT (HZ * 5)	/* default urb timeout */ +#define MOS_WDR_TIMEOUT		5000	/* default urb timeout */  #define MOS_PORT1       0x0200  #define MOS_PORT2       0x0300 @@ -1232,9 +1231,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty)  		return 0;  	spin_lock_irqsave(&mos7840_port->pool_lock, flags); -	for (i = 0; i < NUM_URBS; ++i) -		if (mos7840_port->busy[i]) -			chars += URB_TRANSFER_BUFFER_SIZE; +	for (i = 0; i < NUM_URBS; ++i) { +		if (mos7840_port->busy[i]) { +			struct urb *urb = mos7840_port->write_urb_pool[i]; +			chars += urb->transfer_buffer_length; +		} +	}  	spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);  	dbg("%s - returns %d", __func__, chars);  	return chars; @@ -1344,7 +1346,7 @@ static void mos7840_close(struct usb_serial_port *port)  static void mos7840_block_until_chase_response(struct tty_struct *tty,  					struct moschip_port *mos7840_port)  { -	int timeout = 1 * HZ; +	int timeout = msecs_to_jiffies(1000);  	int wait = 10;  	int count; @@ -2672,7 +2674,7 @@ static int mos7840_startup(struct usb_serial *serial)  	/* setting configuration feature to one */  	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), -			(__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ); +			(__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT);  	return 0;  error:  	for (/* nothing */; i >= 0; i--) { diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 08ff9b86204..cc40f47ecea 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -80,85 +80,9 @@ static void option_instat_callback(struct urb *urb);  #define OPTION_PRODUCT_GTM380_MODEM		0x7201  #define HUAWEI_VENDOR_ID			0x12D1 -#define HUAWEI_PRODUCT_E600			0x1001 -#define HUAWEI_PRODUCT_E220			0x1003 -#define HUAWEI_PRODUCT_E220BIS			0x1004 -#define HUAWEI_PRODUCT_E1401			0x1401 -#define HUAWEI_PRODUCT_E1402			0x1402 -#define HUAWEI_PRODUCT_E1403			0x1403 -#define HUAWEI_PRODUCT_E1404			0x1404 -#define HUAWEI_PRODUCT_E1405			0x1405 -#define HUAWEI_PRODUCT_E1406			0x1406 -#define HUAWEI_PRODUCT_E1407			0x1407 -#define HUAWEI_PRODUCT_E1408			0x1408 -#define HUAWEI_PRODUCT_E1409			0x1409 -#define HUAWEI_PRODUCT_E140A			0x140A -#define HUAWEI_PRODUCT_E140B			0x140B -#define HUAWEI_PRODUCT_E140C			0x140C -#define HUAWEI_PRODUCT_E140D			0x140D -#define HUAWEI_PRODUCT_E140E			0x140E -#define HUAWEI_PRODUCT_E140F			0x140F -#define HUAWEI_PRODUCT_E1410			0x1410 -#define HUAWEI_PRODUCT_E1411			0x1411 -#define HUAWEI_PRODUCT_E1412			0x1412 -#define HUAWEI_PRODUCT_E1413			0x1413 -#define HUAWEI_PRODUCT_E1414			0x1414 -#define HUAWEI_PRODUCT_E1415			0x1415 -#define HUAWEI_PRODUCT_E1416			0x1416 -#define HUAWEI_PRODUCT_E1417			0x1417 -#define HUAWEI_PRODUCT_E1418			0x1418 -#define HUAWEI_PRODUCT_E1419			0x1419 -#define HUAWEI_PRODUCT_E141A			0x141A -#define HUAWEI_PRODUCT_E141B			0x141B -#define HUAWEI_PRODUCT_E141C			0x141C -#define HUAWEI_PRODUCT_E141D			0x141D -#define HUAWEI_PRODUCT_E141E			0x141E -#define HUAWEI_PRODUCT_E141F			0x141F -#define HUAWEI_PRODUCT_E1420			0x1420 -#define HUAWEI_PRODUCT_E1421			0x1421 -#define HUAWEI_PRODUCT_E1422			0x1422 -#define HUAWEI_PRODUCT_E1423			0x1423 -#define HUAWEI_PRODUCT_E1424			0x1424 -#define HUAWEI_PRODUCT_E1425			0x1425 -#define HUAWEI_PRODUCT_E1426			0x1426 -#define HUAWEI_PRODUCT_E1427			0x1427 -#define HUAWEI_PRODUCT_E1428			0x1428 -#define HUAWEI_PRODUCT_E1429			0x1429 -#define HUAWEI_PRODUCT_E142A			0x142A -#define HUAWEI_PRODUCT_E142B			0x142B -#define HUAWEI_PRODUCT_E142C			0x142C -#define HUAWEI_PRODUCT_E142D			0x142D -#define HUAWEI_PRODUCT_E142E			0x142E -#define HUAWEI_PRODUCT_E142F			0x142F -#define HUAWEI_PRODUCT_E1430			0x1430 -#define HUAWEI_PRODUCT_E1431			0x1431 -#define HUAWEI_PRODUCT_E1432			0x1432 -#define HUAWEI_PRODUCT_E1433			0x1433 -#define HUAWEI_PRODUCT_E1434			0x1434 -#define HUAWEI_PRODUCT_E1435			0x1435 -#define HUAWEI_PRODUCT_E1436			0x1436 -#define HUAWEI_PRODUCT_E1437			0x1437 -#define HUAWEI_PRODUCT_E1438			0x1438 -#define HUAWEI_PRODUCT_E1439			0x1439 -#define HUAWEI_PRODUCT_E143A			0x143A -#define HUAWEI_PRODUCT_E143B			0x143B -#define HUAWEI_PRODUCT_E143C			0x143C -#define HUAWEI_PRODUCT_E143D			0x143D -#define HUAWEI_PRODUCT_E143E			0x143E -#define HUAWEI_PRODUCT_E143F			0x143F  #define HUAWEI_PRODUCT_K4505			0x1464  #define HUAWEI_PRODUCT_K3765			0x1465 -#define HUAWEI_PRODUCT_E14AC			0x14AC -#define HUAWEI_PRODUCT_K3806			0x14AE  #define HUAWEI_PRODUCT_K4605			0x14C6 -#define HUAWEI_PRODUCT_K5005			0x14C8 -#define HUAWEI_PRODUCT_K3770			0x14C9 -#define HUAWEI_PRODUCT_K3771			0x14CA -#define HUAWEI_PRODUCT_K4510			0x14CB -#define HUAWEI_PRODUCT_K4511			0x14CC -#define HUAWEI_PRODUCT_ETS1220			0x1803 -#define HUAWEI_PRODUCT_E353			0x1506 -#define HUAWEI_PRODUCT_E173S			0x1C05  #define QUANTA_VENDOR_ID			0x0408  #define QUANTA_PRODUCT_Q101			0xEA02 @@ -615,104 +539,123 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },  	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },  	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff),  		.driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) }, -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) },  /* E398 3G Modem */ -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) },  /* E398 3G PC UI Interface */ -	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) },  /* E398 3G Application Interface */ +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) }, +	{ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) }, + +  	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },  	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },  	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, @@ -943,6 +886,8 @@ static const struct usb_device_id option_ids[] = {  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),  	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, +	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff), +	  .driver_info = (kernel_ulong_t)&net_intf3_blacklist },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },  	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1297,8 +1242,8 @@ static struct usb_serial_driver option_1port_device = {  	.tiocmset          = usb_wwan_tiocmset,  	.ioctl             = usb_wwan_ioctl,  	.attach            = usb_wwan_startup, -	.disconnect        = usb_wwan_disconnect,  	.release           = option_release, +	.port_remove	   = usb_wwan_port_remove,  	.read_int_callback = option_instat_callback,  #ifdef CONFIG_PM  	.suspend           = usb_wwan_suspend, @@ -1414,8 +1359,6 @@ static void option_release(struct usb_serial *serial)  	struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);  	struct option_private *priv = intfdata->private; -	usb_wwan_release(serial); -  	kfree(priv);  	kfree(intfdata);  } diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 8d103019d6a..bfd50779f0c 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -199,43 +199,49 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)  	/* default to enabling interface */  	altsetting = 0; -	switch (ifnum) { -		/* Composite mode; don't bind to the QMI/net interface as that -		 * gets handled by other drivers. -		 */ +	/* Composite mode; don't bind to the QMI/net interface as that +	 * gets handled by other drivers. +	 */ + +	if (is_gobi1k) {  		/* Gobi 1K USB layout:  		 * 0: serial port (doesn't respond)  		 * 1: serial port (doesn't respond)  		 * 2: AT-capable modem port  		 * 3: QMI/net -		 * -		 * Gobi 2K+ USB layout: +		 */ +		if (ifnum == 2) +			dev_dbg(dev, "Modem port found\n"); +		else +			altsetting = -1; +	} else { +		/* Gobi 2K+ USB layout:  		 * 0: QMI/net  		 * 1: DM/DIAG (use libqcdm from ModemManager for communication)  		 * 2: AT-capable modem port  		 * 3: NMEA  		 */ - -	case 1: -		if (is_gobi1k) +		switch (ifnum) { +		case 0: +			/* Don't claim the QMI/net interface */  			altsetting = -1; -		else +			break; +		case 1:  			dev_dbg(dev, "Gobi 2K+ DM/DIAG interface found\n"); -		break; -	case 2: -		dev_dbg(dev, "Modem port found\n"); -		break; -	case 3: -		if (is_gobi1k) -			altsetting = -1; -		else +			break; +		case 2: +			dev_dbg(dev, "Modem port found\n"); +			break; +		case 3:  			/*  			 * NMEA (serial line 9600 8N1)  			 * # echo "\$GPS_START" > /dev/ttyUSBx  			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx  			 */  			dev_dbg(dev, "Gobi 2K+ NMEA GPS interface found\n"); +			break; +		}  	}  done: @@ -262,8 +268,7 @@ static void qc_release(struct usb_serial *serial)  {  	struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); -	/* Call usb_wwan release & free the private data allocated in qcprobe */ -	usb_wwan_release(serial); +	/* Free the private data allocated in qcprobe */  	usb_set_serial_data(serial, NULL);  	kfree(priv);  } @@ -283,8 +288,8 @@ static struct usb_serial_driver qcdevice = {  	.write_room	     = usb_wwan_write_room,  	.chars_in_buffer     = usb_wwan_chars_in_buffer,  	.attach		     = usb_wwan_startup, -	.disconnect	     = usb_wwan_disconnect,  	.release	     = qc_release, +	.port_remove	     = usb_wwan_port_remove,  #ifdef CONFIG_PM  	.suspend	     = usb_wwan_suspend,  	.resume		     = usb_wwan_resume, diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index c47b6ec0306..1f034d2397c 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -9,8 +9,7 @@ extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);  extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);  extern void usb_wwan_close(struct usb_serial_port *port);  extern int usb_wwan_startup(struct usb_serial *serial); -extern void usb_wwan_disconnect(struct usb_serial *serial); -extern void usb_wwan_release(struct usb_serial *serial); +extern int usb_wwan_port_remove(struct usb_serial_port *port);  extern int usb_wwan_write_room(struct tty_struct *tty);  extern void usb_wwan_set_termios(struct tty_struct *tty,  				 struct usb_serial_port *port, diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index f35971dff4a..6855d5ed033 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -565,62 +565,52 @@ bail_out_error:  }  EXPORT_SYMBOL(usb_wwan_startup); -static void stop_read_write_urbs(struct usb_serial *serial) +int usb_wwan_port_remove(struct usb_serial_port *port)  { -	int i, j; -	struct usb_serial_port *port; +	int i;  	struct usb_wwan_port_private *portdata; -	/* Stop reading/writing urbs */ -	for (i = 0; i < serial->num_ports; ++i) { -		port = serial->port[i]; -		portdata = usb_get_serial_port_data(port); -		for (j = 0; j < N_IN_URB; j++) -			usb_kill_urb(portdata->in_urbs[j]); -		for (j = 0; j < N_OUT_URB; j++) -			usb_kill_urb(portdata->out_urbs[j]); +	portdata = usb_get_serial_port_data(port); +	usb_set_serial_port_data(port, NULL); + +	/* Stop reading/writing urbs and free them */ +	for (i = 0; i < N_IN_URB; i++) { +		usb_kill_urb(portdata->in_urbs[i]); +		usb_free_urb(portdata->in_urbs[i]); +		free_page((unsigned long)portdata->in_buffer[i]); +	} +	for (i = 0; i < N_OUT_URB; i++) { +		usb_kill_urb(portdata->out_urbs[i]); +		usb_free_urb(portdata->out_urbs[i]); +		kfree(portdata->out_buffer[i]);  	} -} -void usb_wwan_disconnect(struct usb_serial *serial) -{ -	stop_read_write_urbs(serial); +	/* Now free port private data */ +	kfree(portdata); +	return 0;  } -EXPORT_SYMBOL(usb_wwan_disconnect); +EXPORT_SYMBOL(usb_wwan_port_remove); -void usb_wwan_release(struct usb_serial *serial) +#ifdef CONFIG_PM +static void stop_read_write_urbs(struct usb_serial *serial)  {  	int i, j;  	struct usb_serial_port *port;  	struct usb_wwan_port_private *portdata; -	/* Now free them */ +	/* Stop reading/writing urbs */  	for (i = 0; i < serial->num_ports; ++i) {  		port = serial->port[i];  		portdata = usb_get_serial_port_data(port); - -		for (j = 0; j < N_IN_URB; j++) { -			usb_free_urb(portdata->in_urbs[j]); -			free_page((unsigned long) -				  portdata->in_buffer[j]); -			portdata->in_urbs[j] = NULL; -		} -		for (j = 0; j < N_OUT_URB; j++) { -			usb_free_urb(portdata->out_urbs[j]); -			kfree(portdata->out_buffer[j]); -			portdata->out_urbs[j] = NULL; -		} -	} - -	/* Now free per port private data */ -	for (i = 0; i < serial->num_ports; i++) { -		port = serial->port[i]; -		kfree(usb_get_serial_port_data(port)); +		if (!portdata) +			continue; +		for (j = 0; j < N_IN_URB; j++) +			usb_kill_urb(portdata->in_urbs[j]); +		for (j = 0; j < N_OUT_URB; j++) +			usb_kill_urb(portdata->out_urbs[j]);  	}  } -EXPORT_SYMBOL(usb_wwan_release); -#ifdef CONFIG_PM  int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)  {  	struct usb_wwan_intf_private *intfdata = serial->private; @@ -712,7 +702,7 @@ int usb_wwan_resume(struct usb_serial *serial)  		/* skip closed ports */  		spin_lock_irq(&intfdata->susp_lock); -		if (!portdata->opened) { +		if (!portdata || !portdata->opened) {  			spin_unlock_irq(&intfdata->susp_lock);  			continue;  		} diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 9591e2b509d..17830c9c7cc 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -264,6 +264,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)  	return group;  } +/* called with vfio.group_lock held */  static void vfio_group_release(struct kref *kref)  {  	struct vfio_group *group = container_of(kref, struct vfio_group, kref); @@ -287,13 +288,7 @@ static void vfio_group_release(struct kref *kref)  static void vfio_group_put(struct vfio_group *group)  { -	mutex_lock(&vfio.group_lock); -	/* -	 * Release needs to unlock to unregister the notifier, so only -	 * unlock if not released. -	 */ -	if (!kref_put(&group->kref, vfio_group_release)) -		mutex_unlock(&vfio.group_lock); +	kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock);  }  /* Assume group_lock or group reference is held */ @@ -401,7 +396,6 @@ static void vfio_device_release(struct kref *kref)  						  struct vfio_device, kref);  	struct vfio_group *group = device->group; -	mutex_lock(&group->device_lock);  	list_del(&device->group_next);  	mutex_unlock(&group->device_lock); @@ -416,8 +410,9 @@ static void vfio_device_release(struct kref *kref)  /* Device reference always implies a group reference */  static void vfio_device_put(struct vfio_device *device)  { -	kref_put(&device->kref, vfio_device_release); -	vfio_group_put(device->group); +	struct vfio_group *group = device->group; +	kref_put_mutex(&device->kref, vfio_device_release, &group->device_lock); +	vfio_group_put(group);  }  static void vfio_device_get(struct vfio_device *device) @@ -1116,10 +1111,10 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)  		 */  		filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); -		fd_install(ret, filep); -  		vfio_device_get(device);  		atomic_inc(&group->container_users); + +		fd_install(ret, filep);  		break;  	}  	mutex_unlock(&group->device_lock); diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index e4e2fd1b510..202bba6c997 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig @@ -9,3 +9,6 @@ config VHOST_NET  	  To compile this driver as a module, choose M here: the module will  	  be called vhost_net. +if STAGING +source "drivers/vhost/Kconfig.tcm" +endif diff --git a/drivers/vhost/Kconfig.tcm b/drivers/vhost/Kconfig.tcm new file mode 100644 index 00000000000..a9c6f76e320 --- /dev/null +++ b/drivers/vhost/Kconfig.tcm @@ -0,0 +1,6 @@ +config TCM_VHOST +	tristate "TCM_VHOST fabric module (EXPERIMENTAL)" +	depends on TARGET_CORE && EVENTFD && EXPERIMENTAL && m +	default n +	---help--- +	Say M here to enable the TCM_VHOST fabric module for use with virtio-scsi guests diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile index 72dd02050bb..a27b053bc9a 100644 --- a/drivers/vhost/Makefile +++ b/drivers/vhost/Makefile @@ -1,2 +1,4 @@  obj-$(CONFIG_VHOST_NET) += vhost_net.o  vhost_net-y := vhost.o net.o + +obj-$(CONFIG_TCM_VHOST) += tcm_vhost.o diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c new file mode 100644 index 00000000000..ed8e2e6c8df --- /dev/null +++ b/drivers/vhost/tcm_vhost.c @@ -0,0 +1,1649 @@ +/******************************************************************************* + * Vhost kernel TCM fabric driver for virtio SCSI initiators + * + * (C) Copyright 2010-2012 RisingTide Systems LLC. + * (C) Copyright 2010-2012 IBM Corp. + * + * Licensed to the Linux Foundation under the General Public License (GPL) version 2. + * + * Authors: Nicholas A. Bellinger <nab@risingtidesystems.com> + *          Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> + * + * 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, or + * (at your option) any later version. + * + * 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. + * + ****************************************************************************/ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <generated/utsrelease.h> +#include <linux/utsname.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/kthread.h> +#include <linux/types.h> +#include <linux/string.h> +#include <linux/configfs.h> +#include <linux/ctype.h> +#include <linux/compat.h> +#include <linux/eventfd.h> +#include <linux/vhost.h> +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <asm/unaligned.h> +#include <scsi/scsi.h> +#include <scsi/scsi_tcq.h> +#include <target/target_core_base.h> +#include <target/target_core_fabric.h> +#include <target/target_core_fabric_configfs.h> +#include <target/target_core_configfs.h> +#include <target/configfs_macros.h> +#include <linux/vhost.h> +#include <linux/virtio_net.h> /* TODO vhost.h currently depends on this */ +#include <linux/virtio_scsi.h> + +#include "vhost.c" +#include "vhost.h" +#include "tcm_vhost.h" + +enum { +	VHOST_SCSI_VQ_CTL = 0, +	VHOST_SCSI_VQ_EVT = 1, +	VHOST_SCSI_VQ_IO = 2, +}; + +struct vhost_scsi { +	struct tcm_vhost_tpg *vs_tpg;	/* Protected by vhost_scsi->dev.mutex */ +	struct vhost_dev dev; +	struct vhost_virtqueue vqs[3]; + +	struct vhost_work vs_completion_work; /* cmd completion work item */ +	struct list_head vs_completion_list;  /* cmd completion queue */ +	spinlock_t vs_completion_lock;        /* protects s_completion_list */ +}; + +/* Local pointer to allocated TCM configfs fabric module */ +static struct target_fabric_configfs *tcm_vhost_fabric_configfs; + +static struct workqueue_struct *tcm_vhost_workqueue; + +/* Global spinlock to protect tcm_vhost TPG list for vhost IOCTL access */ +static DEFINE_MUTEX(tcm_vhost_mutex); +static LIST_HEAD(tcm_vhost_list); + +static int tcm_vhost_check_true(struct se_portal_group *se_tpg) +{ +	return 1; +} + +static int tcm_vhost_check_false(struct se_portal_group *se_tpg) +{ +	return 0; +} + +static char *tcm_vhost_get_fabric_name(void) +{ +	return "vhost"; +} + +static u8 tcm_vhost_get_fabric_proto_ident(struct se_portal_group *se_tpg) +{ +	struct tcm_vhost_tpg *tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); +	struct tcm_vhost_tport *tport = tpg->tport; + +	switch (tport->tport_proto_id) { +	case SCSI_PROTOCOL_SAS: +		return sas_get_fabric_proto_ident(se_tpg); +	case SCSI_PROTOCOL_FCP: +		return fc_get_fabric_proto_ident(se_tpg); +	case SCSI_PROTOCOL_ISCSI: +		return iscsi_get_fabric_proto_ident(se_tpg); +	default: +		pr_err("Unknown tport_proto_id: 0x%02x, using" +			" SAS emulation\n", tport->tport_proto_id); +		break; +	} + +	return sas_get_fabric_proto_ident(se_tpg); +} + +static char *tcm_vhost_get_fabric_wwn(struct se_portal_group *se_tpg) +{ +	struct tcm_vhost_tpg *tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); +	struct tcm_vhost_tport *tport = tpg->tport; + +	return &tport->tport_name[0]; +} + +static u16 tcm_vhost_get_tag(struct se_portal_group *se_tpg) +{ +	struct tcm_vhost_tpg *tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); +	return tpg->tport_tpgt; +} + +static u32 tcm_vhost_get_default_depth(struct se_portal_group *se_tpg) +{ +	return 1; +} + +static u32 tcm_vhost_get_pr_transport_id(struct se_portal_group *se_tpg, +	struct se_node_acl *se_nacl, +	struct t10_pr_registration *pr_reg, +	int *format_code, +	unsigned char *buf) +{ +	struct tcm_vhost_tpg *tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); +	struct tcm_vhost_tport *tport = tpg->tport; + +	switch (tport->tport_proto_id) { +	case SCSI_PROTOCOL_SAS: +		return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg, +					format_code, buf); +	case SCSI_PROTOCOL_FCP: +		return fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg, +					format_code, buf); +	case SCSI_PROTOCOL_ISCSI: +		return iscsi_get_pr_transport_id(se_tpg, se_nacl, pr_reg, +					format_code, buf); +	default: +		pr_err("Unknown tport_proto_id: 0x%02x, using" +			" SAS emulation\n", tport->tport_proto_id); +		break; +	} + +	return sas_get_pr_transport_id(se_tpg, se_nacl, pr_reg, +			format_code, buf); +} + +static u32 tcm_vhost_get_pr_transport_id_len(struct se_portal_group *se_tpg, +	struct se_node_acl *se_nacl, +	struct t10_pr_registration *pr_reg, +	int *format_code) +{ +	struct tcm_vhost_tpg *tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); +	struct tcm_vhost_tport *tport = tpg->tport; + +	switch (tport->tport_proto_id) { +	case SCSI_PROTOCOL_SAS: +		return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, +					format_code); +	case SCSI_PROTOCOL_FCP: +		return fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, +					format_code); +	case SCSI_PROTOCOL_ISCSI: +		return iscsi_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, +					format_code); +	default: +		pr_err("Unknown tport_proto_id: 0x%02x, using" +			" SAS emulation\n", tport->tport_proto_id); +		break; +	} + +	return sas_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, +			format_code); +} + +static char *tcm_vhost_parse_pr_out_transport_id(struct se_portal_group *se_tpg, +	const char *buf, +	u32 *out_tid_len, +	char **port_nexus_ptr) +{ +	struct tcm_vhost_tpg *tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); +	struct tcm_vhost_tport *tport = tpg->tport; + +	switch (tport->tport_proto_id) { +	case SCSI_PROTOCOL_SAS: +		return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, +					port_nexus_ptr); +	case SCSI_PROTOCOL_FCP: +		return fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, +					port_nexus_ptr); +	case SCSI_PROTOCOL_ISCSI: +		return iscsi_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, +					port_nexus_ptr); +	default: +		pr_err("Unknown tport_proto_id: 0x%02x, using" +			" SAS emulation\n", tport->tport_proto_id); +		break; +	} + +	return sas_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, +			port_nexus_ptr); +} + +static struct se_node_acl *tcm_vhost_alloc_fabric_acl( +	struct se_portal_group *se_tpg) +{ +	struct tcm_vhost_nacl *nacl; + +	nacl = kzalloc(sizeof(struct tcm_vhost_nacl), GFP_KERNEL); +	if (!nacl) { +		pr_err("Unable to alocate struct tcm_vhost_nacl\n"); +		return NULL; +	} + +	return &nacl->se_node_acl; +} + +static void tcm_vhost_release_fabric_acl(struct se_portal_group *se_tpg, +	struct se_node_acl *se_nacl) +{ +	struct tcm_vhost_nacl *nacl = container_of(se_nacl, +			struct tcm_vhost_nacl, se_node_acl); +	kfree(nacl); +} + +static u32 tcm_vhost_tpg_get_inst_index(struct se_portal_group *se_tpg) +{ +	return 1; +} + +static void tcm_vhost_release_cmd(struct se_cmd *se_cmd) +{ +	return; +} + +static int tcm_vhost_shutdown_session(struct se_session *se_sess) +{ +	return 0; +} + +static void tcm_vhost_close_session(struct se_session *se_sess) +{ +	return; +} + +static u32 tcm_vhost_sess_get_index(struct se_session *se_sess) +{ +	return 0; +} + +static int tcm_vhost_write_pending(struct se_cmd *se_cmd) +{ +	/* Go ahead and process the write immediately */ +	target_execute_cmd(se_cmd); +	return 0; +} + +static int tcm_vhost_write_pending_status(struct se_cmd *se_cmd) +{ +	return 0; +} + +static void tcm_vhost_set_default_node_attrs(struct se_node_acl *nacl) +{ +	return; +} + +static u32 tcm_vhost_get_task_tag(struct se_cmd *se_cmd) +{ +	return 0; +} + +static int tcm_vhost_get_cmd_state(struct se_cmd *se_cmd) +{ +	return 0; +} + +static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *tv_cmd) +{ +	struct vhost_scsi *vs = tv_cmd->tvc_vhost; + +	spin_lock_bh(&vs->vs_completion_lock); +	list_add_tail(&tv_cmd->tvc_completion_list, &vs->vs_completion_list); +	spin_unlock_bh(&vs->vs_completion_lock); + +	vhost_work_queue(&vs->dev, &vs->vs_completion_work); +} + +static int tcm_vhost_queue_data_in(struct se_cmd *se_cmd) +{ +	struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd, +				struct tcm_vhost_cmd, tvc_se_cmd); +	vhost_scsi_complete_cmd(tv_cmd); +	return 0; +} + +static int tcm_vhost_queue_status(struct se_cmd *se_cmd) +{ +	struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd, +				struct tcm_vhost_cmd, tvc_se_cmd); +	vhost_scsi_complete_cmd(tv_cmd); +	return 0; +} + +static int tcm_vhost_queue_tm_rsp(struct se_cmd *se_cmd) +{ +	return 0; +} + +static u16 tcm_vhost_set_fabric_sense_len(struct se_cmd *se_cmd, +	u32 sense_length) +{ +	return 0; +} + +static u16 tcm_vhost_get_fabric_sense_len(void) +{ +	return 0; +} + +static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd) +{ +	struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; + +	/* TODO locking against target/backend threads? */ +	transport_generic_free_cmd(se_cmd, 1); + +	if (tv_cmd->tvc_sgl_count) { +		u32 i; +		for (i = 0; i < tv_cmd->tvc_sgl_count; i++) +			put_page(sg_page(&tv_cmd->tvc_sgl[i])); + +		kfree(tv_cmd->tvc_sgl); +	} + +	kfree(tv_cmd); +} + +/* Dequeue a command from the completion list */ +static struct tcm_vhost_cmd *vhost_scsi_get_cmd_from_completion( +	struct vhost_scsi *vs) +{ +	struct tcm_vhost_cmd *tv_cmd = NULL; + +	spin_lock_bh(&vs->vs_completion_lock); +	if (list_empty(&vs->vs_completion_list)) { +		spin_unlock_bh(&vs->vs_completion_lock); +		return NULL; +	} + +	list_for_each_entry(tv_cmd, &vs->vs_completion_list, +			    tvc_completion_list) { +		list_del(&tv_cmd->tvc_completion_list); +		break; +	} +	spin_unlock_bh(&vs->vs_completion_lock); +	return tv_cmd; +} + +/* Fill in status and signal that we are done processing this command + * + * This is scheduled in the vhost work queue so we are called with the owner + * process mm and can access the vring. + */ +static void vhost_scsi_complete_cmd_work(struct vhost_work *work) +{ +	struct vhost_scsi *vs = container_of(work, struct vhost_scsi, +					vs_completion_work); +	struct tcm_vhost_cmd *tv_cmd; + +	while ((tv_cmd = vhost_scsi_get_cmd_from_completion(vs))) { +		struct virtio_scsi_cmd_resp v_rsp; +		struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; +		int ret; + +		pr_debug("%s tv_cmd %p resid %u status %#02x\n", __func__, +			tv_cmd, se_cmd->residual_count, se_cmd->scsi_status); + +		memset(&v_rsp, 0, sizeof(v_rsp)); +		v_rsp.resid = se_cmd->residual_count; +		/* TODO is status_qualifier field needed? */ +		v_rsp.status = se_cmd->scsi_status; +		v_rsp.sense_len = se_cmd->scsi_sense_length; +		memcpy(v_rsp.sense, tv_cmd->tvc_sense_buf, +		       v_rsp.sense_len); +		ret = copy_to_user(tv_cmd->tvc_resp, &v_rsp, sizeof(v_rsp)); +		if (likely(ret == 0)) +			vhost_add_used(&vs->vqs[2], tv_cmd->tvc_vq_desc, 0); +		else +			pr_err("Faulted on virtio_scsi_cmd_resp\n"); + +		vhost_scsi_free_cmd(tv_cmd); +	} + +	vhost_signal(&vs->dev, &vs->vqs[2]); +} + +static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd( +	struct tcm_vhost_tpg *tv_tpg, +	struct virtio_scsi_cmd_req *v_req, +	u32 exp_data_len, +	int data_direction) +{ +	struct tcm_vhost_cmd *tv_cmd; +	struct tcm_vhost_nexus *tv_nexus; +	struct se_portal_group *se_tpg = &tv_tpg->se_tpg; +	struct se_session *se_sess; +	struct se_cmd *se_cmd; +	int sam_task_attr; + +	tv_nexus = tv_tpg->tpg_nexus; +	if (!tv_nexus) { +		pr_err("Unable to locate active struct tcm_vhost_nexus\n"); +		return ERR_PTR(-EIO); +	} +	se_sess = tv_nexus->tvn_se_sess; + +	tv_cmd = kzalloc(sizeof(struct tcm_vhost_cmd), GFP_ATOMIC); +	if (!tv_cmd) { +		pr_err("Unable to allocate struct tcm_vhost_cmd\n"); +		return ERR_PTR(-ENOMEM); +	} +	INIT_LIST_HEAD(&tv_cmd->tvc_completion_list); +	tv_cmd->tvc_tag = v_req->tag; + +	se_cmd = &tv_cmd->tvc_se_cmd; +	/* +	 * Locate the SAM Task Attr from virtio_scsi_cmd_req +	 */ +	sam_task_attr = v_req->task_attr; +	/* +	 * Initialize struct se_cmd descriptor from TCM infrastructure +	 */ +	transport_init_se_cmd(se_cmd, se_tpg->se_tpg_tfo, se_sess, exp_data_len, +				data_direction, sam_task_attr, +				&tv_cmd->tvc_sense_buf[0]); + +#if 0	/* FIXME: vhost_scsi_allocate_cmd() BIDI operation */ +	if (bidi) +		se_cmd->se_cmd_flags |= SCF_BIDI; +#endif +	return tv_cmd; +} + +/* + * Map a user memory range into a scatterlist + * + * Returns the number of scatterlist entries used or -errno on error. + */ +static int vhost_scsi_map_to_sgl(struct scatterlist *sgl, +	unsigned int sgl_count, void __user *ptr, size_t len, int write) +{ +	struct scatterlist *sg = sgl; +	unsigned int npages = 0; +	int ret; + +	while (len > 0) { +		struct page *page; +		unsigned int offset = (uintptr_t)ptr & ~PAGE_MASK; +		unsigned int nbytes = min_t(unsigned int, +				PAGE_SIZE - offset, len); + +		if (npages == sgl_count) { +			ret = -ENOBUFS; +			goto err; +		} + +		ret = get_user_pages_fast((unsigned long)ptr, 1, write, &page); +		BUG_ON(ret == 0); /* we should either get our page or fail */ +		if (ret < 0) +			goto err; + +		sg_set_page(sg, page, nbytes, offset); +		ptr += nbytes; +		len -= nbytes; +		sg++; +		npages++; +	} +	return npages; + +err: +	/* Put pages that we hold */ +	for (sg = sgl; sg != &sgl[npages]; sg++) +		put_page(sg_page(sg)); +	return ret; +} + +static int vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd, +	struct iovec *iov, unsigned int niov, int write) +{ +	int ret; +	unsigned int i; +	u32 sgl_count; +	struct scatterlist *sg; + +	/* +	 * Find out how long sglist needs to be +	 */ +	sgl_count = 0; +	for (i = 0; i < niov; i++) { +		sgl_count += (((uintptr_t)iov[i].iov_base + iov[i].iov_len + +				PAGE_SIZE - 1) >> PAGE_SHIFT) - +				((uintptr_t)iov[i].iov_base >> PAGE_SHIFT); +	} +	/* TODO overflow checking */ + +	sg = kmalloc(sizeof(tv_cmd->tvc_sgl[0]) * sgl_count, GFP_ATOMIC); +	if (!sg) +		return -ENOMEM; +	pr_debug("%s sg %p sgl_count %u is_err %d\n", __func__, +	       sg, sgl_count, !sg); +	sg_init_table(sg, sgl_count); + +	tv_cmd->tvc_sgl = sg; +	tv_cmd->tvc_sgl_count = sgl_count; + +	pr_debug("Mapping %u iovecs for %u pages\n", niov, sgl_count); +	for (i = 0; i < niov; i++) { +		ret = vhost_scsi_map_to_sgl(sg, sgl_count, iov[i].iov_base, +					iov[i].iov_len, write); +		if (ret < 0) { +			for (i = 0; i < tv_cmd->tvc_sgl_count; i++) +				put_page(sg_page(&tv_cmd->tvc_sgl[i])); +			kfree(tv_cmd->tvc_sgl); +			tv_cmd->tvc_sgl = NULL; +			tv_cmd->tvc_sgl_count = 0; +			return ret; +		} + +		sg += ret; +		sgl_count -= ret; +	} +	return 0; +} + +static void tcm_vhost_submission_work(struct work_struct *work) +{ +	struct tcm_vhost_cmd *tv_cmd = +		container_of(work, struct tcm_vhost_cmd, work); +	struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; +	struct scatterlist *sg_ptr, *sg_bidi_ptr = NULL; +	int rc, sg_no_bidi = 0; +	/* +	 * Locate the struct se_lun pointer based on v_req->lun, and +	 * attach it to struct se_cmd +	 */ +	rc = transport_lookup_cmd_lun(&tv_cmd->tvc_se_cmd, tv_cmd->tvc_lun); +	if (rc < 0) { +		pr_err("Failed to look up lun: %d\n", tv_cmd->tvc_lun); +		transport_send_check_condition_and_sense(&tv_cmd->tvc_se_cmd, +			tv_cmd->tvc_se_cmd.scsi_sense_reason, 0); +		transport_generic_free_cmd(se_cmd, 0); +		return; +	} + +	rc = target_setup_cmd_from_cdb(se_cmd, tv_cmd->tvc_cdb); +	if (rc == -ENOMEM) { +		transport_send_check_condition_and_sense(se_cmd, +				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); +		transport_generic_free_cmd(se_cmd, 0); +		return; +	} else if (rc < 0) { +		if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) +			tcm_vhost_queue_status(se_cmd); +		else +			transport_send_check_condition_and_sense(se_cmd, +					se_cmd->scsi_sense_reason, 0); +		transport_generic_free_cmd(se_cmd, 0); +		return; +	} + +	if (tv_cmd->tvc_sgl_count) { +		sg_ptr = tv_cmd->tvc_sgl; +		/* +		 * For BIDI commands, pass in the extra READ buffer +		 * to transport_generic_map_mem_to_cmd() below.. +		 */ +/* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */ +#if 0 +		if (se_cmd->se_cmd_flags & SCF_BIDI) { +			sg_bidi_ptr = NULL; +			sg_no_bidi = 0; +		} +#endif +	} else { +		sg_ptr = NULL; +	} + +	rc = transport_generic_map_mem_to_cmd(se_cmd, sg_ptr, +				tv_cmd->tvc_sgl_count, sg_bidi_ptr, +				sg_no_bidi); +	if (rc < 0) { +		transport_send_check_condition_and_sense(se_cmd, +				se_cmd->scsi_sense_reason, 0); +		transport_generic_free_cmd(se_cmd, 0); +		return; +	} +	transport_handle_cdb_direct(se_cmd); +} + +static void vhost_scsi_handle_vq(struct vhost_scsi *vs) +{ +	struct vhost_virtqueue *vq = &vs->vqs[2]; +	struct virtio_scsi_cmd_req v_req; +	struct tcm_vhost_tpg *tv_tpg; +	struct tcm_vhost_cmd *tv_cmd; +	u32 exp_data_len, data_first, data_num, data_direction; +	unsigned out, in, i; +	int head, ret; + +	/* Must use ioctl VHOST_SCSI_SET_ENDPOINT */ +	tv_tpg = vs->vs_tpg; +	if (unlikely(!tv_tpg)) { +		pr_err("%s endpoint not set\n", __func__); +		return; +	} + +	mutex_lock(&vq->mutex); +	vhost_disable_notify(&vs->dev, vq); + +	for (;;) { +		head = vhost_get_vq_desc(&vs->dev, vq, vq->iov, +					ARRAY_SIZE(vq->iov), &out, &in, +					NULL, NULL); +		pr_debug("vhost_get_vq_desc: head: %d, out: %u in: %u\n", +					head, out, in); +		/* On error, stop handling until the next kick. */ +		if (unlikely(head < 0)) +			break; +		/* Nothing new?  Wait for eventfd to tell us they refilled. */ +		if (head == vq->num) { +			if (unlikely(vhost_enable_notify(&vs->dev, vq))) { +				vhost_disable_notify(&vs->dev, vq); +				continue; +			} +			break; +		} + +/* FIXME: BIDI operation */ +		if (out == 1 && in == 1) { +			data_direction = DMA_NONE; +			data_first = 0; +			data_num = 0; +		} else if (out == 1 && in > 1) { +			data_direction = DMA_FROM_DEVICE; +			data_first = out + 1; +			data_num = in - 1; +		} else if (out > 1 && in == 1) { +			data_direction = DMA_TO_DEVICE; +			data_first = 1; +			data_num = out - 1; +		} else { +			vq_err(vq, "Invalid buffer layout out: %u in: %u\n", +					out, in); +			break; +		} + +		/* +		 * Check for a sane resp buffer so we can report errors to +		 * the guest. +		 */ +		if (unlikely(vq->iov[out].iov_len != +					sizeof(struct virtio_scsi_cmd_resp))) { +			vq_err(vq, "Expecting virtio_scsi_cmd_resp, got %zu" +				" bytes\n", vq->iov[out].iov_len); +			break; +		} + +		if (unlikely(vq->iov[0].iov_len != sizeof(v_req))) { +			vq_err(vq, "Expecting virtio_scsi_cmd_req, got %zu" +				" bytes\n", vq->iov[0].iov_len); +			break; +		} +		pr_debug("Calling __copy_from_user: vq->iov[0].iov_base: %p," +			" len: %zu\n", vq->iov[0].iov_base, sizeof(v_req)); +		ret = __copy_from_user(&v_req, vq->iov[0].iov_base, +				sizeof(v_req)); +		if (unlikely(ret)) { +			vq_err(vq, "Faulted on virtio_scsi_cmd_req\n"); +			break; +		} + +		exp_data_len = 0; +		for (i = 0; i < data_num; i++) +			exp_data_len += vq->iov[data_first + i].iov_len; + +		tv_cmd = vhost_scsi_allocate_cmd(tv_tpg, &v_req, +					exp_data_len, data_direction); +		if (IS_ERR(tv_cmd)) { +			vq_err(vq, "vhost_scsi_allocate_cmd failed %ld\n", +					PTR_ERR(tv_cmd)); +			break; +		} +		pr_debug("Allocated tv_cmd: %p exp_data_len: %d, data_direction" +			": %d\n", tv_cmd, exp_data_len, data_direction); + +		tv_cmd->tvc_vhost = vs; + +		if (unlikely(vq->iov[out].iov_len != +				sizeof(struct virtio_scsi_cmd_resp))) { +			vq_err(vq, "Expecting virtio_scsi_cmd_resp, got %zu" +				" bytes, out: %d, in: %d\n", +				vq->iov[out].iov_len, out, in); +			break; +		} + +		tv_cmd->tvc_resp = vq->iov[out].iov_base; + +		/* +		 * Copy in the recieved CDB descriptor into tv_cmd->tvc_cdb +		 * that will be used by tcm_vhost_new_cmd_map() and down into +		 * target_setup_cmd_from_cdb() +		 */ +		memcpy(tv_cmd->tvc_cdb, v_req.cdb, TCM_VHOST_MAX_CDB_SIZE); +		/* +		 * Check that the recieved CDB size does not exceeded our +		 * hardcoded max for tcm_vhost +		 */ +		/* TODO what if cdb was too small for varlen cdb header? */ +		if (unlikely(scsi_command_size(tv_cmd->tvc_cdb) > +					TCM_VHOST_MAX_CDB_SIZE)) { +			vq_err(vq, "Received SCSI CDB with command_size: %d that" +				" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n", +				scsi_command_size(tv_cmd->tvc_cdb), +				TCM_VHOST_MAX_CDB_SIZE); +			break; /* TODO */ +		} +		tv_cmd->tvc_lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF; + +		pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n", +			tv_cmd->tvc_cdb[0], tv_cmd->tvc_lun); + +		if (data_direction != DMA_NONE) { +			ret = vhost_scsi_map_iov_to_sgl(tv_cmd, +					&vq->iov[data_first], data_num, +					data_direction == DMA_TO_DEVICE); +			if (unlikely(ret)) { +				vq_err(vq, "Failed to map iov to sgl\n"); +				break; /* TODO */ +			} +		} + +		/* +		 * Save the descriptor from vhost_get_vq_desc() to be used to +		 * complete the virtio-scsi request in TCM callback context via +		 * tcm_vhost_queue_data_in() and tcm_vhost_queue_status() +		 */ +		tv_cmd->tvc_vq_desc = head; +		/* +		 * Dispatch tv_cmd descriptor for cmwq execution in process +		 * context provided by tcm_vhost_workqueue.  This also ensures +		 * tv_cmd is executed on the same kworker CPU as this vhost +		 * thread to gain positive L2 cache locality effects.. +		 */ +		INIT_WORK(&tv_cmd->work, tcm_vhost_submission_work); +		queue_work(tcm_vhost_workqueue, &tv_cmd->work); +	} + +	mutex_unlock(&vq->mutex); +} + +static void vhost_scsi_ctl_handle_kick(struct vhost_work *work) +{ +	pr_debug("%s: The handling func for control queue.\n", __func__); +} + +static void vhost_scsi_evt_handle_kick(struct vhost_work *work) +{ +	pr_debug("%s: The handling func for event queue.\n", __func__); +} + +static void vhost_scsi_handle_kick(struct vhost_work *work) +{ +	struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue, +						poll.work); +	struct vhost_scsi *vs = container_of(vq->dev, struct vhost_scsi, dev); + +	vhost_scsi_handle_vq(vs); +} + +/* + * Called from vhost_scsi_ioctl() context to walk the list of available + * tcm_vhost_tpg with an active struct tcm_vhost_nexus + */ +static int vhost_scsi_set_endpoint( +	struct vhost_scsi *vs, +	struct vhost_scsi_target *t) +{ +	struct tcm_vhost_tport *tv_tport; +	struct tcm_vhost_tpg *tv_tpg; +	int index; + +	mutex_lock(&vs->dev.mutex); +	/* Verify that ring has been setup correctly. */ +	for (index = 0; index < vs->dev.nvqs; ++index) { +		/* Verify that ring has been setup correctly. */ +		if (!vhost_vq_access_ok(&vs->vqs[index])) { +			mutex_unlock(&vs->dev.mutex); +			return -EFAULT; +		} +	} +	mutex_unlock(&vs->dev.mutex); + +	mutex_lock(&tcm_vhost_mutex); +	list_for_each_entry(tv_tpg, &tcm_vhost_list, tv_tpg_list) { +		mutex_lock(&tv_tpg->tv_tpg_mutex); +		if (!tv_tpg->tpg_nexus) { +			mutex_unlock(&tv_tpg->tv_tpg_mutex); +			continue; +		} +		if (tv_tpg->tv_tpg_vhost_count != 0) { +			mutex_unlock(&tv_tpg->tv_tpg_mutex); +			continue; +		} +		tv_tport = tv_tpg->tport; + +		if (!strcmp(tv_tport->tport_name, t->vhost_wwpn) && +		    (tv_tpg->tport_tpgt == t->vhost_tpgt)) { +			tv_tpg->tv_tpg_vhost_count++; +			mutex_unlock(&tv_tpg->tv_tpg_mutex); +			mutex_unlock(&tcm_vhost_mutex); + +			mutex_lock(&vs->dev.mutex); +			if (vs->vs_tpg) { +				mutex_unlock(&vs->dev.mutex); +				mutex_lock(&tv_tpg->tv_tpg_mutex); +				tv_tpg->tv_tpg_vhost_count--; +				mutex_unlock(&tv_tpg->tv_tpg_mutex); +				return -EEXIST; +			} + +			vs->vs_tpg = tv_tpg; +			smp_mb__after_atomic_inc(); +			mutex_unlock(&vs->dev.mutex); +			return 0; +		} +		mutex_unlock(&tv_tpg->tv_tpg_mutex); +	} +	mutex_unlock(&tcm_vhost_mutex); +	return -EINVAL; +} + +static int vhost_scsi_clear_endpoint( +	struct vhost_scsi *vs, +	struct vhost_scsi_target *t) +{ +	struct tcm_vhost_tport *tv_tport; +	struct tcm_vhost_tpg *tv_tpg; +	int index, ret; + +	mutex_lock(&vs->dev.mutex); +	/* Verify that ring has been setup correctly. */ +	for (index = 0; index < vs->dev.nvqs; ++index) { +		if (!vhost_vq_access_ok(&vs->vqs[index])) { +			ret = -EFAULT; +			goto err; +		} +	} + +	if (!vs->vs_tpg) { +		ret = -ENODEV; +		goto err; +	} +	tv_tpg = vs->vs_tpg; +	tv_tport = tv_tpg->tport; + +	if (strcmp(tv_tport->tport_name, t->vhost_wwpn) || +	    (tv_tpg->tport_tpgt != t->vhost_tpgt)) { +		pr_warn("tv_tport->tport_name: %s, tv_tpg->tport_tpgt: %hu" +			" does not match t->vhost_wwpn: %s, t->vhost_tpgt: %hu\n", +			tv_tport->tport_name, tv_tpg->tport_tpgt, +			t->vhost_wwpn, t->vhost_tpgt); +		ret = -EINVAL; +		goto err; +	} +	tv_tpg->tv_tpg_vhost_count--; +	vs->vs_tpg = NULL; +	mutex_unlock(&vs->dev.mutex); + +	return 0; + +err: +	mutex_unlock(&vs->dev.mutex); +	return ret; +} + +static int vhost_scsi_open(struct inode *inode, struct file *f) +{ +	struct vhost_scsi *s; +	int r; + +	s = kzalloc(sizeof(*s), GFP_KERNEL); +	if (!s) +		return -ENOMEM; + +	vhost_work_init(&s->vs_completion_work, vhost_scsi_complete_cmd_work); +	INIT_LIST_HEAD(&s->vs_completion_list); +	spin_lock_init(&s->vs_completion_lock); + +	s->vqs[VHOST_SCSI_VQ_CTL].handle_kick = vhost_scsi_ctl_handle_kick; +	s->vqs[VHOST_SCSI_VQ_EVT].handle_kick = vhost_scsi_evt_handle_kick; +	s->vqs[VHOST_SCSI_VQ_IO].handle_kick = vhost_scsi_handle_kick; +	r = vhost_dev_init(&s->dev, s->vqs, 3); +	if (r < 0) { +		kfree(s); +		return r; +	} + +	f->private_data = s; +	return 0; +} + +static int vhost_scsi_release(struct inode *inode, struct file *f) +{ +	struct vhost_scsi *s = f->private_data; + +	if (s->vs_tpg && s->vs_tpg->tport) { +		struct vhost_scsi_target backend; + +		memcpy(backend.vhost_wwpn, s->vs_tpg->tport->tport_name, +				sizeof(backend.vhost_wwpn)); +		backend.vhost_tpgt = s->vs_tpg->tport_tpgt; +		vhost_scsi_clear_endpoint(s, &backend); +	} + +	vhost_dev_cleanup(&s->dev, false); +	kfree(s); +	return 0; +} + +static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index) +{ +	vhost_poll_flush(&vs->dev.vqs[index].poll); +} + +static void vhost_scsi_flush(struct vhost_scsi *vs) +{ +	vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_CTL); +	vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_EVT); +	vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_IO); +} + +static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) +{ +	if (features & ~VHOST_FEATURES) +		return -EOPNOTSUPP; + +	mutex_lock(&vs->dev.mutex); +	if ((features & (1 << VHOST_F_LOG_ALL)) && +	    !vhost_log_access_ok(&vs->dev)) { +		mutex_unlock(&vs->dev.mutex); +		return -EFAULT; +	} +	vs->dev.acked_features = features; +	smp_wmb(); +	vhost_scsi_flush(vs); +	mutex_unlock(&vs->dev.mutex); +	return 0; +} + +static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, +				unsigned long arg) +{ +	struct vhost_scsi *vs = f->private_data; +	struct vhost_scsi_target backend; +	void __user *argp = (void __user *)arg; +	u64 __user *featurep = argp; +	u64 features; +	int r, abi_version = VHOST_SCSI_ABI_VERSION; + +	switch (ioctl) { +	case VHOST_SCSI_SET_ENDPOINT: +		if (copy_from_user(&backend, argp, sizeof backend)) +			return -EFAULT; +		if (backend.reserved != 0) +			return -EOPNOTSUPP; + +		return vhost_scsi_set_endpoint(vs, &backend); +	case VHOST_SCSI_CLEAR_ENDPOINT: +		if (copy_from_user(&backend, argp, sizeof backend)) +			return -EFAULT; +		if (backend.reserved != 0) +			return -EOPNOTSUPP; + +		return vhost_scsi_clear_endpoint(vs, &backend); +	case VHOST_SCSI_GET_ABI_VERSION: +		if (copy_to_user(argp, &abi_version, sizeof abi_version)) +			return -EFAULT; +		return 0; +	case VHOST_GET_FEATURES: +		features = VHOST_FEATURES; +		if (copy_to_user(featurep, &features, sizeof features)) +			return -EFAULT; +		return 0; +	case VHOST_SET_FEATURES: +		if (copy_from_user(&features, featurep, sizeof features)) +			return -EFAULT; +		return vhost_scsi_set_features(vs, features); +	default: +		mutex_lock(&vs->dev.mutex); +		r = vhost_dev_ioctl(&vs->dev, ioctl, arg); +		mutex_unlock(&vs->dev.mutex); +		return r; +	} +} + +#ifdef CONFIG_COMPAT +static long vhost_scsi_compat_ioctl(struct file *f, unsigned int ioctl, +				unsigned long arg) +{ +	return vhost_scsi_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); +} +#endif + +static const struct file_operations vhost_scsi_fops = { +	.owner          = THIS_MODULE, +	.release        = vhost_scsi_release, +	.unlocked_ioctl = vhost_scsi_ioctl, +#ifdef CONFIG_COMPAT +	.compat_ioctl	= vhost_scsi_compat_ioctl, +#endif +	.open           = vhost_scsi_open, +	.llseek		= noop_llseek, +}; + +static struct miscdevice vhost_scsi_misc = { +	MISC_DYNAMIC_MINOR, +	"vhost-scsi", +	&vhost_scsi_fops, +}; + +static int __init vhost_scsi_register(void) +{ +	return misc_register(&vhost_scsi_misc); +} + +static int vhost_scsi_deregister(void) +{ +	return misc_deregister(&vhost_scsi_misc); +} + +static char *tcm_vhost_dump_proto_id(struct tcm_vhost_tport *tport) +{ +	switch (tport->tport_proto_id) { +	case SCSI_PROTOCOL_SAS: +		return "SAS"; +	case SCSI_PROTOCOL_FCP: +		return "FCP"; +	case SCSI_PROTOCOL_ISCSI: +		return "iSCSI"; +	default: +		break; +	} + +	return "Unknown"; +} + +static int tcm_vhost_port_link(struct se_portal_group *se_tpg, +	struct se_lun *lun) +{ +	struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); + +	mutex_lock(&tv_tpg->tv_tpg_mutex); +	tv_tpg->tv_tpg_port_count++; +	mutex_unlock(&tv_tpg->tv_tpg_mutex); + +	return 0; +} + +static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg, +	struct se_lun *se_lun) +{ +	struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); + +	mutex_lock(&tv_tpg->tv_tpg_mutex); +	tv_tpg->tv_tpg_port_count--; +	mutex_unlock(&tv_tpg->tv_tpg_mutex); +} + +static struct se_node_acl *tcm_vhost_make_nodeacl( +	struct se_portal_group *se_tpg, +	struct config_group *group, +	const char *name) +{ +	struct se_node_acl *se_nacl, *se_nacl_new; +	struct tcm_vhost_nacl *nacl; +	u64 wwpn = 0; +	u32 nexus_depth; + +	/* tcm_vhost_parse_wwn(name, &wwpn, 1) < 0) +		return ERR_PTR(-EINVAL); */ +	se_nacl_new = tcm_vhost_alloc_fabric_acl(se_tpg); +	if (!se_nacl_new) +		return ERR_PTR(-ENOMEM); + +	nexus_depth = 1; +	/* +	 * se_nacl_new may be released by core_tpg_add_initiator_node_acl() +	 * when converting a NodeACL from demo mode -> explict +	 */ +	se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new, +				name, nexus_depth); +	if (IS_ERR(se_nacl)) { +		tcm_vhost_release_fabric_acl(se_tpg, se_nacl_new); +		return se_nacl; +	} +	/* +	 * Locate our struct tcm_vhost_nacl and set the FC Nport WWPN +	 */ +	nacl = container_of(se_nacl, struct tcm_vhost_nacl, se_node_acl); +	nacl->iport_wwpn = wwpn; + +	return se_nacl; +} + +static void tcm_vhost_drop_nodeacl(struct se_node_acl *se_acl) +{ +	struct tcm_vhost_nacl *nacl = container_of(se_acl, +				struct tcm_vhost_nacl, se_node_acl); +	core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1); +	kfree(nacl); +} + +static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg, +	const char *name) +{ +	struct se_portal_group *se_tpg; +	struct tcm_vhost_nexus *tv_nexus; + +	mutex_lock(&tv_tpg->tv_tpg_mutex); +	if (tv_tpg->tpg_nexus) { +		mutex_unlock(&tv_tpg->tv_tpg_mutex); +		pr_debug("tv_tpg->tpg_nexus already exists\n"); +		return -EEXIST; +	} +	se_tpg = &tv_tpg->se_tpg; + +	tv_nexus = kzalloc(sizeof(struct tcm_vhost_nexus), GFP_KERNEL); +	if (!tv_nexus) { +		mutex_unlock(&tv_tpg->tv_tpg_mutex); +		pr_err("Unable to allocate struct tcm_vhost_nexus\n"); +		return -ENOMEM; +	} +	/* +	 *  Initialize the struct se_session pointer +	 */ +	tv_nexus->tvn_se_sess = transport_init_session(); +	if (IS_ERR(tv_nexus->tvn_se_sess)) { +		mutex_unlock(&tv_tpg->tv_tpg_mutex); +		kfree(tv_nexus); +		return -ENOMEM; +	} +	/* +	 * Since we are running in 'demo mode' this call with generate a +	 * struct se_node_acl for the tcm_vhost struct se_portal_group with +	 * the SCSI Initiator port name of the passed configfs group 'name'. +	 */ +	tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl( +				se_tpg, (unsigned char *)name); +	if (!tv_nexus->tvn_se_sess->se_node_acl) { +		mutex_unlock(&tv_tpg->tv_tpg_mutex); +		pr_debug("core_tpg_check_initiator_node_acl() failed" +				" for %s\n", name); +		transport_free_session(tv_nexus->tvn_se_sess); +		kfree(tv_nexus); +		return -ENOMEM; +	} +	/* +	 * Now register the TCM vhost virtual I_T Nexus as active with the +	 * call to __transport_register_session() +	 */ +	__transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl, +			tv_nexus->tvn_se_sess, tv_nexus); +	tv_tpg->tpg_nexus = tv_nexus; + +	mutex_unlock(&tv_tpg->tv_tpg_mutex); +	return 0; +} + +static int tcm_vhost_drop_nexus(struct tcm_vhost_tpg *tpg) +{ +	struct se_session *se_sess; +	struct tcm_vhost_nexus *tv_nexus; + +	mutex_lock(&tpg->tv_tpg_mutex); +	tv_nexus = tpg->tpg_nexus; +	if (!tv_nexus) { +		mutex_unlock(&tpg->tv_tpg_mutex); +		return -ENODEV; +	} + +	se_sess = tv_nexus->tvn_se_sess; +	if (!se_sess) { +		mutex_unlock(&tpg->tv_tpg_mutex); +		return -ENODEV; +	} + +	if (tpg->tv_tpg_port_count != 0) { +		mutex_unlock(&tpg->tv_tpg_mutex); +		pr_err("Unable to remove TCM_vhost I_T Nexus with" +			" active TPG port count: %d\n", +			tpg->tv_tpg_port_count); +		return -EBUSY; +	} + +	if (tpg->tv_tpg_vhost_count != 0) { +		mutex_unlock(&tpg->tv_tpg_mutex); +		pr_err("Unable to remove TCM_vhost I_T Nexus with" +			" active TPG vhost count: %d\n", +			tpg->tv_tpg_vhost_count); +		return -EBUSY; +	} + +	pr_debug("TCM_vhost_ConfigFS: Removing I_T Nexus to emulated" +		" %s Initiator Port: %s\n", tcm_vhost_dump_proto_id(tpg->tport), +		tv_nexus->tvn_se_sess->se_node_acl->initiatorname); +	/* +	 * Release the SCSI I_T Nexus to the emulated vhost Target Port +	 */ +	transport_deregister_session(tv_nexus->tvn_se_sess); +	tpg->tpg_nexus = NULL; +	mutex_unlock(&tpg->tv_tpg_mutex); + +	kfree(tv_nexus); +	return 0; +} + +static ssize_t tcm_vhost_tpg_show_nexus(struct se_portal_group *se_tpg, +	char *page) +{ +	struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); +	struct tcm_vhost_nexus *tv_nexus; +	ssize_t ret; + +	mutex_lock(&tv_tpg->tv_tpg_mutex); +	tv_nexus = tv_tpg->tpg_nexus; +	if (!tv_nexus) { +		mutex_unlock(&tv_tpg->tv_tpg_mutex); +		return -ENODEV; +	} +	ret = snprintf(page, PAGE_SIZE, "%s\n", +			tv_nexus->tvn_se_sess->se_node_acl->initiatorname); +	mutex_unlock(&tv_tpg->tv_tpg_mutex); + +	return ret; +} + +static ssize_t tcm_vhost_tpg_store_nexus(struct se_portal_group *se_tpg, +	const char *page, +	size_t count) +{ +	struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); +	struct tcm_vhost_tport *tport_wwn = tv_tpg->tport; +	unsigned char i_port[TCM_VHOST_NAMELEN], *ptr, *port_ptr; +	int ret; +	/* +	 * Shutdown the active I_T nexus if 'NULL' is passed.. +	 */ +	if (!strncmp(page, "NULL", 4)) { +		ret = tcm_vhost_drop_nexus(tv_tpg); +		return (!ret) ? count : ret; +	} +	/* +	 * Otherwise make sure the passed virtual Initiator port WWN matches +	 * the fabric protocol_id set in tcm_vhost_make_tport(), and call +	 * tcm_vhost_make_nexus(). +	 */ +	if (strlen(page) >= TCM_VHOST_NAMELEN) { +		pr_err("Emulated NAA Sas Address: %s, exceeds" +				" max: %d\n", page, TCM_VHOST_NAMELEN); +		return -EINVAL; +	} +	snprintf(&i_port[0], TCM_VHOST_NAMELEN, "%s", page); + +	ptr = strstr(i_port, "naa."); +	if (ptr) { +		if (tport_wwn->tport_proto_id != SCSI_PROTOCOL_SAS) { +			pr_err("Passed SAS Initiator Port %s does not" +				" match target port protoid: %s\n", i_port, +				tcm_vhost_dump_proto_id(tport_wwn)); +			return -EINVAL; +		} +		port_ptr = &i_port[0]; +		goto check_newline; +	} +	ptr = strstr(i_port, "fc."); +	if (ptr) { +		if (tport_wwn->tport_proto_id != SCSI_PROTOCOL_FCP) { +			pr_err("Passed FCP Initiator Port %s does not" +				" match target port protoid: %s\n", i_port, +				tcm_vhost_dump_proto_id(tport_wwn)); +			return -EINVAL; +		} +		port_ptr = &i_port[3]; /* Skip over "fc." */ +		goto check_newline; +	} +	ptr = strstr(i_port, "iqn."); +	if (ptr) { +		if (tport_wwn->tport_proto_id != SCSI_PROTOCOL_ISCSI) { +			pr_err("Passed iSCSI Initiator Port %s does not" +				" match target port protoid: %s\n", i_port, +				tcm_vhost_dump_proto_id(tport_wwn)); +			return -EINVAL; +		} +		port_ptr = &i_port[0]; +		goto check_newline; +	} +	pr_err("Unable to locate prefix for emulated Initiator Port:" +			" %s\n", i_port); +	return -EINVAL; +	/* +	 * Clear any trailing newline for the NAA WWN +	 */ +check_newline: +	if (i_port[strlen(i_port)-1] == '\n') +		i_port[strlen(i_port)-1] = '\0'; + +	ret = tcm_vhost_make_nexus(tv_tpg, port_ptr); +	if (ret < 0) +		return ret; + +	return count; +} + +TF_TPG_BASE_ATTR(tcm_vhost, nexus, S_IRUGO | S_IWUSR); + +static struct configfs_attribute *tcm_vhost_tpg_attrs[] = { +	&tcm_vhost_tpg_nexus.attr, +	NULL, +}; + +static struct se_portal_group *tcm_vhost_make_tpg(struct se_wwn *wwn, +	struct config_group *group, +	const char *name) +{ +	struct tcm_vhost_tport *tport = container_of(wwn, +			struct tcm_vhost_tport, tport_wwn); + +	struct tcm_vhost_tpg *tpg; +	unsigned long tpgt; +	int ret; + +	if (strstr(name, "tpgt_") != name) +		return ERR_PTR(-EINVAL); +	if (kstrtoul(name + 5, 10, &tpgt) || tpgt > UINT_MAX) +		return ERR_PTR(-EINVAL); + +	tpg = kzalloc(sizeof(struct tcm_vhost_tpg), GFP_KERNEL); +	if (!tpg) { +		pr_err("Unable to allocate struct tcm_vhost_tpg"); +		return ERR_PTR(-ENOMEM); +	} +	mutex_init(&tpg->tv_tpg_mutex); +	INIT_LIST_HEAD(&tpg->tv_tpg_list); +	tpg->tport = tport; +	tpg->tport_tpgt = tpgt; + +	ret = core_tpg_register(&tcm_vhost_fabric_configfs->tf_ops, wwn, +				&tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); +	if (ret < 0) { +		kfree(tpg); +		return NULL; +	} +	mutex_lock(&tcm_vhost_mutex); +	list_add_tail(&tpg->tv_tpg_list, &tcm_vhost_list); +	mutex_unlock(&tcm_vhost_mutex); + +	return &tpg->se_tpg; +} + +static void tcm_vhost_drop_tpg(struct se_portal_group *se_tpg) +{ +	struct tcm_vhost_tpg *tpg = container_of(se_tpg, +				struct tcm_vhost_tpg, se_tpg); + +	mutex_lock(&tcm_vhost_mutex); +	list_del(&tpg->tv_tpg_list); +	mutex_unlock(&tcm_vhost_mutex); +	/* +	 * Release the virtual I_T Nexus for this vhost TPG +	 */ +	tcm_vhost_drop_nexus(tpg); +	/* +	 * Deregister the se_tpg from TCM.. +	 */ +	core_tpg_deregister(se_tpg); +	kfree(tpg); +} + +static struct se_wwn *tcm_vhost_make_tport(struct target_fabric_configfs *tf, +	struct config_group *group, +	const char *name) +{ +	struct tcm_vhost_tport *tport; +	char *ptr; +	u64 wwpn = 0; +	int off = 0; + +	/* if (tcm_vhost_parse_wwn(name, &wwpn, 1) < 0) +		return ERR_PTR(-EINVAL); */ + +	tport = kzalloc(sizeof(struct tcm_vhost_tport), GFP_KERNEL); +	if (!tport) { +		pr_err("Unable to allocate struct tcm_vhost_tport"); +		return ERR_PTR(-ENOMEM); +	} +	tport->tport_wwpn = wwpn; +	/* +	 * Determine the emulated Protocol Identifier and Target Port Name +	 * based on the incoming configfs directory name. +	 */ +	ptr = strstr(name, "naa."); +	if (ptr) { +		tport->tport_proto_id = SCSI_PROTOCOL_SAS; +		goto check_len; +	} +	ptr = strstr(name, "fc."); +	if (ptr) { +		tport->tport_proto_id = SCSI_PROTOCOL_FCP; +		off = 3; /* Skip over "fc." */ +		goto check_len; +	} +	ptr = strstr(name, "iqn."); +	if (ptr) { +		tport->tport_proto_id = SCSI_PROTOCOL_ISCSI; +		goto check_len; +	} + +	pr_err("Unable to locate prefix for emulated Target Port:" +			" %s\n", name); +	kfree(tport); +	return ERR_PTR(-EINVAL); + +check_len: +	if (strlen(name) >= TCM_VHOST_NAMELEN) { +		pr_err("Emulated %s Address: %s, exceeds" +			" max: %d\n", name, tcm_vhost_dump_proto_id(tport), +			TCM_VHOST_NAMELEN); +		kfree(tport); +		return ERR_PTR(-EINVAL); +	} +	snprintf(&tport->tport_name[0], TCM_VHOST_NAMELEN, "%s", &name[off]); + +	pr_debug("TCM_VHost_ConfigFS: Allocated emulated Target" +		" %s Address: %s\n", tcm_vhost_dump_proto_id(tport), name); + +	return &tport->tport_wwn; +} + +static void tcm_vhost_drop_tport(struct se_wwn *wwn) +{ +	struct tcm_vhost_tport *tport = container_of(wwn, +				struct tcm_vhost_tport, tport_wwn); + +	pr_debug("TCM_VHost_ConfigFS: Deallocating emulated Target" +		" %s Address: %s\n", tcm_vhost_dump_proto_id(tport), +		tport->tport_name); + +	kfree(tport); +} + +static ssize_t tcm_vhost_wwn_show_attr_version( +	struct target_fabric_configfs *tf, +	char *page) +{ +	return sprintf(page, "TCM_VHOST fabric module %s on %s/%s" +		"on "UTS_RELEASE"\n", TCM_VHOST_VERSION, utsname()->sysname, +		utsname()->machine); +} + +TF_WWN_ATTR_RO(tcm_vhost, version); + +static struct configfs_attribute *tcm_vhost_wwn_attrs[] = { +	&tcm_vhost_wwn_version.attr, +	NULL, +}; + +static struct target_core_fabric_ops tcm_vhost_ops = { +	.get_fabric_name		= tcm_vhost_get_fabric_name, +	.get_fabric_proto_ident		= tcm_vhost_get_fabric_proto_ident, +	.tpg_get_wwn			= tcm_vhost_get_fabric_wwn, +	.tpg_get_tag			= tcm_vhost_get_tag, +	.tpg_get_default_depth		= tcm_vhost_get_default_depth, +	.tpg_get_pr_transport_id	= tcm_vhost_get_pr_transport_id, +	.tpg_get_pr_transport_id_len	= tcm_vhost_get_pr_transport_id_len, +	.tpg_parse_pr_out_transport_id	= tcm_vhost_parse_pr_out_transport_id, +	.tpg_check_demo_mode		= tcm_vhost_check_true, +	.tpg_check_demo_mode_cache	= tcm_vhost_check_true, +	.tpg_check_demo_mode_write_protect = tcm_vhost_check_false, +	.tpg_check_prod_mode_write_protect = tcm_vhost_check_false, +	.tpg_alloc_fabric_acl		= tcm_vhost_alloc_fabric_acl, +	.tpg_release_fabric_acl		= tcm_vhost_release_fabric_acl, +	.tpg_get_inst_index		= tcm_vhost_tpg_get_inst_index, +	.release_cmd			= tcm_vhost_release_cmd, +	.shutdown_session		= tcm_vhost_shutdown_session, +	.close_session			= tcm_vhost_close_session, +	.sess_get_index			= tcm_vhost_sess_get_index, +	.sess_get_initiator_sid		= NULL, +	.write_pending			= tcm_vhost_write_pending, +	.write_pending_status		= tcm_vhost_write_pending_status, +	.set_default_node_attributes	= tcm_vhost_set_default_node_attrs, +	.get_task_tag			= tcm_vhost_get_task_tag, +	.get_cmd_state			= tcm_vhost_get_cmd_state, +	.queue_data_in			= tcm_vhost_queue_data_in, +	.queue_status			= tcm_vhost_queue_status, +	.queue_tm_rsp			= tcm_vhost_queue_tm_rsp, +	.get_fabric_sense_len		= tcm_vhost_get_fabric_sense_len, +	.set_fabric_sense_len		= tcm_vhost_set_fabric_sense_len, +	/* +	 * Setup callers for generic logic in target_core_fabric_configfs.c +	 */ +	.fabric_make_wwn		= tcm_vhost_make_tport, +	.fabric_drop_wwn		= tcm_vhost_drop_tport, +	.fabric_make_tpg		= tcm_vhost_make_tpg, +	.fabric_drop_tpg		= tcm_vhost_drop_tpg, +	.fabric_post_link		= tcm_vhost_port_link, +	.fabric_pre_unlink		= tcm_vhost_port_unlink, +	.fabric_make_np			= NULL, +	.fabric_drop_np			= NULL, +	.fabric_make_nodeacl		= tcm_vhost_make_nodeacl, +	.fabric_drop_nodeacl		= tcm_vhost_drop_nodeacl, +}; + +static int tcm_vhost_register_configfs(void) +{ +	struct target_fabric_configfs *fabric; +	int ret; + +	pr_debug("TCM_VHOST fabric module %s on %s/%s" +		" on "UTS_RELEASE"\n", TCM_VHOST_VERSION, utsname()->sysname, +		utsname()->machine); +	/* +	 * Register the top level struct config_item_type with TCM core +	 */ +	fabric = target_fabric_configfs_init(THIS_MODULE, "vhost"); +	if (IS_ERR(fabric)) { +		pr_err("target_fabric_configfs_init() failed\n"); +		return PTR_ERR(fabric); +	} +	/* +	 * Setup fabric->tf_ops from our local tcm_vhost_ops +	 */ +	fabric->tf_ops = tcm_vhost_ops; +	/* +	 * Setup default attribute lists for various fabric->tf_cit_tmpl +	 */ +	TF_CIT_TMPL(fabric)->tfc_wwn_cit.ct_attrs = tcm_vhost_wwn_attrs; +	TF_CIT_TMPL(fabric)->tfc_tpg_base_cit.ct_attrs = tcm_vhost_tpg_attrs; +	TF_CIT_TMPL(fabric)->tfc_tpg_attrib_cit.ct_attrs = NULL; +	TF_CIT_TMPL(fabric)->tfc_tpg_param_cit.ct_attrs = NULL; +	TF_CIT_TMPL(fabric)->tfc_tpg_np_base_cit.ct_attrs = NULL; +	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_base_cit.ct_attrs = NULL; +	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_attrib_cit.ct_attrs = NULL; +	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_auth_cit.ct_attrs = NULL; +	TF_CIT_TMPL(fabric)->tfc_tpg_nacl_param_cit.ct_attrs = NULL; +	/* +	 * Register the fabric for use within TCM +	 */ +	ret = target_fabric_configfs_register(fabric); +	if (ret < 0) { +		pr_err("target_fabric_configfs_register() failed" +				" for TCM_VHOST\n"); +		return ret; +	} +	/* +	 * Setup our local pointer to *fabric +	 */ +	tcm_vhost_fabric_configfs = fabric; +	pr_debug("TCM_VHOST[0] - Set fabric -> tcm_vhost_fabric_configfs\n"); +	return 0; +}; + +static void tcm_vhost_deregister_configfs(void) +{ +	if (!tcm_vhost_fabric_configfs) +		return; + +	target_fabric_configfs_deregister(tcm_vhost_fabric_configfs); +	tcm_vhost_fabric_configfs = NULL; +	pr_debug("TCM_VHOST[0] - Cleared tcm_vhost_fabric_configfs\n"); +}; + +static int __init tcm_vhost_init(void) +{ +	int ret = -ENOMEM; +	/* +	 * Use our own dedicated workqueue for submitting I/O into +	 * target core to avoid contention within system_wq. +	 */ +	tcm_vhost_workqueue = alloc_workqueue("tcm_vhost", 0, 0); +	if (!tcm_vhost_workqueue) +		goto out; + +	ret = vhost_scsi_register(); +	if (ret < 0) +		goto out_destroy_workqueue; + +	ret = tcm_vhost_register_configfs(); +	if (ret < 0) +		goto out_vhost_scsi_deregister; + +	return 0; + +out_vhost_scsi_deregister: +	vhost_scsi_deregister(); +out_destroy_workqueue: +	destroy_workqueue(tcm_vhost_workqueue); +out: +	return ret; +}; + +static void tcm_vhost_exit(void) +{ +	tcm_vhost_deregister_configfs(); +	vhost_scsi_deregister(); +	destroy_workqueue(tcm_vhost_workqueue); +}; + +MODULE_DESCRIPTION("TCM_VHOST series fabric driver"); +MODULE_LICENSE("GPL"); +module_init(tcm_vhost_init); +module_exit(tcm_vhost_exit); diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h new file mode 100644 index 00000000000..d9e93557d66 --- /dev/null +++ b/drivers/vhost/tcm_vhost.h @@ -0,0 +1,103 @@ +#define TCM_VHOST_VERSION  "v0.1" +#define TCM_VHOST_NAMELEN 256 +#define TCM_VHOST_MAX_CDB_SIZE 32 + +struct tcm_vhost_cmd { +	/* Descriptor from vhost_get_vq_desc() for virt_queue segment */ +	int tvc_vq_desc; +	/* The Tag from include/linux/virtio_scsi.h:struct virtio_scsi_cmd_req */ +	u64 tvc_tag; +	/* The number of scatterlists associated with this cmd */ +	u32 tvc_sgl_count; +	/* Saved unpacked SCSI LUN for tcm_vhost_submission_work() */ +	u32 tvc_lun; +	/* Pointer to the SGL formatted memory from virtio-scsi */ +	struct scatterlist *tvc_sgl; +	/* Pointer to response */ +	struct virtio_scsi_cmd_resp __user *tvc_resp; +	/* Pointer to vhost_scsi for our device */ +	struct vhost_scsi *tvc_vhost; +	/* The TCM I/O descriptor that is accessed via container_of() */ +	struct se_cmd tvc_se_cmd; +	/* work item used for cmwq dispatch to tcm_vhost_submission_work() */ +	struct work_struct work; +	/* Copy of the incoming SCSI command descriptor block (CDB) */ +	unsigned char tvc_cdb[TCM_VHOST_MAX_CDB_SIZE]; +	/* Sense buffer that will be mapped into outgoing status */ +	unsigned char tvc_sense_buf[TRANSPORT_SENSE_BUFFER]; +	/* Completed commands list, serviced from vhost worker thread */ +	struct list_head tvc_completion_list; +}; + +struct tcm_vhost_nexus { +	/* Pointer to TCM session for I_T Nexus */ +	struct se_session *tvn_se_sess; +}; + +struct tcm_vhost_nacl { +	/* Binary World Wide unique Port Name for Vhost Initiator port */ +	u64 iport_wwpn; +	/* ASCII formatted WWPN for Sas Initiator port */ +	char iport_name[TCM_VHOST_NAMELEN]; +	/* Returned by tcm_vhost_make_nodeacl() */ +	struct se_node_acl se_node_acl; +}; + +struct tcm_vhost_tpg { +	/* Vhost port target portal group tag for TCM */ +	u16 tport_tpgt; +	/* Used to track number of TPG Port/Lun Links wrt to explict I_T Nexus shutdown */ +	int tv_tpg_port_count; +	/* Used for vhost_scsi device reference to tpg_nexus, protected by tv_tpg_mutex */ +	int tv_tpg_vhost_count; +	/* list for tcm_vhost_list */ +	struct list_head tv_tpg_list; +	/* Used to protect access for tpg_nexus */ +	struct mutex tv_tpg_mutex; +	/* Pointer to the TCM VHost I_T Nexus for this TPG endpoint */ +	struct tcm_vhost_nexus *tpg_nexus; +	/* Pointer back to tcm_vhost_tport */ +	struct tcm_vhost_tport *tport; +	/* Returned by tcm_vhost_make_tpg() */ +	struct se_portal_group se_tpg; +}; + +struct tcm_vhost_tport { +	/* SCSI protocol the tport is providing */ +	u8 tport_proto_id; +	/* Binary World Wide unique Port Name for Vhost Target port */ +	u64 tport_wwpn; +	/* ASCII formatted WWPN for Vhost Target port */ +	char tport_name[TCM_VHOST_NAMELEN]; +	/* Returned by tcm_vhost_make_tport() */ +	struct se_wwn tport_wwn; +}; + +/* + * As per request from MST, keep TCM_VHOST related ioctl defines out of + * linux/vhost.h (user-space) for now.. + */ + +#include <linux/vhost.h> + +/* + * Used by QEMU userspace to ensure a consistent vhost-scsi ABI. + * + * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate + + *            RFC-v2 vhost-scsi userspace.  Add GET_ABI_VERSION ioctl usage + */ + +#define VHOST_SCSI_ABI_VERSION	0 + +struct vhost_scsi_target { +	int abi_version; +	char vhost_wwpn[TRANSPORT_IQN_LEN]; +	unsigned short vhost_tpgt; +	unsigned short reserved; +}; + +/* VHOST_SCSI specific defines */ +#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) +#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target) +/* Changing this breaks userspace. */ +#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 2e471c22abf..88e92041d8f 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -372,8 +372,15 @@ static void fb_flashcursor(struct work_struct *work)  	struct vc_data *vc = NULL;  	int c;  	int mode; +	int ret; + +	/* FIXME: we should sort out the unbind locking instead */ +	/* instead we just fail to flash the cursor if we can't get +	 * the lock instead of blocking fbcon deinit */ +	ret = console_trylock(); +	if (ret == 0) +		return; -	console_lock();  	if (ops && ops->currcon != -1)  		vc = vc_cons[ops->currcon].d; diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index d90062b211f..92d08e7fcba 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c @@ -91,6 +91,11 @@ static struct w1_family w1_therm_family_DS28EA00 = {  	.fops = &w1_therm_fops,  }; +static struct w1_family w1_therm_family_DS1825 = { +	.fid = W1_THERM_DS1825, +	.fops = &w1_therm_fops, +}; +  struct w1_therm_family_converter  {  	u8			broken; @@ -120,6 +125,10 @@ static struct w1_therm_family_converter w1_therm_families[] = {  		.f		= &w1_therm_family_DS28EA00,  		.convert	= w1_DS18B20_convert_temp  	}, +	{ +		.f		= &w1_therm_family_DS1825, +		.convert	= w1_DS18B20_convert_temp +	}  };  static inline int w1_DS18B20_convert_temp(u8 rom[9]) diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h index b00ada44a89..a1f0ce151d5 100644 --- a/drivers/w1/w1_family.h +++ b/drivers/w1/w1_family.h @@ -39,6 +39,7 @@  #define W1_EEPROM_DS2431	0x2D  #define W1_FAMILY_DS2760	0x30  #define W1_FAMILY_DS2780	0x32 +#define W1_THERM_DS1825		0x3B  #define W1_FAMILY_DS2781	0x3D  #define W1_THERM_DS28EA00	0x42 diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index 181fa8158a8..858c9714b2f 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -37,7 +37,6 @@ struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];       */  struct zorro_bus { -	struct list_head devices;	/* list of devices on this bus */  	struct device dev;  }; @@ -136,7 +135,6 @@ static int __init amiga_zorro_probe(struct platform_device *pdev)  	if (!bus)  		return -ENOMEM; -	INIT_LIST_HEAD(&bus->devices);  	bus->dev.parent = &pdev->dev;  	dev_set_name(&bus->dev, "zorro");  	error = device_register(&bus->dev); diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 1feb68ecef9..842d00048a6 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -94,25 +94,21 @@ static struct dentry *get_next_positive_subdir(struct dentry *prev,  {  	struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb);  	struct list_head *next; -	struct dentry *p, *q; +	struct dentry *q;  	spin_lock(&sbi->lookup_lock); +	spin_lock(&root->d_lock); -	if (prev == NULL) { -		spin_lock(&root->d_lock); +	if (prev) +		next = prev->d_u.d_child.next; +	else {  		prev = dget_dlock(root);  		next = prev->d_subdirs.next; -		p = prev; -		goto start;  	} -	p = prev; -	spin_lock(&p->d_lock); -again: -	next = p->d_u.d_child.next; -start: +cont:  	if (next == &root->d_subdirs) { -		spin_unlock(&p->d_lock); +		spin_unlock(&root->d_lock);  		spin_unlock(&sbi->lookup_lock);  		dput(prev);  		return NULL; @@ -121,16 +117,15 @@ start:  	q = list_entry(next, struct dentry, d_u.d_child);  	spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED); -	/* Negative dentry - try next */ -	if (!simple_positive(q)) { -		spin_unlock(&p->d_lock); -		lock_set_subclass(&q->d_lock.dep_map, 0, _RET_IP_); -		p = q; -		goto again; +	/* Already gone or negative dentry (under construction) - try next */ +	if (q->d_count == 0 || !simple_positive(q)) { +		spin_unlock(&q->d_lock); +		next = q->d_u.d_child.next; +		goto cont;  	}  	dget_dlock(q);  	spin_unlock(&q->d_lock); -	spin_unlock(&p->d_lock); +	spin_unlock(&root->d_lock);  	spin_unlock(&sbi->lookup_lock);  	dput(prev); @@ -404,11 +399,6 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,  			DPRINTK("checking mountpoint %p %.*s",  				dentry, (int)dentry->d_name.len, dentry->d_name.name); -			/* Path walk currently on this dentry? */ -			ino_count = atomic_read(&ino->count) + 2; -			if (dentry->d_count > ino_count) -				goto next; -  			/* Can we umount this guy */  			if (autofs4_mount_busy(mnt, dentry))  				goto next; @@ -1312,7 +1312,7 @@ EXPORT_SYMBOL(bio_copy_kern);   * Note that this code is very hard to test under normal circumstances because   * direct-io pins the pages with get_user_pages().  This makes   * is_page_cache_freeable return false, and the VM will not clean the pages. - * But other code (eg, pdflush) could clean the pages if they are mapped + * But other code (eg, flusher threads) could clean the pages if they are mapped   * pagecache.   *   * Simply disabling the call to bio_set_pages_dirty() is a good way to test the diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 83baec24946..6e8f416773d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -324,7 +324,8 @@ static noinline int add_async_extent(struct async_cow *cow,   * If this code finds it can't get good compression, it puts an   * entry onto the work queue to write the uncompressed bytes.  This   * makes sure that both compressed inodes and uncompressed inodes - * are written in the same order that pdflush sent them down. + * are written in the same order that the flusher thread sent them + * down.   */  static noinline int compress_file_range(struct inode *inode,  					struct page *locked_page, diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index bc2f6ffff3c..7bb755677a2 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -664,10 +664,6 @@ static noinline int btrfs_mksubvol(struct path *parent,  	struct dentry *dentry;  	int error; -	error = mnt_want_write(parent->mnt); -	if (error) -		return error; -  	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);  	dentry = lookup_one_len(name, parent->dentry, namelen); @@ -703,7 +699,6 @@ out_dput:  	dput(dentry);  out_unlock:  	mutex_unlock(&dir->i_mutex); -	mnt_drop_write(parent->mnt);  	return error;  } diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 643335a4fe3..051c7fe551d 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -596,7 +596,7 @@ void btrfs_start_ordered_extent(struct inode *inode,  	/*  	 * pages in the range can be dirty, clean or writeback.  We  	 * start IO on any dirty ones so the wait doesn't stall waiting -	 * for pdflush to find them +	 * for the flusher thread to find them  	 */  	if (!test_bit(BTRFS_ORDERED_DIRECT, &entry->flags))  		filemap_fdatawrite_range(inode->i_mapping, start, end); diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8c6e61d6eed..f2eb24c477a 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -100,10 +100,6 @@ static void __save_error_info(struct btrfs_fs_info *fs_info)  	fs_info->fs_state = BTRFS_SUPER_FLAG_ERROR;  } -/* NOTE: - *	We move write_super stuff at umount in order to avoid deadlock - *	for umount hold all lock. - */  static void save_error_info(struct btrfs_fs_info *fs_info)  {  	__save_error_info(fs_info); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b8708f994e6..e86ae04abe6 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1744,10 +1744,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)  	device->fs_devices = root->fs_info->fs_devices; -	/* -	 * we don't want write_supers to jump in here with our device -	 * half setup -	 */  	mutex_lock(&root->fs_info->fs_devices->device_list_mutex);  	list_add_rcu(&device->dev_list, &root->fs_info->fs_devices->devices);  	list_add(&device->dev_alloc_list, diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index fb962efdace..6d59006bfa2 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)  	int err = -ENOMEM;  	dout("ceph_fs_debugfs_init\n"); +	BUG_ON(!fsc->client->debugfs_dir);  	fsc->debugfs_congestion_kb =  		debugfs_create_file("writeback_congestion_kb",  				    0600, diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 9fff9f3b17e..4b5762ef7c2 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -992,11 +992,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,  	if (rinfo->head->is_dentry) {  		struct inode *dir = req->r_locked_dir; -		err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, -				 session, req->r_request_started, -1, -				 &req->r_caps_reservation); -		if (err < 0) -			return err; +		if (dir) { +			err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, +					 session, req->r_request_started, -1, +					 &req->r_caps_reservation); +			if (err < 0) +				return err; +		} else { +			WARN_ON_ONCE(1); +		}  	}  	/* @@ -1004,6 +1008,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,  	 * will have trouble splicing in the virtual snapdir later  	 */  	if (rinfo->head->is_dentry && !req->r_aborted && +	    req->r_locked_dir &&  	    (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name,  					       fsc->mount_options->snapdir_name,  					       req->r_dentry->d_name.len))) { diff --git a/fs/ceph/ioctl.c b/fs/ceph/ioctl.c index 8e3fb69fbe6..1396ceb4679 100644 --- a/fs/ceph/ioctl.c +++ b/fs/ceph/ioctl.c @@ -42,7 +42,8 @@ static long __validate_layout(struct ceph_mds_client *mdsc,  	/* validate striping parameters */  	if ((l->object_size & ~PAGE_MASK) ||  	    (l->stripe_unit & ~PAGE_MASK) || -	    ((unsigned)l->object_size % (unsigned)l->stripe_unit)) +	    (l->stripe_unit != 0 && +	     ((unsigned)l->object_size % (unsigned)l->stripe_unit)))  		return -EINVAL;  	/* make sure it's a valid data pool */ diff --git a/fs/compat.c b/fs/compat.c index 6161255fac4..1bdb350ea5d 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1155,11 +1155,14 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec,  	struct file *file;  	int fput_needed;  	ssize_t ret; +	loff_t pos;  	file = fget_light(fd, &fput_needed);  	if (!file)  		return -EBADF; -	ret = compat_readv(file, vec, vlen, &file->f_pos); +	pos = file->f_pos; +	ret = compat_readv(file, vec, vlen, &pos); +	file->f_pos = pos;  	fput_light(file, fput_needed);  	return ret;  } @@ -1221,11 +1224,14 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec,  	struct file *file;  	int fput_needed;  	ssize_t ret; +	loff_t pos;  	file = fget_light(fd, &fput_needed);  	if (!file)  		return -EBADF; -	ret = compat_writev(file, vec, vlen, &file->f_pos); +	pos = file->f_pos; +	ret = compat_writev(file, vec, vlen, &pos); +	file->f_pos = pos;  	fput_light(file, fput_needed);  	return ret;  } diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 1c8b5567080..eedec84c180 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1654,8 +1654,8 @@ SYSCALL_DEFINE1(epoll_create1, int, flags)  		error = PTR_ERR(file);  		goto out_free_fd;  	} -	fd_install(fd, file);  	ep->file = file; +	fd_install(fd, file);  	return fd;  out_free_fd: diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 5badb0c039d..1562c27a2fa 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -37,15 +37,12 @@  #define EXOFS_DBGMSG2(M...) do {} while (0) -enum {MAX_PAGES_KMALLOC = PAGE_SIZE / sizeof(struct page *), }; -  unsigned exofs_max_io_pages(struct ore_layout *layout,  			    unsigned expected_pages)  { -	unsigned pages = min_t(unsigned, expected_pages, MAX_PAGES_KMALLOC); +	unsigned pages = min_t(unsigned, expected_pages, +			       layout->max_io_length / PAGE_SIZE); -	/* TODO: easily support bio chaining */ -	pages =  min_t(unsigned, pages, layout->max_io_length / PAGE_SIZE);  	return pages;  } @@ -101,7 +98,8 @@ static void _pcol_reset(struct page_collect *pcol)  	 * it might not end here. don't be left with nothing  	 */  	if (!pcol->expected_pages) -		pcol->expected_pages = MAX_PAGES_KMALLOC; +		pcol->expected_pages = +				exofs_max_io_pages(&pcol->sbi->layout, ~0);  }  static int pcol_try_alloc(struct page_collect *pcol) @@ -389,6 +387,8 @@ static int readpage_strip(void *data, struct page *page)  	size_t len;  	int ret; +	BUG_ON(!PageLocked(page)); +  	/* FIXME: Just for debugging, will be removed */  	if (PageUptodate(page))  		EXOFS_ERR("PageUptodate(0x%lx, 0x%lx)\n", pcol->inode->i_ino, @@ -572,8 +572,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)  	if (!pcol->that_locked_page ||  	    (pcol->that_locked_page->index != index)) { -		struct page *page = find_get_page(pcol->inode->i_mapping, index); +		struct page *page; +		loff_t i_size = i_size_read(pcol->inode); + +		if (offset >= i_size) { +			*uptodate = true; +			EXOFS_DBGMSG("offset >= i_size index=0x%lx\n", index); +			return ZERO_PAGE(0); +		} +		page =  find_get_page(pcol->inode->i_mapping, index);  		if (!page) {  			page = find_or_create_page(pcol->inode->i_mapping,  						   index, GFP_NOFS); @@ -602,12 +610,13 @@ static void __r4w_put_page(void *priv, struct page *page)  {  	struct page_collect *pcol = priv; -	if (pcol->that_locked_page != page) { +	if ((pcol->that_locked_page != page) && (ZERO_PAGE(0) != page)) {  		EXOFS_DBGMSG("index=0x%lx\n", page->index);  		page_cache_release(page);  		return;  	} -	EXOFS_DBGMSG("that_locked_page index=0x%lx\n", page->index); +	EXOFS_DBGMSG("that_locked_page index=0x%lx\n", +		     ZERO_PAGE(0) == page ? -1 : page->index);  }  static const struct _ore_r4w_op _r4w_op = { diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index 24a49d47e93..1585db1aa36 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c @@ -837,11 +837,11 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp)  				bio->bi_rw |= REQ_WRITE;  			} -			osd_req_write(or, _ios_obj(ios, dev), per_dev->offset, -				      bio, per_dev->length); +			osd_req_write(or, _ios_obj(ios, cur_comp), +				      per_dev->offset, bio, per_dev->length);  			ORE_DBGMSG("write(0x%llx) offset=0x%llx "  				      "length=0x%llx dev=%d\n", -				     _LLU(_ios_obj(ios, dev)->id), +				     _LLU(_ios_obj(ios, cur_comp)->id),  				     _LLU(per_dev->offset),  				     _LLU(per_dev->length), dev);  		} else if (ios->kern_buff) { @@ -853,20 +853,20 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp)  			       (ios->si.unit_off + ios->length >  				ios->layout->stripe_unit)); -			ret = osd_req_write_kern(or, _ios_obj(ios, per_dev->dev), +			ret = osd_req_write_kern(or, _ios_obj(ios, cur_comp),  						 per_dev->offset,  						 ios->kern_buff, ios->length);  			if (unlikely(ret))  				goto out;  			ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx "  				      "length=0x%llx dev=%d\n", -				     _LLU(_ios_obj(ios, dev)->id), +				     _LLU(_ios_obj(ios, cur_comp)->id),  				     _LLU(per_dev->offset),  				     _LLU(ios->length), per_dev->dev);  		} else { -			osd_req_set_attributes(or, _ios_obj(ios, dev)); +			osd_req_set_attributes(or, _ios_obj(ios, cur_comp));  			ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n", -				     _LLU(_ios_obj(ios, dev)->id), +				     _LLU(_ios_obj(ios, cur_comp)->id),  				     ios->out_attr_len, dev);  		} diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 433783624d1..dde41a75c7c 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -400,8 +400,6 @@ static int exofs_sync_fs(struct super_block *sb, int wait)  	ret = ore_write(ios);  	if (unlikely(ret))  		EXOFS_ERR("%s: ore_write failed.\n", __func__); -	else -		sb->s_dirt = 0;  	unlock_super(sb); @@ -412,14 +410,6 @@ out:  	return ret;  } -static void exofs_write_super(struct super_block *sb) -{ -	if (!(sb->s_flags & MS_RDONLY)) -		exofs_sync_fs(sb, 1); -	else -		sb->s_dirt = 0; -} -  static void _exofs_print_device(const char *msg, const char *dev_path,  				struct osd_dev *od, u64 pid)  { @@ -952,7 +942,6 @@ static const struct super_operations exofs_sops = {  	.write_inode    = exofs_write_inode,  	.evict_inode    = exofs_evict_inode,  	.put_super      = exofs_put_super, -	.write_super    = exofs_write_super,  	.sync_fs	= exofs_sync_fs,  	.statfs         = exofs_statfs,  }; diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 9a4a5c48b1c..a07597307fd 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -3459,14 +3459,6 @@ ext3_reserve_inode_write(handle_t *handle, struct inode *inode,   * inode out, but prune_icache isn't a user-visible syncing function.   * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync)   * we start and wait on commits. - * - * Is this efficient/effective?  Well, we're being nice to the system - * by cleaning up our inodes proactively so they can be reaped - * without I/O.  But we are potentially leaving up to five seconds' - * worth of inodes floating about which prune_icache wants us to - * write out.  One way to fix that would be to get prune_icache() - * to do a write_super() to free up some memory.  It has the desired - * effect.   */  int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode)  { diff --git a/fs/ext3/super.c b/fs/ext3/super.c index ff9bcdc5b0d..8c892e93d8e 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -64,11 +64,6 @@ static int ext3_freeze(struct super_block *sb);  /*   * Wrappers for journal_start/end. - * - * The only special thing we need to do here is to make sure that all - * journal_end calls result in the superblock being marked dirty, so - * that sync() will call the filesystem's write_super callback if - * appropriate.   */  handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)  { @@ -90,12 +85,6 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)  	return journal_start(journal, nblocks);  } -/* - * The only special thing we need to do here is to make sure that all - * journal_stop calls result in the superblock being marked dirty, so - * that sync() will call the filesystem's write_super callback if - * appropriate. - */  int __ext3_journal_stop(const char *where, handle_t *handle)  {  	struct super_block *sb; diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index d23b31ca9d7..1b5089067d0 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -280,14 +280,18 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,  	return desc;  } -static int ext4_valid_block_bitmap(struct super_block *sb, -				   struct ext4_group_desc *desc, -				   unsigned int block_group, -				   struct buffer_head *bh) +/* + * Return the block number which was discovered to be invalid, or 0 if + * the block bitmap is valid. + */ +static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb, +					    struct ext4_group_desc *desc, +					    unsigned int block_group, +					    struct buffer_head *bh)  {  	ext4_grpblk_t offset;  	ext4_grpblk_t next_zero_bit; -	ext4_fsblk_t bitmap_blk; +	ext4_fsblk_t blk;  	ext4_fsblk_t group_first_block;  	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { @@ -297,37 +301,33 @@ static int ext4_valid_block_bitmap(struct super_block *sb,  		 * or it has to also read the block group where the bitmaps  		 * are located to verify they are set.  		 */ -		return 1; +		return 0;  	}  	group_first_block = ext4_group_first_block_no(sb, block_group);  	/* check whether block bitmap block number is set */ -	bitmap_blk = ext4_block_bitmap(sb, desc); -	offset = bitmap_blk - group_first_block; +	blk = ext4_block_bitmap(sb, desc); +	offset = blk - group_first_block;  	if (!ext4_test_bit(offset, bh->b_data))  		/* bad block bitmap */ -		goto err_out; +		return blk;  	/* check whether the inode bitmap block number is set */ -	bitmap_blk = ext4_inode_bitmap(sb, desc); -	offset = bitmap_blk - group_first_block; +	blk = ext4_inode_bitmap(sb, desc); +	offset = blk - group_first_block;  	if (!ext4_test_bit(offset, bh->b_data))  		/* bad block bitmap */ -		goto err_out; +		return blk;  	/* check whether the inode table block number is set */ -	bitmap_blk = ext4_inode_table(sb, desc); -	offset = bitmap_blk - group_first_block; +	blk = ext4_inode_table(sb, desc); +	offset = blk - group_first_block;  	next_zero_bit = ext4_find_next_zero_bit(bh->b_data,  				offset + EXT4_SB(sb)->s_itb_per_group,  				offset); -	if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group) -		/* good bitmap for inode tables */ -		return 1; - -err_out: -	ext4_error(sb, "Invalid block bitmap - block_group = %d, block = %llu", -			block_group, bitmap_blk); +	if (next_zero_bit < offset + EXT4_SB(sb)->s_itb_per_group) +		/* bad bitmap for inode tables */ +		return blk;  	return 0;  } @@ -336,14 +336,26 @@ void ext4_validate_block_bitmap(struct super_block *sb,  			       unsigned int block_group,  			       struct buffer_head *bh)  { +	ext4_fsblk_t	blk; +  	if (buffer_verified(bh))  		return;  	ext4_lock_group(sb, block_group); -	if (ext4_valid_block_bitmap(sb, desc, block_group, bh) && -	    ext4_block_bitmap_csum_verify(sb, block_group, desc, bh, -					  EXT4_BLOCKS_PER_GROUP(sb) / 8)) -		set_buffer_verified(bh); +	blk = ext4_valid_block_bitmap(sb, desc, block_group, bh); +	if (unlikely(blk != 0)) { +		ext4_unlock_group(sb, block_group); +		ext4_error(sb, "bg %u: block %llu: invalid block bitmap", +			   block_group, blk); +		return; +	} +	if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, +			desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) { +		ext4_unlock_group(sb, block_group); +		ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); +		return; +	} +	set_buffer_verified(bh);  	ext4_unlock_group(sb, block_group);  } diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index f8716eab999..5c2d1813ebe 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -79,7 +79,6 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,  	if (provided == calculated)  		return 1; -	ext4_error(sb, "Bad block bitmap checksum: block_group = %u", group);  	return 0;  } diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index cd0c7ed0677..aabbb3f5368 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2662,6 +2662,7 @@ cont:  		}  		path[0].p_depth = depth;  		path[0].p_hdr = ext_inode_hdr(inode); +		i = 0;  		if (ext4_ext_check(inode, path[0].p_hdr, depth)) {  			err = -EIO; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 6324f74e034..dff171c3a12 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1970,7 +1970,7 @@ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate);   * This function can get called via...   *   - ext4_da_writepages after taking page lock (have journal handle)   *   - journal_submit_inode_data_buffers (no journal handle) - *   - shrink_page_list via pdflush (no journal handle) + *   - shrink_page_list via the kswapd/direct reclaim (no journal handle)   *   - grab_page_cache when doing write_begin (have journal handle)   *   * We don't do any block allocation in this function. If we have page with @@ -4589,14 +4589,6 @@ static int ext4_expand_extra_isize(struct inode *inode,   * inode out, but prune_icache isn't a user-visible syncing function.   * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync)   * we start and wait on commits. - * - * Is this efficient/effective?  Well, we're being nice to the system - * by cleaning up our inodes proactively so they can be reaped - * without I/O.  But we are potentially leaving up to five seconds' - * worth of inodes floating about which prune_icache wants us to - * write out.  One way to fix that would be to get prune_icache() - * to do a write_super() to free up some memory.  It has the desired - * effect.   */  int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)  { diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d76ec8277d3..c6e0cb3d1f4 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -326,11 +326,6 @@ static void ext4_put_nojournal(handle_t *handle)  /*   * Wrappers for jbd2_journal_start/end. - * - * The only special thing we need to do here is to make sure that all - * journal_end calls result in the superblock being marked dirty, so - * that sync() will call the filesystem's write_super callback if - * appropriate.   */  handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)  { @@ -356,12 +351,6 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)  	return jbd2_journal_start(journal, nblocks);  } -/* - * The only special thing we need to do here is to make sure that all - * jbd2_journal_stop calls result in the superblock being marked dirty, so - * that sync() will call the filesystem's write_super callback if - * appropriate. - */  int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle)  {  	struct super_block *sb; @@ -959,6 +948,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)  	ei->i_reserved_meta_blocks = 0;  	ei->i_allocated_meta_blocks = 0;  	ei->i_da_metadata_calc_len = 0; +	ei->i_da_metadata_calc_last_lblock = 0;  	spin_lock_init(&(ei->i_block_reservation_lock));  #ifdef CONFIG_QUOTA  	ei->i_reserved_quota = 0; @@ -3119,6 +3109,10 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp,  	ext4_group_t		i, ngroups = ext4_get_groups_count(sb);  	int			s, j, count = 0; +	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) +		return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + +			sbi->s_itb_per_group + 2); +  	first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +  		(grp * EXT4_BLOCKS_PER_GROUP(sb));  	last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; @@ -4430,6 +4424,7 @@ static void ext4_clear_journal_err(struct super_block *sb,  		ext4_commit_super(sb, 1);  		jbd2_journal_clear_err(journal); +		jbd2_journal_update_sb_errno(journal);  	}  } diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8964cf3999b..324bc085053 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -383,6 +383,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,  	struct fuse_entry_out outentry;  	struct fuse_file *ff; +	/* Userspace expects S_IFREG in create mode */ +	BUG_ON((mode & S_IFMT) != S_IFREG); +  	forget = fuse_alloc_forget();  	err = -ENOMEM;  	if (!forget) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 93d8d6c9494..aba15f1b7ad 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -703,13 +703,16 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov,  				  unsigned long nr_segs, loff_t pos)  {  	struct inode *inode = iocb->ki_filp->f_mapping->host; +	struct fuse_conn *fc = get_fuse_conn(inode); -	if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { +	/* +	 * In auto invalidate mode, always update attributes on read. +	 * Otherwise, only update if we attempt to read past EOF (to ensure +	 * i_size is up to date). +	 */ +	if (fc->auto_inval_data || +	    (pos + iov_length(iov, nr_segs) > i_size_read(inode))) {  		int err; -		/* -		 * If trying to read past EOF, make sure the i_size -		 * attribute is up-to-date. -		 */  		err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL);  		if (err)  			return err; @@ -1700,7 +1703,7 @@ static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)  	size_t n;  	u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; -	for (n = 0; n < count; n++) { +	for (n = 0; n < count; n++, iov++) {  		if (iov->iov_len > (size_t) max)  			return -ENOMEM;  		max -= iov->iov_len; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 771fb6322c0..e24dd74e306 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -484,6 +484,9 @@ struct fuse_conn {  	/** Is fallocate not implemented by fs? */  	unsigned no_fallocate:1; +	/** Use enhanced/automatic page cache invalidation. */ +	unsigned auto_inval_data:1; +  	/** The number of requests waiting for completion */  	atomic_t num_waiting; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 1cd61652018..ce0a2838ccd 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -197,6 +197,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,  	struct fuse_conn *fc = get_fuse_conn(inode);  	struct fuse_inode *fi = get_fuse_inode(inode);  	loff_t oldsize; +	struct timespec old_mtime;  	spin_lock(&fc->lock);  	if (attr_version != 0 && fi->attr_version > attr_version) { @@ -204,15 +205,35 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,  		return;  	} +	old_mtime = inode->i_mtime;  	fuse_change_attributes_common(inode, attr, attr_valid);  	oldsize = inode->i_size;  	i_size_write(inode, attr->size);  	spin_unlock(&fc->lock); -	if (S_ISREG(inode->i_mode) && oldsize != attr->size) { -		truncate_pagecache(inode, oldsize, attr->size); -		invalidate_inode_pages2(inode->i_mapping); +	if (S_ISREG(inode->i_mode)) { +		bool inval = false; + +		if (oldsize != attr->size) { +			truncate_pagecache(inode, oldsize, attr->size); +			inval = true; +		} else if (fc->auto_inval_data) { +			struct timespec new_mtime = { +				.tv_sec = attr->mtime, +				.tv_nsec = attr->mtimensec, +			}; + +			/* +			 * Auto inval mode also checks and invalidates if mtime +			 * has changed. +			 */ +			if (!timespec_equal(&old_mtime, &new_mtime)) +				inval = true; +		} + +		if (inval) +			invalidate_inode_pages2(inode->i_mapping);  	}  } @@ -834,6 +855,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)  				fc->big_writes = 1;  			if (arg->flags & FUSE_DONT_MASK)  				fc->dont_mask = 1; +			if (arg->flags & FUSE_AUTO_INVAL_DATA) +				fc->auto_inval_data = 1;  		} else {  			ra_pages = fc->max_read / PAGE_CACHE_SIZE;  			fc->no_lock = 1; @@ -859,7 +882,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)  	arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;  	arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |  		FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | -		FUSE_FLOCK_LOCKS; +		FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | +		FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA;  	req->in.h.opcode = FUSE_INIT;  	req->in.numargs = 1;  	req->in.args[0].size = sizeof(*arg); diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 3a56c8d94de..22255d96b27 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -52,7 +52,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb  		/*  		 * If it's a fully non-blocking write attempt and we cannot  		 * lock the buffer then redirty the page.  Note that this can -		 * potentially cause a busy-wait loop from pdflush and kswapd +		 * potentially cause a busy-wait loop from flusher thread and kswapd  		 * activity, but those code paths have their own higher-level  		 * throttling.  		 */ diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index 5fd51a5833f..b7ec224910c 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -236,10 +236,10 @@ out:   * hfs_mdb_commit()   *   * Description: - *   This updates the MDB on disk (look also at hfs_write_super()). + *   This updates the MDB on disk.   *   It does not check, if the superblock has been modified, or   *   if the filesystem has been mounted read-only. It is mainly - *   called by hfs_write_super() and hfs_btree_extend(). + *   called by hfs_sync_fs() and flush_mdb().   * Input Variable(s):   *   struct hfs_mdb *mdb: Pointer to the hfs MDB   *   int backup; diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 425c2f2cf17..09357508ec9 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -534,8 +534,8 @@ int journal_start_commit(journal_t *journal, tid_t *ptid)  		ret = 1;  	} else if (journal->j_committing_transaction) {  		/* -		 * If ext3_write_super() recently started a commit, then we -		 * have to wait for completion of that transaction +		 * If commit has been started, then we have to wait for +		 * completion of that transaction.  		 */  		if (ptid)  			*ptid = journal->j_committing_transaction->t_tid; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index e9a3c4c8559..e149b99a7ff 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -612,8 +612,8 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid)  		ret = 1;  	} else if (journal->j_committing_transaction) {  		/* -		 * If ext3_write_super() recently started a commit, then we -		 * have to wait for completion of that transaction +		 * If commit has been started, then we have to wait for +		 * completion of that transaction.  		 */  		if (ptid)  			*ptid = journal->j_committing_transaction->t_tid; @@ -1377,7 +1377,7 @@ static void jbd2_mark_journal_empty(journal_t *journal)   * Update a journal's errno.  Write updated superblock to disk waiting for IO   * to complete.   */ -static void jbd2_journal_update_sb_errno(journal_t *journal) +void jbd2_journal_update_sb_errno(journal_t *journal)  {  	journal_superblock_t *sb = journal->j_superblock; @@ -1390,6 +1390,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal)  	jbd2_write_superblock(journal, WRITE_SYNC);  } +EXPORT_SYMBOL(jbd2_journal_update_sb_errno);  /*   * Read the superblock for a given journal, performing initial diff --git a/fs/namei.c b/fs/namei.c index 1b464390dde..dd1ed1b8e98 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -352,6 +352,7 @@ int __inode_permission(struct inode *inode, int mask)  /**   * sb_permission - Check superblock-level permissions   * @sb: Superblock of inode to check permission on + * @inode: Inode to check permission on   * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)   *   * Separate out file-system wide checks from inode-specific permission checks. @@ -656,6 +657,7 @@ int sysctl_protected_hardlinks __read_mostly = 1;  /**   * may_follow_link - Check symlink following for unsafe situations   * @link: The path of the symlink + * @nd: nameidata pathwalk data   *   * In the case of the sysctl_protected_symlinks sysctl being enabled,   * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is @@ -2414,7 +2416,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,  		goto out;  	} -	mode = op->mode & S_IALLUGO; +	mode = op->mode;  	if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))  		mode &= ~current_umask(); @@ -2452,7 +2454,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,  	}  	if (open_flag & O_CREAT) { -		error = may_o_create(&nd->path, dentry, op->mode); +		error = may_o_create(&nd->path, dentry, mode);  		if (error) {  			create_error = error;  			if (open_flag & O_EXCL) @@ -2489,6 +2491,10 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,  			dput(dentry);  			dentry = file->f_path.dentry;  		} +		if (create_error && dentry->d_inode == NULL) { +			error = create_error; +			goto out; +		}  		goto looked_up;  	} diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 8bf3a3f6925..b7db60897f9 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -12,19 +12,19 @@ nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o  nfs-$(CONFIG_SYSCTL)	+= sysctl.o  nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o -obj-$(CONFIG_NFS_V2) += nfs2.o -nfs2-y := nfs2super.o proc.o nfs2xdr.o +obj-$(CONFIG_NFS_V2) += nfsv2.o +nfsv2-y := nfs2super.o proc.o nfs2xdr.o -obj-$(CONFIG_NFS_V3) += nfs3.o -nfs3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o -nfs3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o +obj-$(CONFIG_NFS_V3) += nfsv3.o +nfsv3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o +nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o -obj-$(CONFIG_NFS_V4) += nfs4.o -nfs4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ +obj-$(CONFIG_NFS_V4) += nfsv4.o +nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \  	  delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \  	  nfs4namespace.o nfs4getroot.o nfs4client.o -nfs4-$(CONFIG_SYSCTL)	+= nfs4sysctl.o -nfs4-$(CONFIG_NFS_V4_1)	+= pnfs.o pnfs_dev.o +nfsv4-$(CONFIG_SYSCTL)	+= nfs4sysctl.o +nfsv4-$(CONFIG_NFS_V4_1)	+= pnfs.o pnfs_dev.o  obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o  nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 9fc0d9dfc91..99694442b93 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -105,7 +105,7 @@ struct nfs_subversion *get_nfs_version(unsigned int version)  	if (IS_ERR(nfs)) {  		mutex_lock(&nfs_version_mutex); -		request_module("nfs%d", version); +		request_module("nfsv%d", version);  		nfs = find_nfs_version(version);  		mutex_unlock(&nfs_version_mutex);  	} diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index b701358c39c..a850079467d 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -61,6 +61,12 @@ struct idmap {  	struct mutex		idmap_mutex;  }; +struct idmap_legacy_upcalldata { +	struct rpc_pipe_msg pipe_msg; +	struct idmap_msg idmap_msg; +	struct idmap *idmap; +}; +  /**   * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields   * @fattr: fully initialised struct nfs_fattr @@ -324,6 +330,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,  		ret = nfs_idmap_request_key(&key_type_id_resolver_legacy,  					    name, namelen, type, data,  					    data_size, idmap); +		idmap->idmap_key_cons = NULL;  		mutex_unlock(&idmap->idmap_mutex);  	}  	return ret; @@ -380,11 +387,13 @@ static const match_table_t nfs_idmap_tokens = {  static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *);  static ssize_t idmap_pipe_downcall(struct file *, const char __user *,  				   size_t); +static void idmap_release_pipe(struct inode *);  static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *);  static const struct rpc_pipe_ops idmap_upcall_ops = {  	.upcall		= rpc_pipe_generic_upcall,  	.downcall	= idmap_pipe_downcall, +	.release_pipe	= idmap_release_pipe,  	.destroy_msg	= idmap_pipe_destroy_msg,  }; @@ -616,7 +625,8 @@ void nfs_idmap_quit(void)  	nfs_idmap_quit_keyring();  } -static int nfs_idmap_prepare_message(char *desc, struct idmap_msg *im, +static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, +				     struct idmap_msg *im,  				     struct rpc_pipe_msg *msg)  {  	substring_t substr; @@ -659,6 +669,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,  				   const char *op,  				   void *aux)  { +	struct idmap_legacy_upcalldata *data;  	struct rpc_pipe_msg *msg;  	struct idmap_msg *im;  	struct idmap *idmap = (struct idmap *)aux; @@ -666,15 +677,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,  	int ret = -ENOMEM;  	/* msg and im are freed in idmap_pipe_destroy_msg */ -	msg = kmalloc(sizeof(*msg), GFP_KERNEL); -	if (!msg) -		goto out0; - -	im = kmalloc(sizeof(*im), GFP_KERNEL); -	if (!im) +	data = kmalloc(sizeof(*data), GFP_KERNEL); +	if (!data)  		goto out1; -	ret = nfs_idmap_prepare_message(key->description, im, msg); +	msg = &data->pipe_msg; +	im = &data->idmap_msg; +	data->idmap = idmap; + +	ret = nfs_idmap_prepare_message(key->description, idmap, im, msg);  	if (ret < 0)  		goto out2; @@ -683,15 +694,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,  	ret = rpc_queue_upcall(idmap->idmap_pipe, msg);  	if (ret < 0) -		goto out2; +		goto out3;  	return ret; +out3: +	idmap->idmap_key_cons = NULL;  out2: -	kfree(im); +	kfree(data);  out1: -	kfree(msg); -out0:  	complete_request_key(cons, ret);  	return ret;  } @@ -749,9 +760,8 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)  	}  	if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { -		ret = mlen; -		complete_request_key(cons, -ENOKEY); -		goto out_incomplete; +		ret = -ENOKEY; +		goto out;  	}  	namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); @@ -768,16 +778,32 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)  out:  	complete_request_key(cons, ret); -out_incomplete:  	return ret;  }  static void  idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg)  { +	struct idmap_legacy_upcalldata *data = container_of(msg, +			struct idmap_legacy_upcalldata, +			pipe_msg); +	struct idmap *idmap = data->idmap; +	struct key_construction *cons; +	if (msg->errno) { +		cons = ACCESS_ONCE(idmap->idmap_key_cons); +		idmap->idmap_key_cons = NULL; +		complete_request_key(cons, msg->errno); +	}  	/* Free memory allocated in nfs_idmap_legacy_upcall() */ -	kfree(msg->data); -	kfree(msg); +	kfree(data); +} + +static void +idmap_release_pipe(struct inode *inode) +{ +	struct rpc_inode *rpci = RPC_I(inode); +	struct idmap *idmap = (struct idmap *)rpci->private; +	idmap->idmap_key_cons = NULL;  }  int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 0952c791df3..d6b3b5f2d77 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -69,7 +69,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,  	nfs_fattr_init(info->fattr);  	status = rpc_call_sync(client, &msg, 0);  	dprintk("%s: reply fsinfo: %d\n", __func__, status); -	if (!(info->fattr->valid & NFS_ATTR_FATTR)) { +	if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) {  		msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];  		msg.rpc_resp = info->fattr;  		status = rpc_call_sync(client, &msg, 0); diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 3b950dd81e8..da0618aeead 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -205,6 +205,9 @@ extern const struct dentry_operations nfs4_dentry_operations;  int nfs_atomic_open(struct inode *, struct dentry *, struct file *,  		    unsigned, umode_t, int *); +/* super.c */ +extern struct file_system_type nfs4_fs_type; +  /* nfs4namespace.c */  rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *);  struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index cbcdfaf3250..24eb663f8ed 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -74,7 +74,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)  	return clp;  error: -	kfree(clp); +	nfs_free_client(clp);  	return ERR_PTR(err);  } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a99a8d94872..635274140b1 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3737,9 +3737,10 @@ out:  static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)  {  	struct nfs4_cached_acl *acl; +	size_t buflen = sizeof(*acl) + acl_len; -	if (pages && acl_len <= PAGE_SIZE) { -		acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); +	if (pages && buflen <= PAGE_SIZE) { +		acl = kmalloc(buflen, GFP_KERNEL);  		if (acl == NULL)  			goto out;  		acl->cached = 1; @@ -3819,7 +3820,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu  	if (ret)  		goto out_free; -	acl_len = res.acl_len - res.acl_data_offset; +	acl_len = res.acl_len;  	if (acl_len > args.acl_len)  		nfs4_write_cached_acl(inode, NULL, 0, acl_len);  	else @@ -6223,11 +6224,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)  	dprintk("<-- %s\n", __func__);  } +static size_t max_response_pages(struct nfs_server *server) +{ +	u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; +	return nfs_page_array_len(0, max_resp_sz); +} + +static void nfs4_free_pages(struct page **pages, size_t size) +{ +	int i; + +	if (!pages) +		return; + +	for (i = 0; i < size; i++) { +		if (!pages[i]) +			break; +		__free_page(pages[i]); +	} +	kfree(pages); +} + +static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags) +{ +	struct page **pages; +	int i; + +	pages = kcalloc(size, sizeof(struct page *), gfp_flags); +	if (!pages) { +		dprintk("%s: can't alloc array of %zu pages\n", __func__, size); +		return NULL; +	} + +	for (i = 0; i < size; i++) { +		pages[i] = alloc_page(gfp_flags); +		if (!pages[i]) { +			dprintk("%s: failed to allocate page\n", __func__); +			nfs4_free_pages(pages, size); +			return NULL; +		} +	} + +	return pages; +} +  static void nfs4_layoutget_release(void *calldata)  {  	struct nfs4_layoutget *lgp = calldata; +	struct nfs_server *server = NFS_SERVER(lgp->args.inode); +	size_t max_pages = max_response_pages(server);  	dprintk("--> %s\n", __func__); +	nfs4_free_pages(lgp->args.layout.pages, max_pages);  	put_nfs_open_context(lgp->args.ctx);  	kfree(calldata);  	dprintk("<-- %s\n", __func__); @@ -6239,9 +6287,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {  	.rpc_release = nfs4_layoutget_release,  }; -int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) +void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)  {  	struct nfs_server *server = NFS_SERVER(lgp->args.inode); +	size_t max_pages = max_response_pages(server);  	struct rpc_task *task;  	struct rpc_message msg = {  		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], @@ -6259,12 +6308,19 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)  	dprintk("--> %s\n", __func__); +	lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); +	if (!lgp->args.layout.pages) { +		nfs4_layoutget_release(lgp); +		return; +	} +	lgp->args.layout.pglen = max_pages * PAGE_SIZE; +  	lgp->res.layoutp = &lgp->args.layout;  	lgp->res.seq_res.sr_slot = NULL;  	nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);  	task = rpc_run_task(&task_setup_data);  	if (IS_ERR(task)) -		return PTR_ERR(task); +		return;  	status = nfs4_wait_for_completion_rpc_task(task);  	if (status == 0)  		status = task->tk_status; @@ -6272,7 +6328,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)  		status = pnfs_layout_process(lgp);  	rpc_put_task(task);  	dprintk("<-- %s status=%d\n", __func__, status); -	return status; +	return;  }  static void @@ -6304,12 +6360,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)  		return;  	}  	spin_lock(&lo->plh_inode->i_lock); -	if (task->tk_status == 0) { -		if (lrp->res.lrs_present) { -			pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); -		} else -			BUG_ON(!list_empty(&lo->plh_segs)); -	} +	if (task->tk_status == 0 && lrp->res.lrs_present) +		pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);  	lo->plh_block_lgets--;  	spin_unlock(&lo->plh_inode->i_lock);  	dprintk("<-- %s\n", __func__); diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 12a31a9dbcd..bd61221ad2c 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -23,14 +23,6 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,  static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,  	int flags, const char *dev_name, void *raw_data); -static struct file_system_type nfs4_fs_type = { -	.owner		= THIS_MODULE, -	.name		= "nfs4", -	.mount		= nfs_fs_mount, -	.kill_sb	= nfs_kill_super, -	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, -}; -  static struct file_system_type nfs4_remote_fs_type = {  	.owner		= THIS_MODULE,  	.name		= "nfs4", @@ -344,14 +336,8 @@ static int __init init_nfs_v4(void)  	if (err)  		goto out1; -	err = register_filesystem(&nfs4_fs_type); -	if (err < 0) -		goto out2; -  	register_nfs_version(&nfs_v4);  	return 0; -out2: -	nfs4_unregister_sysctl();  out1:  	nfs_idmap_quit();  out: @@ -361,7 +347,6 @@ out:  static void __exit exit_nfs_v4(void)  {  	unregister_nfs_version(&nfs_v4); -	unregister_filesystem(&nfs4_fs_type);  	nfs4_unregister_sysctl();  	nfs_idmap_quit();  } diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index ca13483edd6..1bfbd67c556 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -5045,22 +5045,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,  			 struct nfs_getaclres *res)  {  	unsigned int savep; -	__be32 *bm_p;  	uint32_t attrlen,  		 bitmap[3] = {0};  	int status; -	size_t page_len = xdr->buf->page_len; +	unsigned int pg_offset;  	res->acl_len = 0;  	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)  		goto out; -	bm_p = xdr->p; -	res->acl_data_offset = be32_to_cpup(bm_p) + 2; -	res->acl_data_offset <<= 2; -	/* Check if the acl data starts beyond the allocated buffer */ -	if (res->acl_data_offset > page_len) -		return -ERANGE; +	xdr_enter_page(xdr, xdr->buf->page_len); + +	/* Calculate the offset of the page data */ +	pg_offset = xdr->buf->head[0].iov_len;  	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)  		goto out; @@ -5074,23 +5071,20 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,  		/* The bitmap (xdr len + bitmaps) and the attr xdr len words  		 * are stored with the acl data to handle the problem of  		 * variable length bitmaps.*/ -		xdr->p = bm_p; +		res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset;  		/* We ignore &savep and don't do consistency checks on  		 * the attr length.  Let userspace figure it out.... */ -		attrlen += res->acl_data_offset; -		if (attrlen > page_len) { +		res->acl_len = attrlen; +		if (attrlen > (xdr->nwords << 2)) {  			if (res->acl_flags & NFS4_ACL_LEN_REQUEST) {  				/* getxattr interface called with a NULL buf */ -				res->acl_len = attrlen;  				goto out;  			} -			dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", -					attrlen, page_len); +			dprintk("NFS: acl reply: attrlen %u > page_len %u\n", +					attrlen, xdr->nwords << 2);  			return -EINVAL;  		} -		xdr_read_pages(xdr, attrlen); -		res->acl_len = attrlen;  	} else  		status = -EOPNOTSUPP; diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index f50d3e8d6f2..ea6d111b03e 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -570,17 +570,66 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,  		return false;  	return pgio->pg_count + req->wb_bytes <= -			OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; +			(unsigned long)pgio->pg_layout_private; +} + +void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +{ +	pnfs_generic_pg_init_read(pgio, req); +	if (unlikely(pgio->pg_lseg == NULL)) +		return; /* Not pNFS */ + +	pgio->pg_layout_private = (void *) +				OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; +} + +static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, +				   unsigned long *stripe_end) +{ +	u32 stripe_off; +	unsigned stripe_size; + +	if (layout->raid_algorithm == PNFS_OSD_RAID_0) +		return true; + +	stripe_size = layout->stripe_unit * +				(layout->group_width - layout->parity); + +	div_u64_rem(offset, stripe_size, &stripe_off); +	if (!stripe_off) +		return true; + +	*stripe_end = stripe_size - stripe_off; +	return false; +} + +void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +{ +	unsigned long stripe_end = 0; + +	pnfs_generic_pg_init_write(pgio, req); +	if (unlikely(pgio->pg_lseg == NULL)) +		return; /* Not pNFS */ + +	if (req->wb_offset || +	    !aligned_on_raid_stripe(req->wb_index * PAGE_SIZE, +			       &OBJIO_LSEG(pgio->pg_lseg)->layout, +			       &stripe_end)) { +		pgio->pg_layout_private = (void *)stripe_end; +	} else { +		pgio->pg_layout_private = (void *) +				OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; +	}  }  static const struct nfs_pageio_ops objio_pg_read_ops = { -	.pg_init = pnfs_generic_pg_init_read, +	.pg_init = objio_init_read,  	.pg_test = objio_pg_test,  	.pg_doio = pnfs_generic_pg_readpages,  };  static const struct nfs_pageio_ops objio_pg_write_ops = { -	.pg_init = pnfs_generic_pg_init_write, +	.pg_init = objio_init_write,  	.pg_test = objio_pg_test,  	.pg_doio = pnfs_generic_pg_writepages,  }; diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 1a6732ed04a..311a79681e2 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -49,6 +49,7 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,  	hdr->io_start = req_offset(hdr->req);  	hdr->good_bytes = desc->pg_count;  	hdr->dreq = desc->pg_dreq; +	hdr->layout_private = desc->pg_layout_private;  	hdr->release = release;  	hdr->completion_ops = desc->pg_completion_ops;  	if (hdr->completion_ops->init_hdr) @@ -268,6 +269,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,  	desc->pg_error = 0;  	desc->pg_lseg = NULL;  	desc->pg_dreq = NULL; +	desc->pg_layout_private = NULL;  }  EXPORT_SYMBOL_GPL(nfs_pageio_init); diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 76875bfcf19..2e00feacd4b 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -583,9 +583,6 @@ send_layoutget(struct pnfs_layout_hdr *lo,  	struct nfs_server *server = NFS_SERVER(ino);  	struct nfs4_layoutget *lgp;  	struct pnfs_layout_segment *lseg = NULL; -	struct page **pages = NULL; -	int i; -	u32 max_resp_sz, max_pages;  	dprintk("--> %s\n", __func__); @@ -594,20 +591,6 @@ send_layoutget(struct pnfs_layout_hdr *lo,  	if (lgp == NULL)  		return NULL; -	/* allocate pages for xdr post processing */ -	max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; -	max_pages = nfs_page_array_len(0, max_resp_sz); - -	pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); -	if (!pages) -		goto out_err_free; - -	for (i = 0; i < max_pages; i++) { -		pages[i] = alloc_page(gfp_flags); -		if (!pages[i]) -			goto out_err_free; -	} -  	lgp->args.minlength = PAGE_CACHE_SIZE;  	if (lgp->args.minlength > range->length)  		lgp->args.minlength = range->length; @@ -616,39 +599,19 @@ send_layoutget(struct pnfs_layout_hdr *lo,  	lgp->args.type = server->pnfs_curr_ld->id;  	lgp->args.inode = ino;  	lgp->args.ctx = get_nfs_open_context(ctx); -	lgp->args.layout.pages = pages; -	lgp->args.layout.pglen = max_pages * PAGE_SIZE;  	lgp->lsegpp = &lseg;  	lgp->gfp_flags = gfp_flags;  	/* Synchronously retrieve layout information from server and  	 * store in lseg.  	 */ -	nfs4_proc_layoutget(lgp); +	nfs4_proc_layoutget(lgp, gfp_flags);  	if (!lseg) {  		/* remember that LAYOUTGET failed and suspend trying */  		set_bit(lo_fail_bit(range->iomode), &lo->plh_flags);  	} -	/* free xdr pages */ -	for (i = 0; i < max_pages; i++) -		__free_page(pages[i]); -	kfree(pages); -  	return lseg; - -out_err_free: -	/* free any allocated xdr pages, lgp as it's not used */ -	if (pages) { -		for (i = 0; i < max_pages; i++) { -			if (!pages[i]) -				break; -			__free_page(pages[i]); -		} -		kfree(pages); -	} -	kfree(lgp); -	return NULL;  }  /* diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 2c6c80503ba..745aa1b39e7 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -172,7 +172,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server,  				   struct pnfs_devicelist *devlist);  extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,  				   struct pnfs_device *dev); -extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); +extern void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags);  extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp);  /* pnfs.c */ diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ac6a3c55dce..239aff7338e 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -319,6 +319,34 @@ EXPORT_SYMBOL_GPL(nfs_sops);  static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *);  static int nfs4_validate_mount_data(void *options,  	struct nfs_parsed_mount_data *args, const char *dev_name); + +struct file_system_type nfs4_fs_type = { +	.owner		= THIS_MODULE, +	.name		= "nfs4", +	.mount		= nfs_fs_mount, +	.kill_sb	= nfs_kill_super, +	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, +}; +EXPORT_SYMBOL_GPL(nfs4_fs_type); + +static int __init register_nfs4_fs(void) +{ +	return register_filesystem(&nfs4_fs_type); +} + +static void unregister_nfs4_fs(void) +{ +	unregister_filesystem(&nfs4_fs_type); +} +#else +static int __init register_nfs4_fs(void) +{ +	return 0; +} + +static void unregister_nfs4_fs(void) +{ +}  #endif  static struct shrinker acl_shrinker = { @@ -337,12 +365,18 @@ int __init register_nfs_fs(void)  	if (ret < 0)  		goto error_0; -	ret = nfs_register_sysctl(); +	ret = register_nfs4_fs();  	if (ret < 0)  		goto error_1; + +	ret = nfs_register_sysctl(); +	if (ret < 0) +		goto error_2;  	register_shrinker(&acl_shrinker);  	return 0; +error_2: +	unregister_nfs4_fs();  error_1:  	unregister_filesystem(&nfs_fs_type);  error_0: @@ -356,6 +390,7 @@ void __exit unregister_nfs_fs(void)  {  	unregister_shrinker(&acl_shrinker);  	nfs_unregister_sysctl(); +	unregister_nfs4_fs();  	unregister_filesystem(&nfs_fs_type);  } @@ -2645,4 +2680,6 @@ MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 "  module_param(send_implementation_id, ushort, 0644);  MODULE_PARM_DESC(send_implementation_id,  		"Send implementation ID with NFSv4.1 exchange_id"); +MODULE_ALIAS("nfs4"); +  #endif /* CONFIG_NFS_V4 */ diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 5829d0ce7cf..e3b55372726 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1814,19 +1814,19 @@ int __init nfs_init_writepagecache(void)  	nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE,  						     nfs_wdata_cachep);  	if (nfs_wdata_mempool == NULL) -		return -ENOMEM; +		goto out_destroy_write_cache;  	nfs_cdata_cachep = kmem_cache_create("nfs_commit_data",  					     sizeof(struct nfs_commit_data),  					     0, SLAB_HWCACHE_ALIGN,  					     NULL);  	if (nfs_cdata_cachep == NULL) -		return -ENOMEM; +		goto out_destroy_write_mempool;  	nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT,  						      nfs_wdata_cachep);  	if (nfs_commit_mempool == NULL) -		return -ENOMEM; +		goto out_destroy_commit_cache;  	/*  	 * NFS congestion size, scale with available memory. @@ -1849,11 +1849,20 @@ int __init nfs_init_writepagecache(void)  		nfs_congestion_kb = 256*1024;  	return 0; + +out_destroy_commit_cache: +	kmem_cache_destroy(nfs_cdata_cachep); +out_destroy_write_mempool: +	mempool_destroy(nfs_wdata_mempool); +out_destroy_write_cache: +	kmem_cache_destroy(nfs_wdata_cachep); +	return -ENOMEM;  }  void nfs_destroy_writepagecache(void)  {  	mempool_destroy(nfs_commit_mempool); +	kmem_cache_destroy(nfs_cdata_cachep);  	mempool_destroy(nfs_wdata_mempool);  	kmem_cache_destroy(nfs_wdata_cachep);  } diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 6522cac6057..6a10812711c 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -676,17 +676,13 @@ static const struct super_operations nilfs_sops = {  	.alloc_inode    = nilfs_alloc_inode,  	.destroy_inode  = nilfs_destroy_inode,  	.dirty_inode    = nilfs_dirty_inode, -	/* .write_inode    = nilfs_write_inode, */ -	/* .drop_inode	  = nilfs_drop_inode, */  	.evict_inode    = nilfs_evict_inode,  	.put_super      = nilfs_put_super, -	/* .write_super    = nilfs_write_super, */  	.sync_fs        = nilfs_sync_fs,  	.freeze_fs	= nilfs_freeze,  	.unfreeze_fs	= nilfs_unfreeze,  	.statfs         = nilfs_statfs,  	.remount_fs     = nilfs_remount, -	/* .umount_begin */  	.show_options = nilfs_show_options  }; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 6eee4177807..be1267a34ce 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -107,8 +107,6 @@ struct the_nilfs {  	 * used for  	 * - loading the latest checkpoint exclusively.  	 * - allocating a new full segment. -	 * - protecting s_dirt in the super_block struct -	 *   (see nilfs_write_super) and the following fields.  	 */  	struct buffer_head     *ns_sbh[2];  	struct nilfs_super_block *ns_sbp[2]; diff --git a/fs/open.c b/fs/open.c index f3d96e7e7b1..e1f2cdb91a4 100644 --- a/fs/open.c +++ b/fs/open.c @@ -717,7 +717,7 @@ cleanup_all:  			 * here, so just reset the state.  			 */  			file_reset_write(f); -			mnt_drop_write(f->f_path.mnt); +			__mnt_drop_write(f->f_path.mnt);  		}  	}  cleanup_file: @@ -852,9 +852,10 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o  	int lookup_flags = 0;  	int acc_mode; -	if (!(flags & O_CREAT)) -		mode = 0; -	op->mode = mode; +	if (flags & O_CREAT) +		op->mode = (mode & S_IALLUGO) | S_IFREG; +	else +		op->mode = 0;  	/* Must never be set by userspace */  	flags &= ~FMODE_NONOTIFY; diff --git a/fs/super.c b/fs/super.c index b05cf47463d..0902cfa6a12 100644 --- a/fs/super.c +++ b/fs/super.c @@ -537,46 +537,6 @@ void drop_super(struct super_block *sb)  EXPORT_SYMBOL(drop_super);  /** - * sync_supers - helper for periodic superblock writeback - * - * Call the write_super method if present on all dirty superblocks in - * the system.  This is for the periodic writeback used by most older - * filesystems.  For data integrity superblock writeback use - * sync_filesystems() instead. - * - * Note: check the dirty flag before waiting, so we don't - * hold up the sync while mounting a device. (The newly - * mounted device won't need syncing.) - */ -void sync_supers(void) -{ -	struct super_block *sb, *p = NULL; - -	spin_lock(&sb_lock); -	list_for_each_entry(sb, &super_blocks, s_list) { -		if (hlist_unhashed(&sb->s_instances)) -			continue; -		if (sb->s_op->write_super && sb->s_dirt) { -			sb->s_count++; -			spin_unlock(&sb_lock); - -			down_read(&sb->s_umount); -			if (sb->s_root && sb->s_dirt && (sb->s_flags & MS_BORN)) -				sb->s_op->write_super(sb); -			up_read(&sb->s_umount); - -			spin_lock(&sb_lock); -			if (p) -				__put_super(p); -			p = sb; -		} -	} -	if (p) -		__put_super(p); -	spin_unlock(&sb_lock); -} - -/**   *	iterate_supers - call function for all active superblocks   *	@f: function to call   *	@arg: argument to pass to it diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 35389ca2d26..7bd6e72afd1 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -37,11 +37,11 @@   *   * A thing to keep in mind: inode @i_mutex is locked in most VFS operations we   * implement. However, this is not true for 'ubifs_writepage()', which may be - * called with @i_mutex unlocked. For example, when pdflush is doing background - * write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. At "normal" - * work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. in the - * "sys_write -> alloc_pages -> direct reclaim path". So, in 'ubifs_writepage()' - * we are only guaranteed that the page is locked. + * called with @i_mutex unlocked. For example, when flusher thread is doing + * background write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. + * At "normal" work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. + * in the "sys_write -> alloc_pages -> direct reclaim path". So, in + * 'ubifs_writepage()' we are only guaranteed that the page is locked.   *   * Similarly, @i_mutex is not always locked in 'ubifs_readpage()', e.g., the   * read-ahead path does not lock it ("sys_read -> generic_file_aio_read -> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 1c766c39c03..c3fa6c5327a 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -303,7 +303,7 @@ static int ubifs_write_inode(struct inode *inode, struct writeback_control *wbc)  	mutex_lock(&ui->ui_mutex);  	/*  	 * Due to races between write-back forced by budgeting -	 * (see 'sync_some_inodes()') and pdflush write-back, the inode may +	 * (see 'sync_some_inodes()') and background write-back, the inode may  	 * have already been synchronized, do not do this again. This might  	 * also happen if it was synchronized in an VFS operation, e.g.  	 * 'ubifs_link()'. diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 2c744c7a5b3..26a92fc28a5 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -491,11 +491,11 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 * slp_typ_a, u8 * slp_typ_b);  acpi_status acpi_enter_sleep_state_prep(u8 sleep_state); -acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state, u8 flags); +acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state);  ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)) -acpi_status acpi_leave_sleep_state_prep(u8 sleep_state, u8 flags); +acpi_status acpi_leave_sleep_state_prep(u8 sleep_state);  acpi_status acpi_leave_sleep_state(u8 sleep_state); diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 3af87de6a68..3d00bd5bd7e 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -803,7 +803,7 @@ typedef u8 acpi_adr_space_type;  /* Sleep function dispatch */ -typedef acpi_status(*ACPI_SLEEP_FUNCTION) (u8 sleep_state, u8 flags); +typedef acpi_status(*ACPI_SLEEP_FUNCTION) (u8 sleep_state);  struct acpi_sleep_functions {  	ACPI_SLEEP_FUNCTION legacy_function; diff --git a/include/asm-generic/mutex-xchg.h b/include/asm-generic/mutex-xchg.h index 580a6d35c70..c04e0db8a2d 100644 --- a/include/asm-generic/mutex-xchg.h +++ b/include/asm-generic/mutex-xchg.h @@ -26,7 +26,13 @@ static inline void  __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))  {  	if (unlikely(atomic_xchg(count, 0) != 1)) -		fail_fn(count); +		/* +		 * We failed to acquire the lock, so mark it contended +		 * to ensure that any waiting tasks are woken up by the +		 * unlock slow path. +		 */ +		if (likely(atomic_xchg(count, -1) != 1)) +			fail_fn(count);  }  /** @@ -43,7 +49,8 @@ static inline int  __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))  {  	if (unlikely(atomic_xchg(count, 0) != 1)) -		return fail_fn(count); +		if (likely(atomic_xchg(count, -1) != 1)) +			return fail_fn(count);  	return 0;  } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index a1a0386e016..ced362533e3 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -166,8 +166,6 @@ struct drm_display_mode {  	int crtc_vsync_start;  	int crtc_vsync_end;  	int crtc_vtotal; -	int crtc_hadjusted; -	int crtc_vadjusted;  	/* Driver private mode info */  	int private_size; diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 7ff5c99b163..c78bb997e2c 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -213,9 +213,12 @@  	{0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ +	{0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \  	{0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index 58056865b8e..dc3a8cd7db8 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h @@ -964,6 +964,8 @@ struct drm_radeon_cs {  #define RADEON_INFO_IB_VM_MAX_SIZE	0x0f  /* max pipes - needed for compute shaders */  #define RADEON_INFO_MAX_PIPES		0x10 +/* timestamp for GL_ARB_timer_query (OpenGL), returns the current GPU clock */ +#define RADEON_INFO_TIMESTAMP		0x11  struct drm_radeon_info {  	uint32_t		request; diff --git a/include/linux/Kbuild b/include/linux/Kbuild index d9a75447487..fa217607c58 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -391,6 +391,7 @@ header-y += v4l2-dv-timings.h  header-y += v4l2-mediabus.h  header-y += v4l2-subdev.h  header-y += veth.h +header-y += vfio.h  header-y += vhost.h  header-y += videodev2.h  header-y += virtio_9p.h diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 3ad510b2528..4f2a7622450 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -96,7 +96,7 @@ void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);  void acpi_numa_slit_init (struct acpi_table_slit *slit);  void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);  void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); -void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); +int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);  void acpi_numa_arch_fixup(void);  #ifdef CONFIG_ACPI_HOTPLUG_CPU diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index c97c6b9cd38..2a9a9abc912 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -124,7 +124,6 @@ void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages,  void bdi_start_background_writeback(struct backing_dev_info *bdi);  int bdi_writeback_thread(void *data);  int bdi_has_dirty_io(struct backing_dev_info *bdi); -void bdi_arm_supers_timer(void);  void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi);  void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2); diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 3c80885fa82..d323a4b4143 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -89,6 +89,12 @@  #define  BCMA_CC_CHIPST_4313_OTP_PRESENT	2  #define  BCMA_CC_CHIPST_4331_SPROM_PRESENT	2  #define  BCMA_CC_CHIPST_4331_OTP_PRESENT	4 +#define  BCMA_CC_CHIPST_43228_ILP_DIV_EN	0x00000001 +#define  BCMA_CC_CHIPST_43228_OTP_PRESENT	0x00000002 +#define  BCMA_CC_CHIPST_43228_SERDES_REFCLK_PADSEL	0x00000004 +#define  BCMA_CC_CHIPST_43228_SDIO_MODE		0x00000008 +#define  BCMA_CC_CHIPST_43228_SDIO_OTP_PRESENT	0x00000010 +#define  BCMA_CC_CHIPST_43228_SDIO_RESET	0x00000020  #define  BCMA_CC_CHIPST_4706_PKG_OPTION		BIT(0) /* 0: full-featured package 1: low-cost package */  #define  BCMA_CC_CHIPST_4706_SFLASH_PRESENT	BIT(1) /* 0: parallel, 1: serial flash is present */  #define  BCMA_CC_CHIPST_4706_SFLASH_TYPE	BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ diff --git a/include/linux/can.h b/include/linux/can.h index 018055efc03..e52958d7c2d 100644 --- a/include/linux/can.h +++ b/include/linux/can.h @@ -74,20 +74,21 @@ struct can_frame {  /*   * defined bits for canfd_frame.flags   * - * As the default for CAN FD should be to support the high data rate in the - * payload section of the frame (HDR) and to support up to 64 byte in the - * data section (EDL) the bits are only set in the non-default case. - * Btw. as long as there's no real implementation for CAN FD network driver - * these bits are only preliminary. + * The use of struct canfd_frame implies the Extended Data Length (EDL) bit to + * be set in the CAN frame bitstream on the wire. The EDL bit switch turns + * the CAN controllers bitstream processor into the CAN FD mode which creates + * two new options within the CAN FD frame specification:   * - * RX: NOHDR/NOEDL - info about received CAN FD frame - *     ESI         - bit from originating CAN controller - * TX: NOHDR/NOEDL - control per-frame settings if supported by CAN controller - *     ESI         - bit is set by local CAN controller + * Bit Rate Switch - to indicate a second bitrate is/was used for the payload + * Error State Indicator - represents the error state of the transmitting node + * + * As the CANFD_ESI bit is internally generated by the transmitting CAN + * controller only the CANFD_BRS bit is relevant for real CAN controllers when + * building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make + * sense for virtual CAN interfaces to test applications with echoed frames.   */ -#define CANFD_NOHDR 0x01 /* frame without high data rate */ -#define CANFD_NOEDL 0x02 /* frame without extended data length */ -#define CANFD_ESI   0x04 /* error state indicator */ +#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ +#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */  /**   * struct canfd_frame - CAN flexible data rate frame structure diff --git a/include/linux/compaction.h b/include/linux/compaction.h index 133ddcf8339..ef658147e4e 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h @@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write,  extern int fragmentation_index(struct zone *zone, unsigned int order);  extern unsigned long try_to_compact_pages(struct zonelist *zonelist,  			int order, gfp_t gfp_mask, nodemask_t *mask, -			bool sync); +			bool sync, bool *contended);  extern int compact_pgdat(pg_data_t *pgdat, int order);  extern unsigned long compaction_suitable(struct zone *zone, int order); @@ -64,7 +64,7 @@ static inline bool compaction_deferred(struct zone *zone, int order)  #else  static inline unsigned long try_to_compact_pages(struct zonelist *zonelist,  			int order, gfp_t gfp_mask, nodemask_t *nodemask, -			bool sync) +			bool sync, bool *contended)  {  	return COMPACT_CONTINUE;  } diff --git a/include/linux/efi.h b/include/linux/efi.h index 103adc6d7e3..ec45ccd8708 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -503,6 +503,8 @@ extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size);  extern int __init efi_uart_console_only (void);  extern void efi_initialize_iomem_resources(struct resource *code_resource,  		struct resource *data_resource, struct resource *bss_resource); +extern unsigned long efi_get_time(void); +extern int efi_set_rtc_mmss(unsigned long nowtime);  extern void efi_reserve_boot_services(void);  extern struct efi_memory_map memmap; diff --git a/include/linux/fs.h b/include/linux/fs.h index 38dba16c417..aa110476a95 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1491,7 +1491,6 @@ struct sb_writers {  struct super_block {  	struct list_head	s_list;		/* Keep this first */  	dev_t			s_dev;		/* search index; _not_ kdev_t */ -	unsigned char		s_dirt;  	unsigned char		s_blocksize_bits;  	unsigned long		s_blocksize;  	loff_t			s_maxbytes;	/* Max file size */ @@ -1861,7 +1860,6 @@ struct super_operations {  	int (*drop_inode) (struct inode *);  	void (*evict_inode) (struct inode *);  	void (*put_super) (struct super_block *); -	void (*write_super) (struct super_block *);  	int (*sync_fs)(struct super_block *sb, int wait);  	int (*freeze_fs) (struct super_block *);  	int (*unfreeze_fs) (struct super_block *); @@ -2397,7 +2395,6 @@ extern int vfs_fsync_range(struct file *file, loff_t start, loff_t end,  			   int datasync);  extern int vfs_fsync(struct file *file, int datasync);  extern int generic_write_sync(struct file *file, loff_t pos, loff_t count); -extern void sync_supers(void);  extern void emergency_sync(void);  extern void emergency_remount(void);  #ifdef CONFIG_BLOCK diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index af961d6f7ab..642928cf57b 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -306,9 +306,10 @@ extern void *perf_trace_buf_prepare(int size, unsigned short type,  static inline void  perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr, -		       u64 count, struct pt_regs *regs, void *head) +		       u64 count, struct pt_regs *regs, void *head, +		       struct task_struct *task)  { -	perf_tp_event(addr, count, raw_data, size, regs, head, rctx); +	perf_tp_event(addr, count, raw_data, size, regs, head, rctx, task);  }  #endif diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 9303348965f..d8c713e148e 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -57,6 +57,9 @@   *   * 7.19   *  - add FUSE_FALLOCATE + * + * 7.20 + *  - add FUSE_AUTO_INVAL_DATA   */  #ifndef _LINUX_FUSE_H @@ -88,7 +91,7 @@  #define FUSE_KERNEL_VERSION 7  /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 19 +#define FUSE_KERNEL_MINOR_VERSION 20  /** The node ID of the root inode */  #define FUSE_ROOT_ID 1 @@ -163,10 +166,19 @@ struct fuse_file_lock {  /**   * INIT request/reply flags   * + * FUSE_ASYNC_READ: asynchronous read requests   * FUSE_POSIX_LOCKS: remote locking for POSIX file locks + * FUSE_FILE_OPS: kernel sends file handle for fstat, etc... (not yet supported) + * FUSE_ATOMIC_O_TRUNC: handles the O_TRUNC open flag in the filesystem   * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." + * FUSE_BIG_WRITES: filesystem can handle write size larger than 4kB   * FUSE_DONT_MASK: don't apply umask to file mode on create operations + * FUSE_SPLICE_WRITE: kernel supports splice write on the device + * FUSE_SPLICE_MOVE: kernel supports splice move on the device + * FUSE_SPLICE_READ: kernel supports splice read on the device   * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks + * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories + * FUSE_AUTO_INVAL_DATA: automatically invalidate cached pages   */  #define FUSE_ASYNC_READ		(1 << 0)  #define FUSE_POSIX_LOCKS	(1 << 1) @@ -175,7 +187,12 @@ struct fuse_file_lock {  #define FUSE_EXPORT_SUPPORT	(1 << 4)  #define FUSE_BIG_WRITES		(1 << 5)  #define FUSE_DONT_MASK		(1 << 6) +#define FUSE_SPLICE_WRITE	(1 << 7) +#define FUSE_SPLICE_MOVE	(1 << 8) +#define FUSE_SPLICE_READ	(1 << 9)  #define FUSE_FLOCK_LOCKS	(1 << 10) +#define FUSE_HAS_IOCTL_DIR	(1 << 11) +#define FUSE_AUTO_INVAL_DATA	(1 << 12)  /**   * CUSE INIT request/reply flags diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index bb7f3097185..305f23cd7cf 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -22,7 +22,7 @@   *   * - bits 16-25 are the hardirq count (max # of nested hardirqs: 1024)   * - bit 26 is the NMI_MASK - * - bit 28 is the PREEMPT_ACTIVE flag + * - bit 27 is the PREEMPT_ACTIVE flag   *   * PREEMPT_MASK: 0x000000ff   * SOFTIRQ_MASK: 0x0000ff00 diff --git a/include/linux/if_team.h b/include/linux/if_team.h index 6960fc1841a..aa2e167e1ef 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -96,21 +96,6 @@ static inline void team_netpoll_send_skb(struct team_port *port,  }  #endif -static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, -				      struct sk_buff *skb) -{ -	BUILD_BUG_ON(sizeof(skb->queue_mapping) != -		     sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); -	skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping); - -	skb->dev = port->dev; -	if (unlikely(netpoll_tx_running(port->dev))) { -		team_netpoll_send_skb(port, skb); -		return 0; -	} -	return dev_queue_xmit(skb); -} -  struct team_mode_ops {  	int (*init)(struct team *team);  	void (*exit)(struct team *team); @@ -200,6 +185,21 @@ struct team {  	long mode_priv[TEAM_MODE_PRIV_LONGS];  }; +static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, +				      struct sk_buff *skb) +{ +	BUILD_BUG_ON(sizeof(skb->queue_mapping) != +		     sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping)); +	skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping); + +	skb->dev = port->dev; +	if (unlikely(netpoll_tx_running(team->dev))) { +		team_netpoll_send_skb(port, skb); +		return 0; +	} +	return dev_queue_xmit(skb); +} +  static inline struct hlist_head *team_port_index_hash(struct team *team,  						      int port_index)  { diff --git a/include/linux/iio/frequency/adf4350.h b/include/linux/iio/frequency/adf4350.h index b76b4a87065..be91f344d5f 100644 --- a/include/linux/iio/frequency/adf4350.h +++ b/include/linux/iio/frequency/adf4350.h @@ -87,6 +87,8 @@  #define ADF4350_MAX_BANDSEL_CLK		125000 /* Hz */  #define ADF4350_MAX_FREQ_REFIN		250000000 /* Hz */  #define ADF4350_MAX_MODULUS		4095 +#define ADF4350_MAX_R_CNT		1023 +  /**   * struct adf4350_platform_data - platform specific information diff --git a/include/linux/input/eeti_ts.h b/include/linux/input/eeti_ts.h index f875b316249..16625d799b6 100644 --- a/include/linux/input/eeti_ts.h +++ b/include/linux/input/eeti_ts.h @@ -2,6 +2,7 @@  #define LINUX_INPUT_EETI_TS_H  struct eeti_ts_platform_data { +	int irq_gpio;  	unsigned int irq_active_high;  }; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 54d6d690073..7e83370e6fd 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -20,6 +20,7 @@  #define __LINUX_IOMMU_H  #include <linux/errno.h> +#include <linux/types.h>  #define IOMMU_READ	(1)  #define IOMMU_WRITE	(2) @@ -30,6 +31,7 @@ struct iommu_group;  struct bus_type;  struct device;  struct iommu_domain; +struct notifier_block;  /* iommu fault flags */  #define IOMMU_FAULT_READ	0x0 diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 379e433e15e..879db26ec40 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -369,6 +369,7 @@ struct ipv6_pinfo {  	__u8			rcv_tclass;  	__u32			dst_cookie; +	__u32			rx_dst_cookie;  	struct ipv6_mc_socklist	__rcu *ipv6_mc_list;  	struct ipv6_ac_socklist	*ipv6_ac_list; diff --git a/include/linux/irq.h b/include/linux/irq.h index 553fb66da13..216b0ba109d 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -349,6 +349,7 @@ enum {  	IRQCHIP_MASK_ON_SUSPEND		= (1 <<  2),  	IRQCHIP_ONOFFLINE_ENABLED	= (1 <<  3),  	IRQCHIP_SKIP_SET_WAKE		= (1 <<  4), +	IRQCHIP_ONESHOT_SAFE		= (1 <<  5),  };  /* This include will go away once we isolated irq_desc usage to core code */ diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index f334c7fab96..3efc43f3f16 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1125,6 +1125,7 @@ extern int	   jbd2_journal_destroy    (journal_t *);  extern int	   jbd2_journal_recover    (journal_t *journal);  extern int	   jbd2_journal_wipe       (journal_t *, int);  extern int	   jbd2_journal_skip_recovery	(journal_t *); +extern void	   jbd2_journal_update_sb_errno(journal_t *);  extern void	   jbd2_journal_update_sb_log_tail	(journal_t *, tid_t,  				unsigned long, int);  extern void	   __jbd2_journal_abort_hard	(journal_t *); diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 265e2c3cbd1..82680541576 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -39,9 +39,6 @@  # error Invalid value of HZ.  #endif -/* LATCH is used in the interval timer and ftape setup. */ -#define LATCH  ((CLOCK_TICK_RATE + HZ/2) / HZ)	/* For divider */ -  /* Suppose we want to divide two numbers NOM and DEN: NOM/DEN, then we can   * improve accuracy by shifting LSH bits, hence calculating:   *     (NOM << LSH) / DEN @@ -54,18 +51,30 @@  #define SH_DIV(NOM,DEN,LSH) (   (((NOM) / (DEN)) << (LSH))              \                               + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) -/* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ -#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) +#ifdef CLOCK_TICK_RATE +/* LATCH is used in the interval timer and ftape setup. */ +# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ)	/* For divider */ + +/* + * HZ is the requested value. However the CLOCK_TICK_RATE may not allow + * for exactly HZ. So SHIFTED_HZ is high res HZ ("<< 8" is for accuracy) + */ +# define SHIFTED_HZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8)) +#else +# define SHIFTED_HZ (HZ << 8) +#endif -/* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */ -#define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8)) +/* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */ +#define TICK_NSEC (SH_DIV(1000000UL * 1000, SHIFTED_HZ, 8))  /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */  #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ) -/* TICK_USEC_TO_NSEC is the time between ticks in nsec assuming real ACTHZ and	*/ -/* a value TUSEC for TICK_USEC (can be set bij adjtimex)		*/ -#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8)) +/* + * TICK_USEC_TO_NSEC is the time between ticks in nsec assuming SHIFTED_HZ and + * a value TUSEC for TICK_USEC (can be set bij adjtimex) + */ +#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV(TUSEC * USER_HZ * 1000, SHIFTED_HZ, 8))  /* some arch's have a small-data section that can be accessed register-relative   * but that can only take up to, say, 4-byte variables. jiffies being part of diff --git a/include/linux/kdb.h b/include/linux/kdb.h index 064725854db..42d9e863a31 100644 --- a/include/linux/kdb.h +++ b/include/linux/kdb.h @@ -75,8 +75,6 @@ extern const char *kdb_diemsg;  #define KDB_FLAG_CATASTROPHIC	(1 << 1) /* A catastrophic event has occurred */  #define KDB_FLAG_CMD_INTERRUPT	(1 << 2) /* Previous command was interrupted */  #define KDB_FLAG_NOIPI		(1 << 3) /* Do not send IPIs */ -#define KDB_FLAG_ONLY_DO_DUMP	(1 << 4) /* Only do a dump, used when -					  * kdb is off */  #define KDB_FLAG_NO_CONSOLE	(1 << 5) /* No console is available,  					  * kdb is disabled */  #define KDB_FLAG_NO_VT_CONSOLE	(1 << 6) /* No VT console is available, do diff --git a/include/linux/kref.h b/include/linux/kref.h index 9c07dcebded..65af6887872 100644 --- a/include/linux/kref.h +++ b/include/linux/kref.h @@ -18,6 +18,7 @@  #include <linux/bug.h>  #include <linux/atomic.h>  #include <linux/kernel.h> +#include <linux/mutex.h>  struct kref {  	atomic_t refcount; @@ -93,4 +94,21 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)  {  	return kref_sub(kref, 1, release);  } + +static inline int kref_put_mutex(struct kref *kref, +				 void (*release)(struct kref *kref), +				 struct mutex *lock) +{ +	WARN_ON(release == NULL); +        if (unlikely(!atomic_add_unless(&kref->refcount, -1, 1))) { +		mutex_lock(lock); +		if (unlikely(!atomic_dec_and_test(&kref->refcount))) { +			mutex_unlock(lock); +			return 0; +		} +		release(kref); +		return 1; +	} +	return 0; +}  #endif /* _KREF_H_ */ diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h index 40c372165f3..32a1b5cfeba 100644 --- a/include/linux/mfd/ezx-pcap.h +++ b/include/linux/mfd/ezx-pcap.h @@ -16,6 +16,7 @@ struct pcap_subdev {  struct pcap_platform_data {  	unsigned int irq_base;  	unsigned int config; +	int gpio;  	void (*init) (void *);	/* board specific init */  	int num_subdevs;  	struct pcap_subdev *subdevs; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index eb06e58bed0..59dc05f3824 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -953,7 +953,8 @@ struct net_device_ops {  #ifdef CONFIG_NET_POLL_CONTROLLER  	void                    (*ndo_poll_controller)(struct net_device *dev);  	int			(*ndo_netpoll_setup)(struct net_device *dev, -						     struct netpoll_info *info); +						     struct netpoll_info *info, +						     gfp_t gfp);  	void			(*ndo_netpoll_cleanup)(struct net_device *dev);  #endif  	int			(*ndo_set_vf_mac)(struct net_device *dev, @@ -1300,6 +1301,8 @@ struct net_device {  	/* for setting kernel sock attribute on TCP connection setup */  #define GSO_MAX_SIZE		65536  	unsigned int		gso_max_size; +#define GSO_MAX_SEGS		65535 +	u16			gso_max_segs;  #ifdef CONFIG_DCB  	/* Data Center Bridging netlink ops */ @@ -1519,6 +1522,8 @@ struct packet_type {  	struct sk_buff		**(*gro_receive)(struct sk_buff **head,  					       struct sk_buff *skb);  	int			(*gro_complete)(struct sk_buff *skb); +	bool			(*id_match)(struct packet_type *ptype, +					    struct sock *sk);  	void			*af_packet_priv;  	struct list_head	list;  }; diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h index 0dfc8b7210a..89f2a627f3f 100644 --- a/include/linux/netfilter/nf_conntrack_sip.h +++ b/include/linux/netfilter/nf_conntrack_sip.h @@ -164,7 +164,7 @@ extern int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr  				      unsigned int dataoff, unsigned int datalen,  				      const char *name,  				      unsigned int *matchoff, unsigned int *matchlen, -				      union nf_inet_addr *addr); +				      union nf_inet_addr *addr, bool delim);  extern int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,  					unsigned int off, unsigned int datalen,  					const char *name, diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index 28f5389c924..66d5379c305 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -23,6 +23,7 @@ struct netpoll {  	u8 remote_mac[ETH_ALEN];  	struct list_head rx; /* rx_np list element */ +	struct rcu_head rcu;  };  struct netpoll_info { @@ -38,28 +39,40 @@ struct netpoll_info {  	struct delayed_work tx_work;  	struct netpoll *netpoll; +	struct rcu_head rcu;  };  void netpoll_send_udp(struct netpoll *np, const char *msg, int len);  void netpoll_print_options(struct netpoll *np);  int netpoll_parse_options(struct netpoll *np, char *opt); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev); +int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp);  int netpoll_setup(struct netpoll *np);  int netpoll_trap(void);  void netpoll_set_trap(int trap);  void __netpoll_cleanup(struct netpoll *np); +void __netpoll_free_rcu(struct netpoll *np);  void netpoll_cleanup(struct netpoll *np); -int __netpoll_rx(struct sk_buff *skb); +int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo);  void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,  			     struct net_device *dev);  static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)  { +	unsigned long flags; +	local_irq_save(flags);  	netpoll_send_skb_on_dev(np, skb, np->dev); +	local_irq_restore(flags);  }  #ifdef CONFIG_NETPOLL +static inline bool netpoll_rx_on(struct sk_buff *skb) +{ +	struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); + +	return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); +} +  static inline bool netpoll_rx(struct sk_buff *skb)  {  	struct netpoll_info *npinfo; @@ -67,14 +80,14 @@ static inline bool netpoll_rx(struct sk_buff *skb)  	bool ret = false;  	local_irq_save(flags); -	npinfo = rcu_dereference_bh(skb->dev->npinfo); -	if (!npinfo || (list_empty(&npinfo->rx_np) && !npinfo->rx_flags)) +	if (!netpoll_rx_on(skb))  		goto out; +	npinfo = rcu_dereference_bh(skb->dev->npinfo);  	spin_lock(&npinfo->rx_lock);  	/* check rx_flags again with the lock held */ -	if (npinfo->rx_flags && __netpoll_rx(skb)) +	if (npinfo->rx_flags && __netpoll_rx(skb, npinfo))  		ret = true;  	spin_unlock(&npinfo->rx_lock); @@ -83,13 +96,6 @@ out:  	return ret;  } -static inline int netpoll_rx_on(struct sk_buff *skb) -{ -	struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo); - -	return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags); -} -  static inline int netpoll_receive_skb(struct sk_buff *skb)  {  	if (!list_empty(&skb->dev->napi_list)) @@ -119,7 +125,7 @@ static inline void netpoll_poll_unlock(void *have)  	}  } -static inline int netpoll_tx_running(struct net_device *dev) +static inline bool netpoll_tx_running(struct net_device *dev)  {  	return irqs_disabled();  } @@ -127,11 +133,11 @@ static inline int netpoll_tx_running(struct net_device *dev)  #else  static inline bool netpoll_rx(struct sk_buff *skb)  { -	return 0; +	return false;  } -static inline int netpoll_rx_on(struct sk_buff *skb) +static inline bool netpoll_rx_on(struct sk_buff *skb)  { -	return 0; +	return false;  }  static inline int netpoll_receive_skb(struct sk_buff *skb)  { @@ -147,9 +153,9 @@ static inline void netpoll_poll_unlock(void *have)  static inline void netpoll_netdev_init(struct net_device *dev)  {  } -static inline int netpoll_tx_running(struct net_device *dev) +static inline bool netpoll_tx_running(struct net_device *dev)  { -	return 0; +	return false;  }  #endif diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 880805774f9..92ce5783b70 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h @@ -69,6 +69,7 @@ struct nfs_pageio_descriptor {  	const struct nfs_pgio_completion_ops *pg_completion_ops;  	struct pnfs_layout_segment *pg_lseg;  	struct nfs_direct_req	*pg_dreq; +	void			*pg_layout_private;  };  #define NFS_WBACK_BUSY(req)	(test_bit(PG_BUSY,&(req)->wb_flags)) diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 00485e08439..ac7c8ae254f 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -1248,6 +1248,7 @@ struct nfs_pgio_header {  	void (*release) (struct nfs_pgio_header *hdr);  	const struct nfs_pgio_completion_ops *completion_ops;  	struct nfs_direct_req	*dreq; +	void			*layout_private;  	spinlock_t		lock;  	/* fields protected by lock */  	int			pnfs_error; diff --git a/include/linux/of.h b/include/linux/of.h index 5919ee33f2b..1b1163225f3 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -190,10 +190,17 @@ extern struct device_node *of_get_parent(const struct device_node *node);  extern struct device_node *of_get_next_parent(struct device_node *node);  extern struct device_node *of_get_next_child(const struct device_node *node,  					     struct device_node *prev); +extern struct device_node *of_get_next_available_child( +	const struct device_node *node, struct device_node *prev); +  #define for_each_child_of_node(parent, child) \  	for (child = of_get_next_child(parent, NULL); child != NULL; \  	     child = of_get_next_child(parent, child)) +#define for_each_available_child_of_node(parent, child) \ +	for (child = of_get_next_available_child(parent, NULL); child != NULL; \ +	     child = of_get_next_available_child(parent, child)) +  static inline int of_get_child_count(const struct device_node *np)  {  	struct device_node *child; diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 76c5c8b724a..7602ccb3f40 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1272,7 +1272,8 @@ static inline bool perf_paranoid_kernel(void)  extern void perf_event_init(void);  extern void perf_tp_event(u64 addr, u64 count, void *record,  			  int entry_size, struct pt_regs *regs, -			  struct hlist_head *head, int rctx); +			  struct hlist_head *head, int rctx, +			  struct task_struct *task);  extern void perf_bp_event(struct perf_event *event, void *data);  #ifndef perf_misc_flags diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h index 6dd96fb4548..e9b7f435084 100644 --- a/include/linux/pinctrl/consumer.h +++ b/include/linux/pinctrl/consumer.h @@ -20,6 +20,7 @@  /* This struct is private to the core and should be regarded as a cookie */  struct pinctrl;  struct pinctrl_state; +struct device;  #ifdef CONFIG_PINCTRL diff --git a/include/linux/sched.h b/include/linux/sched.h index c147e7024f1..b8c86648a2f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -334,14 +334,6 @@ static inline void lockup_detector_init(void)  }  #endif -#if defined(CONFIG_LOCKUP_DETECTOR) && defined(CONFIG_SUSPEND) -void lockup_detector_bootcpu_resume(void); -#else -static inline void lockup_detector_bootcpu_resume(void) -{ -} -#endif -  #ifdef CONFIG_DETECT_HUNG_TASK  extern unsigned int  sysctl_hung_task_panic;  extern unsigned long sysctl_hung_task_check_count; diff --git a/include/linux/security.h b/include/linux/security.h index 4e5a73cdbbe..3dea6a9d568 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1242,8 +1242,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)   *	Check that the @parent process has sufficient permission to trace the   *	current process before allowing the current process to present itself   *	to the @parent process for tracing. - *	The parent process will still have to undergo the ptrace_access_check - *	checks before it is allowed to trace this one.   *	@parent contains the task_struct structure for debugger process.   *	Return 0 if permission is granted.   * @capget: diff --git a/include/linux/string.h b/include/linux/string.h index ffe0442e18d..b9178812d9d 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -144,8 +144,8 @@ static inline bool strstarts(const char *str, const char *prefix)  {  	return strncmp(str, prefix, strlen(prefix)) == 0;  } -#endif  extern size_t memweight(const void *ptr, size_t bytes); +#endif /* __KERNEL__ */  #endif /* _LINUX_STRING_H_ */ diff --git a/include/linux/timex.h b/include/linux/timex.h index 99bc88b1fc0..7c5ceb20e03 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h @@ -232,7 +232,7 @@ struct timex {   * estimated error = NTP dispersion.   */  extern unsigned long tick_usec;		/* USER_HZ period (usec) */ -extern unsigned long tick_nsec;		/* ACTHZ          period (nsec) */ +extern unsigned long tick_nsec;		/* SHIFTED_HZ period (nsec) */  extern void ntp_init(void);  extern void ntp_clear(void); diff --git a/include/linux/topology.h b/include/linux/topology.h index e91cd43394d..fec12d66721 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -164,6 +164,7 @@ int arch_update_cpu_topology(void);  				| 0*SD_SHARE_CPUPOWER			\  				| 0*SD_SHARE_PKG_RESOURCES		\  				| 0*SD_SERIALIZE			\ +				| 1*SD_PREFER_SIBLING			\  				,					\  	.last_balance		= jiffies,				\  	.balance_interval	= 1,					\ diff --git a/include/linux/writeback.h b/include/linux/writeback.h index c66fe3332d8..50c3e8fa06a 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -104,7 +104,6 @@ static inline void wait_on_inode(struct inode *inode)  	wait_on_bit(&inode->i_state, __I_NEW, inode_wait, TASK_UNINTERRUPTIBLE);  } -  /*   * mm/page-writeback.c   */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 493fa0c7900..3d254e10ff3 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -96,6 +96,7 @@ enum ieee80211_band {   * 	is not permitted.   * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel   * 	is not permitted. + * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel.   */  enum ieee80211_channel_flags {  	IEEE80211_CHAN_DISABLED		= 1<<0, @@ -104,6 +105,7 @@ enum ieee80211_channel_flags {  	IEEE80211_CHAN_RADAR		= 1<<3,  	IEEE80211_CHAN_NO_HT40PLUS	= 1<<4,  	IEEE80211_CHAN_NO_HT40MINUS	= 1<<5, +	IEEE80211_CHAN_NO_OFDM		= 1<<6,  };  #define IEEE80211_CHAN_NO_HT40 \ diff --git a/include/net/codel.h b/include/net/codel.h index 550debfc240..389cf621161 100644 --- a/include/net/codel.h +++ b/include/net/codel.h @@ -305,6 +305,8 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,  			}  		}  	} else if (drop) { +		u32 delta; +  		if (params->ecn && INET_ECN_set_ce(skb)) {  			stats->ecn_mark++;  		} else { @@ -320,9 +322,11 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,  		 * assume that the drop rate that controlled the queue on the  		 * last cycle is a good starting point to control it now.  		 */ -		if (codel_time_before(now - vars->drop_next, +		delta = vars->count - vars->lastcount; +		if (delta > 1 && +		    codel_time_before(now - vars->drop_next,  				      16 * params->interval)) { -			vars->count = (vars->count - vars->lastcount) | 1; +			vars->count = delta;  			/* we dont care if rec_inv_sqrt approximation  			 * is not very precise :  			 * Next Newton steps will correct it quadratically. diff --git a/include/net/dst.h b/include/net/dst.h index baf59789006..621e3513ef5 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -110,7 +110,7 @@ struct dst_entry {  };  extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); -extern const u32 dst_default_metrics[RTAX_MAX]; +extern const u32 dst_default_metrics[];  #define DST_METRICS_READ_ONLY	0x1UL  #define __DST_METRICS_PTR(Y)	\ diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 5ee66f517b4..ba1d3615acb 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -39,6 +39,7 @@ struct inet_connection_sock_af_ops {  	int	    (*queue_xmit)(struct sk_buff *skb, struct flowi *fl);  	void	    (*send_check)(struct sock *sk, struct sk_buff *skb);  	int	    (*rebuild_header)(struct sock *sk); +	void	    (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb);  	int	    (*conn_request)(struct sock *sk, struct sk_buff *skb);  	struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,  				      struct request_sock *req, diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 83b567fe194..613cfa40167 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -249,13 +249,4 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk)  	return flags;  } -static inline void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) -{ -	struct dst_entry *dst = skb_dst(skb); - -	dst_hold(dst); -	sk->sk_rx_dst = dst; -	inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; -} -  #endif	/* _INET_SOCK_H */ diff --git a/include/net/ip.h b/include/net/ip.h index bd5e444a19c..5a5d84d3d2c 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -120,7 +120,7 @@ extern struct sk_buff  *__ip_make_skb(struct sock *sk,  				      struct flowi4 *fl4,  				      struct sk_buff_head *queue,  				      struct inet_cork *cork); -extern int		ip_send_skb(struct sk_buff *skb); +extern int		ip_send_skb(struct net *net, struct sk_buff *skb);  extern int		ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4);  extern void		ip_flush_pending_frames(struct sock *sk);  extern struct sk_buff  *ip_make_skb(struct sock *sk, diff --git a/include/net/llc.h b/include/net/llc.h index 226c846cab0..f2d0fc57052 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -133,7 +133,7 @@ extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,  extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);  extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); -extern int llc_station_init(void); +extern void llc_station_init(void);  extern void llc_station_exit(void);  #ifdef CONFIG_PROC_FS diff --git a/include/net/scm.h b/include/net/scm.h index 079d7887dac..7dc0854f0b3 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -70,9 +70,11 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)  }  static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, -			       struct scm_cookie *scm) +			       struct scm_cookie *scm, bool forcecreds)  {  	memset(scm, 0, sizeof(*scm)); +	if (forcecreds) +		scm_set_cred(scm, task_tgid(current), current_cred());  	unix_get_peersec_dgram(sock, scm);  	if (msg->msg_controllen <= 0)  		return 0; diff --git a/include/net/sock.h b/include/net/sock.h index b3730239bf1..72132aef53f 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -218,6 +218,7 @@ struct cg_proto;    *	@sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)    *	@sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)    *	@sk_gso_max_size: Maximum GSO segment size to build +  *	@sk_gso_max_segs: Maximum number of GSO segments    *	@sk_lingertime: %SO_LINGER l_linger setting    *	@sk_backlog: always used with the per-socket spinlock held    *	@sk_callback_lock: used with the callbacks in the end of this struct @@ -338,6 +339,7 @@ struct sock {  	netdev_features_t	sk_route_nocaps;  	int			sk_gso_type;  	unsigned int		sk_gso_max_size; +	u16			sk_gso_max_segs;  	int			sk_rcvlowat;  	unsigned long	        sk_lingertime;  	struct sk_buff_head	sk_error_queue; diff --git a/include/net/tcp.h b/include/net/tcp.h index e19124b84cd..1f000ffe707 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -464,6 +464,7 @@ extern int tcp_disconnect(struct sock *sk, int flags);  void tcp_connect_init(struct sock *sk);  void tcp_finish_connect(struct sock *sk, struct sk_buff *skb);  int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size); +void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb);  /* From syncookies.c */  extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; diff --git a/include/net/xfrm.h b/include/net/xfrm.h index d9509eb29b8..976a81abe1a 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -213,6 +213,9 @@ struct xfrm_state {  	struct xfrm_lifetime_cur curlft;  	struct tasklet_hrtimer	mtimer; +	/* used to fix curlft->add_time when changing date */ +	long		saved_tmo; +  	/* Last used time */  	unsigned long		lastused; @@ -238,6 +241,7 @@ static inline struct net *xs_net(struct xfrm_state *x)  /* xflags - make enum if more show up */  #define XFRM_TIME_DEFER	1 +#define XFRM_SOFT_EXPIRE 2  enum {  	XFRM_STATE_VOID, @@ -288,6 +292,8 @@ struct xfrm_policy_afinfo {  						  struct flowi *fl,  						  int reverse);  	int			(*get_tos)(const struct flowi *fl); +	void			(*init_dst)(struct net *net, +					    struct xfrm_dst *dst);  	int			(*init_path)(struct xfrm_dst *path,  					     struct dst_entry *dst,  					     int nfheader_len); diff --git a/include/sound/pcm.h b/include/sound/pcm.h index c75c0d1a85e..cdca2ab1e71 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1075,7 +1075,8 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)  const char *snd_pcm_format_name(snd_pcm_format_t format);  /** - * Get a string naming the direction of a stream + * snd_pcm_stream_str - Get a string naming the direction of a stream + * @substream: the pcm substream instance   */  static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream)  { diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 128ce46fa48..015cea01ae3 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -503,8 +503,6 @@ struct se_cmd {  	u32			se_ordered_id;  	/* Total size in bytes associated with command */  	u32			data_length; -	/* SCSI Presented Data Transfer Length */ -	u32			cmd_spdtl;  	u32			residual_count;  	u32			orig_fe_lun;  	/* Persistent Reservation key */ diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index ea7a2035456..5a8671e8a67 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -73,6 +73,9 @@ DECLARE_EVENT_CLASS(sched_wakeup_template,  		__entry->prio		= p->prio;  		__entry->success	= success;  		__entry->target_cpu	= task_cpu(p); +	) +	TP_perf_assign( +		__perf_task(p);  	),  	TP_printk("comm=%s pid=%d prio=%d success=%d target_cpu=%03d", @@ -325,6 +328,7 @@ DECLARE_EVENT_CLASS(sched_stat_template,  	)  	TP_perf_assign(  		__perf_count(delay); +		__perf_task(tsk);  	),  	TP_printk("comm=%s pid=%d delay=%Lu [ns]", diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index c6bc2faaf26..a763888a36f 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -712,6 +712,9 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call  #undef __perf_count  #define __perf_count(c) __count = (c) +#undef __perf_task +#define __perf_task(t) __task = (t) +  #undef TP_perf_assign  #define TP_perf_assign(args...) args @@ -725,6 +728,7 @@ perf_trace_##call(void *__data, proto)					\  	struct ftrace_raw_##call *entry;				\  	struct pt_regs __regs;						\  	u64 __addr = 0, __count = 1;					\ +	struct task_struct *__task = NULL;				\  	struct hlist_head *head;					\  	int __entry_size;						\  	int __data_size;						\ @@ -752,7 +756,7 @@ perf_trace_##call(void *__data, proto)					\  									\  	head = this_cpu_ptr(event_call->perf_events);			\  	perf_trace_buf_submit(entry, __entry_size, rctx, __addr,	\ -		__count, &__regs, head);				\ +		__count, &__regs, head, __task);			\  }  /* diff --git a/init/main.c b/init/main.c index e60679de61c..b28673087ac 100644 --- a/init/main.c +++ b/init/main.c @@ -461,10 +461,6 @@ static void __init mm_init(void)  	percpu_init_late();  	pgtable_cache_init();  	vmalloc_init(); -#ifdef CONFIG_X86 -	if (efi_enabled) -		efi_enter_virtual_mode(); -#endif  }  asmlinkage void __init start_kernel(void) @@ -606,6 +602,10 @@ asmlinkage void __init start_kernel(void)  	calibrate_delay();  	pidmap_init();  	anon_vma_init(); +#ifdef CONFIG_X86 +	if (efi_enabled) +		efi_enter_virtual_mode(); +#endif  	thread_info_cache_init();  	cred_init();  	fork_init(totalram_pages); diff --git a/ipc/mqueue.c b/ipc/mqueue.c index f8e54f5b908..9a08acc9e64 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -726,7 +726,6 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir,  			struct mq_attr *attr)  {  	const struct cred *cred = current_cred(); -	struct file *result;  	int ret;  	if (attr) { @@ -748,21 +747,11 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir,  	}  	mode &= ~current_umask(); -	ret = mnt_want_write(path->mnt); -	if (ret) -		return ERR_PTR(ret);  	ret = vfs_create(dir, path->dentry, mode, true);  	path->dentry->d_fsdata = NULL; -	if (!ret) -		result = dentry_open(path, oflag, cred); -	else -		result = ERR_PTR(ret); -	/* -	 * dentry_open() took a persistent mnt_want_write(), -	 * so we can now drop this one. -	 */ -	mnt_drop_write(path->mnt); -	return result; +	if (ret) +		return ERR_PTR(ret); +	return dentry_open(path, oflag, cred);  }  /* Opens existing queue */ @@ -788,7 +777,9 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  	struct mq_attr attr;  	int fd, error;  	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; -	struct dentry *root = ipc_ns->mq_mnt->mnt_root; +	struct vfsmount *mnt = ipc_ns->mq_mnt; +	struct dentry *root = mnt->mnt_root; +	int ro;  	if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))  		return -EFAULT; @@ -802,6 +793,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  	if (fd < 0)  		goto out_putname; +	ro = mnt_want_write(mnt);	/* we'll drop it in any case */  	error = 0;  	mutex_lock(&root->d_inode->i_mutex);  	path.dentry = lookup_one_len(name, root, strlen(name)); @@ -809,7 +801,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  		error = PTR_ERR(path.dentry);  		goto out_putfd;  	} -	path.mnt = mntget(ipc_ns->mq_mnt); +	path.mnt = mntget(mnt);  	if (oflag & O_CREAT) {  		if (path.dentry->d_inode) {	/* entry already exists */ @@ -820,6 +812,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,  			}  			filp = do_open(&path, oflag);  		} else { +			if (ro) { +				error = ro; +				goto out; +			}  			filp = do_create(ipc_ns, root->d_inode,  						&path, oflag, mode,  						u_attr ? &attr : NULL); @@ -845,6 +841,7 @@ out_putfd:  		fd = error;  	}  	mutex_unlock(&root->d_inode->i_mutex); +	mnt_drop_write(mnt);  out_putname:  	putname(name);  	return fd; @@ -857,40 +854,38 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)  	struct dentry *dentry;  	struct inode *inode = NULL;  	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; +	struct vfsmount *mnt = ipc_ns->mq_mnt;  	name = getname(u_name);  	if (IS_ERR(name))  		return PTR_ERR(name); -	mutex_lock_nested(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex, -			I_MUTEX_PARENT); -	dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); +	err = mnt_want_write(mnt); +	if (err) +		goto out_name; +	mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT); +	dentry = lookup_one_len(name, mnt->mnt_root, strlen(name));  	if (IS_ERR(dentry)) {  		err = PTR_ERR(dentry);  		goto out_unlock;  	} -	if (!dentry->d_inode) { -		err = -ENOENT; -		goto out_err; -	} -  	inode = dentry->d_inode; -	if (inode) +	if (!inode) { +		err = -ENOENT; +	} else {  		ihold(inode); -	err = mnt_want_write(ipc_ns->mq_mnt); -	if (err) -		goto out_err; -	err = vfs_unlink(dentry->d_parent->d_inode, dentry); -	mnt_drop_write(ipc_ns->mq_mnt); -out_err: +		err = vfs_unlink(dentry->d_parent->d_inode, dentry); +	}  	dput(dentry);  out_unlock: -	mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); -	putname(name); +	mutex_unlock(&mnt->mnt_root->d_inode->i_mutex);  	if (inode)  		iput(inode); +	mnt_drop_write(mnt); +out_name: +	putname(name);  	return err;  } diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 3a5ca582ba1..ed206fd88cc 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -250,7 +250,6 @@ static void untag_chunk(struct node *p)  		spin_unlock(&hash_lock);  		spin_unlock(&entry->lock);  		fsnotify_destroy_mark(entry); -		fsnotify_put_mark(entry);  		goto out;  	} @@ -259,7 +258,7 @@ static void untag_chunk(struct node *p)  	fsnotify_duplicate_mark(&new->mark, entry);  	if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) { -		free_chunk(new); +		fsnotify_put_mark(&new->mark);  		goto Fallback;  	} @@ -293,7 +292,7 @@ static void untag_chunk(struct node *p)  	spin_unlock(&hash_lock);  	spin_unlock(&entry->lock);  	fsnotify_destroy_mark(entry); -	fsnotify_put_mark(entry); +	fsnotify_put_mark(&new->mark);	/* drop initial reference */  	goto out;  Fallback: @@ -322,7 +321,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree)  	entry = &chunk->mark;  	if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) { -		free_chunk(chunk); +		fsnotify_put_mark(entry);  		return -ENOSPC;  	} @@ -347,6 +346,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree)  	insert_hash(chunk);  	spin_unlock(&hash_lock);  	spin_unlock(&entry->lock); +	fsnotify_put_mark(entry);	/* drop initial reference */  	return 0;  } @@ -396,7 +396,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)  	fsnotify_duplicate_mark(chunk_entry, old_entry);  	if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, NULL, 1)) {  		spin_unlock(&old_entry->lock); -		free_chunk(chunk); +		fsnotify_put_mark(chunk_entry);  		fsnotify_put_mark(old_entry);  		return -ENOSPC;  	} @@ -444,8 +444,8 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)  	spin_unlock(&chunk_entry->lock);  	spin_unlock(&old_entry->lock);  	fsnotify_destroy_mark(old_entry); +	fsnotify_put_mark(chunk_entry);	/* drop initial reference */  	fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ -	fsnotify_put_mark(old_entry); /* and kill it */  	return 0;  } @@ -916,7 +916,12 @@ static void audit_tree_freeing_mark(struct fsnotify_mark *entry, struct fsnotify  	struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark);  	evict_chunk(chunk); -	fsnotify_put_mark(entry); + +	/* +	 * We are guaranteed to have at least one reference to the mark from +	 * either the inode or the caller of fsnotify_destroy_mark(). +	 */ +	BUG_ON(atomic_read(&entry->refcnt) < 1);  }  static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, diff --git a/kernel/debug/kdb/kdb_debugger.c b/kernel/debug/kdb/kdb_debugger.c index 8b68ce78ff1..be7b33b73d3 100644 --- a/kernel/debug/kdb/kdb_debugger.c +++ b/kernel/debug/kdb/kdb_debugger.c @@ -12,6 +12,7 @@  #include <linux/kdb.h>  #include <linux/kdebug.h>  #include <linux/export.h> +#include <linux/hardirq.h>  #include "kdb_private.h"  #include "../debug_core.h" @@ -52,6 +53,9 @@ int kdb_stub(struct kgdb_state *ks)  	if (atomic_read(&kgdb_setting_breakpoint))  		reason = KDB_REASON_KEYBOARD; +	if (in_nmi()) +		reason = KDB_REASON_NMI; +  	for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) {  		if ((bp->bp_enabled) && (bp->bp_addr == addr)) {  			reason = KDB_REASON_BREAK; diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index bb9520f0f6f..0a69d2adc4f 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -715,9 +715,6 @@ kdb_printit:  	/* check for having reached the LINES number of printed lines */  	if (kdb_nextline == linecount) {  		char buf1[16] = ""; -#if defined(CONFIG_SMP) -		char buf2[32]; -#endif  		/* Watch out for recursion here.  Any routine that calls  		 * kdb_printf will come back through here.  And kdb_read @@ -732,14 +729,6 @@ kdb_printit:  		if (moreprompt == NULL)  			moreprompt = "more> "; -#if defined(CONFIG_SMP) -		if (strchr(moreprompt, '%')) { -			sprintf(buf2, moreprompt, get_cpu()); -			put_cpu(); -			moreprompt = buf2; -		} -#endif -  		kdb_input_flush();  		c = console_drivers; diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 1f91413edb8..31df1706b9a 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -139,11 +139,10 @@ static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t);  static char *__env[] = {  #if defined(CONFIG_SMP)   "PROMPT=[%d]kdb> ", - "MOREPROMPT=[%d]more> ",  #else   "PROMPT=kdb> ", - "MOREPROMPT=more> ",  #endif + "MOREPROMPT=more> ",   "RADIX=16",   "MDCOUNT=8",			/* lines of md output */   KDB_PLATFORM_ENV, @@ -1236,18 +1235,6 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,  		*cmdbuf = '\0';  		*(cmd_hist[cmd_head]) = '\0'; -		if (KDB_FLAG(ONLY_DO_DUMP)) { -			/* kdb is off but a catastrophic error requires a dump. -			 * Take the dump and reboot. -			 * Turn on logging so the kdb output appears in the log -			 * buffer in the dump. -			 */ -			const char *setargs[] = { "set", "LOGGING", "1" }; -			kdb_set(2, setargs); -			kdb_reboot(0, NULL); -			/*NOTREACHED*/ -		} -  do_full_getstr:  #if defined(CONFIG_SMP)  		snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c index 6581a040f39..98d4597f43d 100644 --- a/kernel/events/callchain.c +++ b/kernel/events/callchain.c @@ -153,7 +153,8 @@ put_callchain_entry(int rctx)  	put_recursion_context(__get_cpu_var(callchain_recursion), rctx);  } -struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) +struct perf_callchain_entry * +perf_callchain(struct perf_event *event, struct pt_regs *regs)  {  	int rctx;  	struct perf_callchain_entry *entry; @@ -178,6 +179,12 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)  	}  	if (regs) { +		/* +		 * Disallow cross-task user callchains. +		 */ +		if (event->ctx->task && event->ctx->task != current) +			goto exit_put; +  		perf_callchain_store(entry, PERF_CONTEXT_USER);  		perf_callchain_user(entry, regs);  	} diff --git a/kernel/events/core.c b/kernel/events/core.c index f1cf0edeb39..b7935fcec7d 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4039,7 +4039,7 @@ void perf_prepare_sample(struct perf_event_header *header,  	if (sample_type & PERF_SAMPLE_CALLCHAIN) {  		int size = 1; -		data->callchain = perf_callchain(regs); +		data->callchain = perf_callchain(event, regs);  		if (data->callchain)  			size += data->callchain->nr; @@ -5209,7 +5209,8 @@ static int perf_tp_event_match(struct perf_event *event,  }  void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, -		   struct pt_regs *regs, struct hlist_head *head, int rctx) +		   struct pt_regs *regs, struct hlist_head *head, int rctx, +		   struct task_struct *task)  {  	struct perf_sample_data data;  	struct perf_event *event; @@ -5228,6 +5229,31 @@ void perf_tp_event(u64 addr, u64 count, void *record, int entry_size,  			perf_swevent_event(event, count, &data, regs);  	} +	/* +	 * If we got specified a target task, also iterate its context and +	 * deliver this event there too. +	 */ +	if (task && task != current) { +		struct perf_event_context *ctx; +		struct trace_entry *entry = record; + +		rcu_read_lock(); +		ctx = rcu_dereference(task->perf_event_ctxp[perf_sw_context]); +		if (!ctx) +			goto unlock; + +		list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { +			if (event->attr.type != PERF_TYPE_TRACEPOINT) +				continue; +			if (event->attr.config != entry->type) +				continue; +			if (perf_tp_event_match(event, &data, regs)) +				perf_swevent_event(event, count, &data, regs); +		} +unlock: +		rcu_read_unlock(); +	} +  	perf_swevent_put_recursion_context(rctx);  }  EXPORT_SYMBOL_GPL(perf_tp_event); diff --git a/kernel/events/internal.h b/kernel/events/internal.h index b0b107f90af..a096c19f2c2 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -101,7 +101,8 @@ __output_copy(struct perf_output_handle *handle,  }  /* Callchain handling */ -extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs); +extern struct perf_callchain_entry * +perf_callchain(struct perf_event *event, struct pt_regs *regs);  extern int get_callchain_buffers(void);  extern void put_callchain_buffers(void); diff --git a/kernel/futex.c b/kernel/futex.c index e2b0fb9a0b3..3717e7b306e 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2231,11 +2231,11 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,   * @uaddr2:	the pi futex we will take prior to returning to user-space   *   * The caller will wait on uaddr and will be requeued by futex_requeue() to - * uaddr2 which must be PI aware.  Normal wakeup will wake on uaddr2 and - * complete the acquisition of the rt_mutex prior to returning to userspace. - * This ensures the rt_mutex maintains an owner when it has waiters; without - * one, the pi logic wouldn't know which task to boost/deboost, if there was a - * need to. + * uaddr2 which must be PI aware and unique from uaddr.  Normal wakeup will wake + * on uaddr2 and complete the acquisition of the rt_mutex prior to returning to + * userspace.  This ensures the rt_mutex maintains an owner when it has waiters; + * without one, the pi logic would not know which task to boost/deboost, if + * there was a need to.   *   * We call schedule in futex_wait_queue_me() when we enqueue and return there   * via the following: @@ -2272,6 +2272,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,  	struct futex_q q = futex_q_init;  	int res, ret; +	if (uaddr == uaddr2) +		return -EINVAL; +  	if (!bitset)  		return -EINVAL; @@ -2343,7 +2346,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,  		 * signal.  futex_unlock_pi() will not destroy the lock_ptr nor  		 * the pi_state.  		 */ -		WARN_ON(!&q.pi_state); +		WARN_ON(!q.pi_state);  		pi_mutex = &q.pi_state->pi_mutex;  		ret = rt_mutex_finish_proxy_lock(pi_mutex, to, &rt_waiter, 1);  		debug_rt_mutex_free_waiter(&rt_waiter); @@ -2370,7 +2373,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,  	 * fault, unlock the rt_mutex and return the fault to userspace.  	 */  	if (ret == -EFAULT) { -		if (rt_mutex_owner(pi_mutex) == current) +		if (pi_mutex && rt_mutex_owner(pi_mutex) == current)  			rt_mutex_unlock(pi_mutex);  	} else if (ret == -EINTR) {  		/* diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0a8e8f05962..4c69326aa77 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -944,6 +944,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)  	}  	/* +	 * Drivers are often written to work w/o knowledge about the +	 * underlying irq chip implementation, so a request for a +	 * threaded irq without a primary hard irq context handler +	 * requires the ONESHOT flag to be set. Some irq chips like +	 * MSI based interrupts are per se one shot safe. Check the +	 * chip flags, so we can avoid the unmask dance at the end of +	 * the threaded handler for those. +	 */ +	if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) +		new->flags &= ~IRQF_ONESHOT; + +	/*  	 * The following block of code has to be executed atomically  	 */  	raw_spin_lock_irqsave(&desc->lock, flags); @@ -1017,7 +1029,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)  		 */  		new->thread_mask = 1 << ffz(thread_mask); -	} else if (new->handler == irq_default_primary_handler) { +	} else if (new->handler == irq_default_primary_handler && +		   !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) {  		/*  		 * The interrupt was requested with handler = NULL, so  		 * we use the default primary handler for it. But it diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 1da39ea248f..c8b7446b27d 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -178,9 +178,6 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)  	arch_suspend_enable_irqs();  	BUG_ON(irqs_disabled()); -	/* Kick the lockup detector */ -	lockup_detector_bootcpu_resume(); -   Enable_cpus:  	enable_nonboot_cpus(); diff --git a/kernel/printk.c b/kernel/printk.c index 6a76ab9d447..66a2ea37b57 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1034,6 +1034,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)  			struct log *msg = log_from_idx(idx);  			len += msg_print_text(msg, prev, true, NULL, 0); +			prev = msg->flags;  			idx = log_next(idx);  			seq++;  		} @@ -1046,6 +1047,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)  			struct log *msg = log_from_idx(idx);  			len -= msg_print_text(msg, prev, true, NULL, 0); +			prev = msg->flags;  			idx = log_next(idx);  			seq++;  		} diff --git a/kernel/sched/core.c b/kernel/sched/core.c index d325c4b2dcb..fbf1fd098dc 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3142,6 +3142,20 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)  # define nsecs_to_cputime(__nsecs)	nsecs_to_jiffies(__nsecs)  #endif +static cputime_t scale_utime(cputime_t utime, cputime_t rtime, cputime_t total) +{ +	u64 temp = (__force u64) rtime; + +	temp *= (__force u64) utime; + +	if (sizeof(cputime_t) == 4) +		temp = div_u64(temp, (__force u32) total); +	else +		temp = div64_u64(temp, (__force u64) total); + +	return (__force cputime_t) temp; +} +  void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st)  {  	cputime_t rtime, utime = p->utime, total = utime + p->stime; @@ -3151,13 +3165,9 @@ void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st)  	 */  	rtime = nsecs_to_cputime(p->se.sum_exec_runtime); -	if (total) { -		u64 temp = (__force u64) rtime; - -		temp *= (__force u64) utime; -		do_div(temp, (__force u32) total); -		utime = (__force cputime_t) temp; -	} else +	if (total) +		utime = scale_utime(utime, rtime, total); +	else  		utime = rtime;  	/* @@ -3184,13 +3194,9 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st)  	total = cputime.utime + cputime.stime;  	rtime = nsecs_to_cputime(cputime.sum_exec_runtime); -	if (total) { -		u64 temp = (__force u64) rtime; - -		temp *= (__force u64) cputime.utime; -		do_div(temp, (__force u32) total); -		utime = (__force cputime_t) temp; -	} else +	if (total) +		utime = scale_utime(cputime.utime, rtime, total); +	else  		utime = rtime;  	sig->prev_utime = max(sig->prev_utime, utime); @@ -4340,9 +4346,7 @@ recheck:  	 */  	if (unlikely(policy == p->policy && (!rt_policy(policy) ||  			param->sched_priority == p->rt_priority))) { - -		__task_rq_unlock(rq); -		raw_spin_unlock_irqrestore(&p->pi_lock, flags); +		task_rq_unlock(rq, p, &flags);  		return 0;  	} @@ -7248,6 +7252,7 @@ int in_sched_functions(unsigned long addr)  #ifdef CONFIG_CGROUP_SCHED  struct task_group root_task_group; +LIST_HEAD(task_groups);  #endif  DECLARE_PER_CPU(cpumask_var_t, load_balance_tmpmask); diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c index d72586fdf66..23aa789c53e 100644 --- a/kernel/sched/cpupri.c +++ b/kernel/sched/cpupri.c @@ -65,8 +65,8 @@ static int convert_prio(int prio)  int cpupri_find(struct cpupri *cp, struct task_struct *p,  		struct cpumask *lowest_mask)  { -	int                  idx      = 0; -	int                  task_pri = convert_prio(p->prio); +	int idx = 0; +	int task_pri = convert_prio(p->prio);  	if (task_pri >= MAX_RT_PRIO)  		return 0; @@ -137,9 +137,9 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,   */  void cpupri_set(struct cpupri *cp, int cpu, int newpri)  { -	int                 *currpri = &cp->cpu_to_pri[cpu]; -	int                  oldpri  = *currpri; -	int                  do_mb = 0; +	int *currpri = &cp->cpu_to_pri[cpu]; +	int oldpri = *currpri; +	int do_mb = 0;  	newpri = convert_prio(newpri); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 22321db6495..c219bf8d704 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3069,6 +3069,9 @@ struct lb_env {  	int			new_dst_cpu;  	enum cpu_idle_type	idle;  	long			imbalance; +	/* The set of CPUs under consideration for load-balancing */ +	struct cpumask		*cpus; +  	unsigned int		flags;  	unsigned int		loop; @@ -3384,6 +3387,14 @@ static int tg_load_down(struct task_group *tg, void *data)  static void update_h_load(long cpu)  { +	struct rq *rq = cpu_rq(cpu); +	unsigned long now = jiffies; + +	if (rq->h_load_throttle == now) +		return; + +	rq->h_load_throttle = now; +  	rcu_read_lock();  	walk_tg_tree(tg_load_down, tg_nop, (void *)cpu);  	rcu_read_unlock(); @@ -3653,8 +3664,7 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)   */  static inline void update_sg_lb_stats(struct lb_env *env,  			struct sched_group *group, int load_idx, -			int local_group, const struct cpumask *cpus, -			int *balance, struct sg_lb_stats *sgs) +			int local_group, int *balance, struct sg_lb_stats *sgs)  {  	unsigned long nr_running, max_nr_running, min_nr_running;  	unsigned long load, max_cpu_load, min_cpu_load; @@ -3671,7 +3681,7 @@ static inline void update_sg_lb_stats(struct lb_env *env,  	max_nr_running = 0;  	min_nr_running = ~0UL; -	for_each_cpu_and(i, sched_group_cpus(group), cpus) { +	for_each_cpu_and(i, sched_group_cpus(group), env->cpus) {  		struct rq *rq = cpu_rq(i);  		nr_running = rq->nr_running; @@ -3800,8 +3810,7 @@ static bool update_sd_pick_busiest(struct lb_env *env,   * @sds: variable to hold the statistics for this sched_domain.   */  static inline void update_sd_lb_stats(struct lb_env *env, -				      const struct cpumask *cpus, -				      int *balance, struct sd_lb_stats *sds) +					int *balance, struct sd_lb_stats *sds)  {  	struct sched_domain *child = env->sd->child;  	struct sched_group *sg = env->sd->groups; @@ -3818,8 +3827,7 @@ static inline void update_sd_lb_stats(struct lb_env *env,  		local_group = cpumask_test_cpu(env->dst_cpu, sched_group_cpus(sg));  		memset(&sgs, 0, sizeof(sgs)); -		update_sg_lb_stats(env, sg, load_idx, local_group, -				   cpus, balance, &sgs); +		update_sg_lb_stats(env, sg, load_idx, local_group, balance, &sgs);  		if (local_group && !(*balance))  			return; @@ -4055,7 +4063,6 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s   * to restore balance.   *   * @env: The load balancing environment. - * @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.   * @@ -4065,7 +4072,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s   *		   put to idle by rebalancing its tasks onto our group.   */  static struct sched_group * -find_busiest_group(struct lb_env *env, const struct cpumask *cpus, int *balance) +find_busiest_group(struct lb_env *env, int *balance)  {  	struct sd_lb_stats sds; @@ -4075,7 +4082,7 @@ find_busiest_group(struct lb_env *env, const struct cpumask *cpus, int *balance)  	 * Compute the various statistics relavent for load balancing at  	 * this level.  	 */ -	update_sd_lb_stats(env, cpus, balance, &sds); +	update_sd_lb_stats(env, balance, &sds);  	/*  	 * this_cpu is not the appropriate cpu to perform load balancing at @@ -4155,8 +4162,7 @@ ret:   * find_busiest_queue - find the busiest runqueue among the cpus in group.   */  static struct rq *find_busiest_queue(struct lb_env *env, -				     struct sched_group *group, -				     const struct cpumask *cpus) +				     struct sched_group *group)  {  	struct rq *busiest = NULL, *rq;  	unsigned long max_load = 0; @@ -4171,7 +4177,7 @@ static struct rq *find_busiest_queue(struct lb_env *env,  		if (!capacity)  			capacity = fix_small_capacity(env->sd, group); -		if (!cpumask_test_cpu(i, cpus)) +		if (!cpumask_test_cpu(i, env->cpus))  			continue;  		rq = cpu_rq(i); @@ -4252,6 +4258,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,  		.dst_grpmask    = sched_group_cpus(sd->groups),  		.idle		= idle,  		.loop_break	= sched_nr_migrate_break, +		.cpus		= cpus,  	};  	cpumask_copy(cpus, cpu_active_mask); @@ -4260,7 +4267,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,  	schedstat_inc(sd, lb_count[idle]);  redo: -	group = find_busiest_group(&env, cpus, balance); +	group = find_busiest_group(&env, balance);  	if (*balance == 0)  		goto out_balanced; @@ -4270,7 +4277,7 @@ redo:  		goto out_balanced;  	} -	busiest = find_busiest_queue(&env, group, cpus); +	busiest = find_busiest_queue(&env, group);  	if (!busiest) {  		schedstat_inc(sd, lb_nobusyq[idle]);  		goto out_balanced; @@ -4294,11 +4301,10 @@ redo:  		env.src_rq    = busiest;  		env.loop_max  = min(sysctl_sched_nr_migrate, busiest->nr_running); +		update_h_load(env.src_cpu);  more_balance:  		local_irq_save(flags);  		double_rq_lock(this_rq, busiest); -		if (!env.loop) -			update_h_load(env.src_cpu);  		/*  		 * cur_ld_moved - load moved in current iteration diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 573e1ca0110..944cb68420e 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -788,6 +788,19 @@ static int do_sched_rt_period_timer(struct rt_bandwidth *rt_b, int overrun)  	const struct cpumask *span;  	span = sched_rt_period_mask(); +#ifdef CONFIG_RT_GROUP_SCHED +	/* +	 * FIXME: isolated CPUs should really leave the root task group, +	 * whether they are isolcpus or were isolated via cpusets, lest +	 * the timer run on a CPU which does not service all runqueues, +	 * potentially leaving other CPUs indefinitely throttled.  If +	 * isolation is really required, the user will turn the throttle +	 * off to kill the perturbations it causes anyway.  Meanwhile, +	 * this maintains functionality for boot and/or troubleshooting. +	 */ +	if (rt_b == &root_task_group.rt_bandwidth) +		span = cpu_online_mask; +#endif  	for_each_cpu(i, span) {  		int enqueue = 0;  		struct rt_rq *rt_rq = sched_rt_period_rt_rq(rt_b, i); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index c35a1a7dd4d..f6714d009e7 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -80,7 +80,7 @@ extern struct mutex sched_domains_mutex;  struct cfs_rq;  struct rt_rq; -static LIST_HEAD(task_groups); +extern struct list_head task_groups;  struct cfs_bandwidth {  #ifdef CONFIG_CFS_BANDWIDTH @@ -374,7 +374,11 @@ struct rq {  #ifdef CONFIG_FAIR_GROUP_SCHED  	/* list of leaf cfs_rq on this cpu: */  	struct list_head leaf_cfs_rq_list; -#endif +#ifdef CONFIG_SMP +	unsigned long h_load_throttle; +#endif /* CONFIG_SMP */ +#endif /* CONFIG_FAIR_GROUP_SCHED */ +  #ifdef CONFIG_RT_GROUP_SCHED  	struct list_head leaf_rt_rq_list;  #endif diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c index 7b386e86fd2..da5eb5bed84 100644 --- a/kernel/sched/stop_task.c +++ b/kernel/sched/stop_task.c @@ -27,8 +27,10 @@ static struct task_struct *pick_next_task_stop(struct rq *rq)  {  	struct task_struct *stop = rq->stop; -	if (stop && stop->on_rq) +	if (stop && stop->on_rq) { +		stop->se.exec_start = rq->clock_task;  		return stop; +	}  	return NULL;  } @@ -52,6 +54,21 @@ static void yield_task_stop(struct rq *rq)  static void put_prev_task_stop(struct rq *rq, struct task_struct *prev)  { +	struct task_struct *curr = rq->curr; +	u64 delta_exec; + +	delta_exec = rq->clock_task - curr->se.exec_start; +	if (unlikely((s64)delta_exec < 0)) +		delta_exec = 0; + +	schedstat_set(curr->se.statistics.exec_max, +			max(curr->se.statistics.exec_max, delta_exec)); + +	curr->se.sum_exec_runtime += delta_exec; +	account_group_exec_runtime(curr, delta_exec); + +	curr->se.exec_start = rq->clock_task; +	cpuacct_charge(curr, delta_exec);  }  static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) @@ -60,6 +77,9 @@ static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued)  static void set_curr_task_stop(struct rq *rq)  { +	struct task_struct *stop = rq->stop; + +	stop->se.exec_start = rq->clock_task;  }  static void switched_to_stop(struct rq *rq, struct task_struct *p) diff --git a/kernel/task_work.c b/kernel/task_work.c index 91d4e1742a0..d320d44903b 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -75,6 +75,7 @@ void task_work_run(void)  			p = q->next;  			q->func(q);  			q = p; +			cond_resched();  		}  	}  } diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c index a470154e040..46da0537c10 100644 --- a/kernel/time/jiffies.c +++ b/kernel/time/jiffies.c @@ -37,7 +37,7 @@   * requested HZ value. It is also not recommended   * for "tick-less" systems.   */ -#define NSEC_PER_JIFFY	((u32)((((u64)NSEC_PER_SEC)<<8)/ACTHZ)) +#define NSEC_PER_JIFFY	((u32)((((u64)NSEC_PER_SEC)<<8)/SHIFTED_HZ))  /* Since jiffies uses a simple NSEC_PER_JIFFY multiplier   * conversion, the .shift value could be zero. However diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index b7fbadc5c97..24174b4d669 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -28,7 +28,7 @@ DEFINE_SPINLOCK(ntp_lock);  /* USER_HZ period (usecs): */  unsigned long			tick_usec = TICK_USEC; -/* ACTHZ period (nsecs): */ +/* SHIFTED_HZ period (nsecs): */  unsigned long			tick_nsec;  static u64			tick_length; diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index f045cc50832..e16af197a2b 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -65,14 +65,14 @@ struct timekeeper {  	 * used instead.  	 */  	struct timespec		wall_to_monotonic; -	/* time spent in suspend */ -	struct timespec		total_sleep_time; -	/* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ -	struct timespec		raw_time;  	/* Offset clock monotonic -> clock realtime */  	ktime_t			offs_real; +	/* time spent in suspend */ +	struct timespec		total_sleep_time;  	/* Offset clock monotonic -> clock boottime */  	ktime_t			offs_boot; +	/* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ +	struct timespec		raw_time;  	/* Seqlock for all timekeeper values */  	seqlock_t		lock;  }; @@ -108,13 +108,38 @@ static struct timespec tk_xtime(struct timekeeper *tk)  static void tk_set_xtime(struct timekeeper *tk, const struct timespec *ts)  {  	tk->xtime_sec = ts->tv_sec; -	tk->xtime_nsec = ts->tv_nsec << tk->shift; +	tk->xtime_nsec = (u64)ts->tv_nsec << tk->shift;  }  static void tk_xtime_add(struct timekeeper *tk, const struct timespec *ts)  {  	tk->xtime_sec += ts->tv_sec; -	tk->xtime_nsec += ts->tv_nsec << tk->shift; +	tk->xtime_nsec += (u64)ts->tv_nsec << tk->shift; +} + +static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) +{ +	struct timespec tmp; + +	/* +	 * Verify consistency of: offset_real = -wall_to_monotonic +	 * before modifying anything +	 */ +	set_normalized_timespec(&tmp, -tk->wall_to_monotonic.tv_sec, +					-tk->wall_to_monotonic.tv_nsec); +	WARN_ON_ONCE(tk->offs_real.tv64 != timespec_to_ktime(tmp).tv64); +	tk->wall_to_monotonic = wtm; +	set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); +	tk->offs_real = timespec_to_ktime(tmp); +} + +static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) +{ +	/* Verify consistency before modifying */ +	WARN_ON_ONCE(tk->offs_boot.tv64 != timespec_to_ktime(tk->total_sleep_time).tv64); + +	tk->total_sleep_time	= t; +	tk->offs_boot		= timespec_to_ktime(t);  }  /** @@ -217,14 +242,6 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)  	return nsec + arch_gettimeoffset();  } -static void update_rt_offset(struct timekeeper *tk) -{ -	struct timespec tmp, *wtm = &tk->wall_to_monotonic; - -	set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec); -	tk->offs_real = timespec_to_ktime(tmp); -} -  /* must hold write on timekeeper.lock */  static void timekeeping_update(struct timekeeper *tk, bool clearntp)  { @@ -234,12 +251,10 @@ static void timekeeping_update(struct timekeeper *tk, bool clearntp)  		tk->ntp_error = 0;  		ntp_clear();  	} -	update_rt_offset(tk);  	xt = tk_xtime(tk);  	update_vsyscall(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult);  } -  /**   * timekeeping_forward_now - update clock to the current time   * @@ -277,18 +292,19 @@ static void timekeeping_forward_now(struct timekeeper *tk)   */  void getnstimeofday(struct timespec *ts)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long seq;  	s64 nsecs = 0;  	WARN_ON(timekeeping_suspended);  	do { -		seq = read_seqbegin(&timekeeper.lock); +		seq = read_seqbegin(&tk->lock); -		ts->tv_sec = timekeeper.xtime_sec; -		ts->tv_nsec = timekeeping_get_ns(&timekeeper); +		ts->tv_sec = tk->xtime_sec; +		ts->tv_nsec = timekeeping_get_ns(tk); -	} while (read_seqretry(&timekeeper.lock, seq)); +	} while (read_seqretry(&tk->lock, seq));  	timespec_add_ns(ts, nsecs);  } @@ -296,19 +312,18 @@ EXPORT_SYMBOL(getnstimeofday);  ktime_t ktime_get(void)  { +	struct timekeeper *tk = &timekeeper;  	unsigned int seq;  	s64 secs, nsecs;  	WARN_ON(timekeeping_suspended);  	do { -		seq = read_seqbegin(&timekeeper.lock); -		secs = timekeeper.xtime_sec + -				timekeeper.wall_to_monotonic.tv_sec; -		nsecs = timekeeping_get_ns(&timekeeper) + -				timekeeper.wall_to_monotonic.tv_nsec; +		seq = read_seqbegin(&tk->lock); +		secs = tk->xtime_sec + tk->wall_to_monotonic.tv_sec; +		nsecs = timekeeping_get_ns(tk) + tk->wall_to_monotonic.tv_nsec; -	} while (read_seqretry(&timekeeper.lock, seq)); +	} while (read_seqretry(&tk->lock, seq));  	/*  	 * Use ktime_set/ktime_add_ns to create a proper ktime on  	 * 32-bit architectures without CONFIG_KTIME_SCALAR. @@ -327,18 +342,19 @@ EXPORT_SYMBOL_GPL(ktime_get);   */  void ktime_get_ts(struct timespec *ts)  { +	struct timekeeper *tk = &timekeeper;  	struct timespec tomono;  	unsigned int seq;  	WARN_ON(timekeeping_suspended);  	do { -		seq = read_seqbegin(&timekeeper.lock); -		ts->tv_sec = timekeeper.xtime_sec; -		ts->tv_nsec = timekeeping_get_ns(&timekeeper); -		tomono = timekeeper.wall_to_monotonic; +		seq = read_seqbegin(&tk->lock); +		ts->tv_sec = tk->xtime_sec; +		ts->tv_nsec = timekeeping_get_ns(tk); +		tomono = tk->wall_to_monotonic; -	} while (read_seqretry(&timekeeper.lock, seq)); +	} while (read_seqretry(&tk->lock, seq));  	set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec,  				ts->tv_nsec + tomono.tv_nsec); @@ -358,22 +374,23 @@ EXPORT_SYMBOL_GPL(ktime_get_ts);   */  void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long seq;  	s64 nsecs_raw, nsecs_real;  	WARN_ON_ONCE(timekeeping_suspended);  	do { -		seq = read_seqbegin(&timekeeper.lock); +		seq = read_seqbegin(&tk->lock); -		*ts_raw = timekeeper.raw_time; -		ts_real->tv_sec = timekeeper.xtime_sec; +		*ts_raw = tk->raw_time; +		ts_real->tv_sec = tk->xtime_sec;  		ts_real->tv_nsec = 0; -		nsecs_raw = timekeeping_get_ns_raw(&timekeeper); -		nsecs_real = timekeeping_get_ns(&timekeeper); +		nsecs_raw = timekeeping_get_ns_raw(tk); +		nsecs_real = timekeeping_get_ns(tk); -	} while (read_seqretry(&timekeeper.lock, seq)); +	} while (read_seqretry(&tk->lock, seq));  	timespec_add_ns(ts_raw, nsecs_raw);  	timespec_add_ns(ts_real, nsecs_real); @@ -406,28 +423,28 @@ EXPORT_SYMBOL(do_gettimeofday);   */  int do_settimeofday(const struct timespec *tv)  { +	struct timekeeper *tk = &timekeeper;  	struct timespec ts_delta, xt;  	unsigned long flags;  	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)  		return -EINVAL; -	write_seqlock_irqsave(&timekeeper.lock, flags); +	write_seqlock_irqsave(&tk->lock, flags); -	timekeeping_forward_now(&timekeeper); +	timekeeping_forward_now(tk); -	xt = tk_xtime(&timekeeper); +	xt = tk_xtime(tk);  	ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;  	ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec; -	timekeeper.wall_to_monotonic = -			timespec_sub(timekeeper.wall_to_monotonic, ts_delta); +	tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, ts_delta)); -	tk_set_xtime(&timekeeper, tv); +	tk_set_xtime(tk, tv); -	timekeeping_update(&timekeeper, true); +	timekeeping_update(tk, true); -	write_sequnlock_irqrestore(&timekeeper.lock, flags); +	write_sequnlock_irqrestore(&tk->lock, flags);  	/* signal hrtimers about time change */  	clock_was_set(); @@ -436,7 +453,6 @@ int do_settimeofday(const struct timespec *tv)  }  EXPORT_SYMBOL(do_settimeofday); -  /**   * timekeeping_inject_offset - Adds or subtracts from the current time.   * @tv:		pointer to the timespec variable containing the offset @@ -445,23 +461,23 @@ EXPORT_SYMBOL(do_settimeofday);   */  int timekeeping_inject_offset(struct timespec *ts)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long flags;  	if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)  		return -EINVAL; -	write_seqlock_irqsave(&timekeeper.lock, flags); +	write_seqlock_irqsave(&tk->lock, flags); -	timekeeping_forward_now(&timekeeper); +	timekeeping_forward_now(tk); -	tk_xtime_add(&timekeeper, ts); -	timekeeper.wall_to_monotonic = -				timespec_sub(timekeeper.wall_to_monotonic, *ts); +	tk_xtime_add(tk, ts); +	tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts)); -	timekeeping_update(&timekeeper, true); +	timekeeping_update(tk, true); -	write_sequnlock_irqrestore(&timekeeper.lock, flags); +	write_sequnlock_irqrestore(&tk->lock, flags);  	/* signal hrtimers about time change */  	clock_was_set(); @@ -477,23 +493,24 @@ EXPORT_SYMBOL(timekeeping_inject_offset);   */  static int change_clocksource(void *data)  { +	struct timekeeper *tk = &timekeeper;  	struct clocksource *new, *old;  	unsigned long flags;  	new = (struct clocksource *) data; -	write_seqlock_irqsave(&timekeeper.lock, flags); +	write_seqlock_irqsave(&tk->lock, flags); -	timekeeping_forward_now(&timekeeper); +	timekeeping_forward_now(tk);  	if (!new->enable || new->enable(new) == 0) { -		old = timekeeper.clock; -		tk_setup_internals(&timekeeper, new); +		old = tk->clock; +		tk_setup_internals(tk, new);  		if (old->disable)  			old->disable(old);  	} -	timekeeping_update(&timekeeper, true); +	timekeeping_update(tk, true); -	write_sequnlock_irqrestore(&timekeeper.lock, flags); +	write_sequnlock_irqrestore(&tk->lock, flags);  	return 0;  } @@ -507,7 +524,9 @@ static int change_clocksource(void *data)   */  void timekeeping_notify(struct clocksource *clock)  { -	if (timekeeper.clock == clock) +	struct timekeeper *tk = &timekeeper; + +	if (tk->clock == clock)  		return;  	stop_machine(change_clocksource, clock, NULL);  	tick_clock_notify(); @@ -536,35 +555,36 @@ EXPORT_SYMBOL_GPL(ktime_get_real);   */  void getrawmonotonic(struct timespec *ts)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long seq;  	s64 nsecs;  	do { -		seq = read_seqbegin(&timekeeper.lock); -		nsecs = timekeeping_get_ns_raw(&timekeeper); -		*ts = timekeeper.raw_time; +		seq = read_seqbegin(&tk->lock); +		nsecs = timekeeping_get_ns_raw(tk); +		*ts = tk->raw_time; -	} while (read_seqretry(&timekeeper.lock, seq)); +	} while (read_seqretry(&tk->lock, seq));  	timespec_add_ns(ts, nsecs);  }  EXPORT_SYMBOL(getrawmonotonic); -  /**   * timekeeping_valid_for_hres - Check if timekeeping is suitable for hres   */  int timekeeping_valid_for_hres(void)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long seq;  	int ret;  	do { -		seq = read_seqbegin(&timekeeper.lock); +		seq = read_seqbegin(&tk->lock); -		ret = timekeeper.clock->flags & CLOCK_SOURCE_VALID_FOR_HRES; +		ret = tk->clock->flags & CLOCK_SOURCE_VALID_FOR_HRES; -	} while (read_seqretry(&timekeeper.lock, seq)); +	} while (read_seqretry(&tk->lock, seq));  	return ret;  } @@ -574,15 +594,16 @@ int timekeeping_valid_for_hres(void)   */  u64 timekeeping_max_deferment(void)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long seq;  	u64 ret;  	do { -		seq = read_seqbegin(&timekeeper.lock); +		seq = read_seqbegin(&tk->lock); -		ret = timekeeper.clock->max_idle_ns; +		ret = tk->clock->max_idle_ns; -	} while (read_seqretry(&timekeeper.lock, seq)); +	} while (read_seqretry(&tk->lock, seq));  	return ret;  } @@ -622,46 +643,43 @@ void __attribute__((weak)) read_boot_clock(struct timespec *ts)   */  void __init timekeeping_init(void)  { +	struct timekeeper *tk = &timekeeper;  	struct clocksource *clock;  	unsigned long flags; -	struct timespec now, boot; +	struct timespec now, boot, tmp;  	read_persistent_clock(&now);  	read_boot_clock(&boot); -	seqlock_init(&timekeeper.lock); +	seqlock_init(&tk->lock);  	ntp_init(); -	write_seqlock_irqsave(&timekeeper.lock, flags); +	write_seqlock_irqsave(&tk->lock, flags);  	clock = clocksource_default_clock();  	if (clock->enable)  		clock->enable(clock); -	tk_setup_internals(&timekeeper, clock); +	tk_setup_internals(tk, clock); -	tk_set_xtime(&timekeeper, &now); -	timekeeper.raw_time.tv_sec = 0; -	timekeeper.raw_time.tv_nsec = 0; +	tk_set_xtime(tk, &now); +	tk->raw_time.tv_sec = 0; +	tk->raw_time.tv_nsec = 0;  	if (boot.tv_sec == 0 && boot.tv_nsec == 0) -		boot = tk_xtime(&timekeeper); +		boot = tk_xtime(tk); + +	set_normalized_timespec(&tmp, -boot.tv_sec, -boot.tv_nsec); +	tk_set_wall_to_mono(tk, tmp); -	set_normalized_timespec(&timekeeper.wall_to_monotonic, -				-boot.tv_sec, -boot.tv_nsec); -	update_rt_offset(&timekeeper); -	timekeeper.total_sleep_time.tv_sec = 0; -	timekeeper.total_sleep_time.tv_nsec = 0; -	write_sequnlock_irqrestore(&timekeeper.lock, flags); +	tmp.tv_sec = 0; +	tmp.tv_nsec = 0; +	tk_set_sleep_time(tk, tmp); + +	write_sequnlock_irqrestore(&tk->lock, flags);  }  /* time in seconds when suspend began */  static struct timespec timekeeping_suspend_time; -static void update_sleep_time(struct timespec t) -{ -	timekeeper.total_sleep_time = t; -	timekeeper.offs_boot = timespec_to_ktime(t); -} -  /**   * __timekeeping_inject_sleeptime - Internal function to add sleep interval   * @delta: pointer to a timespec delta value @@ -677,13 +695,11 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,  					"sleep delta value!\n");  		return;  	} -  	tk_xtime_add(tk, delta); -	tk->wall_to_monotonic = timespec_sub(tk->wall_to_monotonic, *delta); -	update_sleep_time(timespec_add(tk->total_sleep_time, *delta)); +	tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *delta)); +	tk_set_sleep_time(tk, timespec_add(tk->total_sleep_time, *delta));  } -  /**   * timekeeping_inject_sleeptime - Adds suspend interval to timeekeeping values   * @delta: pointer to a timespec delta value @@ -696,6 +712,7 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,   */  void timekeeping_inject_sleeptime(struct timespec *delta)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long flags;  	struct timespec ts; @@ -704,21 +721,20 @@ void timekeeping_inject_sleeptime(struct timespec *delta)  	if (!(ts.tv_sec == 0 && ts.tv_nsec == 0))  		return; -	write_seqlock_irqsave(&timekeeper.lock, flags); +	write_seqlock_irqsave(&tk->lock, flags); -	timekeeping_forward_now(&timekeeper); +	timekeeping_forward_now(tk); -	__timekeeping_inject_sleeptime(&timekeeper, delta); +	__timekeeping_inject_sleeptime(tk, delta); -	timekeeping_update(&timekeeper, true); +	timekeeping_update(tk, true); -	write_sequnlock_irqrestore(&timekeeper.lock, flags); +	write_sequnlock_irqrestore(&tk->lock, flags);  	/* signal hrtimers about time change */  	clock_was_set();  } -  /**   * timekeeping_resume - Resumes the generic timekeeping subsystem.   * @@ -728,6 +744,7 @@ void timekeeping_inject_sleeptime(struct timespec *delta)   */  static void timekeeping_resume(void)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long flags;  	struct timespec ts; @@ -735,18 +752,18 @@ static void timekeeping_resume(void)  	clocksource_resume(); -	write_seqlock_irqsave(&timekeeper.lock, flags); +	write_seqlock_irqsave(&tk->lock, flags);  	if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) {  		ts = timespec_sub(ts, timekeeping_suspend_time); -		__timekeeping_inject_sleeptime(&timekeeper, &ts); +		__timekeeping_inject_sleeptime(tk, &ts);  	}  	/* re-base the last cycle value */ -	timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); -	timekeeper.ntp_error = 0; +	tk->clock->cycle_last = tk->clock->read(tk->clock); +	tk->ntp_error = 0;  	timekeeping_suspended = 0; -	timekeeping_update(&timekeeper, false); -	write_sequnlock_irqrestore(&timekeeper.lock, flags); +	timekeeping_update(tk, false); +	write_sequnlock_irqrestore(&tk->lock, flags);  	touch_softlockup_watchdog(); @@ -758,14 +775,15 @@ static void timekeeping_resume(void)  static int timekeeping_suspend(void)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long flags;  	struct timespec		delta, delta_delta;  	static struct timespec	old_delta;  	read_persistent_clock(&timekeeping_suspend_time); -	write_seqlock_irqsave(&timekeeper.lock, flags); -	timekeeping_forward_now(&timekeeper); +	write_seqlock_irqsave(&tk->lock, flags); +	timekeeping_forward_now(tk);  	timekeeping_suspended = 1;  	/* @@ -774,7 +792,7 @@ static int timekeeping_suspend(void)  	 * try to compensate so the difference in system time  	 * and persistent_clock time stays close to constant.  	 */ -	delta = timespec_sub(tk_xtime(&timekeeper), timekeeping_suspend_time); +	delta = timespec_sub(tk_xtime(tk), timekeeping_suspend_time);  	delta_delta = timespec_sub(delta, old_delta);  	if (abs(delta_delta.tv_sec)  >= 2) {  		/* @@ -787,7 +805,7 @@ static int timekeeping_suspend(void)  		timekeeping_suspend_time =  			timespec_add(timekeeping_suspend_time, delta_delta);  	} -	write_sequnlock_irqrestore(&timekeeper.lock, flags); +	write_sequnlock_irqrestore(&tk->lock, flags);  	clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);  	clocksource_suspend(); @@ -898,27 +916,29 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)  		 * the error. This causes the likely below to be unlikely.  		 *  		 * The proper fix is to avoid rounding up by using -		 * the high precision timekeeper.xtime_nsec instead of +		 * the high precision tk->xtime_nsec instead of  		 * xtime.tv_nsec everywhere. Fixing this will take some  		 * time.  		 */  		if (likely(error <= interval))  			adj = 1;  		else -			adj = timekeeping_bigadjust(tk, error, &interval, -							&offset); -	} else if (error < -interval) { -		/* See comment above, this is just switched for the negative */ -		error >>= 2; -		if (likely(error >= -interval)) { -			adj = -1; -			interval = -interval; -			offset = -offset; -		} else -			adj = timekeeping_bigadjust(tk, error, &interval, -							&offset); -	} else -		return; +			adj = timekeeping_bigadjust(tk, error, &interval, &offset); +	} else { +		if (error < -interval) { +			/* See comment above, this is just switched for the negative */ +			error >>= 2; +			if (likely(error >= -interval)) { +				adj = -1; +				interval = -interval; +				offset = -offset; +			} else { +				adj = timekeeping_bigadjust(tk, error, &interval, &offset); +			} +		} else { +			goto out_adjust; +		} +	}  	if (unlikely(tk->clock->maxadj &&  		(tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) { @@ -981,6 +1001,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)  	tk->xtime_nsec -= offset;  	tk->ntp_error -= (interval - offset) << tk->ntp_error_shift; +out_adjust:  	/*  	 * It may be possible that when we entered this function, xtime_nsec  	 * was very small.  Further, if we're slightly speeding the clocksource @@ -1003,7 +1024,6 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)  } -  /**   * accumulate_nsecs_to_secs - Accumulates nsecs into secs   * @@ -1024,15 +1044,21 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)  		/* Figure out if its a leap sec and apply if needed */  		leap = second_overflow(tk->xtime_sec); -		tk->xtime_sec += leap; -		tk->wall_to_monotonic.tv_sec -= leap; -		if (leap) -			clock_was_set_delayed(); +		if (unlikely(leap)) { +			struct timespec ts; + +			tk->xtime_sec += leap; + +			ts.tv_sec = leap; +			ts.tv_nsec = 0; +			tk_set_wall_to_mono(tk, +				timespec_sub(tk->wall_to_monotonic, ts)); +			clock_was_set_delayed(); +		}  	}  } -  /**   * logarithmic_accumulation - shifted accumulation of cycles   * @@ -1076,7 +1102,6 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,  	return offset;  } -  /**   * update_wall_time - Uses the current clocksource to increment the wall time   * @@ -1084,21 +1109,22 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,  static void update_wall_time(void)  {  	struct clocksource *clock; +	struct timekeeper *tk = &timekeeper;  	cycle_t offset;  	int shift = 0, maxshift;  	unsigned long flags;  	s64 remainder; -	write_seqlock_irqsave(&timekeeper.lock, flags); +	write_seqlock_irqsave(&tk->lock, flags);  	/* Make sure we're fully resumed: */  	if (unlikely(timekeeping_suspended))  		goto out; -	clock = timekeeper.clock; +	clock = tk->clock;  #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET -	offset = timekeeper.cycle_interval; +	offset = tk->cycle_interval;  #else  	offset = (clock->read(clock) - clock->cycle_last) & clock->mask;  #endif @@ -1111,19 +1137,19 @@ static void update_wall_time(void)  	 * chunk in one go, and then try to consume the next smaller  	 * doubled multiple.  	 */ -	shift = ilog2(offset) - ilog2(timekeeper.cycle_interval); +	shift = ilog2(offset) - ilog2(tk->cycle_interval);  	shift = max(0, shift);  	/* Bound shift to one less than what overflows tick_length */  	maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;  	shift = min(shift, maxshift); -	while (offset >= timekeeper.cycle_interval) { -		offset = logarithmic_accumulation(&timekeeper, offset, shift); -		if(offset < timekeeper.cycle_interval<<shift) +	while (offset >= tk->cycle_interval) { +		offset = logarithmic_accumulation(tk, offset, shift); +		if (offset < tk->cycle_interval<<shift)  			shift--;  	}  	/* correct the clock when NTP error is too big */ -	timekeeping_adjust(&timekeeper, offset); +	timekeeping_adjust(tk, offset);  	/* @@ -1135,21 +1161,21 @@ static void update_wall_time(void)  	* the vsyscall implementations are converted to use xtime_nsec  	* (shifted nanoseconds), this can be killed.  	*/ -	remainder = timekeeper.xtime_nsec & ((1 << timekeeper.shift) - 1); -	timekeeper.xtime_nsec -= remainder; -	timekeeper.xtime_nsec += 1 << timekeeper.shift; -	timekeeper.ntp_error += remainder << timekeeper.ntp_error_shift; +	remainder = tk->xtime_nsec & ((1 << tk->shift) - 1); +	tk->xtime_nsec -= remainder; +	tk->xtime_nsec += 1 << tk->shift; +	tk->ntp_error += remainder << tk->ntp_error_shift;  	/*  	 * Finally, make sure that after the rounding  	 * xtime_nsec isn't larger than NSEC_PER_SEC  	 */ -	accumulate_nsecs_to_secs(&timekeeper); +	accumulate_nsecs_to_secs(tk); -	timekeeping_update(&timekeeper, false); +	timekeeping_update(tk, false);  out: -	write_sequnlock_irqrestore(&timekeeper.lock, flags); +	write_sequnlock_irqrestore(&tk->lock, flags);  } @@ -1166,18 +1192,18 @@ out:   */  void getboottime(struct timespec *ts)  { +	struct timekeeper *tk = &timekeeper;  	struct timespec boottime = { -		.tv_sec = timekeeper.wall_to_monotonic.tv_sec + -				timekeeper.total_sleep_time.tv_sec, -		.tv_nsec = timekeeper.wall_to_monotonic.tv_nsec + -				timekeeper.total_sleep_time.tv_nsec +		.tv_sec = tk->wall_to_monotonic.tv_sec + +				tk->total_sleep_time.tv_sec, +		.tv_nsec = tk->wall_to_monotonic.tv_nsec + +				tk->total_sleep_time.tv_nsec  	};  	set_normalized_timespec(ts, -boottime.tv_sec, -boottime.tv_nsec);  }  EXPORT_SYMBOL_GPL(getboottime); -  /**   * get_monotonic_boottime - Returns monotonic time since boot   * @ts:		pointer to the timespec to be set @@ -1189,19 +1215,20 @@ EXPORT_SYMBOL_GPL(getboottime);   */  void get_monotonic_boottime(struct timespec *ts)  { +	struct timekeeper *tk = &timekeeper;  	struct timespec tomono, sleep;  	unsigned int seq;  	WARN_ON(timekeeping_suspended);  	do { -		seq = read_seqbegin(&timekeeper.lock); -		ts->tv_sec = timekeeper.xtime_sec; -		ts->tv_nsec = timekeeping_get_ns(&timekeeper); -		tomono = timekeeper.wall_to_monotonic; -		sleep = timekeeper.total_sleep_time; +		seq = read_seqbegin(&tk->lock); +		ts->tv_sec = tk->xtime_sec; +		ts->tv_nsec = timekeeping_get_ns(tk); +		tomono = tk->wall_to_monotonic; +		sleep = tk->total_sleep_time; -	} while (read_seqretry(&timekeeper.lock, seq)); +	} while (read_seqretry(&tk->lock, seq));  	set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec,  			ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec); @@ -1231,31 +1258,38 @@ EXPORT_SYMBOL_GPL(ktime_get_boottime);   */  void monotonic_to_bootbased(struct timespec *ts)  { -	*ts = timespec_add(*ts, timekeeper.total_sleep_time); +	struct timekeeper *tk = &timekeeper; + +	*ts = timespec_add(*ts, tk->total_sleep_time);  }  EXPORT_SYMBOL_GPL(monotonic_to_bootbased);  unsigned long get_seconds(void)  { -	return timekeeper.xtime_sec; +	struct timekeeper *tk = &timekeeper; + +	return tk->xtime_sec;  }  EXPORT_SYMBOL(get_seconds);  struct timespec __current_kernel_time(void)  { -	return tk_xtime(&timekeeper); +	struct timekeeper *tk = &timekeeper; + +	return tk_xtime(tk);  }  struct timespec current_kernel_time(void)  { +	struct timekeeper *tk = &timekeeper;  	struct timespec now;  	unsigned long seq;  	do { -		seq = read_seqbegin(&timekeeper.lock); +		seq = read_seqbegin(&tk->lock); -		now = tk_xtime(&timekeeper); -	} while (read_seqretry(&timekeeper.lock, seq)); +		now = tk_xtime(tk); +	} while (read_seqretry(&tk->lock, seq));  	return now;  } @@ -1263,15 +1297,16 @@ EXPORT_SYMBOL(current_kernel_time);  struct timespec get_monotonic_coarse(void)  { +	struct timekeeper *tk = &timekeeper;  	struct timespec now, mono;  	unsigned long seq;  	do { -		seq = read_seqbegin(&timekeeper.lock); +		seq = read_seqbegin(&tk->lock); -		now = tk_xtime(&timekeeper); -		mono = timekeeper.wall_to_monotonic; -	} while (read_seqretry(&timekeeper.lock, seq)); +		now = tk_xtime(tk); +		mono = tk->wall_to_monotonic; +	} while (read_seqretry(&tk->lock, seq));  	set_normalized_timespec(&now, now.tv_sec + mono.tv_sec,  				now.tv_nsec + mono.tv_nsec); @@ -1300,14 +1335,15 @@ void do_timer(unsigned long ticks)  void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,  				struct timespec *wtom, struct timespec *sleep)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long seq;  	do { -		seq = read_seqbegin(&timekeeper.lock); -		*xtim = tk_xtime(&timekeeper); -		*wtom = timekeeper.wall_to_monotonic; -		*sleep = timekeeper.total_sleep_time; -	} while (read_seqretry(&timekeeper.lock, seq)); +		seq = read_seqbegin(&tk->lock); +		*xtim = tk_xtime(tk); +		*wtom = tk->wall_to_monotonic; +		*sleep = tk->total_sleep_time; +	} while (read_seqretry(&tk->lock, seq));  }  #ifdef CONFIG_HIGH_RES_TIMERS @@ -1321,19 +1357,20 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,   */  ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot)  { +	struct timekeeper *tk = &timekeeper;  	ktime_t now;  	unsigned int seq;  	u64 secs, nsecs;  	do { -		seq = read_seqbegin(&timekeeper.lock); +		seq = read_seqbegin(&tk->lock); -		secs = timekeeper.xtime_sec; -		nsecs = timekeeping_get_ns(&timekeeper); +		secs = tk->xtime_sec; +		nsecs = timekeeping_get_ns(tk); -		*offs_real = timekeeper.offs_real; -		*offs_boot = timekeeper.offs_boot; -	} while (read_seqretry(&timekeeper.lock, seq)); +		*offs_real = tk->offs_real; +		*offs_boot = tk->offs_boot; +	} while (read_seqretry(&tk->lock, seq));  	now = ktime_add_ns(ktime_set(secs, 0), nsecs);  	now = ktime_sub(now, *offs_real); @@ -1346,19 +1383,19 @@ ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot)   */  ktime_t ktime_get_monotonic_offset(void)  { +	struct timekeeper *tk = &timekeeper;  	unsigned long seq;  	struct timespec wtom;  	do { -		seq = read_seqbegin(&timekeeper.lock); -		wtom = timekeeper.wall_to_monotonic; -	} while (read_seqretry(&timekeeper.lock, seq)); +		seq = read_seqbegin(&tk->lock); +		wtom = tk->wall_to_monotonic; +	} while (read_seqretry(&tk->lock, seq));  	return timespec_to_ktime(wtom);  }  EXPORT_SYMBOL_GPL(ktime_get_monotonic_offset); -  /**   * xtime_update() - advances the timekeeping infrastructure   * @ticks:	number of ticks, that have elapsed since the last call. diff --git a/kernel/timer.c b/kernel/timer.c index a61c09374eb..8c5e7b908c6 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1407,13 +1407,6 @@ SYSCALL_DEFINE1(alarm, unsigned int, seconds)  #endif -#ifndef __alpha__ - -/* - * The Alpha uses getxpid, getxuid, and getxgid instead.  Maybe this - * should be moved into arch/i386 instead? - */ -  /**   * sys_getpid - return the thread group id of the current process   * @@ -1469,8 +1462,6 @@ SYSCALL_DEFINE0(getegid)  	return from_kgid_munged(current_user_ns(), current_egid());  } -#endif -  static void process_timeout(unsigned long __data)  {  	wake_up_process((struct task_struct *)__data); diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index fee3752ae8f..8a6d2ee2086 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -281,7 +281,7 @@ perf_ftrace_function_call(unsigned long ip, unsigned long parent_ip)  	head = this_cpu_ptr(event_function.perf_events);  	perf_trace_buf_submit(entry, ENTRY_SIZE, rctx, 0, -			      1, ®s, head); +			      1, ®s, head, NULL);  #undef ENTRY_SIZE  } diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index b31d3d5699f..1a2117043bb 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1002,7 +1002,8 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp,  	store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);  	head = this_cpu_ptr(call->perf_events); -	perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); +	perf_trace_buf_submit(entry, size, rctx, +					entry->ip, 1, regs, head, NULL);  }  /* Kretprobe profile handler */ @@ -1033,7 +1034,8 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,  	store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);  	head = this_cpu_ptr(call->perf_events); -	perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, regs, head); +	perf_trace_buf_submit(entry, size, rctx, +					entry->ret_ip, 1, regs, head, NULL);  }  #endif	/* CONFIG_PERF_EVENTS */ diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 96fc7336909..60e4d787567 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -532,7 +532,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)  			       (unsigned long *)&rec->args);  	head = this_cpu_ptr(sys_data->enter_event->perf_events); -	perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head); +	perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL);  }  int perf_sysenter_enable(struct ftrace_event_call *call) @@ -608,7 +608,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret)  	rec->ret = syscall_get_return_value(current, regs);  	head = this_cpu_ptr(sys_data->exit_event->perf_events); -	perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head); +	perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL);  }  int perf_sysexit_enable(struct ftrace_event_call *call) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 2b36ac68549..03003cd7dd9 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -670,7 +670,7 @@ static void uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs)  		call_fetch(&tu->args[i].fetch, regs, data + tu->args[i].offset);  	head = this_cpu_ptr(call->perf_events); -	perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head); +	perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head, NULL);   out:  	preempt_enable(); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 69add8a9da6..4b1dfba70f7 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -575,7 +575,7 @@ out:  /*   * Create/destroy watchdog threads as CPUs come and go:   */ -static int +static int __cpuinit  cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)  {  	int hotcpu = (unsigned long)hcpu; @@ -610,27 +610,10 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)  	return NOTIFY_OK;  } -static struct notifier_block cpu_nfb = { +static struct notifier_block __cpuinitdata cpu_nfb = {  	.notifier_call = cpu_callback  }; -#ifdef CONFIG_SUSPEND -/* - * On exit from suspend we force an offline->online transition on the boot CPU - * so that the PMU state that was lost while in suspended state gets set up - * properly for the boot CPU.  This information is required for restarting the - * NMI watchdog. - */ -void lockup_detector_bootcpu_resume(void) -{ -	void *cpu = (void *)(long)smp_processor_id(); - -	cpu_callback(&cpu_nfb, CPU_DEAD_FROZEN, cpu); -	cpu_callback(&cpu_nfb, CPU_UP_PREPARE_FROZEN, cpu); -	cpu_callback(&cpu_nfb, CPU_ONLINE_FROZEN, cpu); -} -#endif -  void __init lockup_detector_init(void)  {  	void *cpu = (void *)(long)smp_processor_id(); diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 6b4718e2ee3..b41823cc05e 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -39,12 +39,6 @@ DEFINE_SPINLOCK(bdi_lock);  LIST_HEAD(bdi_list);  LIST_HEAD(bdi_pending_list); -static struct task_struct *sync_supers_tsk; -static struct timer_list sync_supers_timer; - -static int bdi_sync_supers(void *); -static void sync_supers_timer_fn(unsigned long); -  void bdi_lock_two(struct bdi_writeback *wb1, struct bdi_writeback *wb2)  {  	if (wb1 < wb2) { @@ -250,12 +244,6 @@ static int __init default_bdi_init(void)  {  	int err; -	sync_supers_tsk = kthread_run(bdi_sync_supers, NULL, "sync_supers"); -	BUG_ON(IS_ERR(sync_supers_tsk)); - -	setup_timer(&sync_supers_timer, sync_supers_timer_fn, 0); -	bdi_arm_supers_timer(); -  	err = bdi_init(&default_backing_dev_info);  	if (!err)  		bdi_register(&default_backing_dev_info, NULL, "default"); @@ -270,46 +258,6 @@ int bdi_has_dirty_io(struct backing_dev_info *bdi)  	return wb_has_dirty_io(&bdi->wb);  } -/* - * kupdated() used to do this. We cannot do it from the bdi_forker_thread() - * or we risk deadlocking on ->s_umount. The longer term solution would be - * to implement sync_supers_bdi() or similar and simply do it from the - * bdi writeback thread individually. - */ -static int bdi_sync_supers(void *unused) -{ -	set_user_nice(current, 0); - -	while (!kthread_should_stop()) { -		set_current_state(TASK_INTERRUPTIBLE); -		schedule(); - -		/* -		 * Do this periodically, like kupdated() did before. -		 */ -		sync_supers(); -	} - -	return 0; -} - -void bdi_arm_supers_timer(void) -{ -	unsigned long next; - -	if (!dirty_writeback_interval) -		return; - -	next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies; -	mod_timer(&sync_supers_timer, round_jiffies_up(next)); -} - -static void sync_supers_timer_fn(unsigned long unused) -{ -	wake_up_process(sync_supers_tsk); -	bdi_arm_supers_timer(); -} -  static void wakeup_timer_fn(unsigned long data)  {  	struct backing_dev_info *bdi = (struct backing_dev_info *)data; diff --git a/mm/compaction.c b/mm/compaction.c index e78cb968842..7fcd3a52e68 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -51,6 +51,47 @@ static inline bool migrate_async_suitable(int migratetype)  }  /* + * Compaction requires the taking of some coarse locks that are potentially + * very heavily contended. Check if the process needs to be scheduled or + * if the lock is contended. For async compaction, back out in the event + * if contention is severe. For sync compaction, schedule. + * + * Returns true if the lock is held. + * Returns false if the lock is released and compaction should abort + */ +static bool compact_checklock_irqsave(spinlock_t *lock, unsigned long *flags, +				      bool locked, struct compact_control *cc) +{ +	if (need_resched() || spin_is_contended(lock)) { +		if (locked) { +			spin_unlock_irqrestore(lock, *flags); +			locked = false; +		} + +		/* async aborts if taking too long or contended */ +		if (!cc->sync) { +			if (cc->contended) +				*cc->contended = true; +			return false; +		} + +		cond_resched(); +		if (fatal_signal_pending(current)) +			return false; +	} + +	if (!locked) +		spin_lock_irqsave(lock, *flags); +	return true; +} + +static inline bool compact_trylock_irqsave(spinlock_t *lock, +			unsigned long *flags, struct compact_control *cc) +{ +	return compact_checklock_irqsave(lock, flags, false, cc); +} + +/*   * Isolate free pages onto a private freelist. Caller must hold zone->lock.   * If @strict is true, will abort returning 0 on any invalid PFNs or non-free   * pages inside of the pageblock (even though it may still end up isolating @@ -173,7 +214,7 @@ isolate_freepages_range(unsigned long start_pfn, unsigned long end_pfn)  }  /* Update the number of anon and file isolated pages in the zone */ -static void acct_isolated(struct zone *zone, struct compact_control *cc) +static void acct_isolated(struct zone *zone, bool locked, struct compact_control *cc)  {  	struct page *page;  	unsigned int count[2] = { 0, }; @@ -181,8 +222,14 @@ static void acct_isolated(struct zone *zone, struct compact_control *cc)  	list_for_each_entry(page, &cc->migratepages, lru)  		count[!!page_is_file_cache(page)]++; -	__mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]); -	__mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]); +	/* If locked we can use the interrupt unsafe versions */ +	if (locked) { +		__mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]); +		__mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]); +	} else { +		mod_zone_page_state(zone, NR_ISOLATED_ANON, count[0]); +		mod_zone_page_state(zone, NR_ISOLATED_FILE, count[1]); +	}  }  /* Similar to reclaim, but different enough that they don't share logic */ @@ -228,6 +275,8 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc,  	struct list_head *migratelist = &cc->migratepages;  	isolate_mode_t mode = 0;  	struct lruvec *lruvec; +	unsigned long flags; +	bool locked;  	/*  	 * Ensure that there are not too many pages isolated from the LRU @@ -247,25 +296,22 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc,  	/* Time to isolate some pages for migration */  	cond_resched(); -	spin_lock_irq(&zone->lru_lock); +	spin_lock_irqsave(&zone->lru_lock, flags); +	locked = true;  	for (; low_pfn < end_pfn; low_pfn++) {  		struct page *page; -		bool locked = true;  		/* give a chance to irqs before checking need_resched() */  		if (!((low_pfn+1) % SWAP_CLUSTER_MAX)) { -			spin_unlock_irq(&zone->lru_lock); +			spin_unlock_irqrestore(&zone->lru_lock, flags);  			locked = false;  		} -		if (need_resched() || spin_is_contended(&zone->lru_lock)) { -			if (locked) -				spin_unlock_irq(&zone->lru_lock); -			cond_resched(); -			spin_lock_irq(&zone->lru_lock); -			if (fatal_signal_pending(current)) -				break; -		} else if (!locked) -			spin_lock_irq(&zone->lru_lock); + +		/* Check if it is ok to still hold the lock */ +		locked = compact_checklock_irqsave(&zone->lru_lock, &flags, +								locked, cc); +		if (!locked) +			break;  		/*  		 * migrate_pfn does not necessarily start aligned to a @@ -349,9 +395,10 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc,  		}  	} -	acct_isolated(zone, cc); +	acct_isolated(zone, locked, cc); -	spin_unlock_irq(&zone->lru_lock); +	if (locked) +		spin_unlock_irqrestore(&zone->lru_lock, flags);  	trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); @@ -384,6 +431,20 @@ static bool suitable_migration_target(struct page *page)  }  /* + * Returns the start pfn of the last page block in a zone.  This is the starting + * point for full compaction of a zone.  Compaction searches for free pages from + * the end of each zone, while isolate_freepages_block scans forward inside each + * page block. + */ +static unsigned long start_free_pfn(struct zone *zone) +{ +	unsigned long free_pfn; +	free_pfn = zone->zone_start_pfn + zone->spanned_pages; +	free_pfn &= ~(pageblock_nr_pages-1); +	return free_pfn; +} + +/*   * Based on information in the current compact_control, find blocks   * suitable for isolating free pages from and then isolate them.   */ @@ -422,17 +483,6 @@ static void isolate_freepages(struct zone *zone,  					pfn -= pageblock_nr_pages) {  		unsigned long isolated; -		/* -		 * Skip ahead if another thread is compacting in the area -		 * simultaneously. If we wrapped around, we can only skip -		 * ahead if zone->compact_cached_free_pfn also wrapped to -		 * above our starting point. -		 */ -		if (cc->order > 0 && (!cc->wrapped || -				      zone->compact_cached_free_pfn > -				      cc->start_free_pfn)) -			pfn = min(pfn, zone->compact_cached_free_pfn); -  		if (!pfn_valid(pfn))  			continue; @@ -458,7 +508,16 @@ static void isolate_freepages(struct zone *zone,  		 * are disabled  		 */  		isolated = 0; -		spin_lock_irqsave(&zone->lock, flags); + +		/* +		 * The zone lock must be held to isolate freepages. This +		 * unfortunately this is a very coarse lock and can be +		 * heavily contended if there are parallel allocations +		 * or parallel compactions. For async compaction do not +		 * spin on the lock +		 */ +		if (!compact_trylock_irqsave(&zone->lock, &flags, cc)) +			break;  		if (suitable_migration_target(page)) {  			end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);  			isolated = isolate_freepages_block(pfn, end_pfn, @@ -474,7 +533,15 @@ static void isolate_freepages(struct zone *zone,  		 */  		if (isolated) {  			high_pfn = max(high_pfn, pfn); -			if (cc->order > 0) + +			/* +			 * If the free scanner has wrapped, update +			 * compact_cached_free_pfn to point to the highest +			 * pageblock with free pages. This reduces excessive +			 * scanning of full pageblocks near the end of the +			 * zone +			 */ +			if (cc->order > 0 && cc->wrapped)  				zone->compact_cached_free_pfn = high_pfn;  		}  	} @@ -484,6 +551,11 @@ static void isolate_freepages(struct zone *zone,  	cc->free_pfn = high_pfn;  	cc->nr_freepages = nr_freepages; + +	/* If compact_cached_free_pfn is reset then set it now */ +	if (cc->order > 0 && !cc->wrapped && +			zone->compact_cached_free_pfn == start_free_pfn(zone)) +		zone->compact_cached_free_pfn = high_pfn;  }  /* @@ -570,20 +642,6 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,  	return ISOLATE_SUCCESS;  } -/* - * Returns the start pfn of the last page block in a zone.  This is the starting - * point for full compaction of a zone.  Compaction searches for free pages from - * the end of each zone, while isolate_freepages_block scans forward inside each - * page block. - */ -static unsigned long start_free_pfn(struct zone *zone) -{ -	unsigned long free_pfn; -	free_pfn = zone->zone_start_pfn + zone->spanned_pages; -	free_pfn &= ~(pageblock_nr_pages-1); -	return free_pfn; -} -  static int compact_finished(struct zone *zone,  			    struct compact_control *cc)  { @@ -771,7 +829,7 @@ out:  static unsigned long compact_zone_order(struct zone *zone,  				 int order, gfp_t gfp_mask, -				 bool sync) +				 bool sync, bool *contended)  {  	struct compact_control cc = {  		.nr_freepages = 0, @@ -780,6 +838,7 @@ static unsigned long compact_zone_order(struct zone *zone,  		.migratetype = allocflags_to_migratetype(gfp_mask),  		.zone = zone,  		.sync = sync, +		.contended = contended,  	};  	INIT_LIST_HEAD(&cc.freepages);  	INIT_LIST_HEAD(&cc.migratepages); @@ -801,7 +860,7 @@ int sysctl_extfrag_threshold = 500;   */  unsigned long try_to_compact_pages(struct zonelist *zonelist,  			int order, gfp_t gfp_mask, nodemask_t *nodemask, -			bool sync) +			bool sync, bool *contended)  {  	enum zone_type high_zoneidx = gfp_zone(gfp_mask);  	int may_enter_fs = gfp_mask & __GFP_FS; @@ -825,7 +884,8 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,  								nodemask) {  		int status; -		status = compact_zone_order(zone, order, gfp_mask, sync); +		status = compact_zone_order(zone, order, gfp_mask, sync, +						contended);  		rc = max(status, rc);  		/* If a normal allocation would succeed, stop compacting */ @@ -861,7 +921,7 @@ static int __compact_pgdat(pg_data_t *pgdat, struct compact_control *cc)  		if (cc->order > 0) {  			int ok = zone_watermark_ok(zone, cc->order,  						low_wmark_pages(zone), 0, 0); -			if (ok && cc->order > zone->compact_order_failed) +			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) diff --git a/mm/internal.h b/mm/internal.h index 3314f79d775..b8c91b342e2 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -130,6 +130,7 @@ struct compact_control {  	int order;			/* order a direct compactor needs */  	int migratetype;		/* MOVABLE, RECLAIMABLE etc */  	struct zone *zone; +	bool *contended;		/* True if a lock was contended */  };  unsigned long diff --git a/mm/mmap.c b/mm/mmap.c index e3e86914f11..9adee9fc0d8 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2309,7 +2309,7 @@ void exit_mmap(struct mm_struct *mm)  	}  	vm_unacct_memory(nr_accounted); -	BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); +	WARN_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT);  }  /* Insert vm structure into process list sorted by address diff --git a/mm/page-writeback.c b/mm/page-writeback.c index e5363f34e02..5ad5ce23c1e 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1532,7 +1532,6 @@ int dirty_writeback_centisecs_handler(ctl_table *table, int write,  	void __user *buffer, size_t *length, loff_t *ppos)  {  	proc_dointvec(table, write, buffer, length, ppos); -	bdi_arm_supers_timer();  	return 0;  } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 009ac285fea..c66fb875104 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1928,6 +1928,17 @@ this_zone_full:  		zlc_active = 0;  		goto zonelist_scan;  	} + +	if (page) +		/* +		 * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was +		 * necessary to allocate the page. The expectation is +		 * that the caller is taking steps that will free more +		 * memory. The caller should avoid the page being used +		 * for !PFMEMALLOC purposes. +		 */ +		page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS); +  	return page;  } @@ -2091,7 +2102,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,  	struct zonelist *zonelist, enum zone_type high_zoneidx,  	nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone,  	int migratetype, bool sync_migration, -	bool *deferred_compaction, +	bool *contended_compaction, bool *deferred_compaction,  	unsigned long *did_some_progress)  {  	struct page *page; @@ -2106,7 +2117,8 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,  	current->flags |= PF_MEMALLOC;  	*did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, -						nodemask, sync_migration); +						nodemask, sync_migration, +						contended_compaction);  	current->flags &= ~PF_MEMALLOC;  	if (*did_some_progress != COMPACT_SKIPPED) { @@ -2152,7 +2164,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,  	struct zonelist *zonelist, enum zone_type high_zoneidx,  	nodemask_t *nodemask, int alloc_flags, struct zone *preferred_zone,  	int migratetype, bool sync_migration, -	bool *deferred_compaction, +	bool *contended_compaction, bool *deferred_compaction,  	unsigned long *did_some_progress)  {  	return NULL; @@ -2325,6 +2337,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,  	unsigned long did_some_progress;  	bool sync_migration = false;  	bool deferred_compaction = false; +	bool contended_compaction = false;  	/*  	 * In the slowpath, we sanity check order to avoid ever trying to @@ -2389,14 +2402,6 @@ rebalance:  				zonelist, high_zoneidx, nodemask,  				preferred_zone, migratetype);  		if (page) { -			/* -			 * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was -			 * necessary to allocate the page. The expectation is -			 * that the caller is taking steps that will free more -			 * memory. The caller should avoid the page being used -			 * for !PFMEMALLOC purposes. -			 */ -			page->pfmemalloc = true;  			goto got_pg;  		}  	} @@ -2422,6 +2427,7 @@ rebalance:  					nodemask,  					alloc_flags, preferred_zone,  					migratetype, sync_migration, +					&contended_compaction,  					&deferred_compaction,  					&did_some_progress);  	if (page) @@ -2431,10 +2437,11 @@ rebalance:  	/*  	 * If compaction is deferred for high-order allocations, it is because  	 * sync compaction recently failed. In this is the case and the caller -	 * has requested the system not be heavily disrupted, fail the -	 * allocation now instead of entering direct reclaim +	 * requested a movable allocation that does not heavily disrupt the +	 * system then fail the allocation instead of entering direct reclaim.  	 */ -	if (deferred_compaction && (gfp_mask & __GFP_NO_KSWAPD)) +	if ((deferred_compaction || contended_compaction) && +						(gfp_mask & __GFP_NO_KSWAPD))  		goto nopage;  	/* Try direct reclaim and then allocating */ @@ -2505,6 +2512,7 @@ rebalance:  					nodemask,  					alloc_flags, preferred_zone,  					migratetype, sync_migration, +					&contended_compaction,  					&deferred_compaction,  					&did_some_progress);  		if (page) @@ -2569,8 +2577,6 @@ retry_cpuset:  		page = __alloc_pages_slowpath(gfp_mask, order,  				zonelist, high_zoneidx, nodemask,  				preferred_zone, migratetype); -	else -		page->pfmemalloc = false;  	trace_mm_page_alloc(page, order, gfp_mask, migratetype); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 73a2a83ee2d..402442402af 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -137,9 +137,21 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,  	return rc;  } +static inline netdev_tx_t vlan_netpoll_send_skb(struct vlan_dev_priv *vlan, struct sk_buff *skb) +{ +#ifdef CONFIG_NET_POLL_CONTROLLER +	if (vlan->netpoll) +		netpoll_send_skb(vlan->netpoll, skb); +#else +	BUG(); +#endif +	return NETDEV_TX_OK; +} +  static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,  					    struct net_device *dev)  { +	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);  	struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data);  	unsigned int len;  	int ret; @@ -150,29 +162,30 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,  	 * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs...  	 */  	if (veth->h_vlan_proto != htons(ETH_P_8021Q) || -	    vlan_dev_priv(dev)->flags & VLAN_FLAG_REORDER_HDR) { +	    vlan->flags & VLAN_FLAG_REORDER_HDR) {  		u16 vlan_tci; -		vlan_tci = vlan_dev_priv(dev)->vlan_id; +		vlan_tci = vlan->vlan_id;  		vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb);  		skb = __vlan_hwaccel_put_tag(skb, vlan_tci);  	} -	skb->dev = vlan_dev_priv(dev)->real_dev; +	skb->dev = vlan->real_dev;  	len = skb->len; -	if (netpoll_tx_running(dev)) -		return skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev); +	if (unlikely(netpoll_tx_running(dev))) +		return vlan_netpoll_send_skb(vlan, skb); +  	ret = dev_queue_xmit(skb);  	if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {  		struct vlan_pcpu_stats *stats; -		stats = this_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats); +		stats = this_cpu_ptr(vlan->vlan_pcpu_stats);  		u64_stats_update_begin(&stats->syncp);  		stats->tx_packets++;  		stats->tx_bytes += len;  		u64_stats_update_end(&stats->syncp);  	} else { -		this_cpu_inc(vlan_dev_priv(dev)->vlan_pcpu_stats->tx_dropped); +		this_cpu_inc(vlan->vlan_pcpu_stats->tx_dropped);  	}  	return ret; @@ -669,25 +682,26 @@ static void vlan_dev_poll_controller(struct net_device *dev)  	return;  } -static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) +static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo, +				  gfp_t gfp)  { -	struct vlan_dev_priv *info = vlan_dev_priv(dev); -	struct net_device *real_dev = info->real_dev; +	struct vlan_dev_priv *vlan = vlan_dev_priv(dev); +	struct net_device *real_dev = vlan->real_dev;  	struct netpoll *netpoll;  	int err = 0; -	netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); +	netpoll = kzalloc(sizeof(*netpoll), gfp);  	err = -ENOMEM;  	if (!netpoll)  		goto out; -	err = __netpoll_setup(netpoll, real_dev); +	err = __netpoll_setup(netpoll, real_dev, gfp);  	if (err) {  		kfree(netpoll);  		goto out;  	} -	info->netpoll = netpoll; +	vlan->netpoll = netpoll;  out:  	return err; @@ -695,19 +709,15 @@ out:  static void vlan_dev_netpoll_cleanup(struct net_device *dev)  { -	struct vlan_dev_priv *info = vlan_dev_priv(dev); -	struct netpoll *netpoll = info->netpoll; +	struct vlan_dev_priv *vlan= vlan_dev_priv(dev); +	struct netpoll *netpoll = vlan->netpoll;  	if (!netpoll)  		return; -	info->netpoll = NULL; - -        /* Wait for transmitting packets to finish before freeing. */ -        synchronize_rcu_bh(); +	vlan->netpoll = NULL; -        __netpoll_cleanup(netpoll); -        kfree(netpoll); +	__netpoll_free_rcu(netpoll);  }  #endif /* CONFIG_NET_POLL_CONTROLLER */ diff --git a/net/atm/common.c b/net/atm/common.c index b4b44dbed64..0c0ad930a63 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -812,6 +812,7 @@ int vcc_getsockopt(struct socket *sock, int level, int optname,  		if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags))  			return -ENOTCONN; +		memset(&pvc, 0, sizeof(pvc));  		pvc.sap_family = AF_ATMPVC;  		pvc.sap_addr.itf = vcc->dev->number;  		pvc.sap_addr.vpi = vcc->vpi; diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 3a734919c36..ae032402140 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -95,6 +95,7 @@ static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr,  		return -ENOTCONN;  	*sockaddr_len = sizeof(struct sockaddr_atmpvc);  	addr = (struct sockaddr_atmpvc *)sockaddr; +	memset(addr, 0, sizeof(*addr));  	addr->sap_family = AF_ATMPVC;  	addr->sap_addr.itf = vcc->dev->number;  	addr->sap_addr.vpi = vcc->vpi; diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index b421cc49d2c..fc866f2e452 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -200,11 +200,11 @@ void batadv_gw_election(struct batadv_priv *bat_priv)  	if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT)  		goto out; -	if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect)) -		goto out; -  	curr_gw = batadv_gw_get_selected_gw_node(bat_priv); +	if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect) && curr_gw) +		goto out; +  	next_gw = batadv_gw_get_best_gw_node(bat_priv);  	if (curr_gw == next_gw) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index a438f4b582f..99dd8f75b3f 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -197,6 +197,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,  del:  		list_del(&entry->list);  		kfree(entry); +		kfree(tt_change_node);  		event_removed = true;  		goto unlock;  	} diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 41ff978a33f..715d7e33fba 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1365,6 +1365,9 @@ static bool hci_resolve_next_name(struct hci_dev *hdev)  		return false;  	e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); +	if (!e) +		return false; +  	if (hci_resolve_name(hdev, e) == 0) {  		e->name_state = NAME_PENDING;  		return true; @@ -1393,12 +1396,20 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,  		return;  	e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); -	if (e) { +	/* If the device was not found in a list of found devices names of which +	 * are pending. there is no need to continue resolving a next name as it +	 * will be done upon receiving another Remote Name Request Complete +	 * Event */ +	if (!e) +		return; + +	list_del(&e->list); +	if (name) {  		e->name_state = NAME_KNOWN; -		list_del(&e->list); -		if (name) -			mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, -					 e->data.rssi, name, name_len); +		mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, +				 e->data.rssi, name, name_len); +	} else { +		e->name_state = NAME_NOT_KNOWN;  	}  	if (hci_resolve_next_name(hdev)) @@ -1762,7 +1773,12 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)  		if (conn->type == ACL_LINK) {  			conn->state = BT_CONFIG;  			hci_conn_hold(conn); -			conn->disc_timeout = HCI_DISCONN_TIMEOUT; + +			if (!conn->out && !hci_conn_ssp_enabled(conn) && +			    !hci_find_link_key(hdev, &ev->bdaddr)) +				conn->disc_timeout = HCI_PAIRING_TIMEOUT; +			else +				conn->disc_timeout = HCI_DISCONN_TIMEOUT;  		} else  			conn->state = BT_CONNECTED; diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index a7f04de03d7..19fdac78e55 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -694,6 +694,7 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr,  	*addr_len = sizeof(*haddr);  	haddr->hci_family = AF_BLUETOOTH;  	haddr->hci_dev    = hdev->id; +	haddr->hci_channel= 0;  	release_sock(sk);  	return 0; @@ -1009,6 +1010,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname,  		{  			struct hci_filter *f = &hci_pi(sk)->filter; +			memset(&uf, 0, sizeof(uf));  			uf.type_mask = f->type_mask;  			uf.opcode    = f->opcode;  			uf.event_mask[0] = *((u32 *) f->event_mask + 0); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a8964db04bf..daa149b7003 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1181,6 +1181,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)  	sk = chan->sk;  	hci_conn_hold(conn->hcon); +	conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT;  	bacpy(&bt_sk(sk)->src, conn->src);  	bacpy(&bt_sk(sk)->dst, conn->dst); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a4bb27e8427..1497edd191a 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -245,6 +245,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l  	BT_DBG("sock %p, sk %p", sock, sk); +	memset(la, 0, sizeof(struct sockaddr_l2));  	addr->sa_family = AF_BLUETOOTH;  	*len = sizeof(struct sockaddr_l2); @@ -1174,7 +1175,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p  	chan = l2cap_chan_create();  	if (!chan) { -		l2cap_sock_kill(sk); +		sk_free(sk);  		return NULL;  	} diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7e1e59645c0..1a17850d093 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -528,6 +528,7 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int *  	BT_DBG("sock %p, sk %p", sock, sk); +	memset(sa, 0, sizeof(*sa));  	sa->rc_family  = AF_BLUETOOTH;  	sa->rc_channel = rfcomm_pi(sk)->channel;  	if (peer) @@ -822,6 +823,7 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c  		}  		sec.level = rfcomm_pi(sk)->sec_level; +		sec.key_size = 0;  		len = min_t(unsigned int, len, sizeof(sec));  		if (copy_to_user(optval, (char *) &sec, len)) diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index cb960773c00..56f182393c4 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -456,7 +456,7 @@ static int rfcomm_get_dev_list(void __user *arg)  	size = sizeof(*dl) + dev_num * sizeof(*di); -	dl = kmalloc(size, GFP_KERNEL); +	dl = kzalloc(size, GFP_KERNEL);  	if (!dl)  		return -ENOMEM; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 40bbe25dcff..3589e21edb0 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -131,6 +131,15 @@ static int sco_conn_del(struct hci_conn *hcon, int err)  		sco_sock_clear_timer(sk);  		sco_chan_del(sk, err);  		bh_unlock_sock(sk); + +		sco_conn_lock(conn); +		conn->sk = NULL; +		sco_pi(sk)->conn = NULL; +		sco_conn_unlock(conn); + +		if (conn->hcon) +			hci_conn_put(conn->hcon); +  		sco_sock_kill(sk);  	} @@ -821,16 +830,6 @@ static void sco_chan_del(struct sock *sk, int err)  	BT_DBG("sk %p, conn %p, err %d", sk, conn, err); -	if (conn) { -		sco_conn_lock(conn); -		conn->sk = NULL; -		sco_pi(sk)->conn = NULL; -		sco_conn_unlock(conn); - -		if (conn->hcon) -			hci_conn_put(conn->hcon); -	} -  	sk->sk_state = BT_CLOSED;  	sk->sk_err   = err;  	sk->sk_state_change(sk); diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 16ef0dc85a0..901a616c808 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -579,8 +579,11 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)  	if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))  		smp = smp_chan_create(conn); +	else +		smp = conn->smp_chan; -	smp = conn->smp_chan; +	if (!smp) +		return SMP_UNSPECIFIED;  	smp->preq[0] = SMP_CMD_PAIRING_REQ;  	memcpy(&smp->preq[1], req, sizeof(*req)); diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 33348453760..070e8a68cfc 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -31,9 +31,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)  	struct net_bridge_mdb_entry *mdst;  	struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); +	rcu_read_lock();  #ifdef CONFIG_BRIDGE_NETFILTER  	if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) {  		br_nf_pre_routing_finish_bridge_slow(skb); +		rcu_read_unlock();  		return NETDEV_TX_OK;  	}  #endif @@ -48,7 +50,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)  	skb_reset_mac_header(skb);  	skb_pull(skb, ETH_HLEN); -	rcu_read_lock();  	if (is_broadcast_ether_addr(dest))  		br_flood_deliver(br, skb);  	else if (is_multicast_ether_addr(dest)) { @@ -206,24 +207,23 @@ static void br_poll_controller(struct net_device *br_dev)  static void br_netpoll_cleanup(struct net_device *dev)  {  	struct net_bridge *br = netdev_priv(dev); -	struct net_bridge_port *p, *n; +	struct net_bridge_port *p; -	list_for_each_entry_safe(p, n, &br->port_list, list) { +	list_for_each_entry(p, &br->port_list, list)  		br_netpoll_disable(p); -	}  } -static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) +static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, +			    gfp_t gfp)  {  	struct net_bridge *br = netdev_priv(dev); -	struct net_bridge_port *p, *n; +	struct net_bridge_port *p;  	int err = 0; -	list_for_each_entry_safe(p, n, &br->port_list, list) { +	list_for_each_entry(p, &br->port_list, list) {  		if (!p->dev)  			continue; - -		err = br_netpoll_enable(p); +		err = br_netpoll_enable(p, gfp);  		if (err)  			goto fail;  	} @@ -236,17 +236,17 @@ fail:  	goto out;  } -int br_netpoll_enable(struct net_bridge_port *p) +int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)  {  	struct netpoll *np;  	int err = 0; -	np = kzalloc(sizeof(*p->np), GFP_KERNEL); +	np = kzalloc(sizeof(*p->np), gfp);  	err = -ENOMEM;  	if (!np)  		goto out; -	err = __netpoll_setup(np, p->dev); +	err = __netpoll_setup(np, p->dev, gfp);  	if (err) {  		kfree(np);  		goto out; @@ -267,11 +267,7 @@ void br_netpoll_disable(struct net_bridge_port *p)  	p->np = NULL; -	/* Wait for transmitting packets to finish before freeing. */ -	synchronize_rcu_bh(); - -	__netpoll_cleanup(np); -	kfree(np); +	__netpoll_free_rcu(np);  }  #endif diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index e9466d41270..02015a505d2 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -65,7 +65,7 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)  {  	skb->dev = to->dev; -	if (unlikely(netpoll_tx_running(to->dev))) { +	if (unlikely(netpoll_tx_running(to->br->dev))) {  		if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))  			kfree_skb(skb);  		else { diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index e1144e1617b..1c8fdc3558c 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -361,7 +361,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)  	if (err)  		goto err2; -	if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) +	if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL))))  		goto err3;  	err = netdev_set_master(dev, br->dev); @@ -427,6 +427,10 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)  	if (!p || p->br != br)  		return -EINVAL; +	/* Since more than one interface can be attached to a bridge, +	 * there still maybe an alternate path for netconsole to use; +	 * therefore there is no reason for a NETDEV_RELEASE event. +	 */  	del_nbp(p);  	spin_lock_bh(&br->lock); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a768b2408ed..f507d2af964 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -316,7 +316,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p,  		netpoll_send_skb(np, skb);  } -extern int br_netpoll_enable(struct net_bridge_port *p); +extern int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp);  extern void br_netpoll_disable(struct net_bridge_port *p);  #else  static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) @@ -329,7 +329,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p,  {  } -static inline int br_netpoll_enable(struct net_bridge_port *p) +static inline int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp)  {  	return 0;  } diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 69771c04ba8..e597733affb 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -94,6 +94,10 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt)  	/* check the version of IP */  	ip_version = skb_header_pointer(skb, 0, 1, &buf); +	if (!ip_version) { +		kfree_skb(skb); +		return -EINVAL; +	}  	switch (*ip_version >> 4) {  	case 4: diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 69e38db28e5..a8020293f34 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -84,7 +84,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)  			return -1;  		}  	} else { -		pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);  		memcpy(&client->fsid, fsid, sizeof(*fsid));  	}  	return 0; diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index 54b531a0112..38b5dc1823d 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c @@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph_client *client)  	snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid,  		 client->monc.auth->global_id); +	dout("ceph_debugfs_client_init %p %s\n", client, name); + +	BUG_ON(client->debugfs_dir);  	client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir);  	if (!client->debugfs_dir)  		goto out; @@ -234,6 +237,7 @@ out:  void ceph_debugfs_client_cleanup(struct ceph_client *client)  { +	dout("ceph_debugfs_client_cleanup %p\n", client);  	debugfs_remove(client->debugfs_osdmap);  	debugfs_remove(client->debugfs_monmap);  	debugfs_remove(client->osdc.debugfs_file); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index b9796750034..24c5eea8c45 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -915,7 +915,6 @@ static int prepare_write_connect(struct ceph_connection *con)  	con->out_connect.authorizer_len = auth ?  		cpu_to_le32(auth->authorizer_buf_len) : 0; -	con_out_kvec_reset(con);  	con_out_kvec_add(con, sizeof (con->out_connect),  					&con->out_connect);  	if (auth && auth->authorizer_buf_len) @@ -1557,6 +1556,7 @@ static int process_connect(struct ceph_connection *con)  			return -1;  		}  		con->auth_retry = 1; +		con_out_kvec_reset(con);  		ret = prepare_write_connect(con);  		if (ret < 0)  			return ret; @@ -1577,6 +1577,7 @@ static int process_connect(struct ceph_connection *con)  		       ENTITY_NAME(con->peer_name),  		       ceph_pr_addr(&con->peer_addr.in_addr));  		reset_connection(con); +		con_out_kvec_reset(con);  		ret = prepare_write_connect(con);  		if (ret < 0)  			return ret; @@ -1601,6 +1602,7 @@ static int process_connect(struct ceph_connection *con)  		     le32_to_cpu(con->out_connect.connect_seq),  		     le32_to_cpu(con->in_reply.connect_seq));  		con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); +		con_out_kvec_reset(con);  		ret = prepare_write_connect(con);  		if (ret < 0)  			return ret; @@ -1617,6 +1619,7 @@ static int process_connect(struct ceph_connection *con)  		     le32_to_cpu(con->in_reply.global_seq));  		get_global_seq(con->msgr,  			       le32_to_cpu(con->in_reply.global_seq)); +		con_out_kvec_reset(con);  		ret = prepare_write_connect(con);  		if (ret < 0)  			return ret; @@ -2135,7 +2138,11 @@ more:  		BUG_ON(con->state != CON_STATE_CONNECTING);  		con->state = CON_STATE_NEGOTIATING; -		/* Banner is good, exchange connection info */ +		/* +		 * Received banner is good, exchange connection info. +		 * Do not reset out_kvec, as sending our banner raced +		 * with receiving peer banner after connect completed. +		 */  		ret = prepare_write_connect(con);  		if (ret < 0)  			goto out; diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 105d533b55f..900ea0f043f 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -311,6 +311,17 @@ int ceph_monc_open_session(struct ceph_mon_client *monc)  EXPORT_SYMBOL(ceph_monc_open_session);  /* + * We require the fsid and global_id in order to initialize our + * debugfs dir. + */ +static bool have_debugfs_info(struct ceph_mon_client *monc) +{ +	dout("have_debugfs_info fsid %d globalid %lld\n", +	     (int)monc->client->have_fsid, monc->auth->global_id); +	return monc->client->have_fsid && monc->auth->global_id > 0; +} + +/*   * The monitor responds with mount ack indicate mount success.  The   * included client ticket allows the client to talk to MDSs and OSDs.   */ @@ -320,9 +331,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,  	struct ceph_client *client = monc->client;  	struct ceph_monmap *monmap = NULL, *old = monc->monmap;  	void *p, *end; +	int had_debugfs_info, init_debugfs = 0;  	mutex_lock(&monc->mutex); +	had_debugfs_info = have_debugfs_info(monc); +  	dout("handle_monmap\n");  	p = msg->front.iov_base;  	end = p + msg->front.iov_len; @@ -344,12 +358,22 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc,  	if (!client->have_fsid) {  		client->have_fsid = true; +		if (!had_debugfs_info && have_debugfs_info(monc)) { +			pr_info("client%lld fsid %pU\n", +				ceph_client_id(monc->client), +				&monc->client->fsid); +			init_debugfs = 1; +		}  		mutex_unlock(&monc->mutex); -		/* -		 * do debugfs initialization without mutex to avoid -		 * creating a locking dependency -		 */ -		ceph_debugfs_client_init(client); + +		if (init_debugfs) { +			/* +			 * do debugfs initialization without mutex to avoid +			 * creating a locking dependency +			 */ +			ceph_debugfs_client_init(monc->client); +		} +  		goto out_unlocked;  	}  out: @@ -865,8 +889,10 @@ static void handle_auth_reply(struct ceph_mon_client *monc,  {  	int ret;  	int was_auth = 0; +	int had_debugfs_info, init_debugfs = 0;  	mutex_lock(&monc->mutex); +	had_debugfs_info = have_debugfs_info(monc);  	if (monc->auth->ops)  		was_auth = monc->auth->ops->is_authenticated(monc->auth);  	monc->pending_auth = 0; @@ -889,7 +915,22 @@ static void handle_auth_reply(struct ceph_mon_client *monc,  		__send_subscribe(monc);  		__resend_generic_request(monc);  	} + +	if (!had_debugfs_info && have_debugfs_info(monc)) { +		pr_info("client%lld fsid %pU\n", +			ceph_client_id(monc->client), +			&monc->client->fsid); +		init_debugfs = 1; +	}  	mutex_unlock(&monc->mutex); + +	if (init_debugfs) { +		/* +		 * do debugfs initialization without mutex to avoid +		 * creating a locking dependency +		 */ +		ceph_debugfs_client_init(monc->client); +	}  }  static int __validate_auth(struct ceph_mon_client *monc) diff --git a/net/core/dev.c b/net/core/dev.c index 0cb3fe8d8e7..83988362805 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1055,6 +1055,8 @@ rollback:   */  int dev_set_alias(struct net_device *dev, const char *alias, size_t len)  { +	char *new_ifalias; +  	ASSERT_RTNL();  	if (len >= IFALIASZ) @@ -1068,9 +1070,10 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len)  		return 0;  	} -	dev->ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); -	if (!dev->ifalias) +	new_ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); +	if (!new_ifalias)  		return -ENOMEM; +	dev->ifalias = new_ifalias;  	strlcpy(dev->ifalias, alias, len+1);  	return len; @@ -1639,6 +1642,19 @@ static inline int deliver_skb(struct sk_buff *skb,  	return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);  } +static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) +{ +	if (ptype->af_packet_priv == NULL) +		return false; + +	if (ptype->id_match) +		return ptype->id_match(ptype, skb->sk); +	else if ((struct sock *)ptype->af_packet_priv == skb->sk) +		return true; + +	return false; +} +  /*   *	Support routine. Sends outgoing frames to any network   *	taps currently in use. @@ -1656,8 +1672,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)  		 * they originated from - MvS (miquels@drinkel.ow.org)  		 */  		if ((ptype->dev == dev || !ptype->dev) && -		    (ptype->af_packet_priv == NULL || -		     (struct sock *)ptype->af_packet_priv != skb->sk)) { +		    (!skb_loop_sk(ptype, skb))) {  			if (pt_prev) {  				deliver_skb(skb2, pt_prev, skb->dev);  				pt_prev = ptype; @@ -2134,6 +2149,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)  	__be16 protocol = skb->protocol;  	netdev_features_t features = skb->dev->features; +	if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) +		features &= ~NETIF_F_GSO_MASK; +  	if (protocol == htons(ETH_P_8021Q)) {  		struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;  		protocol = veh->h_vlan_encapsulated_proto; @@ -5726,6 +5744,7 @@ EXPORT_SYMBOL(netdev_refcnt_read);  /**   * netdev_wait_allrefs - wait until all references are gone. + * @dev: target net_device   *   * This is called when unregistering network devices.   * @@ -5986,6 +6005,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,  	dev_net_set(dev, &init_net);  	dev->gso_max_size = GSO_MAX_SIZE; +	dev->gso_max_segs = GSO_MAX_SEGS;  	INIT_LIST_HEAD(&dev->napi_list);  	INIT_LIST_HEAD(&dev->unreg_list); diff --git a/net/core/dst.c b/net/core/dst.c index 069d51d2941..56d63612e1e 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -149,7 +149,15 @@ int dst_discard(struct sk_buff *skb)  }  EXPORT_SYMBOL(dst_discard); -const u32 dst_default_metrics[RTAX_MAX]; +const u32 dst_default_metrics[RTAX_MAX + 1] = { +	/* This initializer is needed to force linker to place this variable +	 * into const section. Otherwise it might end into bss section. +	 * We really want to avoid false sharing on this variable, and catch +	 * any writes on it. +	 */ +	[RTAX_MAX] = 0xdeadbeef, +}; +  void *dst_alloc(struct dst_ops *ops, struct net_device *dev,  		int initial_ref, int initial_obsolete, unsigned short flags) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index b4c90e42b44..346b1eb83a1 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -26,6 +26,7 @@  #include <linux/workqueue.h>  #include <linux/slab.h>  #include <linux/export.h> +#include <linux/if_vlan.h>  #include <net/tcp.h>  #include <net/udp.h>  #include <asm/unaligned.h> @@ -54,7 +55,7 @@ static atomic_t trapped;  	 MAX_UDP_CHUNK)  static void zap_completion_queue(void); -static void arp_reply(struct sk_buff *skb); +static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo);  static unsigned int carrier_timeout = 4;  module_param(carrier_timeout, uint, 0644); @@ -167,15 +168,24 @@ static void poll_napi(struct net_device *dev)  	struct napi_struct *napi;  	int budget = 16; +	WARN_ON_ONCE(!irqs_disabled()); +  	list_for_each_entry(napi, &dev->napi_list, dev_list) { +		local_irq_enable();  		if (napi->poll_owner != smp_processor_id() &&  		    spin_trylock(&napi->poll_lock)) { -			budget = poll_one_napi(dev->npinfo, napi, budget); +			rcu_read_lock_bh(); +			budget = poll_one_napi(rcu_dereference_bh(dev->npinfo), +					       napi, budget); +			rcu_read_unlock_bh();  			spin_unlock(&napi->poll_lock); -			if (!budget) +			if (!budget) { +				local_irq_disable();  				break; +			}  		} +		local_irq_disable();  	}  } @@ -185,13 +195,14 @@ static void service_arp_queue(struct netpoll_info *npi)  		struct sk_buff *skb;  		while ((skb = skb_dequeue(&npi->arp_tx))) -			arp_reply(skb); +			netpoll_arp_reply(skb, npi);  	}  }  static void netpoll_poll_dev(struct net_device *dev)  {  	const struct net_device_ops *ops; +	struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo);  	if (!dev || !netif_running(dev))  		return; @@ -206,17 +217,18 @@ static void netpoll_poll_dev(struct net_device *dev)  	poll_napi(dev);  	if (dev->flags & IFF_SLAVE) { -		if (dev->npinfo) { +		if (ni) {  			struct net_device *bond_dev = dev->master;  			struct sk_buff *skb; -			while ((skb = skb_dequeue(&dev->npinfo->arp_tx))) { +			struct netpoll_info *bond_ni = rcu_dereference_bh(bond_dev->npinfo); +			while ((skb = skb_dequeue(&ni->arp_tx))) {  				skb->dev = bond_dev; -				skb_queue_tail(&bond_dev->npinfo->arp_tx, skb); +				skb_queue_tail(&bond_ni->arp_tx, skb);  			}  		}  	} -	service_arp_queue(dev->npinfo); +	service_arp_queue(ni);  	zap_completion_queue();  } @@ -302,6 +314,7 @@ static int netpoll_owner_active(struct net_device *dev)  	return 0;  } +/* call with IRQ disabled */  void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,  			     struct net_device *dev)  { @@ -309,8 +322,11 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,  	unsigned long tries;  	const struct net_device_ops *ops = dev->netdev_ops;  	/* It is up to the caller to keep npinfo alive. */ -	struct netpoll_info *npinfo = np->dev->npinfo; +	struct netpoll_info *npinfo; + +	WARN_ON_ONCE(!irqs_disabled()); +	npinfo = rcu_dereference_bh(np->dev->npinfo);  	if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) {  		__kfree_skb(skb);  		return; @@ -319,16 +335,22 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,  	/* don't get messages out of order, and no recursion */  	if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) {  		struct netdev_queue *txq; -		unsigned long flags;  		txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); -		local_irq_save(flags);  		/* try until next clock tick */  		for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;  		     tries > 0; --tries) {  			if (__netif_tx_trylock(txq)) {  				if (!netif_xmit_stopped(txq)) { +					if (vlan_tx_tag_present(skb) && +					    !(netif_skb_features(skb) & NETIF_F_HW_VLAN_TX)) { +						skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb)); +						if (unlikely(!skb)) +							break; +						skb->vlan_tci = 0; +					} +  					status = ops->ndo_start_xmit(skb, dev);  					if (status == NETDEV_TX_OK)  						txq_trans_update(txq); @@ -347,10 +369,9 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,  		}  		WARN_ONCE(!irqs_disabled(), -			"netpoll_send_skb(): %s enabled interrupts in poll (%pF)\n", +			"netpoll_send_skb_on_dev(): %s enabled interrupts in poll (%pF)\n",  			dev->name, ops->ndo_start_xmit); -		local_irq_restore(flags);  	}  	if (status != NETDEV_TX_OK) { @@ -423,9 +444,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)  }  EXPORT_SYMBOL(netpoll_send_udp); -static void arp_reply(struct sk_buff *skb) +static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo)  { -	struct netpoll_info *npinfo = skb->dev->npinfo;  	struct arphdr *arp;  	unsigned char *arp_ptr;  	int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; @@ -543,13 +563,12 @@ static void arp_reply(struct sk_buff *skb)  	spin_unlock_irqrestore(&npinfo->rx_lock, flags);  } -int __netpoll_rx(struct sk_buff *skb) +int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)  {  	int proto, len, ulen;  	int hits = 0;  	const struct iphdr *iph;  	struct udphdr *uh; -	struct netpoll_info *npinfo = skb->dev->npinfo;  	struct netpoll *np, *tmp;  	if (list_empty(&npinfo->rx_np)) @@ -565,6 +584,12 @@ int __netpoll_rx(struct sk_buff *skb)  		return 1;  	} +	if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { +		skb = vlan_untag(skb); +		if (unlikely(!skb)) +			goto out; +	} +  	proto = ntohs(eth_hdr(skb)->h_proto);  	if (proto != ETH_P_IP)  		goto out; @@ -715,7 +740,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)  }  EXPORT_SYMBOL(netpoll_parse_options); -int __netpoll_setup(struct netpoll *np, struct net_device *ndev) +int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)  {  	struct netpoll_info *npinfo;  	const struct net_device_ops *ops; @@ -734,7 +759,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)  	}  	if (!ndev->npinfo) { -		npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); +		npinfo = kmalloc(sizeof(*npinfo), gfp);  		if (!npinfo) {  			err = -ENOMEM;  			goto out; @@ -752,7 +777,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)  		ops = np->dev->netdev_ops;  		if (ops->ndo_netpoll_setup) { -			err = ops->ndo_netpoll_setup(ndev, npinfo); +			err = ops->ndo_netpoll_setup(ndev, npinfo, gfp);  			if (err)  				goto free_npinfo;  		} @@ -857,7 +882,7 @@ int netpoll_setup(struct netpoll *np)  	refill_skbs();  	rtnl_lock(); -	err = __netpoll_setup(np, ndev); +	err = __netpoll_setup(np, ndev, GFP_KERNEL);  	rtnl_unlock();  	if (err) @@ -878,6 +903,24 @@ static int __init netpoll_init(void)  }  core_initcall(netpoll_init); +static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head) +{ +	struct netpoll_info *npinfo = +			container_of(rcu_head, struct netpoll_info, rcu); + +	skb_queue_purge(&npinfo->arp_tx); +	skb_queue_purge(&npinfo->txq); + +	/* we can't call cancel_delayed_work_sync here, as we are in softirq */ +	cancel_delayed_work(&npinfo->tx_work); + +	/* clean after last, unfinished work */ +	__skb_queue_purge(&npinfo->txq); +	/* now cancel it again */ +	cancel_delayed_work(&npinfo->tx_work); +	kfree(npinfo); +} +  void __netpoll_cleanup(struct netpoll *np)  {  	struct netpoll_info *npinfo; @@ -903,20 +946,24 @@ void __netpoll_cleanup(struct netpoll *np)  			ops->ndo_netpoll_cleanup(np->dev);  		RCU_INIT_POINTER(np->dev->npinfo, NULL); +		call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); +	} +} +EXPORT_SYMBOL_GPL(__netpoll_cleanup); -		/* avoid racing with NAPI reading npinfo */ -		synchronize_rcu_bh(); +static void rcu_cleanup_netpoll(struct rcu_head *rcu_head) +{ +	struct netpoll *np = container_of(rcu_head, struct netpoll, rcu); -		skb_queue_purge(&npinfo->arp_tx); -		skb_queue_purge(&npinfo->txq); -		cancel_delayed_work_sync(&npinfo->tx_work); +	__netpoll_cleanup(np); +	kfree(np); +} -		/* clean after last, unfinished work */ -		__skb_queue_purge(&npinfo->txq); -		kfree(npinfo); -	} +void __netpoll_free_rcu(struct netpoll *np) +{ +	call_rcu_bh(&np->rcu, rcu_cleanup_netpoll);  } -EXPORT_SYMBOL_GPL(__netpoll_cleanup); +EXPORT_SYMBOL_GPL(__netpoll_free_rcu);  void netpoll_cleanup(struct netpoll *np)  { diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index ed0c0431fcd..c75e3f9d060 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -101,12 +101,10 @@ static int write_update_netdev_table(struct net_device *dev)  	u32 max_len;  	struct netprio_map *map; -	rtnl_lock();  	max_len = atomic_read(&max_prioidx) + 1;  	map = rtnl_dereference(dev->priomap);  	if (!map || map->priomap_len < max_len)  		ret = extend_netdev_table(dev, max_len); -	rtnl_unlock();  	return ret;  } @@ -256,17 +254,17 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft,  	if (!dev)  		goto out_free_devname; +	rtnl_lock();  	ret = write_update_netdev_table(dev);  	if (ret < 0)  		goto out_put_dev; -	rcu_read_lock(); -	map = rcu_dereference(dev->priomap); +	map = rtnl_dereference(dev->priomap);  	if (map)  		map->priomap[prioidx] = priority; -	rcu_read_unlock();  out_put_dev: +	rtnl_unlock();  	dev_put(dev);  out_free_devname: @@ -277,12 +275,6 @@ out_free_devname:  void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)  {  	struct task_struct *p; -	char *tmp = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL); - -	if (!tmp) { -		pr_warn("Unable to attach cgrp due to alloc failure!\n"); -		return; -	}  	cgroup_taskset_for_each(p, cgrp, tset) {  		unsigned int fd; @@ -296,32 +288,24 @@ void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)  			continue;  		} -		rcu_read_lock(); +		spin_lock(&files->file_lock);  		fdt = files_fdtable(files);  		for (fd = 0; fd < fdt->max_fds; fd++) { -			char *path;  			struct file *file;  			struct socket *sock; -			unsigned long s; -			int rv, err = 0; +			int err;  			file = fcheck_files(files, fd);  			if (!file)  				continue; -			path = d_path(&file->f_path, tmp, PAGE_SIZE); -			rv = sscanf(path, "socket:[%lu]", &s); -			if (rv <= 0) -				continue; -  			sock = sock_from_file(file, &err); -			if (!err) +			if (sock)  				sock_update_netprioidx(sock->sk, p);  		} -		rcu_read_unlock(); +		spin_unlock(&files->file_lock);  		task_unlock(p);  	} -	kfree(tmp);  }  static struct cftype ss_files[] = { diff --git a/net/core/scm.c b/net/core/scm.c index 8f6ccfd68ef..040cebeed45 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -265,6 +265,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)  	for (i=0, cmfptr=(__force int __user *)CMSG_DATA(cm); i<fdmax;  	     i++, cmfptr++)  	{ +		struct socket *sock;  		int new_fd;  		err = security_file_receive(fp[i]);  		if (err) @@ -281,6 +282,9 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)  		}  		/* Bump the usage count and install the file. */  		get_file(fp[i]); +		sock = sock_from_file(fp[i], &err); +		if (sock) +			sock_update_netprioidx(sock->sk, current);  		fd_install(new_fd, fp[i]);  	} diff --git a/net/core/sock.c b/net/core/sock.c index 6b654b3ddfd..8f67ced8d6a 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1458,6 +1458,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)  		} else {  			sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;  			sk->sk_gso_max_size = dst->dev->gso_max_size; +			sk->sk_gso_max_segs = dst->dev->gso_max_segs;  		}  	}  } diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 75c3582a767..fb85d371a8d 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -246,7 +246,7 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,  					u32 __user *optval, int __user *optlen)  {  	int rc = -ENOPROTOOPT; -	if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) +	if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)  		rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,  						 optval, optlen);  	return rc; @@ -257,7 +257,7 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,  					u32 __user *optval, int __user *optlen)  {  	int rc = -ENOPROTOOPT; -	if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) +	if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)  		rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,  						 optval, optlen);  	return rc; diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index d65e98798ec..119c04317d4 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -535,6 +535,7 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,  	case DCCP_SOCKOPT_CCID_TX_INFO:  		if (len < sizeof(tfrc))  			return -EINVAL; +		memset(&tfrc, 0, sizeof(tfrc));  		tfrc.tfrctx_x	   = hc->tx_x;  		tfrc.tfrctx_x_recv = hc->tx_x_recv;  		tfrc.tfrctx_x_calc = hc->tx_x_calc; diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index f0cdb30921c..57bd978483e 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -367,7 +367,7 @@ static void __leaf_free_rcu(struct rcu_head *head)  static inline void free_leaf(struct leaf *l)  { -	call_rcu_bh(&l->rcu, __leaf_free_rcu); +	call_rcu(&l->rcu, __leaf_free_rcu);  }  static inline void free_leaf_info(struct leaf_info *leaf) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index db0cf17c00f..7f75f21d7b8 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -404,12 +404,15 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,  {  	const struct inet_request_sock *ireq = inet_rsk(req);  	struct inet_sock *newinet = inet_sk(newsk); -	struct ip_options_rcu *opt = ireq->opt; +	struct ip_options_rcu *opt;  	struct net *net = sock_net(sk);  	struct flowi4 *fl4;  	struct rtable *rt;  	fl4 = &newinet->cork.fl.u.ip4; + +	rcu_read_lock(); +	opt = rcu_dereference(newinet->inet_opt);  	flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark,  			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,  			   sk->sk_protocol, inet_sk_flowi_flags(sk), @@ -421,11 +424,13 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,  		goto no_route;  	if (opt && opt->opt.is_strictroute && rt->rt_gateway)  		goto route_err; +	rcu_read_unlock();  	return &rt->dst;  route_err:  	ip_rt_put(rt);  no_route: +	rcu_read_unlock();  	IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);  	return NULL;  } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index ba39a52d18c..c196d749daf 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -197,7 +197,7 @@ static inline int ip_finish_output2(struct sk_buff *skb)  	neigh = __ipv4_neigh_lookup_noref(dev, nexthop);  	if (unlikely(!neigh))  		neigh = __neigh_create(&arp_tbl, &nexthop, dev, false); -	if (neigh) { +	if (!IS_ERR(neigh)) {  		int res = dst_neigh_output(dst, neigh, skb);  		rcu_read_unlock_bh(); @@ -1338,10 +1338,10 @@ struct sk_buff *__ip_make_skb(struct sock *sk,  	iph->ihl = 5;  	iph->tos = inet->tos;  	iph->frag_off = df; -	ip_select_ident(iph, &rt->dst, sk);  	iph->ttl = ttl;  	iph->protocol = sk->sk_protocol;  	ip_copy_addrs(iph, fl4); +	ip_select_ident(iph, &rt->dst, sk);  	if (opt) {  		iph->ihl += opt->optlen>>2; @@ -1366,9 +1366,8 @@ out:  	return skb;  } -int ip_send_skb(struct sk_buff *skb) +int ip_send_skb(struct net *net, struct sk_buff *skb)  { -	struct net *net = sock_net(skb->sk);  	int err;  	err = ip_local_out(skb); @@ -1391,7 +1390,7 @@ int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4)  		return 0;  	/* Netfilter gets whole the not fragmented skb. */ -	return ip_send_skb(skb); +	return ip_send_skb(sock_net(sk), skb);  }  /* @@ -1536,6 +1535,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,  			  arg->csumoffset) = csum_fold(csum_add(nskb->csum,  								arg->csum));  		nskb->ip_summed = CHECKSUM_NONE; +		skb_orphan(nskb);  		skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb));  		ip_push_pending_frames(sk, &fl4);  	} diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index ea4a23813d2..4ad9cf17399 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -148,7 +148,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,  	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,  				    hdr, NULL, &matchoff, &matchlen,  				    &addr, &port) > 0) { -		unsigned int matchend, poff, plen, buflen, n; +		unsigned int olen, matchend, poff, plen, buflen, n;  		char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];  		/* We're only interested in headers related to this @@ -163,17 +163,18 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,  				goto next;  		} +		olen = *datalen;  		if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,  			      &addr, port))  			return NF_DROP; -		matchend = matchoff + matchlen; +		matchend = matchoff + matchlen + *datalen - olen;  		/* The maddr= parameter (RFC 2361) specifies where to send  		 * the reply. */  		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,  					       "maddr=", &poff, &plen, -					       &addr) > 0 && +					       &addr, true) > 0 &&  		    addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&  		    addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {  			buflen = sprintf(buffer, "%pI4", @@ -187,7 +188,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,  		 * from which the server received the request. */  		if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen,  					       "received=", &poff, &plen, -					       &addr) > 0 && +					       &addr, false) > 0 &&  		    addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&  		    addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {  			buflen = sprintf(buffer, "%pI4", diff --git a/net/ipv4/route.c b/net/ipv4/route.c index c035251beb0..fd9ecb52c66 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -70,7 +70,6 @@  #include <linux/types.h>  #include <linux/kernel.h>  #include <linux/mm.h> -#include <linux/bootmem.h>  #include <linux/string.h>  #include <linux/socket.h>  #include <linux/sockios.h> @@ -80,7 +79,6 @@  #include <linux/netdevice.h>  #include <linux/proc_fs.h>  #include <linux/init.h> -#include <linux/workqueue.h>  #include <linux/skbuff.h>  #include <linux/inetdevice.h>  #include <linux/igmp.h> @@ -88,11 +86,9 @@  #include <linux/mroute.h>  #include <linux/netfilter_ipv4.h>  #include <linux/random.h> -#include <linux/jhash.h>  #include <linux/rcupdate.h>  #include <linux/times.h>  #include <linux/slab.h> -#include <linux/prefetch.h>  #include <net/dst.h>  #include <net/net_namespace.h>  #include <net/protocol.h> @@ -2032,7 +2028,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)  		}  		dev_out = net->loopback_dev;  		fl4->flowi4_oif = dev_out->ifindex; -		res.fi = NULL;  		flags |= RTCF_LOCAL;  		goto make_route;  	} diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index e7e6eeae49c..2109ff4a1da 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -811,7 +811,9 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now,  			   old_size_goal + mss_now > xmit_size_goal)) {  			xmit_size_goal = old_size_goal;  		} else { -			tp->xmit_size_goal_segs = xmit_size_goal / mss_now; +			tp->xmit_size_goal_segs = +				min_t(u16, xmit_size_goal / mss_now, +				      sk->sk_gso_max_segs);  			xmit_size_goal = tp->xmit_size_goal_segs * mss_now;  		}  	} diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 4d4db16e336..1432cdb0644 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -291,7 +291,8 @@ bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight)  	left = tp->snd_cwnd - in_flight;  	if (sk_can_gso(sk) &&  	    left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && -	    left * tp->mss_cache < sk->sk_gso_max_size) +	    left * tp->mss_cache < sk->sk_gso_max_size && +	    left < sk->sk_gso_max_segs)  		return true;  	return left <= tcp_max_tso_deferred_mss(tp);  } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2fd2bc9e3c6..85308b90df8 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5392,6 +5392,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,  {  	struct tcp_sock *tp = tcp_sk(sk); +	if (unlikely(sk->sk_rx_dst == NULL)) +		inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb);  	/*  	 *	Header prediction.  	 *	The code loosely follows the one in the famous @@ -5605,7 +5607,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)  	tcp_set_state(sk, TCP_ESTABLISHED);  	if (skb != NULL) { -		inet_sk_rx_dst_set(sk, skb); +		icsk->icsk_af_ops->sk_rx_dst_set(sk, skb);  		security_inet_conn_established(sk, skb);  	} diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 42b2a6a7309..00a748d1406 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -417,10 +417,12 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)  		if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */  			tp->mtu_info = info; -			if (!sock_owned_by_user(sk)) +			if (!sock_owned_by_user(sk)) {  				tcp_v4_mtu_reduced(sk); -			else -				set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags); +			} else { +				if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags)) +					sock_hold(sk); +			}  			goto out;  		} @@ -1462,6 +1464,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,  		goto exit_nonewsk;  	newsk->sk_gso_type = SKB_GSO_TCPV4; +	inet_sk_rx_dst_set(newsk, skb);  	newtp		      = tcp_sk(newsk);  	newinet		      = inet_sk(newsk); @@ -1627,9 +1630,6 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)  				sk->sk_rx_dst = NULL;  			}  		} -		if (unlikely(sk->sk_rx_dst == NULL)) -			inet_sk_rx_dst_set(sk, skb); -  		if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {  			rsk = sk;  			goto reset; @@ -1872,10 +1872,21 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = {  	.twsk_destructor= tcp_twsk_destructor,  }; +void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +{ +	struct dst_entry *dst = skb_dst(skb); + +	dst_hold(dst); +	sk->sk_rx_dst = dst; +	inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; +} +EXPORT_SYMBOL(inet_sk_rx_dst_set); +  const struct inet_connection_sock_af_ops ipv4_specific = {  	.queue_xmit	   = ip_queue_xmit,  	.send_check	   = tcp_v4_send_check,  	.rebuild_header	   = inet_sk_rebuild_header, +	.sk_rx_dst_set	   = inet_sk_rx_dst_set,  	.conn_request	   = tcp_v4_conn_request,  	.syn_recv_sock	   = tcp_v4_syn_recv_sock,  	.net_header_len	   = sizeof(struct iphdr), diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 2288a6399e1..0abe67bb4d3 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -731,6 +731,18 @@ static int __net_init tcp_net_metrics_init(struct net *net)  static void __net_exit tcp_net_metrics_exit(struct net *net)  { +	unsigned int i; + +	for (i = 0; i < (1U << net->ipv4.tcp_metrics_hash_log) ; i++) { +		struct tcp_metrics_block *tm, *next; + +		tm = rcu_dereference_protected(net->ipv4.tcp_metrics_hash[i].chain, 1); +		while (tm) { +			next = rcu_dereference_protected(tm->tcpm_next, 1); +			kfree(tm); +			tm = next; +		} +	}  	kfree(net->ipv4.tcp_metrics_hash);  } diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 232a90c3ec8..6ff7f10dce9 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -387,8 +387,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,  		struct tcp_sock *oldtp = tcp_sk(sk);  		struct tcp_cookie_values *oldcvp = oldtp->cookie_values; -		inet_sk_rx_dst_set(newsk, skb); -  		/* TCP Cookie Transactions require space for the cookie pair,  		 * as it differs for each connection.  There is no need to  		 * copy any s_data_payload stored at the original socket. diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3f1bcff0b10..d04632673a9 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -910,14 +910,18 @@ void tcp_release_cb(struct sock *sk)  	if (flags & (1UL << TCP_TSQ_DEFERRED))  		tcp_tsq_handler(sk); -	if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) +	if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) {  		tcp_write_timer_handler(sk); - -	if (flags & (1UL << TCP_DELACK_TIMER_DEFERRED)) +		__sock_put(sk); +	} +	if (flags & (1UL << TCP_DELACK_TIMER_DEFERRED)) {  		tcp_delack_timer_handler(sk); - -	if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) +		__sock_put(sk); +	} +	if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) {  		sk->sk_prot->mtu_reduced(sk); +		__sock_put(sk); +	}  }  EXPORT_SYMBOL(tcp_release_cb); @@ -940,7 +944,7 @@ void __init tcp_tasklet_init(void)   * We cant xmit new skbs from this context, as we might already   * hold qdisc lock.   */ -void tcp_wfree(struct sk_buff *skb) +static void tcp_wfree(struct sk_buff *skb)  {  	struct sock *sk = skb->sk;  	struct tcp_sock *tp = tcp_sk(sk); @@ -1522,21 +1526,21 @@ static void tcp_cwnd_validate(struct sock *sk)   * when we would be allowed to send the split-due-to-Nagle skb fully.   */  static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb, -					unsigned int mss_now, unsigned int cwnd) +					unsigned int mss_now, unsigned int max_segs)  {  	const struct tcp_sock *tp = tcp_sk(sk); -	u32 needed, window, cwnd_len; +	u32 needed, window, max_len;  	window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; -	cwnd_len = mss_now * cwnd; +	max_len = mss_now * max_segs; -	if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk))) -		return cwnd_len; +	if (likely(max_len <= window && skb != tcp_write_queue_tail(sk))) +		return max_len;  	needed = min(skb->len, window); -	if (cwnd_len <= needed) -		return cwnd_len; +	if (max_len <= needed) +		return max_len;  	return needed - needed % mss_now;  } @@ -1765,7 +1769,8 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)  	limit = min(send_win, cong_win);  	/* If a full-sized TSO skb can be sent, do it. */ -	if (limit >= sk->sk_gso_max_size) +	if (limit >= min_t(unsigned int, sk->sk_gso_max_size, +			   sk->sk_gso_max_segs * tp->mss_cache))  		goto send_now;  	/* Middle in queue won't get any more data, full sendable already? */ @@ -1999,7 +2004,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,  		limit = mss_now;  		if (tso_segs > 1 && !tcp_urg_mode(tp))  			limit = tcp_mss_split_point(sk, skb, mss_now, -						    cwnd_quota); +						    min_t(unsigned int, +							  cwnd_quota, +							  sk->sk_gso_max_segs));  		if (skb->len > limit &&  		    unlikely(tso_fragment(sk, skb, limit, mss_now, gfp))) diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 6df36ad55a3..b774a03bd1d 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -252,7 +252,8 @@ static void tcp_delack_timer(unsigned long data)  		inet_csk(sk)->icsk_ack.blocked = 1;  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED);  		/* deleguate our work to tcp_release_cb() */ -		set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); +		if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) +			sock_hold(sk);  	}  	bh_unlock_sock(sk);  	sock_put(sk); @@ -481,7 +482,8 @@ static void tcp_write_timer(unsigned long data)  		tcp_write_timer_handler(sk);  	} else {  		/* deleguate our work to tcp_release_cb() */ -		set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); +		if (!test_and_set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) +			sock_hold(sk);  	}  	bh_unlock_sock(sk);  	sock_put(sk); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b4c3582a991..6f6d1aca3c3 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -758,7 +758,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4)  		uh->check = CSUM_MANGLED_0;  send: -	err = ip_send_skb(skb); +	err = ip_send_skb(sock_net(sk), skb);  	if (err) {  		if (err == -ENOBUFS && !inet->recverr) {  			UDP_INC_STATS_USER(sock_net(sk), diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 79181819a24..6bc85f7c31e 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -494,8 +494,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf)  	struct net_device *dev;  	struct inet6_dev *idev; -	rcu_read_lock(); -	for_each_netdev_rcu(net, dev) { +	for_each_netdev(net, dev) {  		idev = __in6_dev_get(dev);  		if (idev) {  			int changed = (!idev->cnf.forwarding) ^ (!newf); @@ -504,7 +503,6 @@ static void addrconf_forward_change(struct net *net, __s32 newf)  				dev_forward_change(idev);  		}  	} -	rcu_read_unlock();  }  static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index da2e92d05c1..745a3204295 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -307,10 +307,10 @@ static int __net_init ipv6_proc_init_net(struct net *net)  		goto proc_dev_snmp6_fail;  	return 0; +proc_dev_snmp6_fail: +	proc_net_remove(net, "snmp6");  proc_snmp6_fail:  	proc_net_remove(net, "sockstat6"); -proc_dev_snmp6_fail: -	proc_net_remove(net, "dev_snmp6");  	return -ENOMEM;  } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index c66b90f71c9..a3e60cc04a8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -94,6 +94,18 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,  }  #endif +static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +{ +	struct dst_entry *dst = skb_dst(skb); +	const struct rt6_info *rt = (const struct rt6_info *)dst; + +	dst_hold(dst); +	sk->sk_rx_dst = dst; +	inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; +	if (rt->rt6i_node) +		inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; +} +  static void tcp_v6_hash(struct sock *sk)  {  	if (sk->sk_state != TCP_CLOSE) { @@ -1270,6 +1282,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,  	newsk->sk_gso_type = SKB_GSO_TCPV6;  	__ip6_dst_store(newsk, dst, NULL, NULL); +	inet6_sk_rx_dst_set(newsk, skb);  	newtcp6sk = (struct tcp6_sock *)newsk;  	inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; @@ -1447,7 +1460,17 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)  		opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC));  	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ +		struct dst_entry *dst = sk->sk_rx_dst; +  		sock_rps_save_rxhash(sk, skb); +		if (dst) { +			if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || +			    dst->ops->check(dst, np->rx_dst_cookie) == NULL) { +				dst_release(dst); +				sk->sk_rx_dst = NULL; +			} +		} +  		if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len))  			goto reset;  		if (opt_skb) @@ -1705,9 +1728,9 @@ static void tcp_v6_early_demux(struct sk_buff *skb)  			struct dst_entry *dst = sk->sk_rx_dst;  			struct inet_sock *icsk = inet_sk(sk);  			if (dst) -				dst = dst_check(dst, 0); +				dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);  			if (dst && -			    icsk->rx_dst_ifindex == inet6_iif(skb)) +			    icsk->rx_dst_ifindex == skb->skb_iif)  				skb_dst_set_noref(skb, dst);  		}  	} @@ -1723,6 +1746,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = {  	.queue_xmit	   = inet6_csk_xmit,  	.send_check	   = tcp_v6_send_check,  	.rebuild_header	   = inet6_sk_rebuild_header, +	.sk_rx_dst_set	   = inet6_sk_rx_dst_set,  	.conn_request	   = tcp_v6_conn_request,  	.syn_recv_sock	   = tcp_v6_syn_recv_sock,  	.net_header_len	   = sizeof(struct ipv6hdr), @@ -1754,6 +1778,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = {  	.queue_xmit	   = ip_queue_xmit,  	.send_check	   = tcp_v4_send_check,  	.rebuild_header	   = inet_sk_rebuild_header, +	.sk_rx_dst_set	   = inet_sk_rx_dst_set,  	.conn_request	   = tcp_v6_conn_request,  	.syn_recv_sock	   = tcp_v6_syn_recv_sock,  	.net_header_len	   = sizeof(struct iphdr), diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index ef39812107b..f8c4c08ffb6 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -73,6 +73,13 @@ static int xfrm6_get_tos(const struct flowi *fl)  	return 0;  } +static void xfrm6_init_dst(struct net *net, struct xfrm_dst *xdst) +{ +	struct rt6_info *rt = (struct rt6_info *)xdst; + +	rt6_init_peer(rt, net->ipv6.peers); +} +  static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst,  			   int nfheader_len)  { @@ -286,6 +293,7 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {  	.get_saddr = 		xfrm6_get_saddr,  	.decode_session =	_decode_session6,  	.get_tos =		xfrm6_get_tos, +	.init_dst =		xfrm6_init_dst,  	.init_path =		xfrm6_init_path,  	.fill_dst =		xfrm6_fill_dst,  	.blackhole_route =	ip6_blackhole_route, diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 35e1e4bde58..927547171bc 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -410,6 +410,7 @@ static int l2tp_ip6_getname(struct socket *sock, struct sockaddr *uaddr,  	lsa->l2tp_family = AF_INET6;  	lsa->l2tp_flowinfo = 0;  	lsa->l2tp_scope_id = 0; +	lsa->l2tp_unused = 0;  	if (peer) {  		if (!lsk->peer_conn_id)  			return -ENOTCONN; diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index f6fe4d40050..c2190005a11 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -969,14 +969,13 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr,  	struct sockaddr_llc sllc;  	struct sock *sk = sock->sk;  	struct llc_sock *llc = llc_sk(sk); -	int rc = 0; +	int rc = -EBADF;  	memset(&sllc, 0, sizeof(sllc));  	lock_sock(sk);  	if (sock_flag(sk, SOCK_ZAPPED))  		goto out;  	*uaddrlen = sizeof(sllc); -	memset(uaddr, 0, *uaddrlen);  	if (peer) {  		rc = -ENOTCONN;  		if (sk->sk_state != TCP_ESTABLISHED) @@ -1206,7 +1205,7 @@ static int __init llc2_init(void)  	rc = llc_proc_init();  	if (rc != 0) {  		printk(llc_proc_err_msg); -		goto out_unregister_llc_proto; +		goto out_station;  	}  	rc = llc_sysctl_init();  	if (rc) { @@ -1226,7 +1225,8 @@ out_sysctl:  	llc_sysctl_exit();  out_proc:  	llc_proc_exit(); -out_unregister_llc_proto: +out_station: +	llc_station_exit();  	proto_unregister(&llc_proto);  	goto out;  } diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index e32cab44ea9..dd3e83328ad 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -42,6 +42,7 @@ static void (*llc_type_handlers[2])(struct llc_sap *sap,  void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,  					    struct sk_buff *skb))  { +	smp_wmb(); /* ensure initialisation is complete before it's called */  	if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)  		llc_type_handlers[type - 1] = handler;  } @@ -50,11 +51,19 @@ void llc_remove_pack(int type)  {  	if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)  		llc_type_handlers[type - 1] = NULL; +	synchronize_net();  }  void llc_set_station_handler(void (*handler)(struct sk_buff *skb))  { +	/* Ensure initialisation is complete before it's called */ +	if (handler) +		smp_wmb(); +  	llc_station_handler = handler; + +	if (!handler) +		synchronize_net();  }  /** @@ -150,6 +159,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,  	int dest;  	int (*rcv)(struct sk_buff *, struct net_device *,  		   struct packet_type *, struct net_device *); +	void (*sta_handler)(struct sk_buff *skb); +	void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb);  	if (!net_eq(dev_net(dev), &init_net))  		goto drop; @@ -182,7 +193,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,  	 */  	rcv = rcu_dereference(sap->rcv_func);  	dest = llc_pdu_type(skb); -	if (unlikely(!dest || !llc_type_handlers[dest - 1])) { +	sap_handler = dest ? ACCESS_ONCE(llc_type_handlers[dest - 1]) : NULL; +	if (unlikely(!sap_handler)) {  		if (rcv)  			rcv(skb, dev, pt, orig_dev);  		else @@ -193,7 +205,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,  			if (cskb)  				rcv(cskb, dev, pt, orig_dev);  		} -		llc_type_handlers[dest - 1](sap, skb); +		sap_handler(sap, skb);  	}  	llc_sap_put(sap);  out: @@ -202,9 +214,10 @@ drop:  	kfree_skb(skb);  	goto out;  handle_station: -	if (!llc_station_handler) +	sta_handler = ACCESS_ONCE(llc_station_handler); +	if (!sta_handler)  		goto drop; -	llc_station_handler(skb); +	sta_handler(skb);  	goto out;  } diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 39a8d8924b9..b2f2bac2c2a 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -268,7 +268,7 @@ static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb)  out:  	return rc;  free: -	kfree_skb(skb); +	kfree_skb(nskb);  	goto out;  } @@ -293,7 +293,7 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb)  out:  	return rc;  free: -	kfree_skb(skb); +	kfree_skb(nskb);  	goto out;  } @@ -322,7 +322,7 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb)  out:  	return rc;  free: -	kfree_skb(skb); +	kfree_skb(nskb);  	goto out;  } @@ -687,12 +687,8 @@ static void llc_station_rcv(struct sk_buff *skb)  	llc_station_state_process(skb);  } -int __init llc_station_init(void) +void __init llc_station_init(void)  { -	int rc = -ENOBUFS; -	struct sk_buff *skb; -	struct llc_station_state_ev *ev; -  	skb_queue_head_init(&llc_main_station.mac_pdu_q);  	skb_queue_head_init(&llc_main_station.ev_q.list);  	spin_lock_init(&llc_main_station.ev_q.lock); @@ -700,23 +696,12 @@ int __init llc_station_init(void)  			(unsigned long)&llc_main_station);  	llc_main_station.ack_timer.expires  = jiffies +  						sysctl_llc_station_ack_timeout; -	skb = alloc_skb(0, GFP_ATOMIC); -	if (!skb) -		goto out; -	rc = 0; -	llc_set_station_handler(llc_station_rcv); -	ev = llc_station_ev(skb); -	memset(ev, 0, sizeof(*ev));  	llc_main_station.maximum_retry	= 1; -	llc_main_station.state		= LLC_STATION_STATE_DOWN; -	ev->type	= LLC_STATION_EV_TYPE_SIMPLE; -	ev->prim_type	= LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; -	rc = llc_station_next_state(skb); -out: -	return rc; +	llc_main_station.state		= LLC_STATION_STATE_UP; +	llc_set_station_handler(llc_station_rcv);  } -void __exit llc_station_exit(void) +void llc_station_exit(void)  {  	llc_set_station_handler(NULL);  } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6fac18c0423..85572353a7e 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -622,6 +622,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)  	del_timer_sync(&sdata->u.mesh.housekeeping_timer);  	del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); +	del_timer_sync(&sdata->u.mesh.mesh_path_timer);  	/*  	 * If the timer fired while we waited for it, it will have  	 * requeued the work. Now the work will be running again @@ -634,6 +635,8 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)  	local->fif_other_bss--;  	atomic_dec(&local->iff_allmultis);  	ieee80211_configure_filter(local); + +	sdata->u.mesh.timers_running = 0;  }  static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index cef0c9e79ab..a4a5acdbaa4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1430,6 +1430,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,  	del_timer_sync(&sdata->u.mgd.bcn_mon_timer);  	del_timer_sync(&sdata->u.mgd.timer);  	del_timer_sync(&sdata->u.mgd.chswitch_timer); + +	sdata->u.mgd.timers_running = 0;  }  void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index bcaee5d1283..839dd973798 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -299,7 +299,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,  	if (local->scan_req != local->int_scan_req)  		cfg80211_scan_done(local->scan_req, aborted);  	local->scan_req = NULL; -	local->scan_sdata = NULL; +	rcu_assign_pointer(local->scan_sdata, NULL);  	local->scanning = 0;  	local->scan_channel = NULL; @@ -984,7 +984,6 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)  			kfree(local->sched_scan_ies.ie[i]);  		drv_sched_scan_stop(local, sdata); -		rcu_assign_pointer(local->sched_scan_sdata, NULL);  	}  out:  	mutex_unlock(&local->mtx); diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 84444dda194..72bf32a8487 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2759,6 +2759,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)  	{  		struct ip_vs_timeout_user t; +		memset(&t, 0, sizeof(t));  		__ip_vs_get_timeouts(net, &t);  		if (copy_to_user(user, &t, sizeof(t)) != 0)  			ret = -EFAULT; diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 45cf602a76b..527651a53a4 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -361,23 +361,6 @@ static void evict_oldest_expect(struct nf_conn *master,  	}  } -static inline int refresh_timer(struct nf_conntrack_expect *i) -{ -	struct nf_conn_help *master_help = nfct_help(i->master); -	const struct nf_conntrack_expect_policy *p; - -	if (!del_timer(&i->timeout)) -		return 0; - -	p = &rcu_dereference_protected( -		master_help->helper, -		lockdep_is_held(&nf_conntrack_lock) -		)->expect_policy[i->class]; -	i->timeout.expires = jiffies + p->timeout * HZ; -	add_timer(&i->timeout); -	return 1; -} -  static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)  {  	const struct nf_conntrack_expect_policy *p; @@ -386,7 +369,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)  	struct nf_conn_help *master_help = nfct_help(master);  	struct nf_conntrack_helper *helper;  	struct net *net = nf_ct_exp_net(expect); -	struct hlist_node *n; +	struct hlist_node *n, *next;  	unsigned int h;  	int ret = 1; @@ -395,12 +378,12 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)  		goto out;  	}  	h = nf_ct_expect_dst_hash(&expect->tuple); -	hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { +	hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) {  		if (expect_matches(i, expect)) { -			/* Refresh timer: if it's dying, ignore.. */ -			if (refresh_timer(i)) { -				ret = 0; -				goto out; +			if (del_timer(&i->timeout)) { +				nf_ct_unlink_expect(i); +				nf_ct_expect_put(i); +				break;  			}  		} else if (expect_clash(i, expect)) {  			ret = -EBUSY; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 14f67a2cbcb..da4fc37a857 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1896,10 +1896,15 @@ static int  ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct)  {  	struct nlattr *cda[CTA_MAX+1]; +	int ret;  	nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy); -	return ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); +	spin_lock_bh(&nf_conntrack_lock); +	ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); +	spin_unlock_bh(&nf_conntrack_lock); + +	return ret;  }  static struct nfq_ct_hook ctnetlink_nfqueue_hook = { diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 758a1bacc12..5c0a112aeee 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -183,12 +183,12 @@ static int media_len(const struct nf_conn *ct, const char *dptr,  	return len + digits_len(ct, dptr, limit, shift);  } -static int parse_addr(const struct nf_conn *ct, const char *cp, -                      const char **endp, union nf_inet_addr *addr, -                      const char *limit) +static int sip_parse_addr(const struct nf_conn *ct, const char *cp, +			  const char **endp, union nf_inet_addr *addr, +			  const char *limit, bool delim)  {  	const char *end; -	int ret = 0; +	int ret;  	if (!ct)  		return 0; @@ -197,16 +197,28 @@ static int parse_addr(const struct nf_conn *ct, const char *cp,  	switch (nf_ct_l3num(ct)) {  	case AF_INET:  		ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); +		if (ret == 0) +			return 0;  		break;  	case AF_INET6: +		if (cp < limit && *cp == '[') +			cp++; +		else if (delim) +			return 0; +  		ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); +		if (ret == 0) +			return 0; + +		if (end < limit && *end == ']') +			end++; +		else if (delim) +			return 0;  		break;  	default:  		BUG();  	} -	if (ret == 0 || end == cp) -		return 0;  	if (endp)  		*endp = end;  	return 1; @@ -219,7 +231,7 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr,  	union nf_inet_addr addr;  	const char *aux = dptr; -	if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { +	if (!sip_parse_addr(ct, dptr, &dptr, &addr, limit, true)) {  		pr_debug("ip: %s parse failed.!\n", dptr);  		return 0;  	} @@ -296,7 +308,7 @@ int ct_sip_parse_request(const struct nf_conn *ct,  		return 0;  	dptr += shift; -	if (!parse_addr(ct, dptr, &end, addr, limit)) +	if (!sip_parse_addr(ct, dptr, &end, addr, limit, true))  		return -1;  	if (end < limit && *end == ':') {  		end++; @@ -550,7 +562,7 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,  	if (ret == 0)  		return ret; -	if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit)) +	if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true))  		return -1;  	if (*c == ':') {  		c++; @@ -599,7 +611,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,  			       unsigned int dataoff, unsigned int datalen,  			       const char *name,  			       unsigned int *matchoff, unsigned int *matchlen, -			       union nf_inet_addr *addr) +			       union nf_inet_addr *addr, bool delim)  {  	const char *limit = dptr + datalen;  	const char *start, *end; @@ -613,7 +625,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,  		return 0;  	start += strlen(name); -	if (!parse_addr(ct, start, &end, addr, limit)) +	if (!sip_parse_addr(ct, start, &end, addr, limit, delim))  		return 0;  	*matchoff = start - dptr;  	*matchlen = end - start; @@ -675,6 +687,47 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr,  	return 1;  } +static int sdp_parse_addr(const struct nf_conn *ct, const char *cp, +			  const char **endp, union nf_inet_addr *addr, +			  const char *limit) +{ +	const char *end; +	int ret; + +	memset(addr, 0, sizeof(*addr)); +	switch (nf_ct_l3num(ct)) { +	case AF_INET: +		ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); +		break; +	case AF_INET6: +		ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); +		break; +	default: +		BUG(); +	} + +	if (ret == 0) +		return 0; +	if (endp) +		*endp = end; +	return 1; +} + +/* skip ip address. returns its length. */ +static int sdp_addr_len(const struct nf_conn *ct, const char *dptr, +			const char *limit, int *shift) +{ +	union nf_inet_addr addr; +	const char *aux = dptr; + +	if (!sdp_parse_addr(ct, dptr, &dptr, &addr, limit)) { +		pr_debug("ip: %s parse failed.!\n", dptr); +		return 0; +	} + +	return dptr - aux; +} +  /* SDP header parsing: a SDP session description contains an ordered set of   * headers, starting with a section containing general session parameters,   * optionally followed by multiple media descriptions. @@ -686,10 +739,10 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr,   */  static const struct sip_header ct_sdp_hdrs[] = {  	[SDP_HDR_VERSION]		= SDP_HDR("v=", NULL, digits_len), -	[SDP_HDR_OWNER_IP4]		= SDP_HDR("o=", "IN IP4 ", epaddr_len), -	[SDP_HDR_CONNECTION_IP4]	= SDP_HDR("c=", "IN IP4 ", epaddr_len), -	[SDP_HDR_OWNER_IP6]		= SDP_HDR("o=", "IN IP6 ", epaddr_len), -	[SDP_HDR_CONNECTION_IP6]	= SDP_HDR("c=", "IN IP6 ", epaddr_len), +	[SDP_HDR_OWNER_IP4]		= SDP_HDR("o=", "IN IP4 ", sdp_addr_len), +	[SDP_HDR_CONNECTION_IP4]	= SDP_HDR("c=", "IN IP4 ", sdp_addr_len), +	[SDP_HDR_OWNER_IP6]		= SDP_HDR("o=", "IN IP6 ", sdp_addr_len), +	[SDP_HDR_CONNECTION_IP6]	= SDP_HDR("c=", "IN IP6 ", sdp_addr_len),  	[SDP_HDR_MEDIA]			= SDP_HDR("m=", NULL, media_len),  }; @@ -775,8 +828,8 @@ static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr,  	if (ret <= 0)  		return ret; -	if (!parse_addr(ct, dptr + *matchoff, NULL, addr, -			dptr + *matchoff + *matchlen)) +	if (!sdp_parse_addr(ct, dptr + *matchoff, NULL, addr, +			    dptr + *matchoff + *matchlen))  		return -1;  	return 1;  } @@ -1515,7 +1568,6 @@ static int sip_help_udp(struct sk_buff *skb, unsigned int protoff,  }  static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly; -static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly;  static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = {  	[SIP_EXPECT_SIGNALLING] = { @@ -1585,9 +1637,9 @@ static int __init nf_conntrack_sip_init(void)  			sip[i][j].me = THIS_MODULE;  			if (ports[i] == SIP_PORT) -				sprintf(sip_names[i][j], "sip"); +				sprintf(sip[i][j].name, "sip");  			else -				sprintf(sip_names[i][j], "sip-%u", i); +				sprintf(sip[i][j].name, "sip-%u", i);  			pr_debug("port #%u: %u\n", i, ports[i]); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 5463969da45..1445d73533e 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1362,7 +1362,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,  	if (NULL == siocb->scm)  		siocb->scm = &scm; -	err = scm_send(sock, msg, siocb->scm); +	err = scm_send(sock, msg, siocb->scm, true);  	if (err < 0)  		return err; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ceaca7c134a..aee7196aac3 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1079,7 +1079,7 @@ static void *packet_current_rx_frame(struct packet_sock *po,  	default:  		WARN(1, "TPACKET version not supported\n");  		BUG(); -		return 0; +		return NULL;  	}  } @@ -1273,6 +1273,14 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po)  	spin_unlock(&f->lock);  } +bool match_fanout_group(struct packet_type *ptype, struct sock * sk) +{ +	if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout) +		return true; + +	return false; +} +  static int fanout_add(struct sock *sk, u16 id, u16 type_flags)  {  	struct packet_sock *po = pkt_sk(sk); @@ -1325,6 +1333,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)  		match->prot_hook.dev = po->prot_hook.dev;  		match->prot_hook.func = packet_rcv_fanout;  		match->prot_hook.af_packet_priv = match; +		match->prot_hook.id_match = match_fanout_group;  		dev_add_pack(&match->prot_hook);  		list_add(&match->list, &fanout_list);  	} @@ -1936,7 +1945,6 @@ static void tpacket_destruct_skb(struct sk_buff *skb)  	if (likely(po->tx_ring.pg_vec)) {  		ph = skb_shinfo(skb)->destructor_arg; -		BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING);  		BUG_ON(atomic_read(&po->tx_ring.pending) == 0);  		atomic_dec(&po->tx_ring.pending);  		__packet_set_status(po, ph, TP_STATUS_AVAILABLE); diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index f10fb825644..05d60859d8e 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c @@ -67,6 +67,9 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,  	struct tcf_common *pc;  	int ret = 0;  	int err; +#ifdef CONFIG_GACT_PROB +	struct tc_gact_p *p_parm = NULL; +#endif  	if (nla == NULL)  		return -EINVAL; @@ -82,6 +85,12 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,  #ifndef CONFIG_GACT_PROB  	if (tb[TCA_GACT_PROB] != NULL)  		return -EOPNOTSUPP; +#else +	if (tb[TCA_GACT_PROB]) { +		p_parm = nla_data(tb[TCA_GACT_PROB]); +		if (p_parm->ptype >= MAX_RAND) +			return -EINVAL; +	}  #endif  	pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info); @@ -103,8 +112,7 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,  	spin_lock_bh(&gact->tcf_lock);  	gact->tcf_action = parm->action;  #ifdef CONFIG_GACT_PROB -	if (tb[TCA_GACT_PROB] != NULL) { -		struct tc_gact_p *p_parm = nla_data(tb[TCA_GACT_PROB]); +	if (p_parm) {  		gact->tcfg_paction = p_parm->paction;  		gact->tcfg_pval    = p_parm->pval;  		gact->tcfg_ptype   = p_parm->ptype; @@ -133,7 +141,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,  	spin_lock(&gact->tcf_lock);  #ifdef CONFIG_GACT_PROB -	if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL) +	if (gact->tcfg_ptype)  		action = gact_rand[gact->tcfg_ptype](gact);  	else  		action = gact->tcf_action; diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 60e281ad0f0..58fb3c7aab9 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -185,7 +185,12 @@ err3:  err2:  	kfree(tname);  err1: -	kfree(pc); +	if (ret == ACT_P_CREATED) { +		if (est) +			gen_kill_estimator(&pc->tcfc_bstats, +					   &pc->tcfc_rate_est); +		kfree_rcu(pc, tcfc_rcu); +	}  	return err;  } diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index fe81cc18e9e..9c0fd0c7881 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c @@ -200,13 +200,12 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,  out:  	if (err) {  		m->tcf_qstats.overlimits++; -		/* should we be asking for packet to be dropped? -		 * may make sense for redirect case only -		 */ -		retval = TC_ACT_SHOT; -	} else { +		if (m->tcfm_eaction != TCA_EGRESS_MIRROR) +			retval = TC_ACT_SHOT; +		else +			retval = m->tcf_action; +	} else  		retval = m->tcf_action; -	}  	spin_unlock(&m->tcf_lock);  	return retval; diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 26aa2f6ce25..45c53ab067a 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -74,7 +74,10 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,  		p = to_pedit(pc);  		keys = kmalloc(ksize, GFP_KERNEL);  		if (keys == NULL) { -			kfree(pc); +			if (est) +				gen_kill_estimator(&pc->tcfc_bstats, +						   &pc->tcfc_rate_est); +			kfree_rcu(pc, tcfc_rcu);  			return -ENOMEM;  		}  		ret = ACT_P_CREATED; diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 3922f2a2821..3714f60f0b3 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c @@ -131,7 +131,10 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,  		d = to_defact(pc);  		ret = alloc_defdata(d, defdata);  		if (ret < 0) { -			kfree(pc); +			if (est) +				gen_kill_estimator(&pc->tcfc_bstats, +						   &pc->tcfc_rate_est); +			kfree_rcu(pc, tcfc_rcu);  			return ret;  		}  		d->tcf_action = parm->action; diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index 9af01f3df18..e4723d31fdd 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -203,6 +203,34 @@ out:  	return index;  } +/* Length of the next packet (0 if the queue is empty). */ +static unsigned int qdisc_peek_len(struct Qdisc *sch) +{ +	struct sk_buff *skb; + +	skb = sch->ops->peek(sch); +	return skb ? qdisc_pkt_len(skb) : 0; +} + +static void qfq_deactivate_class(struct qfq_sched *, struct qfq_class *); +static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl, +			       unsigned int len); + +static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl, +				    u32 lmax, u32 inv_w, int delta_w) +{ +	int i; + +	/* update qfq-specific data */ +	cl->lmax = lmax; +	cl->inv_w = inv_w; +	i = qfq_calc_index(cl->inv_w, cl->lmax); + +	cl->grp = &q->groups[i]; + +	q->wsum += delta_w; +} +  static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,  			    struct nlattr **tca, unsigned long *arg)  { @@ -250,6 +278,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,  		lmax = 1UL << QFQ_MTU_SHIFT;  	if (cl != NULL) { +		bool need_reactivation = false; +  		if (tca[TCA_RATE]) {  			err = gen_replace_estimator(&cl->bstats, &cl->rate_est,  						    qdisc_root_sleeping_lock(sch), @@ -258,12 +288,29 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,  				return err;  		} -		if (inv_w != cl->inv_w) { -			sch_tree_lock(sch); -			q->wsum += delta_w; -			cl->inv_w = inv_w; -			sch_tree_unlock(sch); +		if (lmax == cl->lmax && inv_w == cl->inv_w) +			return 0; /* nothing to update */ + +		i = qfq_calc_index(inv_w, lmax); +		sch_tree_lock(sch); +		if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) { +			/* +			 * shift cl->F back, to not charge the +			 * class for the not-yet-served head +			 * packet +			 */ +			cl->F = cl->S; +			/* remove class from its slot in the old group */ +			qfq_deactivate_class(q, cl); +			need_reactivation = true;  		} + +		qfq_update_class_params(q, cl, lmax, inv_w, delta_w); + +		if (need_reactivation) /* activate in new group */ +			qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc)); +		sch_tree_unlock(sch); +  		return 0;  	} @@ -273,11 +320,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,  	cl->refcnt = 1;  	cl->common.classid = classid; -	cl->lmax = lmax; -	cl->inv_w = inv_w; -	i = qfq_calc_index(cl->inv_w, cl->lmax); -	cl->grp = &q->groups[i]; +	qfq_update_class_params(q, cl, lmax, inv_w, delta_w);  	cl->qdisc = qdisc_create_dflt(sch->dev_queue,  				      &pfifo_qdisc_ops, classid); @@ -294,7 +338,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,  			return err;  		}  	} -	q->wsum += weight;  	sch_tree_lock(sch);  	qdisc_class_hash_insert(&q->clhash, &cl->common); @@ -711,15 +754,6 @@ static void qfq_update_eligible(struct qfq_sched *q, u64 old_V)  	}  } -/* What is length of next packet in queue (0 if queue is empty) */ -static unsigned int qdisc_peek_len(struct Qdisc *sch) -{ -	struct sk_buff *skb; - -	skb = sch->ops->peek(sch); -	return skb ? qdisc_pkt_len(skb) : 0; -} -  /*   * Updates the class, returns true if also the group needs to be updated.   */ @@ -843,11 +877,8 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)  static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)  {  	struct qfq_sched *q = qdisc_priv(sch); -	struct qfq_group *grp;  	struct qfq_class *cl;  	int err; -	u64 roundedS; -	int s;  	cl = qfq_classify(skb, sch, &err);  	if (cl == NULL) { @@ -876,11 +907,25 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)  		return err;  	/* If reach this point, queue q was idle */ -	grp = cl->grp; +	qfq_activate_class(q, cl, qdisc_pkt_len(skb)); + +	return err; +} + +/* + * Handle class switch from idle to backlogged. + */ +static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl, +			       unsigned int pkt_len) +{ +	struct qfq_group *grp = cl->grp; +	u64 roundedS; +	int s; +  	qfq_update_start(q, cl);  	/* compute new finish time and rounded start. */ -	cl->F = cl->S + (u64)qdisc_pkt_len(skb) * cl->inv_w; +	cl->F = cl->S + (u64)pkt_len * cl->inv_w;  	roundedS = qfq_round_down(cl->S, grp->slot_shift);  	/* @@ -917,8 +962,6 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)  skip_update:  	qfq_slot_insert(grp, cl, roundedS); - -	return err;  } diff --git a/net/socket.c b/net/socket.c index dfe5b66c97e..a5471f804d9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2657,6 +2657,7 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)  	if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf)))  		return -EFAULT; +	memset(&ifc, 0, sizeof(ifc));  	if (ifc32.ifcbuf == 0) {  		ifc32.ifc_len = 0;  		ifc.ifc_len = 0; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index e4768c180da..c5ee4ff6136 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1450,7 +1450,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,  	if (NULL == siocb->scm)  		siocb->scm = &tmp_scm;  	wait_for_unix_gc(); -	err = scm_send(sock, msg, siocb->scm); +	err = scm_send(sock, msg, siocb->scm, false);  	if (err < 0)  		return err; @@ -1619,7 +1619,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,  	if (NULL == siocb->scm)  		siocb->scm = &tmp_scm;  	wait_for_unix_gc(); -	err = scm_send(sock, msg, siocb->scm); +	err = scm_send(sock, msg, siocb->scm, false);  	if (err < 0)  		return err; diff --git a/net/wireless/core.c b/net/wireless/core.c index 31b40cc4a9c..dcd64d5b07a 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -952,6 +952,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,  		 */  		synchronize_rcu();  		INIT_LIST_HEAD(&wdev->list); +		/* +		 * Ensure that all events have been processed and +		 * freed. +		 */ +		cfg80211_process_wdev_events(wdev);  		break;  	case NETDEV_PRE_UP:  		if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) diff --git a/net/wireless/core.h b/net/wireless/core.h index 5206c6844fd..bc7430b5477 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -426,6 +426,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,  			  struct net_device *dev, enum nl80211_iftype ntype,  			  u32 *flags, struct vif_params *params);  void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); +void cfg80211_process_wdev_events(struct wireless_dev *wdev);  int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,  				 struct wireless_dev *wdev, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2303ee73b50..2ded3c7fad0 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -680,6 +680,8 @@ static u32 map_regdom_flags(u32 rd_flags)  		channel_flags |= IEEE80211_CHAN_NO_IBSS;  	if (rd_flags & NL80211_RRF_DFS)  		channel_flags |= IEEE80211_CHAN_RADAR; +	if (rd_flags & NL80211_RRF_NO_OFDM) +		channel_flags |= IEEE80211_CHAN_NO_OFDM;  	return channel_flags;  } @@ -901,7 +903,21 @@ static void handle_channel(struct wiphy *wiphy,  	chan->max_antenna_gain = min(chan->orig_mag,  		(int) MBI_TO_DBI(power_rule->max_antenna_gain));  	chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); -	chan->max_power = min(chan->max_power, chan->max_reg_power); +	if (chan->orig_mpwr) { +		/* +		 * Devices that have their own custom regulatory domain +		 * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the +		 * passed country IE power settings. +		 */ +		if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && +		    wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && +		    wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) +			chan->max_power = chan->max_reg_power; +		else +			chan->max_power = min(chan->orig_mpwr, +					      chan->max_reg_power); +	} else +		chan->max_power = chan->max_reg_power;  }  static void handle_band(struct wiphy *wiphy, @@ -1885,6 +1901,7 @@ static void restore_custom_reg_settings(struct wiphy *wiphy)  			chan->flags = chan->orig_flags;  			chan->max_antenna_gain = chan->orig_mag;  			chan->max_power = chan->orig_mpwr; +			chan->beacon_found = false;  		}  	}  } diff --git a/net/wireless/util.c b/net/wireless/util.c index 26f8cd30f71..994e2f0cc7a 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -735,7 +735,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)  	wdev->connect_keys = NULL;  } -static void cfg80211_process_wdev_events(struct wireless_dev *wdev) +void cfg80211_process_wdev_events(struct wireless_dev *wdev)  {  	struct cfg80211_event *ev;  	unsigned long flags; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index c5a5165a592..5a2aa17e4d3 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1357,6 +1357,8 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)  		memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst));  		xdst->flo.ops = &xfrm_bundle_fc_ops; +		if (afinfo->init_dst) +			afinfo->init_dst(net, xdst);  	} else  		xdst = ERR_PTR(-ENOBUFS); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5b228f97d4b..87cd0e4d428 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -415,8 +415,17 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)  	if (x->lft.hard_add_expires_seconds) {  		long tmo = x->lft.hard_add_expires_seconds +  			x->curlft.add_time - now; -		if (tmo <= 0) -			goto expired; +		if (tmo <= 0) { +			if (x->xflags & XFRM_SOFT_EXPIRE) { +				/* enter hard expire without soft expire first?! +				 * setting a new date could trigger this. +				 * workarbound: fix x->curflt.add_time by below: +				 */ +				x->curlft.add_time = now - x->saved_tmo - 1; +				tmo = x->lft.hard_add_expires_seconds - x->saved_tmo; +			} else +				goto expired; +		}  		if (tmo < next)  			next = tmo;  	} @@ -433,10 +442,14 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me)  	if (x->lft.soft_add_expires_seconds) {  		long tmo = x->lft.soft_add_expires_seconds +  			x->curlft.add_time - now; -		if (tmo <= 0) +		if (tmo <= 0) {  			warn = 1; -		else if (tmo < next) +			x->xflags &= ~XFRM_SOFT_EXPIRE; +		} else if (tmo < next) {  			next = tmo; +			x->xflags |= XFRM_SOFT_EXPIRE; +			x->saved_tmo = tmo; +		}  	}  	if (x->lft.soft_use_expires_seconds) {  		long tmo = x->lft.soft_use_expires_seconds + diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 913d6bdfdda..ca05ba217f5 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3016,7 +3016,8 @@ sub process {  					$herectx .= raw_line($linenr, $n) . "\n";  				} -				if (($stmts =~ tr/;/;/) == 1) { +				if (($stmts =~ tr/;/;/) == 1 && +				    $stmts !~ /^\s*(if|while|for|switch)\b/) {  					WARN("SINGLE_STATEMENT_DO_WHILE_MACRO",  					     "Single statement macros should not use a do {} while (0) loop\n" . "$herectx");  				} diff --git a/scripts/decodecode b/scripts/decodecode index 18ba881c341..4f8248d5a11 100755 --- a/scripts/decodecode +++ b/scripts/decodecode @@ -89,7 +89,7 @@ echo $code >> $T.s  disas $T  cat $T.dis >> $T.aa -faultline=`cat $T.dis | head -1 | cut -d":" -f2` +faultline=`cat $T.dis | head -1 | cut -d":" -f2-`  faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'`  cat $T.oo | sed -e "s/\($faultline\)/\*\1     <-- trapping instruction/g" diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9b0c0b8b4ab..8fd107a3fac 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1786,6 +1786,7 @@ sub dump_function($$) {      $prototype =~ s/__init +//;      $prototype =~ s/__init_or_module +//;      $prototype =~ s/__must_check +//; +    $prototype =~ s/__weak +//;      $prototype =~ s/^#\s*define\s+//; #ak added      $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//; diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 83554ee8a58..0cc99a3ea42 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -279,12 +279,46 @@ static int yama_ptrace_access_check(struct task_struct *child,  	}  	if (rc) { -		char name[sizeof(current->comm)];  		printk_ratelimited(KERN_NOTICE  			"ptrace of pid %d was attempted by: %s (pid %d)\n", -			child->pid, -			get_task_comm(name, current), -			current->pid); +			child->pid, current->comm, current->pid); +	} + +	return rc; +} + +/** + * yama_ptrace_traceme - validate PTRACE_TRACEME calls + * @parent: task that will become the ptracer of the current task + * + * Returns 0 if following the ptrace is allowed, -ve on error. + */ +static int yama_ptrace_traceme(struct task_struct *parent) +{ +	int rc; + +	/* If standard caps disallows it, so does Yama.  We should +	 * only tighten restrictions further. +	 */ +	rc = cap_ptrace_traceme(parent); +	if (rc) +		return rc; + +	/* Only disallow PTRACE_TRACEME on more aggressive settings. */ +	switch (ptrace_scope) { +	case YAMA_SCOPE_CAPABILITY: +		if (!ns_capable(task_user_ns(parent), CAP_SYS_PTRACE)) +			rc = -EPERM; +		break; +	case YAMA_SCOPE_NO_ATTACH: +		rc = -EPERM; +		break; +	} + +	if (rc) { +		printk_ratelimited(KERN_NOTICE +			"ptraceme of pid %d was attempted by: %s (pid %d)\n", +			current->pid, parent->comm, parent->pid);  	}  	return rc; @@ -294,6 +328,7 @@ static struct security_operations yama_ops = {  	.name =			"yama",  	.ptrace_access_check =	yama_ptrace_access_check, +	.ptrace_traceme =	yama_ptrace_traceme,  	.task_prctl =		yama_task_prctl,  	.task_free =		yama_task_free,  }; diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index 0d7b25e8164..4e1fda75c1c 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c @@ -106,7 +106,7 @@ static struct pxa2xx_pcm_client pxa2xx_ac97_pcm_client = {  	.prepare		= pxa2xx_ac97_pcm_prepare,  }; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int pxa2xx_ac97_do_suspend(struct snd_card *card)  { @@ -243,7 +243,7 @@ static struct platform_driver pxa2xx_ac97_driver = {  	.driver		= {  		.name	= "pxa2xx-ac97",  		.owner	= THIS_MODULE, -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  		.pm	= &pxa2xx_ac97_pm_ops,  #endif  	}, diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c index eb4ceb71123..277ebce23a4 100644 --- a/sound/atmel/abdac.c +++ b/sound/atmel/abdac.c @@ -452,6 +452,7 @@ static int __devinit atmel_abdac_probe(struct platform_device *pdev)  	dac->regs = ioremap(regs->start, resource_size(regs));  	if (!dac->regs) {  		dev_dbg(&pdev->dev, "could not remap register memory\n"); +		retval = -ENOMEM;  		goto out_free_card;  	} @@ -534,7 +535,7 @@ out_put_pclk:  	return retval;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int atmel_abdac_suspend(struct device *pdev)  {  	struct snd_card *card = dev_get_drvdata(pdev); diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index bf47025bdf4..9052aff37f6 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -278,14 +278,9 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,  	if (retval < 0)  		return retval;  	/* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ -	if (cpu_is_at32ap7000()) { -		if (retval < 0) -			return retval; -		/* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ -		if (retval == 1) -			if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) -				dw_dma_cyclic_free(chip->dma.rx_chan); -	} +	if (cpu_is_at32ap7000() && retval == 1) +		if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) +			dw_dma_cyclic_free(chip->dma.rx_chan);  	/* Set restrictions to params. */  	mutex_lock(&opened_mutex); @@ -980,6 +975,7 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)  	if (!chip->regs) {  		dev_dbg(&pdev->dev, "could not remap register memory\n"); +		retval = -ENOMEM;  		goto err_ioremap;  	} @@ -1134,7 +1130,7 @@ err_snd_card_new:  	return retval;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int atmel_ac97c_suspend(struct device *pdev)  {  	struct snd_card *card = dev_get_drvdata(pdev); diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index 4e7ec2b4987..d0f00356fc1 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -101,7 +101,7 @@ void *snd_malloc_sgbuf_pages(struct device *device,  		if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, device,  						 chunk, &tmpb) < 0) {  			if (!sgbuf->pages) -				return NULL; +				goto _failed;  			if (!res_size)  				goto _failed;  			size = sgbuf->pages * PAGE_SIZE; diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 1128b35b2b0..5a34355e78e 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -1176,7 +1176,7 @@ static int __devexit loopback_remove(struct platform_device *devptr)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int loopback_suspend(struct device *pdev)  {  	struct snd_card *card = dev_get_drvdata(pdev); diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index f7d3bfc6bca..54bb6644a59 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -1064,7 +1064,7 @@ static int __devexit snd_dummy_remove(struct platform_device *devptr)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int snd_dummy_suspend(struct device *pdev)  {  	struct snd_card *card = dev_get_drvdata(pdev); diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 6ca59fc6dcb..ef171295f6d 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c @@ -199,7 +199,7 @@ static void pcsp_stop_beep(struct snd_pcsp *chip)  	pcspkr_stop_sound();  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int pcsp_suspend(struct device *dev)  {  	struct snd_pcsp *chip = dev_get_drvdata(dev); @@ -212,7 +212,7 @@ static SIMPLE_DEV_PM_OPS(pcsp_pm, pcsp_suspend, NULL);  #define PCSP_PM_OPS	&pcsp_pm  #else  #define PCSP_PM_OPS	NULL -#endif	/* CONFIG_PM */ +#endif	/* CONFIG_PM_SLEEP */  static void pcsp_shutdown(struct platform_device *dev)  { diff --git a/sound/isa/als100.c b/sound/isa/als100.c index 2d67c78c9f4..f7cdaf51512 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c @@ -233,7 +233,7 @@ static int __devinit snd_card_als100_probe(int dev,  			irq[dev], dma8[dev], dma16[dev]);  	} -	if ((error = snd_sb16dsp_pcm(chip, 0, NULL)) < 0) { +	if ((error = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0) {  		snd_card_free(card);  		return error;  	} diff --git a/sound/oss/sb_audio.c b/sound/oss/sb_audio.c index 733b014ec7d..b2b3c014221 100644 --- a/sound/oss/sb_audio.c +++ b/sound/oss/sb_audio.c @@ -575,13 +575,15 @@ static int jazz16_audio_set_speed(int dev, int speed)  	if (speed > 0)  	{  		int tmp; -		int s = speed * devc->channels; +		int s;  		if (speed < 5000)  			speed = 5000;  		if (speed > 44100)  			speed = 44100; +		s = speed * devc->channels; +  		devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff;  		tmp = 256 - devc->tconst; diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index f75f5ffdfdf..a71d1c14a0f 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -94,7 +94,7 @@ static unsigned short snd_cs46xx_codec_read(struct snd_cs46xx *chip,  	if (snd_BUG_ON(codec_index != CS46XX_PRIMARY_CODEC_INDEX &&  		       codec_index != CS46XX_SECONDARY_CODEC_INDEX)) -		return -EINVAL; +		return 0xffff;  	chip->active_ctrl(chip, 1); diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 8e40262d411..2f6e9c762d3 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c @@ -1725,8 +1725,10 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,  	atc_connect_resources(atc);  	atc->timer = ct_timer_new(atc); -	if (!atc->timer) +	if (!atc->timer) { +		err = -ENOMEM;  		goto error1; +	}  	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, atc, &ops);  	if (err < 0) diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 4f502a2bdc3..0a436626182 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -326,7 +326,10 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst  	for (page = blk->first_page; page <= blk->last_page; page++, idx++) {  		unsigned long ofs = idx << PAGE_SHIFT;  		dma_addr_t addr; -		addr = snd_pcm_sgbuf_get_addr(substream, ofs); +		if (ofs >= runtime->dma_bytes) +			addr = emu->silent_page.addr; +		else +			addr = snd_pcm_sgbuf_get_addr(substream, ofs);  		if (! is_valid_page(emu, addr)) {  			printk(KERN_ERR "emu: failure page = %d\n", idx);  			mutex_unlock(&hdr->block_mutex); diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 647218d69f6..4f7d2dfcef7 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -332,13 +332,12 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,  	if (cfg->dig_outs)  		snd_printd("   dig-out=0x%x/0x%x\n",  			   cfg->dig_out_pins[0], cfg->dig_out_pins[1]); -	snd_printd("   inputs:"); +	snd_printd("   inputs:\n");  	for (i = 0; i < cfg->num_inputs; i++) { -		snd_printd(" %s=0x%x", +		snd_printd("     %s=0x%x\n",  			    hda_get_autocfg_input_label(codec, cfg, i),  			    cfg->inputs[i].pin);  	} -	snd_printd("\n");  	if (cfg->dig_in_pin)  		snd_printd("   dig-in=0x%x\n", cfg->dig_in_pin); diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 0bc2315b181..0849aac449f 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -231,16 +231,22 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)  }  EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); +static bool ctl_has_mute(struct snd_kcontrol *kcontrol) +{ +	struct hda_codec *codec = snd_kcontrol_chip(kcontrol); +	return query_amp_caps(codec, get_amp_nid(kcontrol), +			      get_amp_direction(kcontrol)) & AC_AMPCAP_MUTE; +} +  /* get/put callbacks for beep mute mixer switches */  int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,  				      struct snd_ctl_elem_value *ucontrol)  {  	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);  	struct hda_beep *beep = codec->beep; -	if (beep) { +	if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) {  		ucontrol->value.integer.value[0] = -			ucontrol->value.integer.value[1] = -			beep->enabled; +			ucontrol->value.integer.value[1] = beep->enabled;  		return 0;  	}  	return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); @@ -252,9 +258,20 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,  {  	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);  	struct hda_beep *beep = codec->beep; -	if (beep) -		snd_hda_enable_beep_device(codec, -					   *ucontrol->value.integer.value); +	if (beep) { +		u8 chs = get_amp_channels(kcontrol); +		int enable = 0; +		long *valp = ucontrol->value.integer.value; +		if (chs & 1) { +			enable |= *valp; +			valp++; +		} +		if (chs & 2) +			enable |= *valp; +		snd_hda_enable_beep_device(codec, enable); +	} +	if (!ctl_has_mute(kcontrol)) +		return 0;  	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);  }  EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 88a9c20eb7a..f560051a949 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1386,6 +1386,44 @@ int snd_hda_codec_configure(struct hda_codec *codec)  }  EXPORT_SYMBOL_HDA(snd_hda_codec_configure); +/* update the stream-id if changed */ +static void update_pcm_stream_id(struct hda_codec *codec, +				 struct hda_cvt_setup *p, hda_nid_t nid, +				 u32 stream_tag, int channel_id) +{ +	unsigned int oldval, newval; + +	if (p->stream_tag != stream_tag || p->channel_id != channel_id) { +		oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); +		newval = (stream_tag << 4) | channel_id; +		if (oldval != newval) +			snd_hda_codec_write(codec, nid, 0, +					    AC_VERB_SET_CHANNEL_STREAMID, +					    newval); +		p->stream_tag = stream_tag; +		p->channel_id = channel_id; +	} +} + +/* update the format-id if changed */ +static void update_pcm_format(struct hda_codec *codec, struct hda_cvt_setup *p, +			      hda_nid_t nid, int format) +{ +	unsigned int oldval; + +	if (p->format_id != format) { +		oldval = snd_hda_codec_read(codec, nid, 0, +					    AC_VERB_GET_STREAM_FORMAT, 0); +		if (oldval != format) { +			msleep(1); +			snd_hda_codec_write(codec, nid, 0, +					    AC_VERB_SET_STREAM_FORMAT, +					    format); +		} +		p->format_id = format; +	} +} +  /**   * snd_hda_codec_setup_stream - set up the codec for streaming   * @codec: the CODEC to set up @@ -1400,7 +1438,6 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,  {  	struct hda_codec *c;  	struct hda_cvt_setup *p; -	unsigned int oldval, newval;  	int type;  	int i; @@ -1413,29 +1450,13 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,  	p = get_hda_cvt_setup(codec, nid);  	if (!p)  		return; -	/* update the stream-id if changed */ -	if (p->stream_tag != stream_tag || p->channel_id != channel_id) { -		oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); -		newval = (stream_tag << 4) | channel_id; -		if (oldval != newval) -			snd_hda_codec_write(codec, nid, 0, -					    AC_VERB_SET_CHANNEL_STREAMID, -					    newval); -		p->stream_tag = stream_tag; -		p->channel_id = channel_id; -	} -	/* update the format-id if changed */ -	if (p->format_id != format) { -		oldval = snd_hda_codec_read(codec, nid, 0, -					    AC_VERB_GET_STREAM_FORMAT, 0); -		if (oldval != format) { -			msleep(1); -			snd_hda_codec_write(codec, nid, 0, -					    AC_VERB_SET_STREAM_FORMAT, -					    format); -		} -		p->format_id = format; -	} + +	if (codec->pcm_format_first) +		update_pcm_format(codec, p, nid, format); +	update_pcm_stream_id(codec, p, nid, stream_tag, channel_id); +	if (!codec->pcm_format_first) +		update_pcm_format(codec, p, nid, format); +  	p->active = 1;  	p->dirty = 0; @@ -3497,7 +3518,7 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg  {  	int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE); -	if (sup < 0) +	if (sup == -1)  		return false;  	if (sup & power_state)  		return true; @@ -4433,6 +4454,8 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)  	 * then there is no need to go through power up here.  	 */  	if (codec->power_on) { +		if (codec->power_transition < 0) +			codec->power_transition = 0;  		spin_unlock(&codec->power_lock);  		return;  	} diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index c422d330ca5..7fbc1bcaf1a 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -861,6 +861,7 @@ struct hda_codec {  	unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */  	unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */  	unsigned int no_jack_detect:1;	/* Machine has no jack-detection */ +	unsigned int pcm_format_first:1; /* PCM format must be set first */  #ifdef CONFIG_SND_HDA_POWER_SAVE  	unsigned int power_on :1;	/* current (global) power-state */  	int power_transition;	/* power-state in transition */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c8aced182fd..60882c62f18 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -151,6 +151,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"  			 "{Intel, CPT},"  			 "{Intel, PPT},"  			 "{Intel, LPT}," +			 "{Intel, LPT_LP},"  			 "{Intel, HPT},"  			 "{Intel, PBG},"  			 "{Intel, SCH}," @@ -3270,6 +3271,14 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {  	{ PCI_DEVICE(0x8086, 0x8c20),  	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |  	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, +	/* Lynx Point-LP */ +	{ PCI_DEVICE(0x8086, 0x9c20), +	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | +	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, +	/* Lynx Point-LP */ +	{ PCI_DEVICE(0x8086, 0x9c21), +	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | +	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO },  	/* Haswell */  	{ PCI_DEVICE(0x8086, 0x0c0c),  	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 7e46258fc70..6894ec66258 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -412,7 +412,7 @@ static void print_digital_conv(struct snd_info_buffer *buffer,  	if (digi1 & AC_DIG1_EMPHASIS)  		snd_iprintf(buffer, " Preemphasis");  	if (digi1 & AC_DIG1_COPYRIGHT) -		snd_iprintf(buffer, " Copyright"); +		snd_iprintf(buffer, " Non-Copyright");  	if (digi1 & AC_DIG1_NONAUDIO)  		snd_iprintf(buffer, " Non-Audio");  	if (digi1 & AC_DIG1_PROFESSIONAL) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index d0d3540e39e..49750a96d64 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -246,7 +246,7 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)  					    AC_VERB_SET_AMP_GAIN_MUTE,  					    AMP_OUT_UNMUTE);  	} -	if (dac) +	if (dac && (get_wcaps(codec, dac) & AC_WCAP_OUT_AMP))  		snd_hda_codec_write(codec, dac, 0,  				    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO);  } @@ -261,7 +261,7 @@ static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)  					    AC_VERB_SET_AMP_GAIN_MUTE,  					    AMP_IN_UNMUTE(0));  	} -	if (adc) +	if (adc && (get_wcaps(codec, adc) & AC_WCAP_IN_AMP))  		snd_hda_codec_write(codec, adc, 0, AC_VERB_SET_AMP_GAIN_MUTE,  				    AMP_IN_UNMUTE(0));  } @@ -275,6 +275,10 @@ static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx,  	int type = dir ? HDA_INPUT : HDA_OUTPUT;  	struct snd_kcontrol_new knew =  		HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); +	if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_MUTE) == 0) { +		snd_printdd("Skipping '%s %s Switch' (no mute on node 0x%x)\n", pfx, dirstr[dir], nid); +		return 0; +	}  	sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]);  	return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));  } @@ -286,6 +290,10 @@ static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx,  	int type = dir ? HDA_INPUT : HDA_OUTPUT;  	struct snd_kcontrol_new knew =  		HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); +	if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_NUM_STEPS) == 0) { +		snd_printdd("Skipping '%s %s Volume' (no amp on node 0x%x)\n", pfx, dirstr[dir], nid); +		return 0; +	}  	sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]);  	return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));  } @@ -464,50 +472,17 @@ exit:  }  /* - * PCM stuffs + * PCM callbacks   */ -static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid, -				 u32 stream_tag, -				 int channel_id, int format) -{ -	unsigned int oldval, newval; - -	if (!nid) -		return; - -	snd_printdd("ca0132_setup_stream: " -		"NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n", -		nid, stream_tag, channel_id, format); - -	/* update the format-id if changed */ -	oldval = snd_hda_codec_read(codec, nid, 0, -				    AC_VERB_GET_STREAM_FORMAT, -				    0); -	if (oldval != format) { -		msleep(20); -		snd_hda_codec_write(codec, nid, 0, -				    AC_VERB_SET_STREAM_FORMAT, -				    format); -	} - -	oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); -	newval = (stream_tag << 4) | channel_id; -	if (oldval != newval) { -		snd_hda_codec_write(codec, nid, 0, -				    AC_VERB_SET_CHANNEL_STREAMID, -				    newval); -	} -} - -static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid) +static int ca0132_playback_pcm_open(struct hda_pcm_stream *hinfo, +				    struct hda_codec *codec, +				    struct snd_pcm_substream *substream)  { -	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); -	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0); +	struct ca0132_spec *spec = codec->spec; +	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, +					     hinfo);  } -/* - * PCM callbacks - */  static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,  			struct hda_codec *codec,  			unsigned int stream_tag, @@ -515,10 +490,8 @@ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,  			struct snd_pcm_substream *substream)  {  	struct ca0132_spec *spec = codec->spec; - -	ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format); - -	return 0; +	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, +						stream_tag, format, substream);  }  static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, @@ -526,92 +499,45 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,  			struct snd_pcm_substream *substream)  {  	struct ca0132_spec *spec = codec->spec; - -	ca0132_cleanup_stream(codec, spec->dacs[0]); - -	return 0; +	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);  }  /*   * Digital out   */ -static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, -			struct hda_codec *codec, -			unsigned int stream_tag, -			unsigned int format, -			struct snd_pcm_substream *substream) -{ -	struct ca0132_spec *spec = codec->spec; - -	ca0132_setup_stream(codec, spec->dig_out, stream_tag, 0, format); - -	return 0; -} - -static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, -			struct hda_codec *codec, -			struct snd_pcm_substream *substream) +static int ca0132_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, +					struct hda_codec *codec, +					struct snd_pcm_substream *substream)  {  	struct ca0132_spec *spec = codec->spec; - -	ca0132_cleanup_stream(codec, spec->dig_out); - -	return 0; +	return snd_hda_multi_out_dig_open(codec, &spec->multiout);  } -/* - * Analog capture - */ -static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo, +static int ca0132_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,  			struct hda_codec *codec,  			unsigned int stream_tag,  			unsigned int format,  			struct snd_pcm_substream *substream)  {  	struct ca0132_spec *spec = codec->spec; - -	ca0132_setup_stream(codec, spec->adcs[substream->number], -			     stream_tag, 0, format); - -	return 0; -} - -static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, -			struct hda_codec *codec, -			struct snd_pcm_substream *substream) -{ -	struct ca0132_spec *spec = codec->spec; - -	ca0132_cleanup_stream(codec, spec->adcs[substream->number]); - -	return 0; +	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, +					     stream_tag, format, substream);  } -/* - * Digital capture - */ -static int ca0132_dig_capture_pcm_prepare(struct hda_pcm_stream *hinfo, +static int ca0132_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,  			struct hda_codec *codec, -			unsigned int stream_tag, -			unsigned int format,  			struct snd_pcm_substream *substream)  {  	struct ca0132_spec *spec = codec->spec; - -	ca0132_setup_stream(codec, spec->dig_in, stream_tag, 0, format); - -	return 0; +	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);  } -static int ca0132_dig_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, -			struct hda_codec *codec, -			struct snd_pcm_substream *substream) +static int ca0132_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, +					 struct hda_codec *codec, +					 struct snd_pcm_substream *substream)  {  	struct ca0132_spec *spec = codec->spec; - -	ca0132_cleanup_stream(codec, spec->dig_in); - -	return 0; +	return snd_hda_multi_out_dig_close(codec, &spec->multiout);  }  /* @@ -621,6 +547,7 @@ static struct hda_pcm_stream ca0132_pcm_analog_playback = {  	.channels_min = 2,  	.channels_max = 2,  	.ops = { +		.open = ca0132_playback_pcm_open,  		.prepare = ca0132_playback_pcm_prepare,  		.cleanup = ca0132_playback_pcm_cleanup  	}, @@ -630,10 +557,6 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = {  	.substreams = 1,  	.channels_min = 2,  	.channels_max = 2, -	.ops = { -		.prepare = ca0132_capture_pcm_prepare, -		.cleanup = ca0132_capture_pcm_cleanup -	},  };  static struct hda_pcm_stream ca0132_pcm_digital_playback = { @@ -641,6 +564,8 @@ static struct hda_pcm_stream ca0132_pcm_digital_playback = {  	.channels_min = 2,  	.channels_max = 2,  	.ops = { +		.open = ca0132_dig_playback_pcm_open, +		.close = ca0132_dig_playback_pcm_close,  		.prepare = ca0132_dig_playback_pcm_prepare,  		.cleanup = ca0132_dig_playback_pcm_cleanup  	}, @@ -650,10 +575,6 @@ static struct hda_pcm_stream ca0132_pcm_digital_capture = {  	.substreams = 1,  	.channels_min = 2,  	.channels_max = 2, -	.ops = { -		.prepare = ca0132_dig_capture_pcm_prepare, -		.cleanup = ca0132_dig_capture_pcm_cleanup -	},  };  static int ca0132_build_pcms(struct hda_codec *codec) @@ -928,18 +849,16 @@ static int ca0132_build_controls(struct hda_codec *codec)  						    spec->dig_out);  		if (err < 0)  			return err; -		err = add_out_volume(codec, spec->dig_out, "IEC958"); +		err = snd_hda_create_spdif_share_sw(codec, &spec->multiout);  		if (err < 0)  			return err; +		/* spec->multiout.share_spdif = 1; */  	}  	if (spec->dig_in) {  		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in);  		if (err < 0)  			return err; -		err = add_in_volume(codec, spec->dig_in, "IEC958"); -		if (err < 0) -			return err;  	}  	return 0;  } @@ -961,6 +880,9 @@ static void ca0132_config(struct hda_codec *codec)  	struct ca0132_spec *spec = codec->spec;  	struct auto_pin_cfg *cfg = &spec->autocfg; +	codec->pcm_format_first = 1; +	codec->no_sticky_stream = 1; +  	/* line-outs */  	cfg->line_outs = 1;  	cfg->line_out_pins[0] = 0x0b; /* front */ @@ -988,14 +910,24 @@ static void ca0132_config(struct hda_codec *codec)  	/* Mic-in */  	spec->input_pins[0] = 0x12; -	spec->input_labels[0] = "Mic-In"; +	spec->input_labels[0] = "Mic";  	spec->adcs[0] = 0x07;  	/* Line-In */  	spec->input_pins[1] = 0x11; -	spec->input_labels[1] = "Line-In"; +	spec->input_labels[1] = "Line";  	spec->adcs[1] = 0x08;  	spec->num_inputs = 2; + +	/* SPDIF I/O */ +	spec->dig_out = 0x05; +	spec->multiout.dig_out_nid = spec->dig_out; +	cfg->dig_out_pins[0] = 0x0c; +	cfg->dig_outs = 1; +	cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF; +	spec->dig_in = 0x09; +	cfg->dig_in_pin = 0x0e; +	cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;  }  static void ca0132_init_chip(struct hda_codec *codec) diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 14361184ae1..5e22a8f43d2 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -2967,12 +2967,10 @@ static const char * const cxt5066_models[CXT5066_MODELS] = {  };  static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { -	SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT5066_AUTO),  	SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),  	SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),  	SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),  	SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), -	SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),  	SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),  	SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD),  	SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD), @@ -2988,14 +2986,10 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {  	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),  	SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),  	SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS), -	SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T510", CXT5066_AUTO), -	SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520 & W520", CXT5066_AUTO),  	SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),  	SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),  	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),  	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS), -	SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO), -	SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO),  	{}  }; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 69b92844978..8f23374fa64 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -877,8 +877,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,  	struct hdmi_eld *eld;  	struct hdmi_spec_per_cvt *per_cvt = NULL; -	hinfo->nid = 0; /* clear the leftover value */ -  	/* Validate hinfo */  	pin_idx = hinfo_to_pin_index(spec, hinfo);  	if (snd_BUG_ON(pin_idx < 0)) @@ -1163,6 +1161,14 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,  	return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);  } +static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, +					     struct hda_codec *codec, +					     struct snd_pcm_substream *substream) +{ +	snd_hda_codec_cleanup_stream(codec, hinfo->nid); +	return 0; +} +  static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,  			  struct hda_codec *codec,  			  struct snd_pcm_substream *substream) @@ -1202,6 +1208,7 @@ static const struct hda_pcm_ops generic_ops = {  	.open = hdmi_pcm_open,  	.close = hdmi_pcm_close,  	.prepare = generic_hdmi_playback_pcm_prepare, +	.cleanup = generic_hdmi_playback_pcm_cleanup,  };  static int generic_hdmi_build_pcms(struct hda_codec *codec) @@ -1220,7 +1227,6 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)  		pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];  		pstr->substreams = 1;  		pstr->ops = generic_ops; -		pstr->nid = 1; /* FIXME: just for avoiding a debug WARNING */  		/* other pstr fields are set in open */  	} diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 344b221d210..4f81dd44c83 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6099,6 +6099,8 @@ static const struct alc_fixup alc269_fixups[] = {  	[ALC269_FIXUP_PCM_44K] = {  		.type = ALC_FIXUP_FUNC,  		.v.func = alc269_fixup_pcm_44k, +		.chained = true, +		.chain_id = ALC269_FIXUP_QUANTA_MUTE  	},  	[ALC269_FIXUP_STEREO_DMIC] = {  		.type = ALC_FIXUP_FUNC, @@ -6206,9 +6208,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {  	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),  	SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),  	SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), +	SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), +	SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), +	SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),  	SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), -	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), -	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), +	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),  	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),  #if 0 diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 94040ccf8e8..ea5775a1a7d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4272,7 +4272,8 @@ static int stac92xx_init(struct hda_codec *codec)  	unsigned int gpio;  	int i; -	snd_hda_sequence_write(codec, spec->init); +	if (spec->init) +		snd_hda_sequence_write(codec, spec->init);  	/* power down adcs initially */  	if (spec->powerdown_adcs) @@ -5748,7 +5749,6 @@ again:  		/* fallthru */  	case 0x111d76b4: /* 6 Port without Analog Mixer */  	case 0x111d76b5: -		spec->init = stac92hd71bxx_core_init;  		codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;  		spec->num_dmics = stac92xx_connected_ports(codec,  					stac92hd71bxx_dmic_nids, @@ -5773,7 +5773,6 @@ again:  			spec->stream_delay = 40; /* 40 milliseconds */  		/* disable VSW */ -		spec->init = stac92hd71bxx_core_init;  		unmute_init++;  		snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);  		snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); @@ -5788,7 +5787,6 @@ again:  		/* fallthru */  	default: -		spec->init = stac92hd71bxx_core_init;  		codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;  		spec->num_dmics = stac92xx_connected_ports(codec,  					stac92hd71bxx_dmic_nids, @@ -5796,6 +5794,9 @@ again:  		break;  	} +	if (get_wcaps_type(get_wcaps(codec, 0x28)) == AC_WID_VOL_KNB) +		spec->init = stac92hd71bxx_core_init; +  	if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP)  		snd_hda_sequence_write_cache(codec, unmute_init); diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 80d90cb4285..43077177691 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1752,6 +1752,14 @@ static int via_suspend(struct hda_codec *codec)  {  	struct via_spec *spec = codec->spec;  	vt1708_stop_hp_work(spec); + +	if (spec->codec_type == VT1802) { +		/* Fix pop noise on headphones */ +		int i; +		for (i = 0; i < spec->autocfg.hp_outs; i++) +			snd_hda_set_pin_ctl(codec, spec->autocfg.hp_pins[i], 0); +	} +  	return 0;  }  #endif diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c index d1ab4370673..5579b08bb35 100644 --- a/sound/pci/lx6464es/lx6464es.c +++ b/sound/pci/lx6464es/lx6464es.c @@ -851,6 +851,8 @@ static int __devinit lx_pcm_create(struct lx6464es *chip)  	/* hardcoded device name & channel count */  	err = snd_pcm_new(chip->card, (char *)card_name, 0,  			  1, 1, &pcm); +	if (err < 0) +		return err;  	pcm->private_data = chip; diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index b8ac8710f47..b12308b5ba2 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6585,7 +6585,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card,  		snd_printk(KERN_ERR "HDSPM: "  				"unable to kmalloc Mixer memory of %d Bytes\n",  				(int)sizeof(struct hdspm_mixer)); -		return err; +		return -ENOMEM;  	}  	hdspm->port_names_in = NULL; diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 512434efcc3..805ab6e9a78 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c @@ -1377,8 +1377,9 @@ static int __devinit sis_chip_create(struct snd_card *card,  	if (rc)  		goto error_out_cleanup; -	if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME, -			sis)) { +	rc = request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME, +			 sis); +	if (rc) {  		dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq);  		goto error_out_cleanup;  	} diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index f5ceb6f282d..210cafe0489 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -143,7 +143,7 @@ static int __devexit snd_pmac_remove(struct platform_device *devptr)  	return 0;  } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int snd_pmac_driver_suspend(struct device *dev)  {  	struct snd_card *card = dev_get_drvdata(dev); diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index 1aa52eff526..9b18b5243a5 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -1040,6 +1040,7 @@ static int __devinit snd_ps3_driver_probe(struct ps3_system_bus_device *dev)  				   GFP_KERNEL);  	if (!the_card.null_buffer_start_vaddr) {  		pr_info("%s: nullbuffer alloc failed\n", __func__); +		ret = -ENOMEM;  		goto clean_preallocate;  	}  	pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__, diff --git a/sound/soc/blackfin/bf6xx-sport.c b/sound/soc/blackfin/bf6xx-sport.c index 318c5ba5360..dfb744381c4 100644 --- a/sound/soc/blackfin/bf6xx-sport.c +++ b/sound/soc/blackfin/bf6xx-sport.c @@ -413,7 +413,14 @@ EXPORT_SYMBOL(sport_create);  void sport_delete(struct sport_device *sport)  { +	if (sport->tx_desc) +		dma_free_coherent(NULL, sport->tx_desc_size, +				sport->tx_desc, 0); +	if (sport->rx_desc) +		dma_free_coherent(NULL, sport->rx_desc_size, +				sport->rx_desc, 0);  	sport_free_resource(sport); +	kfree(sport);  }  EXPORT_SYMBOL(sport_delete); diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 3c795921c5f..23b40186f9b 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2406,6 +2406,10 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec)  	/* Setup AB8500 according to board-settings */  	pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); + +	/* Inform SoC Core that we have our own I/O arrangements. */ +	codec->control_data = (void *)true; +  	status = ab8500_audio_setup_mics(codec, &pdata->codec->amics);  	if (status < 0) {  		pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 8c39dddd7d0..11b1b714b8b 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c @@ -186,6 +186,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)  	printk(KERN_INFO "AD1980 SoC Audio Codec\n"); +	codec->control_data = codec;	/* we don't use regmap! */  	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);  	if (ret < 0) {  		printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 6276e352125..8f726c063f4 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c @@ -581,6 +581,8 @@ static int mc13783_probe(struct snd_soc_codec *codec)  {  	struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); +	codec->control_data = priv->mc13xxx; +  	mc13xxx_lock(priv->mc13xxx);  	/* these are the reset values */ diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 8af6a5245b1..df2f99d1d42 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -239,6 +239,7 @@ static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = {  	{"Headphone Mux", "DAC", "DAC"},	/* dac --> hp_mux */  	{"LO", NULL, "DAC"},			/* dac --> line_out */ +	{"LINE_IN", NULL, "VAG_POWER"},  	{"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */  	{"HP", NULL, "Headphone Mux"},		/* hp_mux --> hp */ @@ -1357,8 +1358,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)  	if (ret)  		goto err; -	snd_soc_dapm_new_widgets(&codec->dapm); -  	return 0;  err: diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 982e437799a..33c0f3d39c8 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c @@ -340,6 +340,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)  	printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); +	codec->control_data = codec;	/* we don't use regmap! */  	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);  	if (ret < 0)  		goto codec_err; diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 6537f16d383..e33d327396a 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -128,13 +128,9 @@ SOC_SINGLE_TLV("EQ4 B5 Volume", ARIZONA_EQ4_2, ARIZONA_EQ4_B5_GAIN_SHIFT,  ARIZONA_MIXER_CONTROLS("DRC1L", ARIZONA_DRC1LMIX_INPUT_1_SOURCE),  ARIZONA_MIXER_CONTROLS("DRC1R", ARIZONA_DRC1RMIX_INPUT_1_SOURCE), -ARIZONA_MIXER_CONTROLS("DRC2L", ARIZONA_DRC2LMIX_INPUT_1_SOURCE), -ARIZONA_MIXER_CONTROLS("DRC2R", ARIZONA_DRC2RMIX_INPUT_1_SOURCE),  SND_SOC_BYTES_MASK("DRC1", ARIZONA_DRC1_CTRL1, 5,  		   ARIZONA_DRC1R_ENA | ARIZONA_DRC1L_ENA), -SND_SOC_BYTES_MASK("DRC2", ARIZONA_DRC2_CTRL1, 5, -		   ARIZONA_DRC2R_ENA | ARIZONA_DRC2L_ENA),  ARIZONA_MIXER_CONTROLS("LHPF1", ARIZONA_HPLP1MIX_INPUT_1_SOURCE),  ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), @@ -236,8 +232,6 @@ ARIZONA_MIXER_ENUMS(EQ4, ARIZONA_EQ4MIX_INPUT_1_SOURCE);  ARIZONA_MIXER_ENUMS(DRC1L, ARIZONA_DRC1LMIX_INPUT_1_SOURCE);  ARIZONA_MIXER_ENUMS(DRC1R, ARIZONA_DRC1RMIX_INPUT_1_SOURCE); -ARIZONA_MIXER_ENUMS(DRC2L, ARIZONA_DRC2LMIX_INPUT_1_SOURCE); -ARIZONA_MIXER_ENUMS(DRC2R, ARIZONA_DRC2RMIX_INPUT_1_SOURCE);  ARIZONA_MIXER_ENUMS(LHPF1, ARIZONA_HPLP1MIX_INPUT_1_SOURCE);  ARIZONA_MIXER_ENUMS(LHPF2, ARIZONA_HPLP2MIX_INPUT_1_SOURCE); @@ -349,10 +343,6 @@ SND_SOC_DAPM_PGA("DRC1L", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1L_ENA_SHIFT, 0,  		 NULL, 0),  SND_SOC_DAPM_PGA("DRC1R", ARIZONA_DRC1_CTRL1, ARIZONA_DRC1R_ENA_SHIFT, 0,  		 NULL, 0), -SND_SOC_DAPM_PGA("DRC2L", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2L_ENA_SHIFT, 0, -		 NULL, 0), -SND_SOC_DAPM_PGA("DRC2R", ARIZONA_DRC2_CTRL1, ARIZONA_DRC2R_ENA_SHIFT, 0, -		 NULL, 0),  SND_SOC_DAPM_PGA("LHPF1", ARIZONA_HPLPF1_1, ARIZONA_LHPF1_ENA_SHIFT, 0,  		 NULL, 0), @@ -466,8 +456,6 @@ ARIZONA_MIXER_WIDGETS(EQ4, "EQ4"),  ARIZONA_MIXER_WIDGETS(DRC1L, "DRC1L"),  ARIZONA_MIXER_WIDGETS(DRC1R, "DRC1R"), -ARIZONA_MIXER_WIDGETS(DRC2L, "DRC2L"), -ARIZONA_MIXER_WIDGETS(DRC2R, "DRC2R"),  ARIZONA_MIXER_WIDGETS(LHPF1, "LHPF1"),  ARIZONA_MIXER_WIDGETS(LHPF2, "LHPF2"), @@ -553,8 +541,6 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),  	{ name, "EQ4", "EQ4" }, \  	{ name, "DRC1L", "DRC1L" }, \  	{ name, "DRC1R", "DRC1R" }, \ -	{ name, "DRC2L", "DRC2L" }, \ -	{ name, "DRC2R", "DRC2R" }, \  	{ name, "LHPF1", "LHPF1" }, \  	{ name, "LHPF2", "LHPF2" }, \  	{ name, "LHPF3", "LHPF3" }, \ @@ -639,6 +625,15 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {  	{ "AIF2 Capture", NULL, "SYSCLK" },  	{ "AIF3 Capture", NULL, "SYSCLK" }, +	{ "IN1L PGA", NULL, "IN1L" }, +	{ "IN1R PGA", NULL, "IN1R" }, + +	{ "IN2L PGA", NULL, "IN2L" }, +	{ "IN2R PGA", NULL, "IN2R" }, + +	{ "IN3L PGA", NULL, "IN3L" }, +	{ "IN3R PGA", NULL, "IN3R" }, +  	ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),  	ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),  	ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), @@ -675,8 +670,6 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {  	ARIZONA_MIXER_ROUTES("DRC1L", "DRC1L"),  	ARIZONA_MIXER_ROUTES("DRC1R", "DRC1R"), -	ARIZONA_MIXER_ROUTES("DRC2L", "DRC2L"), -	ARIZONA_MIXER_ROUTES("DRC2R", "DRC2R"),  	ARIZONA_MIXER_ROUTES("LHPF1", "LHPF1"),  	ARIZONA_MIXER_ROUTES("LHPF2", "LHPF2"), diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 8033f706518..01ebbcc5c6a 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -681,6 +681,18 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = {  	{ "AIF2 Capture", NULL, "SYSCLK" },  	{ "AIF3 Capture", NULL, "SYSCLK" }, +	{ "IN1L PGA", NULL, "IN1L" }, +	{ "IN1R PGA", NULL, "IN1R" }, + +	{ "IN2L PGA", NULL, "IN2L" }, +	{ "IN2R PGA", NULL, "IN2R" }, + +	{ "IN3L PGA", NULL, "IN3L" }, +	{ "IN3R PGA", NULL, "IN3R" }, + +	{ "IN4L PGA", NULL, "IN4L" }, +	{ "IN4R PGA", NULL, "IN4R" }, +  	ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"),  	ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"),  	ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index eaf65863ec2..ce672007379 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2501,6 +2501,9 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,  		/* VMID 2*250k */  		snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,  				    WM8962_VMID_SEL_MASK, 0x100); + +		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) +			msleep(100);  		break;  	case SND_SOC_BIAS_OFF: @@ -3730,21 +3733,6 @@ static int wm8962_runtime_resume(struct device *dev)  	regcache_sync(wm8962->regmap); -	regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, -			   WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA, -			   WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA); - -	/* Bias enable at 2*50k for ramp */ -	regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, -			   WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, -			   WM8962_BIAS_ENA | 0x180); - -	msleep(5); - -	/* VMID back to 2x250k for standby */ -	regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1, -			   WM8962_VMID_SEL_MASK, 0x100); -  	return 0;  } diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index bb62f4b3d56..6c9eeca85b9 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2649,7 +2649,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,  		return -EINVAL;  	} -	bclk_rate = params_rate(params) * 2; +	bclk_rate = params_rate(params) * 4;  	switch (params_format(params)) {  	case SNDRV_PCM_FORMAT_S16_LE:  		bclk_rate *= 16; @@ -3253,10 +3253,13 @@ static void wm8994_mic_work(struct work_struct *work)  	int ret;  	int report; +	pm_runtime_get_sync(dev); +  	ret = regmap_read(regmap, WM8994_INTERRUPT_RAW_STATUS_2, ®);  	if (ret < 0) {  		dev_err(dev, "Failed to read microphone status: %d\n",  			ret); +		pm_runtime_put(dev);  		return;  	} @@ -3299,6 +3302,8 @@ static void wm8994_mic_work(struct work_struct *work)  	snd_soc_jack_report(priv->micdet[1].jack, report,  			    SND_JACK_HEADSET | SND_JACK_BTN_0); + +	pm_runtime_put(dev);  }  static irqreturn_t wm8994_mic_irq(int irq, void *data) @@ -3421,12 +3426,15 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)  	int reg;  	bool present; +	pm_runtime_get_sync(codec->dev); +  	mutex_lock(&wm8994->accdet_lock);  	reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);  	if (reg < 0) {  		dev_err(codec->dev, "Failed to read jack status: %d\n", reg);  		mutex_unlock(&wm8994->accdet_lock); +		pm_runtime_put(codec->dev);  		return IRQ_NONE;  	} @@ -3491,6 +3499,7 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)  				    SND_JACK_MECHANICAL | SND_JACK_HEADSET |  				    wm8994->btn_mask); +	pm_runtime_put(codec->dev);  	return IRQ_HANDLED;  } @@ -3602,6 +3611,8 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)  	if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA))  		return IRQ_HANDLED; +	pm_runtime_get_sync(codec->dev); +  	/* We may occasionally read a detection without an impedence  	 * range being provided - if that happens loop again.  	 */ @@ -3612,6 +3623,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)  			dev_err(codec->dev,  				"Failed to read mic detect status: %d\n",  				reg); +			pm_runtime_put(codec->dev);  			return IRQ_NONE;  		} @@ -3639,6 +3651,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)  		dev_warn(codec->dev, "Accessory detection with no callback\n");  out: +	pm_runtime_put(codec->dev);  	return IRQ_HANDLED;  } @@ -4025,6 +4038,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)  		break;  	case WM8958:  		if (wm8994->revision < 1) { +			snd_soc_dapm_add_routes(dapm, wm8994_intercon, +						ARRAY_SIZE(wm8994_intercon));  			snd_soc_dapm_add_routes(dapm, wm8994_revd_intercon,  						ARRAY_SIZE(wm8994_revd_intercon));  			snd_soc_dapm_add_routes(dapm, wm8994_lateclk_revd_intercon, diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 099e6ec3212..c6d2076a796 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -148,7 +148,7 @@ SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1),  SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1),  SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), -SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1), +SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0),  SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),  SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv), @@ -272,7 +272,7 @@ SOC_DAPM_ENUM("Route", wm9712_enum[9]);  /* Mic select */  static const struct snd_kcontrol_new wm9712_mic_src_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[7]); +SOC_DAPM_ENUM("Mic Source Select", wm9712_enum[7]);  /* diff select */  static const struct snd_kcontrol_new wm9712_diff_sel_controls = @@ -291,7 +291,9 @@ SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,  	&wm9712_capture_selectl_controls),  SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,  	&wm9712_capture_selectr_controls), -SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0, +SND_SOC_DAPM_MUX("Left Mic Select Source", SND_SOC_NOPM, 0, 0, +	&wm9712_mic_src_controls), +SND_SOC_DAPM_MUX("Right Mic Select Source", SND_SOC_NOPM, 0, 0,  	&wm9712_mic_src_controls),  SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0,  	&wm9712_diff_sel_controls), @@ -319,6 +321,7 @@ SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0),  SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0),  SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0),  SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0), +SND_SOC_DAPM_PGA("Differential Mic", SND_SOC_NOPM, 0, 0, NULL, 0),  SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1),  SND_SOC_DAPM_OUTPUT("MONOOUT"),  SND_SOC_DAPM_OUTPUT("HPOUTL"), @@ -379,6 +382,18 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = {  	{"Mic PGA", NULL, "MIC1"},  	{"Mic PGA", NULL, "MIC2"}, +	/* microphones */ +	{"Differential Mic", NULL, "MIC1"}, +	{"Differential Mic", NULL, "MIC2"}, +	{"Left Mic Select Source", "Mic 1", "MIC1"}, +	{"Left Mic Select Source", "Mic 2", "MIC2"}, +	{"Left Mic Select Source", "Stereo", "MIC1"}, +	{"Left Mic Select Source", "Differential", "Differential Mic"}, +	{"Right Mic Select Source", "Mic 1", "MIC1"}, +	{"Right Mic Select Source", "Mic 2", "MIC2"}, +	{"Right Mic Select Source", "Stereo", "MIC2"}, +	{"Right Mic Select Source", "Differential", "Differential Mic"}, +  	/* left capture selector */  	{"Left Capture Select", "Mic", "MIC1"},  	{"Left Capture Select", "Speaker Mixer", "Speaker Mixer"}, @@ -619,6 +634,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)  {  	int ret = 0; +	codec->control_data = codec;	/* we don't use regmap! */  	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);  	if (ret < 0) {  		printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 3eb19fb71d1..d0b8a3287a8 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c @@ -1196,6 +1196,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)  	if (wm9713 == NULL)  		return -ENOMEM;  	snd_soc_codec_set_drvdata(codec, wm9713); +	codec->control_data = wm9713;	/* we don't use regmap! */  	ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);  	if (ret < 0) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 95441bfc819..ce5e5cd254d 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -380,14 +380,20 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev)  static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)  {  	if (stream == SNDRV_PCM_STREAM_PLAYBACK) { -		if (dev->txnumevt)	/* enable FIFO */ +		if (dev->txnumevt) {	/* enable FIFO */ +			mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, +								FIFO_ENABLE);  			mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,  								FIFO_ENABLE); +		}  		mcasp_start_tx(dev);  	} else { -		if (dev->rxnumevt)	/* enable FIFO */ +		if (dev->rxnumevt) {	/* enable FIFO */ +			mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, +								FIFO_ENABLE);  			mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,  								FIFO_ENABLE); +		}  		mcasp_start_rx(dev);  	}  } diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 28dd76c7cb1..81d7728cf67 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -380,13 +380,14 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai)  static struct snd_soc_dai_driver imx_ssi_dai = {  	.probe = imx_ssi_dai_probe,  	.playback = { -		.channels_min = 1, +		/* The SSI does not support monaural audio. */ +		.channels_min = 2,  		.channels_max = 2,  		.rates = SNDRV_PCM_RATE_8000_96000,  		.formats = SNDRV_PCM_FMTBIT_S16_LE,  	},  	.capture = { -		.channels_min = 1, +		.channels_min = 2,  		.channels_max = 2,  		.rates = SNDRV_PCM_RATE_8000_96000,  		.formats = SNDRV_PCM_FMTBIT_S16_LE, diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig index 99a997f19bb..b6fa77678d9 100644 --- a/sound/soc/mxs/Kconfig +++ b/sound/soc/mxs/Kconfig @@ -10,7 +10,7 @@ menuconfig SND_MXS_SOC  if SND_MXS_SOC  config SND_SOC_MXS_SGTL5000 -	tristate "SoC Audio support for i.MX boards with sgtl5000" +	tristate "SoC Audio support for MXS boards with sgtl5000"  	depends on I2C  	select SND_SOC_SGTL5000  	help diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index aba71bfa33b..b3030718c22 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -394,9 +394,14 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream,  			     struct snd_soc_dai *cpu_dai)  {  	struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); +	struct mxs_saif *master_saif;  	u32 scr, stat;  	int ret; +	master_saif = mxs_saif_get_master(saif); +	if (!master_saif) +		return -EINVAL; +  	/* mclk should already be set */  	if (!saif->mclk && saif->mclk_in_use) {  		dev_err(cpu_dai->dev, "set mclk first\n"); @@ -420,6 +425,25 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream,  		return ret;  	} +	/* prepare clk in hw_param, enable in trigger */ +	clk_prepare(saif->clk); +	if (saif != master_saif) { +		/* +		* Set an initial clock rate for the saif internal logic to work +		* properly. This is important when working in EXTMASTER mode +		* that uses the other saif's BITCLK&LRCLK but it still needs a +		* basic clock which should be fast enough for the internal +		* logic. +		*/ +		clk_enable(saif->clk); +		ret = clk_set_rate(saif->clk, 24000000); +		clk_disable(saif->clk); +		if (ret) +			return ret; + +		clk_prepare(master_saif->clk); +	} +  	scr = __raw_readl(saif->base + SAIF_CTRL);  	scr &= ~BM_SAIF_CTRL_WORD_LENGTH; diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index 34835e8a916..d33c48baaf7 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -745,7 +745,7 @@ int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux)  {  	const char *signal, *src; -	if (mcbsp->pdata->mux_signal) +	if (!mcbsp->pdata->mux_signal)  		return -EINVAL;  	switch (mux) { diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 1046083e90a..acdd3ef14e0 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c @@ -820,3 +820,4 @@ module_platform_driver(asoc_mcbsp_driver);  MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");  MODULE_DESCRIPTION("OMAP I2S SoC Interface");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:omap-mcbsp"); diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index 5a649da9122..f0feb06615f 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c @@ -441,3 +441,4 @@ module_platform_driver(omap_pcm_driver);  MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");  MODULE_DESCRIPTION("OMAP PCM DMA module");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:omap-pcm-audio"); diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index b7b2a1f9142..89b064650f1 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c @@ -20,7 +20,7 @@  #include <sound/pcm_params.h>  #include <plat/audio.h> -#include <plat/dma.h> +#include <mach/dma.h>  #include "dma.h"  #include "pcm.h" diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f219b2f7ee6..c501af6d8db 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -826,7 +826,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)  	}  	if (!rtd->cpu_dai) { -		dev_dbg(card->dev, "CPU DAI %s not registered\n", +		dev_err(card->dev, "CPU DAI %s not registered\n",  			dai_link->cpu_dai_name);  		return -EPROBE_DEFER;  	} @@ -857,14 +857,14 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)  		}  		if (!rtd->codec_dai) { -			dev_dbg(card->dev, "CODEC DAI %s not registered\n", +			dev_err(card->dev, "CODEC DAI %s not registered\n",  				dai_link->codec_dai_name);  			return -EPROBE_DEFER;  		}  	}  	if (!rtd->codec) { -		dev_dbg(card->dev, "CODEC %s not registered\n", +		dev_err(card->dev, "CODEC %s not registered\n",  			dai_link->codec_name);  		return -EPROBE_DEFER;  	} @@ -888,7 +888,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)  		rtd->platform = platform;  	}  	if (!rtd->platform) { -		dev_dbg(card->dev, "platform %s not registered\n", +		dev_err(card->dev, "platform %s not registered\n",  			dai_link->platform_name);  		return -EPROBE_DEFER;  	} @@ -1096,7 +1096,7 @@ static int soc_probe_codec(struct snd_soc_card *card,  	}  	/* If the driver didn't set I/O up try regmap */ -	if (!codec->control_data) +	if (!codec->write && dev_get_regmap(codec->dev, NULL))  		snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);  	if (driver->controls) @@ -1481,6 +1481,8 @@ static int soc_check_aux_dev(struct snd_soc_card *card, int num)  			return 0;  	} +	dev_err(card->dev, "%s not registered\n", aux_dev->codec_name); +  	return -EPROBE_DEFER;  } diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 7f8b3b7428b..0c172938b82 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -103,7 +103,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)  	}  	/* Report before the DAPM sync to help users updating micbias status */ -	blocking_notifier_call_chain(&jack->notifier, status, jack); +	blocking_notifier_call_chain(&jack->notifier, jack->status, jack);  	snd_soc_dapm_sync(dapm); diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index d684df294c0..e463529b38b 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -177,7 +177,7 @@ static __devinit int tegra_alc5632_probe(struct platform_device *pdev)  	}  	alc5632->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0); -	if (alc5632->gpio_hp_det == -ENODEV) +	if (alc5632->gpio_hp_det == -EPROBE_DEFER)  		return -EPROBE_DEFER;  	ret = snd_soc_of_parse_card_name(card, "nvidia,model"); diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 0c5bb33d258..d4f14e49234 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -284,27 +284,27 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)  	} else if (np) {  		pdata->gpio_spkr_en = of_get_named_gpio(np,  						"nvidia,spkr-en-gpios", 0); -		if (pdata->gpio_spkr_en == -ENODEV) +		if (pdata->gpio_spkr_en == -EPROBE_DEFER)  			return -EPROBE_DEFER;  		pdata->gpio_hp_mute = of_get_named_gpio(np,  						"nvidia,hp-mute-gpios", 0); -		if (pdata->gpio_hp_mute == -ENODEV) +		if (pdata->gpio_hp_mute == -EPROBE_DEFER)  			return -EPROBE_DEFER;  		pdata->gpio_hp_det = of_get_named_gpio(np,  						"nvidia,hp-det-gpios", 0); -		if (pdata->gpio_hp_det == -ENODEV) +		if (pdata->gpio_hp_det == -EPROBE_DEFER)  			return -EPROBE_DEFER;  		pdata->gpio_int_mic_en = of_get_named_gpio(np,  						"nvidia,int-mic-en-gpios", 0); -		if (pdata->gpio_int_mic_en == -ENODEV) +		if (pdata->gpio_int_mic_en == -EPROBE_DEFER)  			return -EPROBE_DEFER;  		pdata->gpio_ext_mic_en = of_get_named_gpio(np,  						"nvidia,ext-mic-en-gpios", 0); -		if (pdata->gpio_ext_mic_en == -ENODEV) +		if (pdata->gpio_ext_mic_en == -EPROBE_DEFER)  			return -EPROBE_DEFER;  	} diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 62ac0285bfa..057e28ef770 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -21,7 +21,7 @@  #include <linux/mfd/dbx500-prcmu.h>  #include <mach/hardware.h> -#include <mach/board-mop500-msp.h> +#include <mach/msp.h>  #include <sound/soc.h>  #include <sound/soc-dai.h> diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index ee14d2dac2f..5c472f335a6 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -19,7 +19,7 @@  #include <linux/slab.h>  #include <mach/hardware.h> -#include <mach/board-mop500-msp.h> +#include <mach/msp.h>  #include <sound/soc.h> diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h index 7f71b4a0d4b..2d9136da986 100644 --- a/sound/soc/ux500/ux500_msp_i2s.h +++ b/sound/soc/ux500/ux500_msp_i2s.h @@ -17,7 +17,7 @@  #include <linux/platform_device.h> -#include <mach/board-mop500-msp.h> +#include <mach/msp.h>  #define MSP_INPUT_FREQ_APB 48000000 diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 0f647d22cb4..c4118120268 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -821,10 +821,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)  	if (++ep->use_count != 1)  		return 0; -	/* just to be sure */ -	deactivate_urbs(ep, 0, 1); -	wait_clear_urbs(ep); -  	ep->active_mask = 0;  	ep->unlink_mask = 0;  	ep->phase = 0; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index a1298f37942..62ec808ed79 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -544,6 +544,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)  	subs->last_frame_number = 0;  	runtime->delay = 0; +	/* clear the pending deactivation on the target EPs */ +	deactivate_endpoints(subs); +  	/* for playback, submit the URBs now; otherwise, the first hwptr_done  	 * updates for all URBs would happen at the same time when starting */  	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 77f124fe57a..35655c3a7b7 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -319,6 +319,8 @@ LIB_H += $(ARCH_INCLUDE)  LIB_H += util/cgroup.h  LIB_H += $(TRACE_EVENT_DIR)event-parse.h  LIB_H += util/target.h +LIB_H += util/rblist.h +LIB_H += util/intlist.h  LIB_OBJS += $(OUTPUT)util/abspath.o  LIB_OBJS += $(OUTPUT)util/alias.o @@ -383,6 +385,8 @@ LIB_OBJS += $(OUTPUT)util/xyarray.o  LIB_OBJS += $(OUTPUT)util/cpumap.o  LIB_OBJS += $(OUTPUT)util/cgroup.o  LIB_OBJS += $(OUTPUT)util/target.o +LIB_OBJS += $(OUTPUT)util/rblist.o +LIB_OBJS += $(OUTPUT)util/intlist.o  BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o @@ -983,7 +987,8 @@ clean:  	$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*  	$(MAKE) -C Documentation/ clean  	$(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS -	$(RM) $(OUTPUT)util/*-{bison,flex}* +	$(RM) $(OUTPUT)util/*-bison* +	$(RM) $(OUTPUT)util/*-flex*  	$(python-clean)  .PHONY: all install clean strip $(LIBTRACEEVENT) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index f5a6452931e..4db6e1ba54e 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -313,7 +313,7 @@ try_again:  		}   	} -	perf_session__update_sample_type(session); +	perf_session__set_id_hdr_size(session);  }  static int process_buildids(struct perf_record *rec) @@ -844,8 +844,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)  	struct perf_record *rec = &record;  	char errbuf[BUFSIZ]; -	perf_header__set_cmdline(argc, argv); -  	evsel_list = perf_evlist__new(NULL, NULL);  	if (evsel_list == NULL)  		return -ENOMEM; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 69b1c118515..7c88a243b5d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -249,8 +249,9 @@ static int process_read_event(struct perf_tool *tool,  static int perf_report__setup_sample_type(struct perf_report *rep)  {  	struct perf_session *self = rep->session; +	u64 sample_type = perf_evlist__sample_type(self->evlist); -	if (!self->fd_pipe && !(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { +	if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {  		if (sort__has_parent) {  			ui__error("Selected --sort parent, but no "  				    "callchain data. Did you call " @@ -274,7 +275,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep)  	if (sort__branch_mode == 1) {  		if (!self->fd_pipe && -		    !(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) { +		    !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {  			ui__error("Selected -b but no branch data. "  				  "Did you call perf record without -b?\n");  			return -1; diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index d909eb74a0e..1d592f5cbea 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -478,7 +478,6 @@ static int test__basic_mmap(void)  	unsigned int nr_events[nsyscalls],  		     expected_nr_events[nsyscalls], i, j;  	struct perf_evsel *evsels[nsyscalls], *evsel; -	int sample_size = __perf_evsel__sample_size(attr.sample_type);  	for (i = 0; i < nsyscalls; ++i) {  		char name[64]; @@ -563,8 +562,7 @@ static int test__basic_mmap(void)  			goto out_munmap;  		} -		err = perf_event__parse_sample(event, attr.sample_type, sample_size, -					       false, &sample, false); +		err = perf_evlist__parse_sample(evlist, event, &sample, false);  		if (err) {  			pr_err("Can't parse sample, err = %d\n", err);  			goto out_munmap; @@ -661,12 +659,12 @@ static int test__PERF_RECORD(void)  	const char *cmd = "sleep";  	const char *argv[] = { cmd, "1", NULL, };  	char *bname; -	u64 sample_type, prev_time = 0; +	u64 prev_time = 0;  	bool found_cmd_mmap = false,  	     found_libc_mmap = false,  	     found_vdso_mmap = false,  	     found_ld_mmap = false; -	int err = -1, errs = 0, i, wakeups = 0, sample_size; +	int err = -1, errs = 0, i, wakeups = 0;  	u32 cpu;  	int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; @@ -757,13 +755,6 @@ static int test__PERF_RECORD(void)  	}  	/* -	 * We'll need these two to parse the PERF_SAMPLE_* fields in each -	 * event. -	 */ -	sample_type = perf_evlist__sample_type(evlist); -	sample_size = __perf_evsel__sample_size(sample_type); - -	/*  	 * Now that all is properly set up, enable the events, they will  	 * count just on workload.pid, which will start...  	 */ @@ -788,9 +779,7 @@ static int test__PERF_RECORD(void)  				if (type < PERF_RECORD_MAX)  					nr_events[type]++; -				err = perf_event__parse_sample(event, sample_type, -							       sample_size, true, -							       &sample, false); +				err = perf_evlist__parse_sample(evlist, event, &sample, false);  				if (err < 0) {  					if (verbose)  						perf_event__fprintf(event, stderr); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 35e86c6df71..68cd61ef6ac 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -38,6 +38,7 @@  #include "util/cpumap.h"  #include "util/xyarray.h"  #include "util/sort.h" +#include "util/intlist.h"  #include "util/debug.h" @@ -706,8 +707,16 @@ static void perf_event__process_sample(struct perf_tool *tool,  	int err;  	if (!machine && perf_guest) { -		pr_err("Can't find guest [%d]'s kernel information\n", -			event->ip.pid); +		static struct intlist *seen; + +		if (!seen) +			seen = intlist__new(); + +		if (!intlist__has_entry(seen, event->ip.pid)) { +			pr_err("Can't find guest [%d]'s kernel information\n", +				event->ip.pid); +			intlist__add(seen, event->ip.pid); +		}  		return;  	} @@ -811,7 +820,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)  	int ret;  	while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) { -		ret = perf_session__parse_sample(session, event, &sample); +		ret = perf_evlist__parse_sample(top->evlist, event, &sample, false);  		if (ret) {  			pr_err("Can't parse sample, err = %d\n", ret);  			continue; @@ -943,8 +952,10 @@ try_again:  			 * based cpu-clock-tick sw counter, which  			 * is always available even if no PMU support:  			 */ -			if (attr->type == PERF_TYPE_HARDWARE && -			    attr->config == PERF_COUNT_HW_CPU_CYCLES) { +			if ((err == ENOENT || err == ENXIO) && +			    (attr->type == PERF_TYPE_HARDWARE) && +			    (attr->config == PERF_COUNT_HW_CPU_CYCLES)) { +  				if (verbose)  					ui__warning("Cycles event not supported,\n"  						    "trying to fall back to cpu-clock-ticks\n"); @@ -1032,7 +1043,7 @@ static int __cmd_top(struct perf_top *top)  					       &top->session->host_machine);  	perf_top__start_counters(top);  	top->session->evlist = top->evlist; -	perf_session__update_sample_type(top->session); +	perf_session__set_id_hdr_size(top->session);  	/* Wait for a minimal set of events before starting the snapshot */  	poll(top->evlist->pollfd, top->evlist->nr_fds, 100); diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 1b197280c62..d84870b0642 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -197,9 +197,6 @@ int perf_event__preprocess_sample(const union perf_event *self,  const char *perf_event__name(unsigned int id); -int perf_event__parse_sample(const union perf_event *event, u64 type, -			     int sample_size, bool sample_id_all, -			     struct perf_sample *sample, bool swapped);  int perf_event__synthesize_sample(union perf_event *event, u64 type,  				  const struct perf_sample *sample,  				  bool swapped); diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3edfd348381..9b38681add9 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -881,3 +881,10 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)  	return 0;  } + +int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, +			      struct perf_sample *sample, bool swapped) +{ +	struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node); +	return perf_evsel__parse_sample(e, event, sample, swapped); +} diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 40d4d3cdced..528c1acd929 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -122,6 +122,9 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist);  bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);  u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist); +int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, +			      struct perf_sample *sample, bool swapped); +  bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);  bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index e8177136486..2eaae140def 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -20,7 +20,7 @@  #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))  #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) -int __perf_evsel__sample_size(u64 sample_type) +static int __perf_evsel__sample_size(u64 sample_type)  {  	u64 mask = sample_type & PERF_SAMPLE_MASK;  	int size = 0; @@ -53,6 +53,7 @@ void perf_evsel__init(struct perf_evsel *evsel,  	evsel->attr	   = *attr;  	INIT_LIST_HEAD(&evsel->node);  	hists__init(&evsel->hists); +	evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);  }  struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) @@ -728,10 +729,10 @@ static bool sample_overlap(const union perf_event *event,  	return false;  } -int perf_event__parse_sample(const union perf_event *event, u64 type, -			     int sample_size, bool sample_id_all, +int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,  			     struct perf_sample *data, bool swapped)  { +	u64 type = evsel->attr.sample_type;  	const u64 *array;  	/* @@ -746,14 +747,14 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,  	data->period = 1;  	if (event->header.type != PERF_RECORD_SAMPLE) { -		if (!sample_id_all) +		if (!evsel->attr.sample_id_all)  			return 0;  		return perf_event__parse_id_sample(event, type, data, swapped);  	}  	array = event->sample.array; -	if (sample_size + sizeof(event->header) > event->header.size) +	if (evsel->sample_size + sizeof(event->header) > event->header.size)  		return -EFAULT;  	if (type & PERF_SAMPLE_IP) { @@ -895,7 +896,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,  		u.val32[1] = sample->tid;  		if (swapped) {  			/* -			 * Inverse of what is done in perf_event__parse_sample +			 * Inverse of what is done in perf_evsel__parse_sample  			 */  			u.val32[0] = bswap_32(u.val32[0]);  			u.val32[1] = bswap_32(u.val32[1]); @@ -930,7 +931,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,  		u.val32[0] = sample->cpu;  		if (swapped) {  			/* -			 * Inverse of what is done in perf_event__parse_sample +			 * Inverse of what is done in perf_evsel__parse_sample  			 */  			u.val32[0] = bswap_32(u.val32[0]);  			u.val64 = bswap_64(u.val64); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 67cc5033d19..b559929983b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -65,6 +65,7 @@ struct perf_evsel {  		void		*func;  		void		*data;  	} handler; +	unsigned int		sample_size;  	bool 			supported;  }; @@ -177,13 +178,8 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,  	return __perf_evsel__read(evsel, ncpus, nthreads, true);  } -int __perf_evsel__sample_size(u64 sample_type); - -static inline int perf_evsel__sample_size(struct perf_evsel *evsel) -{ -	return __perf_evsel__sample_size(evsel->attr.sample_type); -} -  void hists__init(struct hists *hists); +int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, +			     struct perf_sample *sample, bool swapped);  #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 3a6d2044333..74ea3c2f813 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -174,6 +174,15 @@ perf_header__set_cmdline(int argc, const char **argv)  {  	int i; +	/* +	 * If header_argv has already been set, do not override it. +	 * This allows a command to set the cmdline, parse args and +	 * then call another builtin function that implements a +	 * command -- e.g, cmd_kvm calling cmd_record. +	 */ +	if (header_argv) +		return 0; +  	header_argc = (u32)argc;  	/* do not include NULL termination */ diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c new file mode 100644 index 00000000000..fd530dced9c --- /dev/null +++ b/tools/perf/util/intlist.c @@ -0,0 +1,101 @@ +/* + * Based on intlist.c by: + * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> + * + * Licensed under the GPLv2. + */ + +#include <errno.h> +#include <stdlib.h> +#include <linux/compiler.h> + +#include "intlist.h" + +static struct rb_node *intlist__node_new(struct rblist *rblist __used, +					 const void *entry) +{ +	int i = (int)((long)entry); +	struct rb_node *rc = NULL; +	struct int_node *node = malloc(sizeof(*node)); + +	if (node != NULL) { +		node->i = i; +		rc = &node->rb_node; +	} + +	return rc; +} + +static void int_node__delete(struct int_node *ilist) +{ +	free(ilist); +} + +static void intlist__node_delete(struct rblist *rblist __used, +				 struct rb_node *rb_node) +{ +	struct int_node *node = container_of(rb_node, struct int_node, rb_node); + +	int_node__delete(node); +} + +static int intlist__node_cmp(struct rb_node *rb_node, const void *entry) +{ +	int i = (int)((long)entry); +	struct int_node *node = container_of(rb_node, struct int_node, rb_node); + +	return node->i - i; +} + +int intlist__add(struct intlist *ilist, int i) +{ +	return rblist__add_node(&ilist->rblist, (void *)((long)i)); +} + +void intlist__remove(struct intlist *ilist __used, struct int_node *node) +{ +	int_node__delete(node); +} + +struct int_node *intlist__find(struct intlist *ilist, int i) +{ +	struct int_node *node = NULL; +	struct rb_node *rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); + +	if (rb_node) +		node = container_of(rb_node, struct int_node, rb_node); + +	return node; +} + +struct intlist *intlist__new(void) +{ +	struct intlist *ilist = malloc(sizeof(*ilist)); + +	if (ilist != NULL) { +		rblist__init(&ilist->rblist); +		ilist->rblist.node_cmp    = intlist__node_cmp; +		ilist->rblist.node_new    = intlist__node_new; +		ilist->rblist.node_delete = intlist__node_delete; +	} + +	return ilist; +} + +void intlist__delete(struct intlist *ilist) +{ +	if (ilist != NULL) +		rblist__delete(&ilist->rblist); +} + +struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx) +{ +	struct int_node *node = NULL; +	struct rb_node *rb_node; + +	rb_node = rblist__entry(&ilist->rblist, idx); +	if (rb_node) +		node = container_of(rb_node, struct int_node, rb_node); + +	return node; +} diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h new file mode 100644 index 00000000000..6d63ab90db5 --- /dev/null +++ b/tools/perf/util/intlist.h @@ -0,0 +1,75 @@ +#ifndef __PERF_INTLIST_H +#define __PERF_INTLIST_H + +#include <linux/rbtree.h> +#include <stdbool.h> + +#include "rblist.h" + +struct int_node { +	struct rb_node rb_node; +	int i; +}; + +struct intlist { +	struct rblist rblist; +}; + +struct intlist *intlist__new(void); +void intlist__delete(struct intlist *ilist); + +void intlist__remove(struct intlist *ilist, struct int_node *in); +int intlist__add(struct intlist *ilist, int i); + +struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx); +struct int_node *intlist__find(struct intlist *ilist, int i); + +static inline bool intlist__has_entry(struct intlist *ilist, int i) +{ +	return intlist__find(ilist, i) != NULL; +} + +static inline bool intlist__empty(const struct intlist *ilist) +{ +	return rblist__empty(&ilist->rblist); +} + +static inline unsigned int intlist__nr_entries(const struct intlist *ilist) +{ +	return rblist__nr_entries(&ilist->rblist); +} + +/* For intlist iteration */ +static inline struct int_node *intlist__first(struct intlist *ilist) +{ +	struct rb_node *rn = rb_first(&ilist->rblist.entries); +	return rn ? rb_entry(rn, struct int_node, rb_node) : NULL; +} +static inline struct int_node *intlist__next(struct int_node *in) +{ +	struct rb_node *rn; +	if (!in) +		return NULL; +	rn = rb_next(&in->rb_node); +	return rn ? rb_entry(rn, struct int_node, rb_node) : NULL; +} + +/** + * intlist_for_each      - iterate over a intlist + * @pos:	the &struct int_node to use as a loop cursor. + * @ilist:	the &struct intlist for loop. + */ +#define intlist__for_each(pos, ilist)	\ +	for (pos = intlist__first(ilist); pos; pos = intlist__next(pos)) + +/** + * intlist_for_each_safe - iterate over a intlist safe against removal of + *                         int_node + * @pos:	the &struct int_node to use as a loop cursor. + * @n:		another &struct int_node to use as temporary storage. + * @ilist:	the &struct intlist for loop. + */ +#define intlist__for_each_safe(pos, n, ilist)	\ +	for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\ +	     pos = n, n = intlist__next(n)) +#endif /* __PERF_INTLIST_H */ diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index 1b997d2b89c..127d648cc54 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -13,6 +13,9 @@ do { \  	} \  } while (0) +#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ +			     PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) +  static int test__checkevent_tracepoint(struct perf_evlist *evlist)  {  	struct perf_evsel *evsel = list_entry(evlist->entries.next, @@ -21,8 +24,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist)  	TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);  	TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);  	TEST_ASSERT_VAL("wrong sample_type", -		(PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == -		evsel->attr.sample_type); +		PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);  	TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);  	return 0;  } @@ -37,8 +39,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)  		TEST_ASSERT_VAL("wrong type",  			PERF_TYPE_TRACEPOINT == evsel->attr.type);  		TEST_ASSERT_VAL("wrong sample_type", -			(PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) -			== evsel->attr.sample_type); +			PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);  		TEST_ASSERT_VAL("wrong sample_period",  			1 == evsel->attr.sample_period);  	} @@ -428,8 +429,7 @@ static int test__checkevent_list(struct perf_evlist *evlist)  	evsel = list_entry(evsel->node.next, struct perf_evsel, node);  	TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);  	TEST_ASSERT_VAL("wrong sample_type", -		(PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == -		evsel->attr.sample_type); +		PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);  	TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);  	TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);  	TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 99d02aa57db..594f8fad5ec 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -1,6 +1,7 @@  #include "util.h"  #include "parse-options.h"  #include "cache.h" +#include "header.h"  #define OPT_SHORT 1  #define OPT_UNSET 2 @@ -413,6 +414,8 @@ int parse_options(int argc, const char **argv, const struct option *options,  {  	struct parse_opt_ctx_t ctx; +	perf_header__set_cmdline(argc, argv); +  	parse_options_start(&ctx, argc, argv, flags);  	switch (parse_options_step(&ctx, options, usagestr)) {  	case PARSE_OPT_HELP: diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index e03b58a4842..0688bfb6d28 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -797,17 +797,13 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,  	event = perf_evlist__mmap_read(evlist, cpu);  	if (event != NULL) { -		struct perf_evsel *first;  		PyObject *pyevent = pyrf_event__new(event);  		struct pyrf_event *pevent = (struct pyrf_event *)pyevent;  		if (pyevent == NULL)  			return PyErr_NoMemory(); -		first = list_entry(evlist->entries.next, struct perf_evsel, node); -		err = perf_event__parse_sample(event, first->attr.sample_type, -					       perf_evsel__sample_size(first), -					       sample_id_all, &pevent->sample, false); +		err = perf_evlist__parse_sample(evlist, event, &pevent->sample, false);  		if (err)  			return PyErr_Format(PyExc_OSError,  					    "perf: can't parse sample, err=%d", err); diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c new file mode 100644 index 00000000000..0171fb61100 --- /dev/null +++ b/tools/perf/util/rblist.c @@ -0,0 +1,107 @@ +/* + * Based on strlist.c by: + * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> + * + * Licensed under the GPLv2. + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#include "rblist.h" + +int rblist__add_node(struct rblist *rblist, const void *new_entry) +{ +	struct rb_node **p = &rblist->entries.rb_node; +	struct rb_node *parent = NULL, *new_node; + +	while (*p != NULL) { +		int rc; + +		parent = *p; + +		rc = rblist->node_cmp(parent, new_entry); +		if (rc > 0) +			p = &(*p)->rb_left; +		else if (rc < 0) +			p = &(*p)->rb_right; +		else +			return -EEXIST; +	} + +	new_node = rblist->node_new(rblist, new_entry); +	if (new_node == NULL) +		return -ENOMEM; + +	rb_link_node(new_node, parent, p); +	rb_insert_color(new_node, &rblist->entries); +	++rblist->nr_entries; + +	return 0; +} + +void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node) +{ +	rb_erase(rb_node, &rblist->entries); +	rblist->node_delete(rblist, rb_node); +} + +struct rb_node *rblist__find(struct rblist *rblist, const void *entry) +{ +	struct rb_node **p = &rblist->entries.rb_node; +	struct rb_node *parent = NULL; + +	while (*p != NULL) { +		int rc; + +		parent = *p; + +		rc = rblist->node_cmp(parent, entry); +		if (rc > 0) +			p = &(*p)->rb_left; +		else if (rc < 0) +			p = &(*p)->rb_right; +		else +			return parent; +	} + +	return NULL; +} + +void rblist__init(struct rblist *rblist) +{ +	if (rblist != NULL) { +		rblist->entries	 = RB_ROOT; +		rblist->nr_entries = 0; +	} + +	return; +} + +void rblist__delete(struct rblist *rblist) +{ +	if (rblist != NULL) { +		struct rb_node *pos, *next = rb_first(&rblist->entries); + +		while (next) { +			pos = next; +			next = rb_next(pos); +			rb_erase(pos, &rblist->entries); +			rblist->node_delete(rblist, pos); +		} +		free(rblist); +	} +} + +struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx) +{ +	struct rb_node *node; + +	for (node = rb_first(&rblist->entries); node; node = rb_next(node)) { +		if (!idx--) +			return node; +	} + +	return NULL; +} diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h new file mode 100644 index 00000000000..6d0cae5ae83 --- /dev/null +++ b/tools/perf/util/rblist.h @@ -0,0 +1,47 @@ +#ifndef __PERF_RBLIST_H +#define __PERF_RBLIST_H + +#include <linux/rbtree.h> +#include <stdbool.h> + +/* + * create node structs of the form: + * struct my_node { + *     struct rb_node rb_node; + *     ... my data ... + * }; + * + * create list structs of the form: + * struct mylist { + *     struct rblist rblist; + *     ... my data ... + * }; + */ + +struct rblist { +	struct rb_root entries; +	unsigned int   nr_entries; + +	int (*node_cmp)(struct rb_node *rbn, const void *entry); +	struct rb_node *(*node_new)(struct rblist *rlist, const void *new_entry); +	void (*node_delete)(struct rblist *rblist, struct rb_node *rb_node); +}; + +void rblist__init(struct rblist *rblist); +void rblist__delete(struct rblist *rblist); +int rblist__add_node(struct rblist *rblist, const void *new_entry); +void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node); +struct rb_node *rblist__find(struct rblist *rblist, const void *entry); +struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx); + +static inline bool rblist__empty(const struct rblist *rblist) +{ +	return rblist->nr_entries == 0; +} + +static inline unsigned int rblist__nr_entries(const struct rblist *rblist) +{ +	return rblist->nr_entries; +} + +#endif /* __PERF_RBLIST_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 8e4f0755d2a..2437fb0b463 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -80,14 +80,12 @@ out_close:  	return -1;  } -void perf_session__update_sample_type(struct perf_session *self) +void perf_session__set_id_hdr_size(struct perf_session *session)  { -	self->sample_type = perf_evlist__sample_type(self->evlist); -	self->sample_size = __perf_evsel__sample_size(self->sample_type); -	self->sample_id_all = perf_evlist__sample_id_all(self->evlist); -	self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); -	self->host_machine.id_hdr_size = self->id_hdr_size; -	machines__set_id_hdr_size(&self->machines, self->id_hdr_size); +	u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist); + +	session->host_machine.id_hdr_size = id_hdr_size; +	machines__set_id_hdr_size(&session->machines, id_hdr_size);  }  int perf_session__create_kernel_maps(struct perf_session *self) @@ -147,7 +145,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,  	if (mode == O_RDONLY) {  		if (perf_session__open(self, force) < 0)  			goto out_delete; -		perf_session__update_sample_type(self); +		perf_session__set_id_hdr_size(self);  	} else if (mode == O_WRONLY) {  		/*  		 * In O_RDONLY mode this will be performed when reading the @@ -158,7 +156,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,  	}  	if (tool && tool->ordering_requires_timestamps && -	    tool->ordered_samples && !self->sample_id_all) { +	    tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) {  		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");  		tool->ordered_samples = false;  	} @@ -673,7 +671,8 @@ static void flush_sample_queue(struct perf_session *s,  		if (iter->timestamp > limit)  			break; -		ret = perf_session__parse_sample(s, iter->event, &sample); +		ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample, +						s->header.needs_swap);  		if (ret)  			pr_err("Can't parse sample, err = %d\n", ret);  		else @@ -865,16 +864,18 @@ static void perf_session__print_tstamp(struct perf_session *session,  				       union perf_event *event,  				       struct perf_sample *sample)  { +	u64 sample_type = perf_evlist__sample_type(session->evlist); +  	if (event->header.type != PERF_RECORD_SAMPLE && -	    !session->sample_id_all) { +	    !perf_evlist__sample_id_all(session->evlist)) {  		fputs("-1 -1 ", stdout);  		return;  	} -	if ((session->sample_type & PERF_SAMPLE_CPU)) +	if ((sample_type & PERF_SAMPLE_CPU))  		printf("%u ", sample->cpu); -	if (session->sample_type & PERF_SAMPLE_TIME) +	if (sample_type & PERF_SAMPLE_TIME)  		printf("%" PRIu64 " ", sample->time);  } @@ -899,6 +900,8 @@ static void dump_event(struct perf_session *session, union perf_event *event,  static void dump_sample(struct perf_session *session, union perf_event *event,  			struct perf_sample *sample)  { +	u64 sample_type; +  	if (!dump_trace)  		return; @@ -906,10 +909,12 @@ static void dump_sample(struct perf_session *session, union perf_event *event,  	       event->header.misc, sample->pid, sample->tid, sample->ip,  	       sample->period, sample->addr); -	if (session->sample_type & PERF_SAMPLE_CALLCHAIN) +	sample_type = perf_evlist__sample_type(session->evlist); + +	if (sample_type & PERF_SAMPLE_CALLCHAIN)  		callchain__printf(sample); -	if (session->sample_type & PERF_SAMPLE_BRANCH_STACK) +	if (sample_type & PERF_SAMPLE_BRANCH_STACK)  		branch_stack__printf(sample);  } @@ -1006,7 +1011,7 @@ static int perf_session__preprocess_sample(struct perf_session *session,  					   union perf_event *event, struct perf_sample *sample)  {  	if (event->header.type != PERF_RECORD_SAMPLE || -	    !(session->sample_type & PERF_SAMPLE_CALLCHAIN)) +	    !(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_CALLCHAIN))  		return 0;  	if (!ip_callchain__valid(sample->callchain, event)) { @@ -1030,7 +1035,7 @@ static int perf_session__process_user_event(struct perf_session *session, union  	case PERF_RECORD_HEADER_ATTR:  		err = tool->attr(event, &session->evlist);  		if (err == 0) -			perf_session__update_sample_type(session); +			perf_session__set_id_hdr_size(session);  		return err;  	case PERF_RECORD_HEADER_EVENT_TYPE:  		return tool->event_type(tool, event); @@ -1065,7 +1070,7 @@ static int perf_session__process_event(struct perf_session *session,  	int ret;  	if (session->header.needs_swap) -		event_swap(event, session->sample_id_all); +		event_swap(event, perf_evlist__sample_id_all(session->evlist));  	if (event->header.type >= PERF_RECORD_HEADER_MAX)  		return -EINVAL; @@ -1078,7 +1083,8 @@ static int perf_session__process_event(struct perf_session *session,  	/*  	 * For all kernel events we get the sample data  	 */ -	ret = perf_session__parse_sample(session, event, &sample); +	ret = perf_evlist__parse_sample(session->evlist, event, &sample, +					session->header.needs_swap);  	if (ret)  		return ret; @@ -1389,9 +1395,9 @@ int perf_session__process_events(struct perf_session *self,  	return err;  } -bool perf_session__has_traces(struct perf_session *self, const char *msg) +bool perf_session__has_traces(struct perf_session *session, const char *msg)  { -	if (!(self->sample_type & PERF_SAMPLE_RAW)) { +	if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) {  		pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);  		return false;  	} diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 7c435bde6eb..1f7ec87db7d 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -41,13 +41,9 @@ struct perf_session {  	 *	  perf.data file.  	 */  	struct hists		hists; -	u64			sample_type; -	int			sample_size;  	int			fd;  	bool			fd_pipe;  	bool			repipe; -	bool			sample_id_all; -	u16			id_hdr_size;  	int			cwdlen;  	char			*cwd;  	struct ordered_samples	ordered_samples; @@ -86,7 +82,7 @@ void perf_event__attr_swap(struct perf_event_attr *attr);  int perf_session__create_kernel_maps(struct perf_session *self); -void perf_session__update_sample_type(struct perf_session *self); +void perf_session__set_id_hdr_size(struct perf_session *session);  void perf_session__remove_thread(struct perf_session *self, struct thread *th);  static inline @@ -130,24 +126,6 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,  size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); -static inline int perf_session__parse_sample(struct perf_session *session, -					     const union perf_event *event, -					     struct perf_sample *sample) -{ -	return perf_event__parse_sample(event, session->sample_type, -					session->sample_size, -					session->sample_id_all, sample, -					session->header.needs_swap); -} - -static inline int perf_session__synthesize_sample(struct perf_session *session, -						  union perf_event *event, -						  const struct perf_sample *sample) -{ -	return perf_event__synthesize_sample(event, session->sample_type, -					     sample, session->header.needs_swap); -} -  struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,  					    unsigned int type); diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c index 6783a204355..95856ff3dda 100644 --- a/tools/perf/util/strlist.c +++ b/tools/perf/util/strlist.c @@ -10,23 +10,28 @@  #include <stdlib.h>  #include <string.h> -static struct str_node *str_node__new(const char *s, bool dupstr) +static +struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry)  { -	struct str_node *self = malloc(sizeof(*self)); +	const char *s = entry; +	struct rb_node *rc = NULL; +	struct strlist *strlist = container_of(rblist, struct strlist, rblist); +	struct str_node *snode = malloc(sizeof(*snode)); -	if (self != NULL) { -		if (dupstr) { +	if (snode != NULL) { +		if (strlist->dupstr) {  			s = strdup(s);  			if (s == NULL)  				goto out_delete;  		} -		self->s = s; +		snode->s = s; +		rc = &snode->rb_node;  	} -	return self; +	return rc;  out_delete: -	free(self); +	free(snode);  	return NULL;  } @@ -37,36 +42,26 @@ static void str_node__delete(struct str_node *self, bool dupstr)  	free(self);  } -int strlist__add(struct strlist *self, const char *new_entry) +static +void strlist__node_delete(struct rblist *rblist, struct rb_node *rb_node)  { -	struct rb_node **p = &self->entries.rb_node; -	struct rb_node *parent = NULL; -	struct str_node *sn; - -	while (*p != NULL) { -		int rc; - -		parent = *p; -		sn = rb_entry(parent, struct str_node, rb_node); -		rc = strcmp(sn->s, new_entry); +	struct strlist *slist = container_of(rblist, struct strlist, rblist); +	struct str_node *snode = container_of(rb_node, struct str_node, rb_node); -		if (rc > 0) -			p = &(*p)->rb_left; -		else if (rc < 0) -			p = &(*p)->rb_right; -		else -			return -EEXIST; -	} +	str_node__delete(snode, slist->dupstr); +} -	sn = str_node__new(new_entry, self->dupstr); -	if (sn == NULL) -		return -ENOMEM; +static int strlist__node_cmp(struct rb_node *rb_node, const void *entry) +{ +	const char *str = entry; +	struct str_node *snode = container_of(rb_node, struct str_node, rb_node); -	rb_link_node(&sn->rb_node, parent, p); -	rb_insert_color(&sn->rb_node, &self->entries); -	++self->nr_entries; +	return strcmp(snode->s, str); +} -	return 0; +int strlist__add(struct strlist *self, const char *new_entry) +{ +	return rblist__add_node(&self->rblist, new_entry);  }  int strlist__load(struct strlist *self, const char *filename) @@ -96,34 +91,20 @@ out:  	return err;  } -void strlist__remove(struct strlist *self, struct str_node *sn) +void strlist__remove(struct strlist *slist, struct str_node *snode)  { -	rb_erase(&sn->rb_node, &self->entries); -	str_node__delete(sn, self->dupstr); +	str_node__delete(snode, slist->dupstr);  } -struct str_node *strlist__find(struct strlist *self, const char *entry) +struct str_node *strlist__find(struct strlist *slist, const char *entry)  { -	struct rb_node **p = &self->entries.rb_node; -	struct rb_node *parent = NULL; +	struct str_node *snode = NULL; +	struct rb_node *rb_node = rblist__find(&slist->rblist, entry); -	while (*p != NULL) { -		struct str_node *sn; -		int rc; +	if (rb_node) +		snode = container_of(rb_node, struct str_node, rb_node); -		parent = *p; -		sn = rb_entry(parent, struct str_node, rb_node); -		rc = strcmp(sn->s, entry); - -		if (rc > 0) -			p = &(*p)->rb_left; -		else if (rc < 0) -			p = &(*p)->rb_right; -		else -			return sn; -	} - -	return NULL; +	return snode;  }  static int strlist__parse_list_entry(struct strlist *self, const char *s) @@ -156,9 +137,12 @@ struct strlist *strlist__new(bool dupstr, const char *slist)  	struct strlist *self = malloc(sizeof(*self));  	if (self != NULL) { -		self->entries	 = RB_ROOT; +		rblist__init(&self->rblist); +		self->rblist.node_cmp    = strlist__node_cmp; +		self->rblist.node_new    = strlist__node_new; +		self->rblist.node_delete = strlist__node_delete; +  		self->dupstr	 = dupstr; -		self->nr_entries = 0;  		if (slist && strlist__parse_list(self, slist) != 0)  			goto out_error;  	} @@ -171,30 +155,18 @@ out_error:  void strlist__delete(struct strlist *self)  { -	if (self != NULL) { -		struct str_node *pos; -		struct rb_node *next = rb_first(&self->entries); - -		while (next) { -			pos = rb_entry(next, struct str_node, rb_node); -			next = rb_next(&pos->rb_node); -			strlist__remove(self, pos); -		} -		self->entries = RB_ROOT; -		free(self); -	} +	if (self != NULL) +		rblist__delete(&self->rblist);  } -struct str_node *strlist__entry(const struct strlist *self, unsigned int idx) +struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx)  { -	struct rb_node *nd; +	struct str_node *snode = NULL; +	struct rb_node *rb_node; -	for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { -		struct str_node *pos = rb_entry(nd, struct str_node, rb_node); +	rb_node = rblist__entry(&slist->rblist, idx); +	if (rb_node) +		snode = container_of(rb_node, struct str_node, rb_node); -		if (!idx--) -			return pos; -	} - -	return NULL; +	return snode;  } diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h index 3ba839007d2..dd9f922ec67 100644 --- a/tools/perf/util/strlist.h +++ b/tools/perf/util/strlist.h @@ -4,14 +4,15 @@  #include <linux/rbtree.h>  #include <stdbool.h> +#include "rblist.h" +  struct str_node {  	struct rb_node rb_node;  	const char     *s;  };  struct strlist { -	struct rb_root entries; -	unsigned int   nr_entries; +	struct rblist rblist;  	bool	       dupstr;  }; @@ -32,18 +33,18 @@ static inline bool strlist__has_entry(struct strlist *self, const char *entry)  static inline bool strlist__empty(const struct strlist *self)  { -	return self->nr_entries == 0; +	return rblist__empty(&self->rblist);  }  static inline unsigned int strlist__nr_entries(const struct strlist *self)  { -	return self->nr_entries; +	return rblist__nr_entries(&self->rblist);  }  /* For strlist iteration */  static inline struct str_node *strlist__first(struct strlist *self)  { -	struct rb_node *rn = rb_first(&self->entries); +	struct rb_node *rn = rb_first(&self->rblist.entries);  	return rn ? rb_entry(rn, struct str_node, rb_node) : NULL;  }  static inline struct str_node *strlist__next(struct str_node *sn) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fdad4eeeb42..8b63b678e12 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -64,7 +64,7 @@ static enum dso_binary_type binary_type_symtab[] = {  	DSO_BINARY_TYPE__NOT_FOUND,  }; -#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab) +#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab)  static enum dso_binary_type binary_type_data[] = {  	DSO_BINARY_TYPE__BUILD_ID_CACHE, @@ -72,7 +72,7 @@ static enum dso_binary_type binary_type_data[] = {  	DSO_BINARY_TYPE__NOT_FOUND,  }; -#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data) +#define DSO_BINARY_TYPE__DATA_CNT ARRAY_SIZE(binary_type_data)  int dso__name_len(const struct dso *dso)  { @@ -2875,6 +2875,7 @@ int machines__create_guest_kernel_maps(struct rb_root *machines)  	int i, items = 0;  	char path[PATH_MAX];  	pid_t pid; +	char *endp;  	if (symbol_conf.default_guest_vmlinux_name ||  	    symbol_conf.default_guest_modules || @@ -2891,7 +2892,14 @@ int machines__create_guest_kernel_maps(struct rb_root *machines)  				/* Filter out . and .. */  				continue;  			} -			pid = atoi(namelist[i]->d_name); +			pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10); +			if ((*endp != '\0') || +			    (endp == namelist[i]->d_name) || +			    (errno == ERANGE)) { +				pr_debug("invalid directory (%s). Skipping.\n", +					 namelist[i]->d_name); +				continue; +			}  			sprintf(path, "%s/%s/proc/kallsyms",  				symbol_conf.guestmount,  				namelist[i]->d_name); diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c index 3f59c496e64..051eaa68095 100644 --- a/tools/perf/util/target.c +++ b/tools/perf/util/target.c @@ -110,7 +110,7 @@ int perf_target__strerror(struct perf_target *target, int errnum,  	int idx;  	const char *msg; -	BUG_ON(buflen > 0); +	BUG_ON(buflen == 0);  	if (errnum >= 0) {  		const char *err = strerror_r(errnum, buf, buflen);  |