diff options
1769 files changed, 22916 insertions, 18264 deletions
diff --git a/.gitignore b/.gitignore index 0f2f40f7191..92bd0e45dfa 100644 --- a/.gitignore +++ b/.gitignore @@ -14,10 +14,6 @@ *.o.* *.a *.s -*.ko.unsigned -*.ko.stripped -*.ko.stripped.dig -*.ko.stripped.sig *.ko *.so *.so.dbg @@ -95,6 +91,4 @@ GTAGS extra_certificates signing_key.priv signing_key.x509 -signing_key.x509.keyid -signing_key.x509.signer x509.genkey @@ -1823,6 +1823,11 @@ S: Kattreinstr 38 S: D-64295 S: Germany +N: Avi Kivity +E: avi.kivity@gmail.com +D: Kernel-based Virtual Machine (KVM) +S: Ra'annana, Israel + N: Andi Kleen E: andi@firstfloor.org U: http://www.halobates.de diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index f54273e2ac9..ceb1ff73546 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -210,6 +210,8 @@ local_ops.txt - semantics and behavior of local atomic operations. lockdep-design.txt - documentation on the runtime locking correctness validator. +lockup-watchdogs.txt + - info on soft and hard lockup detectors (aka nmi_watchdog). logo.gif - full colour GIF image of Linux logo (penguin - Tux). logo.txt @@ -240,8 +242,6 @@ netlabel/ - directory with information on the NetLabel subsystem. networking/ - directory with info on various aspects of networking with Linux. -nmi_watchdog.txt - - info on NMI watchdog for SMP systems. nommu-mmap.txt - documentation about no-mmu memory mapping support. numastat.txt diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile index 9b7e4c55792..f9fd615427f 100644 --- a/Documentation/DocBook/media/Makefile +++ b/Documentation/DocBook/media/Makefile @@ -56,15 +56,15 @@ FUNCS = \ write \ IOCTLS = \ - $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/videodev2.h) \ - $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/audio.h) \ - $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/ca.h) \ - $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/dmx.h) \ - $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/frontend.h) \ - $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/net.h) \ - $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/video.h) \ - $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/media.h) \ - $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/v4l2-subdev.h) \ + $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/videodev2.h) \ + $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/audio.h) \ + $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/ca.h) \ + $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/dmx.h) \ + $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/frontend.h) \ + $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/net.h) \ + $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/video.h) \ + $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/media.h) \ + $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \ VIDIOC_SUBDEV_G_FRAME_INTERVAL \ VIDIOC_SUBDEV_S_FRAME_INTERVAL \ VIDIOC_SUBDEV_ENUM_MBUS_CODE \ @@ -74,32 +74,32 @@ IOCTLS = \ VIDIOC_SUBDEV_S_SELECTION \ TYPES = \ - $(shell perl -ne 'print "$$1 " if /^typedef\s+[^\s]+\s+([^\s]+)\;/' $(srctree)/include/linux/videodev2.h) \ - $(shell perl -ne 'print "$$1 " if /^}\s+([a-z0-9_]+_t)/' $(srctree)/include/linux/dvb/frontend.h) + $(shell perl -ne 'print "$$1 " if /^typedef\s+[^\s]+\s+([^\s]+)\;/' $(srctree)/include/uapi/linux/videodev2.h) \ + $(shell perl -ne 'print "$$1 " if /^}\s+([a-z0-9_]+_t)/' $(srctree)/include/uapi/linux/dvb/frontend.h) ENUMS = \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/audio.h) \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/ca.h) \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/dmx.h) \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/frontend.h) \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/net.h) \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/video.h) \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h) \ - $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h) + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/videodev2.h) \ + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/audio.h) \ + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/ca.h) \ + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/dmx.h) \ + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/frontend.h) \ + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/net.h) \ + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/video.h) \ + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \ + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h) \ + $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h) STRUCTS = \ - $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \ - $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s\{]+)\s*/)' $(srctree)/include/linux/dvb/audio.h) \ - $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/ca.h) \ - $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/dmx.h) \ - $(shell perl -ne 'print "$$1 " if (!/dtv\_cmds\_h/ && /^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/frontend.h) \ - $(shell perl -ne 'print "$$1 " if (/^struct\s+([A-Z][^\s]+)\s+/)' $(srctree)/include/linux/dvb/net.h) \ - $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/video.h) \ - $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \ - $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h) \ - $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h) + $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/videodev2.h) \ + $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s\{]+)\s*/)' $(srctree)/include/uapi/linux/dvb/audio.h) \ + $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/ca.h) \ + $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/dmx.h) \ + $(shell perl -ne 'print "$$1 " if (!/dtv\_cmds\_h/ && /^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/frontend.h) \ + $(shell perl -ne 'print "$$1 " if (/^struct\s+([A-Z][^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/net.h) \ + $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/video.h) \ + $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \ + $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \ + $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h) ERRORS = \ E2BIG \ @@ -205,7 +205,7 @@ $(MEDIA_OBJ_DIR)/v4l2.xml: $(OBJIMGFILES) @(ln -sf $(MEDIA_SRC_DIR)/v4l/*xml $(MEDIA_OBJ_DIR)/) @(ln -sf $(MEDIA_SRC_DIR)/dvb/*xml $(MEDIA_OBJ_DIR)/) -$(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/linux/videodev2.h $(MEDIA_OBJ_DIR)/v4l2.xml +$(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/uapi/linux/videodev2.h $(MEDIA_OBJ_DIR)/v4l2.xml @$($(quiet)gen_xml) @( \ echo "<programlisting>") > $@ @@ -216,7 +216,7 @@ $(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/linux/videodev2.h $(MEDIA_O @( \ echo "</programlisting>") >> $@ -$(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/linux/dvb/audio.h $(MEDIA_OBJ_DIR)/v4l2.xml +$(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/uapi/linux/dvb/audio.h $(MEDIA_OBJ_DIR)/v4l2.xml @$($(quiet)gen_xml) @( \ echo "<programlisting>") > $@ @@ -227,7 +227,7 @@ $(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/linux/dvb/audio.h $(MEDIA_OBJ_D @( \ echo "</programlisting>") >> $@ -$(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4l2.xml +$(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/uapi/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4l2.xml @$($(quiet)gen_xml) @( \ echo "<programlisting>") > $@ @@ -238,7 +238,7 @@ $(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4 @( \ echo "</programlisting>") >> $@ -$(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/v4l2.xml +$(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/uapi/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/v4l2.xml @$($(quiet)gen_xml) @( \ echo "<programlisting>") > $@ @@ -249,7 +249,7 @@ $(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/ @( \ echo "</programlisting>") >> $@ -$(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/linux/dvb/frontend.h $(MEDIA_OBJ_DIR)/v4l2.xml +$(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/uapi/linux/dvb/frontend.h $(MEDIA_OBJ_DIR)/v4l2.xml @$($(quiet)gen_xml) @( \ echo "<programlisting>") > $@ @@ -260,7 +260,7 @@ $(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/linux/dvb/frontend.h $(MEDIA @( \ echo "</programlisting>") >> $@ -$(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/linux/dvb/net.h $(MEDIA_OBJ_DIR)/v4l2.xml +$(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/uapi/linux/dvb/net.h $(MEDIA_OBJ_DIR)/v4l2.xml @$($(quiet)gen_xml) @( \ echo "<programlisting>") > $@ @@ -271,7 +271,7 @@ $(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/linux/dvb/net.h $(MEDIA_OBJ_DIR)/ @( \ echo "</programlisting>") >> $@ -$(MEDIA_OBJ_DIR)/video.h.xml: $(srctree)/include/linux/dvb/video.h $(MEDIA_OBJ_DIR)/v4l2.xml +$(MEDIA_OBJ_DIR)/video.h.xml: $(srctree)/include/uapi/linux/dvb/video.h $(MEDIA_OBJ_DIR)/v4l2.xml @$($(quiet)gen_xml) @( \ echo "<programlisting>") > $@ diff --git a/Documentation/DocBook/networking.tmpl b/Documentation/DocBook/networking.tmpl index 59ad69a9d77..29df25016c7 100644 --- a/Documentation/DocBook/networking.tmpl +++ b/Documentation/DocBook/networking.tmpl @@ -56,7 +56,7 @@ !Enet/core/filter.c </sect1> <sect1><title>Generic Network Statistics</title> -!Iinclude/linux/gen_stats.h +!Iinclude/uapi/linux/gen_stats.h !Enet/core/gen_stats.c !Enet/core/gen_estimator.c </sect1> @@ -80,7 +80,7 @@ !Enet/wimax/op-rfkill.c !Enet/wimax/stack.c !Iinclude/net/wimax.h -!Iinclude/linux/wimax.h +!Iinclude/uapi/linux/wimax.h </sect1> </chapter> diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt index b2bea15137d..16eb4c9e923 100644 --- a/Documentation/IPMI.txt +++ b/Documentation/IPMI.txt @@ -42,13 +42,7 @@ The driver interface depends on your hardware. If your system properly provides the SMBIOS info for IPMI, the driver will detect it and just work. If you have a board with a standard interface (These will generally be either "KCS", "SMIC", or "BT", consult your hardware -manual), choose the 'IPMI SI handler' option. A driver also exists -for direct I2C access to the IPMI management controller. Some boards -support this, but it is unknown if it will work on every board. For -this, choose 'IPMI SMBus handler', but be ready to try to do some -figuring to see if it will work on your system if the SMBIOS/APCI -information is wrong or not present. It is fairly safe to have both -these enabled and let the drivers auto-detect what is present. +manual), choose the 'IPMI SI handler' option. You should generally enable ACPI on your system, as systems with IPMI can have ACPI tables describing them. @@ -58,8 +52,7 @@ their job correctly, the IPMI controller should be automatically detected (via ACPI or SMBIOS tables) and should just work. Sadly, many boards do not have this information. The driver attempts standard defaults, but they may not work. If you fall into this -situation, you need to read the section below named 'The SI Driver' or -"The SMBus Driver" on how to hand-configure your system. +situation, you need to read the section below named 'The SI Driver'. IPMI defines a standard watchdog timer. You can enable this with the 'IPMI Watchdog Timer' config option. If you compile the driver into @@ -104,12 +97,7 @@ driver, each open file for this device ties in to the message handler as an IPMI user. ipmi_si - A driver for various system interfaces. This supports KCS, -SMIC, and BT interfaces. Unless you have an SMBus interface or your -own custom interface, you probably need to use this. - -ipmi_smb - A driver for accessing BMCs on the SMBus. It uses the -I2C kernel driver's SMBus interfaces to send and receive IPMI messages -over the SMBus. +SMIC, and BT interfaces. ipmi_watchdog - IPMI requires systems to have a very capable watchdog timer. This driver implements the standard Linux watchdog timer @@ -482,53 +470,6 @@ for specifying an interface. Note that when removing an interface, only the first three parameters (si type, address type, and address) are used for the comparison. Any options are ignored for removing. -The SMBus Driver ----------------- - -The SMBus driver allows up to 4 SMBus devices to be configured in the -system. By default, the driver will register any SMBus interfaces it finds -in the I2C address range of 0x20 to 0x4f on any adapter. You can change this -at module load time (for a module) with: - - modprobe ipmi_smb.o - addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]] - dbg=<flags1>,<flags2>... - [defaultprobe=1] [dbg_probe=1] - -The addresses are specified in pairs, the first is the adapter ID and the -second is the I2C address on that adapter. - -The debug flags are bit flags for each BMC found, they are: -IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8 - -Setting smb_defaultprobe to zero disabled the default probing of SMBus -interfaces at address range 0x20 to 0x4f. This means that only the -BMCs specified on the smb_addr line will be detected. - -Setting smb_dbg_probe to 1 will enable debugging of the probing and -detection process for BMCs on the SMBusses. - -Discovering the IPMI compliant BMC on the SMBus can cause devices -on the I2C bus to fail. The SMBus driver writes a "Get Device ID" IPMI -message as a block write to the I2C bus and waits for a response. -This action can be detrimental to some I2C devices. It is highly recommended -that the known I2c address be given to the SMBus driver in the smb_addr -parameter. The default address range will not be used when a smb_addr -parameter is provided. - -When compiled into the kernel, the addresses can be specified on the -kernel command line as: - - ipmb_smb.addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]] - ipmi_smb.dbg=<flags1>,<flags2>... - ipmi_smb.defaultprobe=0 ipmi_smb.dbg_probe=1 - -These are the same options as on the module command line. - -Note that you might need some I2C changes if CONFIG_IPMI_PANIC_EVENT -is enabled along with this, so the I2C driver knows to run to -completion during sending a panic event. - Other Pieces ------------ diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt index dbbdcbba75a..4110cca96bd 100644 --- a/Documentation/arm64/memory.txt +++ b/Documentation/arm64/memory.txt @@ -27,17 +27,17 @@ Start End Size Use ----------------------------------------------------------------------- 0000000000000000 0000007fffffffff 512GB user -ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc +ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc -ffffffbbfffd0000 ffffffbcfffdffff 64KB [guard page] +ffffffbbffff0000 ffffffbbffffffff 64KB [guard page] -ffffffbbfffe0000 ffffffbcfffeffff 64KB PCI I/O space +ffffffbc00000000 ffffffbdffffffff 8GB vmemmap -ffffffbbffff0000 ffffffbcffffffff 64KB [guard page] +ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap] -ffffffbc00000000 ffffffbdffffffff 8GB vmemmap +ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space -ffffffbe00000000 ffffffbffbffffff ~8GB [guard, future vmmemap] +ffffffbbffff0000 ffffffbcffffffff ~2MB [guard] ffffffbffc000000 ffffffbfffffffff 64MB modules diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index c07f7b4fb88..71c4da41344 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -466,6 +466,10 @@ Note: 5.3 swappiness Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only. +Please note that unlike the global swappiness, memcg knob set to 0 +really prevents from any swapping even if there is a swap storage +available. This might lead to memcg OOM killer if there are no file +pages to reclaim. Following cgroups' swappiness can't be changed. - root cgroup (uses /proc/sys/vm/swappiness). diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index ecc81e36871..d187e9f7cf1 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -8,7 +8,7 @@ PIT Timer required properties: shared across all System Controller members. TC/TCLIB Timer required properties: -- compatible: Should be "atmel,<chip>-pit". +- compatible: Should be "atmel,<chip>-tcb". <chip> can be "at91rm9200" or "at91sam9x5" - reg: Should contain registers location and length - interrupts: Should contain all interrupts for the TC block diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt new file mode 100644 index 00000000000..df70318a617 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt @@ -0,0 +1,19 @@ +* EETI eGalax Multiple Touch Controller + +Required properties: +- compatible: must be "eeti,egalax_ts" +- reg: i2c slave address +- interrupt-parent: the phandle for the interrupt controller +- interrupts: touch controller interrupt +- wakeup-gpios: the gpio pin to be used for waking up the controller + as well as uased as irq pin + +Example: + + egalax_ts@04 { + compatible = "eeti,egalax_ts"; + reg = <0x04>; + interrupt-parent = <&gpio1>; + interrupts = <9 2>; + wakeup-gpios = <&gpio1 9 0>; + }; diff --git a/Documentation/devicetree/bindings/net/mdio-gpio.txt b/Documentation/devicetree/bindings/net/mdio-gpio.txt index bc954952901..c79bab02536 100644 --- a/Documentation/devicetree/bindings/net/mdio-gpio.txt +++ b/Documentation/devicetree/bindings/net/mdio-gpio.txt @@ -8,9 +8,16 @@ gpios property as described in section VIII.1 in the following order: MDC, MDIO. +Note: Each gpio-mdio bus should have an alias correctly numbered in "aliases" +node. + Example: -mdio { +aliases { + mdio-gpio0 = <&mdio0>; +}; + +mdio0: mdio { compatible = "virtual,mdio-gpio"; #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt index c8e578263ce..683fde93c4f 100644 --- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt @@ -93,7 +93,7 @@ Valid values for pin and group names are: With some exceptions, these support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength, - nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling. + nvidia,pull-up-strength, nvidia,slew-rate-rising, nvidia,slew-rate-falling. drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2, drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg, diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt index c275b70349c..6f426ed7009 100644 --- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt +++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt @@ -83,7 +83,7 @@ Valid values for pin and group names are: drive groups: These all support nvidia,pull-down-strength, nvidia,pull-up-strength, - nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all + nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode. ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1, diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index a1793d670cd..3844d21d6ca 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -33,7 +33,7 @@ Table of Contents 2 Modifying System Parameters 3 Per-Process Parameters - 3.1 /proc/<pid>/oom_score_adj - Adjust the oom-killer + 3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj - Adjust the oom-killer score 3.2 /proc/<pid>/oom_score - Display current oom-killer score 3.3 /proc/<pid>/io - Display the IO accounting fields @@ -1320,10 +1320,10 @@ of the kernel. CHAPTER 3: PER-PROCESS PARAMETERS ------------------------------------------------------------------------------ -3.1 /proc/<pid>/oom_score_adj- Adjust the oom-killer score +3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj- Adjust the oom-killer score -------------------------------------------------------------------------------- -This file can be used to adjust the badness heuristic used to select which +These file can be used to adjust the badness heuristic used to select which process gets killed in out of memory conditions. The badness heuristic assigns a value to each candidate task ranging from 0 @@ -1361,6 +1361,12 @@ same system, cpuset, mempolicy, or memory controller resources to use at least equivalent to discounting 50% of the task's allowed memory from being considered as scoring against the task. +For backwards compatibility with previous kernels, /proc/<pid>/oom_adj may also +be used to tune the badness score. Its acceptable values range from -16 +(OOM_ADJUST_MIN) to +15 (OOM_ADJUST_MAX) and a special value of -17 +(OOM_DISABLE) to disable oom killing entirely for that task. Its value is +scaled linearly with /proc/<pid>/oom_score_adj. + The value of /proc/<pid>/oom_score_adj may be reduced no lower than the last value set by a CAP_SYS_RESOURCE process. To reduce the value any lower requires CAP_SYS_RESOURCE. @@ -1375,7 +1381,9 @@ minimal amount of work. ------------------------------------------------------------- This file can be used to check the current score used by the oom-killer is for -any given <pid>. +any given <pid>. Use it together with /proc/<pid>/oom_score_adj to tune which +process should be killed in an out-of-memory situation. + 3.3 /proc/<pid>/io - Display the IO accounting fields ------------------------------------------------------- diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README index 7eceaff63f5..815b711bcd8 100644 --- a/Documentation/firmware_class/README +++ b/Documentation/firmware_class/README @@ -18,32 +18,40 @@ High level behavior (mixed): ============================ - kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device) - - userspace: + 1), kernel(driver): + - calls request_firmware(&fw_entry, $FIRMWARE, device) + - kernel searchs the fimware image with name $FIRMWARE directly + in the below search path of root filesystem: + "/lib/firmware/updates/" UTS_RELEASE, + "/lib/firmware/updates", + "/lib/firmware/" UTS_RELEASE, + "/lib/firmware" + - If found, goto 7), else goto 2) + + 2), userspace: - /sys/class/firmware/xxx/{loading,data} appear. - hotplug gets called with a firmware identifier in $FIRMWARE and the usual hotplug environment. - hotplug: echo 1 > /sys/class/firmware/xxx/loading - kernel: Discard any previous partial load. + 3), kernel: Discard any previous partial load. - userspace: + 4), userspace: - hotplug: cat appropriate_firmware_image > \ /sys/class/firmware/xxx/data - kernel: grows a buffer in PAGE_SIZE increments to hold the image as it + 5), kernel: grows a buffer in PAGE_SIZE increments to hold the image as it comes in. - userspace: + 6), userspace: - hotplug: echo 0 > /sys/class/firmware/xxx/loading - kernel: request_firmware() returns and the driver has the firmware + 7), kernel: request_firmware() returns and the driver has the firmware image in fw_entry->{data,size}. If something went wrong request_firmware() returns non-zero and fw_entry is set to NULL. - kernel(driver): Driver code calls release_firmware(fw_entry) releasing + 8), kernel(driver): Driver code calls release_firmware(fw_entry) releasing the firmware image and any related resource. High level behavior (driver code): diff --git a/Documentation/hwmon/coretemp b/Documentation/hwmon/coretemp index c86b50c03ea..f17256f069b 100644 --- a/Documentation/hwmon/coretemp +++ b/Documentation/hwmon/coretemp @@ -105,6 +105,7 @@ Process Processor TjMax(C) 330/230 125 E680/660/640/620 90 E680T/660T/640T/620T 110 + CE4170/4150/4110 110 45nm Core2 Processors Solo ULV SU3500/3300 100 diff --git a/Documentation/hwmon/fam15h_power b/Documentation/hwmon/fam15h_power index a92918e0bd6..80654813d04 100644 --- a/Documentation/hwmon/fam15h_power +++ b/Documentation/hwmon/fam15h_power @@ -10,7 +10,7 @@ Supported chips: BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors (not yet published) -Author: Andreas Herrmann <andreas.herrmann3@amd.com> +Author: Andreas Herrmann <herrmann.der.user@googlemail.com> Description ----------- diff --git a/Documentation/hwmon/submitting-patches b/Documentation/hwmon/submitting-patches index 790f774a303..843751c41fe 100644 --- a/Documentation/hwmon/submitting-patches +++ b/Documentation/hwmon/submitting-patches @@ -60,8 +60,7 @@ increase the chances of your change being accepted. * Add the driver to Kconfig and Makefile in alphabetical order. -* Make sure that all dependencies are listed in Kconfig. For new drivers, it - is most likely prudent to add a dependency on EXPERIMENTAL. +* Make sure that all dependencies are listed in Kconfig. * Avoid forward declarations if you can. Rearrange the code if necessary. diff --git a/Documentation/networking/netdev-features.txt b/Documentation/networking/netdev-features.txt index 4164f5c02e4..f310edec8a7 100644 --- a/Documentation/networking/netdev-features.txt +++ b/Documentation/networking/netdev-features.txt @@ -164,4 +164,4 @@ read the CRC recorded by the NIC on receipt of the packet. This requests that the NIC receive all possible frames, including errored frames (such as bad FCS, etc). This can be helpful when sniffing a link with bad packets on it. Some NICs may receive more packets if also put into normal -PROMISC mdoe. +PROMISC mode. diff --git a/Documentation/networking/vxlan.txt b/Documentation/networking/vxlan.txt index 5b34b762d7d..6d993510f09 100644 --- a/Documentation/networking/vxlan.txt +++ b/Documentation/networking/vxlan.txt @@ -32,7 +32,7 @@ no entry is in the forwarding table. # ip link delete vxlan0 3. Show vxlan info - # ip -d show vxlan0 + # ip -d link show vxlan0 It is possible to create, destroy and display the vxlan forwarding table using the new bridge command. @@ -41,7 +41,7 @@ forwarding table using the new bridge command. # bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0 2. Delete forwarding table entry - # bridge fdb delete 00:17:42:8a:b4:05 + # bridge fdb delete 00:17:42:8a:b4:05 dev vxlan0 3. Show forwarding table # bridge fdb show dev vxlan0 diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index 642f84495b2..2a4cdda4828 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt @@ -116,6 +116,7 @@ On all - write a character to /proc/sysrq-trigger. e.g.: 'w' - Dumps tasks that are in uninterruptable (blocked) state. 'x' - Used by xmon interface on ppc/powerpc platforms. + Show global PMU Registers on sparc64. 'y' - Show global CPU Registers [SPARC-64 specific] diff --git a/Documentation/zh_CN/IRQ.txt b/Documentation/zh_CN/IRQ.txt new file mode 100644 index 00000000000..956026d5cf8 --- /dev/null +++ b/Documentation/zh_CN/IRQ.txt @@ -0,0 +1,39 @@ +Chinese translated version of Documentation/IRQ.txt + +If you have any comment or update to the content, please contact the +original document maintainer directly. However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help. Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Maintainer: Eric W. Biederman <ebiederman@xmission.com> +Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> +--------------------------------------------------------------------- +Documentation/IRQ.txt 的中文翻译 + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者。 +英文版维护者: Eric W. Biederman <ebiederman@xmission.com> +中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com> +中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> +中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> + + +以下为正文 +--------------------------------------------------------------------- +何为 IRQ? + +一个 IRQ 是来自某个设备的一个中断请求。目前,它们可以来自一个硬件引脚, +或来自一个数据包。多个设备可能连接到同个硬件引脚,从而共享一个 IRQ。 + +一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下,这是一个 +全局 irq_desc 数组的索引,但是除了在 linux/interrupt.h 中的实现, +具体的细节是体系结构特定的。 + +一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下,枚举的编号是 +该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况, +枚举的是在两个 i8259 中断控制器中 16 个输入引脚。 + +架构可以对 IRQ 编号指定额外的含义,在硬件涉及任何手工配置的情况下, +是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。 diff --git a/Documentation/zh_CN/arm64/booting.txt b/Documentation/zh_CN/arm64/booting.txt new file mode 100644 index 00000000000..28fa325b746 --- /dev/null +++ b/Documentation/zh_CN/arm64/booting.txt @@ -0,0 +1,156 @@ +Chinese translated version of Documentation/arm64/booting.txt + +If you have any comment or update to the content, please contact the +original document maintainer directly. However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help. Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Maintainer: Will Deacon <will.deacon@arm.com> +Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> +--------------------------------------------------------------------- +Documentation/arm64/booting.txt 的中文翻译 + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者。 + +英文版维护者: Will Deacon <will.deacon@arm.com> +中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com> +中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> +中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> + +以下为正文 +--------------------------------------------------------------------- + 启动 AArch64 Linux + ================== + +作者: Will Deacon <will.deacon@arm.com> +日期: 2012 年 09 月 07 日 + +本文档基于 Russell King 的 ARM 启动文档,且适用于所有公开发布的 +AArch64 Linux 内核代码。 + +AArch64 异常模型由多个异常级别(EL0 - EL3)组成,对于 EL0 和 EL1 +异常级有对应的安全和非安全模式。EL2 是系统管理级,且仅存在于 +非安全模式下。EL3 是最高特权级,且仅存在于安全模式下。 + +基于本文档的目的,我们将简单地使用‘引导装载程序’(‘boot loader’) +这个术语来定义在将控制权交给 Linux 内核前 CPU 上执行的所有软件。 +这可能包含安全监控和系统管理代码,或者它可能只是一些用于准备最小启动 +环境的指令。 + +基本上,引导装载程序(至少)应实现以下操作: + +1、设置和初始化 RAM +2、设置设备树数据 +3、解压内核映像 +4、调用内核映像 + + +1、设置和初始化 RAM +----------------- + +必要性: 强制 + +引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。 +这个操作的执行是设备依赖的。(它可能使用内部算法来自动定位和计算所有 +RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何引导装载程序 +设计者想到的匹配方法。) + + +2、设置设备树数据 +--------------- + +必要性: 强制 + +设备树数据块(dtb)大小必须不大于 2 MB,且位于从内核映像起始算起第一个 +512MB 内的 2MB 边界上。这使得内核可以通过初始页表中的单个节描述符来 +映射此数据块。 + + +3、解压内核映像 +------------- + +必要性: 可选 + +AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内核映像文件 +(比如 Image.gz),则需要通过引导装载程序(使用 gzip 等)来进行解压。 +若引导装载程序没有实现这个需求,就要使用非压缩内核映像文件。 + + +4、调用内核映像 +------------- + +必要性: 强制 + +已解压的内核映像包含一个 32 字节的头,内容如下: + + u32 magic = 0x14000008; /* 跳转到 stext, 小端 */ + u32 res0 = 0; /* 保留 */ + u64 text_offset; /* 映像装载偏移 */ + u64 res1 = 0; /* 保留 */ + u64 res2 = 0; /* 保留 */ + +映像必须位于系统 RAM 起始处的特定偏移(当前是 0x80000)。系统 RAM +的起始地址必须是以 2MB 对齐的。 + +在跳转入内核前,必须符合以下状态: + +- 停止所有 DMA 设备,这样内存数据就不会因为虚假网络包或磁盘数据而 + 被破坏。这可能可以节省你许多的调试时间。 + +- 主 CPU 通用寄存器设置 + x0 = 系统 RAM 中设备树数据块(dtb)的物理地址。 + x1 = 0 (保留,将来可能使用) + x2 = 0 (保留,将来可能使用) + x3 = 0 (保留,将来可能使用) + +- CPU 模式 + 所有形式的中断必须在 PSTATE.DAIF 中被屏蔽(Debug、SError、IRQ + 和 FIQ)。 + CPU 必须处于 EL2(推荐,可访问虚拟化扩展)或非安全 EL1 模式下。 + +- 高速缓存、MMU + MMU 必须关闭。 + 指令缓存开启或关闭都可以。 + 数据缓存必须关闭且无效。 + 外部高速缓存(如果存在)必须配置并禁用。 + +- 架构计时器 + CNTFRQ 必须设定为计时器的频率。 + 如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0) + 必须置位。 + +- 一致性 + 通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。 + 这可能要根据具体实现来定义初始化过程,以使能每个CPU上对维护操作的 + 接收。 + +- 系统寄存器 + 在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件 + 在一个更高的异常级别下初始化,以防止在 未知 状态下运行。 + +引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口: + +- 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树 + 数据块必须在每个 CPU 节点中包含以下内容: + + 1、‘enable-method’属性。目前,此字段支持的值仅为字符串“spin-table”。 + + 2、‘cpu-release-addr’标识一个 64-bit、初始化为零的内存位置。 + + 引导装载程序必须生成这些设备树属性,并在跳入内核入口之前将其插入 + 数据块。 + +- 任何辅助 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递 + 给内核)中自旋于内核之外,轮询它们的 cpu-release-addr 位置(必须 + 包含在保留区中)。可通过插入 wfe 指令来降低忙循环开销,而主 CPU 将 + 发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值 + 时,CPU 必须直接跳入此值所指向的地址。 + +- 辅助 CPU 通用寄存器设置 + x0 = 0 (保留,将来可能使用) + x1 = 0 (保留,将来可能使用) + x2 = 0 (保留,将来可能使用) + x3 = 0 (保留,将来可能使用) diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/zh_CN/arm64/memory.txt new file mode 100644 index 00000000000..83b51931470 --- /dev/null +++ b/Documentation/zh_CN/arm64/memory.txt @@ -0,0 +1,93 @@ +Chinese translated version of Documentation/arm64/memory.txt + +If you have any comment or update to the content, please contact the +original document maintainer directly. However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help. Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Maintainer: Catalin Marinas <catalin.marinas@arm.com> +Chinese maintainer: Fu Wei <tekkamanninja@gmail.com> +--------------------------------------------------------------------- +Documentation/arm64/memory.txt 的中文翻译 + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者。 + +英文版维护者: Catalin Marinas <catalin.marinas@arm.com> +中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com> +中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> +中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com> + +以下为正文 +--------------------------------------------------------------------- + Linux 在 AArch64 中的内存布局 + =========================== + +作者: Catalin Marinas <catalin.marinas@arm.com> +日期: 2012 年 02 月 20 日 + +本文档描述 AArch64 Linux 内核所使用的虚拟内存布局。此构架可以实现 +页大小为 4KB 的 4 级转换表和页大小为 64KB 的 3 级转换表。 + +AArch64 Linux 使用页大小为 4KB 的 3 级转换表配置,对于用户和内核 +都有 39-bit (512GB) 的虚拟地址空间。对于页大小为 64KB的配置,仅 +使用 2 级转换表,但内存布局相同。 + +用户地址空间的 63:39 位为 0,而内核地址空间的相应位为 1。TTBRx 的 +选择由虚拟地址的 63 位给出。swapper_pg_dir 仅包含内核(全局)映射, +而用户 pgd 仅包含用户(非全局)映射。swapper_pgd_dir 地址被写入 +TTBR1 中,且从不写入 TTBR0。 + + +AArch64 Linux 内存布局: + +起始地址 结束地址 大小 用途 +----------------------------------------------------------------------- +0000000000000000 0000007fffffffff 512GB 用户空间 + +ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc + +ffffffbbfffd0000 ffffffbcfffdffff 64KB [防护页] + +ffffffbbfffe0000 ffffffbcfffeffff 64KB PCI I/O 空间 + +ffffffbbffff0000 ffffffbcffffffff 64KB [防护页] + +ffffffbc00000000 ffffffbdffffffff 8GB vmemmap + +ffffffbe00000000 ffffffbffbffffff ~8GB [防护页,未来用于 vmmemap] + +ffffffbffc000000 ffffffbfffffffff 64MB 模块 + +ffffffc000000000 ffffffffffffffff 256GB 内存空间 + + +4KB 页大小的转换表查找: + ++--------+--------+--------+--------+--------+--------+--------+--------+ +|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| ++--------+--------+--------+--------+--------+--------+--------+--------+ + | | | | | | + | | | | | v + | | | | | [11:0] 页内偏移 + | | | | +-> [20:12] L3 索引 + | | | +-----------> [29:21] L2 索引 + | | +---------------------> [38:30] L1 索引 + | +-------------------------------> [47:39] L0 索引 (未使用) + +-------------------------------------------------> [63] TTBR0/1 + + +64KB 页大小的转换表查找: + ++--------+--------+--------+--------+--------+--------+--------+--------+ +|63 56|55 48|47 40|39 32|31 24|23 16|15 8|7 0| ++--------+--------+--------+--------+--------+--------+--------+--------+ + | | | | | + | | | | v + | | | | [15:0] 页内偏移 + | | | +----------> [28:16] L3 索引 + | | +--------------------------> [41:29] L2 索引 (仅使用 38:29 ) + | +-------------------------------> [47:42] L1 索引 (未使用) + +-------------------------------------------------> [63] TTBR0/1 diff --git a/MAINTAINERS b/MAINTAINERS index e73060fe078..9386a63ea8f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -235,6 +235,7 @@ F: drivers/platform/x86/acer-wmi.c ACPI M: Len Brown <lenb@kernel.org> +M: Rafael J. Wysocki <rjw@sisk.pl> L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ Q: http://patchwork.kernel.org/project/linux-acpi/list/ @@ -502,7 +503,7 @@ F: include/linux/altera_uart.h F: include/linux/altera_jtaguart.h AMD FAM15H PROCESSOR POWER MONITORING DRIVER -M: Andreas Herrmann <andreas.herrmann3@amd.com> +M: Andreas Herrmann <herrmann.der.user@googlemail.com> L: lm-sensors@lm-sensors.org S: Maintained F: Documentation/hwmon/fam15h_power @@ -525,17 +526,17 @@ F: drivers/video/geode/ F: arch/x86/include/asm/geode.h AMD IOMMU (AMD-VI) -M: Joerg Roedel <joerg.roedel@amd.com> +M: Joerg Roedel <joro@8bytes.org> L: iommu@lists.linux-foundation.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git -S: Supported +S: Maintained F: drivers/iommu/amd_iommu*.[ch] F: include/linux/amd-iommu.h AMD MICROCODE UPDATE SUPPORT -M: Andreas Herrmann <andreas.herrmann3@amd.com> +M: Andreas Herrmann <herrmann.der.user@googlemail.com> L: amd64-microcode@amd64.org -S: Supported +S: Maintained F: arch/x86/kernel/microcode_amd.c AMS (Apple Motion Sensor) DRIVER @@ -636,6 +637,13 @@ W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/ +ARM SUB-ARCHITECTURES +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: MAINTAINED +F: arch/arm/mach-*/ +F: arch/arm/plat-*/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git + ARM PRIMECELL AACI PL041 DRIVER M: Russell King <linux@arm.linux.org.uk> S: Maintained @@ -833,6 +841,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git F: arch/arm/mach-sa1100/jornada720.c F: arch/arm/mach-sa1100/include/mach/jornada720.h +ARM/IGEP MACHINE SUPPORT +M: Enric Balletbo i Serra <eballetbo@gmail.com> +M: Javier Martinez Canillas <javier@dowhile0.org> +L: linux-omap@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-omap2/board-igep0020.c + ARM/INCOME PXA270 SUPPORT M: Marek Vasut <marek.vasut@gmail.com> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -2499,6 +2515,7 @@ M: Joonyoung Shim <jy0922.shim@samsung.com> M: Seung-Woo Kim <sw0312.kim@samsung.com> M: Kyungmin Park <kyungmin.park@samsung.com> L: dri-devel@lists.freedesktop.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git S: Supported F: drivers/gpu/drm/exynos F: include/drm/exynos* @@ -2699,10 +2716,10 @@ F: include/linux/edac.h EDAC-AMD64 M: Doug Thompson <dougthompson@xmission.com> -M: Borislav Petkov <borislav.petkov@amd.com> +M: Borislav Petkov <bp@alien8.de> L: linux-edac@vger.kernel.org W: bluesmoke.sourceforge.net -S: Supported +S: Maintained F: drivers/edac/amd64_edac* EDAC-E752X @@ -2801,6 +2818,7 @@ F: sound/usb/misc/ua101.c EXTENSIBLE FIRMWARE INTERFACE (EFI) M: Matt Fleming <matt.fleming@intel.com> L: linux-efi@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git S: Maintained F: Documentation/x86/efi-stub.txt F: arch/ia64/kernel/efi.c @@ -3588,6 +3606,49 @@ F: drivers/hid/hid-hyperv.c F: drivers/net/hyperv/ F: drivers/staging/hv/ +I2C OVER PARALLEL PORT +M: Jean Delvare <khali@linux-fr.org> +L: linux-i2c@vger.kernel.org +S: Maintained +F: Documentation/i2c/busses/i2c-parport +F: Documentation/i2c/busses/i2c-parport-light +F: drivers/i2c/busses/i2c-parport.c +F: drivers/i2c/busses/i2c-parport-light.c + +I2C/SMBUS CONTROLLER DRIVERS FOR PC +M: Jean Delvare <khali@linux-fr.org> +L: linux-i2c@vger.kernel.org +S: Maintained +F: Documentation/i2c/busses/i2c-ali1535 +F: Documentation/i2c/busses/i2c-ali1563 +F: Documentation/i2c/busses/i2c-ali15x3 +F: Documentation/i2c/busses/i2c-amd756 +F: Documentation/i2c/busses/i2c-amd8111 +F: Documentation/i2c/busses/i2c-i801 +F: Documentation/i2c/busses/i2c-nforce2 +F: Documentation/i2c/busses/i2c-piix4 +F: Documentation/i2c/busses/i2c-sis5595 +F: Documentation/i2c/busses/i2c-sis630 +F: Documentation/i2c/busses/i2c-sis96x +F: Documentation/i2c/busses/i2c-via +F: Documentation/i2c/busses/i2c-viapro +F: drivers/i2c/busses/i2c-ali1535.c +F: drivers/i2c/busses/i2c-ali1563.c +F: drivers/i2c/busses/i2c-ali15x3.c +F: drivers/i2c/busses/i2c-amd756.c +F: drivers/i2c/busses/i2c-amd756-s4882.c +F: drivers/i2c/busses/i2c-amd8111.c +F: drivers/i2c/busses/i2c-i801.c +F: drivers/i2c/busses/i2c-isch.c +F: drivers/i2c/busses/i2c-nforce2.c +F: drivers/i2c/busses/i2c-nforce2-s4985.c +F: drivers/i2c/busses/i2c-piix4.c +F: drivers/i2c/busses/i2c-sis5595.c +F: drivers/i2c/busses/i2c-sis630.c +F: drivers/i2c/busses/i2c-sis96x.c +F: drivers/i2c/busses/i2c-via.c +F: drivers/i2c/busses/i2c-viapro.c + I2C/SMBUS STUB DRIVER M: "Mark M. Hoffman" <mhoffman@lightlink.com> L: linux-i2c@vger.kernel.org @@ -3595,9 +3656,8 @@ S: Maintained F: drivers/i2c/busses/i2c-stub.c I2C SUBSYSTEM -M: "Jean Delvare (PC drivers, core)" <khali@linux-fr.org> +M: Wolfram Sang <w.sang@pengutronix.de> M: "Ben Dooks (embedded platforms)" <ben-linux@fluff.org> -M: "Wolfram Sang (embedded platforms)" <w.sang@pengutronix.de> L: linux-i2c@vger.kernel.org W: http://i2c.wiki.kernel.org/ T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/ @@ -3608,6 +3668,13 @@ F: drivers/i2c/ F: include/linux/i2c.h F: include/linux/i2c-*.h +I2C-TAOS-EVM DRIVER +M: Jean Delvare <khali@linux-fr.org> +L: linux-i2c@vger.kernel.org +S: Maintained +F: Documentation/i2c/busses/i2c-taos-evm +F: drivers/i2c/busses/i2c-taos-evm.c + I2C-TINY-USB DRIVER M: Till Harbaum <till@harbaum.org> L: linux-i2c@vger.kernel.org @@ -3694,7 +3761,7 @@ S: Maintained F: drivers/platform/x86/ideapad-laptop.c IDE/ATAPI DRIVERS -M: Borislav Petkov <petkovbb@gmail.com> +M: Borislav Petkov <bp@alien8.de> L: linux-ide@vger.kernel.org S: Maintained F: Documentation/cdrom/ide-cd @@ -4221,8 +4288,8 @@ F: include/linux/lockd/ F: include/linux/sunrpc/ KERNEL VIRTUAL MACHINE (KVM) -M: Avi Kivity <avi@redhat.com> M: Marcelo Tosatti <mtosatti@redhat.com> +M: Gleb Natapov <gleb@redhat.com> L: kvm@vger.kernel.org W: http://kvm.qumranet.com S: Supported @@ -4372,7 +4439,7 @@ F: Documentation/scsi/53c700.txt F: drivers/scsi/53c700* LED SUBSYSTEM -M: Bryan Wu <bryan.wu@canonical.com> +M: Bryan Wu <cooloney@gmail.com> M: Richard Purdie <rpurdie@rpsys.net> L: linux-leds@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git @@ -5019,6 +5086,20 @@ F: net/ipv6/ F: include/net/ip* F: arch/x86/net/* +NETWORKING [IPSEC] +M: Steffen Klassert <steffen.klassert@secunet.com> +M: Herbert Xu <herbert@gondor.apana.org.au> +M: "David S. Miller" <davem@davemloft.net> +L: netdev@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git +S: Maintained +F: net/xfrm/ +F: net/key/ +F: net/ipv4/xfrm* +F: net/ipv6/xfrm* +F: include/uapi/linux/xfrm.h +F: include/net/xfrm.h + NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK) M: Paul Moore <paul@paul-moore.com> L: netdev@vger.kernel.org @@ -5046,7 +5127,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git S: Odd Fixes F: drivers/net/ F: include/linux/if_* -F: include/linux/*device.h +F: include/linux/netdevice.h +F: include/linux/arcdevice.h +F: include/linux/etherdevice.h +F: include/linux/fcdevice.h +F: include/linux/fddidevice.h +F: include/linux/hippidevice.h +F: include/linux/inetdevice.h NETXEN (1/10) GbE SUPPORT M: Sony Chacko <sony.chacko@qlogic.com> @@ -5334,7 +5421,7 @@ S: Maintained F: sound/drivers/opl4/ OPROFILE -M: Robert Richter <robert.richter@amd.com> +M: Robert Richter <rric@kernel.org> L: oprofile-list@lists.sf.net S: Maintained F: arch/*/include/asm/oprofile*.h @@ -5618,7 +5705,7 @@ S: Maintained F: drivers/pinctrl/spear/ PKTCDVD DRIVER -M: Peter Osterlund <petero2@telia.com> +M: Jiri Kosina <jkosina@suse.cz> S: Maintained F: drivers/block/pktcdvd.c F: include/linux/pktcdvd.h @@ -7180,6 +7267,14 @@ L: linux-xtensa@linux-xtensa.org S: Maintained F: arch/xtensa/ +THERMAL +M: Zhang Rui <rui.zhang@intel.com> +L: linux-pm@vger.kernel.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git +S: Supported +F: drivers/thermal/ +F: include/linux/thermal.h + THINKPAD ACPI EXTRAS DRIVER M: Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br> L: ibm-acpi-devel@lists.sourceforge.net @@ -7731,6 +7826,13 @@ W: http://www.ideasonboard.org/uvc/ S: Maintained F: drivers/media/usb/uvc/ +USB WEBCAM GADGET +M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +L: linux-usb@vger.kernel.org +S: Maintained +F: drivers/usb/gadget/*uvc*.c +F: drivers/usb/gadget/webcam.c + USB WIRELESS RNDIS DRIVER (rndis_wlan) M: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> L: linux-wireless@vger.kernel.org @@ -7850,13 +7952,6 @@ M: Roger Luethi <rl@hellgate.ch> S: Maintained F: drivers/net/ethernet/via/via-rhine.c -VIAPRO SMBUS DRIVER -M: Jean Delvare <khali@linux-fr.org> -L: linux-i2c@vger.kernel.org -S: Maintained -F: Documentation/i2c/busses/i2c-viapro -F: drivers/i2c/busses/i2c-viapro.c - VIA SD/MMC CARD CONTROLLER DRIVER M: Bruce Chang <brucechang@via.com.tw> M: Harald Welte <HaraldWelte@viatech.com> @@ -8111,7 +8206,7 @@ F: drivers/platform/x86 X86 MCE INFRASTRUCTURE M: Tony Luck <tony.luck@intel.com> -M: Borislav Petkov <bp@amd64.org> +M: Borislav Petkov <bp@alien8.de> L: linux-edac@vger.kernel.org S: Maintained F: arch/x86/kernel/cpu/mcheck/* @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 7 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc7 NAME = Terrified Chipmunk # *DOCUMENTATION* @@ -437,7 +437,9 @@ endif PHONY += asm-generic asm-generic: $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \ - obj=arch/$(SRCARCH)/include/generated/asm + src=asm obj=arch/$(SRCARCH)/include/generated/asm + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \ + src=uapi/asm obj=arch/$(SRCARCH)/include/generated/uapi/asm # To make sure we do not include .config for any of the *config targets # catch them early, and hand them over to scripts/kconfig/Makefile @@ -717,6 +719,17 @@ endif # INSTALL_MOD_STRIP export mod_strip_cmd +ifeq ($(CONFIG_MODULE_SIG),y) +MODSECKEY = ./signing_key.priv +MODPUBKEY = ./signing_key.x509 +export MODPUBKEY +mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY) +else +mod_sign_cmd = true +endif +export mod_sign_cmd + + ifeq ($(KBUILD_EXTMOD),) core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ diff --git a/arch/Kconfig b/arch/Kconfig index 366ec06a518..8d698fb5ccc 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -341,4 +341,18 @@ config MODULES_USE_ELF_REL Modules only use ELF REL relocations. Modules with ELF RELA relocations will give an error. +# +# ABI hall of shame +# +config CLONE_BACKWARDS + bool + help + Architecture has tls passed as the 4th argument of clone(2), + not the 5th one. + +config CLONE_BACKWARDS2 + bool + help + Architecture has the first two arguments of clone(2) swapped. + source "kernel/gcov/Kconfig" diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h index 4554ecbff7c..1f8c72959fb 100644 --- a/arch/alpha/include/asm/thread_info.h +++ b/arch/alpha/include/asm/thread_info.h @@ -7,6 +7,7 @@ #include <asm/processor.h> #include <asm/types.h> #include <asm/hwrpb.h> +#include <asm/sysinfo.h> #endif #ifndef __ASSEMBLY__ @@ -21,6 +22,7 @@ struct thread_info { mm_segment_t addr_limit; /* thread address space */ unsigned cpu; /* current CPU */ int preempt_count; /* 0 => preemptable, <0 => BUG */ + unsigned int status; /* thread-synchronous flags */ int bpt_nsaved; unsigned long bpt_addr[2]; /* breakpoint handling */ @@ -63,8 +65,6 @@ register struct thread_info *__current_thread_info __asm__("$8"); * - these are process state flags and used from assembly * - pending work-to-be-done flags come first and must be assigned to be * within bits 0 to 7 to fit in and immediate operand. - * - ALPHA_UAC_SHIFT below must be kept consistent with the unaligned - * control flags. * * TIF_SYSCALL_TRACE is known to be 0 via blbs. */ @@ -72,18 +72,12 @@ register struct thread_info *__current_thread_info __asm__("$8"); #define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ -#define TIF_POLLING_NRFLAG 8 /* poll_idle is polling NEED_RESCHED */ #define TIF_DIE_IF_KERNEL 9 /* dik recursion lock */ -#define TIF_UAC_NOPRINT 10 /* ! Preserve sequence of following */ -#define TIF_UAC_NOFIX 11 /* ! flags as they match */ -#define TIF_UAC_SIGBUS 12 /* ! userspace part of 'osf_sysinfo' */ #define TIF_MEMDIE 13 /* is terminating due to OOM killer */ -#define TIF_RESTORE_SIGMASK 14 /* restore signal mask in do_signal */ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) -#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) /* Work to do on interrupt/exception return. */ @@ -94,29 +88,63 @@ register struct thread_info *__current_thread_info __asm__("$8"); #define _TIF_ALLWORK_MASK (_TIF_WORK_MASK \ | _TIF_SYSCALL_TRACE) -#define ALPHA_UAC_SHIFT TIF_UAC_NOPRINT -#define ALPHA_UAC_MASK (1 << TIF_UAC_NOPRINT | 1 << TIF_UAC_NOFIX | \ - 1 << TIF_UAC_SIGBUS) +#define TS_UAC_NOPRINT 0x0001 /* ! Preserve the following three */ +#define TS_UAC_NOFIX 0x0002 /* ! flags as they match */ +#define TS_UAC_SIGBUS 0x0004 /* ! userspace part of 'osf_sysinfo' */ +#define TS_RESTORE_SIGMASK 0x0008 /* restore signal mask in do_signal() */ +#define TS_POLLING 0x0010 /* idle task polling need_resched, + skip sending interrupt */ -#define SET_UNALIGN_CTL(task,value) ({ \ - task_thread_info(task)->flags = ((task_thread_info(task)->flags & \ - ~ALPHA_UAC_MASK) \ - | (((value) << ALPHA_UAC_SHIFT) & (1<<TIF_UAC_NOPRINT))\ - | (((value) << (ALPHA_UAC_SHIFT + 1)) & (1<<TIF_UAC_SIGBUS)) \ - | (((value) << (ALPHA_UAC_SHIFT - 1)) & (1<<TIF_UAC_NOFIX)));\ +#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING) + +#ifndef __ASSEMBLY__ +#define HAVE_SET_RESTORE_SIGMASK 1 +static inline void set_restore_sigmask(void) +{ + struct thread_info *ti = current_thread_info(); + ti->status |= TS_RESTORE_SIGMASK; + WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags)); +} +static inline void clear_restore_sigmask(void) +{ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; +} +static inline bool test_restore_sigmask(void) +{ + return current_thread_info()->status & TS_RESTORE_SIGMASK; +} +static inline bool test_and_clear_restore_sigmask(void) +{ + struct thread_info *ti = current_thread_info(); + if (!(ti->status & TS_RESTORE_SIGMASK)) + return false; + ti->status &= ~TS_RESTORE_SIGMASK; + return true; +} +#endif + +#define SET_UNALIGN_CTL(task,value) ({ \ + __u32 status = task_thread_info(task)->status & ~UAC_BITMASK; \ + if (value & PR_UNALIGN_NOPRINT) \ + status |= TS_UAC_NOPRINT; \ + if (value & PR_UNALIGN_SIGBUS) \ + status |= TS_UAC_SIGBUS; \ + if (value & 4) /* alpha-specific */ \ + status |= TS_UAC_NOFIX; \ + task_thread_info(task)->status = status; \ 0; }) #define GET_UNALIGN_CTL(task,value) ({ \ - put_user((task_thread_info(task)->flags & (1 << TIF_UAC_NOPRINT))\ - >> ALPHA_UAC_SHIFT \ - | (task_thread_info(task)->flags & (1 << TIF_UAC_SIGBUS))\ - >> (ALPHA_UAC_SHIFT + 1) \ - | (task_thread_info(task)->flags & (1 << TIF_UAC_NOFIX))\ - >> (ALPHA_UAC_SHIFT - 1), \ - (int __user *)(value)); \ + __u32 status = task_thread_info(task)->status & ~UAC_BITMASK; \ + __u32 res = 0; \ + if (status & TS_UAC_NOPRINT) \ + res |= PR_UNALIGN_NOPRINT; \ + if (status & TS_UAC_SIGBUS) \ + res |= PR_UNALIGN_SIGBUS; \ + if (status & TS_UAC_NOFIX) \ + res |= 4; \ + put_user(res, (int __user *)(value)); \ }) -#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG) - #endif /* __KERNEL__ */ #endif /* _ALPHA_THREAD_INFO_H */ diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index a7607832dd4..c245de65c61 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -617,7 +617,6 @@ ret_from_kernel_thread: .ent sys_fork sys_fork: .prologue 0 - mov $sp, $21 bsr $1, do_switch_stack bis $31, SIGCHLD, $16 mov $31, $17 @@ -625,7 +624,9 @@ sys_fork: mov $31, $19 mov $31, $20 jsr $26, alpha_clone - bsr $1, undo_switch_stack +fork_out: + ldq $26, 56($sp) + lda $sp, SWITCH_STACK_SIZE($sp) ret .end sys_fork @@ -634,12 +635,10 @@ sys_fork: .ent sys_clone sys_clone: .prologue 0 - mov $sp, $21 bsr $1, do_switch_stack /* $16, $17, $18, $19, $20 come from the user. */ - jsr $26, alpha_clone - bsr $1, undo_switch_stack - ret + lda $26, fork_out + jsr $31, alpha_clone .end sys_clone .align 4 @@ -647,11 +646,9 @@ sys_clone: .ent sys_vfork sys_vfork: .prologue 0 - mov $sp, $16 bsr $1, do_switch_stack - jsr $26, alpha_vfork - bsr $1, undo_switch_stack - ret + lda $26, fork_out + jsr $31, alpha_vfork .end sys_vfork .align 4 @@ -661,8 +658,6 @@ sys_sigreturn: .prologue 0 lda $9, ret_from_straced cmpult $26, $9, $9 - mov $sp, $17 - lda $18, -SWITCH_STACK_SIZE($sp) lda $sp, -SWITCH_STACK_SIZE($sp) jsr $26, do_sigreturn bne $9, 1f @@ -678,8 +673,6 @@ sys_rt_sigreturn: .prologue 0 lda $9, ret_from_straced cmpult $26, $9, $9 - mov $sp, $17 - lda $18, -SWITCH_STACK_SIZE($sp) lda $sp, -SWITCH_STACK_SIZE($sp) jsr $26, do_rt_sigreturn bne $9, 1f diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 9eb090582cf..14db93e4c8a 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -445,7 +445,7 @@ struct procfs_args { * unhappy with OSF UFS. [CHECKME] */ static int -osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags) +osf_ufs_mount(const char *dirname, struct ufs_args __user *args, int flags) { int retval; struct cdfs_args tmp; @@ -465,7 +465,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags) } static int -osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags) +osf_cdfs_mount(const char *dirname, struct cdfs_args __user *args, int flags) { int retval; struct cdfs_args tmp; @@ -485,7 +485,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags) } static int -osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags) +osf_procfs_mount(const char *dirname, struct procfs_args __user *args, int flags) { struct procfs_args tmp; @@ -793,8 +793,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer, case GSI_UACPROC: if (nbytes < sizeof(unsigned int)) return -EINVAL; - w = (current_thread_info()->flags >> ALPHA_UAC_SHIFT) & - UAC_BITMASK; + w = current_thread_info()->status & UAC_BITMASK; if (put_user(w, (unsigned int __user *)buffer)) return -EFAULT; return 1; @@ -904,24 +903,20 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer, break; case SSI_NVPAIRS: { - unsigned long v, w, i; - unsigned int old, new; + unsigned __user *p = buffer; + unsigned i; - for (i = 0; i < nbytes; ++i) { + for (i = 0, p = buffer; i < nbytes; ++i, p += 2) { + unsigned v, w, status; - if (get_user(v, 2*i + (unsigned int __user *)buffer)) - return -EFAULT; - if (get_user(w, 2*i + 1 + (unsigned int __user *)buffer)) + if (get_user(v, p) || get_user(w, p + 1)) return -EFAULT; switch (v) { case SSIN_UACPROC: - again: - old = current_thread_info()->flags; - new = old & ~(UAC_BITMASK << ALPHA_UAC_SHIFT); - new = new | (w & UAC_BITMASK) << ALPHA_UAC_SHIFT; - if (cmpxchg(¤t_thread_info()->flags, - old, new) != old) - goto again; + w &= UAC_BITMASK; + status = current_thread_info()->status; + status = (status & ~UAC_BITMASK) | w; + current_thread_info()->status = status; break; default: diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 4054e0ffe2b..a4dc79ba030 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -49,7 +49,7 @@ EXPORT_SYMBOL(pm_power_off); void cpu_idle(void) { - set_thread_flag(TIF_POLLING_NRFLAG); + current_thread_info()->status |= TS_POLLING; while (1) { /* FIXME -- EV6 and LCA45 know how to power down @@ -246,19 +246,17 @@ release_thread(struct task_struct *dead_task) int alpha_clone(unsigned long clone_flags, unsigned long usp, int __user *parent_tid, int __user *child_tid, - unsigned long tls_value, struct pt_regs *regs) + unsigned long tls_value) { - if (!usp) - usp = rdusp(); - - return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid); + return do_fork(clone_flags, usp, current_pt_regs(), 0, + parent_tid, child_tid); } int -alpha_vfork(struct pt_regs *regs) +alpha_vfork(void) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), - regs, 0, NULL, NULL); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, + current_pt_regs(), 0, NULL, NULL); } /* @@ -268,18 +266,22 @@ alpha_vfork(struct pt_regs *regs) int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, - struct task_struct * p, struct pt_regs * regs) + struct task_struct *p, struct pt_regs *wontuse) { extern void ret_from_fork(void); extern void ret_from_kernel_thread(void); struct thread_info *childti = task_thread_info(p); struct pt_regs *childregs = task_pt_regs(p); + struct pt_regs *regs = current_pt_regs(); struct switch_stack *childstack, *stack; unsigned long settls; childstack = ((struct switch_stack *) childregs) - 1; - if (unlikely(!regs)) { + childti->pcb.ksp = (unsigned long) childstack; + childti->pcb.flags = 1; /* set FEN, clear everything else */ + + if (unlikely(p->flags & PF_KTHREAD)) { /* kernel thread */ memset(childstack, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs)); @@ -288,12 +290,17 @@ copy_thread(unsigned long clone_flags, unsigned long usp, childstack->r10 = arg; childregs->hae = alpha_mv.hae_cache, childti->pcb.usp = 0; - childti->pcb.ksp = (unsigned long) childstack; - childti->pcb.flags = 1; /* set FEN, clear everything else */ return 0; } + /* Note: if CLONE_SETTLS is not set, then we must inherit the + value from the parent, which will have been set by the block + copy in dup_task_struct. This is non-intuitive, but is + required for proper operation in the case of a threaded + application calling fork. */ + if (clone_flags & CLONE_SETTLS) + childti->pcb.unique = regs->r20; + childti->pcb.usp = usp ?: rdusp(); *childregs = *regs; - settls = regs->r20; childregs->r0 = 0; childregs->r19 = 0; childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ @@ -301,22 +308,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, stack = ((struct switch_stack *) regs) - 1; *childstack = *stack; childstack->r26 = (unsigned long) ret_from_fork; - childti->pcb.usp = usp; - childti->pcb.ksp = (unsigned long) childstack; - childti->pcb.flags = 1; /* set FEN, clear everything else */ - - /* Set a new TLS for the child thread? Peek back into the - syscall arguments that we saved on syscall entry. Oops, - except we'd have clobbered it with the parent/child set - of r20. Read the saved copy. */ - /* Note: if CLONE_SETTLS is not set, then we must inherit the - value from the parent, which will have been set by the block - copy in dup_task_struct. This is non-intuitive, but is - required for proper operation in the case of a threaded - application calling fork. */ - if (clone_flags & CLONE_SETTLS) - childti->pcb.unique = settls; - return 0; } diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 32575f85507..336393c9c11 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -160,10 +160,10 @@ extern char compile_time_assert #define INSN_CALLSYS 0x00000083 static long -restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, - struct switch_stack *sw) +restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) { unsigned long usp; + struct switch_stack *sw = (struct switch_stack *)regs - 1; long i, err = __get_user(regs->pc, &sc->sc_pc); current_thread_info()->restart_block.fn = do_no_restart_syscall; @@ -215,9 +215,9 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, registers and transfer control from userland. */ asmlinkage void -do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, - struct switch_stack *sw) +do_sigreturn(struct sigcontext __user *sc) { + struct pt_regs *regs = current_pt_regs(); sigset_t set; /* Verify that it's a good sigcontext before using it */ @@ -228,7 +228,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs, set_current_blocked(&set); - if (restore_sigcontext(sc, regs, sw)) + if (restore_sigcontext(sc, regs)) goto give_sigsegv; /* Send SIGTRAP if we're single-stepping: */ @@ -249,9 +249,9 @@ give_sigsegv: } asmlinkage void -do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, - struct switch_stack *sw) +do_rt_sigreturn(struct rt_sigframe __user *frame) { + struct pt_regs *regs = current_pt_regs(); sigset_t set; /* Verify that it's a good ucontext_t before using it */ @@ -262,7 +262,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs, set_current_blocked(&set); - if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) + if (restore_sigcontext(&frame->uc.uc_mcontext, regs)) goto give_sigsegv; /* Send SIGTRAP if we're single-stepping: */ diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 80d987c0e9a..272666d006d 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -780,17 +780,17 @@ do_entUnaUser(void __user * va, unsigned long opcode, /* Check the UAC bits to decide what the user wants us to do with the unaliged access. */ - if (!test_thread_flag (TIF_UAC_NOPRINT)) { + if (!(current_thread_info()->status & TS_UAC_NOPRINT)) { if (__ratelimit(&ratelimit)) { printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n", current->comm, task_pid_nr(current), regs->pc - 4, va, opcode, reg); } } - if (test_thread_flag (TIF_UAC_SIGBUS)) + if ((current_thread_info()->status & TS_UAC_SIGBUS)) goto give_sigbus; /* Not sure why you'd want to use this, but... */ - if (test_thread_flag (TIF_UAC_NOFIX)) + if ((current_thread_info()->status & TS_UAC_NOFIX)) return; /* Don't bother reading ds in the access check since we already diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 73067efd484..ade7e924bef 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1603,8 +1603,8 @@ config NR_CPUS default "4" config HOTPLUG_CPU - bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" - depends on SMP && HOTPLUG && EXPERIMENTAL + bool "Support for hot-pluggable CPUs" + depends on SMP && HOTPLUG help Say Y here to experiment with turning CPUs off and on. CPUs can be controlled through /sys/devices/system/cpu. @@ -1645,8 +1645,8 @@ config HZ default 100 config THUMB2_KERNEL - bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)" - depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL + bool "Compile the kernel in Thumb-2 mode" + depends on CPU_V7 && !CPU_V6 && !CPU_V6K select AEABI select ARM_ASM_UNIFIED select ARM_UNWIND @@ -1850,6 +1850,7 @@ config XEN_DOM0 config XEN bool "Xen guest support on ARM (EXPERIMENTAL)" depends on EXPERIMENTAL && ARM && OF + depends on CPU_V7 && !CPU_V6 help Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. diff --git a/arch/arm/Makefile b/arch/arm/Makefile index f023e3acdfb..5f914fca911 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -21,8 +21,6 @@ endif OBJCOPYFLAGS :=-O binary -R .comment -S GZFLAGS :=-9 #KBUILD_CFLAGS +=-pipe -# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: -KBUILD_CFLAGS +=$(call cc-option,-marm,) # Never generate .eh_frame KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm) @@ -105,17 +103,20 @@ endif ifeq ($(CONFIG_THUMB2_KERNEL),y) AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it) AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W) -CFLAGS_THUMB2 :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN) -AFLAGS_THUMB2 :=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb +CFLAGS_ISA :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN) +AFLAGS_ISA :=$(CFLAGS_ISA) -Wa$(comma)-mthumb # Work around buggy relocation from gas if requested: ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y) CFLAGS_MODULE +=-fno-optimize-sibling-calls endif +else +CFLAGS_ISA :=$(call cc-option,-marm,) +AFLAGS_ISA :=$(CFLAGS_ISA) endif # Need -Uarm for gcc < 3.x -KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm -KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float +KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm +KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float CHECKFLAGS += -D__arm__ diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 3fdab016aa5..9137df539b6 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -33,7 +33,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y) $(obj)/xipImage: vmlinux FORCE $(call if_changed,objcopy) - @echo ' Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))' + @$(kecho) ' Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))' $(obj)/Image $(obj)/zImage: FORCE @echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)' @@ -48,14 +48,14 @@ $(obj)/xipImage: FORCE $(obj)/Image: vmlinux FORCE $(call if_changed,objcopy) - @echo ' Kernel: $@ is ready' + @$(kecho) ' Kernel: $@ is ready' $(obj)/compressed/vmlinux: $(obj)/Image FORCE $(Q)$(MAKE) $(build)=$(obj)/compressed $@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) - @echo ' Kernel: $@ is ready' + @$(kecho) ' Kernel: $@ is ready' endif @@ -90,7 +90,7 @@ fi $(obj)/uImage: $(obj)/zImage FORCE @$(check_for_multiple_loadaddr) $(call if_changed,uimage) - @echo ' Image $@ is ready' + @$(kecho) ' Image $@ is ready' $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE $(Q)$(MAKE) $(build)=$(obj)/bootp $@ @@ -98,7 +98,7 @@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE $(obj)/bootpImage: $(obj)/bootp/bootp FORCE $(call if_changed,objcopy) - @echo ' Kernel: $@ is ready' + @$(kecho) ' Kernel: $@ is ready' PHONY += initrd FORCE initrd: diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index c1ce813fcc4..f37cf9fa5fa 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -25,6 +25,8 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \ exynos4210-trats.dtb \ exynos5250-smdk5250.dtb dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb +dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \ + integratorcp.dtb dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \ kirkwood-dns325.dtb \ diff --git a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi index b06c0db273b..e6391a4e664 100644 --- a/arch/arm/boot/dts/at91sam9g20ek_common.dtsi +++ b/arch/arm/boot/dts/at91sam9g20ek_common.dtsi @@ -126,14 +126,14 @@ #size-cells = <0>; btn3 { - label = "Buttin 3"; + label = "Button 3"; gpios = <&pioA 30 1>; linux,code = <0x103>; gpio-key,wakeup; }; btn4 { - label = "Buttin 4"; + label = "Button 4"; gpios = <&pioA 31 1>; linux,code = <0x104>; gpio-key,wakeup; diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi index 748ba7aa746..4b0e0ca08f4 100644 --- a/arch/arm/boot/dts/dbx5x0.dtsi +++ b/arch/arm/boot/dts/dbx5x0.dtsi @@ -483,6 +483,8 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80004000 0x1000>; interrupts = <0 21 0x4>; + arm,primecell-periphid = <0x180024>; + #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -494,6 +496,8 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80122000 0x1000>; interrupts = <0 22 0x4>; + arm,primecell-periphid = <0x180024>; + #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -505,6 +509,8 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80128000 0x1000>; interrupts = <0 55 0x4>; + arm,primecell-periphid = <0x180024>; + #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -516,6 +522,8 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x80110000 0x1000>; interrupts = <0 12 0x4>; + arm,primecell-periphid = <0x180024>; + #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -527,6 +535,8 @@ compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell"; reg = <0x8012a000 0x1000>; interrupts = <0 51 0x4>; + arm,primecell-periphid = <0x180024>; + #address-cells = <1>; #size-cells = <0>; v-i2c-supply = <&db8500_vape_reg>; @@ -573,33 +583,38 @@ interrupts = <0 60 0x4>; status = "disabled"; }; + sdi@80118000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80118000 0x1000>; interrupts = <0 50 0x4>; status = "disabled"; }; + sdi@80005000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80005000 0x1000>; interrupts = <0 41 0x4>; status = "disabled"; }; + sdi@80119000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80119000 0x1000>; interrupts = <0 59 0x4>; status = "disabled"; }; + sdi@80114000 { compatible = "arm,pl18x", "arm,primecell"; reg = <0x80114000 0x1000>; interrupts = <0 99 0x4>; status = "disabled"; }; + sdi@80008000 { compatible = "arm,pl18x", "arm,primecell"; - reg = <0x80114000 0x1000>; + reg = <0x80008000 0x1000>; interrupts = <0 100 0x4>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi index 96fb824b5e6..5a00022383e 100644 --- a/arch/arm/boot/dts/dove.dtsi +++ b/arch/arm/boot/dts/dove.dtsi @@ -4,21 +4,32 @@ compatible = "marvell,dove"; model = "Marvell Armada 88AP510 SoC"; - interrupt-parent = <&intc>; - - intc: interrupt-controller { - compatible = "marvell,orion-intc"; - interrupt-controller; - #interrupt-cells = <1>; - reg = <0xf1020204 0x04>, - <0xf1020214 0x04>; - }; - - mbus@f1000000 { + soc@f1000000 { compatible = "simple-bus"; - ranges = <0 0xf1000000 0x4000000>; #address-cells = <1>; #size-cells = <1>; + interrupt-parent = <&intc>; + + ranges = <0xc8000000 0xc8000000 0x0100000 /* CESA SRAM 1M */ + 0xe0000000 0xe0000000 0x8000000 /* PCIe0 Mem 128M */ + 0xe8000000 0xe8000000 0x8000000 /* PCIe1 Mem 128M */ + 0xf0000000 0xf0000000 0x0100000 /* ScratchPad 1M */ + 0x00000000 0xf1000000 0x1000000 /* SB/NB regs 16M */ + 0xf2000000 0xf2000000 0x0100000 /* PCIe0 I/O 1M */ + 0xf2100000 0xf2100000 0x0100000 /* PCIe0 I/O 1M */ + 0xf8000000 0xf8000000 0x8000000>; /* BootROM 128M */ + + l2: l2-cache { + compatible = "marvell,tauros2-cache"; + marvell,tauros2-cache-features = <0>; + }; + + intc: interrupt-controller { + compatible = "marvell,orion-intc"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x20204 0x04>, <0x20214 0x04>; + }; uart0: serial@12000 { compatible = "ns16550a"; @@ -56,11 +67,6 @@ status = "disabled"; }; - wdt: wdt@20300 { - compatible = "marvell,orion-wdt"; - reg = <0x20300 0x28>; - }; - gpio0: gpio@d0400 { compatible = "marvell,orion-gpio"; #gpio-cells = <2>; @@ -139,5 +145,14 @@ nr-ports = <1>; status = "disabled"; }; + + crypto: crypto@30000 { + compatible = "marvell,orion-crypto"; + reg = <0x30000 0x10000>, + <0xc8000000 0x800>; + reg-names = "regs", "sram"; + interrupts = <31>; + status = "okay"; + }; }; }; diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index 73567b843e7..a21511c1407 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -20,8 +20,10 @@ compatible = "samsung,trats", "samsung,exynos4210"; memory { - reg = <0x40000000 0x20000000 - 0x60000000 0x20000000>; + reg = <0x40000000 0x10000000 + 0x50000000 0x10000000 + 0x60000000 0x10000000 + 0x70000000 0x10000000>; }; chosen { diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi index 9ca4ca70c1b..6d31aa38346 100644 --- a/arch/arm/boot/dts/imx23.dtsi +++ b/arch/arm/boot/dts/imx23.dtsi @@ -69,6 +69,7 @@ interrupts = <13>, <56>; interrupt-names = "gpmi-dma", "bch"; clocks = <&clks 34>; + clock-names = "gpmi_io"; fsl,gpmi-dma-channel = <4>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index e16d6315548..55c57ea6169 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -85,6 +85,7 @@ interrupts = <88>, <41>; interrupt-names = "gpmi-dma", "bch"; clocks = <&clks 50>; + clock-names = "gpmi_io"; fsl,gpmi-dma-channel = <4>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts index 15df4c105e8..5bfa02a3f85 100644 --- a/arch/arm/boot/dts/imx6q-arm2.dts +++ b/arch/arm/boot/dts/imx6q-arm2.dts @@ -37,6 +37,13 @@ pinctrl_hog: hoggrp { fsl,pins = < 176 0x80000000 /* MX6Q_PAD_EIM_D25__GPIO_3_25 */ + >; + }; + }; + + arm2 { + pinctrl_usdhc3_arm2: usdhc3grp-arm2 { + fsl,pins = < 1363 0x80000000 /* MX6Q_PAD_NANDF_CS0__GPIO_6_11 */ 1369 0x80000000 /* MX6Q_PAD_NANDF_CS1__GPIO_6_14 */ >; @@ -58,7 +65,8 @@ wp-gpios = <&gpio6 14 0>; vmmc-supply = <®_3p3v>; pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc3_1>; + pinctrl-0 = <&pinctrl_usdhc3_1 + &pinctrl_usdhc3_arm2>; status = "okay"; }; diff --git a/arch/arm/boot/dts/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/kirkwood-lsxl.dtsi index 8ac51c08269..8fea375c734 100644 --- a/arch/arm/boot/dts/kirkwood-lsxl.dtsi +++ b/arch/arm/boot/dts/kirkwood-lsxl.dtsi @@ -48,17 +48,19 @@ #size-cells = <0>; button@1 { label = "Function Button"; - linux,code = <132>; + linux,code = <357>; gpios = <&gpio1 9 1>; }; button@2 { label = "Power-on Switch"; - linux,code = <116>; + linux,code = <0>; + linux,input-type = <5>; gpios = <&gpio1 10 1>; }; button@3 { label = "Power-auto Switch"; - linux,code = <142>; + linux,code = <1>; + linux,input-type = <5>; gpios = <&gpio1 11 1>; }; }; @@ -67,28 +69,28 @@ compatible = "gpio-leds"; led@1 { - label = "lschlv2:blue:func"; + label = "lsxl:blue:func"; gpios = <&gpio1 4 1>; }; led@2 { - label = "lschlv2:red:alarm"; + label = "lsxl:red:alarm"; gpios = <&gpio1 5 1>; }; led@3 { - label = "lschlv2:amber:info"; + label = "lsxl:amber:info"; gpios = <&gpio1 6 1>; }; led@4 { - label = "lschlv2:blue:power"; + label = "lsxl:blue:power"; gpios = <&gpio1 7 1>; linux,default-trigger = "default-on"; }; led@5 { - label = "lschlv2:red:func"; + label = "lsxl:red:func"; gpios = <&gpio1 16 1>; }; }; diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index f38ea8771b4..696e929d030 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -257,7 +257,7 @@ interrupt-names = "common", "tx", "rx", "sidetone"; interrupt-parent = <&intc>; ti,buffer-size = <1280>; - ti,hwmods = "mcbsp2"; + ti,hwmods = "mcbsp2", "mcbsp2_sidetone"; }; mcbsp3: mcbsp@49024000 { @@ -272,7 +272,7 @@ interrupt-names = "common", "tx", "rx", "sidetone"; interrupt-parent = <&intc>; ti,buffer-size = <128>; - ti,hwmods = "mcbsp3"; + ti,hwmods = "mcbsp3", "mcbsp3_sidetone"; }; mcbsp4: mcbsp@49026000 { diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index b1497c7d7d6..df7f2270fc9 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -73,8 +73,8 @@ pinmux: pinmux { compatible = "nvidia,tegra30-pinmux"; - reg = <0x70000868 0xd0 /* Pad control registers */ - 0x70003000 0x3e0>; /* Mux registers */ + reg = <0x70000868 0xd4 /* Pad control registers */ + 0x70003000 0x3e4>; /* Mux registers */ }; serial@70006000 { diff --git a/arch/arm/boot/dts/wm8505.dtsi b/arch/arm/boot/dts/wm8505.dtsi index b459691655a..330f833ac3b 100644 --- a/arch/arm/boot/dts/wm8505.dtsi +++ b/arch/arm/boot/dts/wm8505.dtsi @@ -71,13 +71,13 @@ ehci@d8007100 { compatible = "via,vt8500-ehci"; reg = <0xd8007100 0x200>; - interrupts = <43>; + interrupts = <1>; }; uhci@d8007300 { compatible = "platform-uhci"; reg = <0xd8007300 0x200>; - interrupts = <43>; + interrupts = <0>; }; fb@d8050800 { diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 66aa7a6db88..394ded624e3 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -139,6 +139,7 @@ CONFIG_I2C_IMX=y CONFIG_SPI=y CONFIG_SPI_IMX=y CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_MC9S08DZ60=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y CONFIG_IMX2_WDT=y @@ -155,6 +156,7 @@ CONFIG_SOC_CAMERA=y CONFIG_SOC_CAMERA_OV2640=y CONFIG_VIDEO_MX3=y CONFIG_FB=y +CONFIG_LCD_PLATFORM=y CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_L4F00242T03=y diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 7bcf850eddc..3458752c4bb 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig @@ -1,6 +1,6 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y -CONFIG_NO_HZ=y +CONFIG_IRQ_DOMAIN_DEBUG=y CONFIG_HIGH_RES_TIMERS=y CONFIG_LOG_BUF_SHIFT=14 CONFIG_BLK_DEV_INITRD=y @@ -9,10 +9,12 @@ CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_ARCH_MVEBU=y -CONFIG_MACH_ARMADA_370_XP=y +CONFIG_MACH_ARMADA_370=y +CONFIG_MACH_ARMADA_XP=y +# CONFIG_CACHE_L2X0 is not set CONFIG_AEABI=y CONFIG_HIGHMEM=y -CONFIG_USE_OF=y +# CONFIG_COMPACTION is not set CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y @@ -23,6 +25,8 @@ CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_GPIOLIB=y CONFIG_GPIO_SYSFS=y +# CONFIG_USB_SUPPORT is not set +# CONFIG_IOMMU_SUPPORT is not set CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set diff --git a/arch/arm/configs/versatile_defconfig b/arch/arm/configs/versatile_defconfig index cdd4d2bd396..2ba9e63d0f1 100644 --- a/arch/arm/configs/versatile_defconfig +++ b/arch/arm/configs/versatile_defconfig @@ -1,3 +1,4 @@ +CONFIG_ARCH_VERSATILE=y CONFIG_EXPERIMENTAL=y # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y diff --git a/arch/arm/include/asm/flat.h b/arch/arm/include/asm/flat.h index 59426a4595c..e847d23351e 100644 --- a/arch/arm/include/asm/flat.h +++ b/arch/arm/include/asm/flat.h @@ -8,7 +8,7 @@ #define flat_argvp_envp_on_stack() 1 #define flat_old_ram_flag(flags) (flags) #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) -#define flat_get_addr_from_rp(rp, relval, flags, persistent) get_unaligned(rp) +#define flat_get_addr_from_rp(rp, relval, flags, persistent) ((void)persistent,get_unaligned(rp)) #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) #define flat_get_relocate_addr(rel) (rel) #define flat_set_persistent(relval, p) 0 diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 35c1ed89b93..42f042ee4ad 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -64,7 +64,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); static inline void __raw_writew(u16 val, volatile void __iomem *addr) { asm volatile("strh %1, %0" - : "+Qo" (*(volatile u16 __force *)addr) + : "+Q" (*(volatile u16 __force *)addr) : "r" (val)); } @@ -72,7 +72,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr) { u16 val; asm volatile("ldrh %1, %0" - : "+Qo" (*(volatile u16 __force *)addr), + : "+Q" (*(volatile u16 __force *)addr), "=r" (val)); return val; } diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index 05b8e82ec9f..e3f75726343 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h @@ -10,7 +10,5 @@ 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/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 77bd79f2ffd..7e1f76027f6 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -200,8 +200,8 @@ extern int __put_user_8(void *, unsigned long long); #define USER_DS KERNEL_DS #define segment_eq(a,b) (1) -#define __addr_ok(addr) (1) -#define __range_ok(addr,size) (0) +#define __addr_ok(addr) ((void)(addr),1) +#define __range_ok(addr,size) ((void)(addr),0) #define get_fs() (KERNEL_DS) static inline void set_fs(mm_segment_t fs) diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index 6a6f1e485f4..301c1db3e99 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h @@ -27,9 +27,9 @@ #if __LINUX_ARM_ARCH__ <= 6 ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] - tst \tmp, #HWCAP_VFPv3D16 - ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} - addne \base, \base, #32*4 @ step over unused register space + tst \tmp, #HWCAP_VFPD32 + ldcnel p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} + addeq \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field @@ -51,9 +51,9 @@ #if __LINUX_ARM_ARCH__ <= 6 ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] - tst \tmp, #HWCAP_VFPv3D16 - stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} - addne \base, \base, #32*4 @ step over unused register space + tst \tmp, #HWCAP_VFPD32 + stcnel p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} + addeq \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h index ae05e56dd17..5000397134b 100644 --- a/arch/arm/include/asm/xen/interface.h +++ b/arch/arm/include/asm/xen/interface.h @@ -29,16 +29,22 @@ #ifndef __ASSEMBLY__ /* Explicitly size integers that represent pfns in the interface with - * Xen so that we can have one ABI that works for 32 and 64 bit guests. */ + * Xen so that we can have one ABI that works for 32 and 64 bit guests. + * Note that this means that the xen_pfn_t type may be capable of + * representing pfn's which the guest cannot represent in its own pfn + * type. However since pfn space is controlled by the guest this is + * fine since it simply wouldn't be able to create any sure pfns in + * the first place. + */ typedef uint64_t xen_pfn_t; +#define PRI_xen_pfn "llx" typedef uint64_t xen_ulong_t; +#define PRI_xen_ulong "llx" /* Guest handles for primitive C types. */ __DEFINE_GUEST_HANDLE(uchar, unsigned char); __DEFINE_GUEST_HANDLE(uint, unsigned int); -__DEFINE_GUEST_HANDLE(ulong, unsigned long); DEFINE_GUEST_HANDLE(char); DEFINE_GUEST_HANDLE(int); -DEFINE_GUEST_HANDLE(long); DEFINE_GUEST_HANDLE(void); DEFINE_GUEST_HANDLE(uint64_t); DEFINE_GUEST_HANDLE(uint32_t); diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h index 174202318df..c6b9096cef9 100644 --- a/arch/arm/include/asm/xen/page.h +++ b/arch/arm/include/asm/xen/page.h @@ -10,7 +10,7 @@ #include <xen/interface/grant_table.h> #define pfn_to_mfn(pfn) (pfn) -#define phys_to_machine_mapping_valid (1) +#define phys_to_machine_mapping_valid(pfn) (1) #define mfn_to_pfn(mfn) (mfn) #define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) @@ -30,6 +30,8 @@ typedef struct xpaddr { #define XMADDR(x) ((xmaddr_t) { .maddr = (x) }) #define XPADDR(x) ((xpaddr_t) { .paddr = (x) }) +#define INVALID_P2M_ENTRY (~0UL) + static inline xmaddr_t phys_to_machine(xpaddr_t phys) { unsigned offset = phys.paddr & ~PAGE_MASK; @@ -74,9 +76,14 @@ static inline int m2p_remove_override(struct page *page, bool clear_pte) return 0; } +static inline bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) +{ + BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); + return true; +} + static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) { - BUG(); - return false; + return __set_phys_to_machine(pfn, mfn); } #endif /* _ASM_ARM_XEN_PAGE_H */ diff --git a/arch/arm/include/debug/8250_32.S b/arch/arm/include/debug/8250_32.S new file mode 100644 index 00000000000..8db01eeabbb --- /dev/null +++ b/arch/arm/include/debug/8250_32.S @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2011 Picochip Ltd., Jamie Iles + * + * 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. + * + * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit + * accesses to the 8250. + */ + +#include <linux/serial_reg.h> + + .macro senduart,rd,rx + str \rd, [\rx, #UART_TX << UART_SHIFT] + .endm + + .macro busyuart,rd,rx +1002: ldr \rd, [\rx, #UART_LSR << UART_SHIFT] + and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE + teq \rd, #UART_LSR_TEMT | UART_LSR_THRE + bne 1002b + .endm + + /* The UART's don't have any flow control IO's wired up. */ + .macro waituart,rd,rx + .endm diff --git a/arch/arm/include/debug/picoxcell.S b/arch/arm/include/debug/picoxcell.S index 7419deb1b94..bc1f07c49cd 100644 --- a/arch/arm/include/debug/picoxcell.S +++ b/arch/arm/include/debug/picoxcell.S @@ -5,10 +5,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit - * accesses to the 8250. */ -#include <linux/serial_reg.h> #define UART_SHIFT 2 #define PICOXCELL_UART1_BASE 0x80230000 @@ -19,17 +16,4 @@ ldr \rp, =PICOXCELL_UART1_BASE .endm - .macro senduart,rd,rx - str \rd, [\rx, #UART_TX << UART_SHIFT] - .endm - - .macro busyuart,rd,rx -1002: ldr \rd, [\rx, #UART_LSR << UART_SHIFT] - and \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE - teq \rd, #UART_LSR_TEMT | UART_LSR_THRE - bne 1002b - .endm - - /* The UART's don't have any flow control IO's wired up. */ - .macro waituart,rd,rx - .endm +#include "8250_32.S" diff --git a/arch/arm/include/debug/socfpga.S b/arch/arm/include/debug/socfpga.S index d6f26d23374..966b2f99494 100644 --- a/arch/arm/include/debug/socfpga.S +++ b/arch/arm/include/debug/socfpga.S @@ -7,6 +7,9 @@ * published by the Free Software Foundation. */ +#define UART_SHIFT 2 +#define DEBUG_LL_UART_OFFSET 0x00002000 + .macro addruart, rp, rv, tmp mov \rp, #DEBUG_LL_UART_OFFSET orr \rp, \rp, #0x00c00000 @@ -14,3 +17,5 @@ orr \rp, \rp, #0xff000000 @ physical base .endm +#include "8250_32.S" + diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h index f254f6503cc..3688fd15a32 100644 --- a/arch/arm/include/uapi/asm/hwcap.h +++ b/arch/arm/include/uapi/asm/hwcap.h @@ -18,11 +18,12 @@ #define HWCAP_THUMBEE (1 << 11) #define HWCAP_NEON (1 << 12) #define HWCAP_VFPv3 (1 << 13) -#define HWCAP_VFPv3D16 (1 << 14) +#define HWCAP_VFPv3D16 (1 << 14) /* also set for VFPv4-D16 */ #define HWCAP_TLS (1 << 15) #define HWCAP_VFPv4 (1 << 16) #define HWCAP_IDIVA (1 << 17) #define HWCAP_IDIVT (1 << 18) +#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */ #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 417bac1846b..34711757ba5 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -88,9 +88,9 @@ ENTRY(ret_from_fork) bl schedule_tail cmp r5, #0 movne r0, r4 - movne lr, pc + adrne lr, BSYM(1f) movne pc, r5 - get_thread_info tsk +1: get_thread_info tsk b ret_slow_syscall ENDPROC(ret_from_fork) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 16cedb42c0c..896165096d6 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -34,6 +34,7 @@ #include <linux/list.h> #include <linux/kallsyms.h> #include <linux/proc_fs.h> +#include <linux/export.h> #include <asm/exception.h> #include <asm/mach/arch.h> @@ -109,6 +110,7 @@ void set_irq_flags(unsigned int irq, unsigned int iflags) /* Order is clear bits in "clr" then set bits in "set" */ irq_modify_status(irq, clr, set & ~clr); } +EXPORT_SYMBOL_GPL(set_irq_flags); void __init init_IRQ(void) { diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c index 38c1a3b103a..83931290506 100644 --- a/arch/arm/kernel/kprobes-test-arm.c +++ b/arch/arm/kernel/kprobes-test-arm.c @@ -366,7 +366,9 @@ void kprobe_arm_test_cases(void) TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3") TEST_UNSUPPORTED(".word 0xe0500090 @ undef") TEST_UNSUPPORTED(".word 0xe05fff9f @ undef") +#endif +#if __LINUX_ARM_ARCH__ >= 7 TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") TEST_RRR( "mlshi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") TEST_RR( "mls lr, r",1, VAL2,", r",2, VAL3,", r13") @@ -456,6 +458,8 @@ void kprobe_arm_test_cases(void) TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */ #if __LINUX_ARM_ARCH__ >= 6 TEST_UNSUPPORTED("ldrex r2, [sp]") +#endif +#if (__LINUX_ARM_ARCH__ >= 7) || defined(CONFIG_CPU_32v6K) TEST_UNSUPPORTED("strexd r0, r2, r3, [sp]") TEST_UNSUPPORTED("ldrexd r2, r3, [sp]") TEST_UNSUPPORTED("strexb r0, r2, [sp]") diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index e29c3337ca8..8ef8c933780 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -45,10 +45,9 @@ int machine_kexec_prepare(struct kimage *image) for (i = 0; i < image->nr_segments; i++) { current_segment = &image->segment[i]; - err = memblock_is_region_memory(current_segment->mem, - current_segment->memsz); - if (err) - return - EINVAL; + if (!memblock_is_region_memory(current_segment->mem, + current_segment->memsz)) + return -EINVAL; err = get_user(header, (__be32*)current_segment->buf); if (err) diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 93971b1a4f0..53c0304b734 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -96,6 +96,10 @@ armpmu_event_set_period(struct perf_event *event, s64 period = hwc->sample_period; int ret = 0; + /* The period may have been changed by PERF_EVENT_IOC_PERIOD */ + if (unlikely(period != hwc->last_period)) + left = period - (hwc->last_period - left); + if (unlikely(left <= -period)) { left = period; local64_set(&hwc->period_left, left); diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index e21bac20d90..fc6692e2b60 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c @@ -107,13 +107,6 @@ 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; @@ -189,18 +182,15 @@ 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; + 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; - } + cd.epoch_cyc = read_sched_clock(); + cd.epoch_cyc_copy = cd.epoch_cyc; + cd.suspended = false; } static struct syscore_ops sched_clock_ops = { diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8e20754dd31..fbc8b2623d8 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -294,18 +294,24 @@ static void percpu_timer_setup(void); asmlinkage void __cpuinit secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; - unsigned int cpu = smp_processor_id(); + unsigned int cpu; + + /* + * The identity mapping is uncached (strongly ordered), so + * switch away from it before attempting any exclusive accesses. + */ + cpu_switch_mm(mm->pgd, mm); + enter_lazy_tlb(mm, current); + local_flush_tlb_all(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ + cpu = smp_processor_id(); atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); - cpu_switch_mm(mm->pgd, mm); - enter_lazy_tlb(mm, current); - local_flush_tlb_all(); printk("CPU%u: Booted secondary processor\n", cpu); diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index e1f906989bb..b22d700fea2 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -42,10 +42,10 @@ static void twd_set_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - /* timer load already set up */ ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_PERIODIC; - __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD); + __raw_writel(DIV_ROUND_CLOSEST(twd_timer_rate, HZ), + twd_base + TWD_TIMER_LOAD); break; case CLOCK_EVT_MODE_ONESHOT: /* period set, and timer enabled in 'next_event' hook */ diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c index 9d0a30032d7..0dc53854a5d 100644 --- a/arch/arm/lib/delay.c +++ b/arch/arm/lib/delay.c @@ -45,6 +45,7 @@ int read_current_timer(unsigned long *timer_val) *timer_val = delay_timer->read_current_timer(); return 0; } +EXPORT_SYMBOL_GPL(read_current_timer); static void __timer_delay(unsigned long cycles) { diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index b1420710193..043624219b5 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -21,19 +21,13 @@ config SOC_AT91SAM9 bool select CPU_ARM926T select GENERIC_CLOCKEVENTS + select MULTI_IRQ_HANDLER + select SPARSE_IRQ menu "Atmel AT91 System-on-Chip" comment "Atmel AT91 Processor" -config SOC_AT91SAM9 - bool - select AT91_SAM9_SMC - select AT91_SAM9_TIME - select CPU_ARM926T - select MULTI_IRQ_HANDLER - select SPARSE_IRQ - config SOC_AT91RM9200 bool "AT91RM9200" select CPU_ARM920T diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index b4f0565aff6..5269825194a 100644 --- a/arch/arm/mach-at91/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c @@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index a563189cdfc..3cee0e6ea7c 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -68,7 +68,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) /* Enable overcurrent notification */ for (i = 0; i < data->ports; i++) { - if (data->overcurrent_pin[i]) + if (gpio_is_valid(data->overcurrent_pin[i])) at91_set_gpio_input(data->overcurrent_pin[i], 1); } @@ -479,7 +479,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91rm9200_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; @@ -512,7 +512,7 @@ static struct resource twi_resources[] = { static struct platform_device at91rm9200_twi_device = { .name = "i2c-at91rm9200", - .id = -1, + .id = 0, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index ad29f93f20c..f8202615f4a 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c @@ -211,8 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk), CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk), /* more usart lookup table for DT entries */ CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck), CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk), diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index a76b8684f52..414bd855fb0 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) /* Enable overcurrent notification */ for (i = 0; i < data->ports; i++) { - if (data->overcurrent_pin[i]) + if (gpio_is_valid(data->overcurrent_pin[i])) at91_set_gpio_input(data->overcurrent_pin[i], 1); } @@ -389,7 +389,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9260_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; @@ -421,7 +421,7 @@ static struct resource twi_resources[] = { }; static struct platform_device at91sam9260_twi_device = { - .id = -1, + .id = 0, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 8d999eb1a13..04295c04b3e 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c @@ -178,8 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk), CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk), CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk), CLKDEV_CON_ID("pioA", &pioA_clk), CLKDEV_CON_ID("pioB", &pioB_clk), CLKDEV_CON_ID("pioC", &pioC_clk), diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 9752f17efba..cd604aad8e9 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) /* Enable overcurrent notification */ for (i = 0; i < data->ports; i++) { - if (data->overcurrent_pin[i]) + if (gpio_is_valid(data->overcurrent_pin[i])) at91_set_gpio_input(data->overcurrent_pin[i], 1); } @@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9261_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; @@ -317,7 +317,7 @@ static struct resource twi_resources[] = { }; static struct platform_device at91sam9261_twi_device = { - .id = -1, + .id = 0, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 6a01d0360df..d6f9c23927c 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c @@ -193,7 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = { CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk), CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk), CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk), - CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk), + CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk), /* fake hclk clock */ CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk), CLKDEV_CON_ID("pioA", &pioA_clk), diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index 8dde220b42b..9c61e59a210 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -78,7 +78,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) /* Enable overcurrent notification */ for (i = 0; i < data->ports; i++) { - if (data->overcurrent_pin[i]) + if (gpio_is_valid(data->overcurrent_pin[i])) at91_set_gpio_input(data->overcurrent_pin[i], 1); } @@ -567,7 +567,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9263_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; @@ -600,7 +600,7 @@ static struct resource twi_resources[] = { static struct platform_device at91sam9263_twi_device = { .name = "i2c-at91sam9260", - .id = -1, + .id = 0, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index b1596072dcc..fcd233cb33d 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -1841,8 +1841,8 @@ static struct resource sha_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = AT91SAM9G45_ID_AESTDESSHA, - .end = AT91SAM9G45_ID_AESTDESSHA, + .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, + .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, .flags = IORESOURCE_IRQ, }, }; @@ -1874,8 +1874,8 @@ static struct resource tdes_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = AT91SAM9G45_ID_AESTDESSHA, - .end = AT91SAM9G45_ID_AESTDESSHA, + .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, + .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, .flags = IORESOURCE_IRQ, }, }; @@ -1910,8 +1910,8 @@ static struct resource aes_resources[] = { .flags = IORESOURCE_MEM, }, [1] = { - .start = AT91SAM9G45_ID_AESTDESSHA, - .end = AT91SAM9G45_ID_AESTDESSHA, + .start = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, + .end = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA, .flags = IORESOURCE_IRQ, }, }; diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index d6ca0543ce8..5047bdc92ad 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9rl_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; @@ -347,7 +347,7 @@ static struct resource twi_resources[] = { static struct platform_device at91sam9rl_twi_device = { .name = "i2c-at91sam9g20", - .id = -1, + .id = 0, .resource = twi_resources, .num_resources = ARRAY_SIZE(twi_resources), }; diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c index 6bd7300a2bc..bb7f54474b9 100644 --- a/arch/arm/mach-at91/at91x40.c +++ b/arch/arm/mach-at91/at91x40.c @@ -88,6 +88,6 @@ void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS]) if (!priority) priority = at91x40_default_irq_priority; - at91_aic_init(priority); + at91_aic_init(priority, at91_extern_irq); } diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c index 9cda3fd346a..6960778af4c 100644 --- a/arch/arm/mach-at91/board-neocore926.c +++ b/arch/arm/mach-at91/board-neocore926.c @@ -129,7 +129,7 @@ static struct spi_board_info neocore926_spi_devices[] = { .max_speed_hz = 125000 * 16, .bus_num = 0, .platform_data = &ads_info, - .irq = AT91SAM9263_ID_IRQ1, + .irq = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1, }, #endif }; diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 27b3af1a304..a9167dd45f9 100644 --- a/arch/arm/mach-at91/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c @@ -309,7 +309,7 @@ static struct spi_board_info ek_spi_devices[] = { .max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */ .bus_num = 0, .platform_data = &ads_info, - .irq = AT91SAM9261_ID_IRQ0, + .irq = NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0, .controller_data = (void *) AT91_PIN_PA28, /* CS pin */ }, #endif diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c index 073e17403d9..b87dbe2be0d 100644 --- a/arch/arm/mach-at91/board-sam9263ek.c +++ b/arch/arm/mach-at91/board-sam9263ek.c @@ -132,7 +132,7 @@ static struct spi_board_info ek_spi_devices[] = { .max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */ .bus_num = 0, .platform_data = &ads_info, - .irq = AT91SAM9263_ID_IRQ1, + .irq = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1, }, #endif }; diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index f4965067765..b62f560e6c7 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h @@ -26,7 +26,8 @@ extern void __init at91_dt_initialize(void); extern void __init at91_init_irq_default(void); extern void __init at91_init_interrupts(unsigned int priority[]); extern void __init at91x40_init_interrupts(unsigned int priority[]); -extern void __init at91_aic_init(unsigned int priority[]); +extern void __init at91_aic_init(unsigned int priority[], + unsigned int ext_irq_mask); extern int __init at91_aic_of_init(struct device_node *node, struct device_node *parent); extern int __init at91_aic5_of_init(struct device_node *node, diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c index 1e02c0e49dc..febc2ee901a 100644 --- a/arch/arm/mach-at91/irq.c +++ b/arch/arm/mach-at91/irq.c @@ -502,14 +502,19 @@ int __init at91_aic5_of_init(struct device_node *node, /* * Initialize the AIC interrupt controller. */ -void __init at91_aic_init(unsigned int *priority) +void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask) { unsigned int i; int irq_base; - if (at91_aic_pm_init()) + at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs) + * sizeof(*at91_extern_irq), GFP_KERNEL); + + if (at91_aic_pm_init() || at91_extern_irq == NULL) panic("Unable to allocate bit maps\n"); + *at91_extern_irq = ext_irq_mask; + at91_aic_base = ioremap(AT91_AIC, 512); if (!at91_aic_base) panic("Unable to ioremap AIC registers\n"); diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index da9881b161e..0b32c81730a 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -47,7 +47,7 @@ void __init at91_init_irq_default(void) void __init at91_init_interrupts(unsigned int *priority) { /* Initialize the AIC interrupt controller */ - at91_aic_init(priority); + at91_aic_init(priority, at91_extern_irq); /* Enable GPIO interrupts */ at91_gpio_irq_setup(); @@ -151,7 +151,7 @@ static void __init soc_detect(u32 dbgu_base) } /* at91sam9g10 */ - if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { + if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { at91_soc_initdata.type = AT91_SOC_SAM9G10; at91_boot_soc = at91sam9261_soc; } diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index cd0c8b1e1ec..14e9947bad6 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -713,8 +713,7 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type, break; case VPBE_ENC_CUSTOM_TIMINGS: if (pclock <= 27000000) { - v |= DM644X_VPSS_MUXSEL_PLL2_MODE | - DM644X_VPSS_DACCLKEN; + v |= DM644X_VPSS_DACCLKEN; writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL)); } else { /* diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c index b37bef1d5ff..f723fe13d0f 100644 --- a/arch/arm/mach-dove/common.c +++ b/arch/arm/mach-dove/common.c @@ -32,6 +32,7 @@ #include <linux/irq.h> #include <plat/time.h> #include <linux/platform_data/usb-ehci-orion.h> +#include <plat/irq.h> #include <plat/common.h> #include <plat/addr-map.h> #include "common.h" @@ -109,8 +110,8 @@ static void __init dove_clk_init(void) orion_clkdev_add(NULL, "orion-ehci.0", usb0); orion_clkdev_add(NULL, "orion-ehci.1", usb1); - orion_clkdev_add(NULL, "mv643xx_eth.0", ge); - orion_clkdev_add("0", "sata_mv.0", sata); + orion_clkdev_add(NULL, "mv643xx_eth_port.0", ge); + orion_clkdev_add(NULL, "sata_mv.0", sata); orion_clkdev_add("0", "pcie", pex0); orion_clkdev_add("1", "pcie", pex1); orion_clkdev_add(NULL, "sdhci-dove.0", sdio0); @@ -399,7 +400,7 @@ static void __init dove_dt_init(void) (dove_tclk + 499999) / 1000000); #ifdef CONFIG_CACHE_TAUROS2 - tauros2_init(); + tauros2_init(0); #endif dove_setup_cpu_mbus(); @@ -415,7 +416,6 @@ static void __init dove_dt_init(void) dove_ehci0_init(); dove_ehci1_init(); dove_pcie_init(1, 1); - dove_crypto_init(); of_platform_populate(NULL, of_default_bus_match_table, dove_auxdata_lookup, NULL); diff --git a/arch/arm/mach-dove/pcie.c b/arch/arm/mach-dove/pcie.c index bb15b26041c..0ef4435b165 100644 --- a/arch/arm/mach-dove/pcie.c +++ b/arch/arm/mach-dove/pcie.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/clk.h> #include <video/vga.h> #include <asm/mach/pci.h> #include <asm/mach/arch.h> @@ -188,6 +189,10 @@ static void __init add_pcie_port(int index, void __iomem *base) if (orion_pcie_link_up(base)) { struct pcie_port *pp = &pcie_port[num_pcie_ports++]; + struct clk *clk = clk_get_sys("pcie", (index ? "1" : "0")); + + if (!IS_ERR(clk)) + clk_prepare_enable(clk); printk(KERN_INFO "link up\n"); diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 715b690e500..1947be8e5f5 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -47,6 +47,7 @@ #include <plat/fimc-core.h> #include <plat/iic-core.h> #include <plat/tv-core.h> +#include <plat/spi-core.h> #include <plat/regs-serial.h> #include "common.h" @@ -346,6 +347,8 @@ static void __init exynos4_map_io(void) s5p_fb_setname(0, "exynos4-fb"); s5p_hdmi_setname("exynos4-hdmi"); + + s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos5_map_io(void) @@ -366,6 +369,8 @@ static void __init exynos5_map_io(void) s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); s3c_i2c2_setname("s3c2440-i2c"); + + s3c64xx_spi_setname("exynos4210-spi"); } static void __init exynos4_init_clocks(int xtal) diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c index 21d568b3b14..87e07d6fc61 100644 --- a/arch/arm/mach-exynos/dma.c +++ b/arch/arm/mach-exynos/dma.c @@ -275,6 +275,9 @@ static int __init exynos_dma_init(void) exynos_pdma1_pdata.nr_valid_peri = ARRAY_SIZE(exynos4210_pdma1_peri); exynos_pdma1_pdata.peri_id = exynos4210_pdma1_peri; + + if (samsung_rev() == EXYNOS4210_REV_0) + exynos_mdma1_device.res.start = EXYNOS4_PA_S_MDMA1; } else if (soc_is_exynos4212() || soc_is_exynos4412()) { exynos_pdma0_pdata.nr_valid_peri = ARRAY_SIZE(exynos4212_pdma0_peri); diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 8480849affb..ed4da4544cd 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -90,6 +90,7 @@ #define EXYNOS4_PA_MDMA0 0x10810000 #define EXYNOS4_PA_MDMA1 0x12850000 +#define EXYNOS4_PA_S_MDMA1 0x12840000 #define EXYNOS4_PA_PDMA0 0x12680000 #define EXYNOS4_PA_PDMA1 0x12690000 #define EXYNOS5_PA_MDMA0 0x10800000 diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index e58d786faf7..eadf4b59e7d 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -99,6 +99,7 @@ static char const *exynos4_dt_compat[] __initdata = { DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)") /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */ + .smp = smp_ops(exynos_smp_ops), .init_irq = exynos4_init_irq, .map_io = exynos4_dt_map_io, .handle_irq = gic_handle_irq, diff --git a/arch/arm/mach-highbank/system.c b/arch/arm/mach-highbank/system.c index 82c27230d4a..86e37cd9376 100644 --- a/arch/arm/mach-highbank/system.c +++ b/arch/arm/mach-highbank/system.c @@ -28,6 +28,7 @@ void highbank_restart(char mode, const char *cmd) hignbank_set_pwr_soft_reset(); scu_power_mode(scu_base_addr, SCU_PM_POWEROFF); - cpu_do_idle(); + while (1) + cpu_do_idle(); } diff --git a/arch/arm/mach-imx/clk-busy.c b/arch/arm/mach-imx/clk-busy.c index 1a7a8dd045a..1ab91b5209e 100644 --- a/arch/arm/mach-imx/clk-busy.c +++ b/arch/arm/mach-imx/clk-busy.c @@ -108,7 +108,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name, busy->div.hw.init = &init; clk = clk_register(NULL, &busy->div.hw); - if (!clk) + if (IS_ERR(clk)) kfree(busy); return clk; diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c index 3c1b8ff9a0a..cc49c7ae186 100644 --- a/arch/arm/mach-imx/clk-gate2.c +++ b/arch/arm/mach-imx/clk-gate2.c @@ -112,7 +112,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name, clk = clk_register(dev, &gate->hw); if (IS_ERR(clk)) - kfree(clk); + kfree(gate); return clk; } diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c index d20d4795f4e..01e2f843bf2 100644 --- a/arch/arm/mach-imx/clk-imx25.c +++ b/arch/arm/mach-imx/clk-imx25.c @@ -127,8 +127,8 @@ int __init mx25_clocks_init(void) clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0), 4); clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0), 5); clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0), 6); - clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per8", ccm(CCM_CGCR0), 7); - clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "ipg_per", ccm(CCM_CGCR0), 8); + clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0), 7); + clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0), 8); clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13); clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14); clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15); diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c index 3b6b640eed2..366e5d59d88 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/arch/arm/mach-imx/clk-imx27.c @@ -109,7 +109,7 @@ int __init mx27_clocks_init(unsigned long fref) clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6); clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6); clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks)); - clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 3); + clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6); clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3); clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks)); clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); @@ -121,7 +121,7 @@ int __init mx27_clocks_init(unsigned long fref) clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks)); clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks)); clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6); - clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 3); + clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6); clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0); clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0); clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1); diff --git a/arch/arm/mach-imx/ehci-imx25.c b/arch/arm/mach-imx/ehci-imx25.c index 412c583a24b..576af744695 100644 --- a/arch/arm/mach-imx/ehci-imx25.c +++ b/arch/arm/mach-imx/ehci-imx25.c @@ -30,7 +30,7 @@ #define MX25_H1_SIC_SHIFT 21 #define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT) #define MX25_H1_PP_BIT (1 << 18) -#define MX25_H1_PM_BIT (1 << 8) +#define MX25_H1_PM_BIT (1 << 16) #define MX25_H1_IPPUE_UP_BIT (1 << 7) #define MX25_H1_IPPUE_DOWN_BIT (1 << 6) #define MX25_H1_TLL_BIT (1 << 5) diff --git a/arch/arm/mach-imx/ehci-imx35.c b/arch/arm/mach-imx/ehci-imx35.c index 779e16eb65c..293397852e4 100644 --- a/arch/arm/mach-imx/ehci-imx35.c +++ b/arch/arm/mach-imx/ehci-imx35.c @@ -30,7 +30,7 @@ #define MX35_H1_SIC_SHIFT 21 #define MX35_H1_SIC_MASK (0x3 << MX35_H1_SIC_SHIFT) #define MX35_H1_PP_BIT (1 << 18) -#define MX35_H1_PM_BIT (1 << 8) +#define MX35_H1_PM_BIT (1 << 16) #define MX35_H1_IPPUE_UP_BIT (1 << 7) #define MX35_H1_IPPUE_DOWN_BIT (1 << 6) #define MX35_H1_TLL_BIT (1 << 5) diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c index 9d2c843bde0..b5deb055455 100644 --- a/arch/arm/mach-imx/mm-imx3.c +++ b/arch/arm/mach-imx/mm-imx3.c @@ -108,9 +108,8 @@ void __init imx3_init_l2x0(void) } l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096); - if (IS_ERR(l2x0_base)) { - printk(KERN_ERR "remapping L2 cache area failed with %ld\n", - PTR_ERR(l2x0_base)); + if (!l2x0_base) { + printk(KERN_ERR "remapping L2 cache area failed\n"); return; } diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c index 70c5a288240..d94872fed8c 100644 --- a/arch/arm/mach-kirkwood/board-dt.c +++ b/arch/arm/mach-kirkwood/board-dt.c @@ -51,9 +51,7 @@ static void __init kirkwood_dt_init(void) kirkwood_setup_cpu_mbus(); -#ifdef CONFIG_CACHE_FEROCEON_L2 kirkwood_l2_init(); -#endif /* Setup root of clk tree */ kirkwood_clk_init(); diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index 3991077f58a..2c6c218fb79 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -633,6 +633,7 @@ char * __init kirkwood_id(void) void __init kirkwood_l2_init(void) { +#ifdef CONFIG_CACHE_FEROCEON_L2 #ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH writel(readl(L2_CONFIG_REG) | L2_WRITETHROUGH, L2_CONFIG_REG); feroceon_l2_init(1); @@ -640,6 +641,7 @@ void __init kirkwood_l2_init(void) writel(readl(L2_CONFIG_REG) & ~L2_WRITETHROUGH, L2_CONFIG_REG); feroceon_l2_init(0); #endif +#endif } void __init kirkwood_init(void) @@ -657,9 +659,7 @@ void __init kirkwood_init(void) kirkwood_setup_cpu_mbus(); -#ifdef CONFIG_CACHE_FEROCEON_L2 kirkwood_l2_init(); -#endif /* Setup root of clk tree */ kirkwood_clk_init(); diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 9518bf5996d..e255164ff08 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -444,16 +444,28 @@ static struct omap1_cam_platform_data ams_delta_camera_platform_data = { .lclk_khz_max = 1334, /* results in 5fps CIF, 10fps QCIF */ }; +static struct platform_device ams_delta_audio_device = { + .name = "ams-delta-audio", + .id = -1, +}; + +static struct platform_device cx20442_codec_device = { + .name = "cx20442-codec", + .id = -1, +}; + static struct platform_device *ams_delta_devices[] __initdata = { &latch1_gpio_device, &latch2_gpio_device, &ams_delta_kp_device, &ams_delta_camera_device, + &ams_delta_audio_device, }; static struct platform_device *late_devices[] __initdata = { &ams_delta_nand_device, &ams_delta_lcd_device, + &cx20442_codec_device, }; static void __init ams_delta_init(void) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 2a1a898c7f9..d669e227e00 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -11,7 +11,6 @@ config ARCH_OMAP2PLUS_TYPICAL select I2C_OMAP select MENELAUS if ARCH_OMAP2 select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5 - select PINCTRL select PM_RUNTIME select REGULATOR select SERIAL_OMAP diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index 48d5e41dfbf..37859069444 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -580,6 +580,11 @@ static void __init igep_wlan_bt_init(void) } else return; + /* Make sure that the GPIO pins are muxed correctly */ + omap_mux_init_gpio(igep_wlan_bt_gpios[0].gpio, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(igep_wlan_bt_gpios[1].gpio, OMAP_PIN_OUTPUT); + omap_mux_init_gpio(igep_wlan_bt_gpios[2].gpio, OMAP_PIN_OUTPUT); + err = gpio_request_array(igep_wlan_bt_gpios, ARRAY_SIZE(igep_wlan_bt_gpios)); if (err) { diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 388c431c745..d41ab98890f 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -24,6 +24,7 @@ #include <linux/input.h> #include <linux/gpio_keys.h> #include <linux/opp.h> +#include <linux/cpu.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> @@ -444,27 +445,31 @@ static struct omap_board_mux board_mux[] __initdata = { }; #endif -static void __init beagle_opp_init(void) +static int __init beagle_opp_init(void) { int r = 0; - /* Initialize the omap3 opp table */ - if (omap3_opp_init()) { + if (!machine_is_omap3_beagle()) + return 0; + + /* Initialize the omap3 opp table if not already created. */ + r = omap3_opp_init(); + if (IS_ERR_VALUE(r) && (r != -EEXIST)) { pr_err("%s: opp default init failed\n", __func__); - return; + return r; } /* Custom OPP enabled for all xM versions */ if (cpu_is_omap3630()) { struct device *mpu_dev, *iva_dev; - mpu_dev = omap_device_get_by_hwmod_name("mpu"); + mpu_dev = get_cpu_device(0); iva_dev = omap_device_get_by_hwmod_name("iva"); if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) { pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n", __func__, mpu_dev, iva_dev); - return; + return -ENODEV; } /* Enable MPU 1GHz and lower opps */ r = opp_enable(mpu_dev, 800000000); @@ -484,8 +489,9 @@ static void __init beagle_opp_init(void) opp_disable(iva_dev, 660000000); } } - return; + return 0; } +device_initcall(beagle_opp_init); static void __init omap3_beagle_init(void) { @@ -522,8 +528,6 @@ static void __init omap3_beagle_init(void) /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); - - beagle_opp_init(); } MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c index 114ab4b8e0e..1a45d6bd253 100644 --- a/arch/arm/mach-omap2/clock33xx_data.c +++ b/arch/arm/mach-omap2/clock33xx_data.c @@ -1073,6 +1073,8 @@ static struct omap_clk am33xx_clks[] = { CLK(NULL, "gfx_fck_div_ck", &gfx_fck_div_ck, CK_AM33XX), CLK(NULL, "sysclkout_pre_ck", &sysclkout_pre_ck, CK_AM33XX), CLK(NULL, "clkout2_ck", &clkout2_ck, CK_AM33XX), + CLK(NULL, "timer_32k_ck", &clkdiv32k_ick, CK_AM33XX), + CLK(NULL, "timer_sys_ck", &sys_clkin_ck, CK_AM33XX), }; int __init am33xx_clk_init(void) diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index d661d138f27..6efc30c961a 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3294,7 +3294,7 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "auxclk5_src_ck", &auxclk5_src_ck, CK_443X), CLK(NULL, "auxclk5_ck", &auxclk5_ck, CK_443X), CLK(NULL, "auxclkreq5_ck", &auxclkreq5_ck, CK_443X), - CLK(NULL, "gpmc_ck", &dummy_ck, CK_443X), + CLK("omap-gpmc", "fck", &dummy_ck, CK_443X), CLK("omap_i2c.1", "ick", &dummy_ck, CK_443X), CLK("omap_i2c.2", "ick", &dummy_ck, CK_443X), CLK("omap_i2c.3", "ick", &dummy_ck, CK_443X), diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index cbb879139c5..512e79a842c 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -925,15 +925,18 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm) if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable) return -EINVAL; + spin_lock_irqsave(&clkdm->lock, flags); + /* * For arch's with no autodeps, clkcm_clk_enable * should be called for every clock instance or hwmod that is * enabled, so the clkdm can be force woken up. */ - if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) + if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) { + spin_unlock_irqrestore(&clkdm->lock, flags); return 0; + } - spin_lock_irqsave(&clkdm->lock, flags); arch_clkdm->clkdm_clk_enable(clkdm); pwrdm_state_switch(clkdm->pwrdm.ptr); spin_unlock_irqrestore(&clkdm->lock, flags); @@ -950,15 +953,19 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm) if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable) return -EINVAL; + spin_lock_irqsave(&clkdm->lock, flags); + if (atomic_read(&clkdm->usecount) == 0) { + spin_unlock_irqrestore(&clkdm->lock, flags); WARN_ON(1); /* underflow */ return -ERANGE; } - if (atomic_dec_return(&clkdm->usecount) > 0) + if (atomic_dec_return(&clkdm->usecount) > 0) { + spin_unlock_irqrestore(&clkdm->lock, flags); return 0; + } - spin_lock_irqsave(&clkdm->lock, flags); arch_clkdm->clkdm_clk_disable(clkdm); pwrdm_state_switch(clkdm->pwrdm.ptr); spin_unlock_irqrestore(&clkdm->lock, flags); diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index b56d06b4878..95192a062d5 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -359,7 +359,7 @@ static struct clockdomain iss_44xx_clkdm = { .clkdm_offs = OMAP4430_CM2_CAM_CAM_CDOFFS, .wkdep_srcs = iss_wkup_sleep_deps, .sleepdep_srcs = iss_wkup_sleep_deps, - .flags = CLKDM_CAN_HWSUP_SWSUP, + .flags = CLKDM_CAN_SWSUP, }; static struct clockdomain l3_dss_44xx_clkdm = { diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c index 48daac2581b..84551f205e4 100644 --- a/arch/arm/mach-omap2/common-board-devices.c +++ b/arch/arm/mach-omap2/common-board-devices.c @@ -64,30 +64,36 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, struct spi_board_info *spi_bi = &ads7846_spi_board_info; int err; - err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown"); - if (err) { - pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err); - return; - } + /* + * If a board defines get_pendown_state() function, request the pendown + * GPIO and set the GPIO debounce time. + * If a board does not define the get_pendown_state() function, then + * the ads7846 driver will setup the pendown GPIO itself. + */ + if (board_pdata && board_pdata->get_pendown_state) { + err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown"); + if (err) { + pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err); + return; + } - if (gpio_debounce) - gpio_set_debounce(gpio_pendown, gpio_debounce); + if (gpio_debounce) + gpio_set_debounce(gpio_pendown, gpio_debounce); + + gpio_export(gpio_pendown, 0); + } spi_bi->bus_num = bus_num; spi_bi->irq = gpio_to_irq(gpio_pendown); + ads7846_config.gpio_pendown = gpio_pendown; + if (board_pdata) { board_pdata->gpio_pendown = gpio_pendown; + board_pdata->gpio_pendown_debounce = gpio_debounce; spi_bi->platform_data = board_pdata; - if (board_pdata->get_pendown_state) - gpio_export(gpio_pendown, 0); - } else { - ads7846_config.gpio_pendown = gpio_pendown; } - if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state)) - gpio_free(gpio_pendown); - spi_register_board_info(&ads7846_spi_board_info, 1); } #else diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index c8c211731d2..c72b5a72772 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -19,6 +19,7 @@ #include <linux/of.h> #include <linux/pinctrl/machine.h> #include <linux/platform_data/omap4-keypad.h> +#include <linux/platform_data/omap_ocp2scp.h> #include <asm/mach-types.h> #include <asm/mach/map.h> @@ -341,7 +342,7 @@ static void __init omap_init_dmic(void) oh = omap_hwmod_lookup("dmic"); if (!oh) { - printk(KERN_ERR "Could not look up mcpdm hw_mod\n"); + pr_err("Could not look up dmic hw_mod\n"); return; } @@ -613,6 +614,83 @@ static void omap_init_vout(void) static inline void omap_init_vout(void) {} #endif +#if defined(CONFIG_OMAP_OCP2SCP) || defined(CONFIG_OMAP_OCP2SCP_MODULE) +static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev) +{ + int cnt = 0; + + while (ocp2scp_dev->drv_name != NULL) { + cnt++; + ocp2scp_dev++; + } + + return cnt; +} + +static void omap_init_ocp2scp(void) +{ + struct omap_hwmod *oh; + struct platform_device *pdev; + int bus_id = -1, dev_cnt = 0, i; + struct omap_ocp2scp_dev *ocp2scp_dev; + const char *oh_name, *name; + struct omap_ocp2scp_platform_data *pdata; + + if (!cpu_is_omap44xx()) + return; + + oh_name = "ocp2scp_usb_phy"; + name = "omap-ocp2scp"; + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err("%s: could not find omap_hwmod for %s\n", __func__, + oh_name); + return; + } + + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + pr_err("%s: No memory for ocp2scp pdata\n", __func__); + return; + } + + ocp2scp_dev = oh->dev_attr; + dev_cnt = count_ocp2scp_devices(ocp2scp_dev); + + if (!dev_cnt) { + pr_err("%s: No devices connected to ocp2scp\n", __func__); + kfree(pdata); + return; + } + + pdata->devices = kzalloc(sizeof(struct omap_ocp2scp_dev *) + * dev_cnt, GFP_KERNEL); + if (!pdata->devices) { + pr_err("%s: No memory for ocp2scp pdata devices\n", __func__); + kfree(pdata); + return; + } + + for (i = 0; i < dev_cnt; i++, ocp2scp_dev++) + pdata->devices[i] = ocp2scp_dev; + + pdata->dev_cnt = dev_cnt; + + pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata), NULL, + 0, false); + if (IS_ERR(pdev)) { + pr_err("Could not build omap_device for %s %s\n", + name, oh_name); + kfree(pdata->devices); + kfree(pdata); + return; + } +} +#else +static inline void omap_init_ocp2scp(void) { } +#endif + /*-------------------------------------------------------------------------*/ static int __init omap2_init_devices(void) @@ -640,6 +718,7 @@ static int __init omap2_init_devices(void) omap_init_sham(); omap_init_aes(); omap_init_vout(); + omap_init_ocp2scp(); return 0; } diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 5ac5cf30406..92b5718fa72 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -868,9 +868,9 @@ static void __devexit gpmc_mem_exit(void) } -static void __devinit gpmc_mem_init(void) +static int __devinit gpmc_mem_init(void) { - int cs; + int cs, rc; unsigned long boot_rom_space = 0; /* never allocate the first page, to facilitate bug detection; @@ -890,13 +890,21 @@ static void __devinit gpmc_mem_init(void) if (!gpmc_cs_mem_enabled(cs)) continue; gpmc_cs_get_memconf(cs, &base, &size); - if (gpmc_cs_insert_mem(cs, base, size) < 0) - BUG(); + rc = gpmc_cs_insert_mem(cs, base, size); + if (IS_ERR_VALUE(rc)) { + while (--cs >= 0) + if (gpmc_cs_mem_enabled(cs)) + gpmc_cs_delete_mem(cs); + return rc; + } } + + return 0; } static __devinit int gpmc_probe(struct platform_device *pdev) { + int rc; u32 l; struct resource *res; @@ -936,7 +944,13 @@ static __devinit int gpmc_probe(struct platform_device *pdev) dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l), GPMC_REVISION_MINOR(l)); - gpmc_mem_init(); + rc = gpmc_mem_init(); + if (IS_ERR_VALUE(rc)) { + clk_disable_unprepare(gpmc_l3_clk); + clk_put(gpmc_l3_clk); + dev_err(gpmc_dev, "failed to reserve memory\n"); + return rc; + } if (IS_ERR_VALUE(gpmc_setup_irq())) dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); diff --git a/arch/arm/mach-omap2/mux34xx.c b/arch/arm/mach-omap2/mux34xx.c index 17f80e4ab16..c47140bbbec 100644 --- a/arch/arm/mach-omap2/mux34xx.c +++ b/arch/arm/mach-omap2/mux34xx.c @@ -614,16 +614,16 @@ static struct omap_mux __initdata omap3_muxmodes[] = { "sys_off_mode", NULL, NULL, NULL, "gpio_9", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_CTS, 150, - "uart1_cts", NULL, NULL, NULL, + "uart1_cts", "ssi1_rdy_tx", NULL, NULL, "gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_RTS, 149, - "uart1_rts", NULL, NULL, NULL, + "uart1_rts", "ssi1_flag_tx", NULL, NULL, "gpio_149", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_RX, 151, - "uart1_rx", NULL, "mcbsp1_clkr", "mcspi4_clk", + "uart1_rx", "ss1_wake_tx", "mcbsp1_clkr", "mcspi4_clk", "gpio_151", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART1_TX, 148, - "uart1_tx", NULL, NULL, NULL, + "uart1_tx", "ssi1_dat_tx", NULL, NULL, "gpio_148", NULL, NULL, "safe_mode"), _OMAP3_MUXENTRY(UART2_CTS, 144, "uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL, diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index b969ab1d258..87cc6d058de 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -422,6 +422,38 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v) } /** + * _wait_softreset_complete - wait for an OCP softreset to complete + * @oh: struct omap_hwmod * to wait on + * + * Wait until the IP block represented by @oh reports that its OCP + * softreset is complete. This can be triggered by software (see + * _ocp_softreset()) or by hardware upon returning from off-mode (one + * example is HSMMC). Waits for up to MAX_MODULE_SOFTRESET_WAIT + * microseconds. Returns the number of microseconds waited. + */ +static int _wait_softreset_complete(struct omap_hwmod *oh) +{ + struct omap_hwmod_class_sysconfig *sysc; + u32 softrst_mask; + int c = 0; + + sysc = oh->class->sysc; + + if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS) + omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs) + & SYSS_RESETDONE_MASK), + MAX_MODULE_SOFTRESET_WAIT, c); + else if (sysc->sysc_flags & SYSC_HAS_RESET_STATUS) { + softrst_mask = (0x1 << sysc->sysc_fields->srst_shift); + omap_test_timeout(!(omap_hwmod_read(oh, sysc->sysc_offs) + & softrst_mask), + MAX_MODULE_SOFTRESET_WAIT, c); + } + + return c; +} + +/** * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v * @oh: struct omap_hwmod * * @@ -1282,6 +1314,18 @@ static void _enable_sysc(struct omap_hwmod *oh) if (!oh->class->sysc) return; + /* + * Wait until reset has completed, this is needed as the IP + * block is reset automatically by hardware in some cases + * (off-mode for example), and the drivers require the + * IP to be ready when they access it + */ + if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) + _enable_optional_clocks(oh); + _wait_softreset_complete(oh); + if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET) + _disable_optional_clocks(oh); + v = oh->_sysc_cache; sf = oh->class->sysc->sysc_flags; @@ -1804,7 +1848,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh) */ static int _ocp_softreset(struct omap_hwmod *oh) { - u32 v, softrst_mask; + u32 v; int c = 0; int ret = 0; @@ -1834,19 +1878,7 @@ static int _ocp_softreset(struct omap_hwmod *oh) if (oh->class->sysc->srst_udelay) udelay(oh->class->sysc->srst_udelay); - if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS) - omap_test_timeout((omap_hwmod_read(oh, - oh->class->sysc->syss_offs) - & SYSS_RESETDONE_MASK), - MAX_MODULE_SOFTRESET_WAIT, c); - else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) { - softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift); - omap_test_timeout(!(omap_hwmod_read(oh, - oh->class->sysc->sysc_offs) - & softrst_mask), - MAX_MODULE_SOFTRESET_WAIT, c); - } - + c = _wait_softreset_complete(oh); if (c == MAX_MODULE_SOFTRESET_WAIT) pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n", oh->name, MAX_MODULE_SOFTRESET_WAIT); @@ -2352,6 +2384,9 @@ static int __init _setup_reset(struct omap_hwmod *oh) if (oh->_state != _HWMOD_STATE_INITIALIZED) return -EINVAL; + if (oh->flags & HWMOD_EXT_OPT_MAIN_CLK) + return -EPERM; + if (oh->rst_lines_cnt == 0) { r = _enable(oh); if (r) { diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 652d0285bd6..0b1249e0039 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -21,6 +21,7 @@ #include <linux/io.h> #include <linux/platform_data/gpio-omap.h> #include <linux/power/smartreflex.h> +#include <linux/platform_data/omap_ocp2scp.h> #include <plat/omap_hwmod.h> #include <plat/i2c.h> @@ -2125,6 +2126,14 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = { .name = "mcpdm", .class = &omap44xx_mcpdm_hwmod_class, .clkdm_name = "abe_clkdm", + /* + * It's suspected that the McPDM requires an off-chip main + * functional clock, controlled via I2C. This IP block is + * currently reset very early during boot, before I2C is + * available, so it doesn't seem that we have any choice in + * the kernel other than to avoid resetting it. + */ + .flags = HWMOD_EXT_OPT_MAIN_CLK, .mpu_irqs = omap44xx_mcpdm_irqs, .sdma_reqs = omap44xx_mcpdm_sdma_reqs, .main_clk = "mcpdm_fck", @@ -2681,6 +2690,32 @@ static struct omap_hwmod_class omap44xx_ocp2scp_hwmod_class = { .sysc = &omap44xx_ocp2scp_sysc, }; +/* ocp2scp dev_attr */ +static struct resource omap44xx_usb_phy_and_pll_addrs[] = { + { + .name = "usb_phy", + .start = 0x4a0ad080, + .end = 0x4a0ae000, + .flags = IORESOURCE_MEM, + }, + { + /* XXX: Remove this once control module driver is in place */ + .name = "ctrl_dev", + .start = 0x4a002300, + .end = 0x4a002303, + .flags = IORESOURCE_MEM, + }, + { } +}; + +static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = { + { + .drv_name = "omap-usb2", + .res = omap44xx_usb_phy_and_pll_addrs, + }, + { } +}; + /* ocp2scp_usb_phy */ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = { .name = "ocp2scp_usb_phy", @@ -2694,6 +2729,7 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = { .modulemode = MODULEMODE_HWCTRL, }, }, + .dev_attr = ocp2scp_dev_attr, }; /* diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 686137d164d..67d66131cfa 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -91,6 +91,7 @@ extern void omap3_save_scratchpad_contents(void); #define PM_RTA_ERRATUM_i608 (1 << 0) #define PM_SDRC_WAKEUP_ERRATUM_i583 (1 << 1) +#define PM_PER_MEMORIES_ERRATUM_i582 (1 << 2) #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) extern u16 pm34xx_errata; diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index ba670db1fd3..3a904de4313 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -652,14 +652,17 @@ static void __init pm_errata_configure(void) /* Enable the l2 cache toggling in sleep logic */ enable_omap3630_toggle_l2_on_restore(); if (omap_rev() < OMAP3630_REV_ES1_2) - pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583; + pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 | + PM_PER_MEMORIES_ERRATUM_i582); + } else if (cpu_is_omap34xx()) { + pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582; } } int __init omap3_pm_init(void) { struct power_state *pwrst, *tmp; - struct clockdomain *neon_clkdm, *mpu_clkdm; + struct clockdomain *neon_clkdm, *mpu_clkdm, *per_clkdm, *wkup_clkdm; int ret; if (!omap3_has_io_chain_ctrl()) @@ -711,6 +714,8 @@ int __init omap3_pm_init(void) neon_clkdm = clkdm_lookup("neon_clkdm"); mpu_clkdm = clkdm_lookup("mpu_clkdm"); + per_clkdm = clkdm_lookup("per_clkdm"); + wkup_clkdm = clkdm_lookup("wkup_clkdm"); #ifdef CONFIG_SUSPEND omap_pm_suspend = omap3_pm_suspend; @@ -727,6 +732,27 @@ int __init omap3_pm_init(void) if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608)) omap3630_ctrl_disable_rta(); + /* + * The UART3/4 FIFO and the sidetone memory in McBSP2/3 are + * not correctly reset when the PER powerdomain comes back + * from OFF or OSWR when the CORE powerdomain is kept active. + * See OMAP36xx Erratum i582 "PER Domain reset issue after + * Domain-OFF/OSWR Wakeup". This wakeup dependency is not a + * complete workaround. The kernel must also prevent the PER + * powerdomain from going to OSWR/OFF while the CORE + * powerdomain is not going to OSWR/OFF. And if PER last + * power state was off while CORE last power state was ON, the + * UART3/4 and McBSP2/3 SIDETONE devices need to run a + * self-test using their loopback tests; if that fails, those + * devices are unusable until the PER/CORE can complete a transition + * from ON to OSWR/OFF and then back to ON. + * + * XXX Technically this workaround is only needed if off-mode + * or OSWR is enabled. + */ + if (IS_PM34XX_ERRATUM(PM_PER_MEMORIES_ERRATUM_i582)) + clkdm_add_wkdep(per_clkdm, wkup_clkdm); + clkdm_add_wkdep(neon_clkdm, mpu_clkdm); if (omap_type() != OMAP2_DEVICE_TYPE_GP) { omap3_secure_ram_storage = diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 0405c819080..a507cd6cf4f 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -329,6 +329,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt); + if (console_uart_id == bdata->id) { + omap_device_enable(pdev); + pm_runtime_set_active(&pdev->dev); + } + oh->dev_attr = uart; if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads) diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 44f9aa7ec0c..69e46631a7c 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -467,7 +467,7 @@ OMAP_SYS_TIMER(3_am33xx) #ifdef CONFIG_ARCH_OMAP4 #ifdef CONFIG_LOCAL_TIMERS static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, - OMAP44XX_LOCAL_TWD_BASE, 29 + OMAP_INTC_START); + OMAP44XX_LOCAL_TWD_BASE, 29); #endif static void __init omap4_timer_init(void) diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index 635e109f5ad..a256135d8e4 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -73,6 +73,7 @@ void __init omap4_pmic_init(const char *pmic_type, { /* PMIC part*/ omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE); + omap_mux_init_signal("fref_clk0_out.sys_drm_msecure", OMAP_PIN_OUTPUT); omap_pmic_init(1, 400, pmic_type, 7 + OMAP44XX_IRQ_GIC_START, pmic_data); /* Register additional devices on i2c1 bus if needed */ @@ -366,7 +367,7 @@ static struct regulator_init_data omap4_clk32kg_idata = { }; static struct regulator_consumer_supply omap4_vdd1_supply[] = { - REGULATOR_SUPPLY("vcc", "mpu.0"), + REGULATOR_SUPPLY("vcc", "cpu0"), }; static struct regulator_consumer_supply omap4_vdd2_supply[] = { diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c index 880249b1701..75878c37959 100644 --- a/arch/arm/mach-omap2/vc.c +++ b/arch/arm/mach-omap2/vc.c @@ -264,7 +264,7 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm) if (initialized) { if (voltdm->pmic->i2c_high_speed != i2c_high_speed) - pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).", + pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).\n", __func__, voltdm->name, i2c_high_speed); return; } diff --git a/arch/arm/mach-prima2/include/mach/gpio.h b/arch/arm/mach-prima2/include/mach/gpio.h deleted file mode 100644 index 1904bb03876..00000000000 --- a/arch/arm/mach-prima2/include/mach/gpio.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __MACH_GPIO_H -#define __MACH_GPIO_H - -/* Pull up/down values */ -enum sirfsoc_gpio_pull { - SIRFSOC_GPIO_PULL_NONE, - SIRFSOC_GPIO_PULL_UP, - SIRFSOC_GPIO_PULL_DOWN, -}; - -void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode); - -#endif diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index 5ecbd17b564..e2c6391863f 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -28,6 +28,7 @@ #include <linux/mfd/asic3.h> #include <linux/mtd/physmap.h> #include <linux/pda_power.h> +#include <linux/pwm.h> #include <linux/pwm_backlight.h> #include <linux/regulator/driver.h> #include <linux/regulator/gpio-regulator.h> @@ -556,7 +557,7 @@ static struct platform_device hx4700_lcd = { */ static struct platform_pwm_backlight_data backlight_data = { - .pwm_id = 1, + .pwm_id = -1, /* Superseded by pwm_lookup */ .max_brightness = 200, .dft_brightness = 100, .pwm_period_ns = 30923, @@ -571,6 +572,10 @@ static struct platform_device backlight = { }, }; +static struct pwm_lookup hx4700_pwm_lookup[] = { + PWM_LOOKUP("pxa27x-pwm.1", 0, "pwm-backlight", NULL), +}; + /* * USB "Transceiver" */ @@ -872,6 +877,7 @@ static void __init hx4700_init(void) pxa_set_stuart_info(NULL); platform_add_devices(devices, ARRAY_SIZE(devices)); + pwm_add_table(hx4700_pwm_lookup, ARRAY_SIZE(hx4700_pwm_lookup)); pxa_set_ficp_info(&ficp_info); pxa27x_set_i2c_power_info(NULL); diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 438f02fe122..842596d4d31 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -86,10 +86,7 @@ static void spitz_discharge1(int on) gpio_set_value(SPITZ_GPIO_LED_GREEN, on); } -static unsigned long gpio18_config[] = { - GPIO18_RDY, - GPIO18_GPIO, -}; +static unsigned long gpio18_config = GPIO18_GPIO; static void spitz_presuspend(void) { @@ -112,7 +109,7 @@ static void spitz_presuspend(void) PGSR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; PGSR2 |= GPIO_bit(SPITZ_GPIO_KEY_STROBE0); - pxa2xx_mfp_config(&gpio18_config[0], 1); + pxa2xx_mfp_config(&gpio18_config, 1); gpio_request_one(18, GPIOF_OUT_INIT_HIGH, "Unknown"); gpio_free(18); @@ -131,7 +128,6 @@ static void spitz_presuspend(void) static void spitz_postsuspend(void) { - pxa2xx_mfp_config(&gpio18_config[1], 1); } static int spitz_should_wakeup(unsigned int resume_on_alarm) diff --git a/arch/arm/mach-s3c24xx/clock-s3c2440.c b/arch/arm/mach-s3c24xx/clock-s3c2440.c index 749220f91a7..4407b173053 100644 --- a/arch/arm/mach-s3c24xx/clock-s3c2440.c +++ b/arch/arm/mach-s3c24xx/clock-s3c2440.c @@ -163,7 +163,7 @@ static struct clk_lookup s3c2440_clk_lookup[] = { CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n), }; -static int s3c2440_clk_add(struct device *dev, struct subsys_interface *sif) +static int __init_refok s3c2440_clk_add(struct device *dev, struct subsys_interface *sif) { struct clk *clock_upll; struct clk *clock_h; diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c index ed5a95ece9e..77ee0b73223 100644 --- a/arch/arm/mach-s3c24xx/s3c2416.c +++ b/arch/arm/mach-s3c24xx/s3c2416.c @@ -61,6 +61,7 @@ #include <plat/nand-core.h> #include <plat/adc-core.h> #include <plat/rtc-core.h> +#include <plat/spi-core.h> static struct map_desc s3c2416_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -132,6 +133,7 @@ void __init s3c2416_map_io(void) /* initialize device information early */ s3c2416_default_sdhci0(); s3c2416_default_sdhci1(); + s3c64xx_spi_setname("s3c2443-spi"); iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc)); } diff --git a/arch/arm/mach-s3c24xx/s3c2443.c b/arch/arm/mach-s3c24xx/s3c2443.c index ab648ad8fa5..165b6a6b3da 100644 --- a/arch/arm/mach-s3c24xx/s3c2443.c +++ b/arch/arm/mach-s3c24xx/s3c2443.c @@ -43,6 +43,7 @@ #include <plat/nand-core.h> #include <plat/adc-core.h> #include <plat/rtc-core.h> +#include <plat/spi-core.h> static struct map_desc s3c2443_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), @@ -100,6 +101,9 @@ void __init s3c2443_map_io(void) s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull; s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull; + /* initialize device information early */ + s3c64xx_spi_setname("s3c2443-spi"); + iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc)); } diff --git a/arch/arm/mach-s5p64x0/common.c b/arch/arm/mach-s5p64x0/common.c index 6e6a0a9d677..111e404a81f 100644 --- a/arch/arm/mach-s5p64x0/common.c +++ b/arch/arm/mach-s5p64x0/common.c @@ -44,6 +44,7 @@ #include <plat/sdhci.h> #include <plat/adc-core.h> #include <plat/fb-core.h> +#include <plat/spi-core.h> #include <plat/gpio-cfg.h> #include <plat/regs-irqtype.h> #include <plat/regs-serial.h> @@ -179,6 +180,7 @@ void __init s5p6440_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); @@ -193,6 +195,7 @@ void __init s5p6450_map_io(void) /* initialize any device information early */ s3c_adc_setname("s3c64xx-adc"); s3c_fb_setname("s5p64x0-fb"); + s3c64xx_spi_setname("s5p64x0-spi"); s5p64x0_default_sdhci0(); s5p64x0_default_sdhci1(); diff --git a/arch/arm/mach-s5pc100/common.c b/arch/arm/mach-s5pc100/common.c index 62190865886..cc6e561c995 100644 --- a/arch/arm/mach-s5pc100/common.c +++ b/arch/arm/mach-s5pc100/common.c @@ -45,6 +45,7 @@ #include <plat/fb-core.h> #include <plat/iic-core.h> #include <plat/onenand-core.h> +#include <plat/spi-core.h> #include <plat/regs-serial.h> #include <plat/watchdog-reset.h> @@ -165,6 +166,8 @@ void __init s5pc100_map_io(void) s3c_onenand_setname("s5pc100-onenand"); s3c_fb_setname("s5pc100-fb"); s3c_cfcon_setname("s5pc100-pata"); + + s3c64xx_spi_setname("s5pc100-spi"); } void __init s5pc100_init_clocks(int xtal) diff --git a/arch/arm/mach-s5pv210/common.c b/arch/arm/mach-s5pv210/common.c index 4c9e9027df9..a0c50efe814 100644 --- a/arch/arm/mach-s5pv210/common.c +++ b/arch/arm/mach-s5pv210/common.c @@ -43,6 +43,7 @@ #include <plat/iic-core.h> #include <plat/keypad-core.h> #include <plat/tv-core.h> +#include <plat/spi-core.h> #include <plat/regs-serial.h> #include "common.h" @@ -196,6 +197,8 @@ void __init s5pv210_map_io(void) /* setup TV devices */ s5p_hdmi_setname("s5pv210-hdmi"); + + s3c64xx_spi_setname("s5pv210-spi"); } void __init s5pv210_init_clocks(int xtal) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index 2912eab3b96..3cc8b1c21da 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -1196,7 +1196,7 @@ static void __init eva_init(void) #ifdef CONFIG_CACHE_L2X0 /* Early BRESP enable, Shared attribute override enable, 32K*8way */ - l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff); + l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff); #endif i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c index 3cafb6ab5e9..37b2a3133b3 100644 --- a/arch/arm/mach-shmobile/clock-r8a7779.c +++ b/arch/arm/mach-shmobile/clock-r8a7779.c @@ -24,17 +24,17 @@ #include <linux/clkdev.h> #include <mach/common.h> -#define FRQMR 0xffc80014 -#define MSTPCR0 0xffc80030 -#define MSTPCR1 0xffc80034 -#define MSTPCR3 0xffc8003c -#define MSTPSR1 0xffc80044 -#define MSTPSR4 0xffc80048 -#define MSTPSR6 0xffc8004c -#define MSTPCR4 0xffc80050 -#define MSTPCR5 0xffc80054 -#define MSTPCR6 0xffc80058 -#define MSTPCR7 0xffc80040 +#define FRQMR IOMEM(0xffc80014) +#define MSTPCR0 IOMEM(0xffc80030) +#define MSTPCR1 IOMEM(0xffc80034) +#define MSTPCR3 IOMEM(0xffc8003c) +#define MSTPSR1 IOMEM(0xffc80044) +#define MSTPSR4 IOMEM(0xffc80048) +#define MSTPSR6 IOMEM(0xffc8004c) +#define MSTPCR4 IOMEM(0xffc80050) +#define MSTPCR5 IOMEM(0xffc80054) +#define MSTPCR6 IOMEM(0xffc80058) +#define MSTPCR7 IOMEM(0xffc80040) /* ioremap() through clock mapping mandatory to avoid * collision with ARM coherent DMA virtual memory range. diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c index 2917668f009..ebbffc25f24 100644 --- a/arch/arm/mach-shmobile/setup-r8a7779.c +++ b/arch/arm/mach-shmobile/setup-r8a7779.c @@ -247,7 +247,7 @@ void __init r8a7779_add_standard_devices(void) { #ifdef CONFIG_CACHE_L2X0 /* Early BRESP enable, Shared attribute override enable, 64K*16way */ - l2x0_init((void __iomem __force *)(0xf0100000), 0x40470000, 0x82000fff); + l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff); #endif r8a7779_pm_init(); diff --git a/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h deleted file mode 100644 index e69de29bb2d..00000000000 --- a/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h +++ /dev/null diff --git a/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h deleted file mode 100644 index e69de29bb2d..00000000000 --- a/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h +++ /dev/null diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index 57e235f4ac7..aa5325cd1c4 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -182,7 +182,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)") .init_early = tegra20_init_early, .init_irq = tegra_dt_init_irq, .handle_irq = gic_handle_irq, - .timer = &tegra_timer, + .timer = &tegra_sys_timer, .init_machine = tegra_dt_init, .init_late = tegra_dt_init_late, .restart = tegra_assert_system_reset, diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c index e4a676d4ddf..5e92a81f9a2 100644 --- a/arch/arm/mach-tegra/board-dt-tegra30.c +++ b/arch/arm/mach-tegra/board-dt-tegra30.c @@ -89,7 +89,7 @@ DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)") .init_early = tegra30_init_early, .init_irq = tegra_dt_init_irq, .handle_irq = gic_handle_irq, - .timer = &tegra_timer, + .timer = &tegra_sys_timer, .init_machine = tegra30_dt_init, .init_late = tegra_init_late, .restart = tegra_assert_system_reset, diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index f88e5143c76..91fbe733a21 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h @@ -55,5 +55,5 @@ static inline int harmony_pcie_init(void) { return 0; } void __init tegra_paz00_wifikill_init(void); -extern struct sys_timer tegra_timer; +extern struct sys_timer tegra_sys_timer; #endif diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c index cc9b5fd8c3d..8d398a33adf 100644 --- a/arch/arm/mach-tegra/tegra20_clocks_data.c +++ b/arch/arm/mach-tegra/tegra20_clocks_data.c @@ -953,6 +953,7 @@ PERIPH_CLK(pcie_xclk, NULL, "pcie_xclk", 74, 0, 26000000, mux_clk_m, static struct clk *tegra_list_clks[] = { &tegra_apbdma, &tegra_rtc, + &tegra_timer, &tegra_i2s1, &tegra_i2s2, &tegra_spdif_out, diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c index 5cd502c2716..e9de5dfd94e 100644 --- a/arch/arm/mach-tegra/tegra30_clocks.c +++ b/arch/arm/mach-tegra/tegra30_clocks.c @@ -1199,7 +1199,7 @@ static long tegra30_pll_round_rate(struct clk_hw *hw, unsigned long rate, { struct clk_tegra *c = to_clk_tegra(hw); unsigned long input_rate = *prate; - unsigned long output_rate = *prate; + u64 output_rate = *prate; const struct clk_pll_freq_table *sel; struct clk_pll_freq_table cfg; int mul; diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c index d92cb556ae3..3d2e5532a9e 100644 --- a/arch/arm/mach-tegra/tegra30_clocks_data.c +++ b/arch/arm/mach-tegra/tegra30_clocks_data.c @@ -1143,6 +1143,7 @@ struct clk *tegra_list_clks[] = { &tegra_apbdma, &tegra_rtc, &tegra_kbc, + &tegra_timer, &tegra_kfuse, &tegra_fuse, &tegra_fuse_burn, diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index eccdce98304..d3b8c8e7368 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c @@ -245,7 +245,7 @@ static void __init tegra_init_timer(void) register_persistent_clock(NULL, tegra_read_persistent_clock); } -struct sys_timer tegra_timer = { +struct sys_timer tegra_sys_timer = { .init = tegra_init_timer, }; diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 2236cbd03cd..1f3fbc2bb77 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -16,6 +16,7 @@ #include <linux/stat.h> #include <linux/of.h> #include <linux/of_irq.h> +#include <linux/irq.h> #include <linux/platform_data/clk-ux500.h> #include <asm/hardware/gic.h> diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index b9f60ebe3bc..b820edaf318 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs, static int do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { - union offset_union offset; + union offset_union uninitialized_var(offset); unsigned long instr = 0, instrptr; int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs); unsigned int type; @@ -856,8 +856,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (thumb2_32b) { offset.un = 0; handler = do_alignment_t32_to_handler(&instr, regs, &offset); - } else + } else { + offset.un = 0; handler = do_alignment_ldmstm; + } break; default: diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 477a2d23ddf..58bc3e4d3bd 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -610,7 +610,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, pgprot_t prot, bool is_coherent, const void *caller) { u64 mask = get_coherent_dma_mask(dev); - struct page *page; + struct page *page = NULL; void *addr; #ifdef CONFIG_DMA_API_DEBUG diff --git a/arch/arm/mm/vmregion.h b/arch/arm/mm/vmregion.h index bf312c354a2..0f5a5f2a2c7 100644 --- a/arch/arm/mm/vmregion.h +++ b/arch/arm/mm/vmregion.h @@ -17,7 +17,6 @@ struct arm_vmregion { struct list_head vm_list; unsigned long vm_start; unsigned long vm_end; - void *priv; int vm_active; const void *caller; }; diff --git a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c index 540d3a7d92d..e7b920b5867 100644 --- a/arch/arm/plat-mxc/devices/platform-mxc-mmc.c +++ b/arch/arm/plat-mxc/devices/platform-mxc-mmc.c @@ -55,7 +55,7 @@ struct platform_device *__init imx_add_mxc_mmc( struct resource res[] = { { .start = data->iobase, - .end = data->iobase + SZ_4K - 1, + .end = data->iobase + data->iosize - 1, .flags = IORESOURCE_MEM, }, { .start = data->irq, diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 7cd56ed5cd9..82fcb206b5b 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -26,6 +26,7 @@ config ARCH_OMAP2PLUS select CLKDEV_LOOKUP select GENERIC_IRQ_CHIP select OMAP_DM_TIMER + select PINCTRL select PROC_DEVICETREE if PROC_FS select SPARSE_IRQ select USE_OF diff --git a/arch/arm/plat-omap/debug-devices.c b/arch/arm/plat-omap/debug-devices.c index c7a4c0902b3..5a4678edd65 100644 --- a/arch/arm/plat-omap/debug-devices.c +++ b/arch/arm/plat-omap/debug-devices.c @@ -16,6 +16,7 @@ #include <linux/smc91x.h> #include <mach/hardware.h> +#include "../mach-omap2/debug-devices.h" /* Many OMAP development platforms reuse the same "debug board"; these * platforms include H2, H3, H4, and Perseus2. diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index a5683a84c6e..6013831a043 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -26,12 +26,14 @@ #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/i2c.h> +#include <linux/i2c-omap.h> #include <linux/slab.h> #include <linux/err.h> #include <linux/clk.h> #include <mach/irqs.h> #include <plat/i2c.h> +#include <plat/omap-pm.h> #include <plat/omap_device.h> #define OMAP_I2C_SIZE 0x3f @@ -127,6 +129,16 @@ static inline int omap1_i2c_add_bus(int bus_id) #ifdef CONFIG_ARCH_OMAP2PLUS +/* + * XXX This function is a temporary compatibility wrapper - only + * needed until the I2C driver can be converted to call + * omap_pm_set_max_dev_wakeup_lat() and handle a return code. + */ +static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, t); +} + static inline int omap2_i2c_add_bus(int bus_id) { int l; @@ -158,6 +170,15 @@ static inline int omap2_i2c_add_bus(int bus_id) dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr; pdata->flags = dev_attr->flags; + /* + * When waiting for completion of a i2c transfer, we need to + * set a wake up latency constraint for the MPU. This is to + * ensure quick enough wakeup from idle, when transfer + * completes. + * Only omap3 has support for constraints + */ + if (cpu_is_omap34xx()) + pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(struct omap_i2c_bus_platform_data), NULL, 0, 0); diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index f4a4cd01479..1957a8516e9 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -40,10 +40,10 @@ #define OMAP_UART_WER_MOD_WKUP 0X7F /* Enable XON/XOFF flow control on output */ -#define OMAP_UART_SW_TX 0x8 +#define OMAP_UART_SW_TX 0x04 /* Enable XON/XOFF flow control on input */ -#define OMAP_UART_SW_RX 0x2 +#define OMAP_UART_SW_RX 0x04 #define OMAP_UART_SYSC_RESET 0X07 #define OMAP_UART_TCR_TRIG 0X0F diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index b3349f7b1a2..1db02943802 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -443,6 +443,11 @@ struct omap_hwmod_omap4_prcm { * in order to complete the reset. Optional clocks will be disabled * again after the reset. * HWMOD_16BIT_REG: Module has 16bit registers + * HWMOD_EXT_OPT_MAIN_CLK: The only main functional clock source for + * this IP block comes from an off-chip source and is not always + * enabled. This prevents the hwmod code from being able to + * enable and reset the IP block early. XXX Eventually it should + * be possible to query the clock framework for this information. */ #define HWMOD_SWSUP_SIDLE (1 << 0) #define HWMOD_SWSUP_MSTANDBY (1 << 1) @@ -453,6 +458,7 @@ struct omap_hwmod_omap4_prcm { #define HWMOD_NO_IDLEST (1 << 6) #define HWMOD_CONTROL_OPT_CLKS_IN_RESET (1 << 7) #define HWMOD_16BIT_REG (1 << 8) +#define HWMOD_EXT_OPT_MAIN_CLK (1 << 9) /* * omap_hwmod._int_flags definitions diff --git a/arch/arm/plat-samsung/include/plat/spi-core.h b/arch/arm/plat-samsung/include/plat/spi-core.h new file mode 100644 index 00000000000..0b9428ab3fc --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/spi-core.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.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 + * published by the Free Software Foundation. + */ + +#ifndef __PLAT_S3C_SPI_CORE_H +#define __PLAT_S3C_SPI_CORE_H + +/* These functions are only for use with the core support code, such as + * the cpu specific initialisation code + */ + +/* re-define device name depending on support. */ +static inline void s3c64xx_spi_setname(char *name) +{ +#ifdef CONFIG_S3C64XX_DEV_SPI0 + s3c64xx_device_spi0.name = name; +#endif +#ifdef CONFIG_S3C64XX_DEV_SPI1 + s3c64xx_device_spi1.name = name; +#endif +#ifdef CONFIG_S3C64XX_DEV_SPI2 + s3c64xx_device_spi2.name = name; +#endif +} + +#endif /* __PLAT_S3C_SPI_CORE_H */ diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile index 635cb1865e4..32d05c8219d 100644 --- a/arch/arm/tools/Makefile +++ b/arch/arm/tools/Makefile @@ -5,6 +5,6 @@ # include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types - @echo ' Generating $@' + @$(kecho) ' Generating $@' @mkdir -p $(dir $@) $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; } diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index c834b32af27..3b44e0dd0a9 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -701,11 +701,14 @@ static int __init vfp_init(void) elf_hwcap |= HWCAP_VFPv3; /* - * Check for VFPv3 D16. CPUs in this configuration - * only have 16 x 64bit registers. + * Check for VFPv3 D16 and VFPv4 D16. CPUs in + * this configuration only have 16 x 64bit + * registers. */ if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) - elf_hwcap |= HWCAP_VFPv3D16; + elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */ + else + elf_hwcap |= HWCAP_VFPD32; } #endif /* diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 59bcb96ac36..f5760927544 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -166,3 +166,14 @@ void free_xenballooned_pages(int nr_pages, struct page **pages) *pages = NULL; } EXPORT_SYMBOL_GPL(free_xenballooned_pages); + +/* In the hypervisor.S file. */ +EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_xen_version); +EXPORT_SYMBOL_GPL(HYPERVISOR_console_io); +EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op); +EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op); +EXPORT_SYMBOL_GPL(privcmd_call); diff --git a/arch/arm/xen/grant-table.c b/arch/arm/xen/grant-table.c index dbd1330c019..859a9bb002d 100644 --- a/arch/arm/xen/grant-table.c +++ b/arch/arm/xen/grant-table.c @@ -33,7 +33,7 @@ #include <xen/page.h> #include <xen/grant_table.h> -int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, +int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes, unsigned long max_nr_gframes, void **__shared) { diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S index 074f5ed101b..71f723984cb 100644 --- a/arch/arm/xen/hypercall.S +++ b/arch/arm/xen/hypercall.S @@ -48,20 +48,16 @@ #include <linux/linkage.h> #include <asm/assembler.h> +#include <asm/opcodes-virt.h> #include <xen/interface/xen.h> -/* HVC 0xEA1 */ -#ifdef CONFIG_THUMB2_KERNEL -#define xen_hvc .word 0xf7e08ea1 -#else -#define xen_hvc .word 0xe140ea71 -#endif +#define XEN_IMM 0xEA1 #define HYPERCALL_SIMPLE(hypercall) \ ENTRY(HYPERVISOR_##hypercall) \ mov r12, #__HYPERVISOR_##hypercall; \ - xen_hvc; \ + __HVC(XEN_IMM); \ mov pc, lr; \ ENDPROC(HYPERVISOR_##hypercall) @@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall) \ stmdb sp!, {r4} \ ldr r4, [sp, #4] \ mov r12, #__HYPERVISOR_##hypercall; \ - xen_hvc \ + __HVC(XEN_IMM); \ ldm sp!, {r4} \ mov pc, lr \ ENDPROC(HYPERVISOR_##hypercall) @@ -100,7 +96,7 @@ ENTRY(privcmd_call) mov r2, r3 ldr r3, [sp, #8] ldr r4, [sp, #4] - xen_hvc + __HVC(XEN_IMM) ldm sp!, {r4} mov pc, lr ENDPROC(privcmd_call); diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 7ff68c94607..20b688c8195 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1,11 +1,14 @@ config ARM64 def_bool y select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE + select ARCH_WANT_COMPAT_IPC_PARSE_VERSION select GENERIC_CLOCKEVENTS select GENERIC_HARDIRQS_NO_DEPRECATED select GENERIC_IOMAP select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW + select GENERIC_KERNEL_EXECVE + select GENERIC_KERNEL_THREAD select GENERIC_SMP_IDLE_THREAD select GENERIC_TIME_VSYSCALL select HARDIRQS_SW_RESEND @@ -22,6 +25,7 @@ config ARM64 select HAVE_PERF_EVENTS select HAVE_SPARSE_IRQ select IRQ_DOMAIN + select MODULES_USE_ELF_RELA select NO_BOOTMEM select OF select OF_EARLY_FLATTREE diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index fe77e51a784..a581a220593 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -18,7 +18,6 @@ generic-y += ipcbuf.h generic-y += irq_regs.h generic-y += kdebug.h generic-y += kmap_types.h -generic-y += linkage.h generic-y += local.h generic-y += local64.h generic-y += mman.h diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index cf284649dfc..07fea290d7c 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -25,12 +25,10 @@ #include <asm/user.h> typedef unsigned long elf_greg_t; -typedef unsigned long elf_freg_t[3]; #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef struct user_fp elf_fpregset_t; +typedef struct user_fpsimd_state elf_fpregset_t; #define EM_AARCH64 183 @@ -87,7 +85,6 @@ typedef struct user_fp elf_fpregset_t; #define R_AARCH64_MOVW_PREL_G2_NC 292 #define R_AARCH64_MOVW_PREL_G3 293 - /* * These are used to set parameters in the core dumps. */ diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h index b42fab9f62a..c43b4ac1300 100644 --- a/arch/arm64/include/asm/fpsimd.h +++ b/arch/arm64/include/asm/fpsimd.h @@ -25,9 +25,8 @@ * - FPSR and FPCR * - 32 128-bit data registers * - * Note that user_fp forms a prefix of this structure, which is relied - * upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must - * form a prefix of struct fpsimd_state. + * Note that user_fpsimd forms a prefix of this structure, which is + * relied upon in the ptrace FP/SIMD accessors. */ struct fpsimd_state { union { diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 74a2a7d304a..d2f05a60827 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -114,7 +114,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) * I/O port access primitives. */ #define IO_SPACE_LIMIT 0xffff -#define PCI_IOBASE ((void __iomem *)0xffffffbbfffe0000UL) +#define PCI_IOBASE ((void __iomem *)(MODULES_VADDR - SZ_2M)) static inline u8 inb(unsigned long addr) { @@ -222,12 +222,12 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot extern void __iounmap(volatile void __iomem *addr); #define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY) -#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) +#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) #define PROT_NORMAL_NC (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC)) -#define ioremap(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE) -#define ioremap_nocache(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE) -#define ioremap_wc(addr, size) __ioremap((addr), (size), PROT_NORMAL_NC) +#define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) +#define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) +#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC)) #define iounmap __iounmap #define ARCH_HAS_IOREMAP_WC diff --git a/arch/arm64/include/asm/linkage.h b/arch/arm64/include/asm/linkage.h new file mode 100644 index 00000000000..636c1bced7d --- /dev/null +++ b/arch/arm64/include/asm/linkage.h @@ -0,0 +1,7 @@ +#ifndef __ASM_LINKAGE_H +#define __ASM_LINKAGE_H + +#define __ALIGN .align 4 +#define __ALIGN_STR ".align 4" + +#endif diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index 0f3b4581d92..75fd13d289b 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -38,7 +38,8 @@ #define PMD_SECT_S (_AT(pmdval_t, 3) << 8) #define PMD_SECT_AF (_AT(pmdval_t, 1) << 10) #define PMD_SECT_NG (_AT(pmdval_t, 1) << 11) -#define PMD_SECT_XN (_AT(pmdval_t, 1) << 54) +#define PMD_SECT_PXN (_AT(pmdval_t, 1) << 53) +#define PMD_SECT_UXN (_AT(pmdval_t, 1) << 54) /* * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). @@ -57,7 +58,8 @@ #define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ #define PTE_AF (_AT(pteval_t, 1) << 10) /* Access Flag */ #define PTE_NG (_AT(pteval_t, 1) << 11) /* nG */ -#define PTE_XN (_AT(pteval_t, 1) << 54) /* XN */ +#define PTE_PXN (_AT(pteval_t, 1) << 53) /* Privileged XN */ +#define PTE_UXN (_AT(pteval_t, 1) << 54) /* User XN */ /* * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers). diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 8960239be72..14aba2db677 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -62,23 +62,23 @@ extern pgprot_t pgprot_default; #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) -#define PAGE_NONE _MOD_PROT(pgprot_default, PTE_NG | PTE_XN | PTE_RDONLY) -#define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN) -#define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG) -#define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) -#define PAGE_COPY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY) -#define PAGE_READONLY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) -#define PAGE_READONLY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY) -#define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_XN | PTE_DIRTY) -#define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_DIRTY) - -#define __PAGE_NONE __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_XN | PTE_RDONLY) -#define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN) -#define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG) -#define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) -#define __PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY) -#define __PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY) -#define __PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY) +#define PAGE_NONE _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) +#define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) +#define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) +#define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) +#define PAGE_COPY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY) +#define PAGE_READONLY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) +#define PAGE_READONLY_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY) +#define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY) +#define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY) + +#define __PAGE_NONE __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) +#define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) +#define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) +#define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) +#define __PAGE_COPY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY) +#define __PAGE_READONLY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) +#define __PAGE_READONLY_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY) #endif /* __ASSEMBLY__ */ @@ -130,10 +130,10 @@ extern struct page *empty_zero_page; #define pte_young(pte) (pte_val(pte) & PTE_AF) #define pte_special(pte) (pte_val(pte) & PTE_SPECIAL) #define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY)) -#define pte_exec(pte) (!(pte_val(pte) & PTE_XN)) +#define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) #define pte_present_exec_user(pte) \ - ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_XN)) == \ + ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \ (PTE_VALID | PTE_USER)) #define PTE_BIT_FUNC(fn,op) \ @@ -262,7 +262,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { - const pteval_t mask = PTE_USER | PTE_XN | PTE_RDONLY; + const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY; pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); return pte; } diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 39a208a392f..ab239b2c456 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -43,6 +43,8 @@ #else #define STACK_TOP STACK_TOP_MAX #endif /* CONFIG_COMPAT */ + +#define ARCH_LOW_ADDRESS_LIMIT PHYS_MASK #endif /* __KERNEL__ */ struct debug_info { @@ -92,30 +94,20 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc) static inline void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { - unsigned long *stack = (unsigned long *)sp; - start_thread_common(regs, pc); regs->pstate = PSR_MODE_EL0t; regs->sp = sp; - regs->regs[2] = stack[2]; /* x2 (envp) */ - regs->regs[1] = stack[1]; /* x1 (argv) */ - regs->regs[0] = stack[0]; /* x0 (argc) */ } #ifdef CONFIG_COMPAT static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { - unsigned int *stack = (unsigned int *)sp; - start_thread_common(regs, pc); regs->pstate = COMPAT_PSR_MODE_USR; if (pc & 1) regs->pstate |= COMPAT_PSR_T_BIT; regs->compat_sp = sp; - regs->regs[2] = stack[2]; /* x2 (envp) */ - regs->regs[1] = stack[1]; /* x1 (argv) */ - regs->regs[0] = stack[0]; /* x0 (argc) */ } #endif @@ -136,11 +128,6 @@ unsigned long get_wchan(struct task_struct *p); extern struct task_struct *cpu_switch_to(struct task_struct *prev, struct task_struct *next); -/* - * Create a new kernel thread - */ -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); - #define task_pt_regs(p) \ ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) diff --git a/arch/arm64/include/asm/syscalls.h b/arch/arm64/include/asm/syscalls.h index 09ff33572aa..a1b00cd6f78 100644 --- a/arch/arm64/include/asm/syscalls.h +++ b/arch/arm64/include/asm/syscalls.h @@ -23,18 +23,16 @@ /* * System call wrappers implemented in kernel/entry.S. */ -asmlinkage long sys_execve_wrapper(const char __user *filename, - const char __user *const __user *argv, - const char __user *const __user *envp); -asmlinkage long sys_clone_wrapper(unsigned long clone_flags, - unsigned long newsp, - void __user *parent_tid, - unsigned long tls_val, - void __user *child_tid); asmlinkage long sys_rt_sigreturn_wrapper(void); asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss, stack_t __user *uoss); +/* + * AArch64 sys_clone implementation has a different prototype than the generic + * one (additional TLS value argument). + */ +#define sys_clone sys_clone + #include <asm-generic/syscalls.h> #endif /* __ASM_SYSCALLS_H */ diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 63f853f8b71..43064a8bd99 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -14,7 +14,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef CONFIG_COMPAT -#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION #define __ARCH_WANT_COMPAT_STAT64 #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE @@ -26,4 +25,5 @@ #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif +#define __ARCH_WANT_SYS_EXECVE #include <uapi/asm/unistd.h> diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 6d909faebf2..d9850cf9870 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -23,7 +23,7 @@ __SYSCALL(0, sys_restart_syscall) __SYSCALL(1, sys_exit) -__SYSCALL(2, compat_sys_fork_wrapper) +__SYSCALL(2, compat_sys_fork) __SYSCALL(3, sys_read) __SYSCALL(4, sys_write) __SYSCALL(5, compat_sys_open) @@ -32,7 +32,7 @@ __SYSCALL(7, sys_ni_syscall) /* 7 was sys_waitpid */ __SYSCALL(8, sys_creat) __SYSCALL(9, sys_link) __SYSCALL(10, sys_unlink) -__SYSCALL(11, compat_sys_execve_wrapper) +__SYSCALL(11, compat_sys_execve) __SYSCALL(12, sys_chdir) __SYSCALL(13, sys_ni_syscall) /* 13 was sys_time */ __SYSCALL(14, sys_mknod) @@ -141,7 +141,7 @@ __SYSCALL(116, compat_sys_sysinfo) __SYSCALL(117, sys_ni_syscall) /* 117 was sys_ipc */ __SYSCALL(118, sys_fsync) __SYSCALL(119, compat_sys_sigreturn_wrapper) -__SYSCALL(120, compat_sys_clone_wrapper) +__SYSCALL(120, sys_clone) __SYSCALL(121, sys_setdomainname) __SYSCALL(122, sys_newuname) __SYSCALL(123, sys_ni_syscall) /* 123 was sys_modify_ldt */ @@ -211,7 +211,7 @@ __SYSCALL(186, compat_sys_sigaltstack_wrapper) __SYSCALL(187, compat_sys_sendfile) __SYSCALL(188, sys_ni_syscall) /* 188 reserved */ __SYSCALL(189, sys_ni_syscall) /* 189 reserved */ -__SYSCALL(190, compat_sys_vfork_wrapper) +__SYSCALL(190, compat_sys_vfork) __SYSCALL(191, compat_sys_getrlimit) /* SuS compliant getrlimit */ __SYSCALL(192, sys_mmap_pgoff) __SYSCALL(193, compat_sys_truncate64_wrapper) diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h index 9b131b4efa0..6913643bbe5 100644 --- a/arch/arm64/include/uapi/asm/ptrace.h +++ b/arch/arm64/include/uapi/asm/ptrace.h @@ -79,13 +79,14 @@ struct user_fpsimd_state { struct user_hwdebug_state { __u32 dbg_info; + __u32 pad; struct { __u64 addr; __u32 ctrl; + __u32 pad; } dbg_regs[16]; }; - #endif /* __ASSEMBLY__ */ #endif /* _UAPI__ASM_PTRACE_H */ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a6f3f7da688..cbfa4d28100 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -594,7 +594,7 @@ work_resched: /* * "slow" syscall return path. */ -ENTRY(ret_to_user) +ret_to_user: disable_irq // disable interrupts ldr x1, [tsk, #TI_FLAGS] and x2, x1, #_TIF_WORK_MASK @@ -611,7 +611,10 @@ ENDPROC(ret_to_user) */ ENTRY(ret_from_fork) bl schedule_tail - get_thread_info tsk + cbz x19, 1f // not a kernel thread + mov x0, x20 + blr x19 +1: get_thread_info tsk b ret_to_user ENDPROC(ret_from_fork) @@ -673,16 +676,6 @@ __sys_trace_return: /* * Special system call wrappers. */ -ENTRY(sys_execve_wrapper) - mov x3, sp - b sys_execve -ENDPROC(sys_execve_wrapper) - -ENTRY(sys_clone_wrapper) - mov x5, sp - b sys_clone -ENDPROC(sys_clone_wrapper) - ENTRY(sys_rt_sigreturn_wrapper) mov x0, sp b sys_rt_sigreturn diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index ecbf2d81ec5..c76c7241125 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -613,17 +613,11 @@ enum armv8_pmuv3_perf_types { ARMV8_PMUV3_PERFCTR_BUS_ACCESS = 0x19, ARMV8_PMUV3_PERFCTR_MEM_ERROR = 0x1A, ARMV8_PMUV3_PERFCTR_BUS_CYCLES = 0x1D, - - /* - * This isn't an architected event. - * We detect this event number and use the cycle counter instead. - */ - ARMV8_PMUV3_PERFCTR_CPU_CYCLES = 0xFF, }; /* PMUv3 HW events mapping. */ static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES, + [PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES, [PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED, [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS, [PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL, @@ -1106,7 +1100,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc, unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT; /* Always place a cycle counter into the cycle counter. */ - if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) { + if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) { if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) return -EAGAIN; diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index f22965ea1cf..8a5f3341861 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -240,27 +240,41 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *childregs = task_pt_regs(p); unsigned long tls = p->thread.tp_value; - *childregs = *regs; - childregs->regs[0] = 0; + memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); - if (is_compat_thread(task_thread_info(p))) - childregs->compat_sp = stack_start; - else { + if (likely(regs)) { + *childregs = *regs; + childregs->regs[0] = 0; + if (is_compat_thread(task_thread_info(p))) { + if (stack_start) + childregs->compat_sp = stack_start; + } else { + /* + * Read the current TLS pointer from tpidr_el0 as it may be + * out-of-sync with the saved value. + */ + asm("mrs %0, tpidr_el0" : "=r" (tls)); + if (stack_start) { + /* 16-byte aligned stack mandatory on AArch64 */ + if (stack_start & 15) + return -EINVAL; + childregs->sp = stack_start; + } + } /* - * Read the current TLS pointer from tpidr_el0 as it may be - * out-of-sync with the saved value. + * If a TLS pointer was passed to clone (4th argument), use it + * for the new thread. */ - asm("mrs %0, tpidr_el0" : "=r" (tls)); - childregs->sp = stack_start; + if (clone_flags & CLONE_SETTLS) + tls = regs->regs[3]; + } else { + memset(childregs, 0, sizeof(struct pt_regs)); + childregs->pstate = PSR_MODE_EL1h; + p->thread.cpu_context.x19 = stack_start; + p->thread.cpu_context.x20 = stk_sz; } - - memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); - p->thread.cpu_context.sp = (unsigned long)childregs; p->thread.cpu_context.pc = (unsigned long)ret_from_fork; - - /* If a TLS pointer was passed to clone, use that for the new thread. */ - if (clone_flags & CLONE_SETTLS) - tls = regs->regs[3]; + p->thread.cpu_context.sp = (unsigned long)childregs; p->thread.tp_value = tls; ptrace_hw_copy_thread(p); @@ -309,61 +323,6 @@ struct task_struct *__switch_to(struct task_struct *prev, return last; } -/* - * Fill in the task's elfregs structure for a core dump. - */ -int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs) -{ - elf_core_copy_regs(elfregs, task_pt_regs(t)); - return 1; -} - -/* - * fill in the fpe structure for a core dump... - */ -int dump_fpu (struct pt_regs *regs, struct user_fp *fp) -{ - return 0; -} -EXPORT_SYMBOL(dump_fpu); - -/* - * Shuffle the argument into the correct register before calling the - * thread function. x1 is the thread argument, x2 is the pointer to - * the thread function, and x3 points to the exit function. - */ -extern void kernel_thread_helper(void); -asm( ".section .text\n" -" .align\n" -" .type kernel_thread_helper, #function\n" -"kernel_thread_helper:\n" -" mov x0, x1\n" -" mov x30, x3\n" -" br x2\n" -" .size kernel_thread_helper, . - kernel_thread_helper\n" -" .previous"); - -#define kernel_thread_exit do_exit - -/* - * Create a kernel thread. - */ -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.regs[1] = (unsigned long)arg; - regs.regs[2] = (unsigned long)fn; - regs.regs[3] = (unsigned long)kernel_thread_exit; - regs.pc = (unsigned long)kernel_thread_helper; - regs.pstate = PSR_MODE_EL1h; - - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - unsigned long get_wchan(struct task_struct *p) { struct stackframe frame; diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 2ea3968367c..6e1e77f1831 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -234,28 +234,33 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type, struct arch_hw_breakpoint_ctrl ctrl, struct perf_event_attr *attr) { - int err, len, type; + int err, len, type, disabled = !ctrl.enabled; - err = arch_bp_generic_fields(ctrl, &len, &type); - if (err) - return err; - - switch (note_type) { - case NT_ARM_HW_BREAK: - if ((type & HW_BREAKPOINT_X) != type) - return -EINVAL; - break; - case NT_ARM_HW_WATCH: - if ((type & HW_BREAKPOINT_RW) != type) + if (disabled) { + len = 0; + type = HW_BREAKPOINT_EMPTY; + } else { + err = arch_bp_generic_fields(ctrl, &len, &type); + if (err) + return err; + + switch (note_type) { + case NT_ARM_HW_BREAK: + if ((type & HW_BREAKPOINT_X) != type) + return -EINVAL; + break; + case NT_ARM_HW_WATCH: + if ((type & HW_BREAKPOINT_RW) != type) + return -EINVAL; + break; + default: return -EINVAL; - break; - default: - return -EINVAL; + } } attr->bp_len = len; attr->bp_type = type; - attr->disabled = !ctrl.enabled; + attr->disabled = disabled; return 0; } @@ -372,7 +377,7 @@ static int ptrace_hbp_set_addr(unsigned int note_type, #define PTRACE_HBP_ADDR_SZ sizeof(u64) #define PTRACE_HBP_CTRL_SZ sizeof(u32) -#define PTRACE_HBP_REG_OFF sizeof(u32) +#define PTRACE_HBP_PAD_SZ sizeof(u32) static int hw_break_get(struct task_struct *target, const struct user_regset *regset, @@ -380,7 +385,7 @@ static int hw_break_get(struct task_struct *target, void *kbuf, void __user *ubuf) { unsigned int note_type = regset->core_note_type; - int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit; + int ret, idx = 0, offset, limit; u32 info, ctrl; u64 addr; @@ -389,11 +394,20 @@ static int hw_break_get(struct task_struct *target, if (ret) return ret; - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 4); + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, + sizeof(info)); + if (ret) + return ret; + + /* Pad */ + offset = offsetof(struct user_hwdebug_state, pad); + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset, + offset + PTRACE_HBP_PAD_SZ); if (ret) return ret; /* (address, ctrl) registers */ + offset = offsetof(struct user_hwdebug_state, dbg_regs); limit = regset->n * regset->size; while (count && offset < limit) { ret = ptrace_hbp_get_addr(note_type, target, idx, &addr); @@ -413,6 +427,13 @@ static int hw_break_get(struct task_struct *target, if (ret) return ret; offset += PTRACE_HBP_CTRL_SZ; + + ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, + offset, + offset + PTRACE_HBP_PAD_SZ); + if (ret) + return ret; + offset += PTRACE_HBP_PAD_SZ; idx++; } @@ -425,12 +446,13 @@ static int hw_break_set(struct task_struct *target, const void *kbuf, const void __user *ubuf) { unsigned int note_type = regset->core_note_type; - int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit; + int ret, idx = 0, offset, limit; u32 ctrl; u64 addr; - /* Resource info */ - ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4); + /* Resource info and pad */ + offset = offsetof(struct user_hwdebug_state, dbg_regs); + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset); if (ret) return ret; @@ -454,6 +476,13 @@ static int hw_break_set(struct task_struct *target, if (ret) return ret; offset += PTRACE_HBP_CTRL_SZ; + + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, + offset, + offset + PTRACE_HBP_PAD_SZ); + if (ret) + return ret; + offset += PTRACE_HBP_PAD_SZ; idx++; } diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 48ffb9fb3fe..7665a9bfdb1 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -170,7 +170,19 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) void __init early_init_dt_add_memory_arch(u64 base, u64 size) { + base &= PAGE_MASK; size &= PAGE_MASK; + if (base + size < PHYS_OFFSET) { + pr_warning("Ignoring memory block 0x%llx - 0x%llx\n", + base, base + size); + return; + } + if (base < PHYS_OFFSET) { + pr_warning("Ignoring memory range 0x%llx - 0x%llx\n", + base, PHYS_OFFSET); + size -= PHYS_OFFSET - base; + base = PHYS_OFFSET; + } memblock_add(base, size); } diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index b711525be21..538300f2273 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -46,7 +46,6 @@ #include <asm/sections.h> #include <asm/tlbflush.h> #include <asm/ptrace.h> -#include <asm/mmu_context.h> /* * as from 2.5, kernels no longer have an init_tasks structure @@ -212,8 +211,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) * before we continue. */ set_cpu_online(cpu, true); - while (!cpu_active(cpu)) - cpu_relax(); + complete(&cpu_running); /* * OK, it's off to the idle thread for us diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c index b120df37de3..4364df85050 100644 --- a/arch/arm64/kernel/sys.c +++ b/arch/arm64/kernel/sys.c @@ -31,79 +31,11 @@ */ asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, int __user *parent_tidptr, unsigned long tls_val, - int __user *child_tidptr, struct pt_regs *regs) + int __user *child_tidptr) { - if (!newsp) - newsp = regs->sp; - /* 16-byte aligned stack mandatory on AArch64 */ - if (newsp & 15) - return -EINVAL; - return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); -} - -/* - * sys_execve() executes a new program. - */ -asmlinkage long sys_execve(const char __user *filenamei, - const char __user *const __user *argv, - const char __user *const __user *envp, - struct pt_regs *regs) -{ - long error; - struct filename *filename; - - filename = getname(filenamei); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename->name, argv, envp, regs); - putname(filename); -out: - return error; -} - -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - struct pt_regs regs; - int ret; - - memset(®s, 0, sizeof(struct pt_regs)); - ret = do_execve(filename, - (const char __user *const __user *)argv, - (const char __user *const __user *)envp, ®s); - if (ret < 0) - goto out; - - /* - * Save argc to the register structure for userspace. - */ - regs.regs[0] = ret; - - /* - * We were successful. We won't be returning to our caller, but - * instead to user space by manipulating the kernel stack. - */ - asm( "add x0, %0, %1\n\t" - "mov x1, %2\n\t" - "mov x2, %3\n\t" - "bl memmove\n\t" /* copy regs to top of stack */ - "mov x27, #0\n\t" /* not a syscall */ - "mov x28, %0\n\t" /* thread structure */ - "mov sp, x0\n\t" /* reposition stack pointer */ - "b ret_to_user" - : - : "r" (current_thread_info()), - "Ir" (THREAD_START_SP - sizeof(regs)), - "r" (®s), - "Ir" (sizeof(regs)) - : "x0", "x1", "x2", "x27", "x28", "x30", "memory"); - - out: - return ret; + return do_fork(clone_flags, newsp, current_pt_regs(), 0, + parent_tidptr, child_tidptr); } -EXPORT_SYMBOL(kernel_execve); asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, @@ -118,8 +50,6 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, /* * Wrappers to pass the pt_regs argument. */ -#define sys_execve sys_execve_wrapper -#define sys_clone sys_clone_wrapper #define sys_rt_sigreturn sys_rt_sigreturn_wrapper #define sys_sigaltstack sys_sigaltstack_wrapper diff --git a/arch/arm64/kernel/sys32.S b/arch/arm64/kernel/sys32.S index 54c4aec47a0..7ef59e9245e 100644 --- a/arch/arm64/kernel/sys32.S +++ b/arch/arm64/kernel/sys32.S @@ -26,25 +26,6 @@ /* * System call wrappers for the AArch32 compatibility layer. */ -compat_sys_fork_wrapper: - mov x0, sp - b compat_sys_fork -ENDPROC(compat_sys_fork_wrapper) - -compat_sys_vfork_wrapper: - mov x0, sp - b compat_sys_vfork -ENDPROC(compat_sys_vfork_wrapper) - -compat_sys_execve_wrapper: - mov x3, sp - b compat_sys_execve -ENDPROC(compat_sys_execve_wrapper) - -compat_sys_clone_wrapper: - mov x5, sp - b compat_sys_clone -ENDPROC(compat_sys_clone_wrapper) compat_sys_sigreturn_wrapper: mov x0, sp diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index 906e3bd270b..6fabc1912da 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c @@ -28,43 +28,15 @@ #include <asm/cacheflush.h> #include <asm/unistd32.h> -asmlinkage int compat_sys_fork(struct pt_regs *regs) +asmlinkage int compat_sys_fork(void) { - return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL); + return do_fork(SIGCHLD, 0, current_pt_regs(), 0, NULL, NULL); } -asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tidptr, int tls_val, - int __user *child_tidptr, struct pt_regs *regs) +asmlinkage int compat_sys_vfork(void) { - if (!newsp) - newsp = regs->compat_sp; - - return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); -} - -asmlinkage int compat_sys_vfork(struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp, - regs, 0, NULL, NULL); -} - -asmlinkage int compat_sys_execve(const char __user *filenamei, - compat_uptr_t argv, compat_uptr_t envp, - struct pt_regs *regs) -{ - int error; - struct filename *filename; - - filename = getname(filenamei); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = compat_do_execve(filename->name, compat_ptr(argv), - compat_ptr(envp), regs); - putname(filename); -out: - return error; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, + current_pt_regs(), 0, NULL, NULL); } asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid, diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 17948fc7d66..ba457943a16 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -28,6 +28,7 @@ #include <linux/sched.h> #include <linux/signal.h> #include <linux/slab.h> +#include <linux/timekeeper_internal.h> #include <linux/vmalloc.h> #include <asm/cacheflush.h> @@ -222,11 +223,10 @@ struct vm_area_struct *get_gate_vma(struct mm_struct *mm) /* * Update the vDSO data page to keep in sync with kernel timekeeping. */ -void update_vsyscall(struct timespec *ts, struct timespec *wtm, - struct clocksource *clock, u32 mult) +void update_vsyscall(struct timekeeper *tk) { struct timespec xtime_coarse; - u32 use_syscall = strcmp(clock->name, "arch_sys_counter"); + u32 use_syscall = strcmp(tk->clock->name, "arch_sys_counter"); ++vdso_data->tb_seq_count; smp_wmb(); @@ -237,13 +237,13 @@ void update_vsyscall(struct timespec *ts, struct timespec *wtm, vdso_data->xtime_coarse_nsec = xtime_coarse.tv_nsec; if (!use_syscall) { - vdso_data->cs_cycle_last = clock->cycle_last; - vdso_data->xtime_clock_sec = ts->tv_sec; - vdso_data->xtime_clock_nsec = ts->tv_nsec; - vdso_data->cs_mult = mult; - vdso_data->cs_shift = clock->shift; - vdso_data->wtm_clock_sec = wtm->tv_sec; - vdso_data->wtm_clock_nsec = wtm->tv_nsec; + vdso_data->cs_cycle_last = tk->clock->cycle_last; + vdso_data->xtime_clock_sec = tk->xtime_sec; + vdso_data->xtime_clock_nsec = tk->xtime_nsec >> tk->shift; + vdso_data->cs_mult = tk->mult; + vdso_data->cs_shift = tk->shift; + vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec; + vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec; } smp_wmb(); diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index efbf7df05d3..4cd28931dba 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -80,7 +80,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) #ifdef CONFIG_ZONE_DMA32 /* 4GB maximum for 32-bit only capable devices */ max_dma32 = min(max, MAX_DMA32_PFN); - zone_size[ZONE_DMA32] = max_dma32 - min; + zone_size[ZONE_DMA32] = max(min, max_dma32) - min; #endif zone_size[ZONE_NORMAL] = max - max_dma32; diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 06e73bf665e..649aeb9acec 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -17,6 +17,8 @@ config AVR32 select GENERIC_CLOCKEVENTS select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE help AVR32 is a high-performance 32-bit RISC microprocessor core, designed for cost-sensitive embedded applications, with particular diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h index 87d8baccc60..48d71c5c898 100644 --- a/arch/avr32/include/asm/processor.h +++ b/arch/avr32/include/asm/processor.h @@ -142,9 +142,6 @@ struct task_struct; /* Free all resources held by a thread */ extern void release_thread(struct task_struct *); -/* Create a kernel thread without removing it from tasklists */ -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); - /* Return saved PC of a blocked thread */ #define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc) diff --git a/arch/avr32/include/asm/unistd.h b/arch/avr32/include/asm/unistd.h index 157b4bd3d5e..641023d1bcb 100644 --- a/arch/avr32/include/asm/unistd.h +++ b/arch/avr32/include/asm/unistd.h @@ -39,6 +39,7 @@ #define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_SYS_EXECVE /* * "Conditional" syscalls diff --git a/arch/avr32/kernel/Makefile b/arch/avr32/kernel/Makefile index 9e2c465ef3a..119a2e41def 100644 --- a/arch/avr32/kernel/Makefile +++ b/arch/avr32/kernel/Makefile @@ -7,7 +7,7 @@ extra-y := head.o vmlinux.lds obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o obj-y += syscall_table.o syscall-stubs.o irq.o obj-y += setup.o traps.o ocd.o ptrace.o -obj-y += signal.o sys_avr32.o process.o time.o +obj-y += signal.o process.o time.o obj-y += switch_to.o cpu.o obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o obj-$(CONFIG_KPROBES) += kprobes.o diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index df288418131..9899d3cc6f0 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -251,13 +251,15 @@ syscall_badsys: .global ret_from_fork ret_from_fork: call schedule_tail + mov r12, 0 + rjmp syscall_return - /* check for syscall tracing */ - get_thread_info r0 - ld.w r1, r0[TI_flags] - andl r1, _TIF_ALLWORK_MASK, COH - brne syscall_exit_work - rjmp syscall_exit_cont + .global ret_from_kernel_thread +ret_from_kernel_thread: + call schedule_tail + mov r12, r0 + mov lr, r2 /* syscall_return */ + mov pc, r1 syscall_trace_enter: pushm r8-r12 diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 1bb0a8abd79..09b894d96d6 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c @@ -69,44 +69,6 @@ void machine_restart(char *cmd) } /* - * PC is actually discarded when returning from a system call -- the - * return address must be stored in LR. This function will make sure - * LR points to do_exit before starting the thread. - * - * Also, when returning from fork(), r12 is 0, so we must copy the - * argument as well. - * - * r0 : The argument to the main thread function - * r1 : The address of do_exit - * r2 : The address of the main thread function - */ -asmlinkage extern void kernel_thread_helper(void); -__asm__(" .type kernel_thread_helper, @function\n" - "kernel_thread_helper:\n" - " mov r12, r0\n" - " mov lr, r2\n" - " mov pc, r1\n" - " .size kernel_thread_helper, . - kernel_thread_helper"); - -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.r0 = (unsigned long)arg; - regs.r1 = (unsigned long)fn; - regs.r2 = (unsigned long)do_exit; - regs.lr = (unsigned long)kernel_thread_helper; - regs.pc = (unsigned long)kernel_thread_helper; - regs.sr = MODE_SUPERVISOR; - - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, - 0, ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - -/* * Free current thread data structures etc */ void exit_thread(void) @@ -332,26 +294,31 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) } asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); +asmlinkage void syscall_return(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { - struct pt_regs *childregs; - - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1; - *childregs = *regs; - - if (user_mode(regs)) + struct pt_regs *childregs = task_pt_regs(p); + + if (unlikely(!regs)) { + memset(childregs, 0, sizeof(struct pt_regs)); + p->thread.cpu_context.r0 = arg; + p->thread.cpu_context.r1 = usp; /* fn */ + p->thread.cpu_context.r2 = syscall_return; + p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread; + childregs->sr = MODE_SUPERVISOR; + } else { + *childregs = *regs; childregs->sp = usp; - else - childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; - - childregs->r12 = 0; /* Set return value for child */ + childregs->r12 = 0; /* Set return value for child */ + p->thread.cpu_context.pc = (unsigned long)ret_from_fork; + } p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM; p->thread.cpu_context.ksp = (unsigned long)childregs; - p->thread.cpu_context.pc = (unsigned long)ret_from_fork; clear_tsk_thread_flag(p, TIF_DEBUG); if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG)) @@ -382,27 +349,6 @@ asmlinkage int sys_vfork(struct pt_regs *regs) 0, NULL, NULL); } -asmlinkage int sys_execve(const char __user *ufilename, - const char __user *const __user *uargv, - const char __user *const __user *uenvp, - struct pt_regs *regs) -{ - int error; - struct filename *filename; - - filename = getname(ufilename); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename->name, uargv, uenvp, regs); - putname(filename); - -out: - return error; -} - - /* * This function is supposed to answer the question "who called * schedule()?" diff --git a/arch/avr32/kernel/sys_avr32.c b/arch/avr32/kernel/sys_avr32.c deleted file mode 100644 index 62635a09ae3..00000000000 --- a/arch/avr32/kernel/sys_avr32.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2004-2006 Atmel Corporation - * - * 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/unistd.h> - -int kernel_execve(const char *file, - const char *const *argv, - const char *const *envp) -{ - register long scno asm("r8") = __NR_execve; - register long sc1 asm("r12") = (long)file; - register long sc2 asm("r11") = (long)argv; - register long sc3 asm("r10") = (long)envp; - - asm volatile("scall" - : "=r"(sc1) - : "r"(scno), "0"(sc1), "r"(sc2), "r"(sc3) - : "cc", "memory"); - return sc1; -} diff --git a/arch/avr32/kernel/syscall-stubs.S b/arch/avr32/kernel/syscall-stubs.S index 0447a3e2ba6..285a61b9194 100644 --- a/arch/avr32/kernel/syscall-stubs.S +++ b/arch/avr32/kernel/syscall-stubs.S @@ -50,12 +50,6 @@ __sys_vfork: mov r12, sp rjmp sys_vfork - .global __sys_execve - .type __sys_execve,@function -__sys_execve: - mov r9, sp - rjmp sys_execve - .global __sys_mmap2 .type __sys_mmap2,@function __sys_mmap2: diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S index 6eba53530d1..fc649770681 100644 --- a/arch/avr32/kernel/syscall_table.S +++ b/arch/avr32/kernel/syscall_table.S @@ -24,7 +24,7 @@ sys_call_table: .long sys_creat .long sys_link .long sys_unlink /* 10 */ - .long __sys_execve + .long sys_execve .long sys_chdir .long sys_time .long sys_mknod diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index b6f3ad5441c..ab9ff4075f4 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -45,6 +45,8 @@ config BLACKFIN select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE config GENERIC_CSUM def_bool y diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h index 4ef7cfe43ce..d0e72e9475a 100644 --- a/arch/blackfin/include/asm/processor.h +++ b/arch/blackfin/include/asm/processor.h @@ -75,8 +75,6 @@ static inline void release_thread(struct task_struct *dead_task) { } -extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags); - /* * Free current thread data structures etc.. */ diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h index 5b2a0748d7d..b4ec1bb3d5d 100644 --- a/arch/blackfin/include/asm/unistd.h +++ b/arch/blackfin/include/asm/unistd.h @@ -446,6 +446,7 @@ #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_SYS_EXECVE /* * "Conditional" syscalls diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S index f33792cc1a0..78f4f637e15 100644 --- a/arch/blackfin/kernel/entry.S +++ b/arch/blackfin/kernel/entry.S @@ -46,22 +46,16 @@ ENTRY(_ret_from_fork) SP += -12; pseudo_long_call _schedule_tail, p5; SP += 12; - r0 = [sp + PT_IPEND]; - cc = bittst(r0,1); - if cc jump .Lin_kernel; + p1 = [sp++]; + r0 = [sp++]; + cc = p1 == 0; + if cc jump .Lfork; + sp += -12; + call (p1); + sp += 12; +.Lfork: RESTORE_CONTEXT rti; -.Lin_kernel: - bitclr(r0,1); - [sp + PT_IPEND] = r0; - /* do a 'fake' RTI by jumping to [RETI] - * to avoid clearing supervisor mode in child - */ - r0 = [sp + PT_PC]; - [sp + PT_P0] = r0; - - RESTORE_ALL_SYS - jump (p0); ENDPROC(_ret_from_fork) ENTRY(_sys_vfork) diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index bb1cc721fcf..da8df0e504a 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -102,40 +102,6 @@ void cpu_idle(void) } /* - * This gets run with P1 containing the - * function to call, and R1 containing - * the "args". Note P0 is clobbered on the way here. - */ -void kernel_thread_helper(void); -__asm__(".section .text\n" - ".align 4\n" - "_kernel_thread_helper:\n\t" - "\tsp += -12;\n\t" - "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous"); - -/* - * Create a kernel thread. - */ -pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.r1 = (unsigned long)arg; - regs.p1 = (unsigned long)fn; - regs.pc = (unsigned long)kernel_thread_helper; - regs.orig_p0 = -1; - /* Set bit 2 to tell ret_from_fork we should be returning to kernel - mode. */ - regs.ipend = 0x8002; - __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):); - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, - NULL); -} -EXPORT_SYMBOL(kernel_thread); - -/* * Do necessary setup to start up a newly executed thread. * * pass the data segment into user programs if it exists, @@ -193,38 +159,31 @@ copy_thread(unsigned long clone_flags, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; + unsigned long *v; childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; - *childregs = *regs; - childregs->r0 = 0; + v = ((unsigned long *)childregs) - 2; + if (unlikely(!regs)) { + memset(childregs, 0, sizeof(struct pt_regs)); + v[0] = usp; + v[1] = topstk; + childregs->orig_p0 = -1; + childregs->ipend = 0x8000; + __asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):); + p->thread.usp = 0; + } else { + *childregs = *regs; + childregs->r0 = 0; + p->thread.usp = usp; + v[0] = v[1] = 0; + } - p->thread.usp = usp; - p->thread.ksp = (unsigned long)childregs; + p->thread.ksp = (unsigned long)v; p->thread.pc = (unsigned long)ret_from_fork; return 0; } -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(const char __user *name, - const char __user *const __user *argv, - const char __user *const __user *envp) -{ - int error; - struct filename *filename; - struct pt_regs *regs = (struct pt_regs *)((&name) + 6); - - filename = getname(name); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - return error; - error = do_execve(filename->name, argv, envp, regs); - putname(filename); - return error; -} - unsigned long get_wchan(struct task_struct *p) { unsigned long fp, pc; diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 1c3d2c5bb0b..4a38c68e2dd 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -530,61 +530,6 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ jump .Lsyscall_really_exit; ENDPROC(_trap) -ENTRY(_kernel_execve) - link SIZEOF_PTREGS; - p0 = sp; - r3 = SIZEOF_PTREGS / 4; - r4 = 0(x); -.Lclear_regs: - [p0++] = r4; - r3 += -1; - cc = r3 == 0; - if !cc jump .Lclear_regs (bp); - - p0 = sp; - sp += -16; - [sp + 12] = p0; - pseudo_long_call _do_execve, p5; - SP += 16; - cc = r0 == 0; - if ! cc jump .Lexecve_failed; - /* Success. Copy our temporary pt_regs to the top of the kernel - * stack and do a normal exception return. - */ - r1 = sp; - r0 = (-KERNEL_STACK_SIZE) (x); - r1 = r1 & r0; - p2 = r1; - p3 = [p2]; - r0 = KERNEL_STACK_SIZE - 4 (z); - p1 = r0; - p1 = p1 + p2; - - p0 = fp; - r4 = [p0--]; - r3 = SIZEOF_PTREGS / 4; -.Lcopy_regs: - r4 = [p0--]; - [p1--] = r4; - r3 += -1; - cc = r3 == 0; - if ! cc jump .Lcopy_regs (bp); - - r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); - p1 = r0; - p1 = p1 + p2; - sp = p1; - r0 = syscfg; - [SP + PT_SYSCFG] = r0; - [p3 + (TASK_THREAD + THREAD_KSP)] = sp; - - RESTORE_CONTEXT; - rti; -.Lexecve_failed: - unlink; - rts; -ENDPROC(_kernel_execve) - ENTRY(_system_call) /* Store IPEND */ p2.l = lo(IPEND); diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig index aee1b569ee6..66eab3703c7 100644 --- a/arch/c6x/Kconfig +++ b/arch/c6x/Kconfig @@ -18,6 +18,7 @@ config C6X select OF_EARLY_FLATTREE select GENERIC_CLOCKEVENTS select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE select MODULES_USE_ELF_RELA config MMU diff --git a/arch/c6x/include/uapi/asm/unistd.h b/arch/c6x/include/uapi/asm/unistd.h index 4ff747d12da..625beafb9cd 100644 --- a/arch/c6x/include/uapi/asm/unistd.h +++ b/arch/c6x/include/uapi/asm/unistd.h @@ -14,7 +14,6 @@ * more details. */ -#define __ARCH_WANT_KERNEL_EXECVE #define __ARCH_WANT_SYS_EXECVE /* Use the standard ABI for syscalls. */ diff --git a/arch/c6x/kernel/entry.S b/arch/c6x/kernel/entry.S index 5449c36018f..75f6f36472c 100644 --- a/arch/c6x/kernel/entry.S +++ b/arch/c6x/kernel/entry.S @@ -413,19 +413,9 @@ ENTRY(ret_from_kernel_thread) 0: B .S2 B10 /* call fn */ LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */ - MVKL .S2 sys_exit,B11 - MVKH .S2 sys_exit,B11 - ADDKPC .S2 0f,B3,1 -0: - BNOP .S2 B11,5 /* jump to sys_exit */ + ADDKPC .S2 ret_from_fork_2,B3,3 ENDPROC(ret_from_kernel_thread) -ENTRY(ret_from_kernel_execve) - GET_THREAD_INFO A12 - BNOP .S2 syscall_exit,4 - ADD .D2X A4,-8,SP -ENDPROC(ret_from_kernel_execve) - ;; ;; These are the interrupt handlers, responsible for calling __do_IRQ() ;; int6 is used for syscalls (see _system_call entry) diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index a67244473a3..81b59d18867 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -49,6 +49,8 @@ config CRIS select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 select GENERIC_CMOS_UPDATE select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE config HZ int diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S index 592fbe9dfb6..897bba67bf7 100644 --- a/arch/cris/arch-v10/kernel/entry.S +++ b/arch/cris/arch-v10/kernel/entry.S @@ -35,6 +35,7 @@ .globl system_call .globl ret_from_intr .globl ret_from_fork + .globl ret_from_kernel_thread .globl resume .globl multiple_interrupt .globl hwbreakpoint @@ -81,7 +82,14 @@ ret_from_fork: jsr schedule_tail ba ret_from_sys_call nop - + +ret_from_kernel_thread: + jsr schedule_tail + move.d $r2, $r10 ; argument is here + jsr $r1 ; call the payload + moveq 0, $r9 ; no syscall restarts, TYVM... + ba ret_from_sys_call + ret_from_intr: ;; check for resched if preemptive kernel or if we're going back to user-mode ;; this test matches the user_regs(regs) macro @@ -586,13 +594,6 @@ _ugdb_handle_breakpoint: ba do_sigtrap ; SIGTRAP the offending process. pop $dccr ; Restore dccr in delay slot. - .global kernel_execve -kernel_execve: - move.d __NR_execve, $r9 - break 13 - ret - nop - .data hw_bp_trigs: diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c index 15ac7150371..1d6458287f3 100644 --- a/arch/cris/arch-v10/kernel/process.c +++ b/arch/cris/arch-v10/kernel/process.c @@ -17,6 +17,7 @@ #include <arch/svinto.h> #include <linux/init.h> #include <arch/system.h> +#include <asm/ptrace.h> #ifdef CONFIG_ETRAX_GPIO void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */ @@ -81,31 +82,6 @@ unsigned long thread_saved_pc(struct task_struct *t) return task_pt_regs(t)->irp; } -static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) -{ - fn(arg); - do_exit(-1); /* Should never be called, return bad exit value */ -} - -/* - * Create a kernel thread - */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - /* Don't use r10 since that is set to 0 in copy_thread */ - regs.r11 = (unsigned long)fn; - regs.r12 = (unsigned long)arg; - regs.irp = (unsigned long)kernel_thread_helper; - regs.dccr = 1 << I_DCCR_BITNR; - - /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -} - /* setup the child's kernel stack with a pt_regs and switch_stack on it. * it will be un-nested during _resume and _ret_from_sys_call when the * new thread is scheduled. @@ -115,29 +91,35 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) * */ asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { - struct pt_regs * childregs; - struct switch_stack *swstack; + struct pt_regs *childregs = task_pt_regs(p); + struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1; /* put the pt_regs structure at the end of the new kernel stack page and fix it up * remember that the task_struct doubles as the kernel stack for the task */ - childregs = task_pt_regs(p); - + if (unlikely(p->flags & PF_KTHREAD)) { + memset(swstack, 0, + sizeof(struct switch_stack) + sizeof(struct pt_regs)); + swstack->r1 = usp; + swstack->r2 = arg; + childregs->dccr = 1 << I_DCCR_BITNR; + swstack->return_ip = (unsigned long) ret_from_kernel_thread; + p->thread.ksp = (unsigned long) swstack; + p->thread.usp = 0; + return 0; + } *childregs = *regs; /* struct copy of pt_regs */ - - p->set_child_tid = p->clear_child_tid = NULL; childregs->r10 = 0; /* child returns 0 after a fork/clone */ - - /* put the switch stack right below the pt_regs */ - swstack = ((struct switch_stack *)childregs) - 1; + /* put the switch stack right below the pt_regs */ swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */ @@ -147,7 +129,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, /* fix the user-mode stackpointer */ - p->thread.usp = usp; + p->thread.usp = usp; /* and the kernel-mode one */ @@ -161,68 +143,28 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, return 0; } -/* - * Be aware of the "magic" 7th argument in the four system-calls below. - * They need the latest stackframe, which is put as the 7th argument by - * entry.S. The previous arguments are dummies or actually used, but need - * to be defined to reach the 7th argument. - * - * N.B.: Another method to get the stackframe is to use current_regs(). But - * it returns the latest stack-frame stacked when going from _user mode_ and - * some of these (at least sys_clone) are called from kernel-mode sometimes - * (for example during kernel_thread, above) and thus cannot use it. Thus, - * to be sure not to get any surprises, we use the method for the other calls - * as well. - */ - -asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, - struct pt_regs *regs) +asmlinkage int sys_fork(void) { - return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); + return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* if newusp is 0, we just grab the old usp */ /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, - int* parent_tid, int* child_tid, long mof, long srp, - struct pt_regs *regs) + int* parent_tid, int* child_tid) { if (!newusp) newusp = rdusp(); - return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); + return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid); } /* vfork is a system call in i386 because of register-pressure - maybe * we can remove it and handle it in libc but we put it here until then. */ -asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, - struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); -} - -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(const char *fname, - const char *const *argv, - const char *const *envp, - long r13, long mof, long srp, - struct pt_regs *regs) +asmlinkage int sys_vfork(void) { - int error; - struct filename *filename; - - filename = getname(fname); - error = PTR_ERR(filename); - - if (IS_ERR(filename)) - goto out; - error = do_execve(filename->name, argv, envp, regs); - putname(filename); - out: - return error; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } unsigned long get_wchan(struct task_struct *p) diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index c3ea4694fba..faa644111fe 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -31,6 +31,7 @@ .globl system_call .globl ret_from_intr .globl ret_from_fork + .globl ret_from_kernel_thread .globl resume .globl multiple_interrupt .globl nmi_interrupt @@ -84,6 +85,18 @@ ret_from_fork: nop .size ret_from_fork, . - ret_from_fork + .type ret_from_kernel_thread,@function +ret_from_kernel_thread: + jsr schedule_tail + nop + move.d $r2, $r10 + jsr $r1 + nop + moveq 0, $r9 ; no syscall restarts, TYVM... + ba ret_from_sys_call + nop + .size ret_from_kernel_thread, . - ret_from_kernel_thread + .type ret_from_intr,@function ret_from_intr: ;; Check for resched if preemptive kernel, or if we're going back to @@ -531,15 +544,6 @@ _ugdb_handle_exception: ba do_sigtrap ; SIGTRAP the offending process. move.d [$sp+], $r0 ; Restore R0 in delay slot. - .global kernel_execve - .type kernel_execve,@function -kernel_execve: - move.d __NR_execve, $r9 - break 13 - ret - nop - .size kernel_execve, . - kernel_execve - .data .section .rodata,"a" diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c index 4e999224635..fe465401b6e 100644 --- a/arch/cris/arch-v32/kernel/process.c +++ b/arch/cris/arch-v32/kernel/process.c @@ -16,6 +16,7 @@ #include <hwregs/reg_map.h> #include <hwregs/timer_defs.h> #include <hwregs/intr_vect_defs.h> +#include <asm/ptrace.h> extern void stop_watchdog(void); @@ -94,31 +95,6 @@ unsigned long thread_saved_pc(struct task_struct *t) return task_pt_regs(t)->erp; } -static void -kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) -{ - fn(arg); - do_exit(-1); /* Should never be called, return bad exit value. */ -} - -/* Create a kernel thread. */ -int -kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - /* Don't use r10 since that is set to 0 in copy_thread. */ - regs.r11 = (unsigned long) fn; - regs.r12 = (unsigned long) arg; - regs.erp = (unsigned long) kernel_thread_helper; - regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); - - /* Create the new process. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -} - /* * Setup the child's kernel stack with a pt_regs and call switch_stack() on it. * It will be unnested during _resume and _ret_from_sys_call when the new thread @@ -129,23 +105,33 @@ kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */ extern asmlinkage void ret_from_fork(void); +extern asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { - struct pt_regs *childregs; - struct switch_stack *swstack; + struct pt_regs *childregs = task_pt_regs(p); + struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1; /* * Put the pt_regs structure at the end of the new kernel stack page and * fix it up. Note: the task_struct doubles as the kernel stack for the * task. */ - childregs = task_pt_regs(p); + if (unlikely(p->flags & PF_KTHREAD)) { + memset(swstack, 0, + sizeof(struct switch_stack) + sizeof(struct pt_regs)); + swstack->r1 = usp; + swstack->r2 = arg; + childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); + swstack->return_ip = (unsigned long) ret_from_kernel_thread; + p->thread.ksp = (unsigned long) swstack; + p->thread.usp = 0; + return 0; + } *childregs = *regs; /* Struct copy of pt_regs. */ - p->set_child_tid = p->clear_child_tid = NULL; childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ /* Set a new TLS ? @@ -156,7 +142,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, } /* Put the switch stack right below the pt_regs. */ - swstack = ((struct switch_stack *) childregs) - 1; /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */ swstack->r9 = 0; @@ -174,35 +159,21 @@ copy_thread(unsigned long clone_flags, unsigned long usp, return 0; } -/* - * Be aware of the "magic" 7th argument in the four system-calls below. - * They need the latest stackframe, which is put as the 7th argument by - * entry.S. The previous arguments are dummies or actually used, but need - * to be defined to reach the 7th argument. - * - * N.B.: Another method to get the stackframe is to use current_regs(). But - * it returns the latest stack-frame stacked when going from _user mode_ and - * some of these (at least sys_clone) are called from kernel-mode sometimes - * (for example during kernel_thread, above) and thus cannot use it. Thus, - * to be sure not to get any surprises, we use the method for the other calls - * as well. - */ asmlinkage int -sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, - struct pt_regs *regs) +sys_fork(void) { - return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); + return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid, - unsigned long tls, long srp, struct pt_regs *regs) + unsigned long tls) { if (!newusp) newusp = rdusp(); - return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); + return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid); } /* @@ -210,32 +181,9 @@ sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child * we can remove it and handle it in libc but we put it here until then. */ asmlinkage int -sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, - struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); -} - -/* sys_execve() executes a new program. */ -asmlinkage int -sys_execve(const char *fname, - const char *const *argv, - const char *const *envp, long r13, long mof, long srp, - struct pt_regs *regs) +sys_vfork(void) { - int error; - struct filename *filename; - - filename = getname(fname); - error = PTR_ERR(filename); - - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename->name, argv, envp, regs); - putname(filename); - out: - return error; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } unsigned long diff --git a/arch/cris/include/asm/processor.h b/arch/cris/include/asm/processor.h index ef4e1bc3efc..675823f70c0 100644 --- a/arch/cris/include/asm/processor.h +++ b/arch/cris/include/asm/processor.h @@ -49,8 +49,6 @@ struct task_struct; #define task_pt_regs(task) user_regs(task_thread_info(task)) #define current_regs() task_pt_regs(current) -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - unsigned long get_wchan(struct task_struct *p); #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) diff --git a/arch/cris/include/asm/unistd.h b/arch/cris/include/asm/unistd.h index 51873a446f8..f181d1fc763 100644 --- a/arch/cris/include/asm/unistd.h +++ b/arch/cris/include/asm/unistd.h @@ -371,6 +371,7 @@ #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_SYS_EXECVE /* * "Conditional" syscalls diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c index 7ac000f6a88..5868cee20eb 100644 --- a/arch/cris/kernel/crisksyms.c +++ b/arch/cris/kernel/crisksyms.c @@ -30,7 +30,6 @@ extern void __negdi2(void); extern void iounmap(volatile void * __iomem); /* Platform dependent support */ -EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL(loops_per_usec); diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index b7412504f08..df2eb4bd9fa 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig @@ -13,6 +13,7 @@ config FRV select GENERIC_CPU_DEVICES select ARCH_WANT_IPC_PARSE_VERSION select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE config ZONE_DMA bool diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile index 6ae3254da01..636d5bbcd53 100644 --- a/arch/frv/boot/Makefile +++ b/arch/frv/boot/Makefile @@ -17,6 +17,8 @@ PARAMS_PHYS = 0x0207c000 INITRD_PHYS = 0x02180000 INITRD_VIRT = 0x02180000 +OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment + # # If you don't define ZRELADDR above, # then it defaults to ZTEXTADDR @@ -32,18 +34,18 @@ Image: $(obj)/Image targets: $(obj)/Image $(obj)/Image: vmlinux FORCE - $(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@ + $(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@ #$(obj)/Image: $(CONFIGURE) $(SYSTEM) -# $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@ +# $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@ bzImage: zImage zImage: $(CONFIGURE) compressed/$(LINUX) - $(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@ + $(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@ bootpImage: bootp/bootp - $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ + $(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@ compressed/$(LINUX): $(LINUX) dep @$(MAKE) -C compressed $(LINUX) diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h index 266a5b25a0c..2358634cacc 100644 --- a/arch/frv/include/asm/unistd.h +++ b/arch/frv/include/asm/unistd.h @@ -30,7 +30,6 @@ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_SYS_EXECVE -#define __ARCH_WANT_KERNEL_EXECVE /* * "Conditional" syscalls diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index 00273296031..dfcd263c051 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -867,13 +867,8 @@ ret_from_fork: ret_from_kernel_thread: lddi.p @(gr28,#REG_GR(8)),gr20 call schedule_tail - or.p gr20,gr20,gr8 - calll @(gr21,gr0) - bra sys_exit - - .globl ret_from_kernel_execve -ret_from_kernel_execve: - ori gr28,0,sp + calll.p @(gr21,gr0) + or gr20,gr20,gr8 bra __syscall_exit ################################################################################################### @@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt: subicc gr5,#0,gr0,icc0 beq icc0,#0,__entry_return_direct -__entry_preempt_need_resched: - ldi @(gr15,#TI_FLAGS),gr4 - andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 - beq icc0,#1,__entry_return_direct - - setlos #PREEMPT_ACTIVE,gr5 - sti gr5,@(gr15,#TI_FLAGS) - - andi gr23,#~PSR_PIL,gr23 - movgs gr23,psr - - call schedule - sti gr0,@(gr15,#TI_PRE_COUNT) - - movsg psr,gr23 - ori gr23,#PSR_PIL_14,gr23 - movgs gr23,psr - bra __entry_preempt_need_resched -#else - bra __entry_return_direct + subcc gr0,gr0,gr0,icc2 /* set Z and clear C */ + call preempt_schedule_irq #endif + bra __entry_return_direct ############################################################################### diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 655d90d20bb..7e33215f1d8 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags, childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); + /* set up the userspace frame (the only place that the USP is stored) */ + *childregs = *__kernel_frame0_ptr; + p->set_child_tid = p->clear_child_tid = NULL; p->thread.frame = childregs; @@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags, p->thread.frame0 = childregs; if (unlikely(!regs)) { - memset(childregs, 0, sizeof(struct pt_regs)); childregs->gr9 = usp; /* function */ childregs->gr8 = arg; - chilregs->psr = PSR_S; p->thread.pc = (unsigned long) ret_from_kernel_thread; save_user_regs(p->thread.user); return 0; diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 1f1e5efb338..b8993c87d3d 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -112,9 +112,11 @@ char __initdata redboot_command_line[COMMAND_LINE_SIZE]; #ifdef CONFIG_PM #define __pminit #define __pminitdata +#define __pminitconst #else #define __pminit __init #define __pminitdata __initdata +#define __pminitconst __initconst #endif struct clock_cmode { diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c index e47857f889b..b99c2a7cc7a 100644 --- a/arch/frv/mb93090-mb00/pci-dma-nommu.c +++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c @@ -11,6 +11,7 @@ #include <linux/types.h> #include <linux/slab.h> +#include <linux/export.h> #include <linux/dma-mapping.h> #include <linux/list.h> #include <linux/pci.h> diff --git a/arch/h8300/include/asm/cache.h b/arch/h8300/include/asm/cache.h index c6350283649..05887a1d80e 100644 --- a/arch/h8300/include/asm/cache.h +++ b/arch/h8300/include/asm/cache.h @@ -2,7 +2,8 @@ #define __ARCH_H8300_CACHE_H /* bytes per L1 cache line */ -#define L1_CACHE_BYTES 4 +#define L1_CACHE_SHIFT 2 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) /* m68k-elf-gcc 2.95.2 doesn't like these */ diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index 0744f7d7b1f..e418803b6c8 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig @@ -31,6 +31,8 @@ config HEXAGON select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS_BROADCAST select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE ---help--- Qualcomm Hexagon is a processor architecture designed for high performance and low power across a wide variety of applications. diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild index 3364b6966d2..3bfa9b30f44 100644 --- a/arch/hexagon/include/asm/Kbuild +++ b/arch/hexagon/include/asm/Kbuild @@ -1,8 +1,5 @@ -include include/asm-generic/Kbuild.asm -header-y += registers.h header-y += ucontext.h -header-y += user.h generic-y += auxvec.h generic-y += bug.h diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h index 3e258043337..468fbb0781c 100644 --- a/arch/hexagon/include/asm/atomic.h +++ b/arch/hexagon/include/asm/atomic.h @@ -1,7 +1,7 @@ /* * Atomic operations for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify diff --git a/arch/hexagon/include/asm/barrier.h b/arch/hexagon/include/asm/barrier.h index a4ed6e26cb1..1041a8e70ce 100644 --- a/arch/hexagon/include/asm/barrier.h +++ b/arch/hexagon/include/asm/barrier.h @@ -1,7 +1,7 @@ /* * Memory barrier definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/bitops.h b/arch/hexagon/include/asm/bitops.h index 4caa649ad78..9b1e4afbab3 100644 --- a/arch/hexagon/include/asm/bitops.h +++ b/arch/hexagon/include/asm/bitops.h @@ -1,7 +1,7 @@ /* * Bit operations for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify diff --git a/arch/hexagon/include/asm/cache.h b/arch/hexagon/include/asm/cache.h index 0f01de2eb4a..f4ca594fdf8 100644 --- a/arch/hexagon/include/asm/cache.h +++ b/arch/hexagon/include/asm/cache.h @@ -1,7 +1,7 @@ /* * Cache definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/cacheflush.h b/arch/hexagon/include/asm/cacheflush.h index 6865c1be927..49e0896ec24 100644 --- a/arch/hexagon/include/asm/cacheflush.h +++ b/arch/hexagon/include/asm/cacheflush.h @@ -1,7 +1,7 @@ /* * Cache flush operations for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/checksum.h b/arch/hexagon/include/asm/checksum.h index 3ce4ecd44f8..46ec8a7fd65 100644 --- a/arch/hexagon/include/asm/checksum.h +++ b/arch/hexagon/include/asm/checksum.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/cmpxchg.h b/arch/hexagon/include/asm/cmpxchg.h index c5f9527e1df..9e7802911a5 100644 --- a/arch/hexagon/include/asm/cmpxchg.h +++ b/arch/hexagon/include/asm/cmpxchg.h @@ -1,7 +1,7 @@ /* * xchg/cmpxchg operations for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify diff --git a/arch/hexagon/include/asm/delay.h b/arch/hexagon/include/asm/delay.h index 9ab12e9a872..53079719d66 100644 --- a/arch/hexagon/include/asm/delay.h +++ b/arch/hexagon/include/asm/delay.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h index 233ed3d2d25..85e9935660c 100644 --- a/arch/hexagon/include/asm/dma-mapping.h +++ b/arch/hexagon/include/asm/dma-mapping.h @@ -1,7 +1,7 @@ /* * DMA operations for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/dma.h b/arch/hexagon/include/asm/dma.h index da6d2f61a93..9e34ff49f3b 100644 --- a/arch/hexagon/include/asm/dma.h +++ b/arch/hexagon/include/asm/dma.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/elf.h b/arch/hexagon/include/asm/elf.h index 82b499621e0..1ba4b3bff5e 100644 --- a/arch/hexagon/include/asm/elf.h +++ b/arch/hexagon/include/asm/elf.h @@ -1,7 +1,7 @@ /* * ELF definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/exec.h b/arch/hexagon/include/asm/exec.h index 350e6d497d4..c32b2132614 100644 --- a/arch/hexagon/include/asm/exec.h +++ b/arch/hexagon/include/asm/exec.h @@ -1,7 +1,7 @@ /* * Process execution related definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/fixmap.h b/arch/hexagon/include/asm/fixmap.h index b27f4941645..b75b6bf4269 100644 --- a/arch/hexagon/include/asm/fixmap.h +++ b/arch/hexagon/include/asm/fixmap.h @@ -1,7 +1,7 @@ /* * Fixmap support for Hexagon - enough to support highmem features * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/hexagon_vm.h b/arch/hexagon/include/asm/hexagon_vm.h index 182cb9d5476..c144bee6cab 100644 --- a/arch/hexagon/include/asm/hexagon_vm.h +++ b/arch/hexagon/include/asm/hexagon_vm.h @@ -1,7 +1,7 @@ /* * Declarations for to Hexagon Virtal Machine. * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/intrinsics.h b/arch/hexagon/include/asm/intrinsics.h index 1c02186d2e9..ca587737fb2 100644 --- a/arch/hexagon/include/asm/intrinsics.h +++ b/arch/hexagon/include/asm/intrinsics.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h index b3acc2cc71b..e527cfeff5b 100644 --- a/arch/hexagon/include/asm/io.h +++ b/arch/hexagon/include/asm/io.h @@ -1,7 +1,7 @@ /* * IO definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/irq.h b/arch/hexagon/include/asm/irq.h index ded8c15cf3e..51661db389d 100644 --- a/arch/hexagon/include/asm/irq.h +++ b/arch/hexagon/include/asm/irq.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/irqflags.h b/arch/hexagon/include/asm/irqflags.h index ec152365541..e5fd9492d60 100644 --- a/arch/hexagon/include/asm/irqflags.h +++ b/arch/hexagon/include/asm/irqflags.h @@ -1,7 +1,7 @@ /* * IRQ support for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/kgdb.h b/arch/hexagon/include/asm/kgdb.h index 9e8779702f1..32a6fb66944 100644 --- a/arch/hexagon/include/asm/kgdb.h +++ b/arch/hexagon/include/asm/kgdb.h @@ -1,7 +1,7 @@ /* * arch/hexagon/include/asm/kgdb.h - Hexagon KGDB Support * - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/linkage.h b/arch/hexagon/include/asm/linkage.h index a00b85f680b..31b4cbe7e58 100644 --- a/arch/hexagon/include/asm/linkage.h +++ b/arch/hexagon/include/asm/linkage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/mem-layout.h b/arch/hexagon/include/asm/mem-layout.h index 72e5dcda79f..af16e977c55 100644 --- a/arch/hexagon/include/asm/mem-layout.h +++ b/arch/hexagon/include/asm/mem-layout.h @@ -1,7 +1,7 @@ /* * Memory layout definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/mmu.h b/arch/hexagon/include/asm/mmu.h index 30a5d8d2659..2288b19fd0f 100644 --- a/arch/hexagon/include/asm/mmu.h +++ b/arch/hexagon/include/asm/mmu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/mmu_context.h b/arch/hexagon/include/asm/mmu_context.h index b4fe5a5411b..d423d2e73c3 100644 --- a/arch/hexagon/include/asm/mmu_context.h +++ b/arch/hexagon/include/asm/mmu_context.h @@ -1,7 +1,7 @@ /* * MM context support for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/module.h b/arch/hexagon/include/asm/module.h index 72ba494e6d7..6b4323acef4 100644 --- a/arch/hexagon/include/asm/module.h +++ b/arch/hexagon/include/asm/module.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/page.h b/arch/hexagon/include/asm/page.h index edd97626c48..692adc21342 100644 --- a/arch/hexagon/include/asm/page.h +++ b/arch/hexagon/include/asm/page.h @@ -1,7 +1,7 @@ /* * Page management definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/perf_event.h b/arch/hexagon/include/asm/perf_event.h index 8b8526b491c..430978b1de3 100644 --- a/arch/hexagon/include/asm/perf_event.h +++ b/arch/hexagon/include/asm/perf_event.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/pgalloc.h b/arch/hexagon/include/asm/pgalloc.h index 13443c77513..679bf6d6648 100644 --- a/arch/hexagon/include/asm/pgalloc.h +++ b/arch/hexagon/include/asm/pgalloc.h @@ -1,7 +1,7 @@ /* * Page table support for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/pgtable.h b/arch/hexagon/include/asm/pgtable.h index ca619bf225e..20d55f69fe5 100644 --- a/arch/hexagon/include/asm/pgtable.h +++ b/arch/hexagon/include/asm/pgtable.h @@ -1,7 +1,7 @@ /* * Page table support for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h index e8ea459002a..6dd5d370686 100644 --- a/arch/hexagon/include/asm/processor.h +++ b/arch/hexagon/include/asm/processor.h @@ -1,7 +1,7 @@ /* * Process/processor support for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -34,7 +34,6 @@ struct task_struct; /* this is defined in arch/process.c */ -extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern unsigned long thread_saved_pc(struct task_struct *tsk); extern void start_thread(struct pt_regs *, unsigned long, unsigned long); diff --git a/arch/hexagon/include/asm/smp.h b/arch/hexagon/include/asm/smp.h index 87c869a6a89..2b9b974e095 100644 --- a/arch/hexagon/include/asm/smp.h +++ b/arch/hexagon/include/asm/smp.h @@ -1,7 +1,7 @@ /* * SMP definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/spinlock.h b/arch/hexagon/include/asm/spinlock.h index 168a920485a..12ca4ebc033 100644 --- a/arch/hexagon/include/asm/spinlock.h +++ b/arch/hexagon/include/asm/spinlock.h @@ -1,7 +1,7 @@ /* * Spinlock support for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify diff --git a/arch/hexagon/include/asm/spinlock_types.h b/arch/hexagon/include/asm/spinlock_types.h index 99b5a7575c2..7a906b5214a 100644 --- a/arch/hexagon/include/asm/spinlock_types.h +++ b/arch/hexagon/include/asm/spinlock_types.h @@ -1,7 +1,7 @@ /* * Spinlock support for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/string.h b/arch/hexagon/include/asm/string.h index f4489c15942..7d37f47a1d0 100644 --- a/arch/hexagon/include/asm/string.h +++ b/arch/hexagon/include/asm/string.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/suspend.h b/arch/hexagon/include/asm/suspend.h index 089dd826879..18b44b557fb 100644 --- a/arch/hexagon/include/asm/suspend.h +++ b/arch/hexagon/include/asm/suspend.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/switch_to.h b/arch/hexagon/include/asm/switch_to.h index 28ca0dfb606..96745e7b3e3 100644 --- a/arch/hexagon/include/asm/switch_to.h +++ b/arch/hexagon/include/asm/switch_to.h @@ -1,7 +1,7 @@ /* * Task switching definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/syscall.h b/arch/hexagon/include/asm/syscall.h index 3e7d61d38d9..fb0e9d48faa 100644 --- a/arch/hexagon/include/asm/syscall.h +++ b/arch/hexagon/include/asm/syscall.h @@ -1,7 +1,7 @@ /* * Syscall support for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/thread_info.h b/arch/hexagon/include/asm/thread_info.h index e4a0aad69cb..f7c32406a71 100644 --- a/arch/hexagon/include/asm/thread_info.h +++ b/arch/hexagon/include/asm/thread_info.h @@ -1,7 +1,7 @@ /* * Thread support for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/time.h b/arch/hexagon/include/asm/time.h index 081b82cac9a..deda170c03b 100644 --- a/arch/hexagon/include/asm/time.h +++ b/arch/hexagon/include/asm/time.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/timer-regs.h b/arch/hexagon/include/asm/timer-regs.h index d80db239a7b..79912b8c1e5 100644 --- a/arch/hexagon/include/asm/timer-regs.h +++ b/arch/hexagon/include/asm/timer-regs.h @@ -1,7 +1,7 @@ /* * Timer support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/timex.h b/arch/hexagon/include/asm/timex.h index b11c62b23f3..f63fe132f07 100644 --- a/arch/hexagon/include/asm/timex.h +++ b/arch/hexagon/include/asm/timex.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/tlb.h b/arch/hexagon/include/asm/tlb.h index 473abde01d6..2f00772cc08 100644 --- a/arch/hexagon/include/asm/tlb.h +++ b/arch/hexagon/include/asm/tlb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/tlbflush.h b/arch/hexagon/include/asm/tlbflush.h index b89a9025122..62d95a9705c 100644 --- a/arch/hexagon/include/asm/tlbflush.h +++ b/arch/hexagon/include/asm/tlbflush.h @@ -1,7 +1,7 @@ /* * TLB flush support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/traps.h b/arch/hexagon/include/asm/traps.h index 6a407f6e5e2..ec11285012c 100644 --- a/arch/hexagon/include/asm/traps.h +++ b/arch/hexagon/include/asm/traps.h @@ -1,7 +1,7 @@ /* * Trap support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/uaccess.h b/arch/hexagon/include/asm/uaccess.h index 7e706eadbf0..e4127e4d6a5 100644 --- a/arch/hexagon/include/asm/uaccess.h +++ b/arch/hexagon/include/asm/uaccess.h @@ -1,7 +1,7 @@ /* * User memory access support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/vdso.h b/arch/hexagon/include/asm/vdso.h index 2d95cbba357..ed08e6c6886 100644 --- a/arch/hexagon/include/asm/vdso.h +++ b/arch/hexagon/include/asm/vdso.h @@ -1,7 +1,7 @@ /* * vDSO implementation for Hexagon * - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/vm_fault.h b/arch/hexagon/include/asm/vm_fault.h index cacda36ef5d..9b0e9c50ced 100644 --- a/arch/hexagon/include/asm/vm_fault.h +++ b/arch/hexagon/include/asm/vm_fault.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/vm_mmu.h b/arch/hexagon/include/asm/vm_mmu.h index 580462de5cc..9a94de7969b 100644 --- a/arch/hexagon/include/asm/vm_mmu.h +++ b/arch/hexagon/include/asm/vm_mmu.h @@ -1,7 +1,7 @@ /* * Hexagon VM page table entry definitions * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/uapi/asm/Kbuild b/arch/hexagon/include/uapi/asm/Kbuild index baebb3da1d4..c31706c3863 100644 --- a/arch/hexagon/include/uapi/asm/Kbuild +++ b/arch/hexagon/include/uapi/asm/Kbuild @@ -1,3 +1,15 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm +header-y += bitsperlong.h +header-y += byteorder.h +header-y += kvm_para.h +header-y += param.h +header-y += ptrace.h +header-y += registers.h +header-y += setup.h +header-y += sigcontext.h +header-y += signal.h +header-y += swab.h +header-y += unistd.h +header-y += user.h diff --git a/arch/hexagon/include/asm/bitsperlong.h b/arch/hexagon/include/uapi/asm/bitsperlong.h index 2701cae3426..4a658151383 100644 --- a/arch/hexagon/include/asm/bitsperlong.h +++ b/arch/hexagon/include/uapi/asm/bitsperlong.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/byteorder.h b/arch/hexagon/include/uapi/asm/byteorder.h index 0e19b9fe4ca..e31f3f7d9a4 100644 --- a/arch/hexagon/include/asm/byteorder.h +++ b/arch/hexagon/include/uapi/asm/byteorder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/kvm_para.h b/arch/hexagon/include/uapi/asm/kvm_para.h index 14fab8f0b95..14fab8f0b95 100644 --- a/arch/hexagon/include/asm/kvm_para.h +++ b/arch/hexagon/include/uapi/asm/kvm_para.h diff --git a/arch/hexagon/include/asm/param.h b/arch/hexagon/include/uapi/asm/param.h index 285344bbd03..5cec8c0417f 100644 --- a/arch/hexagon/include/asm/param.h +++ b/arch/hexagon/include/uapi/asm/param.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/ptrace.h b/arch/hexagon/include/uapi/asm/ptrace.h index 3d2f607cd63..1ffce0c6ee0 100644 --- a/arch/hexagon/include/asm/ptrace.h +++ b/arch/hexagon/include/uapi/asm/ptrace.h @@ -1,7 +1,7 @@ /* * Ptrace definitions for the Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,4 +32,8 @@ extern int regs_query_register_offset(const char *name); extern const char *regs_query_register_name(unsigned int offset); +#define current_pt_regs() \ + ((struct pt_regs *) \ + ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) + #endif diff --git a/arch/hexagon/include/asm/registers.h b/arch/hexagon/include/uapi/asm/registers.h index 4dd741be855..c20406f63b5 100644 --- a/arch/hexagon/include/asm/registers.h +++ b/arch/hexagon/include/uapi/asm/registers.h @@ -1,23 +1,8 @@ /* * Register definitions for the Hexagon architecture - * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. */ + #ifndef _ASM_REGISTERS_H #define _ASM_REGISTERS_H diff --git a/arch/hexagon/include/asm/setup.h b/arch/hexagon/include/uapi/asm/setup.h index 3b754c50bc0..e48285e4af9 100644 --- a/arch/hexagon/include/asm/setup.h +++ b/arch/hexagon/include/uapi/asm/setup.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/sigcontext.h b/arch/hexagon/include/uapi/asm/sigcontext.h index ce6dcd99522..b6ba5369ccc 100644 --- a/arch/hexagon/include/asm/sigcontext.h +++ b/arch/hexagon/include/uapi/asm/sigcontext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/signal.h b/arch/hexagon/include/uapi/asm/signal.h index 471c0562e17..939556817d3 100644 --- a/arch/hexagon/include/asm/signal.h +++ b/arch/hexagon/include/uapi/asm/signal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/swab.h b/arch/hexagon/include/uapi/asm/swab.h index 99cf0be3fb8..9069e9247a2 100644 --- a/arch/hexagon/include/asm/swab.h +++ b/arch/hexagon/include/uapi/asm/swab.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/include/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h index c0d5565030a..26b2e0f909c 100644 --- a/arch/hexagon/include/asm/unistd.h +++ b/arch/hexagon/include/uapi/asm/unistd.h @@ -1,7 +1,7 @@ /* * Syscall support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,5 +27,6 @@ */ #define sys_mmap2 sys_mmap_pgoff +#define __ARCH_WANT_SYS_EXECVE #include <asm-generic/unistd.h> diff --git a/arch/hexagon/include/asm/user.h b/arch/hexagon/include/uapi/asm/user.h index 3a55078543d..cef13ee1413 100644 --- a/arch/hexagon/include/asm/user.h +++ b/arch/hexagon/include/uapi/asm/user.h @@ -1,21 +1,3 @@ -/* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - #ifndef HEXAGON_ASM_USER_H #define HEXAGON_ASM_USER_H diff --git a/arch/hexagon/kernel/asm-offsets.c b/arch/hexagon/kernel/asm-offsets.c index 89ffa514611..2d5e84d3b00 100644 --- a/arch/hexagon/kernel/asm-offsets.c +++ b/arch/hexagon/kernel/asm-offsets.c @@ -5,7 +5,7 @@ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000 MIPS Technologies, Inc. * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c index 2b48751aa5f..65c7bdcf565 100644 --- a/arch/hexagon/kernel/dma.c +++ b/arch/hexagon/kernel/dma.c @@ -1,7 +1,7 @@ /* * DMA implementation for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/head.S b/arch/hexagon/kernel/head.S index 8e6b819125a..d859402c73b 100644 --- a/arch/hexagon/kernel/head.S +++ b/arch/hexagon/kernel/head.S @@ -1,7 +1,7 @@ /* * Early kernel startup code for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c index 7f189247180..32b1379d687 100644 --- a/arch/hexagon/kernel/hexagon_ksyms.c +++ b/arch/hexagon/kernel/hexagon_ksyms.c @@ -1,7 +1,7 @@ /* * Export of symbols defined in assembly files and/or libgcc. * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/irq_cpu.c b/arch/hexagon/kernel/irq_cpu.c index d4416a1a431..85883e1fdc1 100644 --- a/arch/hexagon/kernel/irq_cpu.c +++ b/arch/hexagon/kernel/irq_cpu.c @@ -1,7 +1,7 @@ /* * First-level interrupt controller model for Hexagon. * - * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/kgdb.c b/arch/hexagon/kernel/kgdb.c index fe4aa1bcca5..34464537064 100644 --- a/arch/hexagon/kernel/kgdb.c +++ b/arch/hexagon/kernel/kgdb.c @@ -1,7 +1,7 @@ /* * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support * - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/module.c b/arch/hexagon/kernel/module.c index 61a76bae366..477d07a5646 100644 --- a/arch/hexagon/kernel/module.c +++ b/arch/hexagon/kernel/module.c @@ -1,7 +1,7 @@ /* * Kernel module loader for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c index af51de63b83..cfbc52bd522 100644 --- a/arch/hexagon/kernel/process.c +++ b/arch/hexagon/kernel/process.c @@ -1,7 +1,7 @@ /* * Process creation support for Hexagon * - * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -26,33 +26,6 @@ #include <linux/slab.h> /* - * Kernel thread creation. The desired kernel function is "wrapped" - * in the kernel_thread_helper function, which does cleanup - * afterwards. - */ -static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *)) -{ - do_exit(fn(arg)); -} - -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - /* - * Yes, we're exploting illicit knowledge of the ABI here. - */ - regs.r00 = (unsigned long) arg; - regs.r01 = (unsigned long) fn; - pt_set_elr(®s, (unsigned long)kernel_thread_helper); - pt_set_kmode(®s); - - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - -/* * Program thread launch. Often defined as a macro in processor.h, * but we're shooting for a small footprint and it's not an inner-loop * performance-critical operation. @@ -114,7 +87,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) * Copy architecture-specific thread state */ int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, struct task_struct *p, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct thread_info *ti = task_thread_info(p); @@ -125,61 +98,50 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) - sizeof(*childregs)); - memcpy(childregs, regs, sizeof(*childregs)); ti->regs = childregs; /* * Establish kernel stack pointer and initial PC for new thread + * Note that unlike the usual situation, we do not copy the + * parent's callee-saved here; those are in pt_regs and whatever + * we leave here will be overridden on return to userland. */ ss = (struct hexagon_switch_stack *) ((unsigned long) childregs - sizeof(*ss)); ss->lr = (unsigned long)ret_from_fork; p->thread.switch_sp = ss; - - /* If User mode thread, set pt_reg stack pointer as per parameter */ - if (user_mode(childregs)) { - pt_set_rte_sp(childregs, usp); - - /* Child sees zero return value */ - childregs->r00 = 0; - - /* - * The clone syscall has the C signature: - * int [r0] clone(int flags [r0], - * void *child_frame [r1], - * void *parent_tid [r2], - * void *child_tid [r3], - * void *thread_control_block [r4]); - * ugp is used to provide TLS support. - */ - if (clone_flags & CLONE_SETTLS) - childregs->ugp = childregs->r04; - - /* - * Parent sees new pid -- not necessary, not even possible at - * this point in the fork process - * Might also want to set things like ti->addr_limit - */ - } else { - /* - * If kernel thread, resume stack is kernel stack base. - * Note that this is pointer arithmetic on pt_regs * - */ - pt_set_rte_sp(childregs, (unsigned long)(childregs + 1)); - /* - * We need the current thread_info fast path pointer - * set up in pt_regs. The register to be used is - * parametric for assembler code, but the mechanism - * doesn't drop neatly into C. Needs to be fixed. - */ - childregs->THREADINFO_REG = (unsigned long) ti; + if (unlikely(p->flags & PF_KTHREAD)) { + memset(childregs, 0, sizeof(struct pt_regs)); + /* r24 <- fn, r25 <- arg */ + ss->r2524 = usp | ((u64)arg << 32); + pt_set_kmode(childregs); + return 0; } + memcpy(childregs, regs, sizeof(*childregs)); + ss->r2524 = 0; + + pt_set_rte_sp(childregs, usp); + + /* Child sees zero return value */ + childregs->r00 = 0; + + /* + * The clone syscall has the C signature: + * int [r0] clone(int flags [r0], + * void *child_frame [r1], + * void *parent_tid [r2], + * void *child_tid [r3], + * void *thread_control_block [r4]); + * ugp is used to provide TLS support. + */ + if (clone_flags & CLONE_SETTLS) + childregs->ugp = childregs->r04; /* - * thread_info pointer is pulled out of task_struct "stack" - * field on switch_to. + * Parent sees new pid -- not necessary, not even possible at + * this point in the fork process + * Might also want to set things like ti->addr_limit */ - p->stack = (void *)ti; return 0; } diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c index 96c3b2c4dba..670b1b0bee6 100644 --- a/arch/hexagon/kernel/ptrace.c +++ b/arch/hexagon/kernel/ptrace.c @@ -1,7 +1,7 @@ /* * Ptrace support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/reset.c b/arch/hexagon/kernel/reset.c index 4d72fc58e9b..6aeabc962b3 100644 --- a/arch/hexagon/kernel/reset.c +++ b/arch/hexagon/kernel/reset.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c index 1202f78d25c..94a38783500 100644 --- a/arch/hexagon/kernel/setup.c +++ b/arch/hexagon/kernel/setup.c @@ -1,7 +1,7 @@ /* * Arch related setup for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c index 1ea16bec7b9..fe0d1373165 100644 --- a/arch/hexagon/kernel/signal.c +++ b/arch/hexagon/kernel/signal.c @@ -1,7 +1,7 @@ /* * Signal support for Hexagon processor * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -249,14 +249,14 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) */ asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { - struct pt_regs *regs = current_thread_info()->regs; + struct pt_regs *regs = current_pt_regs(); return do_sigaltstack(uss, uoss, regs->r29); } asmlinkage int sys_rt_sigreturn(void) { - struct pt_regs *regs = current_thread_info()->regs; + struct pt_regs *regs = current_pt_regs(); struct rt_sigframe __user *frame; sigset_t blocked; diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c index 149fbefc1a4..8e095dffd07 100644 --- a/arch/hexagon/kernel/smp.c +++ b/arch/hexagon/kernel/smp.c @@ -1,7 +1,7 @@ /* * SMP support for Hexagon * - * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/stacktrace.c b/arch/hexagon/kernel/stacktrace.c index 11c597b2ac5..f94918b449a 100644 --- a/arch/hexagon/kernel/stacktrace.c +++ b/arch/hexagon/kernel/stacktrace.c @@ -1,7 +1,7 @@ /* * Stacktrace support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c index 25a9bfe3445..d2cc3270af3 100644 --- a/arch/hexagon/kernel/syscall.c +++ b/arch/hexagon/kernel/syscall.c @@ -1,7 +1,7 @@ /* * Hexagon system calls * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -35,55 +35,13 @@ * See signal.c for signal-related system call wrappers. */ -asmlinkage int sys_execve(char __user *ufilename, - const char __user *const __user *argv, - const char __user *const __user *envp) -{ - struct pt_regs *pregs = current_thread_info()->regs; - struct filename *filename; - int retval; - - filename = getname(ufilename); - retval = PTR_ERR(filename); - if (IS_ERR(filename)) - return retval; - - retval = do_execve(filename->name, argv, envp, pregs); - putname(filename); - - return retval; -} - asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, unsigned long parent_tidp, unsigned long child_tidp) { - struct pt_regs *pregs = current_thread_info()->regs; + struct pt_regs *pregs = current_pt_regs(); if (!newsp) newsp = pregs->SP; return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp, (int __user *)child_tidp); } - -/* - * Do a system call from the kernel, so as to have a proper pt_regs - * and recycle the sys_execvpe infrustructure. - */ -int kernel_execve(const char *filename, - const char *const argv[], const char *const envp[]) -{ - register unsigned long __a0 asm("r0") = (unsigned long) filename; - register unsigned long __a1 asm("r1") = (unsigned long) argv; - register unsigned long __a2 asm("r2") = (unsigned long) envp; - int retval; - - __asm__ volatile( - " R6 = #%4;\n" - " trap0(#1);\n" - " %0 = R0;\n" - : "=r" (retval) - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve) - ); - - return retval; -} diff --git a/arch/hexagon/kernel/syscalltab.c b/arch/hexagon/kernel/syscalltab.c index c550f4177ab..7024b1ddc08 100644 --- a/arch/hexagon/kernel/syscalltab.c +++ b/arch/hexagon/kernel/syscalltab.c @@ -1,7 +1,7 @@ /* * System call table for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c index 36ba6418571..9903fad997f 100644 --- a/arch/hexagon/kernel/time.c +++ b/arch/hexagon/kernel/time.c @@ -1,7 +1,7 @@ /* * Time related functions for Hexagon architecture * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/topology.c b/arch/hexagon/kernel/topology.c index ba447518443..352f27e809f 100644 --- a/arch/hexagon/kernel/topology.c +++ b/arch/hexagon/kernel/topology.c @@ -1,7 +1,7 @@ /* * CPU topology for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/trampoline.S b/arch/hexagon/kernel/trampoline.S index 06c36c036b9..18110a9056b 100644 --- a/arch/hexagon/kernel/trampoline.S +++ b/arch/hexagon/kernel/trampoline.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/traps.c b/arch/hexagon/kernel/traps.c index f08857d0715..a41eeb8eeaa 100644 --- a/arch/hexagon/kernel/traps.c +++ b/arch/hexagon/kernel/traps.c @@ -1,7 +1,7 @@ /* * Kernel traps/events for Hexagon processor * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/vdso.c b/arch/hexagon/kernel/vdso.c index 5d39f42f708..0bf5a87e4d0 100644 --- a/arch/hexagon/kernel/vdso.c +++ b/arch/hexagon/kernel/vdso.c @@ -1,7 +1,7 @@ /* * vDSO implementation for Hexagon * - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S index 5b99066cbc8..425e50c694f 100644 --- a/arch/hexagon/kernel/vm_entry.S +++ b/arch/hexagon/kernel/vm_entry.S @@ -1,7 +1,7 @@ /* * Event entry/exit for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -266,4 +266,8 @@ _K_enter_machcheck: .globl ret_from_fork ret_from_fork: call schedule_tail + P0 = cmp.eq(R24, #0); + if P0 jump return_from_syscall + R0 = R25; + callr R24 jump return_from_syscall diff --git a/arch/hexagon/kernel/vm_events.c b/arch/hexagon/kernel/vm_events.c index 591fc1b6863..9b5a4a295a6 100644 --- a/arch/hexagon/kernel/vm_events.c +++ b/arch/hexagon/kernel/vm_events.c @@ -1,7 +1,7 @@ /* * Mostly IRQ support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/vm_init_segtable.S b/arch/hexagon/kernel/vm_init_segtable.S index aebb35b6465..80967f2192b 100644 --- a/arch/hexagon/kernel/vm_init_segtable.S +++ b/arch/hexagon/kernel/vm_init_segtable.S @@ -1,7 +1,7 @@ /* * Initial page table for Linux kernel under Hexagon VM, * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/vm_ops.S b/arch/hexagon/kernel/vm_ops.S index 24d7fcac4ff..9fb77b3f6cf 100644 --- a/arch/hexagon/kernel/vm_ops.S +++ b/arch/hexagon/kernel/vm_ops.S @@ -1,7 +1,7 @@ /* * Hexagon VM instruction support * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/vm_switch.S b/arch/hexagon/kernel/vm_switch.S index 0decf2f58e3..62c6df91b3b 100644 --- a/arch/hexagon/kernel/vm_switch.S +++ b/arch/hexagon/kernel/vm_switch.S @@ -1,7 +1,7 @@ /* * Context switch support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/vm_vectors.S b/arch/hexagon/kernel/vm_vectors.S index 97a4b50b00d..620f42cc582 100644 --- a/arch/hexagon/kernel/vm_vectors.S +++ b/arch/hexagon/kernel/vm_vectors.S @@ -1,7 +1,7 @@ /* * Event jump tables * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S index 071d3c30edf..14e793f6abb 100644 --- a/arch/hexagon/kernel/vmlinux.lds.S +++ b/arch/hexagon/kernel/vmlinux.lds.S @@ -1,7 +1,7 @@ /* * Linker script for Hexagon kernel * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/lib/checksum.c b/arch/hexagon/lib/checksum.c index 93005522d52..8169f78a46a 100644 --- a/arch/hexagon/lib/checksum.c +++ b/arch/hexagon/lib/checksum.c @@ -1,7 +1,7 @@ /* * Checksum functions for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/lib/io.c b/arch/hexagon/lib/io.c index 8ae47ba0e70..885c9626d5e 100644 --- a/arch/hexagon/lib/io.c +++ b/arch/hexagon/lib/io.c @@ -1,7 +1,7 @@ /* * I/O access functions for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/lib/memcpy.S b/arch/hexagon/lib/memcpy.S index 2101c339566..81c561c4b4d 100644 --- a/arch/hexagon/lib/memcpy.S +++ b/arch/hexagon/lib/memcpy.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * * This program is free software; you can redistribute it and/or modify diff --git a/arch/hexagon/lib/memset.S b/arch/hexagon/lib/memset.S index 26d961439ab..9341889ea3f 100644 --- a/arch/hexagon/lib/memset.S +++ b/arch/hexagon/lib/memset.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Code Aurora Forum. All rights reserved. + * Copyright (c) 2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/cache.c b/arch/hexagon/mm/cache.c index c5cf6ee2758..fe14ccf2856 100644 --- a/arch/hexagon/mm/cache.c +++ b/arch/hexagon/mm/cache.c @@ -1,7 +1,7 @@ /* * Cache management functions for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/copy_from_user.S b/arch/hexagon/mm/copy_from_user.S index 8eb1d4d61a3..7fc94f3e664 100644 --- a/arch/hexagon/mm/copy_from_user.S +++ b/arch/hexagon/mm/copy_from_user.S @@ -1,7 +1,7 @@ /* * User memory copy functions for kernel * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/copy_to_user.S b/arch/hexagon/mm/copy_to_user.S index cb9740ed9e7..0cfbcc09d1d 100644 --- a/arch/hexagon/mm/copy_to_user.S +++ b/arch/hexagon/mm/copy_to_user.S @@ -1,7 +1,7 @@ /* * User memory copying routines for the Hexagon Kernel * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/copy_user_template.S b/arch/hexagon/mm/copy_user_template.S index 08d7d7b23da..254d8cc766b 100644 --- a/arch/hexagon/mm/copy_user_template.S +++ b/arch/hexagon/mm/copy_user_template.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/init.c b/arch/hexagon/mm/init.c index b57d741750b..69ffcfd2879 100644 --- a/arch/hexagon/mm/init.c +++ b/arch/hexagon/mm/init.c @@ -1,7 +1,7 @@ /* * Memory subsystem initialization for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/ioremap.c b/arch/hexagon/mm/ioremap.c index 3a37bc3b011..5905fd5f97f 100644 --- a/arch/hexagon/mm/ioremap.c +++ b/arch/hexagon/mm/ioremap.c @@ -1,7 +1,7 @@ /* * I/O remap functions for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/pgalloc.c b/arch/hexagon/mm/pgalloc.c index b175e2d42b8..19760a4611d 100644 --- a/arch/hexagon/mm/pgalloc.c +++ b/arch/hexagon/mm/pgalloc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/strnlen_user.S b/arch/hexagon/mm/strnlen_user.S index 5c6a16c7c72..0eecb7a768f 100644 --- a/arch/hexagon/mm/strnlen_user.S +++ b/arch/hexagon/mm/strnlen_user.S @@ -1,7 +1,7 @@ /* * User string length functions for kernel * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/uaccess.c b/arch/hexagon/mm/uaccess.c index e748108b47a..34127261c2b 100644 --- a/arch/hexagon/mm/uaccess.c +++ b/arch/hexagon/mm/uaccess.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c index 513b74cb397..308ef0ce648 100644 --- a/arch/hexagon/mm/vm_fault.c +++ b/arch/hexagon/mm/vm_fault.c @@ -1,7 +1,7 @@ /* * Memory fault handling for Hexagon * - * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/hexagon/mm/vm_tlb.c b/arch/hexagon/mm/vm_tlb.c index c6ff4157546..9647d00cb76 100644 --- a/arch/hexagon/mm/vm_tlb.c +++ b/arch/hexagon/mm/vm_tlb.c @@ -1,7 +1,7 @@ /* * Hexagon Virtual Machine TLB functions * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 3279646120e..67060046812 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -42,6 +42,8 @@ config IA64 select GENERIC_TIME_VSYSCALL_OLD select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE default y help The Itanium Processor Family is Intel's 64-bit successor to diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index 4a159da2363..dd02f09b6ed 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@ -1,3 +1,4 @@ generic-y += clkdev.h generic-y += exec.h +generic-y += kvm_para.h diff --git a/arch/ia64/include/asm/kvm_para.h b/arch/ia64/include/asm/kvm_para.h deleted file mode 100644 index 47c00f91043..00000000000 --- a/arch/ia64/include/asm/kvm_para.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - */ -#ifndef __IA64_KVM_PARA_H -#define __IA64_KVM_PARA_H - -#include <uapi/asm/kvm_para.h> - - -static inline unsigned int kvm_arch_para_features(void) -{ - return 0; -} - -static inline bool kvm_check_and_clear_guest_paused(void) -{ - return false; -} - -#endif diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h index 944152a5091..e0a899a1a8a 100644 --- a/arch/ia64/include/asm/processor.h +++ b/arch/ia64/include/asm/processor.h @@ -340,22 +340,6 @@ struct task_struct; */ #define release_thread(dead_task) -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE 1: Only a kernel-only process (ie the swapper or direct - * descendants who haven't done an "execve()") should use this: it - * will work within a system call from a "real" process, but the - * process memory space will not be free'd until both the parent and - * the child have exited. - * - * NOTE 2: This MUST NOT be an inlined function. Otherwise, we get - * into trouble in init/main.c when the child thread returns to - * do_basic_setup() and the timing is such that free_initmem() has - * been called already. - */ -extern pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags); - /* Get wait channel for task P. */ extern unsigned long get_wchan (struct task_struct *p); diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index 8b3ff2f5b86..1574bca8613 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h @@ -29,6 +29,7 @@ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_SYS_EXECVE #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) diff --git a/arch/ia64/include/uapi/asm/Kbuild b/arch/ia64/include/uapi/asm/Kbuild index 30cafac9370..1b3f5eb5fcd 100644 --- a/arch/ia64/include/uapi/asm/Kbuild +++ b/arch/ia64/include/uapi/asm/Kbuild @@ -1,6 +1,8 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm +generic-y += kvm_para.h + header-y += auxvec.h header-y += bitsperlong.h header-y += break.h diff --git a/arch/ia64/include/uapi/asm/kvm_para.h b/arch/ia64/include/uapi/asm/kvm_para.h deleted file mode 100644 index e69de29bb2d..00000000000 --- a/arch/ia64/include/uapi/asm/kvm_para.h +++ /dev/null diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 1ccbe12a4d8..940a6726362 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -61,14 +61,13 @@ ENTRY(ia64_execve) * Allocate 8 input registers since ptrace() may clobber them */ .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) - alloc loc1=ar.pfs,8,2,4,0 + alloc loc1=ar.pfs,8,2,3,0 mov loc0=rp .body mov out0=in0 // filename ;; // stop bit between alloc and call mov out1=in1 // argv mov out2=in2 // envp - add out3=16,sp // regs br.call.sptk.many rp=sys_execve .ret0: cmp4.ge p6,p7=r8,r0 @@ -76,7 +75,6 @@ ENTRY(ia64_execve) sxt4 r8=r8 // return 64-bit result ;; stf.spill [sp]=f0 -(p6) cmp.ne pKStk,pUStk=r0,r0 // a successful execve() lands us in user-mode... mov rp=loc0 (p6) mov ar.pfs=r0 // clear ar.pfs on success (p7) br.ret.sptk.many rp @@ -484,19 +482,6 @@ GLOBAL_ENTRY(prefetch_stack) br.ret.sptk.many rp END(prefetch_stack) -GLOBAL_ENTRY(kernel_execve) - rum psr.ac - mov r15=__NR_execve // put syscall number in place - break __BREAK_SYSCALL - br.ret.sptk.many rp -END(kernel_execve) - -GLOBAL_ENTRY(clone) - mov r15=__NR_clone // put syscall number in place - break __BREAK_SYSCALL - br.ret.sptk.many rp -END(clone) - /* * Invoke a system call, but do some tracing before and after the call. * We MUST preserve the current register frame throughout this routine @@ -600,6 +585,27 @@ GLOBAL_ENTRY(ia64_strace_leave_kernel) .ret4: br.cond.sptk ia64_leave_kernel END(ia64_strace_leave_kernel) +ENTRY(call_payload) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0) + /* call the kernel_thread payload; fn is in r4, arg - in r5 */ + alloc loc1=ar.pfs,0,3,1,0 + mov loc0=rp + mov loc2=gp + mov out0=r5 // arg + ld8 r14 = [r4], 8 // fn.address + ;; + mov b6 = r14 + ld8 gp = [r4] // fn.gp + ;; + br.call.sptk.many rp=b6 // fn(arg) +.ret12: mov gp=loc2 + mov rp=loc0 + mov ar.pfs=loc1 + /* ... and if it has returned, we are going to userland */ + cmp.ne pKStk,pUStk=r0,r0 + br.ret.sptk.many rp +END(call_payload) + GLOBAL_ENTRY(ia64_ret_from_clone) PT_REGS_UNWIND_INFO(0) { /* @@ -616,6 +622,7 @@ GLOBAL_ENTRY(ia64_ret_from_clone) br.call.sptk.many rp=ia64_invoke_schedule_tail } .ret8: +(pKStk) br.call.sptk.many rp=call_payload adds r2=TI_FLAGS+IA64_TASK_SIZE,r13 ;; ld4 r2=[r2] diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 629a250f7c1..4738ff7bd66 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -1093,19 +1093,6 @@ GLOBAL_ENTRY(cycle_to_cputime) END(cycle_to_cputime) #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ -GLOBAL_ENTRY(start_kernel_thread) - .prologue - .save rp, r0 // this is the end of the call-chain - .body - alloc r2 = ar.pfs, 0, 0, 2, 0 - mov out0 = r9 - mov out1 = r11;; - br.call.sptk.many rp = kernel_thread_helper;; - mov out0 = r8 - br.call.sptk.many rp = sys_exit;; -1: br.sptk.few 1b // not reached -END(start_kernel_thread) - #ifdef CONFIG_IA64_BRL_EMU /* diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 35e106f2ed1..25543a295ad 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -401,64 +401,15 @@ copy_thread(unsigned long clone_flags, struct pt_regs *child_ptregs; int retval = 0; -#ifdef CONFIG_SMP - /* - * For SMP idle threads, fork_by_hand() calls do_fork with - * NULL regs. - */ - if (!regs) - return 0; -#endif - - stack = ((struct switch_stack *) regs) - 1; - child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; child_stack = (struct switch_stack *) child_ptregs - 1; - /* copy parent's switch_stack & pt_regs to child: */ - memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); - rbs = (unsigned long) current + IA64_RBS_OFFSET; child_rbs = (unsigned long) p + IA64_RBS_OFFSET; - rbs_size = stack->ar_bspstore - rbs; - - /* copy the parent's register backing store to the child: */ - memcpy((void *) child_rbs, (void *) rbs, rbs_size); - - if (likely(user_mode(child_ptregs))) { - if (clone_flags & CLONE_SETTLS) - child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ - if (user_stack_base) { - child_ptregs->r12 = user_stack_base + user_stack_size - 16; - child_ptregs->ar_bspstore = user_stack_base; - child_ptregs->ar_rnat = 0; - child_ptregs->loadrs = 0; - } - } else { - /* - * Note: we simply preserve the relative position of - * the stack pointer here. There is no need to - * allocate a scratch area here, since that will have - * been taken care of by the caller of sys_clone() - * already. - */ - child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */ - child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */ - } - child_stack->ar_bspstore = child_rbs + rbs_size; - child_stack->b0 = (unsigned long) &ia64_ret_from_clone; /* copy parts of thread_struct: */ p->thread.ksp = (unsigned long) child_stack - 16; - /* stop some PSR bits from being inherited. - * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() - * therefore we must specify them explicitly here and not include them in - * IA64_PSR_BITS_TO_CLEAR. - */ - child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) - & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); - /* * NOTE: The calling convention considers all floating point * registers in the high partition (fph) to be scratch. Since @@ -480,8 +431,66 @@ copy_thread(unsigned long clone_flags, # define THREAD_FLAGS_TO_SET 0 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | THREAD_FLAGS_TO_SET); + ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ + if (unlikely(p->flags & PF_KTHREAD)) { + if (unlikely(!user_stack_base)) { + /* fork_idle() called us */ + return 0; + } + memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack)); + child_stack->r4 = user_stack_base; /* payload */ + child_stack->r5 = user_stack_size; /* argument */ + /* + * Preserve PSR bits, except for bits 32-34 and 37-45, + * which we can't read. + */ + child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; + /* mark as valid, empty frame */ + child_ptregs->cr_ifs = 1UL << 63; + child_stack->ar_fpsr = child_ptregs->ar_fpsr + = ia64_getreg(_IA64_REG_AR_FPSR); + child_stack->pr = (1 << PRED_KERNEL_STACK); + child_stack->ar_bspstore = child_rbs; + child_stack->b0 = (unsigned long) &ia64_ret_from_clone; + + /* stop some PSR bits from being inherited. + * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() + * therefore we must specify them explicitly here and not include them in + * IA64_PSR_BITS_TO_CLEAR. + */ + child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) + & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); + + return 0; + } + stack = ((struct switch_stack *) regs) - 1; + /* copy parent's switch_stack & pt_regs to child: */ + memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); + + /* copy the parent's register backing store to the child: */ + rbs_size = stack->ar_bspstore - rbs; + memcpy((void *) child_rbs, (void *) rbs, rbs_size); + if (clone_flags & CLONE_SETTLS) + child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ + if (user_stack_base) { + child_ptregs->r12 = user_stack_base + user_stack_size - 16; + child_ptregs->ar_bspstore = user_stack_base; + child_ptregs->ar_rnat = 0; + child_ptregs->loadrs = 0; + } + child_stack->ar_bspstore = child_rbs + rbs_size; + child_stack->b0 = (unsigned long) &ia64_ret_from_clone; + + /* stop some PSR bits from being inherited. + * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() + * therefore we must specify them explicitly here and not include them in + * IA64_PSR_BITS_TO_CLEAR. + */ + child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) + & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); + #ifdef CONFIG_PERFMON if (current->thread.pfm_context) pfm_inherit(p, child_ptregs); @@ -608,57 +617,6 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst) return 1; /* f0-f31 are always valid so we always return 1 */ } -long -sys_execve (const char __user *filename, - const char __user *const __user *argv, - const char __user *const __user *envp, - struct pt_regs *regs) -{ - struct filename *fname; - int error; - - fname = getname(filename); - error = PTR_ERR(fname); - if (IS_ERR(fname)) - goto out; - error = do_execve(fname->name, argv, envp, regs); - putname(fname); -out: - return error; -} - -pid_t -kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) -{ - extern void start_kernel_thread (void); - unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread; - struct { - struct switch_stack sw; - struct pt_regs pt; - } regs; - - memset(®s, 0, sizeof(regs)); - regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */ - regs.pt.r1 = helper_fptr[1]; /* set GP */ - regs.pt.r9 = (unsigned long) fn; /* 1st argument */ - regs.pt.r11 = (unsigned long) arg; /* 2nd argument */ - /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */ - regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; - regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */ - regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR); - regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET; - regs.sw.pr = (1 << PRED_KERNEL_STACK); - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - -/* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */ -int -kernel_thread_helper (int (*fn)(void *), void *arg) -{ - return (*fn)(arg); -} - /* * Flush thread state. This is called when a thread does an execve(). */ diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index acd5b68e887..082e383c1b6 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -637,7 +637,6 @@ mem_init (void) high_memory = __va(max_low_pfn * PAGE_SIZE); - reset_zone_present_pages(); for_each_online_pgdat(pgdat) if (pgdat->bdata->node_bootmem_map) totalram_pages += free_all_bootmem_node(pgdat); diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index f807721e19a..5183f43a2cf 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig @@ -15,6 +15,8 @@ config M32R select GENERIC_ATOMIC64 select ARCH_USES_GETTIMEOFFSET select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE config SBUS bool diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h index da17253b573..5767367550c 100644 --- a/arch/m32r/include/asm/processor.h +++ b/arch/m32r/include/asm/processor.h @@ -118,11 +118,6 @@ struct mm_struct; /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); -/* - * create a kernel thread without removing it from tasklists - */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - /* Copy and release all segment info associated with a VM */ extern void copy_segments(struct task_struct *p, struct mm_struct * mm); extern void release_segments(struct mm_struct * mm); diff --git a/arch/m32r/include/asm/ptrace.h b/arch/m32r/include/asm/ptrace.h index 4313aa62b51..c4432f1fb2c 100644 --- a/arch/m32r/include/asm/ptrace.h +++ b/arch/m32r/include/asm/ptrace.h @@ -139,6 +139,8 @@ extern void withdraw_debug_trap(struct pt_regs *regs); #define task_pt_regs(task) \ ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1) +#define current_pt_regs() ((struct pt_regs *) \ + ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) #endif /* __KERNEL */ diff --git a/arch/m32r/include/asm/unistd.h b/arch/m32r/include/asm/unistd.h index d5e66a48078..b27bdcbc7c2 100644 --- a/arch/m32r/include/asm/unistd.h +++ b/arch/m32r/include/asm/unistd.h @@ -352,6 +352,7 @@ #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_SYS_EXECVE #define __IGNORE_lchown #define __IGNORE_setuid diff --git a/arch/m32r/kernel/entry.S b/arch/m32r/kernel/entry.S index 225412bc227..0c01543f10c 100644 --- a/arch/m32r/kernel/entry.S +++ b/arch/m32r/kernel/entry.S @@ -125,6 +125,15 @@ and \reg, sp .endm +ENTRY(ret_from_kernel_thread) + pop r0 + bl schedule_tail + GET_THREAD_INFO(r8) + ld r0, R0(r8) + ld r1, R1(r8) + jl r1 + bra syscall_exit + ENTRY(ret_from_fork) pop r0 bl schedule_tail diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index e7366276ef3..62c713f5694 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -165,41 +165,6 @@ void show_regs(struct pt_regs * regs) } /* - * Create a kernel thread - */ - -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. - */ -static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg) -{ - fn(arg); - do_exit(-1); -} - -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof (regs)); - regs.r1 = (unsigned long)fn; - regs.r2 = (unsigned long)arg; - - regs.bpc = (unsigned long)kernel_thread_helper; - - regs.psw = M32R_PSW_BIE; - - /* Ok, create the new process. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, - NULL); -} - -/* * Free current thread data structures etc.. */ void exit_thread(void) @@ -227,29 +192,35 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) } int copy_thread(unsigned long clone_flags, unsigned long spu, - unsigned long unused, struct task_struct *tsk, struct pt_regs *regs) + unsigned long arg, struct task_struct *tsk, struct pt_regs *regs) { struct pt_regs *childregs = task_pt_regs(tsk); extern void ret_from_fork(void); - - /* Copy registers */ - *childregs = *regs; - - childregs->spu = spu; - childregs->r0 = 0; /* Child gets zero as return value */ - regs->r0 = tsk->pid; + extern void ret_from_kernel_thread(void); + + if (unlikely(tsk->flags & PF_KTHREAD)) { + memset(childregs, 0, sizeof(struct pt_regs)); + childregs->psw = M32R_PSW_BIE; + childregs->r1 = spu; /* fn */ + childregs->r0 = arg; + tsk->thread.lr = (unsigned long)ret_from_kernel_thread; + } else { + /* Copy registers */ + *childregs = *regs; + childregs->spu = spu; + childregs->r0 = 0; /* Child gets zero as return value */ + tsk->thread.lr = (unsigned long)ret_from_fork; + } tsk->thread.sp = (unsigned long)childregs; - tsk->thread.lr = (unsigned long)ret_from_fork; return 0; } -asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2, - unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, - struct pt_regs regs) +asmlinkage int sys_fork(void) { #ifdef CONFIG_MMU - return do_fork(SIGCHLD, regs.spu, ®s, 0, NULL, NULL); + struct pt_regs *regs = current_pt_regs(); + return do_fork(SIGCHLD, regs->spu, regs, 0, NULL, NULL); #else return -EINVAL; #endif /* CONFIG_MMU */ @@ -257,14 +228,13 @@ asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2, asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, unsigned long parent_tidptr, - unsigned long child_tidptr, - unsigned long r4, unsigned long r5, unsigned long r6, - struct pt_regs regs) + unsigned long child_tidptr) { + struct pt_regs *regs = current_pt_regs(); if (!newsp) - newsp = regs.spu; + newsp = regs->spu; - return do_fork(clone_flags, newsp, ®s, 0, + return do_fork(clone_flags, newsp, regs, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr); } @@ -278,38 +248,14 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, * do not have enough call-clobbered registers to hold all * the information you need. */ -asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2, - unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, - struct pt_regs regs) +asmlinkage int sys_vfork(void) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, ®s, 0, + struct pt_regs *regs = current_pt_regs(); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->spu, regs, 0, NULL, NULL); } /* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(const char __user *ufilename, - const char __user *const __user *uargv, - const char __user *const __user *uenvp, - unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, struct pt_regs regs) -{ - int error; - struct filename *filename; - - filename = getname(ufilename); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename->name, uargv, uenvp, ®s); - putname(filename); -out: - return error; -} - -/* * These bracket the sleeping functions.. */ #define first_sched ((unsigned long) scheduling_functions_start_here) diff --git a/arch/m32r/kernel/sys_m32r.c b/arch/m32r/kernel/sys_m32r.c index d841fb6cc70..c3fdd632fba 100644 --- a/arch/m32r/kernel/sys_m32r.c +++ b/arch/m32r/kernel/sys_m32r.c @@ -88,24 +88,3 @@ asmlinkage int sys_cachectl(char *addr, int nbytes, int op) /* Not implemented yet. */ return -ENOSYS; } - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - register long __scno __asm__ ("r7") = __NR_execve; - register long __arg3 __asm__ ("r2") = (long)(envp); - register long __arg2 __asm__ ("r1") = (long)(argv); - register long __res __asm__ ("r0") = (long)(filename); - __asm__ __volatile__ ( - "trap #" SYSCALL_VECTOR "|| nop" - : "=r" (__res) - : "r" (__scno), "0" (__res), "r" (__arg2), - "r" (__arg3) - : "memory"); - return __res; -} diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index e7c161433ea..953a7ba5d05 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -16,6 +16,7 @@ config M68K select ARCH_WANT_IPC_PARSE_VERSION select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_REL select MODULES_USE_ELF_RELA diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index ecb540810ab..88fa3ac86fa 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -1,5 +1,3 @@ -include include/asm-generic/Kbuild.asm -header-y += cachectl.h generic-y += bitsperlong.h generic-y += clkdev.h diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h index 5e08b597f01..0f717045bdd 100644 --- a/arch/m68k/include/asm/ptrace.h +++ b/arch/m68k/include/asm/ptrace.h @@ -1,82 +1,10 @@ #ifndef _M68K_PTRACE_H #define _M68K_PTRACE_H -#define PT_D1 0 -#define PT_D2 1 -#define PT_D3 2 -#define PT_D4 3 -#define PT_D5 4 -#define PT_D6 5 -#define PT_D7 6 -#define PT_A0 7 -#define PT_A1 8 -#define PT_A2 9 -#define PT_A3 10 -#define PT_A4 11 -#define PT_A5 12 -#define PT_A6 13 -#define PT_D0 14 -#define PT_USP 15 -#define PT_ORIG_D0 16 -#define PT_SR 17 -#define PT_PC 18 +#include <uapi/asm/ptrace.h> #ifndef __ASSEMBLY__ -/* this struct defines the way the registers are stored on the - stack during a system call. */ - -struct pt_regs { - long d1; - long d2; - long d3; - long d4; - long d5; - long a0; - long a1; - long a2; - long d0; - long orig_d0; - long stkadj; -#ifdef CONFIG_COLDFIRE - unsigned format : 4; /* frame format specifier */ - unsigned vector : 12; /* vector offset */ - unsigned short sr; - unsigned long pc; -#else - unsigned short sr; - unsigned long pc; - unsigned format : 4; /* frame format specifier */ - unsigned vector : 12; /* vector offset */ -#endif -}; - -/* - * This is the extended stack used by signal handlers and the context - * switcher: it's pushed after the normal "struct pt_regs". - */ -struct switch_stack { - unsigned long d6; - unsigned long d7; - unsigned long a3; - unsigned long a4; - unsigned long a5; - unsigned long a6; - unsigned long retpc; -}; - -/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ -#define PTRACE_GETREGS 12 -#define PTRACE_SETREGS 13 -#define PTRACE_GETFPREGS 14 -#define PTRACE_SETFPREGS 15 - -#define PTRACE_GET_THREAD_AREA 25 - -#define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ - -#ifdef __KERNEL__ - #ifndef PS_S #define PS_S (0x2000) #define PS_M (0x1000) @@ -94,6 +22,5 @@ struct switch_stack { #define arch_has_block_step() (1) #endif -#endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ #endif /* _M68K_PTRACE_H */ diff --git a/arch/m68k/include/asm/setup.h b/arch/m68k/include/asm/setup.h index 00c2c5397d3..65e78a2dad6 100644 --- a/arch/m68k/include/asm/setup.h +++ b/arch/m68k/include/asm/setup.h @@ -19,33 +19,12 @@ ** Redesign of the boot information structure; moved boot information ** structure to bootinfo.h */ - #ifndef _M68K_SETUP_H #define _M68K_SETUP_H +#include <uapi/asm/setup.h> - /* - * Linux/m68k Architectures - */ - -#define MACH_AMIGA 1 -#define MACH_ATARI 2 -#define MACH_MAC 3 -#define MACH_APOLLO 4 -#define MACH_SUN3 5 -#define MACH_MVME147 6 -#define MACH_MVME16x 7 -#define MACH_BVME6000 8 -#define MACH_HP300 9 -#define MACH_Q40 10 -#define MACH_SUN3X 11 -#define MACH_M54XX 12 - -#define COMMAND_LINE_SIZE 256 - -#ifdef __KERNEL__ - #define CL_SIZE COMMAND_LINE_SIZE #ifndef __ASSEMBLY__ @@ -194,63 +173,6 @@ extern unsigned long m68k_machtype; # define MACH_TYPE (m68k_machtype) #endif -#endif /* __KERNEL__ */ - - - /* - * CPU, FPU and MMU types - * - * Note: we may rely on the following equalities: - * - * CPU_68020 == MMU_68851 - * CPU_68030 == MMU_68030 - * CPU_68040 == FPU_68040 == MMU_68040 - * CPU_68060 == FPU_68060 == MMU_68060 - */ - -#define CPUB_68020 0 -#define CPUB_68030 1 -#define CPUB_68040 2 -#define CPUB_68060 3 -#define CPUB_COLDFIRE 4 - -#define CPU_68020 (1<<CPUB_68020) -#define CPU_68030 (1<<CPUB_68030) -#define CPU_68040 (1<<CPUB_68040) -#define CPU_68060 (1<<CPUB_68060) -#define CPU_COLDFIRE (1<<CPUB_COLDFIRE) - -#define FPUB_68881 0 -#define FPUB_68882 1 -#define FPUB_68040 2 /* Internal FPU */ -#define FPUB_68060 3 /* Internal FPU */ -#define FPUB_SUNFPA 4 /* Sun-3 FPA */ -#define FPUB_COLDFIRE 5 /* ColdFire FPU */ - -#define FPU_68881 (1<<FPUB_68881) -#define FPU_68882 (1<<FPUB_68882) -#define FPU_68040 (1<<FPUB_68040) -#define FPU_68060 (1<<FPUB_68060) -#define FPU_SUNFPA (1<<FPUB_SUNFPA) -#define FPU_COLDFIRE (1<<FPUB_COLDFIRE) - -#define MMUB_68851 0 -#define MMUB_68030 1 /* Internal MMU */ -#define MMUB_68040 2 /* Internal MMU */ -#define MMUB_68060 3 /* Internal MMU */ -#define MMUB_APOLLO 4 /* Custom Apollo */ -#define MMUB_SUN3 5 /* Custom Sun-3 */ -#define MMUB_COLDFIRE 6 /* Internal MMU */ - -#define MMU_68851 (1<<MMUB_68851) -#define MMU_68030 (1<<MMUB_68030) -#define MMU_68040 (1<<MMUB_68040) -#define MMU_68060 (1<<MMUB_68060) -#define MMU_SUN3 (1<<MMUB_SUN3) -#define MMU_APOLLO (1<<MMUB_APOLLO) -#define MMU_COLDFIRE (1<<MMUB_COLDFIRE) - -#ifdef __KERNEL__ #ifndef __ASSEMBLY__ extern unsigned long m68k_cputype; @@ -385,6 +307,4 @@ extern int m68k_realnum_memory; /* real # of memory blocks found */ extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */ #endif -#endif /* __KERNEL__ */ - #endif /* _M68K_SETUP_H */ diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h index 60e88660169..2df26b57c26 100644 --- a/arch/m68k/include/asm/signal.h +++ b/arch/m68k/include/asm/signal.h @@ -1,12 +1,8 @@ #ifndef _M68K_SIGNAL_H #define _M68K_SIGNAL_H -#include <linux/types.h> +#include <uapi/asm/signal.h> -/* Avoid too many header ordering problems. */ -struct siginfo; - -#ifdef __KERNEL__ /* Most things should be clean enough to redefine this at will, if care is taken to make libc match. */ @@ -20,92 +16,6 @@ typedef struct { unsigned long sig[_NSIG_WORDS]; } sigset_t; -#else -/* Here we must cater to libcs that poke about in kernel headers. */ - -#define NSIG 32 -typedef unsigned long sigset_t; - -#endif /* __KERNEL__ */ - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX _NSIG - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP 0x00000001 -#define SA_NOCLDWAIT 0x00000002 -#define SA_SIGINFO 0x00000004 -#define SA_ONSTACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_NODEFER 0x40000000 -#define SA_RESETHAND 0x80000000 - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -/* - * sigaltstack controls - */ -#define SS_ONSTACK 1 -#define SS_DISABLE 2 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 - -#include <asm-generic/signal-defs.h> - -#ifdef __KERNEL__ struct old_sigaction { __sighandler_t sa_handler; old_sigset_t sa_mask; @@ -123,31 +33,6 @@ struct sigaction { struct k_sigaction { struct sigaction sa; }; -#else -/* Here we must cater to libcs that poke about in kernel headers. */ - -struct sigaction { - union { - __sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo *, void *); - } _u; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -#define sa_handler _u._sa_handler -#define sa_sigaction _u._sa_sigaction - -#endif /* __KERNEL__ */ - -typedef struct sigaltstack { - void __user *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -#ifdef __KERNEL__ #include <asm/sigcontext.h> #ifndef CONFIG_CPU_HAS_NO_BITFIELDS @@ -156,7 +41,7 @@ typedef struct sigaltstack { static inline void sigaddset(sigset_t *set, int _sig) { asm ("bfset %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -164,7 +49,7 @@ static inline void sigaddset(sigset_t *set, int _sig) static inline void sigdelset(sigset_t *set, int _sig) { asm ("bfclr %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -180,7 +65,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig) int ret; asm ("bfextu %1{%2,#1},%0" : "=d" (ret) - : "od" (*set), "id" ((_sig-1) ^ 31) + : "o" (*set), "id" ((_sig-1) ^ 31) : "cc"); return ret; } @@ -208,5 +93,4 @@ struct pt_regs; extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie); #endif /* __uClinux__ */ -#endif /* __KERNEL__ */ #endif /* _M68K_SIGNAL_H */ diff --git a/arch/m68k/include/asm/termios.h b/arch/m68k/include/asm/termios.h index 0823032e404..ad8efb09866 100644 --- a/arch/m68k/include/asm/termios.h +++ b/arch/m68k/include/asm/termios.h @@ -1,27 +1,8 @@ #ifndef _M68K_TERMIOS_H #define _M68K_TERMIOS_H -#include <asm/termbits.h> -#include <asm/ioctls.h> +#include <uapi/asm/termios.h> -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 8 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - -#ifdef __KERNEL__ /* intr=^C quit=^| erase=del kill=^U eof=^D vtime=\0 vmin=\1 sxtc=\0 start=^Q stop=^S susp=^Z eol=\0 @@ -29,27 +10,6 @@ struct termio { eol2=\0 */ #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" -#endif - -/* modem lines */ -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ - -#ifdef __KERNEL__ /* * Translate a "termio" structure into a "termios". Ugh. @@ -87,6 +47,4 @@ struct termio { #define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios)) #define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios)) -#endif /* __KERNEL__ */ - #endif /* _M68K_TERMIOS_H */ diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index c702ad71679..0aa16540596 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -1,361 +1,10 @@ #ifndef _ASM_M68K_UNISTD_H_ #define _ASM_M68K_UNISTD_H_ -/* - * This file contains the system call numbers. - */ - -#define __NR_restart_syscall 0 -#define __NR_exit 1 -#define __NR_fork 2 -#define __NR_read 3 -#define __NR_write 4 -#define __NR_open 5 -#define __NR_close 6 -#define __NR_waitpid 7 -#define __NR_creat 8 -#define __NR_link 9 -#define __NR_unlink 10 -#define __NR_execve 11 -#define __NR_chdir 12 -#define __NR_time 13 -#define __NR_mknod 14 -#define __NR_chmod 15 -#define __NR_chown 16 -/*#define __NR_break 17*/ -#define __NR_oldstat 18 -#define __NR_lseek 19 -#define __NR_getpid 20 -#define __NR_mount 21 -#define __NR_umount 22 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_ptrace 26 -#define __NR_alarm 27 -#define __NR_oldfstat 28 -#define __NR_pause 29 -#define __NR_utime 30 -/*#define __NR_stty 31*/ -/*#define __NR_gtty 32*/ -#define __NR_access 33 -#define __NR_nice 34 -/*#define __NR_ftime 35*/ -#define __NR_sync 36 -#define __NR_kill 37 -#define __NR_rename 38 -#define __NR_mkdir 39 -#define __NR_rmdir 40 -#define __NR_dup 41 -#define __NR_pipe 42 -#define __NR_times 43 -/*#define __NR_prof 44*/ -#define __NR_brk 45 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_signal 48 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_acct 51 -#define __NR_umount2 52 -/*#define __NR_lock 53*/ -#define __NR_ioctl 54 -#define __NR_fcntl 55 -/*#define __NR_mpx 56*/ -#define __NR_setpgid 57 -/*#define __NR_ulimit 58*/ -/*#define __NR_oldolduname 59*/ -#define __NR_umask 60 -#define __NR_chroot 61 -#define __NR_ustat 62 -#define __NR_dup2 63 -#define __NR_getppid 64 -#define __NR_getpgrp 65 -#define __NR_setsid 66 -#define __NR_sigaction 67 -#define __NR_sgetmask 68 -#define __NR_ssetmask 69 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_sigsuspend 72 -#define __NR_sigpending 73 -#define __NR_sethostname 74 -#define __NR_setrlimit 75 -#define __NR_getrlimit 76 -#define __NR_getrusage 77 -#define __NR_gettimeofday 78 -#define __NR_settimeofday 79 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_select 82 -#define __NR_symlink 83 -#define __NR_oldlstat 84 -#define __NR_readlink 85 -#define __NR_uselib 86 -#define __NR_swapon 87 -#define __NR_reboot 88 -#define __NR_readdir 89 -#define __NR_mmap 90 -#define __NR_munmap 91 -#define __NR_truncate 92 -#define __NR_ftruncate 93 -#define __NR_fchmod 94 -#define __NR_fchown 95 -#define __NR_getpriority 96 -#define __NR_setpriority 97 -/*#define __NR_profil 98*/ -#define __NR_statfs 99 -#define __NR_fstatfs 100 -/*#define __NR_ioperm 101*/ -#define __NR_socketcall 102 -#define __NR_syslog 103 -#define __NR_setitimer 104 -#define __NR_getitimer 105 -#define __NR_stat 106 -#define __NR_lstat 107 -#define __NR_fstat 108 -/*#define __NR_olduname 109*/ -/*#define __NR_iopl 110*/ /* not supported */ -#define __NR_vhangup 111 -/*#define __NR_idle 112*/ /* Obsolete */ -/*#define __NR_vm86 113*/ /* not supported */ -#define __NR_wait4 114 -#define __NR_swapoff 115 -#define __NR_sysinfo 116 -#define __NR_ipc 117 -#define __NR_fsync 118 -#define __NR_sigreturn 119 -#define __NR_clone 120 -#define __NR_setdomainname 121 -#define __NR_uname 122 -#define __NR_cacheflush 123 -#define __NR_adjtimex 124 -#define __NR_mprotect 125 -#define __NR_sigprocmask 126 -#define __NR_create_module 127 -#define __NR_init_module 128 -#define __NR_delete_module 129 -#define __NR_get_kernel_syms 130 -#define __NR_quotactl 131 -#define __NR_getpgid 132 -#define __NR_fchdir 133 -#define __NR_bdflush 134 -#define __NR_sysfs 135 -#define __NR_personality 136 -/*#define __NR_afs_syscall 137*/ /* Syscall for Andrew File System */ -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR_getdents 141 -#define __NR__newselect 142 -#define __NR_flock 143 -#define __NR_msync 144 -#define __NR_readv 145 -#define __NR_writev 146 -#define __NR_getsid 147 -#define __NR_fdatasync 148 -#define __NR__sysctl 149 -#define __NR_mlock 150 -#define __NR_munlock 151 -#define __NR_mlockall 152 -#define __NR_munlockall 153 -#define __NR_sched_setparam 154 -#define __NR_sched_getparam 155 -#define __NR_sched_setscheduler 156 -#define __NR_sched_getscheduler 157 -#define __NR_sched_yield 158 -#define __NR_sched_get_priority_max 159 -#define __NR_sched_get_priority_min 160 -#define __NR_sched_rr_get_interval 161 -#define __NR_nanosleep 162 -#define __NR_mremap 163 -#define __NR_setresuid 164 -#define __NR_getresuid 165 -#define __NR_getpagesize 166 -#define __NR_query_module 167 -#define __NR_poll 168 -#define __NR_nfsservctl 169 -#define __NR_setresgid 170 -#define __NR_getresgid 171 -#define __NR_prctl 172 -#define __NR_rt_sigreturn 173 -#define __NR_rt_sigaction 174 -#define __NR_rt_sigprocmask 175 -#define __NR_rt_sigpending 176 -#define __NR_rt_sigtimedwait 177 -#define __NR_rt_sigqueueinfo 178 -#define __NR_rt_sigsuspend 179 -#define __NR_pread64 180 -#define __NR_pwrite64 181 -#define __NR_lchown 182 -#define __NR_getcwd 183 -#define __NR_capget 184 -#define __NR_capset 185 -#define __NR_sigaltstack 186 -#define __NR_sendfile 187 -#define __NR_getpmsg 188 /* some people actually want streams */ -#define __NR_putpmsg 189 /* some people actually want streams */ -#define __NR_vfork 190 -#define __NR_ugetrlimit 191 -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_chown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_setgroups32 206 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_lchown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_setfsuid32 215 -#define __NR_setfsgid32 216 -#define __NR_pivot_root 217 -/* 218*/ -/* 219*/ -#define __NR_getdents64 220 -#define __NR_gettid 221 -#define __NR_tkill 222 -#define __NR_setxattr 223 -#define __NR_lsetxattr 224 -#define __NR_fsetxattr 225 -#define __NR_getxattr 226 -#define __NR_lgetxattr 227 -#define __NR_fgetxattr 228 -#define __NR_listxattr 229 -#define __NR_llistxattr 230 -#define __NR_flistxattr 231 -#define __NR_removexattr 232 -#define __NR_lremovexattr 233 -#define __NR_fremovexattr 234 -#define __NR_futex 235 -#define __NR_sendfile64 236 -#define __NR_mincore 237 -#define __NR_madvise 238 -#define __NR_fcntl64 239 -#define __NR_readahead 240 -#define __NR_io_setup 241 -#define __NR_io_destroy 242 -#define __NR_io_getevents 243 -#define __NR_io_submit 244 -#define __NR_io_cancel 245 -#define __NR_fadvise64 246 -#define __NR_exit_group 247 -#define __NR_lookup_dcookie 248 -#define __NR_epoll_create 249 -#define __NR_epoll_ctl 250 -#define __NR_epoll_wait 251 -#define __NR_remap_file_pages 252 -#define __NR_set_tid_address 253 -#define __NR_timer_create 254 -#define __NR_timer_settime 255 -#define __NR_timer_gettime 256 -#define __NR_timer_getoverrun 257 -#define __NR_timer_delete 258 -#define __NR_clock_settime 259 -#define __NR_clock_gettime 260 -#define __NR_clock_getres 261 -#define __NR_clock_nanosleep 262 -#define __NR_statfs64 263 -#define __NR_fstatfs64 264 -#define __NR_tgkill 265 -#define __NR_utimes 266 -#define __NR_fadvise64_64 267 -#define __NR_mbind 268 -#define __NR_get_mempolicy 269 -#define __NR_set_mempolicy 270 -#define __NR_mq_open 271 -#define __NR_mq_unlink 272 -#define __NR_mq_timedsend 273 -#define __NR_mq_timedreceive 274 -#define __NR_mq_notify 275 -#define __NR_mq_getsetattr 276 -#define __NR_waitid 277 -/*#define __NR_vserver 278*/ -#define __NR_add_key 279 -#define __NR_request_key 280 -#define __NR_keyctl 281 -#define __NR_ioprio_set 282 -#define __NR_ioprio_get 283 -#define __NR_inotify_init 284 -#define __NR_inotify_add_watch 285 -#define __NR_inotify_rm_watch 286 -#define __NR_migrate_pages 287 -#define __NR_openat 288 -#define __NR_mkdirat 289 -#define __NR_mknodat 290 -#define __NR_fchownat 291 -#define __NR_futimesat 292 -#define __NR_fstatat64 293 -#define __NR_unlinkat 294 -#define __NR_renameat 295 -#define __NR_linkat 296 -#define __NR_symlinkat 297 -#define __NR_readlinkat 298 -#define __NR_fchmodat 299 -#define __NR_faccessat 300 -#define __NR_pselect6 301 -#define __NR_ppoll 302 -#define __NR_unshare 303 -#define __NR_set_robust_list 304 -#define __NR_get_robust_list 305 -#define __NR_splice 306 -#define __NR_sync_file_range 307 -#define __NR_tee 308 -#define __NR_vmsplice 309 -#define __NR_move_pages 310 -#define __NR_sched_setaffinity 311 -#define __NR_sched_getaffinity 312 -#define __NR_kexec_load 313 -#define __NR_getcpu 314 -#define __NR_epoll_pwait 315 -#define __NR_utimensat 316 -#define __NR_signalfd 317 -#define __NR_timerfd_create 318 -#define __NR_eventfd 319 -#define __NR_fallocate 320 -#define __NR_timerfd_settime 321 -#define __NR_timerfd_gettime 322 -#define __NR_signalfd4 323 -#define __NR_eventfd2 324 -#define __NR_epoll_create1 325 -#define __NR_dup3 326 -#define __NR_pipe2 327 -#define __NR_inotify_init1 328 -#define __NR_preadv 329 -#define __NR_pwritev 330 -#define __NR_rt_tgsigqueueinfo 331 -#define __NR_perf_event_open 332 -#define __NR_get_thread_area 333 -#define __NR_set_thread_area 334 -#define __NR_atomic_cmpxchg_32 335 -#define __NR_atomic_barrier 336 -#define __NR_fanotify_init 337 -#define __NR_fanotify_mark 338 -#define __NR_prlimit64 339 -#define __NR_name_to_handle_at 340 -#define __NR_open_by_handle_at 341 -#define __NR_clock_adjtime 342 -#define __NR_syncfs 343 -#define __NR_setns 344 -#define __NR_process_vm_readv 345 -#define __NR_process_vm_writev 346 +#include <uapi/asm/unistd.h> -#ifdef __KERNEL__ -#define NR_syscalls 347 +#define NR_syscalls 348 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_STAT @@ -383,7 +32,6 @@ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_SYS_EXECVE -#define __ARCH_WANT_KERNEL_EXECVE /* * "Conditional" syscalls @@ -393,5 +41,4 @@ */ #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") -#endif /* __KERNEL__ */ #endif /* _ASM_M68K_UNISTD_H_ */ diff --git a/arch/m68k/include/uapi/asm/Kbuild b/arch/m68k/include/uapi/asm/Kbuild index baebb3da1d4..972bce120e1 100644 --- a/arch/m68k/include/uapi/asm/Kbuild +++ b/arch/m68k/include/uapi/asm/Kbuild @@ -1,3 +1,26 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm +header-y += a.out.h +header-y += auxvec.h +header-y += byteorder.h +header-y += cachectl.h +header-y += fcntl.h +header-y += ioctls.h +header-y += msgbuf.h +header-y += param.h +header-y += poll.h +header-y += posix_types.h +header-y += ptrace.h +header-y += sembuf.h +header-y += setup.h +header-y += shmbuf.h +header-y += sigcontext.h +header-y += signal.h +header-y += socket.h +header-y += sockios.h +header-y += stat.h +header-y += swab.h +header-y += termbits.h +header-y += termios.h +header-y += unistd.h diff --git a/arch/m68k/include/asm/a.out.h b/arch/m68k/include/uapi/asm/a.out.h index 3885fe43432..3885fe43432 100644 --- a/arch/m68k/include/asm/a.out.h +++ b/arch/m68k/include/uapi/asm/a.out.h diff --git a/arch/m68k/include/asm/auxvec.h b/arch/m68k/include/uapi/asm/auxvec.h index 844d6d52204..844d6d52204 100644 --- a/arch/m68k/include/asm/auxvec.h +++ b/arch/m68k/include/uapi/asm/auxvec.h diff --git a/arch/m68k/include/asm/byteorder.h b/arch/m68k/include/uapi/asm/byteorder.h index 31b260a8880..31b260a8880 100644 --- a/arch/m68k/include/asm/byteorder.h +++ b/arch/m68k/include/uapi/asm/byteorder.h diff --git a/arch/m68k/include/asm/cachectl.h b/arch/m68k/include/uapi/asm/cachectl.h index 525978e959e..525978e959e 100644 --- a/arch/m68k/include/asm/cachectl.h +++ b/arch/m68k/include/uapi/asm/cachectl.h diff --git a/arch/m68k/include/asm/fcntl.h b/arch/m68k/include/uapi/asm/fcntl.h index 1c369b20dc4..1c369b20dc4 100644 --- a/arch/m68k/include/asm/fcntl.h +++ b/arch/m68k/include/uapi/asm/fcntl.h diff --git a/arch/m68k/include/asm/ioctls.h b/arch/m68k/include/uapi/asm/ioctls.h index 1332bb4ca5b..1332bb4ca5b 100644 --- a/arch/m68k/include/asm/ioctls.h +++ b/arch/m68k/include/uapi/asm/ioctls.h diff --git a/arch/m68k/include/asm/msgbuf.h b/arch/m68k/include/uapi/asm/msgbuf.h index 243cb798de8..243cb798de8 100644 --- a/arch/m68k/include/asm/msgbuf.h +++ b/arch/m68k/include/uapi/asm/msgbuf.h diff --git a/arch/m68k/include/asm/param.h b/arch/m68k/include/uapi/asm/param.h index 36265ccf5c7..36265ccf5c7 100644 --- a/arch/m68k/include/asm/param.h +++ b/arch/m68k/include/uapi/asm/param.h diff --git a/arch/m68k/include/asm/poll.h b/arch/m68k/include/uapi/asm/poll.h index f080fcdb61b..f080fcdb61b 100644 --- a/arch/m68k/include/asm/poll.h +++ b/arch/m68k/include/uapi/asm/poll.h diff --git a/arch/m68k/include/asm/posix_types.h b/arch/m68k/include/uapi/asm/posix_types.h index cf4dbf70fdc..cf4dbf70fdc 100644 --- a/arch/m68k/include/asm/posix_types.h +++ b/arch/m68k/include/uapi/asm/posix_types.h diff --git a/arch/m68k/include/uapi/asm/ptrace.h b/arch/m68k/include/uapi/asm/ptrace.h new file mode 100644 index 00000000000..caf92fd3493 --- /dev/null +++ b/arch/m68k/include/uapi/asm/ptrace.h @@ -0,0 +1,79 @@ +#ifndef _UAPI_M68K_PTRACE_H +#define _UAPI_M68K_PTRACE_H + +#define PT_D1 0 +#define PT_D2 1 +#define PT_D3 2 +#define PT_D4 3 +#define PT_D5 4 +#define PT_D6 5 +#define PT_D7 6 +#define PT_A0 7 +#define PT_A1 8 +#define PT_A2 9 +#define PT_A3 10 +#define PT_A4 11 +#define PT_A5 12 +#define PT_A6 13 +#define PT_D0 14 +#define PT_USP 15 +#define PT_ORIG_D0 16 +#define PT_SR 17 +#define PT_PC 18 + +#ifndef __ASSEMBLY__ + +/* this struct defines the way the registers are stored on the + stack during a system call. */ + +struct pt_regs { + long d1; + long d2; + long d3; + long d4; + long d5; + long a0; + long a1; + long a2; + long d0; + long orig_d0; + long stkadj; +#ifdef CONFIG_COLDFIRE + unsigned format : 4; /* frame format specifier */ + unsigned vector : 12; /* vector offset */ + unsigned short sr; + unsigned long pc; +#else + unsigned short sr; + unsigned long pc; + unsigned format : 4; /* frame format specifier */ + unsigned vector : 12; /* vector offset */ +#endif +}; + +/* + * This is the extended stack used by signal handlers and the context + * switcher: it's pushed after the normal "struct pt_regs". + */ +struct switch_stack { + unsigned long d6; + unsigned long d7; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long retpc; +}; + +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 + +#define PTRACE_GET_THREAD_AREA 25 + +#define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ + +#endif /* __ASSEMBLY__ */ +#endif /* _UAPI_M68K_PTRACE_H */ diff --git a/arch/m68k/include/asm/sembuf.h b/arch/m68k/include/uapi/asm/sembuf.h index 2308052a8c2..2308052a8c2 100644 --- a/arch/m68k/include/asm/sembuf.h +++ b/arch/m68k/include/uapi/asm/sembuf.h diff --git a/arch/m68k/include/uapi/asm/setup.h b/arch/m68k/include/uapi/asm/setup.h new file mode 100644 index 00000000000..85579bff455 --- /dev/null +++ b/arch/m68k/include/uapi/asm/setup.h @@ -0,0 +1,103 @@ +/* +** asm/setup.h -- Definition of the Linux/m68k setup information +** +** Copyright 1992 by Greg Harp +** +** This file is subject to the terms and conditions of the GNU General Public +** License. See the file COPYING in the main directory of this archive +** for more details. +** +** Created 09/29/92 by Greg Harp +** +** 5/2/94 Roman Hodek: +** Added bi_atari part of the machine dependent union bi_un; for now it +** contains just a model field to distinguish between TT and Falcon. +** 26/7/96 Roman Zippel: +** Renamed to setup.h; added some useful macros to allow gcc some +** optimizations if possible. +** 5/10/96 Geert Uytterhoeven: +** Redesign of the boot information structure; moved boot information +** structure to bootinfo.h +*/ + +#ifndef _UAPI_M68K_SETUP_H +#define _UAPI_M68K_SETUP_H + + + + /* + * Linux/m68k Architectures + */ + +#define MACH_AMIGA 1 +#define MACH_ATARI 2 +#define MACH_MAC 3 +#define MACH_APOLLO 4 +#define MACH_SUN3 5 +#define MACH_MVME147 6 +#define MACH_MVME16x 7 +#define MACH_BVME6000 8 +#define MACH_HP300 9 +#define MACH_Q40 10 +#define MACH_SUN3X 11 +#define MACH_M54XX 12 + +#define COMMAND_LINE_SIZE 256 + + + + /* + * CPU, FPU and MMU types + * + * Note: we may rely on the following equalities: + * + * CPU_68020 == MMU_68851 + * CPU_68030 == MMU_68030 + * CPU_68040 == FPU_68040 == MMU_68040 + * CPU_68060 == FPU_68060 == MMU_68060 + */ + +#define CPUB_68020 0 +#define CPUB_68030 1 +#define CPUB_68040 2 +#define CPUB_68060 3 +#define CPUB_COLDFIRE 4 + +#define CPU_68020 (1<<CPUB_68020) +#define CPU_68030 (1<<CPUB_68030) +#define CPU_68040 (1<<CPUB_68040) +#define CPU_68060 (1<<CPUB_68060) +#define CPU_COLDFIRE (1<<CPUB_COLDFIRE) + +#define FPUB_68881 0 +#define FPUB_68882 1 +#define FPUB_68040 2 /* Internal FPU */ +#define FPUB_68060 3 /* Internal FPU */ +#define FPUB_SUNFPA 4 /* Sun-3 FPA */ +#define FPUB_COLDFIRE 5 /* ColdFire FPU */ + +#define FPU_68881 (1<<FPUB_68881) +#define FPU_68882 (1<<FPUB_68882) +#define FPU_68040 (1<<FPUB_68040) +#define FPU_68060 (1<<FPUB_68060) +#define FPU_SUNFPA (1<<FPUB_SUNFPA) +#define FPU_COLDFIRE (1<<FPUB_COLDFIRE) + +#define MMUB_68851 0 +#define MMUB_68030 1 /* Internal MMU */ +#define MMUB_68040 2 /* Internal MMU */ +#define MMUB_68060 3 /* Internal MMU */ +#define MMUB_APOLLO 4 /* Custom Apollo */ +#define MMUB_SUN3 5 /* Custom Sun-3 */ +#define MMUB_COLDFIRE 6 /* Internal MMU */ + +#define MMU_68851 (1<<MMUB_68851) +#define MMU_68030 (1<<MMUB_68030) +#define MMU_68040 (1<<MMUB_68040) +#define MMU_68060 (1<<MMUB_68060) +#define MMU_SUN3 (1<<MMUB_SUN3) +#define MMU_APOLLO (1<<MMUB_APOLLO) +#define MMU_COLDFIRE (1<<MMUB_COLDFIRE) + + +#endif /* _UAPI_M68K_SETUP_H */ diff --git a/arch/m68k/include/asm/shmbuf.h b/arch/m68k/include/uapi/asm/shmbuf.h index f8928d62f1b..f8928d62f1b 100644 --- a/arch/m68k/include/asm/shmbuf.h +++ b/arch/m68k/include/uapi/asm/shmbuf.h diff --git a/arch/m68k/include/asm/sigcontext.h b/arch/m68k/include/uapi/asm/sigcontext.h index 523db2a51cf..523db2a51cf 100644 --- a/arch/m68k/include/asm/sigcontext.h +++ b/arch/m68k/include/uapi/asm/sigcontext.h diff --git a/arch/m68k/include/uapi/asm/signal.h b/arch/m68k/include/uapi/asm/signal.h new file mode 100644 index 00000000000..2b450f311bd --- /dev/null +++ b/arch/m68k/include/uapi/asm/signal.h @@ -0,0 +1,118 @@ +#ifndef _UAPI_M68K_SIGNAL_H +#define _UAPI_M68K_SIGNAL_H + +#include <linux/types.h> + +/* Avoid too many header ordering problems. */ +struct siginfo; + +#ifndef __KERNEL__ +/* Here we must cater to libcs that poke about in kernel headers. */ + +#define NSIG 32 +typedef unsigned long sigset_t; + +#endif /* __KERNEL__ */ + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +/* +#define SIGLOST 29 +*/ +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED 31 + +/* These should not be considered constants from userland. */ +#define SIGRTMIN 32 +#define SIGRTMAX _NSIG + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP 0x00000001 +#define SA_NOCLDWAIT 0x00000002 +#define SA_SIGINFO 0x00000004 +#define SA_ONSTACK 0x08000000 +#define SA_RESTART 0x10000000 +#define SA_NODEFER 0x40000000 +#define SA_RESETHAND 0x80000000 + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 + +#include <asm-generic/signal-defs.h> + +#ifndef __KERNEL__ +/* Here we must cater to libcs that poke about in kernel headers. */ + +struct sigaction { + union { + __sighandler_t _sa_handler; + void (*_sa_sigaction)(int, struct siginfo *, void *); + } _u; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; + +#define sa_handler _u._sa_handler +#define sa_sigaction _u._sa_sigaction + +#endif /* __KERNEL__ */ + +typedef struct sigaltstack { + void __user *ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +#endif /* _UAPI_M68K_SIGNAL_H */ diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/uapi/asm/socket.h index d1be684edf9..d1be684edf9 100644 --- a/arch/m68k/include/asm/socket.h +++ b/arch/m68k/include/uapi/asm/socket.h diff --git a/arch/m68k/include/asm/sockios.h b/arch/m68k/include/uapi/asm/sockios.h index c04a23943cb..c04a23943cb 100644 --- a/arch/m68k/include/asm/sockios.h +++ b/arch/m68k/include/uapi/asm/sockios.h diff --git a/arch/m68k/include/asm/stat.h b/arch/m68k/include/uapi/asm/stat.h index dd38bc2e9f9..dd38bc2e9f9 100644 --- a/arch/m68k/include/asm/stat.h +++ b/arch/m68k/include/uapi/asm/stat.h diff --git a/arch/m68k/include/asm/swab.h b/arch/m68k/include/uapi/asm/swab.h index b7b37a40def..b7b37a40def 100644 --- a/arch/m68k/include/asm/swab.h +++ b/arch/m68k/include/uapi/asm/swab.h diff --git a/arch/m68k/include/asm/termbits.h b/arch/m68k/include/uapi/asm/termbits.h index aea1e37b765..aea1e37b765 100644 --- a/arch/m68k/include/asm/termbits.h +++ b/arch/m68k/include/uapi/asm/termbits.h diff --git a/arch/m68k/include/uapi/asm/termios.h b/arch/m68k/include/uapi/asm/termios.h new file mode 100644 index 00000000000..ce2142c9ac1 --- /dev/null +++ b/arch/m68k/include/uapi/asm/termios.h @@ -0,0 +1,44 @@ +#ifndef _UAPI_M68K_TERMIOS_H +#define _UAPI_M68K_TERMIOS_H + +#include <asm/termbits.h> +#include <asm/ioctls.h> + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 8 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + + +#endif /* _UAPI_M68K_TERMIOS_H */ diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h new file mode 100644 index 00000000000..b94bfbf9070 --- /dev/null +++ b/arch/m68k/include/uapi/asm/unistd.h @@ -0,0 +1,357 @@ +#ifndef _UAPI_ASM_M68K_UNISTD_H_ +#define _UAPI_ASM_M68K_UNISTD_H_ + +/* + * This file contains the system call numbers. + */ + +#define __NR_restart_syscall 0 +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_chown 16 +/*#define __NR_break 17*/ +#define __NR_oldstat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_oldfstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +/*#define __NR_stty 31*/ +/*#define __NR_gtty 32*/ +#define __NR_access 33 +#define __NR_nice 34 +/*#define __NR_ftime 35*/ +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +/*#define __NR_prof 44*/ +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_umount2 52 +/*#define __NR_lock 53*/ +#define __NR_ioctl 54 +#define __NR_fcntl 55 +/*#define __NR_mpx 56*/ +#define __NR_setpgid 57 +/*#define __NR_ulimit 58*/ +/*#define __NR_oldolduname 59*/ +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_oldlstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +#define __NR_mmap 90 +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_fchown 95 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +/*#define __NR_profil 98*/ +#define __NR_statfs 99 +#define __NR_fstatfs 100 +/*#define __NR_ioperm 101*/ +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +/*#define __NR_olduname 109*/ +/*#define __NR_iopl 110*/ /* not supported */ +#define __NR_vhangup 111 +/*#define __NR_idle 112*/ /* Obsolete */ +/*#define __NR_vm86 113*/ /* not supported */ +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +#define __NR_cacheflush 123 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +/*#define __NR_afs_syscall 137*/ /* Syscall for Andrew File System */ +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 +#define __NR_getdents 141 +#define __NR__newselect 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_setresuid 164 +#define __NR_getresuid 165 +#define __NR_getpagesize 166 +#define __NR_query_module 167 +#define __NR_poll 168 +#define __NR_nfsservctl 169 +#define __NR_setresgid 170 +#define __NR_getresgid 171 +#define __NR_prctl 172 +#define __NR_rt_sigreturn 173 +#define __NR_rt_sigaction 174 +#define __NR_rt_sigprocmask 175 +#define __NR_rt_sigpending 176 +#define __NR_rt_sigtimedwait 177 +#define __NR_rt_sigqueueinfo 178 +#define __NR_rt_sigsuspend 179 +#define __NR_pread64 180 +#define __NR_pwrite64 181 +#define __NR_lchown 182 +#define __NR_getcwd 183 +#define __NR_capget 184 +#define __NR_capset 185 +#define __NR_sigaltstack 186 +#define __NR_sendfile 187 +#define __NR_getpmsg 188 /* some people actually want streams */ +#define __NR_putpmsg 189 /* some people actually want streams */ +#define __NR_vfork 190 +#define __NR_ugetrlimit 191 +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 +#define __NR_chown32 198 +#define __NR_getuid32 199 +#define __NR_getgid32 200 +#define __NR_geteuid32 201 +#define __NR_getegid32 202 +#define __NR_setreuid32 203 +#define __NR_setregid32 204 +#define __NR_getgroups32 205 +#define __NR_setgroups32 206 +#define __NR_fchown32 207 +#define __NR_setresuid32 208 +#define __NR_getresuid32 209 +#define __NR_setresgid32 210 +#define __NR_getresgid32 211 +#define __NR_lchown32 212 +#define __NR_setuid32 213 +#define __NR_setgid32 214 +#define __NR_setfsuid32 215 +#define __NR_setfsgid32 216 +#define __NR_pivot_root 217 +/* 218*/ +/* 219*/ +#define __NR_getdents64 220 +#define __NR_gettid 221 +#define __NR_tkill 222 +#define __NR_setxattr 223 +#define __NR_lsetxattr 224 +#define __NR_fsetxattr 225 +#define __NR_getxattr 226 +#define __NR_lgetxattr 227 +#define __NR_fgetxattr 228 +#define __NR_listxattr 229 +#define __NR_llistxattr 230 +#define __NR_flistxattr 231 +#define __NR_removexattr 232 +#define __NR_lremovexattr 233 +#define __NR_fremovexattr 234 +#define __NR_futex 235 +#define __NR_sendfile64 236 +#define __NR_mincore 237 +#define __NR_madvise 238 +#define __NR_fcntl64 239 +#define __NR_readahead 240 +#define __NR_io_setup 241 +#define __NR_io_destroy 242 +#define __NR_io_getevents 243 +#define __NR_io_submit 244 +#define __NR_io_cancel 245 +#define __NR_fadvise64 246 +#define __NR_exit_group 247 +#define __NR_lookup_dcookie 248 +#define __NR_epoll_create 249 +#define __NR_epoll_ctl 250 +#define __NR_epoll_wait 251 +#define __NR_remap_file_pages 252 +#define __NR_set_tid_address 253 +#define __NR_timer_create 254 +#define __NR_timer_settime 255 +#define __NR_timer_gettime 256 +#define __NR_timer_getoverrun 257 +#define __NR_timer_delete 258 +#define __NR_clock_settime 259 +#define __NR_clock_gettime 260 +#define __NR_clock_getres 261 +#define __NR_clock_nanosleep 262 +#define __NR_statfs64 263 +#define __NR_fstatfs64 264 +#define __NR_tgkill 265 +#define __NR_utimes 266 +#define __NR_fadvise64_64 267 +#define __NR_mbind 268 +#define __NR_get_mempolicy 269 +#define __NR_set_mempolicy 270 +#define __NR_mq_open 271 +#define __NR_mq_unlink 272 +#define __NR_mq_timedsend 273 +#define __NR_mq_timedreceive 274 +#define __NR_mq_notify 275 +#define __NR_mq_getsetattr 276 +#define __NR_waitid 277 +/*#define __NR_vserver 278*/ +#define __NR_add_key 279 +#define __NR_request_key 280 +#define __NR_keyctl 281 +#define __NR_ioprio_set 282 +#define __NR_ioprio_get 283 +#define __NR_inotify_init 284 +#define __NR_inotify_add_watch 285 +#define __NR_inotify_rm_watch 286 +#define __NR_migrate_pages 287 +#define __NR_openat 288 +#define __NR_mkdirat 289 +#define __NR_mknodat 290 +#define __NR_fchownat 291 +#define __NR_futimesat 292 +#define __NR_fstatat64 293 +#define __NR_unlinkat 294 +#define __NR_renameat 295 +#define __NR_linkat 296 +#define __NR_symlinkat 297 +#define __NR_readlinkat 298 +#define __NR_fchmodat 299 +#define __NR_faccessat 300 +#define __NR_pselect6 301 +#define __NR_ppoll 302 +#define __NR_unshare 303 +#define __NR_set_robust_list 304 +#define __NR_get_robust_list 305 +#define __NR_splice 306 +#define __NR_sync_file_range 307 +#define __NR_tee 308 +#define __NR_vmsplice 309 +#define __NR_move_pages 310 +#define __NR_sched_setaffinity 311 +#define __NR_sched_getaffinity 312 +#define __NR_kexec_load 313 +#define __NR_getcpu 314 +#define __NR_epoll_pwait 315 +#define __NR_utimensat 316 +#define __NR_signalfd 317 +#define __NR_timerfd_create 318 +#define __NR_eventfd 319 +#define __NR_fallocate 320 +#define __NR_timerfd_settime 321 +#define __NR_timerfd_gettime 322 +#define __NR_signalfd4 323 +#define __NR_eventfd2 324 +#define __NR_epoll_create1 325 +#define __NR_dup3 326 +#define __NR_pipe2 327 +#define __NR_inotify_init1 328 +#define __NR_preadv 329 +#define __NR_pwritev 330 +#define __NR_rt_tgsigqueueinfo 331 +#define __NR_perf_event_open 332 +#define __NR_get_thread_area 333 +#define __NR_set_thread_area 334 +#define __NR_atomic_cmpxchg_32 335 +#define __NR_atomic_barrier 336 +#define __NR_fanotify_init 337 +#define __NR_fanotify_mark 338 +#define __NR_prlimit64 339 +#define __NR_name_to_handle_at 340 +#define __NR_open_by_handle_at 341 +#define __NR_clock_adjtime 342 +#define __NR_syncfs 343 +#define __NR_setns 344 +#define __NR_process_vm_readv 345 +#define __NR_process_vm_writev 346 +#define __NR_kcmp 347 + +#endif /* _UAPI_ASM_M68K_UNISTD_H_ */ diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 946cb018775..45b2f293f8c 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -115,16 +115,9 @@ ENTRY(ret_from_kernel_thread) | a3 contains the kernel thread payload, d7 - its argument movel %d1,%sp@- jsr schedule_tail - GET_CURRENT(%d0) movel %d7,(%sp) jsr %a3@ addql #4,%sp - movel %d0,(%sp) - jra sys_exit - -ENTRY(ret_from_kernel_execve) - movel 4(%sp), %sp - GET_CURRENT(%d0) jra ret_from_exception #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU) diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index ce827b37611..4fc2e29b771 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S @@ -367,4 +367,5 @@ ENTRY(sys_call_table) .long sys_setns .long sys_process_vm_readv /* 345 */ .long sys_process_vm_writev + .long sys_kcmp diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 4cba7439f9d..198abf6d41c 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig @@ -26,6 +26,8 @@ config MICROBLAZE select GENERIC_ATOMIC64 select GENERIC_CLOCKEVENTS select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE config SWAP def_bool n diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index af2bb965239..0759153e811 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h @@ -31,6 +31,7 @@ extern const struct seq_operations cpuinfo_op; void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); extern void ret_from_fork(void); +extern void ret_from_kernel_thread(void); # endif /* __ASSEMBLY__ */ @@ -78,11 +79,6 @@ extern unsigned long thread_saved_pc(struct task_struct *t); extern unsigned long get_wchan(struct task_struct *p); -/* - * create a kernel thread without removing it from tasklists - */ -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); - # define KSTK_EIP(tsk) (0) # define KSTK_ESP(tsk) (0) @@ -131,8 +127,6 @@ extern inline void release_thread(struct task_struct *dead_task) { } -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); - /* Free current thread data structures etc. */ static inline void exit_thread(void) { diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 6985e6e9d82..ea744283429 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -422,6 +422,7 @@ #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_SYS_EXECVE /* * "Conditional" syscalls diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 75c3ea1f48a..673a49c04a0 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -474,6 +474,14 @@ ENTRY(ret_from_fork) brid ret_to_user nop +ENTRY(ret_from_kernel_thread) + brlid r15, schedule_tail + addk r5, r0, r3 + brald r15, r20 + addk r5, r0, r19 + brid ret_to_user + addk r3, r0, r0 + work_pending: enable_irq @@ -559,10 +567,6 @@ sys_clone: brid microblaze_clone addk r7, r1, r0 -sys_execve: - brid microblaze_execve - addk r8, r1, r0 - sys_rt_sigreturn_wrapper: brid sys_rt_sigreturn addk r5, r1, r0 diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 03f7b8ce6b6..10f360ed82b 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -293,24 +293,6 @@ C_ENTRY(_user_exception): swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ addi r14, r14, 4 /* return address is 4 byte after call */ - mfs r1, rmsr - nop - andi r1, r1, MSR_UMS - bnei r1, 1f - -/* Kernel-mode state save - kernel execve */ - lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ - tophys(r1,r1); - - addik r1, r1, -PT_SIZE; /* Make room on the stack. */ - SAVE_REGS - - swi r1, r1, PT_MODE; /* pt_regs -> kernel mode */ - brid 2f; - nop; /* Fill delay slot */ - -/* User-mode state save. */ -1: lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ tophys(r1,r1); lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ @@ -479,11 +461,20 @@ C_ENTRY(sys_fork_wrapper): saved context). */ C_ENTRY(ret_from_fork): bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ - add r3, r5, r0; /* switch_thread returns the prev task */ + add r5, r3, r0; /* switch_thread returns the prev task */ /* ( in the delay slot ) */ brid ret_from_trap; /* Do normal trap return */ add r3, r0, r0; /* Child's fork call should return 0. */ +C_ENTRY(ret_from_kernel_thread): + bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ + add r5, r3, r0; /* switch_thread returns the prev task */ + /* ( in the delay slot ) */ + brald r15, r20 /* fn was left in r20 */ + addk r5, r0, r19 /* ... and argument - in r19 */ + brid ret_from_trap + add r3, r0, r0 + C_ENTRY(sys_vfork): brid microblaze_vfork /* Do real work (tail-call) */ addik r5, r1, 0 @@ -498,10 +489,6 @@ C_ENTRY(sys_clone): brid do_fork /* Do real work (tail-call) */ add r8, r0, r0; /* Arg 3: (unused) */ -C_ENTRY(sys_execve): - brid microblaze_execve; /* Do real work (tail-call).*/ - addik r8, r1, 0; /* add user context as 4th arg */ - C_ENTRY(sys_rt_sigreturn_wrapper): brid sys_rt_sigreturn /* Do real work */ addik r5, r1, 0; /* add user context as 1st arg */ diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index 1944e00f07e..29768c3dc35 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -119,46 +119,38 @@ void flush_thread(void) } int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs = task_pt_regs(p); struct thread_info *ti = task_thread_info(p); + if (unlikely(p->flags & PF_KTHREAD)) { + /* if we're creating a new kernel thread then just zeroing all + * the registers. That's OK for a brand new thread.*/ + memset(childregs, 0, sizeof(struct pt_regs)); + memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); + ti->cpu_context.r1 = (unsigned long)childregs; + ti->cpu_context.r20 = (unsigned long)usp; /* fn */ + ti->cpu_context.r19 = (unsigned long)arg; + childregs->pt_mode = 1; + local_save_flags(childregs->msr); +#ifdef CONFIG_MMU + ti->cpu_context.msr = childregs->msr & ~MSR_IE; +#endif + ti->cpu_context.r15 = (unsigned long)ret_from_kernel_thread - 8; + return 0; + } *childregs = *regs; - if (user_mode(regs)) - childregs->r1 = usp; - else - childregs->r1 = ((unsigned long) ti) + THREAD_SIZE; + childregs->r1 = usp; -#ifndef CONFIG_MMU memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); ti->cpu_context.r1 = (unsigned long)childregs; +#ifndef CONFIG_MMU ti->cpu_context.msr = (unsigned long)childregs->msr; #else + childregs->msr |= MSR_UMS; - /* if creating a kernel thread then update the current reg (we don't - * want to use the parent's value when restoring by POP_STATE) */ - if (kernel_mode(regs)) - /* save new current on stack to use POP_STATE */ - childregs->CURRENT_TASK = (unsigned long)p; - /* if returning to user then use the parent's value of this register */ - - /* if we're creating a new kernel thread then just zeroing all - * the registers. That's OK for a brand new thread.*/ - /* Pls. note that some of them will be restored in POP_STATE */ - if (kernel_mode(regs)) - memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); - /* if this thread is created for fork/vfork/clone, then we want to - * restore all the parent's context */ - /* in addition to the registers which will be restored by POP_STATE */ - else { - ti->cpu_context = *(struct cpu_context *)regs; - childregs->msr |= MSR_UMS; - } - - /* FIXME STATE_SAVE_PT_OFFSET; */ - ti->cpu_context.r1 = (unsigned long)childregs; /* we should consider the fact that childregs is a copy of the parent * regs which were saved immediately after entering the kernel state * before enabling VM. This MSR will be restored in switch_to and @@ -209,29 +201,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk) } #endif -static void kernel_thread_helper(int (*fn)(void *), void *arg) -{ - fn(arg); - do_exit(-1); -} - -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - /* store them in non-volatile registers */ - regs.r5 = (unsigned long)fn; - regs.r6 = (unsigned long)arg; - local_save_flags(regs.msr); - regs.pc = (unsigned long)kernel_thread_helper; - regs.pt_mode = 1; - - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, - ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL_GPL(kernel_thread); - unsigned long get_wchan(struct task_struct *p) { /* TBD (used by procfs) */ @@ -246,6 +215,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp) regs->pt_mode = 0; #ifdef CONFIG_MMU regs->msr |= MSR_UMS; + regs->msr &= ~MSR_VM; #endif } diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 3847e5b9c60..3903e3d11f5 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -111,7 +111,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1)) + if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1) == -EFAULT) goto badframe; return rval; diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index 404c0f24bd4..a6a7bae9f5c 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -48,24 +48,6 @@ asmlinkage long microblaze_clone(int flags, unsigned long stack, return do_fork(flags, stack, regs, 0, NULL, NULL); } -asmlinkage long microblaze_execve(const char __user *filenamei, - const char __user *const __user *argv, - const char __user *const __user *envp, - struct pt_regs *regs) -{ - int error; - struct filename *filename; - - filename = getname(filenamei); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename->name, argv, envp, regs); - putname(filename); -out: - return error; -} - asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, off_t pgoff) @@ -75,24 +57,3 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); } - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - register const char *__a __asm__("r5") = filename; - register const void *__b __asm__("r6") = argv; - register const void *__c __asm__("r7") = envp; - register unsigned long __syscall __asm__("r12") = __NR_execve; - register unsigned long __ret __asm__("r3"); - __asm__ __volatile__ ("brki r14, 0x8" - : "=r" (__ret), "=r" (__syscall) - : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) - : "r4", "r8", "r9", - "r10", "r11", "r14", "cc", "memory"); - return __ret; -} diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index dba9390d37c..4183e62f178 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -40,6 +40,8 @@ config MIPS select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_REL select MODULES_USE_ELF_RELA if 64BIT + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE menu "Machine selection" diff --git a/arch/mips/cavium-octeon/executive/cvmx-l2c.c b/arch/mips/cavium-octeon/executive/cvmx-l2c.c index d38246e33dd..9f883bf7695 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-l2c.c +++ b/arch/mips/cavium-octeon/executive/cvmx-l2c.c @@ -30,6 +30,7 @@ * measurement, and debugging facilities. */ +#include <linux/irqflags.h> #include <asm/octeon/cvmx.h> #include <asm/octeon/cvmx-l2c.h> #include <asm/octeon/cvmx-spinlock.h> diff --git a/arch/mips/fw/arc/misc.c b/arch/mips/fw/arc/misc.c index 7cf80ca2c1d..f9f5307434c 100644 --- a/arch/mips/fw/arc/misc.c +++ b/arch/mips/fw/arc/misc.c @@ -11,6 +11,7 @@ */ #include <linux/init.h> #include <linux/kernel.h> +#include <linux/irqflags.h> #include <asm/bcache.h> diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild index e69de29bb2d..533053d12ce 100644 --- a/arch/mips/include/asm/Kbuild +++ b/arch/mips/include/asm/Kbuild @@ -0,0 +1 @@ +# MIPS headers diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index 82ad35ce2b4..46ac73abd5e 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -14,7 +14,6 @@ #endif #include <linux/compiler.h> -#include <linux/irqflags.h> #include <linux/types.h> #include <asm/barrier.h> #include <asm/byteorder.h> /* sigh ... */ @@ -44,6 +43,24 @@ #define smp_mb__before_clear_bit() smp_mb__before_llsc() #define smp_mb__after_clear_bit() smp_llsc_mb() + +/* + * These are the "slower" versions of the functions and are in bitops.c. + * These functions call raw_local_irq_{save,restore}(). + */ +void __mips_set_bit(unsigned long nr, volatile unsigned long *addr); +void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr); +void __mips_change_bit(unsigned long nr, volatile unsigned long *addr); +int __mips_test_and_set_bit(unsigned long nr, + volatile unsigned long *addr); +int __mips_test_and_set_bit_lock(unsigned long nr, + volatile unsigned long *addr); +int __mips_test_and_clear_bit(unsigned long nr, + volatile unsigned long *addr); +int __mips_test_and_change_bit(unsigned long nr, + volatile unsigned long *addr); + + /* * set_bit - Atomically set a bit in memory * @nr: the bit to set @@ -57,7 +74,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) { unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); - unsigned short bit = nr & SZLONG_MASK; + int bit = nr & SZLONG_MASK; unsigned long temp; if (kernel_uses_llsc && R10000_LLSC_WAR) { @@ -92,17 +109,8 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) : "=&r" (temp), "+m" (*m) : "ir" (1UL << bit)); } while (unlikely(!temp)); - } else { - volatile unsigned long *a = addr; - unsigned long mask; - unsigned long flags; - - a += nr >> SZLONG_LOG; - mask = 1UL << bit; - raw_local_irq_save(flags); - *a |= mask; - raw_local_irq_restore(flags); - } + } else + __mips_set_bit(nr, addr); } /* @@ -118,7 +126,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) { unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); - unsigned short bit = nr & SZLONG_MASK; + int bit = nr & SZLONG_MASK; unsigned long temp; if (kernel_uses_llsc && R10000_LLSC_WAR) { @@ -153,17 +161,8 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) : "=&r" (temp), "+m" (*m) : "ir" (~(1UL << bit))); } while (unlikely(!temp)); - } else { - volatile unsigned long *a = addr; - unsigned long mask; - unsigned long flags; - - a += nr >> SZLONG_LOG; - mask = 1UL << bit; - raw_local_irq_save(flags); - *a &= ~mask; - raw_local_irq_restore(flags); - } + } else + __mips_clear_bit(nr, addr); } /* @@ -191,7 +190,7 @@ static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *ad */ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned short bit = nr & SZLONG_MASK; + int bit = nr & SZLONG_MASK; if (kernel_uses_llsc && R10000_LLSC_WAR) { unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); @@ -220,17 +219,8 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) : "=&r" (temp), "+m" (*m) : "ir" (1UL << bit)); } while (unlikely(!temp)); - } else { - volatile unsigned long *a = addr; - unsigned long mask; - unsigned long flags; - - a += nr >> SZLONG_LOG; - mask = 1UL << bit; - raw_local_irq_save(flags); - *a ^= mask; - raw_local_irq_restore(flags); - } + } else + __mips_change_bit(nr, addr); } /* @@ -244,7 +234,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned short bit = nr & SZLONG_MASK; + int bit = nr & SZLONG_MASK; unsigned long res; smp_mb__before_llsc(); @@ -281,18 +271,8 @@ static inline int test_and_set_bit(unsigned long nr, } while (unlikely(!res)); res = temp & (1UL << bit); - } else { - volatile unsigned long *a = addr; - unsigned long mask; - unsigned long flags; - - a += nr >> SZLONG_LOG; - mask = 1UL << bit; - raw_local_irq_save(flags); - res = (mask & *a); - *a |= mask; - raw_local_irq_restore(flags); - } + } else + res = __mips_test_and_set_bit(nr, addr); smp_llsc_mb(); @@ -310,7 +290,7 @@ static inline int test_and_set_bit(unsigned long nr, static inline int test_and_set_bit_lock(unsigned long nr, volatile unsigned long *addr) { - unsigned short bit = nr & SZLONG_MASK; + int bit = nr & SZLONG_MASK; unsigned long res; if (kernel_uses_llsc && R10000_LLSC_WAR) { @@ -345,18 +325,8 @@ static inline int test_and_set_bit_lock(unsigned long nr, } while (unlikely(!res)); res = temp & (1UL << bit); - } else { - volatile unsigned long *a = addr; - unsigned long mask; - unsigned long flags; - - a += nr >> SZLONG_LOG; - mask = 1UL << bit; - raw_local_irq_save(flags); - res = (mask & *a); - *a |= mask; - raw_local_irq_restore(flags); - } + } else + res = __mips_test_and_set_bit_lock(nr, addr); smp_llsc_mb(); @@ -373,7 +343,7 @@ static inline int test_and_set_bit_lock(unsigned long nr, static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned short bit = nr & SZLONG_MASK; + int bit = nr & SZLONG_MASK; unsigned long res; smp_mb__before_llsc(); @@ -428,18 +398,8 @@ static inline int test_and_clear_bit(unsigned long nr, } while (unlikely(!res)); res = temp & (1UL << bit); - } else { - volatile unsigned long *a = addr; - unsigned long mask; - unsigned long flags; - - a += nr >> SZLONG_LOG; - mask = 1UL << bit; - raw_local_irq_save(flags); - res = (mask & *a); - *a &= ~mask; - raw_local_irq_restore(flags); - } + } else + res = __mips_test_and_clear_bit(nr, addr); smp_llsc_mb(); @@ -457,7 +417,7 @@ static inline int test_and_clear_bit(unsigned long nr, static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned short bit = nr & SZLONG_MASK; + int bit = nr & SZLONG_MASK; unsigned long res; smp_mb__before_llsc(); @@ -494,18 +454,8 @@ static inline int test_and_change_bit(unsigned long nr, } while (unlikely(!res)); res = temp & (1UL << bit); - } else { - volatile unsigned long *a = addr; - unsigned long mask; - unsigned long flags; - - a += nr >> SZLONG_LOG; - mask = 1UL << bit; - raw_local_irq_save(flags); - res = (mask & *a); - *a ^= mask; - raw_local_irq_restore(flags); - } + } else + res = __mips_test_and_change_bit(nr, addr); smp_llsc_mb(); diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h index 58277e0e9cd..3c5d1464b7b 100644 --- a/arch/mips/include/asm/compat.h +++ b/arch/mips/include/asm/compat.h @@ -290,7 +290,7 @@ struct compat_shmid64_ds { static inline int is_compat_task(void) { - return test_thread_flag(TIF_32BIT); + return test_thread_flag(TIF_32BIT_ADDR); } #endif /* _ASM_COMPAT_H */ diff --git a/arch/mips/include/asm/delay.h b/arch/mips/include/asm/delay.h index e7cd78277c2..dc0a5f77a35 100644 --- a/arch/mips/include/asm/delay.h +++ b/arch/mips/include/asm/delay.h @@ -13,9 +13,9 @@ #include <linux/param.h> -extern void __delay(unsigned int loops); -extern void __ndelay(unsigned int ns); -extern void __udelay(unsigned int us); +extern void __delay(unsigned long loops); +extern void __ndelay(unsigned long ns); +extern void __udelay(unsigned long us); #define ndelay(ns) __ndelay(ns) #define udelay(us) __udelay(us) diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 29d9c23c20c..ff2e0345e01 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -15,6 +15,7 @@ #include <linux/compiler.h> #include <linux/kernel.h> #include <linux/types.h> +#include <linux/irqflags.h> #include <asm/addrspace.h> #include <asm/bug.h> diff --git a/arch/mips/include/asm/irqflags.h b/arch/mips/include/asm/irqflags.h index 309cbcd6909..9f3384c789d 100644 --- a/arch/mips/include/asm/irqflags.h +++ b/arch/mips/include/asm/irqflags.h @@ -16,83 +16,13 @@ #include <linux/compiler.h> #include <asm/hazards.h> -__asm__( - " .macro arch_local_irq_enable \n" - " .set push \n" - " .set reorder \n" - " .set noat \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n" - " ori $1, 0x400 \n" - " xori $1, 0x400 \n" - " mtc0 $1, $2, 1 \n" -#elif defined(CONFIG_CPU_MIPSR2) - " ei \n" -#else - " mfc0 $1,$12 \n" - " ori $1,0x1f \n" - " xori $1,0x1e \n" - " mtc0 $1,$12 \n" -#endif - " irq_enable_hazard \n" - " .set pop \n" - " .endm"); +#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) -extern void smtc_ipi_replay(void); - -static inline void arch_local_irq_enable(void) -{ -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC kernel needs to do a software replay of queued - * IPIs, at the cost of call overhead on each local_irq_enable() - */ - smtc_ipi_replay(); -#endif - __asm__ __volatile__( - "arch_local_irq_enable" - : /* no outputs */ - : /* no inputs */ - : "memory"); -} - - -/* - * For cli() we have to insert nops to make sure that the new value - * has actually arrived in the status register before the end of this - * macro. - * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs - * no nops at all. - */ -/* - * For TX49, operating only IE bit is not enough. - * - * If mfc0 $12 follows store and the mfc0 is last instruction of a - * page and fetching the next instruction causes TLB miss, the result - * of the mfc0 might wrongly contain EXL bit. - * - * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008 - * - * Workaround: mask EXL bit of the result or place a nop before mfc0. - */ __asm__( " .macro arch_local_irq_disable\n" " .set push \n" " .set noat \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 $1, $2, 1 \n" - " ori $1, 0x400 \n" - " .set noreorder \n" - " mtc0 $1, $2, 1 \n" -#elif defined(CONFIG_CPU_MIPSR2) " di \n" -#else - " mfc0 $1,$12 \n" - " ori $1,0x1f \n" - " xori $1,0x1f \n" - " .set noreorder \n" - " mtc0 $1,$12 \n" -#endif " irq_disable_hazard \n" " .set pop \n" " .endm \n"); @@ -106,46 +36,14 @@ static inline void arch_local_irq_disable(void) : "memory"); } -__asm__( - " .macro arch_local_save_flags flags \n" - " .set push \n" - " .set reorder \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 \\flags, $2, 1 \n" -#else - " mfc0 \\flags, $12 \n" -#endif - " .set pop \n" - " .endm \n"); - -static inline unsigned long arch_local_save_flags(void) -{ - unsigned long flags; - asm volatile("arch_local_save_flags %0" : "=r" (flags)); - return flags; -} __asm__( " .macro arch_local_irq_save result \n" " .set push \n" " .set reorder \n" " .set noat \n" -#ifdef CONFIG_MIPS_MT_SMTC - " mfc0 \\result, $2, 1 \n" - " ori $1, \\result, 0x400 \n" - " .set noreorder \n" - " mtc0 $1, $2, 1 \n" - " andi \\result, \\result, 0x400 \n" -#elif defined(CONFIG_CPU_MIPSR2) " di \\result \n" " andi \\result, 1 \n" -#else - " mfc0 \\result, $12 \n" - " ori $1, \\result, 0x1f \n" - " xori $1, 0x1f \n" - " .set noreorder \n" - " mtc0 $1, $12 \n" -#endif " irq_disable_hazard \n" " .set pop \n" " .endm \n"); @@ -160,61 +58,37 @@ static inline unsigned long arch_local_irq_save(void) return flags; } + __asm__( " .macro arch_local_irq_restore flags \n" " .set push \n" " .set noreorder \n" " .set noat \n" -#ifdef CONFIG_MIPS_MT_SMTC - "mfc0 $1, $2, 1 \n" - "andi \\flags, 0x400 \n" - "ori $1, 0x400 \n" - "xori $1, 0x400 \n" - "or \\flags, $1 \n" - "mtc0 \\flags, $2, 1 \n" -#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) +#if defined(CONFIG_IRQ_CPU) /* * Slow, but doesn't suffer from a relatively unlikely race * condition we're having since days 1. */ " beqz \\flags, 1f \n" - " di \n" + " di \n" " ei \n" "1: \n" -#elif defined(CONFIG_CPU_MIPSR2) +#else /* * Fast, dangerous. Life is fun, life is good. */ " mfc0 $1, $12 \n" " ins $1, \\flags, 0, 1 \n" " mtc0 $1, $12 \n" -#else - " mfc0 $1, $12 \n" - " andi \\flags, 1 \n" - " ori $1, 0x1f \n" - " xori $1, 0x1f \n" - " or \\flags, $1 \n" - " mtc0 \\flags, $12 \n" #endif " irq_disable_hazard \n" " .set pop \n" " .endm \n"); - static inline void arch_local_irq_restore(unsigned long flags) { unsigned long __tmp1; -#ifdef CONFIG_MIPS_MT_SMTC - /* - * SMTC kernel needs to do a software replay of queued - * IPIs, at the cost of branch and call overhead on each - * local_irq_restore() - */ - if (unlikely(!(flags & 0x0400))) - smtc_ipi_replay(); -#endif - __asm__ __volatile__( "arch_local_irq_restore\t%0" : "=r" (__tmp1) @@ -232,6 +106,75 @@ static inline void __arch_local_irq_restore(unsigned long flags) : "0" (flags) : "memory"); } +#else +/* Functions that require preempt_{dis,en}able() are in mips-atomic.c */ +void arch_local_irq_disable(void); +unsigned long arch_local_irq_save(void); +void arch_local_irq_restore(unsigned long flags); +void __arch_local_irq_restore(unsigned long flags); +#endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */ + + +__asm__( + " .macro arch_local_irq_enable \n" + " .set push \n" + " .set reorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n" + " ori $1, 0x400 \n" + " xori $1, 0x400 \n" + " mtc0 $1, $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) + " ei \n" +#else + " mfc0 $1,$12 \n" + " ori $1,0x1f \n" + " xori $1,0x1e \n" + " mtc0 $1,$12 \n" +#endif + " irq_enable_hazard \n" + " .set pop \n" + " .endm"); + +extern void smtc_ipi_replay(void); + +static inline void arch_local_irq_enable(void) +{ +#ifdef CONFIG_MIPS_MT_SMTC + /* + * SMTC kernel needs to do a software replay of queued + * IPIs, at the cost of call overhead on each local_irq_enable() + */ + smtc_ipi_replay(); +#endif + __asm__ __volatile__( + "arch_local_irq_enable" + : /* no outputs */ + : /* no inputs */ + : "memory"); +} + + +__asm__( + " .macro arch_local_save_flags flags \n" + " .set push \n" + " .set reorder \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 \\flags, $2, 1 \n" +#else + " mfc0 \\flags, $12 \n" +#endif + " .set pop \n" + " .endm \n"); + +static inline unsigned long arch_local_save_flags(void) +{ + unsigned long flags; + asm volatile("arch_local_save_flags %0" : "=r" (flags)); + return flags; +} + static inline int arch_irqs_disabled_flags(unsigned long flags) { @@ -245,7 +188,7 @@ static inline int arch_irqs_disabled_flags(unsigned long flags) #endif } -#endif +#endif /* #ifndef __ASSEMBLY__ */ /* * Do the CPU's IRQ-state tracing from assembly code. diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h index c26e1825007..f5b521d5a67 100644 --- a/arch/mips/include/asm/pgtable-64.h +++ b/arch/mips/include/asm/pgtable-64.h @@ -9,6 +9,7 @@ #ifndef _ASM_PGTABLE_64_H #define _ASM_PGTABLE_64_H +#include <linux/compiler.h> #include <linux/linkage.h> #include <asm/addrspace.h> @@ -172,7 +173,19 @@ static inline int pmd_none(pmd_t pmd) return pmd_val(pmd) == (unsigned long) invalid_pte_table; } -#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) +static inline int pmd_bad(pmd_t pmd) +{ +#ifdef CONFIG_HUGETLB_PAGE + /* pmd_huge(pmd) but inline */ + if (unlikely(pmd_val(pmd) & _PAGE_HUGE)) + return 0; +#endif + + if (unlikely(pmd_val(pmd) & ~PAGE_MASK)) + return 1; + + return 0; +} static inline int pmd_present(pmd_t pmd) { diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 5e33fabe354..d28c41e0887 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -310,8 +310,6 @@ struct task_struct; /* Free all resources held by a thread. */ #define release_thread(thread) do { } while(0) -extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - extern unsigned long thread_saved_pc(struct task_struct *tsk); /* diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index 4f5da948a77..cec5e125f7e 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -61,4 +61,10 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs) die(str, regs); } +#define current_pt_regs() \ +({ \ + unsigned long sp = (unsigned long)__builtin_frame_address(0); \ + (struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1; \ +}) + #endif /* _ASM_PTRACE_H */ diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 8debe9e9175..18806a52061 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -112,12 +112,6 @@ register struct thread_info *__current_thread_info __asm__("$28"); #define TIF_LOAD_WATCH 25 /* If set, load watch registers */ #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ -#ifdef CONFIG_MIPS32_O32 -#define TIF_32BIT TIF_32BIT_REGS -#elif defined(CONFIG_MIPS32_N32) -#define TIF_32BIT _TIF_32BIT_ADDR -#endif /* CONFIG_MIPS32_O32 */ - #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index 9e47cc11aa2..b306e2081ca 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -20,6 +20,7 @@ #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_SYS_ALARM +#define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_IPC #define __ARCH_WANT_SYS_PAUSE diff --git a/arch/mips/jz4740/serial.h b/arch/mips/jz4740/serial.h index b9fe3ade028..8eb715bb1ea 100644 --- a/arch/mips/jz4740/serial.h +++ b/arch/mips/jz4740/serial.h @@ -14,6 +14,9 @@ */ #ifndef __MIPS_JZ4740_SERIAL_H__ +#define __MIPS_JZ4740_SERIAL_H__ + +struct uart_port; void jz4740_serial_out(struct uart_port *p, int offset, int value); diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index a6c13321200..3320cb4ac1d 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -65,6 +65,12 @@ need_resched: b need_resched #endif +FEXPORT(ret_from_kernel_thread) + jal schedule_tail # a0 = struct task_struct *prev + move a0, s1 + jal s0 + j syscall_exit + FEXPORT(ret_from_fork) jal schedule_tail # a0 = struct task_struct *prev diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 3a21acedf88..8796dbc7e35 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -3,7 +3,6 @@ * * Copyright (C) 2000 Silicon Graphics, Inc. * Written by Ulf Carlsson (ulfc@engr.sgi.com) - * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) */ #include <linux/compiler.h> #include <linux/mm.h> @@ -77,26 +76,6 @@ out: return error; } -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) -{ - int error; - struct filename *filename; - - filename = getname(compat_ptr(regs.regs[4])); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]), - compat_ptr(regs.regs[6]), ®s); - putname(filename); - -out: - return error; -} - #define RLIM_INFINITY32 0x7fffffff #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c index 3fc1691110d..2d9304c2b54 100644 --- a/arch/mips/kernel/mips_ksyms.c +++ b/arch/mips/kernel/mips_ksyms.c @@ -32,8 +32,6 @@ EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(kernel_thread); - /* * Functions that operate on entire pages. Mostly used by memory management. */ diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index e9a5fd7277f..d13720ac656 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -84,6 +84,7 @@ void __noreturn cpu_idle(void) } asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) { @@ -113,7 +114,7 @@ void flush_thread(void) } int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; @@ -136,19 +137,30 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs = (struct pt_regs *) childksp - 1; /* Put the stack after the struct pt_regs. */ childksp = (unsigned long) childregs; + p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); + if (unlikely(p->flags & PF_KTHREAD)) { + unsigned long status = p->thread.cp0_status; + memset(childregs, 0, sizeof(struct pt_regs)); + ti->addr_limit = KERNEL_DS; + p->thread.reg16 = usp; /* fn */ + p->thread.reg17 = arg; + p->thread.reg29 = childksp; + p->thread.reg31 = (unsigned long) ret_from_kernel_thread; +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) + status = (status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) | + ((status & (ST0_KUC | ST0_IEC)) << 2); +#else + status |= ST0_EXL; +#endif + childregs->cp0_status = status; + return 0; + } *childregs = *regs; childregs->regs[7] = 0; /* Clear error flag */ - childregs->regs[2] = 0; /* Child gets zero as return value */ + childregs->regs[29] = usp; + ti->addr_limit = USER_DS; - if (childregs->cp0_status & ST0_CU0) { - childregs->regs[28] = (unsigned long) ti; - childregs->regs[29] = childksp; - ti->addr_limit = KERNEL_DS; - } else { - childregs->regs[29] = usp; - ti->addr_limit = USER_DS; - } p->thread.reg29 = (unsigned long) childregs; p->thread.reg31 = (unsigned long) ret_from_fork; @@ -156,7 +168,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, * New tasks lose permission to use the fpu. This accelerates context * switching for most programs since they don't use the fpu. */ - p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); #ifdef CONFIG_MIPS_MT_SMTC @@ -222,35 +233,6 @@ int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr) } /* - * Create a kernel thread - */ -static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *)) -{ - do_exit(fn(arg)); -} - -long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.regs[4] = (unsigned long) arg; - regs.regs[5] = (unsigned long) fn; - regs.cp0_epc = (unsigned long) kernel_thread_helper; - regs.cp0_status = read_c0_status(); -#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) - regs.cp0_status = (regs.cp0_status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) | - ((regs.cp0_status & (ST0_KUC | ST0_IEC)) << 2); -#else - regs.cp0_status |= ST0_EXL; -#endif - - /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -} - -/* * */ struct mips_frame_info { diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index f6ba8381ee0..d27ca340d46 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -167,7 +167,7 @@ EXPORT(sysn32_call_table) PTR sys_getsockopt PTR sys_clone /* 6055 */ PTR sys_fork - PTR sys32_execve + PTR compat_sys_execve PTR sys_exit PTR compat_sys_wait4 PTR sys_kill /* 6060 */ diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index 53c2d724576..9601be6afa3 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -203,7 +203,7 @@ sys_call_table: PTR sys_creat PTR sys_link PTR sys_unlink /* 4010 */ - PTR sys32_execve + PTR compat_sys_execve PTR sys_chdir PTR compat_sys_time PTR sys_mknod diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index a53f8ec37aa..290dc6a1d7a 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -79,7 +79,7 @@ static struct resource data_resource = { .name = "Kernel data", }; void __init add_memory_region(phys_t start, phys_t size, long type) { int x = boot_mem_map.nr_map; - struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1; + int i; /* Sanity check */ if (start + size < start) { @@ -88,15 +88,29 @@ void __init add_memory_region(phys_t start, phys_t size, long type) } /* - * Try to merge with previous entry if any. This is far less than - * perfect but is sufficient for most real world cases. + * Try to merge with existing entry, if any. */ - if (x && prev->addr + prev->size == start && prev->type == type) { - prev->size += size; + for (i = 0; i < boot_mem_map.nr_map; i++) { + struct boot_mem_map_entry *entry = boot_mem_map.map + i; + unsigned long top; + + if (entry->type != type) + continue; + + if (start + size < entry->addr) + continue; /* no overlap */ + + if (entry->addr + entry->size < start) + continue; /* no overlap */ + + top = max(entry->addr + entry->size, start + size); + entry->addr = min(entry->addr, start); + entry->size = top - entry->addr; + return; } - if (x == BOOT_MEM_MAP_MAX) { + if (boot_mem_map.nr_map == BOOT_MEM_MAP_MAX) { pr_err("Ooops! Too many entries in the memory map!\n"); return; } diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c index afc379ca375..06cd0c610f4 100644 --- a/arch/mips/kernel/smp-cmp.c +++ b/arch/mips/kernel/smp-cmp.c @@ -97,7 +97,7 @@ static void cmp_init_secondary(void) /* Enable per-cpu interrupts: platform specific */ - c->core = (read_c0_ebase() >> 1) & 0xff; + c->core = (read_c0_ebase() >> 1) & 0x1ff; #if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC) c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE; #endif diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 2bd561bc05a..c611e2df776 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -127,28 +127,6 @@ _sys_clone(nabi_no_regargs struct pt_regs regs) parent_tidptr, child_tidptr); } -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs) -{ - int error; - struct filename *filename; - - filename = getname((const char __user *) (long)regs.regs[4]); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename->name, - (const char __user *const __user *) (long)regs.regs[5], - (const char __user *const __user *) (long)regs.regs[6], - ®s); - putname(filename); - -out: - return error; -} - SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) { struct thread_info *ti = task_thread_info(current); @@ -313,34 +291,3 @@ asmlinkage void bad_stack(void) { do_exit(SIGSEGV); } - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - register unsigned long __a0 asm("$4") = (unsigned long) filename; - register unsigned long __a1 asm("$5") = (unsigned long) argv; - register unsigned long __a2 asm("$6") = (unsigned long) envp; - register unsigned long __a3 asm("$7"); - unsigned long __v0; - - __asm__ volatile (" \n" - " .set noreorder \n" - " li $2, %5 # __NR_execve \n" - " syscall \n" - " move %0, $2 \n" - " .set reorder \n" - : "=&r" (__v0), "=r" (__a3) - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve) - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", - "memory"); - - if (__a3 == 0) - return __v0; - - return -__v0; -} diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index c4a82e841c7..eeddc58802e 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -2,8 +2,9 @@ # Makefile for MIPS-specific library files.. # -lib-y += csum_partial.o delay.o memcpy.o memset.o \ - strlen_user.o strncpy_user.o strnlen_user.o uncached.o +lib-y += bitops.o csum_partial.o delay.o memcpy.o memset.o \ + mips-atomic.o strlen_user.o strncpy_user.o \ + strnlen_user.o uncached.o obj-y += iomap.o obj-$(CONFIG_PCI) += iomap-pci.o diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c new file mode 100644 index 00000000000..239a9c957b0 --- /dev/null +++ b/arch/mips/lib/bitops.c @@ -0,0 +1,179 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 1994-1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org) + * Copyright (c) 1999, 2000 Silicon Graphics, Inc. + */ +#include <linux/bitops.h> +#include <linux/irqflags.h> +#include <linux/export.h> + + +/** + * __mips_set_bit - Atomically set a bit in memory. This is called by + * set_bit() if it cannot find a faster solution. + * @nr: the bit to set + * @addr: the address to start counting from + */ +void __mips_set_bit(unsigned long nr, volatile unsigned long *addr) +{ + volatile unsigned long *a = addr; + unsigned bit = nr & SZLONG_MASK; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + *a |= mask; + raw_local_irq_restore(flags); +} +EXPORT_SYMBOL(__mips_set_bit); + + +/** + * __mips_clear_bit - Clears a bit in memory. This is called by clear_bit() if + * it cannot find a faster solution. + * @nr: Bit to clear + * @addr: Address to start counting from + */ +void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr) +{ + volatile unsigned long *a = addr; + unsigned bit = nr & SZLONG_MASK; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + *a &= ~mask; + raw_local_irq_restore(flags); +} +EXPORT_SYMBOL(__mips_clear_bit); + + +/** + * __mips_change_bit - Toggle a bit in memory. This is called by change_bit() + * if it cannot find a faster solution. + * @nr: Bit to change + * @addr: Address to start counting from + */ +void __mips_change_bit(unsigned long nr, volatile unsigned long *addr) +{ + volatile unsigned long *a = addr; + unsigned bit = nr & SZLONG_MASK; + unsigned long mask; + unsigned long flags; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + *a ^= mask; + raw_local_irq_restore(flags); +} +EXPORT_SYMBOL(__mips_change_bit); + + +/** + * __mips_test_and_set_bit - Set a bit and return its old value. This is + * called by test_and_set_bit() if it cannot find a faster solution. + * @nr: Bit to set + * @addr: Address to count from + */ +int __mips_test_and_set_bit(unsigned long nr, + volatile unsigned long *addr) +{ + volatile unsigned long *a = addr; + unsigned bit = nr & SZLONG_MASK; + unsigned long mask; + unsigned long flags; + unsigned long res; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + res = (mask & *a); + *a |= mask; + raw_local_irq_restore(flags); + return res; +} +EXPORT_SYMBOL(__mips_test_and_set_bit); + + +/** + * __mips_test_and_set_bit_lock - Set a bit and return its old value. This is + * called by test_and_set_bit_lock() if it cannot find a faster solution. + * @nr: Bit to set + * @addr: Address to count from + */ +int __mips_test_and_set_bit_lock(unsigned long nr, + volatile unsigned long *addr) +{ + volatile unsigned long *a = addr; + unsigned bit = nr & SZLONG_MASK; + unsigned long mask; + unsigned long flags; + unsigned long res; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + res = (mask & *a); + *a |= mask; + raw_local_irq_restore(flags); + return res; +} +EXPORT_SYMBOL(__mips_test_and_set_bit_lock); + + +/** + * __mips_test_and_clear_bit - Clear a bit and return its old value. This is + * called by test_and_clear_bit() if it cannot find a faster solution. + * @nr: Bit to clear + * @addr: Address to count from + */ +int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) +{ + volatile unsigned long *a = addr; + unsigned bit = nr & SZLONG_MASK; + unsigned long mask; + unsigned long flags; + unsigned long res; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + res = (mask & *a); + *a &= ~mask; + raw_local_irq_restore(flags); + return res; +} +EXPORT_SYMBOL(__mips_test_and_clear_bit); + + +/** + * __mips_test_and_change_bit - Change a bit and return its old value. This is + * called by test_and_change_bit() if it cannot find a faster solution. + * @nr: Bit to change + * @addr: Address to count from + */ +int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr) +{ + volatile unsigned long *a = addr; + unsigned bit = nr & SZLONG_MASK; + unsigned long mask; + unsigned long flags; + unsigned long res; + + a += nr >> SZLONG_LOG; + mask = 1UL << bit; + raw_local_irq_save(flags); + res = (mask & *a); + *a ^= mask; + raw_local_irq_restore(flags); + return res; +} +EXPORT_SYMBOL(__mips_test_and_change_bit); diff --git a/arch/mips/lib/delay.c b/arch/mips/lib/delay.c index 5995969e8c4..dc81ca8dc0d 100644 --- a/arch/mips/lib/delay.c +++ b/arch/mips/lib/delay.c @@ -15,13 +15,17 @@ #include <asm/compiler.h> #include <asm/war.h> -inline void __delay(unsigned int loops) +void __delay(unsigned long loops) { __asm__ __volatile__ ( " .set noreorder \n" " .align 3 \n" "1: bnez %0, 1b \n" +#if __SIZEOF_LONG__ == 4 " subu %0, 1 \n" +#else + " dsubu %0, 1 \n" +#endif " .set reorder \n" : "=r" (loops) : "0" (loops)); diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index 3f69725556a..a99c1d3fc56 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c @@ -50,8 +50,9 @@ static void dump_tlb(int first, int last) { unsigned long s_entryhi, entryhi, asid; unsigned long long entrylo0, entrylo1; - unsigned int s_index, pagemask, c0, c1, i; + unsigned int s_index, s_pagemask, pagemask, c0, c1, i; + s_pagemask = read_c0_pagemask(); s_entryhi = read_c0_entryhi(); s_index = read_c0_index(); asid = s_entryhi & 0xff; @@ -103,6 +104,7 @@ static void dump_tlb(int first, int last) write_c0_entryhi(s_entryhi); write_c0_index(s_index); + write_c0_pagemask(s_pagemask); } void dump_tlb_all(void) diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c new file mode 100644 index 00000000000..cd160be3ce4 --- /dev/null +++ b/arch/mips/lib/mips-atomic.c @@ -0,0 +1,176 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle + * Copyright (C) 1996 by Paul M. Antoine + * Copyright (C) 1999 Silicon Graphics + * Copyright (C) 2000 MIPS Technologies, Inc. + */ +#include <asm/irqflags.h> +#include <asm/hazards.h> +#include <linux/compiler.h> +#include <linux/preempt.h> +#include <linux/export.h> + +#if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) + +/* + * For cli() we have to insert nops to make sure that the new value + * has actually arrived in the status register before the end of this + * macro. + * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs + * no nops at all. + */ +/* + * For TX49, operating only IE bit is not enough. + * + * If mfc0 $12 follows store and the mfc0 is last instruction of a + * page and fetching the next instruction causes TLB miss, the result + * of the mfc0 might wrongly contain EXL bit. + * + * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008 + * + * Workaround: mask EXL bit of the result or place a nop before mfc0. + */ +__asm__( + " .macro arch_local_irq_disable\n" + " .set push \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 $1, $2, 1 \n" + " ori $1, 0x400 \n" + " .set noreorder \n" + " mtc0 $1, $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) + /* see irqflags.h for inline function */ +#else + " mfc0 $1,$12 \n" + " ori $1,0x1f \n" + " xori $1,0x1f \n" + " .set noreorder \n" + " mtc0 $1,$12 \n" +#endif + " irq_disable_hazard \n" + " .set pop \n" + " .endm \n"); + +notrace void arch_local_irq_disable(void) +{ + preempt_disable(); + __asm__ __volatile__( + "arch_local_irq_disable" + : /* no outputs */ + : /* no inputs */ + : "memory"); + preempt_enable(); +} +EXPORT_SYMBOL(arch_local_irq_disable); + + +__asm__( + " .macro arch_local_irq_save result \n" + " .set push \n" + " .set reorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 \\result, $2, 1 \n" + " ori $1, \\result, 0x400 \n" + " .set noreorder \n" + " mtc0 $1, $2, 1 \n" + " andi \\result, \\result, 0x400 \n" +#elif defined(CONFIG_CPU_MIPSR2) + /* see irqflags.h for inline function */ +#else + " mfc0 \\result, $12 \n" + " ori $1, \\result, 0x1f \n" + " xori $1, 0x1f \n" + " .set noreorder \n" + " mtc0 $1, $12 \n" +#endif + " irq_disable_hazard \n" + " .set pop \n" + " .endm \n"); + +notrace unsigned long arch_local_irq_save(void) +{ + unsigned long flags; + preempt_disable(); + asm volatile("arch_local_irq_save\t%0" + : "=r" (flags) + : /* no inputs */ + : "memory"); + preempt_enable(); + return flags; +} +EXPORT_SYMBOL(arch_local_irq_save); + + +__asm__( + " .macro arch_local_irq_restore flags \n" + " .set push \n" + " .set noreorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + "mfc0 $1, $2, 1 \n" + "andi \\flags, 0x400 \n" + "ori $1, 0x400 \n" + "xori $1, 0x400 \n" + "or \\flags, $1 \n" + "mtc0 \\flags, $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) + /* see irqflags.h for inline function */ +#elif defined(CONFIG_CPU_MIPSR2) + /* see irqflags.h for inline function */ +#else + " mfc0 $1, $12 \n" + " andi \\flags, 1 \n" + " ori $1, 0x1f \n" + " xori $1, 0x1f \n" + " or \\flags, $1 \n" + " mtc0 \\flags, $12 \n" +#endif + " irq_disable_hazard \n" + " .set pop \n" + " .endm \n"); + +notrace void arch_local_irq_restore(unsigned long flags) +{ + unsigned long __tmp1; + +#ifdef CONFIG_MIPS_MT_SMTC + /* + * SMTC kernel needs to do a software replay of queued + * IPIs, at the cost of branch and call overhead on each + * local_irq_restore() + */ + if (unlikely(!(flags & 0x0400))) + smtc_ipi_replay(); +#endif + preempt_disable(); + __asm__ __volatile__( + "arch_local_irq_restore\t%0" + : "=r" (__tmp1) + : "0" (flags) + : "memory"); + preempt_enable(); +} +EXPORT_SYMBOL(arch_local_irq_restore); + + +notrace void __arch_local_irq_restore(unsigned long flags) +{ + unsigned long __tmp1; + + preempt_disable(); + __asm__ __volatile__( + "arch_local_irq_restore\t%0" + : "=r" (__tmp1) + : "0" (flags) + : "memory"); + preempt_enable(); +} +EXPORT_SYMBOL(__arch_local_irq_restore); + +#endif /* !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) */ diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 87b9cfcc30f..4b9b935a070 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -320,6 +320,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) tlb_write_random(); else tlb_write_indexed(); + tlbw_use_hazard(); write_c0_pagemask(PM_DEFAULT_MASK); } else #endif diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 658a520364c..2833dcb67b5 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -148,8 +148,8 @@ enum label_id { label_leave, label_vmalloc, label_vmalloc_done, - label_tlbw_hazard, - label_split, + label_tlbw_hazard_0, + label_split = label_tlbw_hazard_0 + 8, label_tlbl_goaround1, label_tlbl_goaround2, label_nopage_tlbl, @@ -167,7 +167,7 @@ UASM_L_LA(_second_part) UASM_L_LA(_leave) UASM_L_LA(_vmalloc) UASM_L_LA(_vmalloc_done) -UASM_L_LA(_tlbw_hazard) +/* _tlbw_hazard_x is handled differently. */ UASM_L_LA(_split) UASM_L_LA(_tlbl_goaround1) UASM_L_LA(_tlbl_goaround2) @@ -181,6 +181,30 @@ UASM_L_LA(_large_segbits_fault) UASM_L_LA(_tlb_huge_update) #endif +static int __cpuinitdata hazard_instance; + +static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance) +{ + switch (instance) { + case 0 ... 7: + uasm_il_bgezl(p, r, 0, label_tlbw_hazard_0 + instance); + return; + default: + BUG(); + } +} + +static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance) +{ + switch (instance) { + case 0 ... 7: + uasm_build_label(l, *p, label_tlbw_hazard_0 + instance); + break; + default: + BUG(); + } +} + /* * For debug purposes. */ @@ -478,21 +502,28 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, * This branch uses up a mtc0 hazard nop slot and saves * two nops after the tlbw instruction. */ - uasm_il_bgezl(p, r, 0, label_tlbw_hazard); + uasm_bgezl_hazard(p, r, hazard_instance); tlbw(p); - uasm_l_tlbw_hazard(l, *p); + uasm_bgezl_label(l, p, hazard_instance); + hazard_instance++; uasm_i_nop(p); break; case CPU_R4600: case CPU_R4700: - case CPU_R5000: - case CPU_R5000A: uasm_i_nop(p); tlbw(p); uasm_i_nop(p); break; + case CPU_R5000: + case CPU_R5000A: + case CPU_NEVADA: + uasm_i_nop(p); /* QED specifies 2 nops hazard */ + uasm_i_nop(p); /* QED specifies 2 nops hazard */ + tlbw(p); + break; + case CPU_R4300: case CPU_5KC: case CPU_TX49XX: @@ -526,17 +557,6 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, tlbw(p); break; - case CPU_NEVADA: - uasm_i_nop(p); /* QED specifies 2 nops hazard */ - /* - * This branch uses up a mtc0 hazard nop slot and saves - * a nop after the tlbw instruction. - */ - uasm_il_bgezl(p, r, 0, label_tlbw_hazard); - tlbw(p); - uasm_l_tlbw_hazard(l, *p); - break; - case CPU_RM7000: uasm_i_nop(p); uasm_i_nop(p); diff --git a/arch/mips/mti-malta/malta-platform.c b/arch/mips/mti-malta/malta-platform.c index 80562b81f0f..74732177851 100644 --- a/arch/mips/mti-malta/malta-platform.c +++ b/arch/mips/mti-malta/malta-platform.c @@ -29,6 +29,7 @@ #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> #include <linux/platform_device.h> +#include <asm/mips-boards/maltaint.h> #include <mtd/mtd-abi.h> #define SMC_PORT(base, int) \ @@ -48,7 +49,7 @@ static struct plat_serial8250_port uart8250_data[] = { SMC_PORT(0x2F8, 3), { .mapbase = 0x1f000900, /* The CBUS UART */ - .irq = MIPS_CPU_IRQ_BASE + 2, + .irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2, .uartclk = 3686400, /* Twice the usual clk! */ .iotype = UPIO_MEM32, .flags = CBUS_UART_FLAGS, diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index 04669fac117..72471744a91 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig @@ -9,6 +9,7 @@ config MN10300 select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER select GENERIC_CLOCKEVENTS select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE select MODULES_USE_ELF_RELA config AM33_2 diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h index 55bbec1887e..9711d51b021 100644 --- a/arch/mn10300/include/asm/unistd.h +++ b/arch/mn10300/include/asm/unistd.h @@ -44,7 +44,6 @@ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_SYS_EXECVE -#define __ARCH_WANT_KERNEL_EXECVE /* * "Conditional" syscalls diff --git a/arch/mn10300/include/uapi/asm/setup.h b/arch/mn10300/include/uapi/asm/setup.h index e69de29bb2d..ae5704fa77a 100644 --- a/arch/mn10300/include/uapi/asm/setup.h +++ b/arch/mn10300/include/uapi/asm/setup.h @@ -0,0 +1,4 @@ +/* + * There isn't anything here anymore, but the file must not be empty or patch + * will delete it. + */ diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S index 0c631d34c8d..68fcab8f8f6 100644 --- a/arch/mn10300/kernel/entry.S +++ b/arch/mn10300/kernel/entry.S @@ -60,13 +60,8 @@ ENTRY(ret_from_kernel_thread) mov (REG_D0,fp),d0 mov (REG_A0,fp),a0 calls (a0) - jmp sys_exit - -ENTRY(ret_from_kernel_execve) - add -12,d0 /* pt_regs -> frame */ - mov d0,sp - GET_THREAD_INFO a2 clr d0 + mov d0,(REG_D0,fp) jmp syscall_exit ############################################################################### diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 05f2ba41ff1..e7f1a2993f7 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig @@ -22,6 +22,8 @@ config OPENRISC select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNLEN_USER select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE config MMU def_bool y diff --git a/arch/openrisc/include/uapi/asm/unistd.h b/arch/openrisc/include/uapi/asm/unistd.h index 437bdbb61b1..5db7bc0fa5a 100644 --- a/arch/openrisc/include/uapi/asm/unistd.h +++ b/arch/openrisc/include/uapi/asm/unistd.h @@ -20,6 +20,8 @@ #define sys_mmap2 sys_mmap_pgoff +#define __ARCH_WANT_SYS_EXECVE + #include <asm-generic/unistd.h> #define __NR_or1k_atomic __NR_arch_specific_syscall diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S index ddfcaa828b0..c60a09df323 100644 --- a/arch/openrisc/kernel/entry.S +++ b/arch/openrisc/kernel/entry.S @@ -894,6 +894,16 @@ ENTRY(ret_from_fork) l.jal schedule_tail l.nop + /* Check if we are a kernel thread */ + l.sfeqi r20,0 + l.bf 1f + l.nop + + /* ...we are a kernel thread so invoke the requested callback */ + l.jalr r20 + l.or r3,r22,r0 + +1: /* _syscall_returns expect r11 to contain return value */ l.lwz r11,PT_GPR11(r1) @@ -915,26 +925,6 @@ ENTRY(ret_from_fork) l.j _syscall_return l.nop -/* Since syscalls don't save call-clobbered registers, the args to - * kernel_thread_helper will need to be passed through callee-saved - * registers and copied to the parameter registers when the thread - * begins running. - * - * See arch/openrisc/kernel/process.c: - * The args are passed as follows: - * arg1 (r3) : passed in r20 - * arg2 (r4) : passed in r22 - */ - -ENTRY(_kernel_thread_helper) - l.or r3,r20,r0 - l.or r4,r22,r0 - l.movhi r31,hi(kernel_thread_helper) - l.ori r31,r31,lo(kernel_thread_helper) - l.jr r31 - l.nop - - /* ========================================================[ switch ] === */ /* @@ -1044,8 +1034,13 @@ ENTRY(_switch) /* Unwind stack to pre-switch state */ l.addi r1,r1,(INT_FRAME_SIZE) - /* Return via the link-register back to where we 'came from', where that can be - * either schedule() or return_from_fork()... */ + /* Return via the link-register back to where we 'came from', where + * that may be either schedule(), ret_from_fork(), or + * ret_from_kernel_thread(). If we are returning to a new thread, + * we are expected to have set up the arg to schedule_tail already, + * hence we do so here unconditionally: + */ + l.lwz r3,TI_STACK(r3) /* Load 'prev' as schedule_tail arg */ l.jr r9 l.nop @@ -1088,10 +1083,6 @@ ENTRY(sys_fork) l.j _fork_save_extra_regs_and_call l.addi r3,r1,0 -ENTRY(sys_execve) - l.j _sys_execve - l.addi r6,r1,0 - ENTRY(sys_sigaltstack) l.j _sys_sigaltstack l.addi r5,r1,0 diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index c35f3ab1a8d..e0874b8e09e 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -109,66 +109,82 @@ void release_thread(struct task_struct *dead_task) */ extern asmlinkage void ret_from_fork(void); +/* + * copy_thread + * @clone_flags: flags + * @usp: user stack pointer or fn for kernel thread + * @arg: arg to fn for kernel thread; always NULL for userspace thread + * @p: the newly created task + * @regs: CPU context to copy for userspace thread; always NULL for kthread + * + * At the top of a newly initialized kernel stack are two stacked pt_reg + * structures. The first (topmost) is the userspace context of the thread. + * The second is the kernelspace context of the thread. + * + * A kernel thread will not be returning to userspace, so the topmost pt_regs + * struct can be uninitialized; it _does_ need to exist, though, because + * a kernel thread can become a userspace thread by doing a kernel_execve, in + * which case the topmost context will be initialized and used for 'returning' + * to userspace. + * + * The second pt_reg struct needs to be initialized to 'return' to + * ret_from_fork. A kernel thread will need to set r20 to the address of + * a function to call into (with arg in r22); userspace threads need to set + * r20 to NULL in which case ret_from_fork will just continue a return to + * userspace. + * + * A kernel thread 'fn' may return; this is effectively what happens when + * kernel_execve is called. In that case, the userspace pt_regs must have + * been initialized (which kernel_execve takes care of, see start_thread + * below); ret_from_fork will then continue its execution causing the + * 'kernel thread' to return to userspace as a userspace thread. + */ + int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { - struct pt_regs *childregs; + struct pt_regs *userregs; struct pt_regs *kregs; unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; - struct thread_info *ti; unsigned long top_of_kernel_stack; top_of_kernel_stack = sp; p->set_child_tid = p->clear_child_tid = NULL; - /* Copy registers */ - /* redzone */ - sp -= STACK_FRAME_OVERHEAD; + /* Locate userspace context on stack... */ + sp -= STACK_FRAME_OVERHEAD; /* redzone */ sp -= sizeof(struct pt_regs); - childregs = (struct pt_regs *)sp; + userregs = (struct pt_regs *) sp; - /* Copy parent registers */ - *childregs = *regs; + /* ...and kernel context */ + sp -= STACK_FRAME_OVERHEAD; /* redzone */ + sp -= sizeof(struct pt_regs); + kregs = (struct pt_regs *)sp; - if ((childregs->sr & SPR_SR_SM) == 1) { - /* for kernel thread, set `current_thread_info' - * and stackptr in new task - */ - childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; - childregs->gpr[10] = (unsigned long)task_thread_info(p); + if (unlikely(p->flags & PF_KTHREAD)) { + memset(kregs, 0, sizeof(struct pt_regs)); + kregs->gpr[20] = usp; /* fn, kernel thread */ + kregs->gpr[22] = arg; } else { - childregs->sp = usp; - } - - childregs->gpr[11] = 0; /* Result from fork() */ + *userregs = *regs; - /* - * The way this works is that at some point in the future - * some task will call _switch to switch to the new task. - * That will pop off the stack frame created below and start - * the new task running at ret_from_fork. The new task will - * do some house keeping and then return from the fork or clone - * system call, using the stack frame created above. - */ - /* redzone */ - sp -= STACK_FRAME_OVERHEAD; - sp -= sizeof(struct pt_regs); - kregs = (struct pt_regs *)sp; + userregs->sp = usp; + userregs->gpr[11] = 0; /* Result from fork() */ - ti = task_thread_info(p); - ti->ksp = sp; + kregs->gpr[20] = 0; /* Userspace thread */ + } - /* kregs->sp must store the location of the 'pre-switch' kernel stack - * pointer... for a newly forked process, this is simply the top of - * the kernel stack. + /* + * _switch wants the kernel stack page in pt_regs->sp so that it + * can restore it to thread_info->ksp... see _switch for details. */ kregs->sp = top_of_kernel_stack; - kregs->gpr[3] = (unsigned long)current; /* arg to schedule_tail */ - kregs->gpr[10] = (unsigned long)task_thread_info(p); kregs->gpr[9] = (unsigned long)ret_from_fork; + task_thread_info(p)->ksp = (unsigned long)kregs; + return 0; } @@ -177,16 +193,14 @@ copy_thread(unsigned long clone_flags, unsigned long usp, */ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { - unsigned long sr = regs->sr & ~SPR_SR_SM; + unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM; set_fs(USER_DS); - memset(regs->gpr, 0, sizeof(regs->gpr)); + memset(regs, 0, sizeof(struct pt_regs)); regs->pc = pc; regs->sr = sr; regs->sp = sp; - -/* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/ } /* Fill in the fpu structure for a core dump. */ @@ -237,74 +251,9 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs) dest[35] = 0; } -extern void _kernel_thread_helper(void); - -void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg) -{ - do_exit(fn(arg)); -} - -/* - * Create a kernel thread. - */ -int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.gpr[20] = (unsigned long)fn; - regs.gpr[22] = (unsigned long)arg; - regs.sr = mfspr(SPR_SR); - regs.pc = (unsigned long)_kernel_thread_helper; - - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, - 0, ®s, 0, NULL, NULL); -} - -/* - * sys_execve() executes a new program. - */ -asmlinkage long _sys_execve(const char __user *name, - const char __user * const __user *argv, - const char __user * const __user *envp, - struct pt_regs *regs) -{ - int error; - struct filename *filename; - - filename = getname(name); - error = PTR_ERR(filename); - - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename->name, argv, envp, regs); - putname(filename); - -out: - return error; -} - unsigned long get_wchan(struct task_struct *p) { /* TODO */ return 0; } - -int kernel_execve(const char *filename, char *const argv[], char *const envp[]) -{ - register long __res asm("r11") = __NR_execve; - register long __a asm("r3") = (long)(filename); - register long __b asm("r4") = (long)(argv); - register long __c asm("r5") = (long)(envp); - __asm__ volatile ("l.sys 1" - : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c) - : "0"(__res), "1"(__a), "2"(__b), "3"(__c) - : "r6", "r7", "r8", "r12", "r13", "r15", - "r17", "r19", "r21", "r23", "r25", "r27", - "r29", "r31"); - __asm__ volatile ("l.nop"); - return __res; -} diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 30110297f4f..ddedc8a7786 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c @@ -84,7 +84,6 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe *frame = (struct rt_sigframe __user *)regs->sp; sigset_t set; - stack_t st; /* * Since we stacked the signal on a dword boundary, @@ -104,11 +103,10 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs) if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; - if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) - goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, regs->sp); + if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) + goto badframe; return regs->gpr[11]; diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 11def45b98c..0aec70c3561 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -22,6 +22,8 @@ config PARISC select GENERIC_STRNCPY_FROM_USER select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE help The PA-RISC microprocessor is designed by Hewlett-Packard and used diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild index 458371a1565..bac8debecff 100644 --- a/arch/parisc/include/asm/Kbuild +++ b/arch/parisc/include/asm/Kbuild @@ -1,6 +1,5 @@ -include include/asm-generic/Kbuild.asm -header-y += pdc.h -generic-y += clkdev.h -generic-y += word-at-a-time.h -generic-y += exec.h +generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \ + segment.h topology.h vga.h device.h percpu.h hw_irq.h mutex.h \ + div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \ + poll.h xor.h clkdev.h exec.h diff --git a/arch/parisc/include/asm/auxvec.h b/arch/parisc/include/asm/auxvec.h deleted file mode 100644 index 9c3ac4b89dc..00000000000 --- a/arch/parisc/include/asm/auxvec.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __ASMPARISC_AUXVEC_H -#define __ASMPARISC_AUXVEC_H - -#endif diff --git a/arch/parisc/include/asm/compat_signal.h b/arch/parisc/include/asm/compat_signal.h deleted file mode 100644 index 6ad02c360b2..00000000000 --- a/arch/parisc/include/asm/compat_signal.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Use generic */ -#include <asm-generic/compat_signal.h> diff --git a/arch/parisc/include/asm/cputime.h b/arch/parisc/include/asm/cputime.h deleted file mode 100644 index dcdf2fbd7e7..00000000000 --- a/arch/parisc/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __PARISC_CPUTIME_H -#define __PARISC_CPUTIME_H - -#include <asm-generic/cputime.h> - -#endif /* __PARISC_CPUTIME_H */ diff --git a/arch/parisc/include/asm/device.h b/arch/parisc/include/asm/device.h deleted file mode 100644 index d8f9872b0e2..00000000000 --- a/arch/parisc/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/parisc/include/asm/div64.h b/arch/parisc/include/asm/div64.h deleted file mode 100644 index 6cd978cefb2..00000000000 --- a/arch/parisc/include/asm/div64.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/div64.h> diff --git a/arch/parisc/include/asm/emergency-restart.h b/arch/parisc/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c48e42..00000000000 --- a/arch/parisc/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/parisc/include/asm/hw_irq.h b/arch/parisc/include/asm/hw_irq.h deleted file mode 100644 index 6707f7df392..00000000000 --- a/arch/parisc/include/asm/hw_irq.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _ASM_HW_IRQ_H -#define _ASM_HW_IRQ_H - -/* - * linux/include/asm/hw_irq.h - */ - -#endif diff --git a/arch/parisc/include/asm/irq_regs.h b/arch/parisc/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b7027..00000000000 --- a/arch/parisc/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/irq_regs.h> diff --git a/arch/parisc/include/asm/kdebug.h b/arch/parisc/include/asm/kdebug.h deleted file mode 100644 index 6ece1b03766..00000000000 --- a/arch/parisc/include/asm/kdebug.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/kdebug.h> diff --git a/arch/parisc/include/asm/kvm_para.h b/arch/parisc/include/asm/kvm_para.h deleted file mode 100644 index 14fab8f0b95..00000000000 --- a/arch/parisc/include/asm/kvm_para.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/kvm_para.h> diff --git a/arch/parisc/include/asm/local.h b/arch/parisc/include/asm/local.h deleted file mode 100644 index c11c530f74d..00000000000 --- a/arch/parisc/include/asm/local.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/local.h> diff --git a/arch/parisc/include/asm/local64.h b/arch/parisc/include/asm/local64.h deleted file mode 100644 index 36c93b5cc23..00000000000 --- a/arch/parisc/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/local64.h> diff --git a/arch/parisc/include/asm/mutex.h b/arch/parisc/include/asm/mutex.h deleted file mode 100644 index 458c1f7fbc1..00000000000 --- a/arch/parisc/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/parisc/include/asm/param.h b/arch/parisc/include/asm/param.h deleted file mode 100644 index 965d4542797..00000000000 --- a/arch/parisc/include/asm/param.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/param.h> diff --git a/arch/parisc/include/asm/pdc.h b/arch/parisc/include/asm/pdc.h index 7f0f2d23059..7eb616e4bf8 100644 --- a/arch/parisc/include/asm/pdc.h +++ b/arch/parisc/include/asm/pdc.h @@ -1,348 +1,10 @@ #ifndef _PARISC_PDC_H #define _PARISC_PDC_H -/* - * PDC return values ... - * All PDC calls return a subset of these errors. - */ - -#define PDC_WARN 3 /* Call completed with a warning */ -#define PDC_REQ_ERR_1 2 /* See above */ -#define PDC_REQ_ERR_0 1 /* Call would generate a requestor error */ -#define PDC_OK 0 /* Call completed successfully */ -#define PDC_BAD_PROC -1 /* Called non-existent procedure*/ -#define PDC_BAD_OPTION -2 /* Called with non-existent option */ -#define PDC_ERROR -3 /* Call could not complete without an error */ -#define PDC_NE_MOD -5 /* Module not found */ -#define PDC_NE_CELL_MOD -7 /* Cell module not found */ -#define PDC_INVALID_ARG -10 /* Called with an invalid argument */ -#define PDC_BUS_POW_WARN -12 /* Call could not complete in allowed power budget */ -#define PDC_NOT_NARROW -17 /* Narrow mode not supported */ - -/* - * PDC entry points... - */ - -#define PDC_POW_FAIL 1 /* perform a power-fail */ -#define PDC_POW_FAIL_PREPARE 0 /* prepare for powerfail */ - -#define PDC_CHASSIS 2 /* PDC-chassis functions */ -#define PDC_CHASSIS_DISP 0 /* update chassis display */ -#define PDC_CHASSIS_WARN 1 /* return chassis warnings */ -#define PDC_CHASSIS_DISPWARN 2 /* update&return chassis status */ -#define PDC_RETURN_CHASSIS_INFO 128 /* HVERSION dependent: return chassis LED/LCD info */ - -#define PDC_PIM 3 /* Get PIM data */ -#define PDC_PIM_HPMC 0 /* Transfer HPMC data */ -#define PDC_PIM_RETURN_SIZE 1 /* Get Max buffer needed for PIM*/ -#define PDC_PIM_LPMC 2 /* Transfer HPMC data */ -#define PDC_PIM_SOFT_BOOT 3 /* Transfer Soft Boot data */ -#define PDC_PIM_TOC 4 /* Transfer TOC data */ - -#define PDC_MODEL 4 /* PDC model information call */ -#define PDC_MODEL_INFO 0 /* returns information */ -#define PDC_MODEL_BOOTID 1 /* set the BOOT_ID */ -#define PDC_MODEL_VERSIONS 2 /* returns cpu-internal versions*/ -#define PDC_MODEL_SYSMODEL 3 /* return system model info */ -#define PDC_MODEL_ENSPEC 4 /* enable specific option */ -#define PDC_MODEL_DISPEC 5 /* disable specific option */ -#define PDC_MODEL_CPU_ID 6 /* returns cpu-id (only newer machines!) */ -#define PDC_MODEL_CAPABILITIES 7 /* returns OS32/OS64-flags */ -/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */ -#define PDC_MODEL_OS64 (1 << 0) -#define PDC_MODEL_OS32 (1 << 1) -#define PDC_MODEL_IOPDIR_FDC (1 << 2) -#define PDC_MODEL_NVA_MASK (3 << 4) -#define PDC_MODEL_NVA_SUPPORTED (0 << 4) -#define PDC_MODEL_NVA_SLOW (1 << 4) -#define PDC_MODEL_NVA_UNSUPPORTED (3 << 4) -#define PDC_MODEL_GET_BOOT__OP 8 /* returns boot test options */ -#define PDC_MODEL_SET_BOOT__OP 9 /* set boot test options */ - -#define PA89_INSTRUCTION_SET 0x4 /* capatibilies returned */ -#define PA90_INSTRUCTION_SET 0x8 - -#define PDC_CACHE 5 /* return/set cache (& TLB) info*/ -#define PDC_CACHE_INFO 0 /* returns information */ -#define PDC_CACHE_SET_COH 1 /* set coherence state */ -#define PDC_CACHE_RET_SPID 2 /* returns space-ID bits */ - -#define PDC_HPA 6 /* return HPA of processor */ -#define PDC_HPA_PROCESSOR 0 -#define PDC_HPA_MODULES 1 - -#define PDC_COPROC 7 /* Co-Processor (usually FP unit(s)) */ -#define PDC_COPROC_CFG 0 /* Co-Processor Cfg (FP unit(s) enabled?) */ - -#define PDC_IODC 8 /* talk to IODC */ -#define PDC_IODC_READ 0 /* read IODC entry point */ -/* PDC_IODC_RI_ * INDEX parameter of PDC_IODC_READ */ -#define PDC_IODC_RI_DATA_BYTES 0 /* IODC Data Bytes */ -/* 1, 2 obsolete - HVERSION dependent*/ -#define PDC_IODC_RI_INIT 3 /* Initialize module */ -#define PDC_IODC_RI_IO 4 /* Module input/output */ -#define PDC_IODC_RI_SPA 5 /* Module input/output */ -#define PDC_IODC_RI_CONFIG 6 /* Module input/output */ -/* 7 obsolete - HVERSION dependent */ -#define PDC_IODC_RI_TEST 8 /* Module input/output */ -#define PDC_IODC_RI_TLB 9 /* Module input/output */ -#define PDC_IODC_NINIT 2 /* non-destructive init */ -#define PDC_IODC_DINIT 3 /* destructive init */ -#define PDC_IODC_MEMERR 4 /* check for memory errors */ -#define PDC_IODC_INDEX_DATA 0 /* get first 16 bytes from mod IODC */ -#define PDC_IODC_BUS_ERROR -4 /* bus error return value */ -#define PDC_IODC_INVALID_INDEX -5 /* invalid index return value */ -#define PDC_IODC_COUNT -6 /* count is too small */ - -#define PDC_TOD 9 /* time-of-day clock (TOD) */ -#define PDC_TOD_READ 0 /* read TOD */ -#define PDC_TOD_WRITE 1 /* write TOD */ - - -#define PDC_STABLE 10 /* stable storage (sprockets) */ -#define PDC_STABLE_READ 0 -#define PDC_STABLE_WRITE 1 -#define PDC_STABLE_RETURN_SIZE 2 -#define PDC_STABLE_VERIFY_CONTENTS 3 -#define PDC_STABLE_INITIALIZE 4 - -#define PDC_NVOLATILE 11 /* often not implemented */ - -#define PDC_ADD_VALID 12 /* Memory validation PDC call */ -#define PDC_ADD_VALID_VERIFY 0 /* Make PDC_ADD_VALID verify region */ - -#define PDC_INSTR 15 /* get instr to invoke PDCE_CHECK() */ - -#define PDC_PROC 16 /* (sprockets) */ - -#define PDC_CONFIG 16 /* (sprockets) */ -#define PDC_CONFIG_DECONFIG 0 -#define PDC_CONFIG_DRECONFIG 1 -#define PDC_CONFIG_DRETURN_CONFIG 2 - -#define PDC_BLOCK_TLB 18 /* manage hardware block-TLB */ -#define PDC_BTLB_INFO 0 /* returns parameter */ -#define PDC_BTLB_INSERT 1 /* insert BTLB entry */ -#define PDC_BTLB_PURGE 2 /* purge BTLB entries */ -#define PDC_BTLB_PURGE_ALL 3 /* purge all BTLB entries */ - -#define PDC_TLB 19 /* manage hardware TLB miss handling */ -#define PDC_TLB_INFO 0 /* returns parameter */ -#define PDC_TLB_SETUP 1 /* set up miss handling */ - -#define PDC_MEM 20 /* Manage memory */ -#define PDC_MEM_MEMINFO 0 -#define PDC_MEM_ADD_PAGE 1 -#define PDC_MEM_CLEAR_PDT 2 -#define PDC_MEM_READ_PDT 3 -#define PDC_MEM_RESET_CLEAR 4 -#define PDC_MEM_GOODMEM 5 -#define PDC_MEM_TABLE 128 /* Non contig mem map (sprockets) */ -#define PDC_MEM_RETURN_ADDRESS_TABLE PDC_MEM_TABLE -#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE 131 -#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES 132 -#define PDC_MEM_GET_PHYSICAL_LOCATION_FROM_MEMORY_ADDRESS 133 - -#define PDC_MEM_RET_SBE_REPLACED 5 /* PDC_MEM return values */ -#define PDC_MEM_RET_DUPLICATE_ENTRY 4 -#define PDC_MEM_RET_BUF_SIZE_SMALL 1 -#define PDC_MEM_RET_PDT_FULL -11 -#define PDC_MEM_RET_INVALID_PHYSICAL_LOCATION ~0ULL - -#define PDC_PSW 21 /* Get/Set default System Mask */ -#define PDC_PSW_MASK 0 /* Return mask */ -#define PDC_PSW_GET_DEFAULTS 1 /* Return defaults */ -#define PDC_PSW_SET_DEFAULTS 2 /* Set default */ -#define PDC_PSW_ENDIAN_BIT 1 /* set for big endian */ -#define PDC_PSW_WIDE_BIT 2 /* set for wide mode */ - -#define PDC_SYSTEM_MAP 22 /* find system modules */ -#define PDC_FIND_MODULE 0 -#define PDC_FIND_ADDRESS 1 -#define PDC_TRANSLATE_PATH 2 - -#define PDC_SOFT_POWER 23 /* soft power switch */ -#define PDC_SOFT_POWER_INFO 0 /* return info about the soft power switch */ -#define PDC_SOFT_POWER_ENABLE 1 /* enable/disable soft power switch */ - - -/* HVERSION dependent */ - -/* The PDC_MEM_MAP calls */ -#define PDC_MEM_MAP 128 /* on s700: return page info */ -#define PDC_MEM_MAP_HPA 0 /* returns hpa of a module */ - -#define PDC_EEPROM 129 /* EEPROM access */ -#define PDC_EEPROM_READ_WORD 0 -#define PDC_EEPROM_WRITE_WORD 1 -#define PDC_EEPROM_READ_BYTE 2 -#define PDC_EEPROM_WRITE_BYTE 3 -#define PDC_EEPROM_EEPROM_PASSWORD -1000 - -#define PDC_NVM 130 /* NVM (non-volatile memory) access */ -#define PDC_NVM_READ_WORD 0 -#define PDC_NVM_WRITE_WORD 1 -#define PDC_NVM_READ_BYTE 2 -#define PDC_NVM_WRITE_BYTE 3 - -#define PDC_SEED_ERROR 132 /* (sprockets) */ - -#define PDC_IO 135 /* log error info, reset IO system */ -#define PDC_IO_READ_AND_CLEAR_ERRORS 0 -#define PDC_IO_RESET 1 -#define PDC_IO_RESET_DEVICES 2 -/* sets bits 6&7 (little endian) of the HcControl Register */ -#define PDC_IO_USB_SUSPEND 0xC000000000000000 -#define PDC_IO_EEPROM_IO_ERR_TABLE_FULL -5 /* return value */ -#define PDC_IO_NO_SUSPEND -6 /* return value */ - -#define PDC_BROADCAST_RESET 136 /* reset all processors */ -#define PDC_DO_RESET 0 /* option: perform a broadcast reset */ -#define PDC_DO_FIRM_TEST_RESET 1 /* Do broadcast reset with bitmap */ -#define PDC_BR_RECONFIGURATION 2 /* reset w/reconfiguration */ -#define PDC_FIRM_TEST_MAGIC 0xab9ec36fUL /* for this reboot only */ - -#define PDC_LAN_STATION_ID 138 /* Hversion dependent mechanism for */ -#define PDC_LAN_STATION_ID_READ 0 /* getting the lan station address */ - -#define PDC_LAN_STATION_ID_SIZE 6 - -#define PDC_CHECK_RANGES 139 /* (sprockets) */ - -#define PDC_NV_SECTIONS 141 /* (sprockets) */ - -#define PDC_PERFORMANCE 142 /* performance monitoring */ - -#define PDC_SYSTEM_INFO 143 /* system information */ -#define PDC_SYSINFO_RETURN_INFO_SIZE 0 -#define PDC_SYSINFO_RRETURN_SYS_INFO 1 -#define PDC_SYSINFO_RRETURN_ERRORS 2 -#define PDC_SYSINFO_RRETURN_WARNINGS 3 -#define PDC_SYSINFO_RETURN_REVISIONS 4 -#define PDC_SYSINFO_RRETURN_DIAGNOSE 5 -#define PDC_SYSINFO_RRETURN_HV_DIAGNOSE 1005 - -#define PDC_RDR 144 /* (sprockets) */ -#define PDC_RDR_READ_BUFFER 0 -#define PDC_RDR_READ_SINGLE 1 -#define PDC_RDR_WRITE_SINGLE 2 - -#define PDC_INTRIGUE 145 /* (sprockets) */ -#define PDC_INTRIGUE_WRITE_BUFFER 0 -#define PDC_INTRIGUE_GET_SCRATCH_BUFSIZE 1 -#define PDC_INTRIGUE_START_CPU_COUNTERS 2 -#define PDC_INTRIGUE_STOP_CPU_COUNTERS 3 - -#define PDC_STI 146 /* STI access */ -/* same as PDC_PCI_XXX values (see below) */ - -/* Legacy PDC definitions for same stuff */ -#define PDC_PCI_INDEX 147 -#define PDC_PCI_INTERFACE_INFO 0 -#define PDC_PCI_SLOT_INFO 1 -#define PDC_PCI_INFLIGHT_BYTES 2 -#define PDC_PCI_READ_CONFIG 3 -#define PDC_PCI_WRITE_CONFIG 4 -#define PDC_PCI_READ_PCI_IO 5 -#define PDC_PCI_WRITE_PCI_IO 6 -#define PDC_PCI_READ_CONFIG_DELAY 7 -#define PDC_PCI_UPDATE_CONFIG_DELAY 8 -#define PDC_PCI_PCI_PATH_TO_PCI_HPA 9 -#define PDC_PCI_PCI_HPA_TO_PCI_PATH 10 -#define PDC_PCI_PCI_PATH_TO_PCI_BUS 11 -#define PDC_PCI_PCI_RESERVED 12 -#define PDC_PCI_PCI_INT_ROUTE_SIZE 13 -#define PDC_PCI_GET_INT_TBL_SIZE PDC_PCI_PCI_INT_ROUTE_SIZE -#define PDC_PCI_PCI_INT_ROUTE 14 -#define PDC_PCI_GET_INT_TBL PDC_PCI_PCI_INT_ROUTE -#define PDC_PCI_READ_MON_TYPE 15 -#define PDC_PCI_WRITE_MON_TYPE 16 - - -/* Get SCSI Interface Card info: SDTR, SCSI ID, mode (SE vs LVD) */ -#define PDC_INITIATOR 163 -#define PDC_GET_INITIATOR 0 -#define PDC_SET_INITIATOR 1 -#define PDC_DELETE_INITIATOR 2 -#define PDC_RETURN_TABLE_SIZE 3 -#define PDC_RETURN_TABLE 4 - -#define PDC_LINK 165 /* (sprockets) */ -#define PDC_LINK_PCI_ENTRY_POINTS 0 /* list (Arg1) = 0 */ -#define PDC_LINK_USB_ENTRY_POINTS 1 /* list (Arg1) = 1 */ - -/* cl_class - * page 3-33 of IO-Firmware ARS - * IODC ENTRY_INIT(Search first) RET[1] - */ -#define CL_NULL 0 /* invalid */ -#define CL_RANDOM 1 /* random access (as disk) */ -#define CL_SEQU 2 /* sequential access (as tape) */ -#define CL_DUPLEX 7 /* full-duplex point-to-point (RS-232, Net) */ -#define CL_KEYBD 8 /* half-duplex console (HIL Keyboard) */ -#define CL_DISPL 9 /* half-duplex console (display) */ -#define CL_FC 10 /* FiberChannel access media */ - -/* IODC ENTRY_INIT() */ -#define ENTRY_INIT_SRCH_FRST 2 -#define ENTRY_INIT_SRCH_NEXT 3 -#define ENTRY_INIT_MOD_DEV 4 -#define ENTRY_INIT_DEV 5 -#define ENTRY_INIT_MOD 6 -#define ENTRY_INIT_MSG 9 - -/* IODC ENTRY_IO() */ -#define ENTRY_IO_BOOTIN 0 -#define ENTRY_IO_BOOTOUT 1 -#define ENTRY_IO_CIN 2 -#define ENTRY_IO_COUT 3 -#define ENTRY_IO_CLOSE 4 -#define ENTRY_IO_GETMSG 9 -#define ENTRY_IO_BBLOCK_IN 16 -#define ENTRY_IO_BBLOCK_OUT 17 - -/* IODC ENTRY_SPA() */ - -/* IODC ENTRY_CONFIG() */ - -/* IODC ENTRY_TEST() */ - -/* IODC ENTRY_TLB() */ - -/* constants for OS (NVM...) */ -#define OS_ID_NONE 0 /* Undefined OS ID */ -#define OS_ID_HPUX 1 /* HP-UX OS */ -#define OS_ID_MPEXL 2 /* MPE XL OS */ -#define OS_ID_OSF 3 /* OSF OS */ -#define OS_ID_HPRT 4 /* HP-RT OS */ -#define OS_ID_NOVEL 5 /* NOVELL OS */ -#define OS_ID_LINUX 6 /* Linux */ - - -/* constants for PDC_CHASSIS */ -#define OSTAT_OFF 0 -#define OSTAT_FLT 1 -#define OSTAT_TEST 2 -#define OSTAT_INIT 3 -#define OSTAT_SHUT 4 -#define OSTAT_WARN 5 -#define OSTAT_RUN 6 -#define OSTAT_ON 7 - -/* Page Zero constant offsets used by the HPMC handler */ -#define BOOT_CONSOLE_HPA_OFFSET 0x3c0 -#define BOOT_CONSOLE_SPA_OFFSET 0x3c4 -#define BOOT_CONSOLE_PATH_OFFSET 0x3a8 - -/* size of the pdc_result buffer for firmware.c */ -#define NUM_PDC_RESULT 32 +#include <uapi/asm/pdc.h> #if !defined(__ASSEMBLY__) -#include <linux/types.h> - -#ifdef __KERNEL__ - extern int pdc_type; /* Values for pdc_type */ @@ -673,88 +335,5 @@ static inline char * os_id_to_string(u16 os_id) { } } -#endif /* __KERNEL__ */ - -/* flags of the device_path */ -#define PF_AUTOBOOT 0x80 -#define PF_AUTOSEARCH 0x40 -#define PF_TIMER 0x0F - -struct device_path { /* page 1-69 */ - unsigned char flags; /* flags see above! */ - unsigned char bc[6]; /* bus converter routing info */ - unsigned char mod; - unsigned int layers[6];/* device-specific layer-info */ -} __attribute__((aligned(8))) ; - -struct pz_device { - struct device_path dp; /* see above */ - /* struct iomod *hpa; */ - unsigned int hpa; /* HPA base address */ - /* char *spa; */ - unsigned int spa; /* SPA base address */ - /* int (*iodc_io)(struct iomod*, ...); */ - unsigned int iodc_io; /* device entry point */ - short pad; /* reserved */ - unsigned short cl_class;/* see below */ -} __attribute__((aligned(8))) ; - -struct zeropage { - /* [0x000] initialize vectors (VEC) */ - unsigned int vec_special; /* must be zero */ - /* int (*vec_pow_fail)(void);*/ - unsigned int vec_pow_fail; /* power failure handler */ - /* int (*vec_toc)(void); */ - unsigned int vec_toc; - unsigned int vec_toclen; - /* int (*vec_rendz)(void); */ - unsigned int vec_rendz; - int vec_pow_fail_flen; - int vec_pad[10]; - - /* [0x040] reserved processor dependent */ - int pad0[112]; - - /* [0x200] reserved */ - int pad1[84]; - - /* [0x350] memory configuration (MC) */ - int memc_cont; /* contiguous mem size (bytes) */ - int memc_phsize; /* physical memory size */ - int memc_adsize; /* additional mem size, bytes of SPA space used by PDC */ - unsigned int mem_pdc_hi; /* used for 64-bit */ - - /* [0x360] various parameters for the boot-CPU */ - /* unsigned int *mem_booterr[8]; */ - unsigned int mem_booterr[8]; /* ptr to boot errors */ - unsigned int mem_free; /* first location, where OS can be loaded */ - /* struct iomod *mem_hpa; */ - unsigned int mem_hpa; /* HPA of the boot-CPU */ - /* int (*mem_pdc)(int, ...); */ - unsigned int mem_pdc; /* PDC entry point */ - unsigned int mem_10msec; /* number of clock ticks in 10msec */ - - /* [0x390] initial memory module (IMM) */ - /* struct iomod *imm_hpa; */ - unsigned int imm_hpa; /* HPA of the IMM */ - int imm_soft_boot; /* 0 = was hard boot, 1 = was soft boot */ - unsigned int imm_spa_size; /* SPA size of the IMM in bytes */ - unsigned int imm_max_mem; /* bytes of mem in IMM */ - - /* [0x3A0] boot console, display device and keyboard */ - struct pz_device mem_cons; /* description of console device */ - struct pz_device mem_boot; /* description of boot device */ - struct pz_device mem_kbd; /* description of keyboard device */ - - /* [0x430] reserved */ - int pad430[116]; - - /* [0x600] processor dependent */ - __u32 pad600[1]; - __u32 proc_sti; /* pointer to STI ROM */ - __u32 pad608[126]; -}; - #endif /* !defined(__ASSEMBLY__) */ - #endif /* _PARISC_PDC_H */ diff --git a/arch/parisc/include/asm/percpu.h b/arch/parisc/include/asm/percpu.h deleted file mode 100644 index a0dcd197012..00000000000 --- a/arch/parisc/include/asm/percpu.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _PARISC_PERCPU_H -#define _PARISC_PERCPU_H - -#include <asm-generic/percpu.h> - -#endif - diff --git a/arch/parisc/include/asm/poll.h b/arch/parisc/include/asm/poll.h deleted file mode 100644 index c98509d3149..00000000000 --- a/arch/parisc/include/asm/poll.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/poll.h> diff --git a/arch/parisc/include/asm/ptrace.h b/arch/parisc/include/asm/ptrace.h index 250ae35aa06..a2db278a5de 100644 --- a/arch/parisc/include/asm/ptrace.h +++ b/arch/parisc/include/asm/ptrace.h @@ -1,49 +1,11 @@ -#ifndef _PARISC_PTRACE_H -#define _PARISC_PTRACE_H - /* written by Philipp Rumpf, Copyright (C) 1999 SuSE GmbH Nuernberg ** Copyright (C) 2000 Grant Grundler, Hewlett-Packard */ +#ifndef _PARISC_PTRACE_H +#define _PARISC_PTRACE_H -#include <linux/types.h> - -/* This struct defines the way the registers are stored on the - * stack during a system call. - * - * N.B. gdb/strace care about the size and offsets within this - * structure. If you change things, you may break object compatibility - * for those applications. - */ - -struct pt_regs { - unsigned long gr[32]; /* PSW is in gr[0] */ - __u64 fr[32]; - unsigned long sr[ 8]; - unsigned long iasq[2]; - unsigned long iaoq[2]; - unsigned long cr27; - unsigned long pad0; /* available for other uses */ - unsigned long orig_r28; - unsigned long ksp; - unsigned long kpc; - unsigned long sar; /* CR11 */ - unsigned long iir; /* CR19 */ - unsigned long isr; /* CR20 */ - unsigned long ior; /* CR21 */ - unsigned long ipsw; /* CR22 */ -}; - -/* - * The numbers chosen here are somewhat arbitrary but absolutely MUST - * not overlap with any of the number assigned in <linux/ptrace.h>. - * - * These ones are taken from IA-64 on the assumption that theirs are - * the most correct (and we also want to support PTRACE_SINGLEBLOCK - * since we have taken branch traps too) - */ -#define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */ +#include <uapi/asm/ptrace.h> -#ifdef __KERNEL__ #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS)) @@ -58,6 +20,4 @@ struct pt_regs { unsigned long profile_pc(struct pt_regs *); -#endif /* __KERNEL__ */ - #endif diff --git a/arch/parisc/include/asm/real.h b/arch/parisc/include/asm/real.h deleted file mode 100644 index 82acb25db39..00000000000 --- a/arch/parisc/include/asm/real.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _PARISC_REAL_H -#define _PARISC_REAL_H - - -#endif diff --git a/arch/parisc/include/asm/segment.h b/arch/parisc/include/asm/segment.h deleted file mode 100644 index 26794ddb652..00000000000 --- a/arch/parisc/include/asm/segment.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __PARISC_SEGMENT_H -#define __PARISC_SEGMENT_H - -/* Only here because we have some old header files that expect it.. */ - -#endif diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h index c20356375d1..21abf4fc169 100644 --- a/arch/parisc/include/asm/signal.h +++ b/arch/parisc/include/asm/signal.h @@ -1,129 +1,19 @@ #ifndef _ASM_PARISC_SIGNAL_H #define _ASM_PARISC_SIGNAL_H -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGEMT 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGBUS 10 -#define SIGSEGV 11 -#define SIGSYS 12 /* Linux doesn't use this */ -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGUSR1 16 -#define SIGUSR2 17 -#define SIGCHLD 18 -#define SIGPWR 19 -#define SIGVTALRM 20 -#define SIGPROF 21 -#define SIGIO 22 -#define SIGPOLL SIGIO -#define SIGWINCH 23 -#define SIGSTOP 24 -#define SIGTSTP 25 -#define SIGCONT 26 -#define SIGTTIN 27 -#define SIGTTOU 28 -#define SIGURG 29 -#define SIGLOST 30 /* Linux doesn't use this either */ -#define SIGUNUSED 31 -#define SIGRESERVE SIGUNUSED +#include <uapi/asm/signal.h> -#define SIGXCPU 33 -#define SIGXFSZ 34 -#define SIGSTKFLT 36 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 37 -#define SIGRTMAX _NSIG /* it's 44 under HP/UX */ - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_ONSTACK 0x00000001 -#define SA_RESETHAND 0x00000004 -#define SA_NOCLDSTOP 0x00000008 -#define SA_SIGINFO 0x00000010 -#define SA_NODEFER 0x00000020 -#define SA_RESTART 0x00000040 -#define SA_NOCLDWAIT 0x00000080 -#define _SA_SIGGFAULT 0x00000100 /* HPUX */ - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -#define SA_RESTORER 0x04000000 /* obsolete -- ignored */ - -/* - * sigaltstack controls - */ -#define SS_ONSTACK 1 -#define SS_DISABLE 2 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 - -#ifdef __KERNEL__ #define _NSIG 64 /* bits-per-word, where word apparently means 'long' not 'int' */ #define _NSIG_BPW BITS_PER_LONG #define _NSIG_WORDS (_NSIG / _NSIG_BPW) -#endif /* __KERNEL__ */ - -#define SIG_BLOCK 0 /* for blocking signals */ -#define SIG_UNBLOCK 1 /* for unblocking signals */ -#define SIG_SETMASK 2 /* for setting the signal mask */ - -#define SIG_DFL ((__sighandler_t)0) /* default signal handling */ -#define SIG_IGN ((__sighandler_t)1) /* ignore signal */ -#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ - # ifndef __ASSEMBLY__ - -# include <linux/types.h> - -/* Avoid too many header ordering problems. */ -struct siginfo; - -/* Type of a signal handler. */ #ifdef CONFIG_64BIT -/* function pointers on 64-bit parisc are pointers to little structs and the - * compiler doesn't support code which changes or tests the address of - * the function in the little struct. This is really ugly -PB - */ -typedef char __user *__sighandler_t; #else -typedef void __signalfn_t(int); -typedef __signalfn_t __user *__sighandler_t; #endif -typedef struct sigaltstack { - void __user *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -#ifdef __KERNEL__ - /* Most things should be clean enough to redefine this at will, if care is taken to make libc match. */ @@ -148,6 +38,5 @@ struct k_sigaction { #include <asm/sigcontext.h> -#endif /* __KERNEL__ */ #endif /* !__ASSEMBLY */ #endif /* _ASM_PARISC_SIGNAL_H */ diff --git a/arch/parisc/include/asm/termios.h b/arch/parisc/include/asm/termios.h index a2a57a4548a..9bbc0c8974e 100644 --- a/arch/parisc/include/asm/termios.h +++ b/arch/parisc/include/asm/termios.h @@ -1,45 +1,8 @@ #ifndef _PARISC_TERMIOS_H #define _PARISC_TERMIOS_H -#include <asm/termbits.h> -#include <asm/ioctls.h> +#include <uapi/asm/termios.h> -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 8 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - -/* modem lines */ -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ - -#ifdef __KERNEL__ /* intr=^C quit=^\ erase=del kill=^U eof=^D vtime=\0 vmin=\1 sxtc=\0 @@ -85,6 +48,4 @@ struct termio { #define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios)) #define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios)) -#endif /* __KERNEL__ */ - #endif /* _PARISC_TERMIOS_H */ diff --git a/arch/parisc/include/asm/topology.h b/arch/parisc/include/asm/topology.h deleted file mode 100644 index d8133eb0b1e..00000000000 --- a/arch/parisc/include/asm/topology.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_PARISC_TOPOLOGY_H -#define _ASM_PARISC_TOPOLOGY_H - -#include <asm-generic/topology.h> - -#endif /* _ASM_PARISC_TOPOLOGY_H */ diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index d61de64f990..55512e26b0c 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -1,840 +1,8 @@ #ifndef _ASM_PARISC_UNISTD_H_ #define _ASM_PARISC_UNISTD_H_ -/* - * This file contains the system call numbers. - */ - -/* - * HP-UX system calls get their native numbers for binary compatibility. - */ - -#define __NR_HPUX_exit 1 -#define __NR_HPUX_fork 2 -#define __NR_HPUX_read 3 -#define __NR_HPUX_write 4 -#define __NR_HPUX_open 5 -#define __NR_HPUX_close 6 -#define __NR_HPUX_wait 7 -#define __NR_HPUX_creat 8 -#define __NR_HPUX_link 9 -#define __NR_HPUX_unlink 10 -#define __NR_HPUX_execv 11 -#define __NR_HPUX_chdir 12 -#define __NR_HPUX_time 13 -#define __NR_HPUX_mknod 14 -#define __NR_HPUX_chmod 15 -#define __NR_HPUX_chown 16 -#define __NR_HPUX_break 17 -#define __NR_HPUX_lchmod 18 -#define __NR_HPUX_lseek 19 -#define __NR_HPUX_getpid 20 -#define __NR_HPUX_mount 21 -#define __NR_HPUX_umount 22 -#define __NR_HPUX_setuid 23 -#define __NR_HPUX_getuid 24 -#define __NR_HPUX_stime 25 -#define __NR_HPUX_ptrace 26 -#define __NR_HPUX_alarm 27 -#define __NR_HPUX_oldfstat 28 -#define __NR_HPUX_pause 29 -#define __NR_HPUX_utime 30 -#define __NR_HPUX_stty 31 -#define __NR_HPUX_gtty 32 -#define __NR_HPUX_access 33 -#define __NR_HPUX_nice 34 -#define __NR_HPUX_ftime 35 -#define __NR_HPUX_sync 36 -#define __NR_HPUX_kill 37 -#define __NR_HPUX_stat 38 -#define __NR_HPUX_setpgrp3 39 -#define __NR_HPUX_lstat 40 -#define __NR_HPUX_dup 41 -#define __NR_HPUX_pipe 42 -#define __NR_HPUX_times 43 -#define __NR_HPUX_profil 44 -#define __NR_HPUX_ki_call 45 -#define __NR_HPUX_setgid 46 -#define __NR_HPUX_getgid 47 -#define __NR_HPUX_sigsys 48 -#define __NR_HPUX_reserved1 49 -#define __NR_HPUX_reserved2 50 -#define __NR_HPUX_acct 51 -#define __NR_HPUX_set_userthreadid 52 -#define __NR_HPUX_oldlock 53 -#define __NR_HPUX_ioctl 54 -#define __NR_HPUX_reboot 55 -#define __NR_HPUX_symlink 56 -#define __NR_HPUX_utssys 57 -#define __NR_HPUX_readlink 58 -#define __NR_HPUX_execve 59 -#define __NR_HPUX_umask 60 -#define __NR_HPUX_chroot 61 -#define __NR_HPUX_fcntl 62 -#define __NR_HPUX_ulimit 63 -#define __NR_HPUX_getpagesize 64 -#define __NR_HPUX_mremap 65 -#define __NR_HPUX_vfork 66 -#define __NR_HPUX_vread 67 -#define __NR_HPUX_vwrite 68 -#define __NR_HPUX_sbrk 69 -#define __NR_HPUX_sstk 70 -#define __NR_HPUX_mmap 71 -#define __NR_HPUX_vadvise 72 -#define __NR_HPUX_munmap 73 -#define __NR_HPUX_mprotect 74 -#define __NR_HPUX_madvise 75 -#define __NR_HPUX_vhangup 76 -#define __NR_HPUX_swapoff 77 -#define __NR_HPUX_mincore 78 -#define __NR_HPUX_getgroups 79 -#define __NR_HPUX_setgroups 80 -#define __NR_HPUX_getpgrp2 81 -#define __NR_HPUX_setpgrp2 82 -#define __NR_HPUX_setitimer 83 -#define __NR_HPUX_wait3 84 -#define __NR_HPUX_swapon 85 -#define __NR_HPUX_getitimer 86 -#define __NR_HPUX_gethostname42 87 -#define __NR_HPUX_sethostname42 88 -#define __NR_HPUX_getdtablesize 89 -#define __NR_HPUX_dup2 90 -#define __NR_HPUX_getdopt 91 -#define __NR_HPUX_fstat 92 -#define __NR_HPUX_select 93 -#define __NR_HPUX_setdopt 94 -#define __NR_HPUX_fsync 95 -#define __NR_HPUX_setpriority 96 -#define __NR_HPUX_socket_old 97 -#define __NR_HPUX_connect_old 98 -#define __NR_HPUX_accept_old 99 -#define __NR_HPUX_getpriority 100 -#define __NR_HPUX_send_old 101 -#define __NR_HPUX_recv_old 102 -#define __NR_HPUX_socketaddr_old 103 -#define __NR_HPUX_bind_old 104 -#define __NR_HPUX_setsockopt_old 105 -#define __NR_HPUX_listen_old 106 -#define __NR_HPUX_vtimes_old 107 -#define __NR_HPUX_sigvector 108 -#define __NR_HPUX_sigblock 109 -#define __NR_HPUX_siggetmask 110 -#define __NR_HPUX_sigpause 111 -#define __NR_HPUX_sigstack 112 -#define __NR_HPUX_recvmsg_old 113 -#define __NR_HPUX_sendmsg_old 114 -#define __NR_HPUX_vtrace_old 115 -#define __NR_HPUX_gettimeofday 116 -#define __NR_HPUX_getrusage 117 -#define __NR_HPUX_getsockopt_old 118 -#define __NR_HPUX_resuba_old 119 -#define __NR_HPUX_readv 120 -#define __NR_HPUX_writev 121 -#define __NR_HPUX_settimeofday 122 -#define __NR_HPUX_fchown 123 -#define __NR_HPUX_fchmod 124 -#define __NR_HPUX_recvfrom_old 125 -#define __NR_HPUX_setresuid 126 -#define __NR_HPUX_setresgid 127 -#define __NR_HPUX_rename 128 -#define __NR_HPUX_truncate 129 -#define __NR_HPUX_ftruncate 130 -#define __NR_HPUX_flock_old 131 -#define __NR_HPUX_sysconf 132 -#define __NR_HPUX_sendto_old 133 -#define __NR_HPUX_shutdown_old 134 -#define __NR_HPUX_socketpair_old 135 -#define __NR_HPUX_mkdir 136 -#define __NR_HPUX_rmdir 137 -#define __NR_HPUX_utimes_old 138 -#define __NR_HPUX_sigcleanup_old 139 -#define __NR_HPUX_setcore 140 -#define __NR_HPUX_getpeername_old 141 -#define __NR_HPUX_gethostid 142 -#define __NR_HPUX_sethostid 143 -#define __NR_HPUX_getrlimit 144 -#define __NR_HPUX_setrlimit 145 -#define __NR_HPUX_killpg_old 146 -#define __NR_HPUX_cachectl 147 -#define __NR_HPUX_quotactl 148 -#define __NR_HPUX_get_sysinfo 149 -#define __NR_HPUX_getsockname_old 150 -#define __NR_HPUX_privgrp 151 -#define __NR_HPUX_rtprio 152 -#define __NR_HPUX_plock 153 -#define __NR_HPUX_reserved3 154 -#define __NR_HPUX_lockf 155 -#define __NR_HPUX_semget 156 -#define __NR_HPUX_osemctl 157 -#define __NR_HPUX_semop 158 -#define __NR_HPUX_msgget 159 -#define __NR_HPUX_omsgctl 160 -#define __NR_HPUX_msgsnd 161 -#define __NR_HPUX_msgrecv 162 -#define __NR_HPUX_shmget 163 -#define __NR_HPUX_oshmctl 164 -#define __NR_HPUX_shmat 165 -#define __NR_HPUX_shmdt 166 -#define __NR_HPUX_m68020_advise 167 -/* [168,189] are for Discless/DUX */ -#define __NR_HPUX_csp 168 -#define __NR_HPUX_cluster 169 -#define __NR_HPUX_mkrnod 170 -#define __NR_HPUX_test 171 -#define __NR_HPUX_unsp_open 172 -#define __NR_HPUX_reserved4 173 -#define __NR_HPUX_getcontext_old 174 -#define __NR_HPUX_osetcontext 175 -#define __NR_HPUX_bigio 176 -#define __NR_HPUX_pipenode 177 -#define __NR_HPUX_lsync 178 -#define __NR_HPUX_getmachineid 179 -#define __NR_HPUX_cnodeid 180 -#define __NR_HPUX_cnodes 181 -#define __NR_HPUX_swapclients 182 -#define __NR_HPUX_rmt_process 183 -#define __NR_HPUX_dskless_stats 184 -#define __NR_HPUX_sigprocmask 185 -#define __NR_HPUX_sigpending 186 -#define __NR_HPUX_sigsuspend 187 -#define __NR_HPUX_sigaction 188 -#define __NR_HPUX_reserved5 189 -#define __NR_HPUX_nfssvc 190 -#define __NR_HPUX_getfh 191 -#define __NR_HPUX_getdomainname 192 -#define __NR_HPUX_setdomainname 193 -#define __NR_HPUX_async_daemon 194 -#define __NR_HPUX_getdirentries 195 -#define __NR_HPUX_statfs 196 -#define __NR_HPUX_fstatfs 197 -#define __NR_HPUX_vfsmount 198 -#define __NR_HPUX_reserved6 199 -#define __NR_HPUX_waitpid 200 -/* 201 - 223 missing */ -#define __NR_HPUX_sigsetreturn 224 -#define __NR_HPUX_sigsetstatemask 225 -/* 226 missing */ -#define __NR_HPUX_cs 227 -#define __NR_HPUX_cds 228 -#define __NR_HPUX_set_no_trunc 229 -#define __NR_HPUX_pathconf 230 -#define __NR_HPUX_fpathconf 231 -/* 232, 233 missing */ -#define __NR_HPUX_nfs_fcntl 234 -#define __NR_HPUX_ogetacl 235 -#define __NR_HPUX_ofgetacl 236 -#define __NR_HPUX_osetacl 237 -#define __NR_HPUX_ofsetacl 238 -#define __NR_HPUX_pstat 239 -#define __NR_HPUX_getaudid 240 -#define __NR_HPUX_setaudid 241 -#define __NR_HPUX_getaudproc 242 -#define __NR_HPUX_setaudproc 243 -#define __NR_HPUX_getevent 244 -#define __NR_HPUX_setevent 245 -#define __NR_HPUX_audwrite 246 -#define __NR_HPUX_audswitch 247 -#define __NR_HPUX_audctl 248 -#define __NR_HPUX_ogetaccess 249 -#define __NR_HPUX_fsctl 250 -/* 251 - 258 missing */ -#define __NR_HPUX_swapfs 259 -#define __NR_HPUX_fss 260 -/* 261 - 266 missing */ -#define __NR_HPUX_tsync 267 -#define __NR_HPUX_getnumfds 268 -#define __NR_HPUX_poll 269 -#define __NR_HPUX_getmsg 270 -#define __NR_HPUX_putmsg 271 -#define __NR_HPUX_fchdir 272 -#define __NR_HPUX_getmount_cnt 273 -#define __NR_HPUX_getmount_entry 274 -#define __NR_HPUX_accept 275 -#define __NR_HPUX_bind 276 -#define __NR_HPUX_connect 277 -#define __NR_HPUX_getpeername 278 -#define __NR_HPUX_getsockname 279 -#define __NR_HPUX_getsockopt 280 -#define __NR_HPUX_listen 281 -#define __NR_HPUX_recv 282 -#define __NR_HPUX_recvfrom 283 -#define __NR_HPUX_recvmsg 284 -#define __NR_HPUX_send 285 -#define __NR_HPUX_sendmsg 286 -#define __NR_HPUX_sendto 287 -#define __NR_HPUX_setsockopt 288 -#define __NR_HPUX_shutdown 289 -#define __NR_HPUX_socket 290 -#define __NR_HPUX_socketpair 291 -#define __NR_HPUX_proc_open 292 -#define __NR_HPUX_proc_close 293 -#define __NR_HPUX_proc_send 294 -#define __NR_HPUX_proc_recv 295 -#define __NR_HPUX_proc_sendrecv 296 -#define __NR_HPUX_proc_syscall 297 -/* 298 - 311 missing */ -#define __NR_HPUX_semctl 312 -#define __NR_HPUX_msgctl 313 -#define __NR_HPUX_shmctl 314 -#define __NR_HPUX_mpctl 315 -#define __NR_HPUX_exportfs 316 -#define __NR_HPUX_getpmsg 317 -#define __NR_HPUX_putpmsg 318 -/* 319 missing */ -#define __NR_HPUX_msync 320 -#define __NR_HPUX_msleep 321 -#define __NR_HPUX_mwakeup 322 -#define __NR_HPUX_msem_init 323 -#define __NR_HPUX_msem_remove 324 -#define __NR_HPUX_adjtime 325 -#define __NR_HPUX_kload 326 -#define __NR_HPUX_fattach 327 -#define __NR_HPUX_fdetach 328 -#define __NR_HPUX_serialize 329 -#define __NR_HPUX_statvfs 330 -#define __NR_HPUX_fstatvfs 331 -#define __NR_HPUX_lchown 332 -#define __NR_HPUX_getsid 333 -#define __NR_HPUX_sysfs 334 -/* 335, 336 missing */ -#define __NR_HPUX_sched_setparam 337 -#define __NR_HPUX_sched_getparam 338 -#define __NR_HPUX_sched_setscheduler 339 -#define __NR_HPUX_sched_getscheduler 340 -#define __NR_HPUX_sched_yield 341 -#define __NR_HPUX_sched_get_priority_max 342 -#define __NR_HPUX_sched_get_priority_min 343 -#define __NR_HPUX_sched_rr_get_interval 344 -#define __NR_HPUX_clock_settime 345 -#define __NR_HPUX_clock_gettime 346 -#define __NR_HPUX_clock_getres 347 -#define __NR_HPUX_timer_create 348 -#define __NR_HPUX_timer_delete 349 -#define __NR_HPUX_timer_settime 350 -#define __NR_HPUX_timer_gettime 351 -#define __NR_HPUX_timer_getoverrun 352 -#define __NR_HPUX_nanosleep 353 -#define __NR_HPUX_toolbox 354 -/* 355 missing */ -#define __NR_HPUX_getdents 356 -#define __NR_HPUX_getcontext 357 -#define __NR_HPUX_sysinfo 358 -#define __NR_HPUX_fcntl64 359 -#define __NR_HPUX_ftruncate64 360 -#define __NR_HPUX_fstat64 361 -#define __NR_HPUX_getdirentries64 362 -#define __NR_HPUX_getrlimit64 363 -#define __NR_HPUX_lockf64 364 -#define __NR_HPUX_lseek64 365 -#define __NR_HPUX_lstat64 366 -#define __NR_HPUX_mmap64 367 -#define __NR_HPUX_setrlimit64 368 -#define __NR_HPUX_stat64 369 -#define __NR_HPUX_truncate64 370 -#define __NR_HPUX_ulimit64 371 -#define __NR_HPUX_pread 372 -#define __NR_HPUX_preadv 373 -#define __NR_HPUX_pwrite 374 -#define __NR_HPUX_pwritev 375 -#define __NR_HPUX_pread64 376 -#define __NR_HPUX_preadv64 377 -#define __NR_HPUX_pwrite64 378 -#define __NR_HPUX_pwritev64 379 -#define __NR_HPUX_setcontext 380 -#define __NR_HPUX_sigaltstack 381 -#define __NR_HPUX_waitid 382 -#define __NR_HPUX_setpgrp 383 -#define __NR_HPUX_recvmsg2 384 -#define __NR_HPUX_sendmsg2 385 -#define __NR_HPUX_socket2 386 -#define __NR_HPUX_socketpair2 387 -#define __NR_HPUX_setregid 388 -#define __NR_HPUX_lwp_create 389 -#define __NR_HPUX_lwp_terminate 390 -#define __NR_HPUX_lwp_wait 391 -#define __NR_HPUX_lwp_suspend 392 -#define __NR_HPUX_lwp_resume 393 -/* 394 missing */ -#define __NR_HPUX_lwp_abort_syscall 395 -#define __NR_HPUX_lwp_info 396 -#define __NR_HPUX_lwp_kill 397 -#define __NR_HPUX_ksleep 398 -#define __NR_HPUX_kwakeup 399 -/* 400 missing */ -#define __NR_HPUX_pstat_getlwp 401 -#define __NR_HPUX_lwp_exit 402 -#define __NR_HPUX_lwp_continue 403 -#define __NR_HPUX_getacl 404 -#define __NR_HPUX_fgetacl 405 -#define __NR_HPUX_setacl 406 -#define __NR_HPUX_fsetacl 407 -#define __NR_HPUX_getaccess 408 -#define __NR_HPUX_lwp_mutex_init 409 -#define __NR_HPUX_lwp_mutex_lock_sys 410 -#define __NR_HPUX_lwp_mutex_unlock 411 -#define __NR_HPUX_lwp_cond_init 412 -#define __NR_HPUX_lwp_cond_signal 413 -#define __NR_HPUX_lwp_cond_broadcast 414 -#define __NR_HPUX_lwp_cond_wait_sys 415 -#define __NR_HPUX_lwp_getscheduler 416 -#define __NR_HPUX_lwp_setscheduler 417 -#define __NR_HPUX_lwp_getstate 418 -#define __NR_HPUX_lwp_setstate 419 -#define __NR_HPUX_lwp_detach 420 -#define __NR_HPUX_mlock 421 -#define __NR_HPUX_munlock 422 -#define __NR_HPUX_mlockall 423 -#define __NR_HPUX_munlockall 424 -#define __NR_HPUX_shm_open 425 -#define __NR_HPUX_shm_unlink 426 -#define __NR_HPUX_sigqueue 427 -#define __NR_HPUX_sigwaitinfo 428 -#define __NR_HPUX_sigtimedwait 429 -#define __NR_HPUX_sigwait 430 -#define __NR_HPUX_aio_read 431 -#define __NR_HPUX_aio_write 432 -#define __NR_HPUX_lio_listio 433 -#define __NR_HPUX_aio_error 434 -#define __NR_HPUX_aio_return 435 -#define __NR_HPUX_aio_cancel 436 -#define __NR_HPUX_aio_suspend 437 -#define __NR_HPUX_aio_fsync 438 -#define __NR_HPUX_mq_open 439 -#define __NR_HPUX_mq_close 440 -#define __NR_HPUX_mq_unlink 441 -#define __NR_HPUX_mq_send 442 -#define __NR_HPUX_mq_receive 443 -#define __NR_HPUX_mq_notify 444 -#define __NR_HPUX_mq_setattr 445 -#define __NR_HPUX_mq_getattr 446 -#define __NR_HPUX_ksem_open 447 -#define __NR_HPUX_ksem_unlink 448 -#define __NR_HPUX_ksem_close 449 -#define __NR_HPUX_ksem_post 450 -#define __NR_HPUX_ksem_wait 451 -#define __NR_HPUX_ksem_read 452 -#define __NR_HPUX_ksem_trywait 453 -#define __NR_HPUX_lwp_rwlock_init 454 -#define __NR_HPUX_lwp_rwlock_destroy 455 -#define __NR_HPUX_lwp_rwlock_rdlock_sys 456 -#define __NR_HPUX_lwp_rwlock_wrlock_sys 457 -#define __NR_HPUX_lwp_rwlock_tryrdlock 458 -#define __NR_HPUX_lwp_rwlock_trywrlock 459 -#define __NR_HPUX_lwp_rwlock_unlock 460 -#define __NR_HPUX_ttrace 461 -#define __NR_HPUX_ttrace_wait 462 -#define __NR_HPUX_lf_wire_mem 463 -#define __NR_HPUX_lf_unwire_mem 464 -#define __NR_HPUX_lf_send_pin_map 465 -#define __NR_HPUX_lf_free_buf 466 -#define __NR_HPUX_lf_wait_nq 467 -#define __NR_HPUX_lf_wakeup_conn_q 468 -#define __NR_HPUX_lf_unused 469 -#define __NR_HPUX_lwp_sema_init 470 -#define __NR_HPUX_lwp_sema_post 471 -#define __NR_HPUX_lwp_sema_wait 472 -#define __NR_HPUX_lwp_sema_trywait 473 -#define __NR_HPUX_lwp_sema_destroy 474 -#define __NR_HPUX_statvfs64 475 -#define __NR_HPUX_fstatvfs64 476 -#define __NR_HPUX_msh_register 477 -#define __NR_HPUX_ptrace64 478 -#define __NR_HPUX_sendfile 479 -#define __NR_HPUX_sendpath 480 -#define __NR_HPUX_sendfile64 481 -#define __NR_HPUX_sendpath64 482 -#define __NR_HPUX_modload 483 -#define __NR_HPUX_moduload 484 -#define __NR_HPUX_modpath 485 -#define __NR_HPUX_getksym 486 -#define __NR_HPUX_modadm 487 -#define __NR_HPUX_modstat 488 -#define __NR_HPUX_lwp_detached_exit 489 -#define __NR_HPUX_crashconf 490 -#define __NR_HPUX_siginhibit 491 -#define __NR_HPUX_sigenable 492 -#define __NR_HPUX_spuctl 493 -#define __NR_HPUX_zerokernelsum 494 -#define __NR_HPUX_nfs_kstat 495 -#define __NR_HPUX_aio_read64 496 -#define __NR_HPUX_aio_write64 497 -#define __NR_HPUX_aio_error64 498 -#define __NR_HPUX_aio_return64 499 -#define __NR_HPUX_aio_cancel64 500 -#define __NR_HPUX_aio_suspend64 501 -#define __NR_HPUX_aio_fsync64 502 -#define __NR_HPUX_lio_listio64 503 -#define __NR_HPUX_recv2 504 -#define __NR_HPUX_recvfrom2 505 -#define __NR_HPUX_send2 506 -#define __NR_HPUX_sendto2 507 -#define __NR_HPUX_acl 508 -#define __NR_HPUX___cnx_p2p_ctl 509 -#define __NR_HPUX___cnx_gsched_ctl 510 -#define __NR_HPUX___cnx_pmon_ctl 511 - -#define __NR_HPUX_syscalls 512 - -/* - * Linux system call numbers. - * - * Cary Coutant says that we should just use another syscall gateway - * page to avoid clashing with the HPUX space, and I think he's right: - * it will would keep a branch out of our syscall entry path, at the - * very least. If we decide to change it later, we can ``just'' tweak - * the LINUX_GATEWAY_ADDR define at the bottom and make __NR_Linux be - * 1024 or something. Oh, and recompile libc. =) - * - * 64-bit HPUX binaries get the syscall gateway address passed in a register - * from the kernel at startup, which seems a sane strategy. - */ - -#define __NR_Linux 0 -#define __NR_restart_syscall (__NR_Linux + 0) -#define __NR_exit (__NR_Linux + 1) -#define __NR_fork (__NR_Linux + 2) -#define __NR_read (__NR_Linux + 3) -#define __NR_write (__NR_Linux + 4) -#define __NR_open (__NR_Linux + 5) -#define __NR_close (__NR_Linux + 6) -#define __NR_waitpid (__NR_Linux + 7) -#define __NR_creat (__NR_Linux + 8) -#define __NR_link (__NR_Linux + 9) -#define __NR_unlink (__NR_Linux + 10) -#define __NR_execve (__NR_Linux + 11) -#define __NR_chdir (__NR_Linux + 12) -#define __NR_time (__NR_Linux + 13) -#define __NR_mknod (__NR_Linux + 14) -#define __NR_chmod (__NR_Linux + 15) -#define __NR_lchown (__NR_Linux + 16) -#define __NR_socket (__NR_Linux + 17) -#define __NR_stat (__NR_Linux + 18) -#define __NR_lseek (__NR_Linux + 19) -#define __NR_getpid (__NR_Linux + 20) -#define __NR_mount (__NR_Linux + 21) -#define __NR_bind (__NR_Linux + 22) -#define __NR_setuid (__NR_Linux + 23) -#define __NR_getuid (__NR_Linux + 24) -#define __NR_stime (__NR_Linux + 25) -#define __NR_ptrace (__NR_Linux + 26) -#define __NR_alarm (__NR_Linux + 27) -#define __NR_fstat (__NR_Linux + 28) -#define __NR_pause (__NR_Linux + 29) -#define __NR_utime (__NR_Linux + 30) -#define __NR_connect (__NR_Linux + 31) -#define __NR_listen (__NR_Linux + 32) -#define __NR_access (__NR_Linux + 33) -#define __NR_nice (__NR_Linux + 34) -#define __NR_accept (__NR_Linux + 35) -#define __NR_sync (__NR_Linux + 36) -#define __NR_kill (__NR_Linux + 37) -#define __NR_rename (__NR_Linux + 38) -#define __NR_mkdir (__NR_Linux + 39) -#define __NR_rmdir (__NR_Linux + 40) -#define __NR_dup (__NR_Linux + 41) -#define __NR_pipe (__NR_Linux + 42) -#define __NR_times (__NR_Linux + 43) -#define __NR_getsockname (__NR_Linux + 44) -#define __NR_brk (__NR_Linux + 45) -#define __NR_setgid (__NR_Linux + 46) -#define __NR_getgid (__NR_Linux + 47) -#define __NR_signal (__NR_Linux + 48) -#define __NR_geteuid (__NR_Linux + 49) -#define __NR_getegid (__NR_Linux + 50) -#define __NR_acct (__NR_Linux + 51) -#define __NR_umount2 (__NR_Linux + 52) -#define __NR_getpeername (__NR_Linux + 53) -#define __NR_ioctl (__NR_Linux + 54) -#define __NR_fcntl (__NR_Linux + 55) -#define __NR_socketpair (__NR_Linux + 56) -#define __NR_setpgid (__NR_Linux + 57) -#define __NR_send (__NR_Linux + 58) -#define __NR_uname (__NR_Linux + 59) -#define __NR_umask (__NR_Linux + 60) -#define __NR_chroot (__NR_Linux + 61) -#define __NR_ustat (__NR_Linux + 62) -#define __NR_dup2 (__NR_Linux + 63) -#define __NR_getppid (__NR_Linux + 64) -#define __NR_getpgrp (__NR_Linux + 65) -#define __NR_setsid (__NR_Linux + 66) -#define __NR_pivot_root (__NR_Linux + 67) -#define __NR_sgetmask (__NR_Linux + 68) -#define __NR_ssetmask (__NR_Linux + 69) -#define __NR_setreuid (__NR_Linux + 70) -#define __NR_setregid (__NR_Linux + 71) -#define __NR_mincore (__NR_Linux + 72) -#define __NR_sigpending (__NR_Linux + 73) -#define __NR_sethostname (__NR_Linux + 74) -#define __NR_setrlimit (__NR_Linux + 75) -#define __NR_getrlimit (__NR_Linux + 76) -#define __NR_getrusage (__NR_Linux + 77) -#define __NR_gettimeofday (__NR_Linux + 78) -#define __NR_settimeofday (__NR_Linux + 79) -#define __NR_getgroups (__NR_Linux + 80) -#define __NR_setgroups (__NR_Linux + 81) -#define __NR_sendto (__NR_Linux + 82) -#define __NR_symlink (__NR_Linux + 83) -#define __NR_lstat (__NR_Linux + 84) -#define __NR_readlink (__NR_Linux + 85) -#define __NR_uselib (__NR_Linux + 86) -#define __NR_swapon (__NR_Linux + 87) -#define __NR_reboot (__NR_Linux + 88) -#define __NR_mmap2 (__NR_Linux + 89) -#define __NR_mmap (__NR_Linux + 90) -#define __NR_munmap (__NR_Linux + 91) -#define __NR_truncate (__NR_Linux + 92) -#define __NR_ftruncate (__NR_Linux + 93) -#define __NR_fchmod (__NR_Linux + 94) -#define __NR_fchown (__NR_Linux + 95) -#define __NR_getpriority (__NR_Linux + 96) -#define __NR_setpriority (__NR_Linux + 97) -#define __NR_recv (__NR_Linux + 98) -#define __NR_statfs (__NR_Linux + 99) -#define __NR_fstatfs (__NR_Linux + 100) -#define __NR_stat64 (__NR_Linux + 101) -/* #define __NR_socketcall (__NR_Linux + 102) */ -#define __NR_syslog (__NR_Linux + 103) -#define __NR_setitimer (__NR_Linux + 104) -#define __NR_getitimer (__NR_Linux + 105) -#define __NR_capget (__NR_Linux + 106) -#define __NR_capset (__NR_Linux + 107) -#define __NR_pread64 (__NR_Linux + 108) -#define __NR_pwrite64 (__NR_Linux + 109) -#define __NR_getcwd (__NR_Linux + 110) -#define __NR_vhangup (__NR_Linux + 111) -#define __NR_fstat64 (__NR_Linux + 112) -#define __NR_vfork (__NR_Linux + 113) -#define __NR_wait4 (__NR_Linux + 114) -#define __NR_swapoff (__NR_Linux + 115) -#define __NR_sysinfo (__NR_Linux + 116) -#define __NR_shutdown (__NR_Linux + 117) -#define __NR_fsync (__NR_Linux + 118) -#define __NR_madvise (__NR_Linux + 119) -#define __NR_clone (__NR_Linux + 120) -#define __NR_setdomainname (__NR_Linux + 121) -#define __NR_sendfile (__NR_Linux + 122) -#define __NR_recvfrom (__NR_Linux + 123) -#define __NR_adjtimex (__NR_Linux + 124) -#define __NR_mprotect (__NR_Linux + 125) -#define __NR_sigprocmask (__NR_Linux + 126) -#define __NR_create_module (__NR_Linux + 127) -#define __NR_init_module (__NR_Linux + 128) -#define __NR_delete_module (__NR_Linux + 129) -#define __NR_get_kernel_syms (__NR_Linux + 130) -#define __NR_quotactl (__NR_Linux + 131) -#define __NR_getpgid (__NR_Linux + 132) -#define __NR_fchdir (__NR_Linux + 133) -#define __NR_bdflush (__NR_Linux + 134) -#define __NR_sysfs (__NR_Linux + 135) -#define __NR_personality (__NR_Linux + 136) -#define __NR_afs_syscall (__NR_Linux + 137) /* Syscall for Andrew File System */ -#define __NR_setfsuid (__NR_Linux + 138) -#define __NR_setfsgid (__NR_Linux + 139) -#define __NR__llseek (__NR_Linux + 140) -#define __NR_getdents (__NR_Linux + 141) -#define __NR__newselect (__NR_Linux + 142) -#define __NR_flock (__NR_Linux + 143) -#define __NR_msync (__NR_Linux + 144) -#define __NR_readv (__NR_Linux + 145) -#define __NR_writev (__NR_Linux + 146) -#define __NR_getsid (__NR_Linux + 147) -#define __NR_fdatasync (__NR_Linux + 148) -#define __NR__sysctl (__NR_Linux + 149) -#define __NR_mlock (__NR_Linux + 150) -#define __NR_munlock (__NR_Linux + 151) -#define __NR_mlockall (__NR_Linux + 152) -#define __NR_munlockall (__NR_Linux + 153) -#define __NR_sched_setparam (__NR_Linux + 154) -#define __NR_sched_getparam (__NR_Linux + 155) -#define __NR_sched_setscheduler (__NR_Linux + 156) -#define __NR_sched_getscheduler (__NR_Linux + 157) -#define __NR_sched_yield (__NR_Linux + 158) -#define __NR_sched_get_priority_max (__NR_Linux + 159) -#define __NR_sched_get_priority_min (__NR_Linux + 160) -#define __NR_sched_rr_get_interval (__NR_Linux + 161) -#define __NR_nanosleep (__NR_Linux + 162) -#define __NR_mremap (__NR_Linux + 163) -#define __NR_setresuid (__NR_Linux + 164) -#define __NR_getresuid (__NR_Linux + 165) -#define __NR_sigaltstack (__NR_Linux + 166) -#define __NR_query_module (__NR_Linux + 167) -#define __NR_poll (__NR_Linux + 168) -#define __NR_nfsservctl (__NR_Linux + 169) -#define __NR_setresgid (__NR_Linux + 170) -#define __NR_getresgid (__NR_Linux + 171) -#define __NR_prctl (__NR_Linux + 172) -#define __NR_rt_sigreturn (__NR_Linux + 173) -#define __NR_rt_sigaction (__NR_Linux + 174) -#define __NR_rt_sigprocmask (__NR_Linux + 175) -#define __NR_rt_sigpending (__NR_Linux + 176) -#define __NR_rt_sigtimedwait (__NR_Linux + 177) -#define __NR_rt_sigqueueinfo (__NR_Linux + 178) -#define __NR_rt_sigsuspend (__NR_Linux + 179) -#define __NR_chown (__NR_Linux + 180) -#define __NR_setsockopt (__NR_Linux + 181) -#define __NR_getsockopt (__NR_Linux + 182) -#define __NR_sendmsg (__NR_Linux + 183) -#define __NR_recvmsg (__NR_Linux + 184) -#define __NR_semop (__NR_Linux + 185) -#define __NR_semget (__NR_Linux + 186) -#define __NR_semctl (__NR_Linux + 187) -#define __NR_msgsnd (__NR_Linux + 188) -#define __NR_msgrcv (__NR_Linux + 189) -#define __NR_msgget (__NR_Linux + 190) -#define __NR_msgctl (__NR_Linux + 191) -#define __NR_shmat (__NR_Linux + 192) -#define __NR_shmdt (__NR_Linux + 193) -#define __NR_shmget (__NR_Linux + 194) -#define __NR_shmctl (__NR_Linux + 195) - -#define __NR_getpmsg (__NR_Linux + 196) /* Somebody *wants* streams? */ -#define __NR_putpmsg (__NR_Linux + 197) - -#define __NR_lstat64 (__NR_Linux + 198) -#define __NR_truncate64 (__NR_Linux + 199) -#define __NR_ftruncate64 (__NR_Linux + 200) -#define __NR_getdents64 (__NR_Linux + 201) -#define __NR_fcntl64 (__NR_Linux + 202) -#define __NR_attrctl (__NR_Linux + 203) -#define __NR_acl_get (__NR_Linux + 204) -#define __NR_acl_set (__NR_Linux + 205) -#define __NR_gettid (__NR_Linux + 206) -#define __NR_readahead (__NR_Linux + 207) -#define __NR_tkill (__NR_Linux + 208) -#define __NR_sendfile64 (__NR_Linux + 209) -#define __NR_futex (__NR_Linux + 210) -#define __NR_sched_setaffinity (__NR_Linux + 211) -#define __NR_sched_getaffinity (__NR_Linux + 212) -#define __NR_set_thread_area (__NR_Linux + 213) -#define __NR_get_thread_area (__NR_Linux + 214) -#define __NR_io_setup (__NR_Linux + 215) -#define __NR_io_destroy (__NR_Linux + 216) -#define __NR_io_getevents (__NR_Linux + 217) -#define __NR_io_submit (__NR_Linux + 218) -#define __NR_io_cancel (__NR_Linux + 219) -#define __NR_alloc_hugepages (__NR_Linux + 220) -#define __NR_free_hugepages (__NR_Linux + 221) -#define __NR_exit_group (__NR_Linux + 222) -#define __NR_lookup_dcookie (__NR_Linux + 223) -#define __NR_epoll_create (__NR_Linux + 224) -#define __NR_epoll_ctl (__NR_Linux + 225) -#define __NR_epoll_wait (__NR_Linux + 226) -#define __NR_remap_file_pages (__NR_Linux + 227) -#define __NR_semtimedop (__NR_Linux + 228) -#define __NR_mq_open (__NR_Linux + 229) -#define __NR_mq_unlink (__NR_Linux + 230) -#define __NR_mq_timedsend (__NR_Linux + 231) -#define __NR_mq_timedreceive (__NR_Linux + 232) -#define __NR_mq_notify (__NR_Linux + 233) -#define __NR_mq_getsetattr (__NR_Linux + 234) -#define __NR_waitid (__NR_Linux + 235) -#define __NR_fadvise64_64 (__NR_Linux + 236) -#define __NR_set_tid_address (__NR_Linux + 237) -#define __NR_setxattr (__NR_Linux + 238) -#define __NR_lsetxattr (__NR_Linux + 239) -#define __NR_fsetxattr (__NR_Linux + 240) -#define __NR_getxattr (__NR_Linux + 241) -#define __NR_lgetxattr (__NR_Linux + 242) -#define __NR_fgetxattr (__NR_Linux + 243) -#define __NR_listxattr (__NR_Linux + 244) -#define __NR_llistxattr (__NR_Linux + 245) -#define __NR_flistxattr (__NR_Linux + 246) -#define __NR_removexattr (__NR_Linux + 247) -#define __NR_lremovexattr (__NR_Linux + 248) -#define __NR_fremovexattr (__NR_Linux + 249) -#define __NR_timer_create (__NR_Linux + 250) -#define __NR_timer_settime (__NR_Linux + 251) -#define __NR_timer_gettime (__NR_Linux + 252) -#define __NR_timer_getoverrun (__NR_Linux + 253) -#define __NR_timer_delete (__NR_Linux + 254) -#define __NR_clock_settime (__NR_Linux + 255) -#define __NR_clock_gettime (__NR_Linux + 256) -#define __NR_clock_getres (__NR_Linux + 257) -#define __NR_clock_nanosleep (__NR_Linux + 258) -#define __NR_tgkill (__NR_Linux + 259) -#define __NR_mbind (__NR_Linux + 260) -#define __NR_get_mempolicy (__NR_Linux + 261) -#define __NR_set_mempolicy (__NR_Linux + 262) -#define __NR_vserver (__NR_Linux + 263) -#define __NR_add_key (__NR_Linux + 264) -#define __NR_request_key (__NR_Linux + 265) -#define __NR_keyctl (__NR_Linux + 266) -#define __NR_ioprio_set (__NR_Linux + 267) -#define __NR_ioprio_get (__NR_Linux + 268) -#define __NR_inotify_init (__NR_Linux + 269) -#define __NR_inotify_add_watch (__NR_Linux + 270) -#define __NR_inotify_rm_watch (__NR_Linux + 271) -#define __NR_migrate_pages (__NR_Linux + 272) -#define __NR_pselect6 (__NR_Linux + 273) -#define __NR_ppoll (__NR_Linux + 274) -#define __NR_openat (__NR_Linux + 275) -#define __NR_mkdirat (__NR_Linux + 276) -#define __NR_mknodat (__NR_Linux + 277) -#define __NR_fchownat (__NR_Linux + 278) -#define __NR_futimesat (__NR_Linux + 279) -#define __NR_fstatat64 (__NR_Linux + 280) -#define __NR_unlinkat (__NR_Linux + 281) -#define __NR_renameat (__NR_Linux + 282) -#define __NR_linkat (__NR_Linux + 283) -#define __NR_symlinkat (__NR_Linux + 284) -#define __NR_readlinkat (__NR_Linux + 285) -#define __NR_fchmodat (__NR_Linux + 286) -#define __NR_faccessat (__NR_Linux + 287) -#define __NR_unshare (__NR_Linux + 288) -#define __NR_set_robust_list (__NR_Linux + 289) -#define __NR_get_robust_list (__NR_Linux + 290) -#define __NR_splice (__NR_Linux + 291) -#define __NR_sync_file_range (__NR_Linux + 292) -#define __NR_tee (__NR_Linux + 293) -#define __NR_vmsplice (__NR_Linux + 294) -#define __NR_move_pages (__NR_Linux + 295) -#define __NR_getcpu (__NR_Linux + 296) -#define __NR_epoll_pwait (__NR_Linux + 297) -#define __NR_statfs64 (__NR_Linux + 298) -#define __NR_fstatfs64 (__NR_Linux + 299) -#define __NR_kexec_load (__NR_Linux + 300) -#define __NR_utimensat (__NR_Linux + 301) -#define __NR_signalfd (__NR_Linux + 302) -#define __NR_timerfd (__NR_Linux + 303) -#define __NR_eventfd (__NR_Linux + 304) -#define __NR_fallocate (__NR_Linux + 305) -#define __NR_timerfd_create (__NR_Linux + 306) -#define __NR_timerfd_settime (__NR_Linux + 307) -#define __NR_timerfd_gettime (__NR_Linux + 308) -#define __NR_signalfd4 (__NR_Linux + 309) -#define __NR_eventfd2 (__NR_Linux + 310) -#define __NR_epoll_create1 (__NR_Linux + 311) -#define __NR_dup3 (__NR_Linux + 312) -#define __NR_pipe2 (__NR_Linux + 313) -#define __NR_inotify_init1 (__NR_Linux + 314) -#define __NR_preadv (__NR_Linux + 315) -#define __NR_pwritev (__NR_Linux + 316) -#define __NR_rt_tgsigqueueinfo (__NR_Linux + 317) -#define __NR_perf_event_open (__NR_Linux + 318) -#define __NR_recvmmsg (__NR_Linux + 319) -#define __NR_accept4 (__NR_Linux + 320) -#define __NR_prlimit64 (__NR_Linux + 321) -#define __NR_fanotify_init (__NR_Linux + 322) -#define __NR_fanotify_mark (__NR_Linux + 323) -#define __NR_clock_adjtime (__NR_Linux + 324) -#define __NR_name_to_handle_at (__NR_Linux + 325) -#define __NR_open_by_handle_at (__NR_Linux + 326) -#define __NR_syncfs (__NR_Linux + 327) -#define __NR_setns (__NR_Linux + 328) -#define __NR_sendmmsg (__NR_Linux + 329) - -#define __NR_Linux_syscalls (__NR_sendmmsg + 1) - - -#define __IGNORE_select /* newselect */ -#define __IGNORE_fadvise64 /* fadvise64_64 */ -#define __IGNORE_utimes /* utime */ - - -#define HPUX_GATEWAY_ADDR 0xC0000004 -#define LINUX_GATEWAY_ADDR 0x100 +#include <uapi/asm/unistd.h> -#ifdef __KERNEL__ #ifndef __ASSEMBLY__ #define SYS_ify(syscall_name) __NR_##syscall_name @@ -995,6 +163,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ #define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND +#define __ARCH_WANT_SYS_EXECVE #endif /* __ASSEMBLY__ */ @@ -1008,5 +177,4 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ */ #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") -#endif /* __KERNEL__ */ #endif /* _ASM_PARISC_UNISTD_H_ */ diff --git a/arch/parisc/include/asm/user.h b/arch/parisc/include/asm/user.h deleted file mode 100644 index 80224753e50..00000000000 --- a/arch/parisc/include/asm/user.h +++ /dev/null @@ -1,5 +0,0 @@ -/* This file should not exist, but lots of generic code still includes - it. It's a hangover from old a.out days and the traditional core - dump format. We are ELF-only, and so are our core dumps. If we - need to support HP/UX core format then we'll do it here - eventually. */ diff --git a/arch/parisc/include/asm/vga.h b/arch/parisc/include/asm/vga.h deleted file mode 100644 index 171399a88ca..00000000000 --- a/arch/parisc/include/asm/vga.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_PARISC_VGA_H__ -#define __ASM_PARISC_VGA_H__ - -/* nothing */ - -#endif /* __ASM_PARISC_VGA_H__ */ diff --git a/arch/parisc/include/asm/xor.h b/arch/parisc/include/asm/xor.h deleted file mode 100644 index c82eb12a5b1..00000000000 --- a/arch/parisc/include/asm/xor.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/xor.h> diff --git a/arch/parisc/include/uapi/asm/Kbuild b/arch/parisc/include/uapi/asm/Kbuild index baebb3da1d4..a580642555b 100644 --- a/arch/parisc/include/uapi/asm/Kbuild +++ b/arch/parisc/include/uapi/asm/Kbuild @@ -1,3 +1,31 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm +header-y += bitsperlong.h +header-y += byteorder.h +header-y += errno.h +header-y += fcntl.h +header-y += ioctl.h +header-y += ioctls.h +header-y += ipcbuf.h +header-y += mman.h +header-y += msgbuf.h +header-y += pdc.h +header-y += posix_types.h +header-y += ptrace.h +header-y += resource.h +header-y += sembuf.h +header-y += setup.h +header-y += shmbuf.h +header-y += sigcontext.h +header-y += siginfo.h +header-y += signal.h +header-y += socket.h +header-y += sockios.h +header-y += stat.h +header-y += statfs.h +header-y += swab.h +header-y += termbits.h +header-y += termios.h +header-y += types.h +header-y += unistd.h diff --git a/arch/parisc/include/asm/bitsperlong.h b/arch/parisc/include/uapi/asm/bitsperlong.h index 75196b415d3..75196b415d3 100644 --- a/arch/parisc/include/asm/bitsperlong.h +++ b/arch/parisc/include/uapi/asm/bitsperlong.h diff --git a/arch/parisc/include/asm/byteorder.h b/arch/parisc/include/uapi/asm/byteorder.h index 58af2c5f5d6..58af2c5f5d6 100644 --- a/arch/parisc/include/asm/byteorder.h +++ b/arch/parisc/include/uapi/asm/byteorder.h diff --git a/arch/parisc/include/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h index 135ad6047e5..135ad6047e5 100644 --- a/arch/parisc/include/asm/errno.h +++ b/arch/parisc/include/uapi/asm/errno.h diff --git a/arch/parisc/include/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h index 0304b92ccfe..0304b92ccfe 100644 --- a/arch/parisc/include/asm/fcntl.h +++ b/arch/parisc/include/uapi/asm/fcntl.h diff --git a/arch/parisc/include/asm/ioctl.h b/arch/parisc/include/uapi/asm/ioctl.h index ec8efa02bed..ec8efa02bed 100644 --- a/arch/parisc/include/asm/ioctl.h +++ b/arch/parisc/include/uapi/asm/ioctl.h diff --git a/arch/parisc/include/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h index 054ec06f9e2..054ec06f9e2 100644 --- a/arch/parisc/include/asm/ioctls.h +++ b/arch/parisc/include/uapi/asm/ioctls.h diff --git a/arch/parisc/include/asm/ipcbuf.h b/arch/parisc/include/uapi/asm/ipcbuf.h index bd956c42578..bd956c42578 100644 --- a/arch/parisc/include/asm/ipcbuf.h +++ b/arch/parisc/include/uapi/asm/ipcbuf.h diff --git a/arch/parisc/include/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h index 12219ebce86..12219ebce86 100644 --- a/arch/parisc/include/asm/mman.h +++ b/arch/parisc/include/uapi/asm/mman.h diff --git a/arch/parisc/include/asm/msgbuf.h b/arch/parisc/include/uapi/asm/msgbuf.h index fe88f264941..fe88f264941 100644 --- a/arch/parisc/include/asm/msgbuf.h +++ b/arch/parisc/include/uapi/asm/msgbuf.h diff --git a/arch/parisc/include/uapi/asm/pdc.h b/arch/parisc/include/uapi/asm/pdc.h new file mode 100644 index 00000000000..702498f7705 --- /dev/null +++ b/arch/parisc/include/uapi/asm/pdc.h @@ -0,0 +1,427 @@ +#ifndef _UAPI_PARISC_PDC_H +#define _UAPI_PARISC_PDC_H + +/* + * PDC return values ... + * All PDC calls return a subset of these errors. + */ + +#define PDC_WARN 3 /* Call completed with a warning */ +#define PDC_REQ_ERR_1 2 /* See above */ +#define PDC_REQ_ERR_0 1 /* Call would generate a requestor error */ +#define PDC_OK 0 /* Call completed successfully */ +#define PDC_BAD_PROC -1 /* Called non-existent procedure*/ +#define PDC_BAD_OPTION -2 /* Called with non-existent option */ +#define PDC_ERROR -3 /* Call could not complete without an error */ +#define PDC_NE_MOD -5 /* Module not found */ +#define PDC_NE_CELL_MOD -7 /* Cell module not found */ +#define PDC_INVALID_ARG -10 /* Called with an invalid argument */ +#define PDC_BUS_POW_WARN -12 /* Call could not complete in allowed power budget */ +#define PDC_NOT_NARROW -17 /* Narrow mode not supported */ + +/* + * PDC entry points... + */ + +#define PDC_POW_FAIL 1 /* perform a power-fail */ +#define PDC_POW_FAIL_PREPARE 0 /* prepare for powerfail */ + +#define PDC_CHASSIS 2 /* PDC-chassis functions */ +#define PDC_CHASSIS_DISP 0 /* update chassis display */ +#define PDC_CHASSIS_WARN 1 /* return chassis warnings */ +#define PDC_CHASSIS_DISPWARN 2 /* update&return chassis status */ +#define PDC_RETURN_CHASSIS_INFO 128 /* HVERSION dependent: return chassis LED/LCD info */ + +#define PDC_PIM 3 /* Get PIM data */ +#define PDC_PIM_HPMC 0 /* Transfer HPMC data */ +#define PDC_PIM_RETURN_SIZE 1 /* Get Max buffer needed for PIM*/ +#define PDC_PIM_LPMC 2 /* Transfer HPMC data */ +#define PDC_PIM_SOFT_BOOT 3 /* Transfer Soft Boot data */ +#define PDC_PIM_TOC 4 /* Transfer TOC data */ + +#define PDC_MODEL 4 /* PDC model information call */ +#define PDC_MODEL_INFO 0 /* returns information */ +#define PDC_MODEL_BOOTID 1 /* set the BOOT_ID */ +#define PDC_MODEL_VERSIONS 2 /* returns cpu-internal versions*/ +#define PDC_MODEL_SYSMODEL 3 /* return system model info */ +#define PDC_MODEL_ENSPEC 4 /* enable specific option */ +#define PDC_MODEL_DISPEC 5 /* disable specific option */ +#define PDC_MODEL_CPU_ID 6 /* returns cpu-id (only newer machines!) */ +#define PDC_MODEL_CAPABILITIES 7 /* returns OS32/OS64-flags */ +/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */ +#define PDC_MODEL_OS64 (1 << 0) +#define PDC_MODEL_OS32 (1 << 1) +#define PDC_MODEL_IOPDIR_FDC (1 << 2) +#define PDC_MODEL_NVA_MASK (3 << 4) +#define PDC_MODEL_NVA_SUPPORTED (0 << 4) +#define PDC_MODEL_NVA_SLOW (1 << 4) +#define PDC_MODEL_NVA_UNSUPPORTED (3 << 4) +#define PDC_MODEL_GET_BOOT__OP 8 /* returns boot test options */ +#define PDC_MODEL_SET_BOOT__OP 9 /* set boot test options */ + +#define PA89_INSTRUCTION_SET 0x4 /* capatibilies returned */ +#define PA90_INSTRUCTION_SET 0x8 + +#define PDC_CACHE 5 /* return/set cache (& TLB) info*/ +#define PDC_CACHE_INFO 0 /* returns information */ +#define PDC_CACHE_SET_COH 1 /* set coherence state */ +#define PDC_CACHE_RET_SPID 2 /* returns space-ID bits */ + +#define PDC_HPA 6 /* return HPA of processor */ +#define PDC_HPA_PROCESSOR 0 +#define PDC_HPA_MODULES 1 + +#define PDC_COPROC 7 /* Co-Processor (usually FP unit(s)) */ +#define PDC_COPROC_CFG 0 /* Co-Processor Cfg (FP unit(s) enabled?) */ + +#define PDC_IODC 8 /* talk to IODC */ +#define PDC_IODC_READ 0 /* read IODC entry point */ +/* PDC_IODC_RI_ * INDEX parameter of PDC_IODC_READ */ +#define PDC_IODC_RI_DATA_BYTES 0 /* IODC Data Bytes */ +/* 1, 2 obsolete - HVERSION dependent*/ +#define PDC_IODC_RI_INIT 3 /* Initialize module */ +#define PDC_IODC_RI_IO 4 /* Module input/output */ +#define PDC_IODC_RI_SPA 5 /* Module input/output */ +#define PDC_IODC_RI_CONFIG 6 /* Module input/output */ +/* 7 obsolete - HVERSION dependent */ +#define PDC_IODC_RI_TEST 8 /* Module input/output */ +#define PDC_IODC_RI_TLB 9 /* Module input/output */ +#define PDC_IODC_NINIT 2 /* non-destructive init */ +#define PDC_IODC_DINIT 3 /* destructive init */ +#define PDC_IODC_MEMERR 4 /* check for memory errors */ +#define PDC_IODC_INDEX_DATA 0 /* get first 16 bytes from mod IODC */ +#define PDC_IODC_BUS_ERROR -4 /* bus error return value */ +#define PDC_IODC_INVALID_INDEX -5 /* invalid index return value */ +#define PDC_IODC_COUNT -6 /* count is too small */ + +#define PDC_TOD 9 /* time-of-day clock (TOD) */ +#define PDC_TOD_READ 0 /* read TOD */ +#define PDC_TOD_WRITE 1 /* write TOD */ + + +#define PDC_STABLE 10 /* stable storage (sprockets) */ +#define PDC_STABLE_READ 0 +#define PDC_STABLE_WRITE 1 +#define PDC_STABLE_RETURN_SIZE 2 +#define PDC_STABLE_VERIFY_CONTENTS 3 +#define PDC_STABLE_INITIALIZE 4 + +#define PDC_NVOLATILE 11 /* often not implemented */ + +#define PDC_ADD_VALID 12 /* Memory validation PDC call */ +#define PDC_ADD_VALID_VERIFY 0 /* Make PDC_ADD_VALID verify region */ + +#define PDC_INSTR 15 /* get instr to invoke PDCE_CHECK() */ + +#define PDC_PROC 16 /* (sprockets) */ + +#define PDC_CONFIG 16 /* (sprockets) */ +#define PDC_CONFIG_DECONFIG 0 +#define PDC_CONFIG_DRECONFIG 1 +#define PDC_CONFIG_DRETURN_CONFIG 2 + +#define PDC_BLOCK_TLB 18 /* manage hardware block-TLB */ +#define PDC_BTLB_INFO 0 /* returns parameter */ +#define PDC_BTLB_INSERT 1 /* insert BTLB entry */ +#define PDC_BTLB_PURGE 2 /* purge BTLB entries */ +#define PDC_BTLB_PURGE_ALL 3 /* purge all BTLB entries */ + +#define PDC_TLB 19 /* manage hardware TLB miss handling */ +#define PDC_TLB_INFO 0 /* returns parameter */ +#define PDC_TLB_SETUP 1 /* set up miss handling */ + +#define PDC_MEM 20 /* Manage memory */ +#define PDC_MEM_MEMINFO 0 +#define PDC_MEM_ADD_PAGE 1 +#define PDC_MEM_CLEAR_PDT 2 +#define PDC_MEM_READ_PDT 3 +#define PDC_MEM_RESET_CLEAR 4 +#define PDC_MEM_GOODMEM 5 +#define PDC_MEM_TABLE 128 /* Non contig mem map (sprockets) */ +#define PDC_MEM_RETURN_ADDRESS_TABLE PDC_MEM_TABLE +#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE 131 +#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES 132 +#define PDC_MEM_GET_PHYSICAL_LOCATION_FROM_MEMORY_ADDRESS 133 + +#define PDC_MEM_RET_SBE_REPLACED 5 /* PDC_MEM return values */ +#define PDC_MEM_RET_DUPLICATE_ENTRY 4 +#define PDC_MEM_RET_BUF_SIZE_SMALL 1 +#define PDC_MEM_RET_PDT_FULL -11 +#define PDC_MEM_RET_INVALID_PHYSICAL_LOCATION ~0ULL + +#define PDC_PSW 21 /* Get/Set default System Mask */ +#define PDC_PSW_MASK 0 /* Return mask */ +#define PDC_PSW_GET_DEFAULTS 1 /* Return defaults */ +#define PDC_PSW_SET_DEFAULTS 2 /* Set default */ +#define PDC_PSW_ENDIAN_BIT 1 /* set for big endian */ +#define PDC_PSW_WIDE_BIT 2 /* set for wide mode */ + +#define PDC_SYSTEM_MAP 22 /* find system modules */ +#define PDC_FIND_MODULE 0 +#define PDC_FIND_ADDRESS 1 +#define PDC_TRANSLATE_PATH 2 + +#define PDC_SOFT_POWER 23 /* soft power switch */ +#define PDC_SOFT_POWER_INFO 0 /* return info about the soft power switch */ +#define PDC_SOFT_POWER_ENABLE 1 /* enable/disable soft power switch */ + + +/* HVERSION dependent */ + +/* The PDC_MEM_MAP calls */ +#define PDC_MEM_MAP 128 /* on s700: return page info */ +#define PDC_MEM_MAP_HPA 0 /* returns hpa of a module */ + +#define PDC_EEPROM 129 /* EEPROM access */ +#define PDC_EEPROM_READ_WORD 0 +#define PDC_EEPROM_WRITE_WORD 1 +#define PDC_EEPROM_READ_BYTE 2 +#define PDC_EEPROM_WRITE_BYTE 3 +#define PDC_EEPROM_EEPROM_PASSWORD -1000 + +#define PDC_NVM 130 /* NVM (non-volatile memory) access */ +#define PDC_NVM_READ_WORD 0 +#define PDC_NVM_WRITE_WORD 1 +#define PDC_NVM_READ_BYTE 2 +#define PDC_NVM_WRITE_BYTE 3 + +#define PDC_SEED_ERROR 132 /* (sprockets) */ + +#define PDC_IO 135 /* log error info, reset IO system */ +#define PDC_IO_READ_AND_CLEAR_ERRORS 0 +#define PDC_IO_RESET 1 +#define PDC_IO_RESET_DEVICES 2 +/* sets bits 6&7 (little endian) of the HcControl Register */ +#define PDC_IO_USB_SUSPEND 0xC000000000000000 +#define PDC_IO_EEPROM_IO_ERR_TABLE_FULL -5 /* return value */ +#define PDC_IO_NO_SUSPEND -6 /* return value */ + +#define PDC_BROADCAST_RESET 136 /* reset all processors */ +#define PDC_DO_RESET 0 /* option: perform a broadcast reset */ +#define PDC_DO_FIRM_TEST_RESET 1 /* Do broadcast reset with bitmap */ +#define PDC_BR_RECONFIGURATION 2 /* reset w/reconfiguration */ +#define PDC_FIRM_TEST_MAGIC 0xab9ec36fUL /* for this reboot only */ + +#define PDC_LAN_STATION_ID 138 /* Hversion dependent mechanism for */ +#define PDC_LAN_STATION_ID_READ 0 /* getting the lan station address */ + +#define PDC_LAN_STATION_ID_SIZE 6 + +#define PDC_CHECK_RANGES 139 /* (sprockets) */ + +#define PDC_NV_SECTIONS 141 /* (sprockets) */ + +#define PDC_PERFORMANCE 142 /* performance monitoring */ + +#define PDC_SYSTEM_INFO 143 /* system information */ +#define PDC_SYSINFO_RETURN_INFO_SIZE 0 +#define PDC_SYSINFO_RRETURN_SYS_INFO 1 +#define PDC_SYSINFO_RRETURN_ERRORS 2 +#define PDC_SYSINFO_RRETURN_WARNINGS 3 +#define PDC_SYSINFO_RETURN_REVISIONS 4 +#define PDC_SYSINFO_RRETURN_DIAGNOSE 5 +#define PDC_SYSINFO_RRETURN_HV_DIAGNOSE 1005 + +#define PDC_RDR 144 /* (sprockets) */ +#define PDC_RDR_READ_BUFFER 0 +#define PDC_RDR_READ_SINGLE 1 +#define PDC_RDR_WRITE_SINGLE 2 + +#define PDC_INTRIGUE 145 /* (sprockets) */ +#define PDC_INTRIGUE_WRITE_BUFFER 0 +#define PDC_INTRIGUE_GET_SCRATCH_BUFSIZE 1 +#define PDC_INTRIGUE_START_CPU_COUNTERS 2 +#define PDC_INTRIGUE_STOP_CPU_COUNTERS 3 + +#define PDC_STI 146 /* STI access */ +/* same as PDC_PCI_XXX values (see below) */ + +/* Legacy PDC definitions for same stuff */ +#define PDC_PCI_INDEX 147 +#define PDC_PCI_INTERFACE_INFO 0 +#define PDC_PCI_SLOT_INFO 1 +#define PDC_PCI_INFLIGHT_BYTES 2 +#define PDC_PCI_READ_CONFIG 3 +#define PDC_PCI_WRITE_CONFIG 4 +#define PDC_PCI_READ_PCI_IO 5 +#define PDC_PCI_WRITE_PCI_IO 6 +#define PDC_PCI_READ_CONFIG_DELAY 7 +#define PDC_PCI_UPDATE_CONFIG_DELAY 8 +#define PDC_PCI_PCI_PATH_TO_PCI_HPA 9 +#define PDC_PCI_PCI_HPA_TO_PCI_PATH 10 +#define PDC_PCI_PCI_PATH_TO_PCI_BUS 11 +#define PDC_PCI_PCI_RESERVED 12 +#define PDC_PCI_PCI_INT_ROUTE_SIZE 13 +#define PDC_PCI_GET_INT_TBL_SIZE PDC_PCI_PCI_INT_ROUTE_SIZE +#define PDC_PCI_PCI_INT_ROUTE 14 +#define PDC_PCI_GET_INT_TBL PDC_PCI_PCI_INT_ROUTE +#define PDC_PCI_READ_MON_TYPE 15 +#define PDC_PCI_WRITE_MON_TYPE 16 + + +/* Get SCSI Interface Card info: SDTR, SCSI ID, mode (SE vs LVD) */ +#define PDC_INITIATOR 163 +#define PDC_GET_INITIATOR 0 +#define PDC_SET_INITIATOR 1 +#define PDC_DELETE_INITIATOR 2 +#define PDC_RETURN_TABLE_SIZE 3 +#define PDC_RETURN_TABLE 4 + +#define PDC_LINK 165 /* (sprockets) */ +#define PDC_LINK_PCI_ENTRY_POINTS 0 /* list (Arg1) = 0 */ +#define PDC_LINK_USB_ENTRY_POINTS 1 /* list (Arg1) = 1 */ + +/* cl_class + * page 3-33 of IO-Firmware ARS + * IODC ENTRY_INIT(Search first) RET[1] + */ +#define CL_NULL 0 /* invalid */ +#define CL_RANDOM 1 /* random access (as disk) */ +#define CL_SEQU 2 /* sequential access (as tape) */ +#define CL_DUPLEX 7 /* full-duplex point-to-point (RS-232, Net) */ +#define CL_KEYBD 8 /* half-duplex console (HIL Keyboard) */ +#define CL_DISPL 9 /* half-duplex console (display) */ +#define CL_FC 10 /* FiberChannel access media */ + +/* IODC ENTRY_INIT() */ +#define ENTRY_INIT_SRCH_FRST 2 +#define ENTRY_INIT_SRCH_NEXT 3 +#define ENTRY_INIT_MOD_DEV 4 +#define ENTRY_INIT_DEV 5 +#define ENTRY_INIT_MOD 6 +#define ENTRY_INIT_MSG 9 + +/* IODC ENTRY_IO() */ +#define ENTRY_IO_BOOTIN 0 +#define ENTRY_IO_BOOTOUT 1 +#define ENTRY_IO_CIN 2 +#define ENTRY_IO_COUT 3 +#define ENTRY_IO_CLOSE 4 +#define ENTRY_IO_GETMSG 9 +#define ENTRY_IO_BBLOCK_IN 16 +#define ENTRY_IO_BBLOCK_OUT 17 + +/* IODC ENTRY_SPA() */ + +/* IODC ENTRY_CONFIG() */ + +/* IODC ENTRY_TEST() */ + +/* IODC ENTRY_TLB() */ + +/* constants for OS (NVM...) */ +#define OS_ID_NONE 0 /* Undefined OS ID */ +#define OS_ID_HPUX 1 /* HP-UX OS */ +#define OS_ID_MPEXL 2 /* MPE XL OS */ +#define OS_ID_OSF 3 /* OSF OS */ +#define OS_ID_HPRT 4 /* HP-RT OS */ +#define OS_ID_NOVEL 5 /* NOVELL OS */ +#define OS_ID_LINUX 6 /* Linux */ + + +/* constants for PDC_CHASSIS */ +#define OSTAT_OFF 0 +#define OSTAT_FLT 1 +#define OSTAT_TEST 2 +#define OSTAT_INIT 3 +#define OSTAT_SHUT 4 +#define OSTAT_WARN 5 +#define OSTAT_RUN 6 +#define OSTAT_ON 7 + +/* Page Zero constant offsets used by the HPMC handler */ +#define BOOT_CONSOLE_HPA_OFFSET 0x3c0 +#define BOOT_CONSOLE_SPA_OFFSET 0x3c4 +#define BOOT_CONSOLE_PATH_OFFSET 0x3a8 + +/* size of the pdc_result buffer for firmware.c */ +#define NUM_PDC_RESULT 32 + +#if !defined(__ASSEMBLY__) + +#include <linux/types.h> + + +/* flags of the device_path */ +#define PF_AUTOBOOT 0x80 +#define PF_AUTOSEARCH 0x40 +#define PF_TIMER 0x0F + +struct device_path { /* page 1-69 */ + unsigned char flags; /* flags see above! */ + unsigned char bc[6]; /* bus converter routing info */ + unsigned char mod; + unsigned int layers[6];/* device-specific layer-info */ +} __attribute__((aligned(8))) ; + +struct pz_device { + struct device_path dp; /* see above */ + /* struct iomod *hpa; */ + unsigned int hpa; /* HPA base address */ + /* char *spa; */ + unsigned int spa; /* SPA base address */ + /* int (*iodc_io)(struct iomod*, ...); */ + unsigned int iodc_io; /* device entry point */ + short pad; /* reserved */ + unsigned short cl_class;/* see below */ +} __attribute__((aligned(8))) ; + +struct zeropage { + /* [0x000] initialize vectors (VEC) */ + unsigned int vec_special; /* must be zero */ + /* int (*vec_pow_fail)(void);*/ + unsigned int vec_pow_fail; /* power failure handler */ + /* int (*vec_toc)(void); */ + unsigned int vec_toc; + unsigned int vec_toclen; + /* int (*vec_rendz)(void); */ + unsigned int vec_rendz; + int vec_pow_fail_flen; + int vec_pad[10]; + + /* [0x040] reserved processor dependent */ + int pad0[112]; + + /* [0x200] reserved */ + int pad1[84]; + + /* [0x350] memory configuration (MC) */ + int memc_cont; /* contiguous mem size (bytes) */ + int memc_phsize; /* physical memory size */ + int memc_adsize; /* additional mem size, bytes of SPA space used by PDC */ + unsigned int mem_pdc_hi; /* used for 64-bit */ + + /* [0x360] various parameters for the boot-CPU */ + /* unsigned int *mem_booterr[8]; */ + unsigned int mem_booterr[8]; /* ptr to boot errors */ + unsigned int mem_free; /* first location, where OS can be loaded */ + /* struct iomod *mem_hpa; */ + unsigned int mem_hpa; /* HPA of the boot-CPU */ + /* int (*mem_pdc)(int, ...); */ + unsigned int mem_pdc; /* PDC entry point */ + unsigned int mem_10msec; /* number of clock ticks in 10msec */ + + /* [0x390] initial memory module (IMM) */ + /* struct iomod *imm_hpa; */ + unsigned int imm_hpa; /* HPA of the IMM */ + int imm_soft_boot; /* 0 = was hard boot, 1 = was soft boot */ + unsigned int imm_spa_size; /* SPA size of the IMM in bytes */ + unsigned int imm_max_mem; /* bytes of mem in IMM */ + + /* [0x3A0] boot console, display device and keyboard */ + struct pz_device mem_cons; /* description of console device */ + struct pz_device mem_boot; /* description of boot device */ + struct pz_device mem_kbd; /* description of keyboard device */ + + /* [0x430] reserved */ + int pad430[116]; + + /* [0x600] processor dependent */ + __u32 pad600[1]; + __u32 proc_sti; /* pointer to STI ROM */ + __u32 pad608[126]; +}; + +#endif /* !defined(__ASSEMBLY__) */ + +#endif /* _UAPI_PARISC_PDC_H */ diff --git a/arch/parisc/include/asm/posix_types.h b/arch/parisc/include/uapi/asm/posix_types.h index b9344256f76..b9344256f76 100644 --- a/arch/parisc/include/asm/posix_types.h +++ b/arch/parisc/include/uapi/asm/posix_types.h diff --git a/arch/parisc/include/uapi/asm/ptrace.h b/arch/parisc/include/uapi/asm/ptrace.h new file mode 100644 index 00000000000..c4fa6c8b9ad --- /dev/null +++ b/arch/parisc/include/uapi/asm/ptrace.h @@ -0,0 +1,47 @@ +/* written by Philipp Rumpf, Copyright (C) 1999 SuSE GmbH Nuernberg +** Copyright (C) 2000 Grant Grundler, Hewlett-Packard +*/ +#ifndef _UAPI_PARISC_PTRACE_H +#define _UAPI_PARISC_PTRACE_H + + +#include <linux/types.h> + +/* This struct defines the way the registers are stored on the + * stack during a system call. + * + * N.B. gdb/strace care about the size and offsets within this + * structure. If you change things, you may break object compatibility + * for those applications. + */ + +struct pt_regs { + unsigned long gr[32]; /* PSW is in gr[0] */ + __u64 fr[32]; + unsigned long sr[ 8]; + unsigned long iasq[2]; + unsigned long iaoq[2]; + unsigned long cr27; + unsigned long pad0; /* available for other uses */ + unsigned long orig_r28; + unsigned long ksp; + unsigned long kpc; + unsigned long sar; /* CR11 */ + unsigned long iir; /* CR19 */ + unsigned long isr; /* CR20 */ + unsigned long ior; /* CR21 */ + unsigned long ipsw; /* CR22 */ +}; + +/* + * The numbers chosen here are somewhat arbitrary but absolutely MUST + * not overlap with any of the number assigned in <linux/ptrace.h>. + * + * These ones are taken from IA-64 on the assumption that theirs are + * the most correct (and we also want to support PTRACE_SINGLEBLOCK + * since we have taken branch traps too) + */ +#define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */ + + +#endif /* _UAPI_PARISC_PTRACE_H */ diff --git a/arch/parisc/include/asm/resource.h b/arch/parisc/include/uapi/asm/resource.h index 8b06343b62e..8b06343b62e 100644 --- a/arch/parisc/include/asm/resource.h +++ b/arch/parisc/include/uapi/asm/resource.h diff --git a/arch/parisc/include/asm/sembuf.h b/arch/parisc/include/uapi/asm/sembuf.h index 1e59ffd3bd1..1e59ffd3bd1 100644 --- a/arch/parisc/include/asm/sembuf.h +++ b/arch/parisc/include/uapi/asm/sembuf.h diff --git a/arch/parisc/include/asm/setup.h b/arch/parisc/include/uapi/asm/setup.h index 7da2e5b8747..7da2e5b8747 100644 --- a/arch/parisc/include/asm/setup.h +++ b/arch/parisc/include/uapi/asm/setup.h diff --git a/arch/parisc/include/asm/shmbuf.h b/arch/parisc/include/uapi/asm/shmbuf.h index 0a3eada1863..0a3eada1863 100644 --- a/arch/parisc/include/asm/shmbuf.h +++ b/arch/parisc/include/uapi/asm/shmbuf.h diff --git a/arch/parisc/include/asm/sigcontext.h b/arch/parisc/include/uapi/asm/sigcontext.h index 27ef31bb3b6..27ef31bb3b6 100644 --- a/arch/parisc/include/asm/sigcontext.h +++ b/arch/parisc/include/uapi/asm/sigcontext.h diff --git a/arch/parisc/include/asm/siginfo.h b/arch/parisc/include/uapi/asm/siginfo.h index d7034728f37..d7034728f37 100644 --- a/arch/parisc/include/asm/siginfo.h +++ b/arch/parisc/include/uapi/asm/siginfo.h diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h new file mode 100644 index 00000000000..b1ddaa24337 --- /dev/null +++ b/arch/parisc/include/uapi/asm/signal.h @@ -0,0 +1,118 @@ +#ifndef _UAPI_ASM_PARISC_SIGNAL_H +#define _UAPI_ASM_PARISC_SIGNAL_H + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGEMT 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGBUS 10 +#define SIGSEGV 11 +#define SIGSYS 12 /* Linux doesn't use this */ +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGUSR1 16 +#define SIGUSR2 17 +#define SIGCHLD 18 +#define SIGPWR 19 +#define SIGVTALRM 20 +#define SIGPROF 21 +#define SIGIO 22 +#define SIGPOLL SIGIO +#define SIGWINCH 23 +#define SIGSTOP 24 +#define SIGTSTP 25 +#define SIGCONT 26 +#define SIGTTIN 27 +#define SIGTTOU 28 +#define SIGURG 29 +#define SIGLOST 30 /* Linux doesn't use this either */ +#define SIGUNUSED 31 +#define SIGRESERVE SIGUNUSED + +#define SIGXCPU 33 +#define SIGXFSZ 34 +#define SIGSTKFLT 36 + +/* These should not be considered constants from userland. */ +#define SIGRTMIN 37 +#define SIGRTMAX _NSIG /* it's 44 under HP/UX */ + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_ONSTACK 0x00000001 +#define SA_RESETHAND 0x00000004 +#define SA_NOCLDSTOP 0x00000008 +#define SA_SIGINFO 0x00000010 +#define SA_NODEFER 0x00000020 +#define SA_RESTART 0x00000040 +#define SA_NOCLDWAIT 0x00000080 +#define _SA_SIGGFAULT 0x00000100 /* HPUX */ + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND + +#define SA_RESTORER 0x04000000 /* obsolete -- ignored */ + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 + + +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */ + +#define SIG_DFL ((__sighandler_t)0) /* default signal handling */ +#define SIG_IGN ((__sighandler_t)1) /* ignore signal */ +#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ + +# ifndef __ASSEMBLY__ + +# include <linux/types.h> + +/* Avoid too many header ordering problems. */ +struct siginfo; + +/* Type of a signal handler. */ +#ifdef CONFIG_64BIT +/* function pointers on 64-bit parisc are pointers to little structs and the + * compiler doesn't support code which changes or tests the address of + * the function in the little struct. This is really ugly -PB + */ +typedef char __user *__sighandler_t; +#else +typedef void __signalfn_t(int); +typedef __signalfn_t __user *__sighandler_t; +#endif + +typedef struct sigaltstack { + void __user *ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +#endif /* !__ASSEMBLY */ +#endif /* _UAPI_ASM_PARISC_SIGNAL_H */ diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index 1b52c2c31a7..1b52c2c31a7 100644 --- a/arch/parisc/include/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h diff --git a/arch/parisc/include/asm/sockios.h b/arch/parisc/include/uapi/asm/sockios.h index dabfbc7483f..dabfbc7483f 100644 --- a/arch/parisc/include/asm/sockios.h +++ b/arch/parisc/include/uapi/asm/sockios.h diff --git a/arch/parisc/include/asm/stat.h b/arch/parisc/include/uapi/asm/stat.h index d76fbda5d62..d76fbda5d62 100644 --- a/arch/parisc/include/asm/stat.h +++ b/arch/parisc/include/uapi/asm/stat.h diff --git a/arch/parisc/include/asm/statfs.h b/arch/parisc/include/uapi/asm/statfs.h index 324bea905dc..324bea905dc 100644 --- a/arch/parisc/include/asm/statfs.h +++ b/arch/parisc/include/uapi/asm/statfs.h diff --git a/arch/parisc/include/asm/swab.h b/arch/parisc/include/uapi/asm/swab.h index e78403b129e..e78403b129e 100644 --- a/arch/parisc/include/asm/swab.h +++ b/arch/parisc/include/uapi/asm/swab.h diff --git a/arch/parisc/include/asm/termbits.h b/arch/parisc/include/uapi/asm/termbits.h index d1ab92177a5..d1ab92177a5 100644 --- a/arch/parisc/include/asm/termbits.h +++ b/arch/parisc/include/uapi/asm/termbits.h diff --git a/arch/parisc/include/uapi/asm/termios.h b/arch/parisc/include/uapi/asm/termios.h new file mode 100644 index 00000000000..f3377395070 --- /dev/null +++ b/arch/parisc/include/uapi/asm/termios.h @@ -0,0 +1,43 @@ +#ifndef _UAPI_PARISC_TERMIOS_H +#define _UAPI_PARISC_TERMIOS_H + +#include <asm/termbits.h> +#include <asm/ioctls.h> + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 8 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + + +#endif /* _UAPI_PARISC_TERMIOS_H */ diff --git a/arch/parisc/include/asm/types.h b/arch/parisc/include/uapi/asm/types.h index 8866f9bbdea..8866f9bbdea 100644 --- a/arch/parisc/include/asm/types.h +++ b/arch/parisc/include/uapi/asm/types.h diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h new file mode 100644 index 00000000000..e178f30f2cc --- /dev/null +++ b/arch/parisc/include/uapi/asm/unistd.h @@ -0,0 +1,837 @@ +#ifndef _UAPI_ASM_PARISC_UNISTD_H_ +#define _UAPI_ASM_PARISC_UNISTD_H_ + +/* + * This file contains the system call numbers. + */ + +/* + * HP-UX system calls get their native numbers for binary compatibility. + */ + +#define __NR_HPUX_exit 1 +#define __NR_HPUX_fork 2 +#define __NR_HPUX_read 3 +#define __NR_HPUX_write 4 +#define __NR_HPUX_open 5 +#define __NR_HPUX_close 6 +#define __NR_HPUX_wait 7 +#define __NR_HPUX_creat 8 +#define __NR_HPUX_link 9 +#define __NR_HPUX_unlink 10 +#define __NR_HPUX_execv 11 +#define __NR_HPUX_chdir 12 +#define __NR_HPUX_time 13 +#define __NR_HPUX_mknod 14 +#define __NR_HPUX_chmod 15 +#define __NR_HPUX_chown 16 +#define __NR_HPUX_break 17 +#define __NR_HPUX_lchmod 18 +#define __NR_HPUX_lseek 19 +#define __NR_HPUX_getpid 20 +#define __NR_HPUX_mount 21 +#define __NR_HPUX_umount 22 +#define __NR_HPUX_setuid 23 +#define __NR_HPUX_getuid 24 +#define __NR_HPUX_stime 25 +#define __NR_HPUX_ptrace 26 +#define __NR_HPUX_alarm 27 +#define __NR_HPUX_oldfstat 28 +#define __NR_HPUX_pause 29 +#define __NR_HPUX_utime 30 +#define __NR_HPUX_stty 31 +#define __NR_HPUX_gtty 32 +#define __NR_HPUX_access 33 +#define __NR_HPUX_nice 34 +#define __NR_HPUX_ftime 35 +#define __NR_HPUX_sync 36 +#define __NR_HPUX_kill 37 +#define __NR_HPUX_stat 38 +#define __NR_HPUX_setpgrp3 39 +#define __NR_HPUX_lstat 40 +#define __NR_HPUX_dup 41 +#define __NR_HPUX_pipe 42 +#define __NR_HPUX_times 43 +#define __NR_HPUX_profil 44 +#define __NR_HPUX_ki_call 45 +#define __NR_HPUX_setgid 46 +#define __NR_HPUX_getgid 47 +#define __NR_HPUX_sigsys 48 +#define __NR_HPUX_reserved1 49 +#define __NR_HPUX_reserved2 50 +#define __NR_HPUX_acct 51 +#define __NR_HPUX_set_userthreadid 52 +#define __NR_HPUX_oldlock 53 +#define __NR_HPUX_ioctl 54 +#define __NR_HPUX_reboot 55 +#define __NR_HPUX_symlink 56 +#define __NR_HPUX_utssys 57 +#define __NR_HPUX_readlink 58 +#define __NR_HPUX_execve 59 +#define __NR_HPUX_umask 60 +#define __NR_HPUX_chroot 61 +#define __NR_HPUX_fcntl 62 +#define __NR_HPUX_ulimit 63 +#define __NR_HPUX_getpagesize 64 +#define __NR_HPUX_mremap 65 +#define __NR_HPUX_vfork 66 +#define __NR_HPUX_vread 67 +#define __NR_HPUX_vwrite 68 +#define __NR_HPUX_sbrk 69 +#define __NR_HPUX_sstk 70 +#define __NR_HPUX_mmap 71 +#define __NR_HPUX_vadvise 72 +#define __NR_HPUX_munmap 73 +#define __NR_HPUX_mprotect 74 +#define __NR_HPUX_madvise 75 +#define __NR_HPUX_vhangup 76 +#define __NR_HPUX_swapoff 77 +#define __NR_HPUX_mincore 78 +#define __NR_HPUX_getgroups 79 +#define __NR_HPUX_setgroups 80 +#define __NR_HPUX_getpgrp2 81 +#define __NR_HPUX_setpgrp2 82 +#define __NR_HPUX_setitimer 83 +#define __NR_HPUX_wait3 84 +#define __NR_HPUX_swapon 85 +#define __NR_HPUX_getitimer 86 +#define __NR_HPUX_gethostname42 87 +#define __NR_HPUX_sethostname42 88 +#define __NR_HPUX_getdtablesize 89 +#define __NR_HPUX_dup2 90 +#define __NR_HPUX_getdopt 91 +#define __NR_HPUX_fstat 92 +#define __NR_HPUX_select 93 +#define __NR_HPUX_setdopt 94 +#define __NR_HPUX_fsync 95 +#define __NR_HPUX_setpriority 96 +#define __NR_HPUX_socket_old 97 +#define __NR_HPUX_connect_old 98 +#define __NR_HPUX_accept_old 99 +#define __NR_HPUX_getpriority 100 +#define __NR_HPUX_send_old 101 +#define __NR_HPUX_recv_old 102 +#define __NR_HPUX_socketaddr_old 103 +#define __NR_HPUX_bind_old 104 +#define __NR_HPUX_setsockopt_old 105 +#define __NR_HPUX_listen_old 106 +#define __NR_HPUX_vtimes_old 107 +#define __NR_HPUX_sigvector 108 +#define __NR_HPUX_sigblock 109 +#define __NR_HPUX_siggetmask 110 +#define __NR_HPUX_sigpause 111 +#define __NR_HPUX_sigstack 112 +#define __NR_HPUX_recvmsg_old 113 +#define __NR_HPUX_sendmsg_old 114 +#define __NR_HPUX_vtrace_old 115 +#define __NR_HPUX_gettimeofday 116 +#define __NR_HPUX_getrusage 117 +#define __NR_HPUX_getsockopt_old 118 +#define __NR_HPUX_resuba_old 119 +#define __NR_HPUX_readv 120 +#define __NR_HPUX_writev 121 +#define __NR_HPUX_settimeofday 122 +#define __NR_HPUX_fchown 123 +#define __NR_HPUX_fchmod 124 +#define __NR_HPUX_recvfrom_old 125 +#define __NR_HPUX_setresuid 126 +#define __NR_HPUX_setresgid 127 +#define __NR_HPUX_rename 128 +#define __NR_HPUX_truncate 129 +#define __NR_HPUX_ftruncate 130 +#define __NR_HPUX_flock_old 131 +#define __NR_HPUX_sysconf 132 +#define __NR_HPUX_sendto_old 133 +#define __NR_HPUX_shutdown_old 134 +#define __NR_HPUX_socketpair_old 135 +#define __NR_HPUX_mkdir 136 +#define __NR_HPUX_rmdir 137 +#define __NR_HPUX_utimes_old 138 +#define __NR_HPUX_sigcleanup_old 139 +#define __NR_HPUX_setcore 140 +#define __NR_HPUX_getpeername_old 141 +#define __NR_HPUX_gethostid 142 +#define __NR_HPUX_sethostid 143 +#define __NR_HPUX_getrlimit 144 +#define __NR_HPUX_setrlimit 145 +#define __NR_HPUX_killpg_old 146 +#define __NR_HPUX_cachectl 147 +#define __NR_HPUX_quotactl 148 +#define __NR_HPUX_get_sysinfo 149 +#define __NR_HPUX_getsockname_old 150 +#define __NR_HPUX_privgrp 151 +#define __NR_HPUX_rtprio 152 +#define __NR_HPUX_plock 153 +#define __NR_HPUX_reserved3 154 +#define __NR_HPUX_lockf 155 +#define __NR_HPUX_semget 156 +#define __NR_HPUX_osemctl 157 +#define __NR_HPUX_semop 158 +#define __NR_HPUX_msgget 159 +#define __NR_HPUX_omsgctl 160 +#define __NR_HPUX_msgsnd 161 +#define __NR_HPUX_msgrecv 162 +#define __NR_HPUX_shmget 163 +#define __NR_HPUX_oshmctl 164 +#define __NR_HPUX_shmat 165 +#define __NR_HPUX_shmdt 166 +#define __NR_HPUX_m68020_advise 167 +/* [168,189] are for Discless/DUX */ +#define __NR_HPUX_csp 168 +#define __NR_HPUX_cluster 169 +#define __NR_HPUX_mkrnod 170 +#define __NR_HPUX_test 171 +#define __NR_HPUX_unsp_open 172 +#define __NR_HPUX_reserved4 173 +#define __NR_HPUX_getcontext_old 174 +#define __NR_HPUX_osetcontext 175 +#define __NR_HPUX_bigio 176 +#define __NR_HPUX_pipenode 177 +#define __NR_HPUX_lsync 178 +#define __NR_HPUX_getmachineid 179 +#define __NR_HPUX_cnodeid 180 +#define __NR_HPUX_cnodes 181 +#define __NR_HPUX_swapclients 182 +#define __NR_HPUX_rmt_process 183 +#define __NR_HPUX_dskless_stats 184 +#define __NR_HPUX_sigprocmask 185 +#define __NR_HPUX_sigpending 186 +#define __NR_HPUX_sigsuspend 187 +#define __NR_HPUX_sigaction 188 +#define __NR_HPUX_reserved5 189 +#define __NR_HPUX_nfssvc 190 +#define __NR_HPUX_getfh 191 +#define __NR_HPUX_getdomainname 192 +#define __NR_HPUX_setdomainname 193 +#define __NR_HPUX_async_daemon 194 +#define __NR_HPUX_getdirentries 195 +#define __NR_HPUX_statfs 196 +#define __NR_HPUX_fstatfs 197 +#define __NR_HPUX_vfsmount 198 +#define __NR_HPUX_reserved6 199 +#define __NR_HPUX_waitpid 200 +/* 201 - 223 missing */ +#define __NR_HPUX_sigsetreturn 224 +#define __NR_HPUX_sigsetstatemask 225 +/* 226 missing */ +#define __NR_HPUX_cs 227 +#define __NR_HPUX_cds 228 +#define __NR_HPUX_set_no_trunc 229 +#define __NR_HPUX_pathconf 230 +#define __NR_HPUX_fpathconf 231 +/* 232, 233 missing */ +#define __NR_HPUX_nfs_fcntl 234 +#define __NR_HPUX_ogetacl 235 +#define __NR_HPUX_ofgetacl 236 +#define __NR_HPUX_osetacl 237 +#define __NR_HPUX_ofsetacl 238 +#define __NR_HPUX_pstat 239 +#define __NR_HPUX_getaudid 240 +#define __NR_HPUX_setaudid 241 +#define __NR_HPUX_getaudproc 242 +#define __NR_HPUX_setaudproc 243 +#define __NR_HPUX_getevent 244 +#define __NR_HPUX_setevent 245 +#define __NR_HPUX_audwrite 246 +#define __NR_HPUX_audswitch 247 +#define __NR_HPUX_audctl 248 +#define __NR_HPUX_ogetaccess 249 +#define __NR_HPUX_fsctl 250 +/* 251 - 258 missing */ +#define __NR_HPUX_swapfs 259 +#define __NR_HPUX_fss 260 +/* 261 - 266 missing */ +#define __NR_HPUX_tsync 267 +#define __NR_HPUX_getnumfds 268 +#define __NR_HPUX_poll 269 +#define __NR_HPUX_getmsg 270 +#define __NR_HPUX_putmsg 271 +#define __NR_HPUX_fchdir 272 +#define __NR_HPUX_getmount_cnt 273 +#define __NR_HPUX_getmount_entry 274 +#define __NR_HPUX_accept 275 +#define __NR_HPUX_bind 276 +#define __NR_HPUX_connect 277 +#define __NR_HPUX_getpeername 278 +#define __NR_HPUX_getsockname 279 +#define __NR_HPUX_getsockopt 280 +#define __NR_HPUX_listen 281 +#define __NR_HPUX_recv 282 +#define __NR_HPUX_recvfrom 283 +#define __NR_HPUX_recvmsg 284 +#define __NR_HPUX_send 285 +#define __NR_HPUX_sendmsg 286 +#define __NR_HPUX_sendto 287 +#define __NR_HPUX_setsockopt 288 +#define __NR_HPUX_shutdown 289 +#define __NR_HPUX_socket 290 +#define __NR_HPUX_socketpair 291 +#define __NR_HPUX_proc_open 292 +#define __NR_HPUX_proc_close 293 +#define __NR_HPUX_proc_send 294 +#define __NR_HPUX_proc_recv 295 +#define __NR_HPUX_proc_sendrecv 296 +#define __NR_HPUX_proc_syscall 297 +/* 298 - 311 missing */ +#define __NR_HPUX_semctl 312 +#define __NR_HPUX_msgctl 313 +#define __NR_HPUX_shmctl 314 +#define __NR_HPUX_mpctl 315 +#define __NR_HPUX_exportfs 316 +#define __NR_HPUX_getpmsg 317 +#define __NR_HPUX_putpmsg 318 +/* 319 missing */ +#define __NR_HPUX_msync 320 +#define __NR_HPUX_msleep 321 +#define __NR_HPUX_mwakeup 322 +#define __NR_HPUX_msem_init 323 +#define __NR_HPUX_msem_remove 324 +#define __NR_HPUX_adjtime 325 +#define __NR_HPUX_kload 326 +#define __NR_HPUX_fattach 327 +#define __NR_HPUX_fdetach 328 +#define __NR_HPUX_serialize 329 +#define __NR_HPUX_statvfs 330 +#define __NR_HPUX_fstatvfs 331 +#define __NR_HPUX_lchown 332 +#define __NR_HPUX_getsid 333 +#define __NR_HPUX_sysfs 334 +/* 335, 336 missing */ +#define __NR_HPUX_sched_setparam 337 +#define __NR_HPUX_sched_getparam 338 +#define __NR_HPUX_sched_setscheduler 339 +#define __NR_HPUX_sched_getscheduler 340 +#define __NR_HPUX_sched_yield 341 +#define __NR_HPUX_sched_get_priority_max 342 +#define __NR_HPUX_sched_get_priority_min 343 +#define __NR_HPUX_sched_rr_get_interval 344 +#define __NR_HPUX_clock_settime 345 +#define __NR_HPUX_clock_gettime 346 +#define __NR_HPUX_clock_getres 347 +#define __NR_HPUX_timer_create 348 +#define __NR_HPUX_timer_delete 349 +#define __NR_HPUX_timer_settime 350 +#define __NR_HPUX_timer_gettime 351 +#define __NR_HPUX_timer_getoverrun 352 +#define __NR_HPUX_nanosleep 353 +#define __NR_HPUX_toolbox 354 +/* 355 missing */ +#define __NR_HPUX_getdents 356 +#define __NR_HPUX_getcontext 357 +#define __NR_HPUX_sysinfo 358 +#define __NR_HPUX_fcntl64 359 +#define __NR_HPUX_ftruncate64 360 +#define __NR_HPUX_fstat64 361 +#define __NR_HPUX_getdirentries64 362 +#define __NR_HPUX_getrlimit64 363 +#define __NR_HPUX_lockf64 364 +#define __NR_HPUX_lseek64 365 +#define __NR_HPUX_lstat64 366 +#define __NR_HPUX_mmap64 367 +#define __NR_HPUX_setrlimit64 368 +#define __NR_HPUX_stat64 369 +#define __NR_HPUX_truncate64 370 +#define __NR_HPUX_ulimit64 371 +#define __NR_HPUX_pread 372 +#define __NR_HPUX_preadv 373 +#define __NR_HPUX_pwrite 374 +#define __NR_HPUX_pwritev 375 +#define __NR_HPUX_pread64 376 +#define __NR_HPUX_preadv64 377 +#define __NR_HPUX_pwrite64 378 +#define __NR_HPUX_pwritev64 379 +#define __NR_HPUX_setcontext 380 +#define __NR_HPUX_sigaltstack 381 +#define __NR_HPUX_waitid 382 +#define __NR_HPUX_setpgrp 383 +#define __NR_HPUX_recvmsg2 384 +#define __NR_HPUX_sendmsg2 385 +#define __NR_HPUX_socket2 386 +#define __NR_HPUX_socketpair2 387 +#define __NR_HPUX_setregid 388 +#define __NR_HPUX_lwp_create 389 +#define __NR_HPUX_lwp_terminate 390 +#define __NR_HPUX_lwp_wait 391 +#define __NR_HPUX_lwp_suspend 392 +#define __NR_HPUX_lwp_resume 393 +/* 394 missing */ +#define __NR_HPUX_lwp_abort_syscall 395 +#define __NR_HPUX_lwp_info 396 +#define __NR_HPUX_lwp_kill 397 +#define __NR_HPUX_ksleep 398 +#define __NR_HPUX_kwakeup 399 +/* 400 missing */ +#define __NR_HPUX_pstat_getlwp 401 +#define __NR_HPUX_lwp_exit 402 +#define __NR_HPUX_lwp_continue 403 +#define __NR_HPUX_getacl 404 +#define __NR_HPUX_fgetacl 405 +#define __NR_HPUX_setacl 406 +#define __NR_HPUX_fsetacl 407 +#define __NR_HPUX_getaccess 408 +#define __NR_HPUX_lwp_mutex_init 409 +#define __NR_HPUX_lwp_mutex_lock_sys 410 +#define __NR_HPUX_lwp_mutex_unlock 411 +#define __NR_HPUX_lwp_cond_init 412 +#define __NR_HPUX_lwp_cond_signal 413 +#define __NR_HPUX_lwp_cond_broadcast 414 +#define __NR_HPUX_lwp_cond_wait_sys 415 +#define __NR_HPUX_lwp_getscheduler 416 +#define __NR_HPUX_lwp_setscheduler 417 +#define __NR_HPUX_lwp_getstate 418 +#define __NR_HPUX_lwp_setstate 419 +#define __NR_HPUX_lwp_detach 420 +#define __NR_HPUX_mlock 421 +#define __NR_HPUX_munlock 422 +#define __NR_HPUX_mlockall 423 +#define __NR_HPUX_munlockall 424 +#define __NR_HPUX_shm_open 425 +#define __NR_HPUX_shm_unlink 426 +#define __NR_HPUX_sigqueue 427 +#define __NR_HPUX_sigwaitinfo 428 +#define __NR_HPUX_sigtimedwait 429 +#define __NR_HPUX_sigwait 430 +#define __NR_HPUX_aio_read 431 +#define __NR_HPUX_aio_write 432 +#define __NR_HPUX_lio_listio 433 +#define __NR_HPUX_aio_error 434 +#define __NR_HPUX_aio_return 435 +#define __NR_HPUX_aio_cancel 436 +#define __NR_HPUX_aio_suspend 437 +#define __NR_HPUX_aio_fsync 438 +#define __NR_HPUX_mq_open 439 +#define __NR_HPUX_mq_close 440 +#define __NR_HPUX_mq_unlink 441 +#define __NR_HPUX_mq_send 442 +#define __NR_HPUX_mq_receive 443 +#define __NR_HPUX_mq_notify 444 +#define __NR_HPUX_mq_setattr 445 +#define __NR_HPUX_mq_getattr 446 +#define __NR_HPUX_ksem_open 447 +#define __NR_HPUX_ksem_unlink 448 +#define __NR_HPUX_ksem_close 449 +#define __NR_HPUX_ksem_post 450 +#define __NR_HPUX_ksem_wait 451 +#define __NR_HPUX_ksem_read 452 +#define __NR_HPUX_ksem_trywait 453 +#define __NR_HPUX_lwp_rwlock_init 454 +#define __NR_HPUX_lwp_rwlock_destroy 455 +#define __NR_HPUX_lwp_rwlock_rdlock_sys 456 +#define __NR_HPUX_lwp_rwlock_wrlock_sys 457 +#define __NR_HPUX_lwp_rwlock_tryrdlock 458 +#define __NR_HPUX_lwp_rwlock_trywrlock 459 +#define __NR_HPUX_lwp_rwlock_unlock 460 +#define __NR_HPUX_ttrace 461 +#define __NR_HPUX_ttrace_wait 462 +#define __NR_HPUX_lf_wire_mem 463 +#define __NR_HPUX_lf_unwire_mem 464 +#define __NR_HPUX_lf_send_pin_map 465 +#define __NR_HPUX_lf_free_buf 466 +#define __NR_HPUX_lf_wait_nq 467 +#define __NR_HPUX_lf_wakeup_conn_q 468 +#define __NR_HPUX_lf_unused 469 +#define __NR_HPUX_lwp_sema_init 470 +#define __NR_HPUX_lwp_sema_post 471 +#define __NR_HPUX_lwp_sema_wait 472 +#define __NR_HPUX_lwp_sema_trywait 473 +#define __NR_HPUX_lwp_sema_destroy 474 +#define __NR_HPUX_statvfs64 475 +#define __NR_HPUX_fstatvfs64 476 +#define __NR_HPUX_msh_register 477 +#define __NR_HPUX_ptrace64 478 +#define __NR_HPUX_sendfile 479 +#define __NR_HPUX_sendpath 480 +#define __NR_HPUX_sendfile64 481 +#define __NR_HPUX_sendpath64 482 +#define __NR_HPUX_modload 483 +#define __NR_HPUX_moduload 484 +#define __NR_HPUX_modpath 485 +#define __NR_HPUX_getksym 486 +#define __NR_HPUX_modadm 487 +#define __NR_HPUX_modstat 488 +#define __NR_HPUX_lwp_detached_exit 489 +#define __NR_HPUX_crashconf 490 +#define __NR_HPUX_siginhibit 491 +#define __NR_HPUX_sigenable 492 +#define __NR_HPUX_spuctl 493 +#define __NR_HPUX_zerokernelsum 494 +#define __NR_HPUX_nfs_kstat 495 +#define __NR_HPUX_aio_read64 496 +#define __NR_HPUX_aio_write64 497 +#define __NR_HPUX_aio_error64 498 +#define __NR_HPUX_aio_return64 499 +#define __NR_HPUX_aio_cancel64 500 +#define __NR_HPUX_aio_suspend64 501 +#define __NR_HPUX_aio_fsync64 502 +#define __NR_HPUX_lio_listio64 503 +#define __NR_HPUX_recv2 504 +#define __NR_HPUX_recvfrom2 505 +#define __NR_HPUX_send2 506 +#define __NR_HPUX_sendto2 507 +#define __NR_HPUX_acl 508 +#define __NR_HPUX___cnx_p2p_ctl 509 +#define __NR_HPUX___cnx_gsched_ctl 510 +#define __NR_HPUX___cnx_pmon_ctl 511 + +#define __NR_HPUX_syscalls 512 + +/* + * Linux system call numbers. + * + * Cary Coutant says that we should just use another syscall gateway + * page to avoid clashing with the HPUX space, and I think he's right: + * it will would keep a branch out of our syscall entry path, at the + * very least. If we decide to change it later, we can ``just'' tweak + * the LINUX_GATEWAY_ADDR define at the bottom and make __NR_Linux be + * 1024 or something. Oh, and recompile libc. =) + * + * 64-bit HPUX binaries get the syscall gateway address passed in a register + * from the kernel at startup, which seems a sane strategy. + */ + +#define __NR_Linux 0 +#define __NR_restart_syscall (__NR_Linux + 0) +#define __NR_exit (__NR_Linux + 1) +#define __NR_fork (__NR_Linux + 2) +#define __NR_read (__NR_Linux + 3) +#define __NR_write (__NR_Linux + 4) +#define __NR_open (__NR_Linux + 5) +#define __NR_close (__NR_Linux + 6) +#define __NR_waitpid (__NR_Linux + 7) +#define __NR_creat (__NR_Linux + 8) +#define __NR_link (__NR_Linux + 9) +#define __NR_unlink (__NR_Linux + 10) +#define __NR_execve (__NR_Linux + 11) +#define __NR_chdir (__NR_Linux + 12) +#define __NR_time (__NR_Linux + 13) +#define __NR_mknod (__NR_Linux + 14) +#define __NR_chmod (__NR_Linux + 15) +#define __NR_lchown (__NR_Linux + 16) +#define __NR_socket (__NR_Linux + 17) +#define __NR_stat (__NR_Linux + 18) +#define __NR_lseek (__NR_Linux + 19) +#define __NR_getpid (__NR_Linux + 20) +#define __NR_mount (__NR_Linux + 21) +#define __NR_bind (__NR_Linux + 22) +#define __NR_setuid (__NR_Linux + 23) +#define __NR_getuid (__NR_Linux + 24) +#define __NR_stime (__NR_Linux + 25) +#define __NR_ptrace (__NR_Linux + 26) +#define __NR_alarm (__NR_Linux + 27) +#define __NR_fstat (__NR_Linux + 28) +#define __NR_pause (__NR_Linux + 29) +#define __NR_utime (__NR_Linux + 30) +#define __NR_connect (__NR_Linux + 31) +#define __NR_listen (__NR_Linux + 32) +#define __NR_access (__NR_Linux + 33) +#define __NR_nice (__NR_Linux + 34) +#define __NR_accept (__NR_Linux + 35) +#define __NR_sync (__NR_Linux + 36) +#define __NR_kill (__NR_Linux + 37) +#define __NR_rename (__NR_Linux + 38) +#define __NR_mkdir (__NR_Linux + 39) +#define __NR_rmdir (__NR_Linux + 40) +#define __NR_dup (__NR_Linux + 41) +#define __NR_pipe (__NR_Linux + 42) +#define __NR_times (__NR_Linux + 43) +#define __NR_getsockname (__NR_Linux + 44) +#define __NR_brk (__NR_Linux + 45) +#define __NR_setgid (__NR_Linux + 46) +#define __NR_getgid (__NR_Linux + 47) +#define __NR_signal (__NR_Linux + 48) +#define __NR_geteuid (__NR_Linux + 49) +#define __NR_getegid (__NR_Linux + 50) +#define __NR_acct (__NR_Linux + 51) +#define __NR_umount2 (__NR_Linux + 52) +#define __NR_getpeername (__NR_Linux + 53) +#define __NR_ioctl (__NR_Linux + 54) +#define __NR_fcntl (__NR_Linux + 55) +#define __NR_socketpair (__NR_Linux + 56) +#define __NR_setpgid (__NR_Linux + 57) +#define __NR_send (__NR_Linux + 58) +#define __NR_uname (__NR_Linux + 59) +#define __NR_umask (__NR_Linux + 60) +#define __NR_chroot (__NR_Linux + 61) +#define __NR_ustat (__NR_Linux + 62) +#define __NR_dup2 (__NR_Linux + 63) +#define __NR_getppid (__NR_Linux + 64) +#define __NR_getpgrp (__NR_Linux + 65) +#define __NR_setsid (__NR_Linux + 66) +#define __NR_pivot_root (__NR_Linux + 67) +#define __NR_sgetmask (__NR_Linux + 68) +#define __NR_ssetmask (__NR_Linux + 69) +#define __NR_setreuid (__NR_Linux + 70) +#define __NR_setregid (__NR_Linux + 71) +#define __NR_mincore (__NR_Linux + 72) +#define __NR_sigpending (__NR_Linux + 73) +#define __NR_sethostname (__NR_Linux + 74) +#define __NR_setrlimit (__NR_Linux + 75) +#define __NR_getrlimit (__NR_Linux + 76) +#define __NR_getrusage (__NR_Linux + 77) +#define __NR_gettimeofday (__NR_Linux + 78) +#define __NR_settimeofday (__NR_Linux + 79) +#define __NR_getgroups (__NR_Linux + 80) +#define __NR_setgroups (__NR_Linux + 81) +#define __NR_sendto (__NR_Linux + 82) +#define __NR_symlink (__NR_Linux + 83) +#define __NR_lstat (__NR_Linux + 84) +#define __NR_readlink (__NR_Linux + 85) +#define __NR_uselib (__NR_Linux + 86) +#define __NR_swapon (__NR_Linux + 87) +#define __NR_reboot (__NR_Linux + 88) +#define __NR_mmap2 (__NR_Linux + 89) +#define __NR_mmap (__NR_Linux + 90) +#define __NR_munmap (__NR_Linux + 91) +#define __NR_truncate (__NR_Linux + 92) +#define __NR_ftruncate (__NR_Linux + 93) +#define __NR_fchmod (__NR_Linux + 94) +#define __NR_fchown (__NR_Linux + 95) +#define __NR_getpriority (__NR_Linux + 96) +#define __NR_setpriority (__NR_Linux + 97) +#define __NR_recv (__NR_Linux + 98) +#define __NR_statfs (__NR_Linux + 99) +#define __NR_fstatfs (__NR_Linux + 100) +#define __NR_stat64 (__NR_Linux + 101) +/* #define __NR_socketcall (__NR_Linux + 102) */ +#define __NR_syslog (__NR_Linux + 103) +#define __NR_setitimer (__NR_Linux + 104) +#define __NR_getitimer (__NR_Linux + 105) +#define __NR_capget (__NR_Linux + 106) +#define __NR_capset (__NR_Linux + 107) +#define __NR_pread64 (__NR_Linux + 108) +#define __NR_pwrite64 (__NR_Linux + 109) +#define __NR_getcwd (__NR_Linux + 110) +#define __NR_vhangup (__NR_Linux + 111) +#define __NR_fstat64 (__NR_Linux + 112) +#define __NR_vfork (__NR_Linux + 113) +#define __NR_wait4 (__NR_Linux + 114) +#define __NR_swapoff (__NR_Linux + 115) +#define __NR_sysinfo (__NR_Linux + 116) +#define __NR_shutdown (__NR_Linux + 117) +#define __NR_fsync (__NR_Linux + 118) +#define __NR_madvise (__NR_Linux + 119) +#define __NR_clone (__NR_Linux + 120) +#define __NR_setdomainname (__NR_Linux + 121) +#define __NR_sendfile (__NR_Linux + 122) +#define __NR_recvfrom (__NR_Linux + 123) +#define __NR_adjtimex (__NR_Linux + 124) +#define __NR_mprotect (__NR_Linux + 125) +#define __NR_sigprocmask (__NR_Linux + 126) +#define __NR_create_module (__NR_Linux + 127) +#define __NR_init_module (__NR_Linux + 128) +#define __NR_delete_module (__NR_Linux + 129) +#define __NR_get_kernel_syms (__NR_Linux + 130) +#define __NR_quotactl (__NR_Linux + 131) +#define __NR_getpgid (__NR_Linux + 132) +#define __NR_fchdir (__NR_Linux + 133) +#define __NR_bdflush (__NR_Linux + 134) +#define __NR_sysfs (__NR_Linux + 135) +#define __NR_personality (__NR_Linux + 136) +#define __NR_afs_syscall (__NR_Linux + 137) /* Syscall for Andrew File System */ +#define __NR_setfsuid (__NR_Linux + 138) +#define __NR_setfsgid (__NR_Linux + 139) +#define __NR__llseek (__NR_Linux + 140) +#define __NR_getdents (__NR_Linux + 141) +#define __NR__newselect (__NR_Linux + 142) +#define __NR_flock (__NR_Linux + 143) +#define __NR_msync (__NR_Linux + 144) +#define __NR_readv (__NR_Linux + 145) +#define __NR_writev (__NR_Linux + 146) +#define __NR_getsid (__NR_Linux + 147) +#define __NR_fdatasync (__NR_Linux + 148) +#define __NR__sysctl (__NR_Linux + 149) +#define __NR_mlock (__NR_Linux + 150) +#define __NR_munlock (__NR_Linux + 151) +#define __NR_mlockall (__NR_Linux + 152) +#define __NR_munlockall (__NR_Linux + 153) +#define __NR_sched_setparam (__NR_Linux + 154) +#define __NR_sched_getparam (__NR_Linux + 155) +#define __NR_sched_setscheduler (__NR_Linux + 156) +#define __NR_sched_getscheduler (__NR_Linux + 157) +#define __NR_sched_yield (__NR_Linux + 158) +#define __NR_sched_get_priority_max (__NR_Linux + 159) +#define __NR_sched_get_priority_min (__NR_Linux + 160) +#define __NR_sched_rr_get_interval (__NR_Linux + 161) +#define __NR_nanosleep (__NR_Linux + 162) +#define __NR_mremap (__NR_Linux + 163) +#define __NR_setresuid (__NR_Linux + 164) +#define __NR_getresuid (__NR_Linux + 165) +#define __NR_sigaltstack (__NR_Linux + 166) +#define __NR_query_module (__NR_Linux + 167) +#define __NR_poll (__NR_Linux + 168) +#define __NR_nfsservctl (__NR_Linux + 169) +#define __NR_setresgid (__NR_Linux + 170) +#define __NR_getresgid (__NR_Linux + 171) +#define __NR_prctl (__NR_Linux + 172) +#define __NR_rt_sigreturn (__NR_Linux + 173) +#define __NR_rt_sigaction (__NR_Linux + 174) +#define __NR_rt_sigprocmask (__NR_Linux + 175) +#define __NR_rt_sigpending (__NR_Linux + 176) +#define __NR_rt_sigtimedwait (__NR_Linux + 177) +#define __NR_rt_sigqueueinfo (__NR_Linux + 178) +#define __NR_rt_sigsuspend (__NR_Linux + 179) +#define __NR_chown (__NR_Linux + 180) +#define __NR_setsockopt (__NR_Linux + 181) +#define __NR_getsockopt (__NR_Linux + 182) +#define __NR_sendmsg (__NR_Linux + 183) +#define __NR_recvmsg (__NR_Linux + 184) +#define __NR_semop (__NR_Linux + 185) +#define __NR_semget (__NR_Linux + 186) +#define __NR_semctl (__NR_Linux + 187) +#define __NR_msgsnd (__NR_Linux + 188) +#define __NR_msgrcv (__NR_Linux + 189) +#define __NR_msgget (__NR_Linux + 190) +#define __NR_msgctl (__NR_Linux + 191) +#define __NR_shmat (__NR_Linux + 192) +#define __NR_shmdt (__NR_Linux + 193) +#define __NR_shmget (__NR_Linux + 194) +#define __NR_shmctl (__NR_Linux + 195) + +#define __NR_getpmsg (__NR_Linux + 196) /* Somebody *wants* streams? */ +#define __NR_putpmsg (__NR_Linux + 197) + +#define __NR_lstat64 (__NR_Linux + 198) +#define __NR_truncate64 (__NR_Linux + 199) +#define __NR_ftruncate64 (__NR_Linux + 200) +#define __NR_getdents64 (__NR_Linux + 201) +#define __NR_fcntl64 (__NR_Linux + 202) +#define __NR_attrctl (__NR_Linux + 203) +#define __NR_acl_get (__NR_Linux + 204) +#define __NR_acl_set (__NR_Linux + 205) +#define __NR_gettid (__NR_Linux + 206) +#define __NR_readahead (__NR_Linux + 207) +#define __NR_tkill (__NR_Linux + 208) +#define __NR_sendfile64 (__NR_Linux + 209) +#define __NR_futex (__NR_Linux + 210) +#define __NR_sched_setaffinity (__NR_Linux + 211) +#define __NR_sched_getaffinity (__NR_Linux + 212) +#define __NR_set_thread_area (__NR_Linux + 213) +#define __NR_get_thread_area (__NR_Linux + 214) +#define __NR_io_setup (__NR_Linux + 215) +#define __NR_io_destroy (__NR_Linux + 216) +#define __NR_io_getevents (__NR_Linux + 217) +#define __NR_io_submit (__NR_Linux + 218) +#define __NR_io_cancel (__NR_Linux + 219) +#define __NR_alloc_hugepages (__NR_Linux + 220) +#define __NR_free_hugepages (__NR_Linux + 221) +#define __NR_exit_group (__NR_Linux + 222) +#define __NR_lookup_dcookie (__NR_Linux + 223) +#define __NR_epoll_create (__NR_Linux + 224) +#define __NR_epoll_ctl (__NR_Linux + 225) +#define __NR_epoll_wait (__NR_Linux + 226) +#define __NR_remap_file_pages (__NR_Linux + 227) +#define __NR_semtimedop (__NR_Linux + 228) +#define __NR_mq_open (__NR_Linux + 229) +#define __NR_mq_unlink (__NR_Linux + 230) +#define __NR_mq_timedsend (__NR_Linux + 231) +#define __NR_mq_timedreceive (__NR_Linux + 232) +#define __NR_mq_notify (__NR_Linux + 233) +#define __NR_mq_getsetattr (__NR_Linux + 234) +#define __NR_waitid (__NR_Linux + 235) +#define __NR_fadvise64_64 (__NR_Linux + 236) +#define __NR_set_tid_address (__NR_Linux + 237) +#define __NR_setxattr (__NR_Linux + 238) +#define __NR_lsetxattr (__NR_Linux + 239) +#define __NR_fsetxattr (__NR_Linux + 240) +#define __NR_getxattr (__NR_Linux + 241) +#define __NR_lgetxattr (__NR_Linux + 242) +#define __NR_fgetxattr (__NR_Linux + 243) +#define __NR_listxattr (__NR_Linux + 244) +#define __NR_llistxattr (__NR_Linux + 245) +#define __NR_flistxattr (__NR_Linux + 246) +#define __NR_removexattr (__NR_Linux + 247) +#define __NR_lremovexattr (__NR_Linux + 248) +#define __NR_fremovexattr (__NR_Linux + 249) +#define __NR_timer_create (__NR_Linux + 250) +#define __NR_timer_settime (__NR_Linux + 251) +#define __NR_timer_gettime (__NR_Linux + 252) +#define __NR_timer_getoverrun (__NR_Linux + 253) +#define __NR_timer_delete (__NR_Linux + 254) +#define __NR_clock_settime (__NR_Linux + 255) +#define __NR_clock_gettime (__NR_Linux + 256) +#define __NR_clock_getres (__NR_Linux + 257) +#define __NR_clock_nanosleep (__NR_Linux + 258) +#define __NR_tgkill (__NR_Linux + 259) +#define __NR_mbind (__NR_Linux + 260) +#define __NR_get_mempolicy (__NR_Linux + 261) +#define __NR_set_mempolicy (__NR_Linux + 262) +#define __NR_vserver (__NR_Linux + 263) +#define __NR_add_key (__NR_Linux + 264) +#define __NR_request_key (__NR_Linux + 265) +#define __NR_keyctl (__NR_Linux + 266) +#define __NR_ioprio_set (__NR_Linux + 267) +#define __NR_ioprio_get (__NR_Linux + 268) +#define __NR_inotify_init (__NR_Linux + 269) +#define __NR_inotify_add_watch (__NR_Linux + 270) +#define __NR_inotify_rm_watch (__NR_Linux + 271) +#define __NR_migrate_pages (__NR_Linux + 272) +#define __NR_pselect6 (__NR_Linux + 273) +#define __NR_ppoll (__NR_Linux + 274) +#define __NR_openat (__NR_Linux + 275) +#define __NR_mkdirat (__NR_Linux + 276) +#define __NR_mknodat (__NR_Linux + 277) +#define __NR_fchownat (__NR_Linux + 278) +#define __NR_futimesat (__NR_Linux + 279) +#define __NR_fstatat64 (__NR_Linux + 280) +#define __NR_unlinkat (__NR_Linux + 281) +#define __NR_renameat (__NR_Linux + 282) +#define __NR_linkat (__NR_Linux + 283) +#define __NR_symlinkat (__NR_Linux + 284) +#define __NR_readlinkat (__NR_Linux + 285) +#define __NR_fchmodat (__NR_Linux + 286) +#define __NR_faccessat (__NR_Linux + 287) +#define __NR_unshare (__NR_Linux + 288) +#define __NR_set_robust_list (__NR_Linux + 289) +#define __NR_get_robust_list (__NR_Linux + 290) +#define __NR_splice (__NR_Linux + 291) +#define __NR_sync_file_range (__NR_Linux + 292) +#define __NR_tee (__NR_Linux + 293) +#define __NR_vmsplice (__NR_Linux + 294) +#define __NR_move_pages (__NR_Linux + 295) +#define __NR_getcpu (__NR_Linux + 296) +#define __NR_epoll_pwait (__NR_Linux + 297) +#define __NR_statfs64 (__NR_Linux + 298) +#define __NR_fstatfs64 (__NR_Linux + 299) +#define __NR_kexec_load (__NR_Linux + 300) +#define __NR_utimensat (__NR_Linux + 301) +#define __NR_signalfd (__NR_Linux + 302) +#define __NR_timerfd (__NR_Linux + 303) +#define __NR_eventfd (__NR_Linux + 304) +#define __NR_fallocate (__NR_Linux + 305) +#define __NR_timerfd_create (__NR_Linux + 306) +#define __NR_timerfd_settime (__NR_Linux + 307) +#define __NR_timerfd_gettime (__NR_Linux + 308) +#define __NR_signalfd4 (__NR_Linux + 309) +#define __NR_eventfd2 (__NR_Linux + 310) +#define __NR_epoll_create1 (__NR_Linux + 311) +#define __NR_dup3 (__NR_Linux + 312) +#define __NR_pipe2 (__NR_Linux + 313) +#define __NR_inotify_init1 (__NR_Linux + 314) +#define __NR_preadv (__NR_Linux + 315) +#define __NR_pwritev (__NR_Linux + 316) +#define __NR_rt_tgsigqueueinfo (__NR_Linux + 317) +#define __NR_perf_event_open (__NR_Linux + 318) +#define __NR_recvmmsg (__NR_Linux + 319) +#define __NR_accept4 (__NR_Linux + 320) +#define __NR_prlimit64 (__NR_Linux + 321) +#define __NR_fanotify_init (__NR_Linux + 322) +#define __NR_fanotify_mark (__NR_Linux + 323) +#define __NR_clock_adjtime (__NR_Linux + 324) +#define __NR_name_to_handle_at (__NR_Linux + 325) +#define __NR_open_by_handle_at (__NR_Linux + 326) +#define __NR_syncfs (__NR_Linux + 327) +#define __NR_setns (__NR_Linux + 328) +#define __NR_sendmmsg (__NR_Linux + 329) + +#define __NR_Linux_syscalls (__NR_sendmmsg + 1) + + +#define __IGNORE_select /* newselect */ +#define __IGNORE_fadvise64 /* fadvise64_64 */ +#define __IGNORE_utimes /* utime */ + + +#define HPUX_GATEWAY_ADDR 0xC0000004 +#define LINUX_GATEWAY_ADDR 0x100 + +#endif /* _UAPI_ASM_PARISC_UNISTD_H_ */ diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 18670a07884..c9a9abd4bc5 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -708,59 +708,9 @@ ENTRY(end_fault_vector) .import do_cpu_irq_mask,code /* - * r26 = function to be called - * r25 = argument to pass in - * r24 = flags for do_fork() - * - * Kernel threads don't ever return, so they don't need - * a true register context. We just save away the arguments - * for copy_thread/ret_ to properly set up the child. - */ - -#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */ -#define CLONE_UNTRACED 0x00800000 - - .import do_fork -ENTRY(__kernel_thread) - STREG %r2, -RP_OFFSET(%r30) - - copy %r30, %r1 - ldo PT_SZ_ALGN(%r30),%r30 -#ifdef CONFIG_64BIT - /* Yo, function pointers in wide mode are little structs... -PB */ - ldd 24(%r26), %r2 - STREG %r2, PT_GR27(%r1) /* Store childs %dp */ - ldd 16(%r26), %r26 - - STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */ - copy %r0, %r22 /* user_tid */ -#endif - STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ - STREG %r25, PT_GR25(%r1) - ldil L%CLONE_UNTRACED, %r26 - ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */ - or %r26, %r24, %r26 /* will have kernel mappings. */ - ldi 1, %r25 /* stack_start, signals kernel thread */ - stw %r0, -52(%r30) /* user_tid */ -#ifdef CONFIG_64BIT - ldo -16(%r30),%r29 /* Reference param save area */ -#endif - BL do_fork, %r2 - copy %r1, %r24 /* pt_regs */ - - /* Parent Returns here */ - - LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2 - ldo -PT_SZ_ALGN(%r30), %r30 - bv %r0(%r2) - nop -ENDPROC(__kernel_thread) - - /* * Child Returns here * - * copy_thread moved args from temp save area set up above - * into task save area. + * copy_thread moved args into task save area. */ ENTRY(ret_from_kernel_thread) @@ -769,51 +719,17 @@ ENTRY(ret_from_kernel_thread) BL schedule_tail, %r2 nop - LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1 + LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 LDREG TASK_PT_GR25(%r1), %r26 #ifdef CONFIG_64BIT LDREG TASK_PT_GR27(%r1), %r27 - LDREG TASK_PT_GR22(%r1), %r22 #endif LDREG TASK_PT_GR26(%r1), %r1 ble 0(%sr7, %r1) copy %r31, %r2 - -#ifdef CONFIG_64BIT - ldo -16(%r30),%r29 /* Reference param save area */ - loadgp /* Thread could have been in a module */ -#endif -#ifndef CONFIG_64BIT - b sys_exit -#else - load32 sys_exit, %r1 - bv %r0(%r1) -#endif - ldi 0, %r26 -ENDPROC(ret_from_kernel_thread) - - .import sys_execve, code -ENTRY(__execve) - copy %r2, %r15 - copy %r30, %r16 - ldo PT_SZ_ALGN(%r30), %r30 - STREG %r26, PT_GR26(%r16) - STREG %r25, PT_GR25(%r16) - STREG %r24, PT_GR24(%r16) -#ifdef CONFIG_64BIT - ldo -16(%r30),%r29 /* Reference param save area */ -#endif - BL sys_execve, %r2 - copy %r16, %r26 - - cmpib,=,n 0,%r28,intr_return /* forward */ - - /* yes, this will trap and die. */ - copy %r15, %r2 - copy %r16, %r30 - bv %r0(%r2) + b finish_child_return nop -ENDPROC(__execve) +ENDPROC(ret_from_kernel_thread) /* @@ -1776,49 +1692,27 @@ ENTRY(sys_fork_wrapper) LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 ldo TASK_REGS(%r1),%r1 reg_save %r1 - mfctl %cr27, %r3 - STREG %r3, PT_CR27(%r1) - - STREG %r2,-RP_OFFSET(%r30) - ldo FRAME_SIZE(%r30),%r30 -#ifdef CONFIG_64BIT - ldo -16(%r30),%r29 /* Reference param save area */ -#endif - - /* These are call-clobbered registers and therefore - also syscall-clobbered (we hope). */ - STREG %r2,PT_GR19(%r1) /* save for child */ - STREG %r30,PT_GR21(%r1) + mfctl %cr27, %r28 + STREG %r28, PT_CR27(%r1) LDREG PT_GR30(%r1),%r25 copy %r1,%r24 - BL sys_clone,%r2 + b sys_clone ldi SIGCHLD,%r26 - - LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 -wrapper_exit: - ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */ - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 - ldo TASK_REGS(%r1),%r1 /* get pt regs */ - - LDREG PT_CR27(%r1), %r3 - mtctl %r3, %cr27 - reg_restore %r1 - - /* strace expects syscall # to be preserved in r20 */ - ldi __NR_fork,%r20 - bv %r0(%r2) - STREG %r20,PT_GR20(%r1) ENDPROC(sys_fork_wrapper) /* Set the return value for the child */ ENTRY(child_return) BL schedule_tail, %r2 nop +finish_child_return: + LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 + ldo TASK_REGS(%r1),%r1 /* get pt regs */ - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 - LDREG TASK_PT_GR19(%r1),%r2 - b wrapper_exit + LDREG PT_CR27(%r1), %r3 + mtctl %r3, %cr27 + reg_restore %r1 + b syscall_exit copy %r0,%r28 ENDPROC(child_return) @@ -1827,23 +1721,10 @@ ENTRY(sys_clone_wrapper) LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 ldo TASK_REGS(%r1),%r1 /* get pt regs */ reg_save %r1 - mfctl %cr27, %r3 - STREG %r3, PT_CR27(%r1) - - STREG %r2,-RP_OFFSET(%r30) - ldo FRAME_SIZE(%r30),%r30 -#ifdef CONFIG_64BIT - ldo -16(%r30),%r29 /* Reference param save area */ -#endif - - /* WARNING - Clobbers r19 and r21, userspace must save these! */ - STREG %r2,PT_GR19(%r1) /* save for child */ - STREG %r30,PT_GR21(%r1) - BL sys_clone,%r2 + mfctl %cr27, %r28 + STREG %r28, PT_CR27(%r1) + b sys_clone copy %r1,%r24 - - b wrapper_exit - LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 ENDPROC(sys_clone_wrapper) @@ -1851,72 +1732,14 @@ ENTRY(sys_vfork_wrapper) LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 ldo TASK_REGS(%r1),%r1 /* get pt regs */ reg_save %r1 - mfctl %cr27, %r3 - STREG %r3, PT_CR27(%r1) + mfctl %cr27, %r28 + STREG %r28, PT_CR27(%r1) - STREG %r2,-RP_OFFSET(%r30) - ldo FRAME_SIZE(%r30),%r30 -#ifdef CONFIG_64BIT - ldo -16(%r30),%r29 /* Reference param save area */ -#endif - - STREG %r2,PT_GR19(%r1) /* save for child */ - STREG %r30,PT_GR21(%r1) - - BL sys_vfork,%r2 + b sys_vfork copy %r1,%r26 - - b wrapper_exit - LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 ENDPROC(sys_vfork_wrapper) - .macro execve_wrapper execve - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 - ldo TASK_REGS(%r1),%r1 /* get pt regs */ - - /* - * Do we need to save/restore r3-r18 here? - * I don't think so. why would new thread need old - * threads registers? - */ - - /* %arg0 - %arg3 are already saved for us. */ - - STREG %r2,-RP_OFFSET(%r30) - ldo FRAME_SIZE(%r30),%r30 -#ifdef CONFIG_64BIT - ldo -16(%r30),%r29 /* Reference param save area */ -#endif - BL \execve,%r2 - copy %r1,%arg0 - - ldo -FRAME_SIZE(%r30),%r30 - LDREG -RP_OFFSET(%r30),%r2 - - /* If exec succeeded we need to load the args */ - - ldo -1024(%r0),%r1 - cmpb,>>= %r28,%r1,error_\execve - copy %r2,%r19 - -error_\execve: - bv %r0(%r19) - nop - .endm - - .import sys_execve -ENTRY(sys_execve_wrapper) - execve_wrapper sys_execve -ENDPROC(sys_execve_wrapper) - -#ifdef CONFIG_64BIT - .import sys32_execve -ENTRY(sys32_execve_wrapper) - execve_wrapper sys32_execve -ENDPROC(sys32_execve_wrapper) -#endif - ENTRY(sys_rt_sigreturn_wrapper) LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 ldo TASK_REGS(%r26),%r26 /* get pt regs */ diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index cbc37216bf9..38db36f6430 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -52,6 +52,7 @@ #include <asm/io.h> #include <asm/asm-offsets.h> +#include <asm/assembly.h> #include <asm/pdc.h> #include <asm/pdc_chassis.h> #include <asm/pgalloc.h> @@ -165,23 +166,6 @@ void (*pm_power_off)(void) = machine_power_off; EXPORT_SYMBOL(pm_power_off); /* - * Create a kernel thread - */ - -extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - - /* - * FIXME: Once we are sure we don't need any debug here, - * kernel_thread can become a #define. - */ - - return __kernel_thread(fn, arg, flags); -} -EXPORT_SYMBOL(kernel_thread); - -/* * Free current thread data structures etc.. */ void exit_thread(void) @@ -256,8 +240,8 @@ sys_vfork(struct pt_regs *regs) int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, /* in ia64 this is "user_stack_size" */ - struct task_struct * p, struct pt_regs * pregs) + unsigned long arg, + struct task_struct *p, struct pt_regs *pregs) { struct pt_regs * cregs = &(p->thread.regs); void *stack = task_stack_page(p); @@ -270,48 +254,32 @@ copy_thread(unsigned long clone_flags, unsigned long usp, #ifdef CONFIG_HPUX extern void * const hpux_child_return; #endif + if (unlikely(p->flags & PF_KTHREAD)) { + memset(cregs, 0, sizeof(struct pt_regs)); + if (!usp) /* idle thread */ + return 0; - *cregs = *pregs; - - /* Set the return value for the child. Note that this is not - actually restored by the syscall exit path, but we put it - here for consistency in case of signals. */ - cregs->gr[28] = 0; /* child */ - - /* - * We need to differentiate between a user fork and a - * kernel fork. We can't use user_mode, because the - * the syscall path doesn't save iaoq. Right now - * We rely on the fact that kernel_thread passes - * in zero for usp. - */ - if (usp == 1) { /* kernel thread */ - cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; /* Must exit via ret_from_kernel_thread in order * to call schedule_tail() */ + cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; cregs->kpc = (unsigned long) &ret_from_kernel_thread; /* * Copy function and argument to be called from * ret_from_kernel_thread. */ #ifdef CONFIG_64BIT - cregs->gr[27] = pregs->gr[27]; + cregs->gr[27] = ((unsigned long *)usp)[3]; + cregs->gr[26] = ((unsigned long *)usp)[2]; +#else + cregs->gr[26] = usp; #endif - cregs->gr[26] = pregs->gr[26]; - cregs->gr[25] = pregs->gr[25]; + cregs->gr[25] = arg; } else { /* user thread */ - /* - * Note that the fork wrappers are responsible - * for setting gr[21]. - */ - - /* Use same stack depth as parent */ - cregs->ksp = (unsigned long)stack - + (pregs->gr[21] & (THREAD_SIZE - 1)); cregs->gr[30] = usp; + cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; if (personality(p->personality) == PER_HPUX) { #ifdef CONFIG_HPUX cregs->kpc = (unsigned long) &hpux_child_return; @@ -323,8 +291,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, } /* Setup thread TLS area from the 4th parameter in clone */ if (clone_flags & CLONE_SETTLS) - cregs->cr27 = pregs->gr[23]; - + cregs->cr27 = pregs->gr[23]; } return 0; @@ -335,39 +302,6 @@ unsigned long thread_saved_pc(struct task_struct *t) return t->thread.regs.kpc; } -/* - * sys_execve() executes a new program. - */ - -asmlinkage int sys_execve(struct pt_regs *regs) -{ - int error; - struct filename *filename; - - filename = getname((const char __user *) regs->gr[26]); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename->name, - (const char __user *const __user *) regs->gr[25], - (const char __user *const __user *) regs->gr[24], - regs); - putname(filename); -out: - - return error; -} - -extern int __execve(const char *filename, - const char *const argv[], - const char *const envp[], struct task_struct *task); -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - return __execve(filename, argv, envp, current); -} - unsigned long get_wchan(struct task_struct *p) { diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index fd49aeda9eb..5dede04f2f3 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -65,7 +65,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) { compat_sigset_t s; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; sigset_64to32(&s, set); return copy_to_user(up, &s, sizeof s); @@ -77,7 +78,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) compat_sigset_t s; int r; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; if ((r = copy_from_user(&s, up, sz)) == 0) { sigset_32to64(set, &s); diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index 7426e40699b..f76c10863c6 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping, struct vm_area_struct *vma; int offset = mapping ? get_offset(mapping) : 0; + offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000; + addr = DCACHE_ALIGN(addr - offset) + offset; for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index bf5b93a885d..9cfdaa19ab6 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -53,28 +53,6 @@ #define DBG(x) #endif -/* - * sys32_execve() executes a new program. - */ - -asmlinkage int sys32_execve(struct pt_regs *regs) -{ - int error; - struct filename *filename; - - DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26])); - filename = getname((const char __user *) regs->gr[26]); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]), - compat_ptr(regs->gr[24]), regs); - putname(filename); -out: - - return error; -} - asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, int r22, int r21, int r20) { diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 3735abd7f8f..cb2da96d6ab 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -66,7 +66,7 @@ ENTRY_SAME(creat) ENTRY_SAME(link) ENTRY_SAME(unlink) /* 10 */ - ENTRY_DIFF(execve_wrapper) + ENTRY_COMP(execve) ENTRY_SAME(chdir) /* See comments in kernel/time.c!!! Maybe we don't need this? */ ENTRY_COMP(time) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a902a5c1c76..5af5aa70717 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -144,6 +144,7 @@ config PPC select GENERIC_KERNEL_THREAD select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_EXECVE config EARLY_PRINTK bool diff --git a/arch/powerpc/boot/dts/mpc5200b.dtsi b/arch/powerpc/boot/dts/mpc5200b.dtsi index 7ab286ab530..39ed65a44c5 100644 --- a/arch/powerpc/boot/dts/mpc5200b.dtsi +++ b/arch/powerpc/boot/dts/mpc5200b.dtsi @@ -231,6 +231,12 @@ interrupts = <2 7 0>; }; + sclpc@3c00 { + compatible = "fsl,mpc5200-lpbfifo"; + reg = <0x3c00 0x60>; + interrupts = <2 23 0>; + }; + i2c@3d00 { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/powerpc/boot/dts/o2d.dtsi b/arch/powerpc/boot/dts/o2d.dtsi index 3444eb8f0ad..24f66803929 100644 --- a/arch/powerpc/boot/dts/o2d.dtsi +++ b/arch/powerpc/boot/dts/o2d.dtsi @@ -86,12 +86,6 @@ reg = <0>; }; }; - - sclpc@3c00 { - compatible = "fsl,mpc5200-lpbfifo"; - reg = <0x3c00 0x60>; - interrupts = <3 23 0>; - }; }; localbus { diff --git a/arch/powerpc/boot/dts/pcm030.dts b/arch/powerpc/boot/dts/pcm030.dts index 9e354997eb7..96512c05803 100644 --- a/arch/powerpc/boot/dts/pcm030.dts +++ b/arch/powerpc/boot/dts/pcm030.dts @@ -59,7 +59,7 @@ #gpio-cells = <2>; }; - psc@2000 { /* PSC1 in ac97 mode */ + audioplatform: psc@2000 { /* PSC1 in ac97 mode */ compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97"; cell-index = <0>; }; @@ -134,4 +134,9 @@ localbus { status = "disabled"; }; + + sound { + compatible = "phytec,pcm030-audio-fabric"; + asoc-platform = <&audioplatform>; + }; }; diff --git a/arch/powerpc/include/asm/kvm_book3s_32.h b/arch/powerpc/include/asm/kvm_book3s_32.h index 38040ff8206..ce0ef6ce8f8 100644 --- a/arch/powerpc/include/asm/kvm_book3s_32.h +++ b/arch/powerpc/include/asm/kvm_book3s_32.h @@ -42,5 +42,6 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu) #define SID_SHIFT 28 #define ESID_MASK 0xf0000000 #define VSID_MASK 0x00fffffff0000000ULL +#define VPN_SHIFT 12 #endif /* __ASM_KVM_BOOK3S_32_H__ */ diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 8734b385527..87502046c0d 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h @@ -388,9 +388,9 @@ extern int powersave_nap; /* set if nap mode can be used in idle loop */ extern void power7_nap(void); #ifdef CONFIG_PSERIES_IDLE -extern void update_smt_snooze_delay(int snooze); +extern void update_smt_snooze_delay(int cpu, int residency); #else -static inline void update_smt_snooze_delay(int snooze) {} +static inline void update_smt_snooze_delay(int cpu, int residency) {} #endif extern void flush_instruction_cache(void); diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 921dce6d844..280068cfff2 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -56,7 +56,6 @@ #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif #define __ARCH_WANT_SYS_EXECVE -#define __ARCH_WANT_KERNEL_EXECVE /* * "Conditional" syscalls diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 9499385676e..d22e73e4618 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -444,11 +444,6 @@ ret_from_kernel_thread: PPC440EP_ERR42 blrl li r3,0 - b do_exit # no return - - .globl __ret_from_kernel_execve -__ret_from_kernel_execve: - addi r1,r3,-STACK_FRAME_OVERHEAD b ret_from_syscall /* Traced system call support */ diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 56e0ff0878b..e9a906c2723 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -373,17 +373,11 @@ _GLOBAL(ret_from_fork) _GLOBAL(ret_from_kernel_thread) bl .schedule_tail REST_NVGPRS(r1) - REST_GPR(2,r1) + ld r14, 0(r14) mtlr r14 mr r3,r15 blrl li r3,0 - b .do_exit # no return - -_GLOBAL(__ret_from_kernel_execve) - addi r1,r3,-STACK_FRAME_OVERHEAD - li r10,1 - std r10,SOFTE(r1) b syscall_exit .section ".toc","aw" diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index ba48233500f..f6d244db920 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -745,25 +745,24 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, /* Copy registers */ sp -= sizeof(struct pt_regs); childregs = (struct pt_regs *) sp; - if (!regs) { - /* for kernel thread, set `current' and stackptr in new task */ + if (unlikely(p->flags & PF_KTHREAD)) { + struct thread_info *ti = (void *)task_stack_page(p); memset(childregs, 0, sizeof(struct pt_regs)); childregs->gpr[1] = sp + sizeof(struct pt_regs); + childregs->gpr[14] = usp; /* function */ #ifdef CONFIG_PPC64 - childregs->gpr[14] = *(unsigned long *)usp; - childregs->gpr[2] = ((unsigned long *)usp)[1], clear_tsk_thread_flag(p, TIF_32BIT); -#else - childregs->gpr[14] = usp; /* function */ - childregs->gpr[2] = (unsigned long) p; + childregs->softe = 1; #endif childregs->gpr[15] = arg; p->thread.regs = NULL; /* no user register state */ + ti->flags |= _TIF_RESTOREALL; f = ret_from_kernel_thread; } else { CHECK_FULL_REGS(regs); *childregs = *regs; - childregs->gpr[1] = usp; + if (usp) + childregs->gpr[1] = usp; p->thread.regs = childregs; childregs->gpr[3] = 0; /* Result from fork() */ if (clone_flags & CLONE_SETTLS) { @@ -1027,22 +1026,11 @@ int get_unalign_ctl(struct task_struct *tsk, unsigned long adr) return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr); } -#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) - int sys_clone(unsigned long clone_flags, unsigned long usp, int __user *parent_tidp, void __user *child_threadptr, int __user *child_tidp, int p6, struct pt_regs *regs) { - CHECK_FULL_REGS(regs); - if (usp == 0) - usp = regs->gpr[1]; /* stack pointer for child */ -#ifdef CONFIG_PPC64 - if (is_32bit_task()) { - parent_tidp = TRUNC_PTR(parent_tidp); - child_tidp = TRUNC_PTR(child_tidp); - } -#endif return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); } @@ -1050,28 +1038,17 @@ int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - CHECK_FULL_REGS(regs); - return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); + return do_fork(SIGCHLD, 0, regs, 0, NULL, NULL); } int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - CHECK_FULL_REGS(regs); - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, regs, 0, NULL, NULL); } -void __ret_from_kernel_execve(struct pt_regs *normal) -__noreturn; - -void ret_from_kernel_execve(struct pt_regs *normal) -{ - set_thread_flag(TIF_RESTOREALL); - __ret_from_kernel_execve(normal); -} - static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, unsigned long nbytes) { diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 8302af64921..cf357a059dd 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -50,7 +50,7 @@ static ssize_t store_smt_snooze_delay(struct device *dev, return -EINVAL; per_cpu(smt_snooze_delay, cpu->dev.id) = snooze; - update_smt_snooze_delay(snooze); + update_smt_snooze_delay(cpu->dev.id, snooze); return count; } diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c index 00aa61268e0..b0f625a3334 100644 --- a/arch/powerpc/kvm/book3s_32_mmu_host.c +++ b/arch/powerpc/kvm/book3s_32_mmu_host.c @@ -173,8 +173,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) BUG_ON(!map); vsid = map->host_vsid; - vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) | ((eaddr & ~ESID_MASK) >> VPN_SHIFT) - + vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) | + ((eaddr & ~ESID_MASK) >> VPN_SHIFT); next_pteg: if (rr == 16) { primary = !primary; diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 0db88f501f9..aa2465e21f1 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -1463,7 +1463,7 @@ static void perf_event_interrupt(struct pt_regs *regs) if (!event->hw.idx || is_limited_pmc(event->hw.idx)) continue; val = read_pmc(event->hw.idx); - if (pmc_overflow(val)) { + if ((int)val < 0) { /* event has overflowed */ found = 1; record_and_restart(event, val, regs); diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index 8520b58a5e9..b89ef65392d 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c @@ -372,10 +372,11 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq, case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break; case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break; case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break; - default: - pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n", - __func__, virq, l1irq, l2irq); - return -EINVAL; + case MPC52xx_IRQ_L1_CRIT: + pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n", + __func__, l2irq); + irq_set_chip(virq, &no_irq_chip); + return 0; } irq_set_chip_and_handler(virq, irqchip, handle_level_irq); diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c b/arch/powerpc/platforms/pseries/eeh_pe.c index 797cd181dc3..d16c8ded108 100644 --- a/arch/powerpc/platforms/pseries/eeh_pe.c +++ b/arch/powerpc/platforms/pseries/eeh_pe.c @@ -449,7 +449,7 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe) if (list_empty(&pe->edevs)) { cnt = 0; list_for_each_entry(child, &pe->child_list, child) { - if (!(pe->type & EEH_PE_INVALID)) { + if (!(child->type & EEH_PE_INVALID)) { cnt++; break; } diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index d19f4977c83..e5b08472313 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c @@ -220,7 +220,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total) /* Get the top level device in the PE */ edev = of_node_to_eeh_dev(dn); - edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list); + if (edev->pe) + edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list); dn = eeh_dev_to_of_node(edev); if (!dn) return NULL; diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c index 455760b1fe6..45d00e5fe14 100644 --- a/arch/powerpc/platforms/pseries/processor_idle.c +++ b/arch/powerpc/platforms/pseries/processor_idle.c @@ -33,13 +33,6 @@ static int max_idle_state = MAX_IDLE_STATE_COUNT - 1; static struct cpuidle_device __percpu *pseries_cpuidle_devices; static struct cpuidle_state *cpuidle_state_table; -void update_smt_snooze_delay(int snooze) -{ - struct cpuidle_driver *drv = cpuidle_get_driver(); - if (drv) - drv->states[0].target_residency = snooze; -} - static inline void idle_loop_prolog(unsigned long *in_purr, ktime_t *kt_before) { @@ -66,32 +59,22 @@ static int snooze_loop(struct cpuidle_device *dev, { unsigned long in_purr; ktime_t kt_before; - unsigned long start_snooze; - long snooze = drv->states[0].target_residency; + int cpu = dev->cpu; idle_loop_prolog(&in_purr, &kt_before); + local_irq_enable(); + set_thread_flag(TIF_POLLING_NRFLAG); - if (snooze) { - start_snooze = get_tb() + snooze * tb_ticks_per_usec; - local_irq_enable(); - set_thread_flag(TIF_POLLING_NRFLAG); - - while ((snooze < 0) || (get_tb() < start_snooze)) { - if (need_resched() || cpu_is_offline(dev->cpu)) - goto out; - ppc64_runlatch_off(); - HMT_low(); - HMT_very_low(); - } - - HMT_medium(); - clear_thread_flag(TIF_POLLING_NRFLAG); - smp_mb(); - local_irq_disable(); + while ((!need_resched()) && cpu_online(cpu)) { + ppc64_runlatch_off(); + HMT_low(); + HMT_very_low(); } -out: HMT_medium(); + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb(); + dev->last_residency = (int)idle_loop_epilog(in_purr, kt_before); return index; @@ -172,8 +155,8 @@ static struct cpuidle_state dedicated_states[MAX_IDLE_STATE_COUNT] = { .name = "CEDE", .desc = "CEDE", .flags = CPUIDLE_FLAG_TIME_VALID, - .exit_latency = 1, - .target_residency = 10, + .exit_latency = 10, + .target_residency = 100, .enter = &dedicated_cede_loop }, }; @@ -190,6 +173,23 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = { .enter = &shared_cede_loop }, }; +void update_smt_snooze_delay(int cpu, int residency) +{ + struct cpuidle_driver *drv = cpuidle_get_driver(); + struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu); + + if (cpuidle_state_table != dedicated_states) + return; + + if (residency < 0) { + /* Disable the Nap state on that cpu */ + if (dev) + dev->states_usage[1].disable = 1; + } else + if (drv) + drv->states[1].target_residency = residency; +} + static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n, unsigned long action, void *hcpu) { @@ -246,10 +246,6 @@ static int pseries_cpuidle_driver_init(void) drv->states[drv->state_count] = /* structure copy */ cpuidle_state_table[idle_state]; - if (cpuidle_state_table == dedicated_states) - drv->states[drv->state_count].target_residency = - __get_cpu_var(smt_snooze_delay); - drv->state_count += 1; } diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 3f3d9ca7a5b..a163784e72c 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -96,6 +96,7 @@ config S390 select HAVE_MEMBLOCK_NODE_MAP select HAVE_CMPXCHG_LOCAL select HAVE_CMPXCHG_DOUBLE + select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_VIRT_CPU_ACCOUNTING select VIRT_CPU_ACCOUNTING select ARCH_DISCARD_MEMBLOCK @@ -130,12 +131,14 @@ config S390 select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE select HAVE_UID16 if 32BIT select ARCH_WANT_IPC_PARSE_VERSION + select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT select GENERIC_SMP_IDLE_THREAD select GENERIC_TIME_VSYSCALL_OLD select GENERIC_CLOCKEVENTS select KTIME_SCALAR if 32BIT select HAVE_ARCH_SECCOMP_FILTER select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA diff --git a/arch/s390/boot/compressed/vmlinux.lds.S b/arch/s390/boot/compressed/vmlinux.lds.S index d80f79d8dd9..8e1fb823928 100644 --- a/arch/s390/boot/compressed/vmlinux.lds.S +++ b/arch/s390/boot/compressed/vmlinux.lds.S @@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") OUTPUT_ARCH(s390:64-bit) #else OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") -OUTPUT_ARCH(s390) +OUTPUT_ARCH(s390:31-bit) #endif ENTRY(startup) diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h index 55bde603521..ad2b924167d 100644 --- a/arch/s390/include/asm/cio.h +++ b/arch/s390/include/asm/cio.h @@ -9,6 +9,8 @@ #define LPM_ANYPATH 0xff #define __MAX_CSSID 0 +#define __MAX_SUBCHANNEL 65535 +#define __MAX_SSID 3 #include <asm/scsw.h> diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index a34a9d612fc..18cd6b59265 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -20,7 +20,7 @@ #define PSW32_MASK_CC 0x00003000UL #define PSW32_MASK_PM 0x00000f00UL -#define PSW32_MASK_USER 0x00003F00UL +#define PSW32_MASK_USER 0x0000FF00UL #define PSW32_ADDR_AMODE 0x80000000UL #define PSW32_ADDR_INSN 0x7FFFFFFFUL diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h index 7941968e12b..5f0173a3169 100644 --- a/arch/s390/include/asm/perf_event.h +++ b/arch/s390/include/asm/perf_event.h @@ -9,7 +9,7 @@ #include <asm/cpu_mf.h> /* CPU-measurement counter facility */ -#define PERF_CPUM_CF_MAX_CTR 160 +#define PERF_CPUM_CF_MAX_CTR 256 /* Per-CPU flags for PMU states */ #define PMU_F_RESERVED 0x1000 diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index dd647c919a6..2d3b7cb2600 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud) static inline int pmd_present(pmd_t pmd) { - return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL; + unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO; + return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE || + !(pmd_val(pmd) & _SEGMENT_ENTRY_INV); } static inline int pmd_none(pmd_t pmd) { - return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL; + return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) && + !(pmd_val(pmd) & _SEGMENT_ENTRY_RO); } static inline int pmd_large(pmd_t pmd) @@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp) } #ifdef CONFIG_TRANSPARENT_HUGEPAGE + +#define SEGMENT_NONE __pgprot(_HPAGE_TYPE_NONE) +#define SEGMENT_RO __pgprot(_HPAGE_TYPE_RO) +#define SEGMENT_RW __pgprot(_HPAGE_TYPE_RW) + #define __HAVE_ARCH_PGTABLE_DEPOSIT extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable); @@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot) { - unsigned long pgprot_pmd = 0; - - if (pgprot_val(pgprot) & _PAGE_INVALID) { - if (pgprot_val(pgprot) & _PAGE_SWT) - pgprot_pmd |= _HPAGE_TYPE_NONE; - pgprot_pmd |= _SEGMENT_ENTRY_INV; - } - if (pgprot_val(pgprot) & _PAGE_RO) - pgprot_pmd |= _SEGMENT_ENTRY_RO; - return pgprot_pmd; + /* + * pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx) + * Convert to segment table entry format. + */ + if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE)) + return pgprot_val(SEGMENT_NONE); + if (pgprot_val(pgprot) == pgprot_val(PAGE_RO)) + return pgprot_val(SEGMENT_RO); + return pgprot_val(SEGMENT_RW); } static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) @@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd) static inline pmd_t pmd_mkwrite(pmd_t pmd) { - pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO; + /* Do not clobber _HPAGE_TYPE_NONE pages! */ + if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV)) + pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO; return pmd; } diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index 9ca30538376..9935cbd6a46 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h @@ -8,6 +8,9 @@ struct cpu; #ifdef CONFIG_SCHED_BOOK +extern unsigned char cpu_socket_id[NR_CPUS]; +#define topology_physical_package_id(cpu) (cpu_socket_id[cpu]) + extern unsigned char cpu_core_id[NR_CPUS]; extern cpumask_t cpu_core_map[NR_CPUS]; diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index bbbae41fa9a..ccbcab7742c 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -54,7 +54,6 @@ # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND # endif #define __ARCH_WANT_SYS_EXECVE -#define __ARCH_WANT_KERNEL_EXECVE /* * "Conditional" syscalls diff --git a/arch/s390/include/uapi/asm/chpid.h b/arch/s390/include/uapi/asm/chpid.h index 581992dfae2..6b4fb29cc19 100644 --- a/arch/s390/include/uapi/asm/chpid.h +++ b/arch/s390/include/uapi/asm/chpid.h @@ -1,5 +1,5 @@ /* - * Copyright IBM Corp. 2007 + * Copyright IBM Corp. 2007, 2012 * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> */ @@ -12,10 +12,10 @@ #define __MAX_CHPID 255 struct chp_id { - u8 reserved1; - u8 cssid; - u8 reserved2; - u8 id; + __u8 reserved1; + __u8 cssid; + __u8 reserved2; + __u8 id; } __attribute__((packed)); diff --git a/arch/s390/include/uapi/asm/kvm_para.h b/arch/s390/include/uapi/asm/kvm_para.h index e69de29bb2d..ff1f4e7b301 100644 --- a/arch/s390/include/uapi/asm/kvm_para.h +++ b/arch/s390/include/uapi/asm/kvm_para.h @@ -0,0 +1,11 @@ +/* + * User API definitions for paravirtual devices on s390 + * + * Copyright IBM Corp. 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> + */ diff --git a/arch/s390/include/uapi/asm/ptrace.h b/arch/s390/include/uapi/asm/ptrace.h index 705588a16d7..a5ca214b34f 100644 --- a/arch/s390/include/uapi/asm/ptrace.h +++ b/arch/s390/include/uapi/asm/ptrace.h @@ -239,7 +239,7 @@ typedef struct #define PSW_MASK_EA 0x00000000UL #define PSW_MASK_BA 0x00000000UL -#define PSW_MASK_USER 0x00003F00UL +#define PSW_MASK_USER 0x0000FF00UL #define PSW_ADDR_AMODE 0x80000000UL #define PSW_ADDR_INSN 0x7FFFFFFFUL @@ -269,7 +269,7 @@ typedef struct #define PSW_MASK_EA 0x0000000100000000UL #define PSW_MASK_BA 0x0000000080000000UL -#define PSW_MASK_USER 0x00003F8180000000UL +#define PSW_MASK_USER 0x0000FF8180000000UL #define PSW_ADDR_AMODE 0x0000000000000000UL #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c index 8df8d8a19c9..64b24650e4f 100644 --- a/arch/s390/kernel/cache.c +++ b/arch/s390/kernel/cache.c @@ -59,8 +59,8 @@ enum { enum { CACHE_TI_UNIFIED = 0, - CACHE_TI_INSTRUCTION = 0, - CACHE_TI_DATA, + CACHE_TI_DATA = 0, + CACHE_TI_INSTRUCTION, }; struct cache_info { @@ -121,7 +121,10 @@ static int __init cache_add(int level, int private, int type) cache = kzalloc(sizeof(*cache), GFP_KERNEL); if (!cache) return -ENOMEM; - ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED; + if (type == CACHE_TYPE_INSTRUCTION) + ti = CACHE_TI_INSTRUCTION; + else + ti = CACHE_TI_UNIFIED; cache->size = ecag(EXTRACT_SIZE, level, ti); cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti); cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti); diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index a1e8a8694bb..593fcc9253f 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -309,6 +309,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 | (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE); + /* Check for invalid user address space control. */ + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); for (i = 0; i < NUM_GPRS; i++) regs->gprs[i] = (__u64) regs32.gprs[i]; @@ -481,7 +485,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->gprs[15] = (__force __u64) frame; - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ + /* Force 31 bit amode and default user address space control. */ + regs->psw.mask = PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__force __u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); @@ -549,7 +556,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->gprs[15] = (__force __u64) frame; - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ + /* Force 31 bit amode and default user address space control. */ + regs->psw.mask = PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index ef46f66bc0d..aa8f2ba6289 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -330,40 +330,18 @@ ENTRY(ret_from_fork) la %r11,STACK_FRAME_OVERHEAD(%r15) l %r12,__LC_THREAD_INFO l %r13,__LC_SVC_NEW_PSW+4 - tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? - je 1f l %r1,BASED(.Lschedule_tail) basr %r14,%r1 # call schedule_tail TRACE_IRQS_ON ssm __LC_SVC_NEW_PSW # reenable interrupts - j sysc_tracenogo - -1: # it's a kernel thread - st %r15,__PT_R15(%r11) # store stack pointer for new kthread - l %r1,BASED(.Lschedule_tail) - basr %r14,%r1 # call schedule_tail - TRACE_IRQS_ON - ssm __LC_SVC_NEW_PSW # reenable interrupts - lm %r9,%r11,__PT_R9(%r11) # load gprs + tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? + jne sysc_tracenogo + # it's a kernel thread + lm %r9,%r10,__PT_R9(%r11) # load gprs ENTRY(kernel_thread_starter) la %r2,0(%r10) basr %r14,%r9 - la %r2,0 - br %r11 # do_exit - -# -# kernel_execve function needs to deal with pt_regs that is not -# at the usual place -# -ENTRY(ret_from_kernel_execve) - ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts - lr %r15,%r2 - lr %r11,%r2 - ahi %r15,-STACK_FRAME_OVERHEAD - xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) - l %r12,__LC_THREAD_INFO - ssm __LC_SVC_NEW_PSW # reenable interrupts - j sysc_return + j sysc_tracenogo /* * Program check handler routine diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 07d8de35398..499e95e90f3 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -352,33 +352,17 @@ sysc_tracenogo: ENTRY(ret_from_fork) la %r11,STACK_FRAME_OVERHEAD(%r15) lg %r12,__LC_THREAD_INFO - tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? - je 1f brasl %r14,schedule_tail TRACE_IRQS_ON ssm __LC_SVC_NEW_PSW # reenable interrupts - j sysc_tracenogo -1: # it's a kernel thread - stg %r15,__PT_R15(%r11) # store stack pointer for new kthread - brasl %r14,schedule_tail - TRACE_IRQS_ON - ssm __LC_SVC_NEW_PSW # reenable interrupts - lmg %r9,%r11,__PT_R9(%r11) # load gprs + tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? + jne sysc_tracenogo + # it's a kernel thread + lmg %r9,%r10,__PT_R9(%r11) # load gprs ENTRY(kernel_thread_starter) la %r2,0(%r10) basr %r14,%r9 - la %r2,0 - br %r11 # do_exit - -ENTRY(ret_from_kernel_execve) - ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts - lgr %r15,%r2 - lgr %r11,%r2 - aghi %r15,-STACK_FRAME_OVERHEAD - xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) - lg %r12,__LC_THREAD_INFO - ssm __LC_SVC_NEW_PSW # reenable interrupts - j sysc_return + j sysc_tracenogo /* * Program check handler routine diff --git a/arch/s390/kernel/head_kdump.S b/arch/s390/kernel/head_kdump.S index acaaaf4b705..085a95eb315 100644 --- a/arch/s390/kernel/head_kdump.S +++ b/arch/s390/kernel/head_kdump.S @@ -85,16 +85,10 @@ .align 2 startup_kdump_relocated: basr %r13,0 -0: - mvc 0(8,%r0),.Lrestart_psw-0b(%r13) # Setup restart PSW - sam31 # Switch to 31 bit addr mode - sr %r1,%r1 # Erase register r1 - sr %r2,%r2 # Erase register r2 - sigp %r1,%r2,SIGP_SET_ARCHITECTURE # Switch to 31 bit arch mode - lpsw 0 # Start new kernel... +0: lpswe .Lrestart_psw-0b(%r13) # Start new kernel... .align 8 .Lrestart_psw: - .long 0x00080000,0x80000000 + startup + .quad 0x0000000080000000,0x0000000000000000 + startup #else .align 2 .Lep_startup_kdump: diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index 9871b1971ed..c4e7269d4a0 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -94,7 +94,7 @@ static int get_counter_set(u64 event) set = CPUMF_CTR_SET_USER; else if (event < 128) set = CPUMF_CTR_SET_CRYPTO; - else if (event < 160) + else if (event < 256) set = CPUMF_CTR_SET_EXT; return set; @@ -138,6 +138,10 @@ static int validate_ctr_version(const struct hw_perf_event *hwc) case CPUMF_CTR_SET_EXT: if (cpuhw->info.csvn < 1) err = -EOPNOTSUPP; + if ((cpuhw->info.csvn == 1 && hwc->config > 159) || + (cpuhw->info.csvn == 2 && hwc->config > 175) || + (cpuhw->info.csvn > 2 && hwc->config > 255)) + err = -EOPNOTSUPP; break; } diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S index bf053898630..b6506ee32a3 100644 --- a/arch/s390/kernel/sclp.S +++ b/arch/s390/kernel/sclp.S @@ -44,6 +44,12 @@ _sclp_wait_int: #endif mvc .LoldpswS1-.LbaseS1(16,%r13),0(%r8) mvc 0(16,%r8),0(%r9) +#ifdef CONFIG_64BIT + epsw %r6,%r7 # set current addressing mode + nill %r6,0x1 # in new psw (31 or 64 bit mode) + nilh %r7,0x8000 + stm %r6,%r7,0(%r8) +#endif lhi %r6,0x0200 # cr mask for ext int (cr0.54) ltr %r2,%r2 jz .LsetctS1 @@ -87,7 +93,7 @@ _sclp_wait_int: .long 0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int #ifdef CONFIG_64BIT .LextpswS1_64: - .quad 0x0000000180000000, .LwaitS1 # PSW to handle ext int, 64 bit + .quad 0, .LwaitS1 # PSW to handle ext int, 64 bit #endif .LwaitpswS1: .long 0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index c13a2a37ef0..d1259d87507 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -136,6 +136,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (user_sregs.regs.psw.mask & PSW_MASK_USER); + /* Check for invalid user address space control. */ + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); /* Check for invalid amode */ if (regs->psw.mask & PSW_MASK_EA) regs->psw.mask |= PSW_MASK_BA; @@ -273,7 +277,10 @@ static int setup_frame(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ + /* Force default amode and default user address space control. */ + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); @@ -346,7 +353,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ + /* Force default amode and default user address space control. */ + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 54d93f4b681..dd55f7c2010 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -40,6 +40,7 @@ static DEFINE_SPINLOCK(topology_lock); static struct mask_info core_info; cpumask_t cpu_core_map[NR_CPUS]; unsigned char cpu_core_id[NR_CPUS]; +unsigned char cpu_socket_id[NR_CPUS]; static struct mask_info book_info; cpumask_t cpu_book_map[NR_CPUS]; @@ -83,11 +84,12 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu, cpumask_set_cpu(lcpu, &book->mask); cpu_book_id[lcpu] = book->id; cpumask_set_cpu(lcpu, &core->mask); + cpu_core_id[lcpu] = rcpu; if (one_core_per_cpu) { - cpu_core_id[lcpu] = rcpu; + cpu_socket_id[lcpu] = rcpu; core = core->next; } else { - cpu_core_id[lcpu] = core->id; + cpu_socket_id[lcpu] = core->id; } smp_cpu_set_polarization(lcpu, tl_cpu->pp); } diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index de8fa9bbd35..79cb51adc74 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -8,7 +8,7 @@ #ifndef CONFIG_64BIT OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") -OUTPUT_ARCH(s390) +OUTPUT_ARCH(s390:31-bit) ENTRY(startup) jiffies = jiffies_64 + 4; #else diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index 2d37bb861fa..9017a63dda3 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c @@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm, pmd = pmd_offset(pud, addr); if (pmd_none(*pmd)) return -0x10UL; - if (pmd_huge(*pmd)) { + if (pmd_large(*pmd)) { if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO)) return -0x04UL; return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK); diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 60acb93a468..1f5315d1215 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr, */ if (pmd_none(pmd) || pmd_trans_splitting(pmd)) return 0; - if (unlikely(pmd_huge(pmd))) { + if (unlikely(pmd_large(pmd))) { if (!gup_huge_pmd(pmdp, pmd, addr, next, write, pages, nr)) return 0; @@ -180,8 +180,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, addr = start; len = (unsigned long) nr_pages << PAGE_SHIFT; end = start + len; - if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ, - (void __user *)start, len))) + if ((end < start) || (end > TASK_SIZE)) return 0; local_irq_save(flags); @@ -229,7 +228,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, addr = start; len = (unsigned long) nr_pages << PAGE_SHIFT; end = start + len; - if (end < start) + if ((end < start) || (end > TASK_SIZE)) goto slow_irqon; /* diff --git a/arch/score/Kconfig b/arch/score/Kconfig index 4f93a431a45..a285e78fb9c 100644 --- a/arch/score/Kconfig +++ b/arch/score/Kconfig @@ -13,6 +13,8 @@ config SCORE select GENERIC_CLOCKEVENTS select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_REL + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE choice prompt "System type" diff --git a/arch/score/include/asm/processor.h b/arch/score/include/asm/processor.h index ab3aceb5420..d9a922d8711 100644 --- a/arch/score/include/asm/processor.h +++ b/arch/score/include/asm/processor.h @@ -13,7 +13,6 @@ struct task_struct; */ extern void (*cpu_wait)(void); -extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); extern unsigned long thread_saved_pc(struct task_struct *tsk); extern void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp); diff --git a/arch/score/include/asm/syscalls.h b/arch/score/include/asm/syscalls.h index 1dd5e0d6b0c..8d332534342 100644 --- a/arch/score/include/asm/syscalls.h +++ b/arch/score/include/asm/syscalls.h @@ -2,7 +2,6 @@ #define _ASM_SCORE_SYSCALLS_H asmlinkage long score_clone(struct pt_regs *regs); -asmlinkage long score_execve(struct pt_regs *regs); asmlinkage long score_sigaltstack(struct pt_regs *regs); asmlinkage long score_rt_sigreturn(struct pt_regs *regs); diff --git a/arch/score/include/asm/unistd.h b/arch/score/include/asm/unistd.h index a862384e9c1..b006ca43512 100644 --- a/arch/score/include/asm/unistd.h +++ b/arch/score/include/asm/unistd.h @@ -4,5 +4,6 @@ #define __ARCH_WANT_SYSCALL_NO_FLAGS #define __ARCH_WANT_SYSCALL_OFF_T #define __ARCH_WANT_SYSCALL_DEPRECATED +#define __ARCH_WANT_SYS_EXECVE #include <asm-generic/unistd.h> diff --git a/arch/score/kernel/entry.S b/arch/score/kernel/entry.S index 83bb96079c4..da9901088bb 100644 --- a/arch/score/kernel/entry.S +++ b/arch/score/kernel/entry.S @@ -278,6 +278,13 @@ need_resched: nop #endif +ENTRY(ret_from_kernel_thread) + bl schedule_tail # r4=struct task_struct *prev + nop + mv r4, r13 + brl r12 + j syscall_exit + ENTRY(ret_from_fork) bl schedule_tail # r4=struct task_struct *prev @@ -480,11 +487,6 @@ illegal_syscall: sw r9, [r0, PT_R7] j syscall_return -ENTRY(sys_execve) - mv r4, r0 - la r8, score_execve - br r8 - ENTRY(sys_clone) mv r4, r0 la r8, score_clone diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c index 637970cfd3f..6f311cf64b9 100644 --- a/arch/score/kernel/process.c +++ b/arch/score/kernel/process.c @@ -60,6 +60,7 @@ void __noreturn cpu_idle(void) } void ret_from_fork(void); +void ret_from_kernel_thread(void); void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { @@ -86,29 +87,27 @@ void flush_thread(void) {} * set up the kernel stack and exception frames for a new process */ int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs = task_pt_regs(p); - p->set_child_tid = NULL; - p->clear_child_tid = NULL; - - *childregs = *regs; - childregs->regs[7] = 0; /* Clear error flag */ - childregs->regs[4] = 0; /* Child gets zero as return value */ - regs->regs[4] = p->pid; - - if (childregs->cp0_psr & 0x8) { /* test kernel fork or user fork */ - childregs->regs[0] = usp; /* user fork */ + p->thread.reg0 = (unsigned long) childregs; + if (unlikely(!regs)) { + memset(childregs, 0, sizeof(struct pt_regs)); + p->thread->reg12 = usp; + p->thread->reg13 = arg; + p->thread.reg3 = (unsigned long) ret_from_kernel_thread; } else { - childregs->regs[28] = (unsigned long) ti; /* kernel fork */ - childregs->regs[0] = (unsigned long) childregs; + *childregs = *regs; + childregs->regs[7] = 0; /* Clear error flag */ + childregs->regs[4] = 0; /* Child gets zero as return value */ + childregs->regs[0] = usp; /* user fork */ + regs->regs[4] = p->pid; /* WTF? */ + p->thread.reg3 = (unsigned long) ret_from_fork; } - p->thread.reg0 = (unsigned long) childregs; - p->thread.reg3 = (unsigned long) ret_from_fork; p->thread.cp0_psr = 0; return 0; @@ -120,32 +119,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) return 1; } -static void __noreturn -kernel_thread_helper(void *unused0, int (*fn)(void *), - void *arg, void *unused1) -{ - do_exit(fn(arg)); -} - -/* - * Create a kernel thread. - */ -long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.regs[6] = (unsigned long) arg; - regs.regs[5] = (unsigned long) fn; - regs.cp0_epc = (unsigned long) kernel_thread_helper; - regs.cp0_psr = (regs.cp0_psr & ~(0x1|0x4|0x8)) | \ - ((regs.cp0_psr & 0x3) << 2); - - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, \ - 0, ®s, 0, NULL, NULL); -} - unsigned long thread_saved_pc(struct task_struct *tsk) { return task_pt_regs(tsk)->cp0_epc; diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c index c268bbf8b41..02353bde92d 100644 --- a/arch/score/kernel/signal.c +++ b/arch/score/kernel/signal.c @@ -148,7 +148,6 @@ score_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; sigset_t set; - stack_t st; int sig; /* Always make any pending restarted system calls return -EINTR */ @@ -168,12 +167,10 @@ score_rt_sigreturn(struct pt_regs *regs) else if (sig) force_sig(sig, current); - if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) - goto badframe; - /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack((stack_t __user *)&st, NULL, regs->regs[0]); + if (do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs->regs[0]) == -EFAULT) + goto badframe; regs->is_syscall = 0; __asm__ __volatile__( diff --git a/arch/score/kernel/sys_score.c b/arch/score/kernel/sys_score.c index d45cf00a335..c54434c2fd9 100644 --- a/arch/score/kernel/sys_score.c +++ b/arch/score/kernel/sys_score.c @@ -83,57 +83,3 @@ score_vfork(struct pt_regs *regs) return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[0], regs, 0, NULL, NULL); } - -/* - * sys_execve() executes a new program. - * This is called indirectly via a small wrapper - */ -asmlinkage long -score_execve(struct pt_regs *regs) -{ - int error; - struct filename *filename; - - filename = getname((char __user*)regs->regs[4]); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - return error; - - error = do_execve(filename->name, - (const char __user *const __user *)regs->regs[5], - (const char __user *const __user *)regs->regs[6], - regs); - - putname(filename); - return error; -} - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -asmlinkage -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - register unsigned long __r4 asm("r4") = (unsigned long) filename; - register unsigned long __r5 asm("r5") = (unsigned long) argv; - register unsigned long __r6 asm("r6") = (unsigned long) envp; - register unsigned long __r7 asm("r7"); - - __asm__ __volatile__ (" \n" - "ldi r27, %5 \n" - "syscall \n" - "mv %0, r4 \n" - "mv %1, r7 \n" - : "=&r" (__r4), "=r" (__r7) - : "r" (__r4), "r" (__r5), "r" (__r6), "i" (__NR_execve) - : "r8", "r9", "r10", "r11", "r22", "r23", "r24", "r25", - "r26", "r27", "memory"); - - if (__r7 == 0) - return __r4; - - return -__r4; -} diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index babc2b826c5..8451317eed5 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -40,6 +40,8 @@ config SUPERH select GENERIC_STRNLEN_USER select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE help The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index 86eadceff09..29f83beeef7 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild @@ -1,4 +1,3 @@ -include include/asm-generic/Kbuild.asm generic-y += bitsperlong.h generic-y += cputime.h @@ -34,13 +33,3 @@ generic-y += termbits.h generic-y += termios.h generic-y += ucontext.h generic-y += xor.h - -header-y += cachectl.h -header-y += cpu-features.h -header-y += hw_breakpoint.h -header-y += posix_types_32.h -header-y += posix_types_64.h -header-y += ptrace_32.h -header-y += ptrace_64.h -header-y += unistd_32.h -header-y += unistd_64.h diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h index 89890f61a7b..ec9ad593c3d 100644 --- a/arch/sh/include/asm/hw_breakpoint.h +++ b/arch/sh/include/asm/hw_breakpoint.h @@ -1,7 +1,8 @@ #ifndef __ASM_SH_HW_BREAKPOINT_H #define __ASM_SH_HW_BREAKPOINT_H -#ifdef __KERNEL__ +#include <uapi/asm/hw_breakpoint.h> + #define __ARCH_HW_BREAKPOINT_H #include <linux/kdebug.h> @@ -66,5 +67,4 @@ extern int register_sh_ubc(struct sh_ubc *); extern struct pmu perf_ops_bp; -#endif /* __KERNEL__ */ #endif /* __ASM_SH_HW_BREAKPOINT_H */ diff --git a/arch/sh/include/asm/posix_types.h b/arch/sh/include/asm/posix_types.h index f08449bcbde..1aa781079b1 100644 --- a/arch/sh/include/asm/posix_types.h +++ b/arch/sh/include/asm/posix_types.h @@ -1,13 +1,5 @@ -#ifdef __KERNEL__ # ifdef CONFIG_SUPERH32 # include <asm/posix_types_32.h> # else # include <asm/posix_types_64.h> # endif -#else -# ifdef __SH5__ -# include <asm/posix_types_64.h> -# else -# include <asm/posix_types_32.h> -# endif -#endif /* __KERNEL__ */ diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index b6311fd2d06..b1320d55ca3 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h @@ -126,11 +126,6 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned lo /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); -/* - * create a kernel thread without removing it from tasklists - */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - /* Copy and release all segment info associated with a VM */ #define copy_segments(p, mm) do { } while(0) #define release_segments(mm) do { } while(0) diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index cd6029fb2c0..1ee8946f095 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h @@ -159,11 +159,6 @@ struct mm_struct; /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); -/* - * create a kernel thread without removing it from tasklists - */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - /* Copy and release all segment info associated with a VM */ #define copy_segments(p, mm) do { } while (0) diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h index a4a38dff997..2506c7db76b 100644 --- a/arch/sh/include/asm/ptrace.h +++ b/arch/sh/include/asm/ptrace.h @@ -1,42 +1,16 @@ -#ifndef __ASM_SH_PTRACE_H -#define __ASM_SH_PTRACE_H - /* * Copyright (C) 1999, 2000 Niibe Yutaka */ +#ifndef __ASM_SH_PTRACE_H +#define __ASM_SH_PTRACE_H -#define PTRACE_GETREGS 12 /* General registers */ -#define PTRACE_SETREGS 13 - -#define PTRACE_GETFPREGS 14 /* FPU registers */ -#define PTRACE_SETFPREGS 15 - -#define PTRACE_GETFDPIC 31 /* get the ELF fdpic loadmap address */ - -#define PTRACE_GETFDPIC_EXEC 0 /* [addr] request the executable loadmap */ -#define PTRACE_GETFDPIC_INTERP 1 /* [addr] request the interpreter loadmap */ - -#define PTRACE_GETDSPREGS 55 /* DSP registers */ -#define PTRACE_SETDSPREGS 56 - -#define PT_TEXT_END_ADDR 240 -#define PT_TEXT_ADDR 244 /* &(struct user)->start_code */ -#define PT_DATA_ADDR 248 /* &(struct user)->start_data */ -#define PT_TEXT_LEN 252 - -#if defined(__SH5__) || defined(CONFIG_CPU_SH5) -#include <asm/ptrace_64.h> -#else -#include <asm/ptrace_32.h> -#endif - -#ifdef __KERNEL__ #include <linux/stringify.h> #include <linux/stddef.h> #include <linux/thread_info.h> #include <asm/addrspace.h> #include <asm/page.h> +#include <uapi/asm/ptrace.h> #define user_mode(regs) (((regs)->sr & 0x40000000)==0) #define kernel_stack_pointer(_regs) ((unsigned long)(_regs)->regs[15]) @@ -140,6 +114,4 @@ static inline unsigned long profile_pc(struct pt_regs *regs) #define profile_pc profile_pc #include <asm-generic/ptrace.h> -#endif /* __KERNEL__ */ - #endif /* __ASM_SH_PTRACE_H */ diff --git a/arch/sh/include/asm/ptrace_32.h b/arch/sh/include/asm/ptrace_32.h index 2d3e906aa72..1dd4480c536 100644 --- a/arch/sh/include/asm/ptrace_32.h +++ b/arch/sh/include/asm/ptrace_32.h @@ -1,79 +1,8 @@ #ifndef __ASM_SH_PTRACE_32_H #define __ASM_SH_PTRACE_32_H -/* - * GCC defines register number like this: - * ----------------------------- - * 0 - 15 are integer registers - * 17 - 22 are control/special registers - * 24 - 39 fp registers - * 40 - 47 xd registers - * 48 - fpscr register - * ----------------------------- - * - * We follows above, except: - * 16 --- program counter (PC) - * 22 --- syscall # - * 23 --- floating point communication register - */ -#define REG_REG0 0 -#define REG_REG15 15 +#include <uapi/asm/ptrace_32.h> -#define REG_PC 16 - -#define REG_PR 17 -#define REG_SR 18 -#define REG_GBR 19 -#define REG_MACH 20 -#define REG_MACL 21 - -#define REG_SYSCALL 22 - -#define REG_FPREG0 23 -#define REG_FPREG15 38 -#define REG_XFREG0 39 -#define REG_XFREG15 54 - -#define REG_FPSCR 55 -#define REG_FPUL 56 - -/* - * This struct defines the way the registers are stored on the - * kernel stack during a system call or other kernel entry. - */ -struct pt_regs { - unsigned long regs[16]; - unsigned long pc; - unsigned long pr; - unsigned long sr; - unsigned long gbr; - unsigned long mach; - unsigned long macl; - long tra; -}; - -/* - * This struct defines the way the DSP registers are stored on the - * kernel stack during a system call or other kernel entry. - */ -struct pt_dspregs { - unsigned long a1; - unsigned long a0g; - unsigned long a1g; - unsigned long m0; - unsigned long m1; - unsigned long a0; - unsigned long x0; - unsigned long x1; - unsigned long y0; - unsigned long y1; - unsigned long dsr; - unsigned long rs; - unsigned long re; - unsigned long mod; -}; - -#ifdef __KERNEL__ #define MAX_REG_OFFSET offsetof(struct pt_regs, tra) static inline long regs_return_value(struct pt_regs *regs) @@ -81,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs) return regs->regs[0]; } -#endif /* __KERNEL__ */ - #endif /* __ASM_SH_PTRACE_32_H */ diff --git a/arch/sh/include/asm/ptrace_64.h b/arch/sh/include/asm/ptrace_64.h index eb3fcceaf64..97f4b5660f2 100644 --- a/arch/sh/include/asm/ptrace_64.h +++ b/arch/sh/include/asm/ptrace_64.h @@ -1,16 +1,8 @@ #ifndef __ASM_SH_PTRACE_64_H #define __ASM_SH_PTRACE_64_H -struct pt_regs { - unsigned long long pc; - unsigned long long sr; - long long syscall_nr; - unsigned long long regs[63]; - unsigned long long tregs[8]; - unsigned long long pad[2]; -}; +#include <uapi/asm/ptrace_64.h> -#ifdef __KERNEL__ #define MAX_REG_OFFSET offsetof(struct pt_regs, tregs[7]) static inline long regs_return_value(struct pt_regs *regs) @@ -18,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs) return regs->regs[3]; } -#endif /* __KERNEL__ */ - #endif /* __ASM_SH_PTRACE_64_H */ diff --git a/arch/sh/include/asm/setup.h b/arch/sh/include/asm/setup.h index 465a22df8fd..99238108e7a 100644 --- a/arch/sh/include/asm/setup.h +++ b/arch/sh/include/asm/setup.h @@ -1,9 +1,8 @@ #ifndef _SH_SETUP_H #define _SH_SETUP_H -#include <asm-generic/setup.h> +#include <uapi/asm/setup.h> -#ifdef __KERNEL__ /* * This is set up by the setup-routine at boot-time */ @@ -22,6 +21,4 @@ void sh_mv_setup(void); void check_for_initrd(void); void per_cpu_trap_init(void); -#endif /* __KERNEL__ */ - #endif /* _SH_SETUP_H */ diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h index 6c1fa559753..d2f89f1741f 100644 --- a/arch/sh/include/asm/syscalls_32.h +++ b/arch/sh/include/asm/syscalls_32.h @@ -19,10 +19,6 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs __regs); -asmlinkage int sys_execve(const char __user *ufilename, - const char __user *const __user *uargv, - const char __user *const __user *uenvp, - unsigned long r7, struct pt_regs __regs); asmlinkage int sys_sigsuspend(old_sigset_t mask); asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact); diff --git a/arch/sh/include/asm/syscalls_64.h b/arch/sh/include/asm/syscalls_64.h index ee519f41d95..3fedd9f1fab 100644 --- a/arch/sh/include/asm/syscalls_64.h +++ b/arch/sh/include/asm/syscalls_64.h @@ -21,10 +21,6 @@ asmlinkage int sys_vfork(unsigned long r2, unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs *pregs); -asmlinkage int sys_execve(const char *ufilename, char **uargv, - char **uenvp, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs); /* Misc syscall related bits */ asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs); diff --git a/arch/sh/include/asm/types.h b/arch/sh/include/asm/types.h index f8421f7ad63..6a31053fa5e 100644 --- a/arch/sh/include/asm/types.h +++ b/arch/sh/include/asm/types.h @@ -1,12 +1,11 @@ #ifndef __ASM_SH_TYPES_H #define __ASM_SH_TYPES_H -#include <asm-generic/types.h> +#include <uapi/asm/types.h> /* * These aren't exported outside the kernel to avoid name space clashes */ -#ifdef __KERNEL__ #ifndef __ASSEMBLY__ #ifdef CONFIG_SUPERH32 @@ -18,6 +17,4 @@ typedef u64 reg_size_t; #endif #endif /* __ASSEMBLY__ */ -#endif /* __KERNEL__ */ - #endif /* __ASM_SH_TYPES_H */ diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h index 307201a854f..f1f4775766a 100644 --- a/arch/sh/include/asm/unistd.h +++ b/arch/sh/include/asm/unistd.h @@ -1,4 +1,3 @@ -#ifdef __KERNEL__ # ifdef CONFIG_SUPERH32 # include <asm/unistd_32.h> # else @@ -29,6 +28,7 @@ # define __ARCH_WANT_SYS_SIGPENDING # define __ARCH_WANT_SYS_SIGPROCMASK # define __ARCH_WANT_SYS_RT_SIGACTION +# define __ARCH_WANT_SYS_EXECVE /* * "Conditional" syscalls @@ -38,10 +38,4 @@ */ # define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") -#else -# ifdef __SH5__ -# include <asm/unistd_64.h> -# else -# include <asm/unistd_32.h> -# endif -#endif +#include <uapi/asm/unistd.h> diff --git a/arch/sh/include/uapi/asm/Kbuild b/arch/sh/include/uapi/asm/Kbuild index baebb3da1d4..60613ae7851 100644 --- a/arch/sh/include/uapi/asm/Kbuild +++ b/arch/sh/include/uapi/asm/Kbuild @@ -1,3 +1,25 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm +header-y += auxvec.h +header-y += byteorder.h +header-y += cachectl.h +header-y += cpu-features.h +header-y += hw_breakpoint.h +header-y += ioctls.h +header-y += posix_types.h +header-y += posix_types_32.h +header-y += posix_types_64.h +header-y += ptrace.h +header-y += ptrace_32.h +header-y += ptrace_64.h +header-y += setup.h +header-y += sigcontext.h +header-y += signal.h +header-y += sockios.h +header-y += stat.h +header-y += swab.h +header-y += types.h +header-y += unistd.h +header-y += unistd_32.h +header-y += unistd_64.h diff --git a/arch/sh/include/asm/auxvec.h b/arch/sh/include/uapi/asm/auxvec.h index 8bcc51af936..8bcc51af936 100644 --- a/arch/sh/include/asm/auxvec.h +++ b/arch/sh/include/uapi/asm/auxvec.h diff --git a/arch/sh/include/asm/byteorder.h b/arch/sh/include/uapi/asm/byteorder.h index db2f5d7cb17..db2f5d7cb17 100644 --- a/arch/sh/include/asm/byteorder.h +++ b/arch/sh/include/uapi/asm/byteorder.h diff --git a/arch/sh/include/asm/cachectl.h b/arch/sh/include/uapi/asm/cachectl.h index 6ffb4b7a212..6ffb4b7a212 100644 --- a/arch/sh/include/asm/cachectl.h +++ b/arch/sh/include/uapi/asm/cachectl.h diff --git a/arch/sh/include/asm/cpu-features.h b/arch/sh/include/uapi/asm/cpu-features.h index 694abe490ed..694abe490ed 100644 --- a/arch/sh/include/asm/cpu-features.h +++ b/arch/sh/include/uapi/asm/cpu-features.h diff --git a/arch/sh/include/uapi/asm/hw_breakpoint.h b/arch/sh/include/uapi/asm/hw_breakpoint.h new file mode 100644 index 00000000000..ae5704fa77a --- /dev/null +++ b/arch/sh/include/uapi/asm/hw_breakpoint.h @@ -0,0 +1,4 @@ +/* + * There isn't anything here anymore, but the file must not be empty or patch + * will delete it. + */ diff --git a/arch/sh/include/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h index a6769f352bf..a6769f352bf 100644 --- a/arch/sh/include/asm/ioctls.h +++ b/arch/sh/include/uapi/asm/ioctls.h diff --git a/arch/sh/include/uapi/asm/posix_types.h b/arch/sh/include/uapi/asm/posix_types.h new file mode 100644 index 00000000000..dc55e5adfe1 --- /dev/null +++ b/arch/sh/include/uapi/asm/posix_types.h @@ -0,0 +1,7 @@ +#ifndef __KERNEL__ +# ifdef __SH5__ +# include <asm/posix_types_64.h> +# else +# include <asm/posix_types_32.h> +# endif +#endif /* __KERNEL__ */ diff --git a/arch/sh/include/asm/posix_types_32.h b/arch/sh/include/uapi/asm/posix_types_32.h index ba0bdc423b0..ba0bdc423b0 100644 --- a/arch/sh/include/asm/posix_types_32.h +++ b/arch/sh/include/uapi/asm/posix_types_32.h diff --git a/arch/sh/include/asm/posix_types_64.h b/arch/sh/include/uapi/asm/posix_types_64.h index 244f7e950e1..244f7e950e1 100644 --- a/arch/sh/include/asm/posix_types_64.h +++ b/arch/sh/include/uapi/asm/posix_types_64.h diff --git a/arch/sh/include/uapi/asm/ptrace.h b/arch/sh/include/uapi/asm/ptrace.h new file mode 100644 index 00000000000..8b8c5aca9c2 --- /dev/null +++ b/arch/sh/include/uapi/asm/ptrace.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 1999, 2000 Niibe Yutaka + */ +#ifndef _UAPI__ASM_SH_PTRACE_H +#define _UAPI__ASM_SH_PTRACE_H + + +#define PTRACE_GETREGS 12 /* General registers */ +#define PTRACE_SETREGS 13 + +#define PTRACE_GETFPREGS 14 /* FPU registers */ +#define PTRACE_SETFPREGS 15 + +#define PTRACE_GETFDPIC 31 /* get the ELF fdpic loadmap address */ + +#define PTRACE_GETFDPIC_EXEC 0 /* [addr] request the executable loadmap */ +#define PTRACE_GETFDPIC_INTERP 1 /* [addr] request the interpreter loadmap */ + +#define PTRACE_GETDSPREGS 55 /* DSP registers */ +#define PTRACE_SETDSPREGS 56 + +#define PT_TEXT_END_ADDR 240 +#define PT_TEXT_ADDR 244 /* &(struct user)->start_code */ +#define PT_DATA_ADDR 248 /* &(struct user)->start_data */ +#define PT_TEXT_LEN 252 + +#if defined(__SH5__) || defined(CONFIG_CPU_SH5) +#include <asm/ptrace_64.h> +#else +#include <asm/ptrace_32.h> +#endif + + +#endif /* _UAPI__ASM_SH_PTRACE_H */ diff --git a/arch/sh/include/uapi/asm/ptrace_32.h b/arch/sh/include/uapi/asm/ptrace_32.h new file mode 100644 index 00000000000..926e0cefc2b --- /dev/null +++ b/arch/sh/include/uapi/asm/ptrace_32.h @@ -0,0 +1,77 @@ +#ifndef _UAPI__ASM_SH_PTRACE_32_H +#define _UAPI__ASM_SH_PTRACE_32_H + +/* + * GCC defines register number like this: + * ----------------------------- + * 0 - 15 are integer registers + * 17 - 22 are control/special registers + * 24 - 39 fp registers + * 40 - 47 xd registers + * 48 - fpscr register + * ----------------------------- + * + * We follows above, except: + * 16 --- program counter (PC) + * 22 --- syscall # + * 23 --- floating point communication register + */ +#define REG_REG0 0 +#define REG_REG15 15 + +#define REG_PC 16 + +#define REG_PR 17 +#define REG_SR 18 +#define REG_GBR 19 +#define REG_MACH 20 +#define REG_MACL 21 + +#define REG_SYSCALL 22 + +#define REG_FPREG0 23 +#define REG_FPREG15 38 +#define REG_XFREG0 39 +#define REG_XFREG15 54 + +#define REG_FPSCR 55 +#define REG_FPUL 56 + +/* + * This struct defines the way the registers are stored on the + * kernel stack during a system call or other kernel entry. + */ +struct pt_regs { + unsigned long regs[16]; + unsigned long pc; + unsigned long pr; + unsigned long sr; + unsigned long gbr; + unsigned long mach; + unsigned long macl; + long tra; +}; + +/* + * This struct defines the way the DSP registers are stored on the + * kernel stack during a system call or other kernel entry. + */ +struct pt_dspregs { + unsigned long a1; + unsigned long a0g; + unsigned long a1g; + unsigned long m0; + unsigned long m1; + unsigned long a0; + unsigned long x0; + unsigned long x1; + unsigned long y0; + unsigned long y1; + unsigned long dsr; + unsigned long rs; + unsigned long re; + unsigned long mod; +}; + + +#endif /* _UAPI__ASM_SH_PTRACE_32_H */ diff --git a/arch/sh/include/uapi/asm/ptrace_64.h b/arch/sh/include/uapi/asm/ptrace_64.h new file mode 100644 index 00000000000..0e52ee83e94 --- /dev/null +++ b/arch/sh/include/uapi/asm/ptrace_64.h @@ -0,0 +1,14 @@ +#ifndef _UAPI__ASM_SH_PTRACE_64_H +#define _UAPI__ASM_SH_PTRACE_64_H + +struct pt_regs { + unsigned long long pc; + unsigned long long sr; + long long syscall_nr; + unsigned long long regs[63]; + unsigned long long tregs[8]; + unsigned long long pad[2]; +}; + + +#endif /* _UAPI__ASM_SH_PTRACE_64_H */ diff --git a/arch/sh/include/uapi/asm/setup.h b/arch/sh/include/uapi/asm/setup.h new file mode 100644 index 00000000000..552df83f1a4 --- /dev/null +++ b/arch/sh/include/uapi/asm/setup.h @@ -0,0 +1 @@ +#include <asm-generic/setup.h> diff --git a/arch/sh/include/asm/sigcontext.h b/arch/sh/include/uapi/asm/sigcontext.h index 8ce1435bc0b..8ce1435bc0b 100644 --- a/arch/sh/include/asm/sigcontext.h +++ b/arch/sh/include/uapi/asm/sigcontext.h diff --git a/arch/sh/include/asm/signal.h b/arch/sh/include/uapi/asm/signal.h index 9ac530a90bc..9ac530a90bc 100644 --- a/arch/sh/include/asm/signal.h +++ b/arch/sh/include/uapi/asm/signal.h diff --git a/arch/sh/include/asm/sockios.h b/arch/sh/include/uapi/asm/sockios.h index cf8b96b1f9a..cf8b96b1f9a 100644 --- a/arch/sh/include/asm/sockios.h +++ b/arch/sh/include/uapi/asm/sockios.h diff --git a/arch/sh/include/asm/stat.h b/arch/sh/include/uapi/asm/stat.h index e1810cc6e3d..e1810cc6e3d 100644 --- a/arch/sh/include/asm/stat.h +++ b/arch/sh/include/uapi/asm/stat.h diff --git a/arch/sh/include/asm/swab.h b/arch/sh/include/uapi/asm/swab.h index 1cd09767a7a..1cd09767a7a 100644 --- a/arch/sh/include/asm/swab.h +++ b/arch/sh/include/uapi/asm/swab.h diff --git a/arch/sh/include/uapi/asm/types.h b/arch/sh/include/uapi/asm/types.h new file mode 100644 index 00000000000..b9e79bc580d --- /dev/null +++ b/arch/sh/include/uapi/asm/types.h @@ -0,0 +1 @@ +#include <asm-generic/types.h> diff --git a/arch/sh/include/uapi/asm/unistd.h b/arch/sh/include/uapi/asm/unistd.h new file mode 100644 index 00000000000..eeef88dd53c --- /dev/null +++ b/arch/sh/include/uapi/asm/unistd.h @@ -0,0 +1,7 @@ +#ifndef __KERNEL__ +# ifdef __SH5__ +# include <asm/unistd_64.h> +# else +# include <asm/unistd_32.h> +# endif +#endif diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/uapi/asm/unistd_32.h index 72fd1e06100..9e465f246dc 100644 --- a/arch/sh/include/asm/unistd_32.h +++ b/arch/sh/include/uapi/asm/unistd_32.h @@ -378,7 +378,8 @@ #define __NR_setns 364 #define __NR_process_vm_readv 365 #define __NR_process_vm_writev 366 +#define __NR_kcmp 367 -#define NR_syscalls 367 +#define NR_syscalls 368 #endif /* __ASM_SH_UNISTD_32_H */ diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h index a28edc32969..8e3a2edd284 100644 --- a/arch/sh/include/asm/unistd_64.h +++ b/arch/sh/include/uapi/asm/unistd_64.h @@ -398,7 +398,8 @@ #define __NR_setns 375 #define __NR_process_vm_readv 376 #define __NR_process_vm_writev 377 +#define __NR_kcmp 378 -#define NR_syscalls 378 +#define NR_syscalls 379 #endif /* __ASM_SH_UNISTD_64_H */ diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 88571ff8eee..f259b37874e 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -16,7 +16,7 @@ obj-y := debugtraps.o dma-nommu.o dumpstack.o \ machvec.o nmi_debug.o process.o \ process_$(BITS).o ptrace.o ptrace_$(BITS).o \ reboot.o return_address.o \ - setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ + setup.o signal_$(BITS).o sys_sh.o \ syscalls_$(BITS).o time.o topology.o traps.o \ traps_$(BITS).o unwinder.o @@ -25,6 +25,7 @@ obj-y += iomap.o obj-$(CONFIG_HAS_IOPORT) += ioport.o endif +obj-$(CONFIG_SUPERH32) += sys_sh32.o obj-y += cpu/ obj-$(CONFIG_VSYSCALL) += vsyscall/ obj-$(CONFIG_SMP) += smp.o diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index 7e605b95592..0c8d0377d40 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -1228,6 +1228,25 @@ ret_from_fork: pta ret_from_syscall, tr0 blink tr0, ZERO +.global ret_from_kernel_thread +ret_from_kernel_thread: + + movi schedule_tail,r5 + ori r5, 1, r5 + ptabs r5, tr0 + blink tr0, LINK + + ld.q SP, FRAME_R(2), r2 + ld.q SP, FRAME_R(3), r3 + ptabs r3, tr0 + blink tr0, LINK + + ld.q SP, FRAME_S(FSPC), r2 + addi r2, 4, r2 /* Move PC, being pre-execution event */ + st.q SP, FRAME_S(FSPC), r2 + pta ret_from_syscall, tr0 + blink tr0, ZERO + syscall_allowed: /* Use LINK to deflect the exit point, default is syscall_ret */ pta syscall_ret, tr0 diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index b96489d8b27..9b6e4beeb29 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -297,6 +297,19 @@ ret_from_fork: mov r0, r4 bra syscall_exit nop + + .align 2 + .globl ret_from_kernel_thread +ret_from_kernel_thread: + mov.l 1f, r8 + jsr @r8 + mov r0, r4 + mov.l @(OFF_R5,r15), r5 ! fn + jsr @r5 + mov.l @(OFF_R4,r15), r4 ! arg + bra syscall_exit + nop + .align 2 1: .long schedule_tail diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index ba7345f37bc..fce8029de92 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -68,38 +68,6 @@ void show_regs(struct pt_regs * regs) show_code(regs); } -/* - * Create a kernel thread - */ -__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *)) -{ - do_exit(fn(arg)); -} - -/* Don't use this in BL=1(cli). Or else, CPU resets! */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - struct pt_regs regs; - int pid; - - memset(®s, 0, sizeof(regs)); - regs.regs[4] = (unsigned long)arg; - regs.regs[5] = (unsigned long)fn; - - regs.pc = (unsigned long)kernel_thread_helper; - regs.sr = SR_MD; -#if defined(CONFIG_SH_FPU) - regs.sr |= SR_FD; -#endif - - /* Ok, create the new process.. */ - pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, - ®s, 0, NULL, NULL); - - return pid; -} -EXPORT_SYMBOL(kernel_thread); - void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned long new_sp) { @@ -157,9 +125,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) EXPORT_SYMBOL(dump_fpu); asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct thread_info *ti = task_thread_info(p); @@ -177,29 +146,34 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, } #endif - childregs = task_pt_regs(p); - *childregs = *regs; + memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); - if (user_mode(regs)) { - childregs->regs[15] = usp; - ti->addr_limit = USER_DS; - } else { - childregs->regs[15] = (unsigned long)childregs; + childregs = task_pt_regs(p); + p->thread.sp = (unsigned long) childregs; + if (unlikely(p->flags & PF_KTHREAD)) { + memset(childregs, 0, sizeof(struct pt_regs)); + p->thread.pc = (unsigned long) ret_from_kernel_thread; + childregs->regs[4] = arg; + childregs->regs[5] = usp; + childregs->sr = SR_MD; +#if defined(CONFIG_SH_FPU) + childregs->sr |= SR_FD; +#endif ti->addr_limit = KERNEL_DS; ti->status &= ~TS_USEDFPU; p->fpu_counter = 0; + return 0; } + *childregs = *regs; + + childregs->regs[15] = usp; + ti->addr_limit = USER_DS; if (clone_flags & CLONE_SETTLS) childregs->gbr = childregs->regs[0]; childregs->regs[0] = 0; /* Set return value for child */ - - p->thread.sp = (unsigned long) childregs; p->thread.pc = (unsigned long) ret_from_fork; - - memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); - return 0; } @@ -288,29 +262,6 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, 0, NULL, NULL); } -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(const char __user *ufilename, - const char __user *const __user *uargv, - const char __user *const __user *uenvp, - unsigned long r7, struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - int error; - struct filename *filename; - - filename = getname(ufilename); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename->name, uargv, uenvp, regs); - putname(filename); -out: - return error; -} - unsigned long get_wchan(struct task_struct *p) { unsigned long pc; diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 98a709f0c3c..3a0f3fd3bb5 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -285,39 +285,6 @@ void show_regs(struct pt_regs *regs) } /* - * Create a kernel thread - */ -__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *)) -{ - do_exit(fn(arg)); -} - -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be freed until both the parent and the child have exited. - */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - regs.regs[2] = (unsigned long)arg; - regs.regs[3] = (unsigned long)fn; - - regs.pc = (unsigned long)kernel_thread_helper; - regs.sr = (1 << 30); - - /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, - ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - -/* * Free current thread data structures etc.. */ void exit_thread(void) @@ -401,15 +368,17 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) EXPORT_SYMBOL(dump_fpu); asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; #ifdef CONFIG_SH_FPU - if(last_task_used_math == current) { + /* can't happen for a kernel thread */ + if (last_task_used_math == current) { enable_fpu(); save_fpu(current); disable_fpu(); @@ -419,7 +388,17 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, #endif /* Copy from sh version */ childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; + p->thread.sp = (unsigned long) childregs; + if (unlikely(p->flags & PF_KTHREAD)) { + memset(childregs, 0, sizeof(struct pt_regs)); + childregs->regs[2] = (unsigned long)arg; + childregs->regs[3] = (unsigned long)fn; + childregs->sr = (1 << 30); /* not user_mode */ + childregs->sr |= SR_FD; /* Invalidate FPU flag */ + p->thread.pc = (unsigned long) ret_from_kernel_thread; + return 0; + } *childregs = *regs; /* @@ -428,19 +407,12 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, * 32-bit wide and context switch must take care * of NEFF sign extension. */ - if (user_mode(regs)) { - childregs->regs[15] = neff_sign_extend(usp); - p->thread.uregs = childregs; - } else { - childregs->regs[15] = - neff_sign_extend((unsigned long)task_stack_page(p) + - THREAD_SIZE); - } + childregs->regs[15] = neff_sign_extend(usp); + p->thread.uregs = childregs; childregs->regs[9] = 0; /* Set return value for child */ childregs->sr |= SR_FD; /* Invalidate FPU flag */ - p->thread.sp = (unsigned long) childregs; p->thread.pc = (unsigned long) ret_from_fork; return 0; @@ -482,31 +454,6 @@ asmlinkage int sys_vfork(unsigned long r2, unsigned long r3, return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); } -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(const char *ufilename, char **uargv, - char **uenvp, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs) -{ - int error; - struct filename *filename; - - filename = getname((char __user *)ufilename); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename->name, - (const char __user *const __user *)uargv, - (const char __user *const __user *)uenvp, - pregs); - putname(filename); -out: - return error; -} - #ifdef CONFIG_FRAME_POINTER static int in_sh64_switch_to(unsigned long pc) { diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 23853814bd1..d867cd95a62 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c @@ -347,7 +347,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3, { struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP; sigset_t set; - stack_t __user st; long long ret; /* Always make any pending restarted system calls return -EINTR */ @@ -365,11 +364,10 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3, goto badframe; regs->pc -= 4; - if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) - goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, REF_REG_SP); + if (do_sigaltstack(&frame->uc.uc_stack, NULL, REF_REG_SP) == -EFAULT) + goto badframe; return (int) ret; diff --git a/arch/sh/kernel/sys_sh32.c b/arch/sh/kernel/sys_sh32.c index f56b6fe5c5d..497bab3a040 100644 --- a/arch/sh/kernel/sys_sh32.c +++ b/arch/sh/kernel/sys_sh32.c @@ -60,27 +60,3 @@ asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1, (u64)len0 << 32 | len1, advice); #endif } - -#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) -#define SYSCALL_ARG3 "trapa #0x23" -#else -#define SYSCALL_ARG3 "trapa #0x13" -#endif - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - register long __sc0 __asm__ ("r3") = __NR_execve; - register long __sc4 __asm__ ("r4") = (long) filename; - register long __sc5 __asm__ ("r5") = (long) argv; - register long __sc6 __asm__ ("r6") = (long) envp; - __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0) - : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) - : "memory"); - return __sc0; -} diff --git a/arch/sh/kernel/sys_sh64.c b/arch/sh/kernel/sys_sh64.c deleted file mode 100644 index c5a38c4bf41..00000000000 --- a/arch/sh/kernel/sys_sh64.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * arch/sh/kernel/sys_sh64.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/SH5 - * platform. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include <linux/errno.h> -#include <linux/rwsem.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/fs.h> -#include <linux/smp.h> -#include <linux/sem.h> -#include <linux/msg.h> -#include <linux/shm.h> -#include <linux/stat.h> -#include <linux/mman.h> -#include <linux/file.h> -#include <linux/syscalls.h> -#include <linux/ipc.h> -#include <asm/uaccess.h> -#include <asm/ptrace.h> -#include <asm/unistd.h> - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve); - register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename; - register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv; - register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp; - __asm__ __volatile__ ("trapa %1 !\t\t\t execve(%2,%3,%4)" - : "=r" (__sc0) - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); - __asm__ __volatile__ ("!dummy %0 %1 %2 %3" - : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory"); - return __sc0; -} diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 4b68f0f7976..fe97ae5e56f 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -384,3 +384,4 @@ ENTRY(sys_call_table) .long sys_setns .long sys_process_vm_readv /* 365 */ .long sys_process_vm_writev + .long sys_kcmp diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 0956345b36e..5c7b1c67bdc 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -404,3 +404,4 @@ sys_call_table: .long sys_setns /* 375 */ .long sys_process_vm_readv .long sys_process_vm_writev + .long sys_kcmp diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index b6b442b0d79..0c7d365fa40 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -20,6 +20,7 @@ config SPARC select HAVE_ARCH_TRACEHOOK select SYSCTL_EXCEPTION_TRACE select ARCH_WANT_OPTIONAL_GPIOLIB + select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select RTC_CLASS select RTC_DRV_M48T59 select HAVE_IRQ_WORK @@ -40,6 +41,8 @@ config SPARC select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNLEN_USER select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE config SPARC32 def_bool !64BIT diff --git a/arch/sparc/crypto/Makefile b/arch/sparc/crypto/Makefile index 6ae1ad5e502..5d469d81761 100644 --- a/arch/sparc/crypto/Makefile +++ b/arch/sparc/crypto/Makefile @@ -13,13 +13,13 @@ obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o -sha1-sparc64-y := sha1_asm.o sha1_glue.o crop_devid.o -sha256-sparc64-y := sha256_asm.o sha256_glue.o crop_devid.o -sha512-sparc64-y := sha512_asm.o sha512_glue.o crop_devid.o -md5-sparc64-y := md5_asm.o md5_glue.o crop_devid.o +sha1-sparc64-y := sha1_asm.o sha1_glue.o +sha256-sparc64-y := sha256_asm.o sha256_glue.o +sha512-sparc64-y := sha512_asm.o sha512_glue.o +md5-sparc64-y := md5_asm.o md5_glue.o -aes-sparc64-y := aes_asm.o aes_glue.o crop_devid.o -des-sparc64-y := des_asm.o des_glue.o crop_devid.o -camellia-sparc64-y := camellia_asm.o camellia_glue.o crop_devid.o +aes-sparc64-y := aes_asm.o aes_glue.o +des-sparc64-y := des_asm.o des_glue.o +camellia-sparc64-y := camellia_asm.o camellia_glue.o -crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o crop_devid.o +crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c index 8f1c9980f63..3965d1d36df 100644 --- a/arch/sparc/crypto/aes_glue.c +++ b/arch/sparc/crypto/aes_glue.c @@ -475,3 +475,5 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated"); MODULE_ALIAS("aes"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c index 42905c08429..62c89af3fd3 100644 --- a/arch/sparc/crypto/camellia_glue.c +++ b/arch/sparc/crypto/camellia_glue.c @@ -320,3 +320,5 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated"); MODULE_ALIAS("aes"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c index 0bd89cea8d8..5162fad912c 100644 --- a/arch/sparc/crypto/crc32c_glue.c +++ b/arch/sparc/crypto/crc32c_glue.c @@ -177,3 +177,5 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated"); MODULE_ALIAS("crc32c"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c index c4940c2d307..41524cebcc4 100644 --- a/arch/sparc/crypto/des_glue.c +++ b/arch/sparc/crypto/des_glue.c @@ -527,3 +527,5 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated"); MODULE_ALIAS("des"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/md5_glue.c b/arch/sparc/crypto/md5_glue.c index 603d723038c..09a9ea1dfb6 100644 --- a/arch/sparc/crypto/md5_glue.c +++ b/arch/sparc/crypto/md5_glue.c @@ -186,3 +186,5 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated"); MODULE_ALIAS("md5"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/sha1_glue.c b/arch/sparc/crypto/sha1_glue.c index 2bbb20bee9f..6cd5f29e1e0 100644 --- a/arch/sparc/crypto/sha1_glue.c +++ b/arch/sparc/crypto/sha1_glue.c @@ -181,3 +181,5 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated"); MODULE_ALIAS("sha1"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/sha256_glue.c b/arch/sparc/crypto/sha256_glue.c index 591e656bd89..04f555ab268 100644 --- a/arch/sparc/crypto/sha256_glue.c +++ b/arch/sparc/crypto/sha256_glue.c @@ -239,3 +239,5 @@ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 op MODULE_ALIAS("sha224"); MODULE_ALIAS("sha256"); + +#include "crop_devid.c" diff --git a/arch/sparc/crypto/sha512_glue.c b/arch/sparc/crypto/sha512_glue.c index 486f0a2b700..f04d1994d19 100644 --- a/arch/sparc/crypto/sha512_glue.c +++ b/arch/sparc/crypto/sha512_glue.c @@ -224,3 +224,5 @@ MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 op MODULE_ALIAS("sha384"); MODULE_ALIAS("sha512"); + +#include "crop_devid.c" diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index ce35a1cf1a2..be56a244c9c 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -1,7 +1,7 @@ /* atomic.h: Thankfully the V9 is at least reasonable for this * stuff. * - * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com) + * Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com) */ #ifndef __ARCH_SPARC64_ATOMIC__ @@ -106,6 +106,8 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u) #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) +extern long atomic64_dec_if_positive(atomic64_t *v); + /* Atomic operations are already serializing */ #define smp_mb__before_atomic_dec() barrier() #define smp_mb__after_atomic_dec() barrier() diff --git a/arch/sparc/include/asm/backoff.h b/arch/sparc/include/asm/backoff.h index db3af0d30fb..4e02086b839 100644 --- a/arch/sparc/include/asm/backoff.h +++ b/arch/sparc/include/asm/backoff.h @@ -1,6 +1,46 @@ #ifndef _SPARC64_BACKOFF_H #define _SPARC64_BACKOFF_H +/* The macros in this file implement an exponential backoff facility + * for atomic operations. + * + * When multiple threads compete on an atomic operation, it is + * possible for one thread to be continually denied a successful + * completion of the compare-and-swap instruction. Heavily + * threaded cpu implementations like Niagara can compound this + * problem even further. + * + * When an atomic operation fails and needs to be retried, we spin a + * certain number of times. At each subsequent failure of the same + * operation we double the spin count, realizing an exponential + * backoff. + * + * When we spin, we try to use an operation that will cause the + * current cpu strand to block, and therefore make the core fully + * available to any other other runnable strands. There are two + * options, based upon cpu capabilities. + * + * On all cpus prior to SPARC-T4 we do three dummy reads of the + * condition code register. Each read blocks the strand for something + * between 40 and 50 cpu cycles. + * + * For SPARC-T4 and later we have a special "pause" instruction + * available. This is implemented using writes to register %asr27. + * The cpu will block the number of cycles written into the register, + * unless a disrupting trap happens first. SPARC-T4 specifically + * implements pause with a granularity of 8 cycles. Each strand has + * an internal pause counter which decrements every 8 cycles. So the + * chip shifts the %asr27 value down by 3 bits, and writes the result + * into the pause counter. If a value smaller than 8 is written, the + * chip blocks for 1 cycle. + * + * To achieve the same amount of backoff as the three %ccr reads give + * on earlier chips, we shift the backoff value up by 7 bits. (Three + * %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the + * whole amount we want to block into the pause register, rather than + * loop writing 128 each time. + */ + #define BACKOFF_LIMIT (4 * 1024) #ifdef CONFIG_SMP @@ -11,16 +51,25 @@ #define BACKOFF_LABEL(spin_label, continue_label) \ spin_label -#define BACKOFF_SPIN(reg, tmp, label) \ - mov reg, tmp; \ -88: brnz,pt tmp, 88b; \ - sub tmp, 1, tmp; \ - set BACKOFF_LIMIT, tmp; \ - cmp reg, tmp; \ - bg,pn %xcc, label; \ - nop; \ - ba,pt %xcc, label; \ - sllx reg, 1, reg; +#define BACKOFF_SPIN(reg, tmp, label) \ + mov reg, tmp; \ +88: rd %ccr, %g0; \ + rd %ccr, %g0; \ + rd %ccr, %g0; \ + .section .pause_3insn_patch,"ax";\ + .word 88b; \ + sllx tmp, 7, tmp; \ + wr tmp, 0, %asr27; \ + clr tmp; \ + .previous; \ + brnz,pt tmp, 88b; \ + sub tmp, 1, tmp; \ + set BACKOFF_LIMIT, tmp; \ + cmp reg, tmp; \ + bg,pn %xcc, label; \ + nop; \ + ba,pt %xcc, label; \ + sllx reg, 1, reg; #else diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index cef99fbc0a2..830502fe62b 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h @@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len) struct pt_regs *regs = current_thread_info()->kregs; unsigned long usp = regs->u_regs[UREG_I6]; - if (!(test_thread_flag(TIF_32BIT))) + if (test_thread_64bit_stack(usp)) usp += STACK_BIAS; - else + + if (test_thread_flag(TIF_32BIT)) usp &= 0xffffffffUL; usp -= len; diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h index f74ac9ee33a..c1e01914fd9 100644 --- a/arch/sparc/include/asm/processor_32.h +++ b/arch/sparc/include/asm/processor_32.h @@ -106,7 +106,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc, /* Free all resources held by a thread. */ #define release_thread(tsk) do { } while(0) -extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern unsigned long get_wchan(struct task_struct *); diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h index 4e5a483122a..cce72ce4c33 100644 --- a/arch/sparc/include/asm/processor_64.h +++ b/arch/sparc/include/asm/processor_64.h @@ -94,6 +94,7 @@ struct thread_struct { #ifndef __ASSEMBLY__ #include <linux/types.h> +#include <asm/fpumacro.h> /* Return saved PC of a blocked thread. */ struct task_struct; @@ -143,6 +144,10 @@ do { \ : \ : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \ "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ + fprs_write(0); \ + current_thread_info()->xfsr[0] = 0; \ + current_thread_info()->fpsaved[0] = 0; \ + regs->tstate &= ~TSTATE_PEF; \ } while (0) #define start_thread32(regs, pc, sp) \ @@ -183,20 +188,37 @@ do { \ : \ : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \ "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ + fprs_write(0); \ + current_thread_info()->xfsr[0] = 0; \ + current_thread_info()->fpsaved[0] = 0; \ + regs->tstate &= ~TSTATE_PEF; \ } while (0) /* Free all resources held by a thread. */ #define release_thread(tsk) do { } while (0) -extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - extern unsigned long get_wchan(struct task_struct *task); #define task_pt_regs(tsk) (task_thread_info(tsk)->kregs) #define KSTK_EIP(tsk) (task_pt_regs(tsk)->tpc) #define KSTK_ESP(tsk) (task_pt_regs(tsk)->u_regs[UREG_FP]) -#define cpu_relax() barrier() +/* Please see the commentary in asm/backoff.h for a description of + * what these instructions are doing and how they have been choosen. + * To make a long story short, we are trying to yield the current cpu + * strand during busy loops. + */ +#define cpu_relax() asm volatile("\n99:\n\t" \ + "rd %%ccr, %%g0\n\t" \ + "rd %%ccr, %%g0\n\t" \ + "rd %%ccr, %%g0\n\t" \ + ".section .pause_3insn_patch,\"ax\"\n\t"\ + ".word 99b\n\t" \ + "wr %%g0, 128, %%asr27\n\t" \ + "nop\n\t" \ + "nop\n\t" \ + ".previous" \ + ::: "memory") /* Prefetch support. This is tuned for UltraSPARC-III and later. * UltraSPARC-I will treat these as nops, and UltraSPARC-II has diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index c2876511070..67c62578d17 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h @@ -63,5 +63,13 @@ extern char *of_console_options; extern void irq_trans_init(struct device_node *dp); extern char *build_path_component(struct device_node *dp); +/* SPARC has local implementations */ +extern int of_address_to_resource(struct device_node *dev, int index, + struct resource *r); +#define of_address_to_resource of_address_to_resource + +void __iomem *of_iomap(struct device_node *node, int index); +#define of_iomap of_iomap + #endif /* __KERNEL__ */ #endif /* _SPARC_PROM_H */ diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h index 0c6f6b06828..bdfafd7af46 100644 --- a/arch/sparc/include/asm/ptrace.h +++ b/arch/sparc/include/asm/ptrace.h @@ -32,6 +32,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs) #define arch_ptrace_stop(exit_code, info) \ synchronize_user_stack() +#define current_pt_regs() \ + ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) + struct global_reg_snapshot { unsigned long tstate; unsigned long tpc; @@ -42,11 +45,20 @@ struct global_reg_snapshot { struct thread_info *thread; unsigned long pad1; }; -extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; -#define force_successful_syscall_return() \ -do { current_thread_info()->syscall_noerror = 1; \ -} while (0) +struct global_pmu_snapshot { + unsigned long pcr[4]; + unsigned long pic[4]; +}; + +union global_cpu_snapshot { + struct global_reg_snapshot reg; + struct global_pmu_snapshot pmu; +}; + +extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; + +#define force_successful_syscall_return() set_thread_noerror(1) #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) #define instruction_pointer(regs) ((regs)->tpc) #define instruction_pointer_set(regs, val) ((regs)->tpc = (val)) @@ -89,6 +101,9 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs) #define arch_ptrace_stop(exit_code, info) \ synchronize_user_stack() +#define current_pt_regs() \ + ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) + #define user_mode(regs) (!((regs)->psr & PSR_PS)) #define instruction_pointer(regs) ((regs)->pc) #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) diff --git a/arch/sparc/include/asm/smp_64.h b/arch/sparc/include/asm/smp_64.h index 29862a9e906..dd3bef4b989 100644 --- a/arch/sparc/include/asm/smp_64.h +++ b/arch/sparc/include/asm/smp_64.h @@ -48,6 +48,7 @@ extern void smp_fill_in_sib_core_maps(void); extern void cpu_play_dead(void); extern void smp_fetch_global_regs(void); +extern void smp_fetch_global_pmu(void); struct seq_file; void smp_bogo(struct seq_file *); @@ -65,6 +66,7 @@ extern void __cpu_die(unsigned int cpu); #define hard_smp_processor_id() 0 #define smp_fill_in_sib_core_maps() do { } while (0) #define smp_fetch_global_regs() do { } while (0) +#define smp_fetch_global_pmu() do { } while (0) #endif /* !(CONFIG_SMP) */ diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h index 7923c4a2be3..cad36f56fa0 100644 --- a/arch/sparc/include/asm/switch_to_64.h +++ b/arch/sparc/include/asm/switch_to_64.h @@ -23,7 +23,7 @@ do { flush_tlb_pending(); \ /* If you are tempted to conditionalize the following */ \ /* so that ASI is only written if it changes, think again. */ \ __asm__ __volatile__("wr %%g0, %0, %%asi" \ - : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\ + : : "r" (task_thread_info(next)->current_ds));\ trap_block[current_thread_info()->cpu].thread = \ task_thread_info(next); \ __asm__ __volatile__( \ diff --git a/arch/sparc/include/asm/syscalls.h b/arch/sparc/include/asm/syscalls.h index 45a43f637a1..bf8972adea1 100644 --- a/arch/sparc/include/asm/syscalls.h +++ b/arch/sparc/include/asm/syscalls.h @@ -8,6 +8,4 @@ extern asmlinkage long sparc_do_fork(unsigned long clone_flags, struct pt_regs *regs, unsigned long stack_size); -extern asmlinkage int sparc_execve(struct pt_regs *regs); - #endif /* _SPARC64_SYSCALLS_H */ diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index 4e227663108..269bd92313d 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -14,12 +14,12 @@ #define TI_FLAG_FAULT_CODE_SHIFT 56 #define TI_FLAG_BYTE_WSTATE 1 #define TI_FLAG_WSTATE_SHIFT 48 -#define TI_FLAG_BYTE_CWP 2 -#define TI_FLAG_CWP_SHIFT 40 -#define TI_FLAG_BYTE_CURRENT_DS 3 -#define TI_FLAG_CURRENT_DS_SHIFT 32 -#define TI_FLAG_BYTE_FPDEPTH 4 -#define TI_FLAG_FPDEPTH_SHIFT 24 +#define TI_FLAG_BYTE_NOERROR 2 +#define TI_FLAG_BYTE_NOERROR_SHIFT 40 +#define TI_FLAG_BYTE_FPDEPTH 3 +#define TI_FLAG_FPDEPTH_SHIFT 32 +#define TI_FLAG_BYTE_CWP 4 +#define TI_FLAG_CWP_SHIFT 24 #define TI_FLAG_BYTE_WSAVED 5 #define TI_FLAG_WSAVED_SHIFT 16 @@ -47,7 +47,7 @@ struct thread_info { struct exec_domain *exec_domain; int preempt_count; /* 0 => preemptable, <0 => BUG */ __u8 new_child; - __u8 syscall_noerror; + __u8 current_ds; __u16 cpu; unsigned long *utraps; @@ -74,9 +74,9 @@ struct thread_info { #define TI_FAULT_CODE (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE) #define TI_WSTATE (TI_FLAGS + TI_FLAG_BYTE_WSTATE) #define TI_CWP (TI_FLAGS + TI_FLAG_BYTE_CWP) -#define TI_CURRENT_DS (TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS) #define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH) #define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED) +#define TI_SYS_NOERROR (TI_FLAGS + TI_FLAG_BYTE_NOERROR) #define TI_FPSAVED 0x00000010 #define TI_KSP 0x00000018 #define TI_FAULT_ADDR 0x00000020 @@ -84,7 +84,7 @@ struct thread_info { #define TI_EXEC_DOMAIN 0x00000030 #define TI_PRE_COUNT 0x00000038 #define TI_NEW_CHILD 0x0000003c -#define TI_SYS_NOERROR 0x0000003d +#define TI_CURRENT_DS 0x0000003d #define TI_CPU 0x0000003e #define TI_UTRAPS 0x00000040 #define TI_REG_WINDOW 0x00000048 @@ -121,7 +121,7 @@ struct thread_info { #define INIT_THREAD_INFO(tsk) \ { \ .task = &tsk, \ - .flags = ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT, \ + .current_ds = ASI_P, \ .exec_domain = &default_exec_domain, \ .preempt_count = INIT_PREEMPT_COUNT, \ .restart_block = { \ @@ -153,13 +153,12 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define set_thread_wstate(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val)) #define get_thread_cwp() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP]) #define set_thread_cwp(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val)) -#define get_thread_current_ds() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS]) -#define set_thread_current_ds(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val)) +#define get_thread_noerror() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR]) +#define set_thread_noerror(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR] = (val)) #define get_thread_fpdepth() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH]) #define set_thread_fpdepth(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val)) #define get_thread_wsaved() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED]) #define set_thread_wsaved(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val)) - #endif /* !(__ASSEMBLY__) */ /* @@ -259,6 +258,11 @@ static inline bool test_and_clear_restore_sigmask(void) #define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG) +#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0) +#define test_thread_64bit_stack(__SP) \ + ((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \ + false : true) + #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h index 48f2807d326..71b5a67522a 100644 --- a/arch/sparc/include/asm/ttable.h +++ b/arch/sparc/include/asm/ttable.h @@ -372,7 +372,9 @@ etrap_spill_fixup_64bit: \ /* Normal 32bit spill */ #define SPILL_2_GENERIC(ASI) \ - srl %sp, 0, %sp; \ + and %sp, 1, %g3; \ + brnz,pn %g3, (. - (128 + 4)); \ + srl %sp, 0, %sp; \ stwa %l0, [%sp + %g0] ASI; \ mov 0x04, %g3; \ stwa %l1, [%sp + %g3] ASI; \ @@ -398,14 +400,16 @@ etrap_spill_fixup_64bit: \ stwa %i6, [%g1 + %g0] ASI; \ stwa %i7, [%g1 + %g3] ASI; \ saved; \ - retry; nop; nop; \ + retry; \ b,a,pt %xcc, spill_fixup_dax; \ b,a,pt %xcc, spill_fixup_mna; \ b,a,pt %xcc, spill_fixup; #define SPILL_2_GENERIC_ETRAP \ etrap_user_spill_32bit: \ - srl %sp, 0, %sp; \ + and %sp, 1, %g3; \ + brnz,pn %g3, etrap_user_spill_64bit; \ + srl %sp, 0, %sp; \ stwa %l0, [%sp + 0x00] %asi; \ stwa %l1, [%sp + 0x04] %asi; \ stwa %l2, [%sp + 0x08] %asi; \ @@ -427,7 +431,7 @@ etrap_user_spill_32bit: \ ba,pt %xcc, etrap_save; \ wrpr %g1, %cwp; \ nop; nop; nop; nop; \ - nop; nop; nop; nop; \ + nop; nop; \ ba,a,pt %xcc, etrap_spill_fixup_32bit; \ ba,a,pt %xcc, etrap_spill_fixup_32bit; \ ba,a,pt %xcc, etrap_spill_fixup_32bit; @@ -592,7 +596,9 @@ user_rtt_fill_64bit: \ /* Normal 32bit fill */ #define FILL_2_GENERIC(ASI) \ - srl %sp, 0, %sp; \ + and %sp, 1, %g3; \ + brnz,pn %g3, (. - (128 + 4)); \ + srl %sp, 0, %sp; \ lduwa [%sp + %g0] ASI, %l0; \ mov 0x04, %g2; \ mov 0x08, %g3; \ @@ -616,14 +622,16 @@ user_rtt_fill_64bit: \ lduwa [%g1 + %g3] ASI, %i6; \ lduwa [%g1 + %g5] ASI, %i7; \ restored; \ - retry; nop; nop; nop; nop; \ + retry; nop; nop; \ b,a,pt %xcc, fill_fixup_dax; \ b,a,pt %xcc, fill_fixup_mna; \ b,a,pt %xcc, fill_fixup; #define FILL_2_GENERIC_RTRAP \ user_rtt_fill_32bit: \ - srl %sp, 0, %sp; \ + and %sp, 1, %g3; \ + brnz,pn %g3, user_rtt_fill_64bit; \ + srl %sp, 0, %sp; \ lduwa [%sp + 0x00] %asi, %l0; \ lduwa [%sp + 0x04] %asi, %l1; \ lduwa [%sp + 0x08] %asi, %l2; \ @@ -643,7 +651,7 @@ user_rtt_fill_32bit: \ ba,pt %xcc, user_rtt_pre_restore; \ restored; \ nop; nop; nop; nop; nop; \ - nop; nop; nop; nop; nop; \ + nop; nop; nop; \ ba,a,pt %xcc, user_rtt_fill_fixup; \ ba,a,pt %xcc, user_rtt_fill_fixup; \ ba,a,pt %xcc, user_rtt_fill_fixup; diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h index 73083e1d38d..e562d3caee5 100644 --- a/arch/sparc/include/asm/uaccess_64.h +++ b/arch/sparc/include/asm/uaccess_64.h @@ -38,14 +38,14 @@ #define VERIFY_READ 0 #define VERIFY_WRITE 1 -#define get_fs() ((mm_segment_t) { get_thread_current_ds() }) +#define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)}) #define get_ds() (KERNEL_DS) #define segment_eq(a,b) ((a).seg == (b).seg) #define set_fs(val) \ do { \ - set_thread_current_ds((val).seg); \ + current_thread_info()->current_ds =(val).seg; \ __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \ } while(0) diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h index 0ecea6ed943..c3e5d8b6417 100644 --- a/arch/sparc/include/asm/unistd.h +++ b/arch/sparc/include/asm/unistd.h @@ -46,6 +46,7 @@ #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif +#define __ARCH_WANT_SYS_EXECVE /* * "Conditional" syscalls diff --git a/arch/sparc/include/uapi/asm/sigcontext.h b/arch/sparc/include/uapi/asm/sigcontext.h index e69de29bb2d..ae5704fa77a 100644 --- a/arch/sparc/include/uapi/asm/sigcontext.h +++ b/arch/sparc/include/uapi/asm/sigcontext.h @@ -0,0 +1,4 @@ +/* + * There isn't anything here anymore, but the file must not be empty or patch + * will delete it. + */ diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h index 8974ef7ae92..cac719d1bc5 100644 --- a/arch/sparc/include/uapi/asm/unistd.h +++ b/arch/sparc/include/uapi/asm/unistd.h @@ -405,8 +405,13 @@ #define __NR_setns 337 #define __NR_process_vm_readv 338 #define __NR_process_vm_writev 339 +#define __NR_kern_features 340 +#define __NR_kcmp 341 -#define NR_syscalls 340 +#define NR_syscalls 342 + +/* Bitmask values returned from kern_features system call. */ +#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001 #ifdef __32bit_syscall_numbers__ /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants, diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index dcaa1cf0de4..21fd1a8f47d 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -806,23 +806,10 @@ sys_nis_syscall: call c_sys_nis_syscall mov %l5, %o7 - .align 4 - .globl sys_execve -sys_execve: - mov %o7, %l5 - add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg - call sparc_execve - mov %l5, %o7 - - .globl sunos_execv sunos_execv: - st %g0, [%sp + STACKFRAME_SZ + PT_I2] - - call sparc_execve - add %sp, STACKFRAME_SZ, %o0 - - b ret_sys_call - ld [%sp + STACKFRAME_SZ + PT_I0], %o0 + .globl sunos_execv + b sys_execve + clr %i2 .align 4 .globl sys_sparc_pipe @@ -959,17 +946,9 @@ flush_patch_four: .align 4 linux_sparc_ni_syscall: sethi %hi(sys_ni_syscall), %l7 - b syscall_is_too_hard + b do_syscall or %l7, %lo(sys_ni_syscall), %l7 -linux_fast_syscall: - andn %l7, 3, %l7 - mov %i0, %o0 - mov %i1, %o1 - mov %i2, %o2 - jmpl %l7 + %g0, %g0 - mov %i3, %o3 - linux_syscall_trace: add %sp, STACKFRAME_SZ, %o0 call syscall_trace @@ -991,6 +970,23 @@ ret_from_fork: b ret_sys_call ld [%sp + STACKFRAME_SZ + PT_I0], %o0 + .globl ret_from_kernel_thread +ret_from_kernel_thread: + call schedule_tail + ld [%g3 + TI_TASK], %o0 + ld [%sp + STACKFRAME_SZ + PT_G1], %l0 + call %l0 + ld [%sp + STACKFRAME_SZ + PT_G2], %o0 + rd %psr, %l1 + ld [%sp + STACKFRAME_SZ + PT_PSR], %l0 + andn %l0, PSR_CWP, %l0 + nop + and %l1, PSR_CWP, %l1 + or %l0, %l1, %l0 + st %l0, [%sp + STACKFRAME_SZ + PT_PSR] + b ret_sys_call + mov 0, %o0 + /* Linux native system calls enter here... */ .align 4 .globl linux_sparc_syscall @@ -1002,11 +998,8 @@ linux_sparc_syscall: bgeu linux_sparc_ni_syscall sll %g1, 2, %l4 ld [%l7 + %l4], %l7 - andcc %l7, 1, %g0 - bne linux_fast_syscall - /* Just do first insn from SAVE_ALL in the delay slot */ -syscall_is_too_hard: +do_syscall: SAVE_ALL_HEAD rd %wim, %l3 diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index 0c218e4c088..cc3c5cb47cd 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h @@ -59,6 +59,13 @@ struct popc_6insn_patch_entry { extern struct popc_6insn_patch_entry __popc_6insn_patch, __popc_6insn_patch_end; +struct pause_patch_entry { + unsigned int addr; + unsigned int insns[3]; +}; +extern struct pause_patch_entry __pause_3insn_patch, + __pause_3insn_patch_end; + extern void __init per_cpu_patch(void); extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *, struct sun4v_1insn_patch_entry *); diff --git a/arch/sparc/kernel/etrap_64.S b/arch/sparc/kernel/etrap_64.S index 786b185e6e3..1276ca2567b 100644 --- a/arch/sparc/kernel/etrap_64.S +++ b/arch/sparc/kernel/etrap_64.S @@ -92,8 +92,10 @@ etrap_save: save %g2, -STACK_BIAS, %sp rdpr %wstate, %g2 wrpr %g0, 0, %canrestore sll %g2, 3, %g2 + + /* Set TI_SYS_FPDEPTH to 1 and clear TI_SYS_NOERROR. */ mov 1, %l5 - stb %l5, [%l6 + TI_FPDEPTH] + sth %l5, [%l6 + TI_SYS_NOERROR] wrpr %g3, 0, %otherwin wrpr %g2, 0, %wstate @@ -152,7 +154,9 @@ etrap_save: save %g2, -STACK_BIAS, %sp add %l6, TI_FPSAVED + 1, %l4 srl %l5, 1, %l3 add %l5, 2, %l5 - stb %l5, [%l6 + TI_FPDEPTH] + + /* Set TI_SYS_FPDEPTH to %l5 and clear TI_SYS_NOERROR. */ + sth %l5, [%l6 + TI_SYS_NOERROR] ba,pt %xcc, 2b stb %g0, [%l4 + %l3] nop diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index f8b6eee40bd..87f60ee6543 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -56,11 +56,13 @@ static inline unsigned int leon_eirq_get(int cpu) static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc) { unsigned int eirq; + struct irq_bucket *p; int cpu = sparc_leon3_cpuid(); eirq = leon_eirq_get(cpu); - if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */ - generic_handle_irq(irq_map[eirq]->irq); + p = irq_map[eirq]; + if ((eirq & 0x10) && p && p->irq) /* bit4 tells if IRQ happened */ + generic_handle_irq(p->irq); } /* The extended IRQ controller has been found, this function registers it */ diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index e48651dace1..b5c38faa4ea 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -817,15 +817,17 @@ static u64 nop_for_index(int idx) static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx) { - u64 val, mask = mask_for_index(idx); + u64 enc, val, mask = mask_for_index(idx); int pcr_index = 0; if (sparc_pmu->num_pcrs > 1) pcr_index = idx; + enc = perf_event_get_enc(cpuc->events[idx]); + val = cpuc->pcr[pcr_index]; val &= ~mask; - val |= hwc->config; + val |= event_encoding(enc, idx); cpuc->pcr[pcr_index] = val; pcr_ops->write_pcr(pcr_index, cpuc->pcr[pcr_index]); @@ -1738,8 +1740,6 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, { unsigned long ufp; - perf_callchain_store(entry, regs->tpc); - ufp = regs->u_regs[UREG_I6] + STACK_BIAS; do { struct sparc_stackf *usf, sf; @@ -1760,19 +1760,27 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, { unsigned long ufp; - perf_callchain_store(entry, regs->tpc); - ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; do { - struct sparc_stackf32 *usf, sf; unsigned long pc; - usf = (struct sparc_stackf32 *) ufp; - if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) - break; + if (thread32_stack_is_64bit(ufp)) { + struct sparc_stackf *usf, sf; - pc = sf.callers_pc; - ufp = (unsigned long)sf.fp; + ufp += STACK_BIAS; + usf = (struct sparc_stackf *) ufp; + if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) + break; + pc = sf.callers_pc & 0xffffffff; + ufp = ((unsigned long) sf.fp) & 0xffffffff; + } else { + struct sparc_stackf32 *usf, sf; + usf = (struct sparc_stackf32 *) ufp; + if (__copy_from_user_inatomic(&sf, usf, sizeof(sf))) + break; + pc = sf.callers_pc; + ufp = (unsigned long)sf.fp; + } perf_callchain_store(entry, pc); } while (entry->nr < PERF_MAX_STACK_DEPTH); } @@ -1780,6 +1788,11 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, void perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) { + perf_callchain_store(entry, regs->tpc); + + if (!current->mm) + return; + flushw_user(); if (test_thread_flag(TIF_32BIT)) perf_callchain_user_32(entry, regs); diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 487bffb36f5..bf4c6addce7 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -316,9 +316,10 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, * XXX See comment above sys_vfork in sparc64. todo. */ extern void ret_from_fork(void); +extern void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long unused, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct thread_info *ti = task_thread_info(p); @@ -336,16 +337,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, } /* - * p->thread_info new_stack childregs - * ! ! ! {if(PSR_PS) } - * V V (stk.fr.) V (pt_regs) { (stk.fr.) } - * +----- - - - - - ------+===========+============={+==========}+ + * p->thread_info new_stack childregs stack bottom + * ! ! ! ! + * V V (stk.fr.) V (pt_regs) V + * +----- - - - - - ------+===========+=============+ */ new_stack = task_stack_page(p) + THREAD_SIZE; - if (regs->psr & PSR_PS) - new_stack -= STACKFRAME_SZ; new_stack -= STACKFRAME_SZ + TRACEREG_SZ; - memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ); childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ); /* @@ -356,55 +354,58 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, * Thus, kpsr|=PSR_PIL. */ ti->ksp = (unsigned long) new_stack; + p->thread.kregs = childregs; + + if (unlikely(p->flags & PF_KTHREAD)) { + extern int nwindows; + unsigned long psr; + memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ); + p->thread.flags |= SPARC_FLAG_KTHREAD; + p->thread.current_ds = KERNEL_DS; + ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8); + childregs->u_regs[UREG_G1] = sp; /* function */ + childregs->u_regs[UREG_G2] = arg; + psr = childregs->psr = get_psr(); + ti->kpsr = psr | PSR_PIL; + ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows); + return 0; + } + memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ); + childregs->u_regs[UREG_FP] = sp; + p->thread.flags &= ~SPARC_FLAG_KTHREAD; + p->thread.current_ds = USER_DS; ti->kpc = (((unsigned long) ret_from_fork) - 0x8); ti->kpsr = current->thread.fork_kpsr | PSR_PIL; ti->kwim = current->thread.fork_kwim; - if(regs->psr & PSR_PS) { - extern struct pt_regs fake_swapper_regs; + if (sp != regs->u_regs[UREG_FP]) { + struct sparc_stackf __user *childstack; + struct sparc_stackf __user *parentstack; - p->thread.kregs = &fake_swapper_regs; - new_stack += STACKFRAME_SZ + TRACEREG_SZ; - childregs->u_regs[UREG_FP] = (unsigned long) new_stack; - p->thread.flags |= SPARC_FLAG_KTHREAD; - p->thread.current_ds = KERNEL_DS; - memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ); - childregs->u_regs[UREG_G6] = (unsigned long) ti; - } else { - p->thread.kregs = childregs; - childregs->u_regs[UREG_FP] = sp; - p->thread.flags &= ~SPARC_FLAG_KTHREAD; - p->thread.current_ds = USER_DS; - - if (sp != regs->u_regs[UREG_FP]) { - struct sparc_stackf __user *childstack; - struct sparc_stackf __user *parentstack; - - /* - * This is a clone() call with supplied user stack. - * Set some valid stack frames to give to the child. - */ - childstack = (struct sparc_stackf __user *) - (sp & ~0xfUL); - parentstack = (struct sparc_stackf __user *) - regs->u_regs[UREG_FP]; + /* + * This is a clone() call with supplied user stack. + * Set some valid stack frames to give to the child. + */ + childstack = (struct sparc_stackf __user *) + (sp & ~0xfUL); + parentstack = (struct sparc_stackf __user *) + regs->u_regs[UREG_FP]; #if 0 - printk("clone: parent stack:\n"); - show_stackframe(parentstack); + printk("clone: parent stack:\n"); + show_stackframe(parentstack); #endif - childstack = clone_stackframe(childstack, parentstack); - if (!childstack) - return -EFAULT; + childstack = clone_stackframe(childstack, parentstack); + if (!childstack) + return -EFAULT; #if 0 - printk("clone: child stack:\n"); - show_stackframe(childstack); + printk("clone: child stack:\n"); + show_stackframe(childstack); #endif - childregs->u_regs[UREG_FP] = (unsigned long)childstack; - } + childregs->u_regs[UREG_FP] = (unsigned long)childstack; } #ifdef CONFIG_SMP @@ -475,69 +476,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) return 1; } -/* - * sparc_execve() executes a new program after the asm stub has set - * things up for us. This should basically do what I want it to. - */ -asmlinkage int sparc_execve(struct pt_regs *regs) -{ - int error, base = 0; - struct filename *filename; - - /* Check for indirect call. */ - if(regs->u_regs[UREG_G1] == 0) - base = 1; - - filename = getname((char __user *)regs->u_regs[base + UREG_I0]); - error = PTR_ERR(filename); - if(IS_ERR(filename)) - goto out; - error = do_execve(filename->name, - (const char __user *const __user *) - regs->u_regs[base + UREG_I1], - (const char __user *const __user *) - regs->u_regs[base + UREG_I2], - regs); - putname(filename); -out: - return error; -} - -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be freed until both the parent and the child have exited. - */ -pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - long retval; - - __asm__ __volatile__("mov %4, %%g2\n\t" /* Set aside fn ptr... */ - "mov %5, %%g3\n\t" /* and arg. */ - "mov %1, %%g1\n\t" - "mov %2, %%o0\n\t" /* Clone flags. */ - "mov 0, %%o1\n\t" /* usp arg == 0 */ - "t 0x10\n\t" /* Linux/Sparc clone(). */ - "cmp %%o1, 0\n\t" - "be 1f\n\t" /* The parent, just return. */ - " nop\n\t" /* Delay slot. */ - "jmpl %%g2, %%o7\n\t" /* Call the function. */ - " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */ - "mov %3, %%g1\n\t" - "t 0x10\n\t" /* Linux/Sparc exit(). */ - /* Notreached by child. */ - "1: mov %%o0, %0\n\t" : - "=r" (retval) : - "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), - "i" (__NR_exit), "r" (fn), "r" (arg) : - "g1", "g2", "g3", "o0", "o1", "memory", "cc"); - return retval; -} -EXPORT_SYMBOL(kernel_thread); - unsigned long get_wchan(struct task_struct *task) { unsigned long pc, fp, bias = 0; diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index fcaa5942112..dff54f46728 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -27,6 +27,7 @@ #include <linux/tick.h> #include <linux/init.h> #include <linux/cpu.h> +#include <linux/perf_event.h> #include <linux/elfcore.h> #include <linux/sysrq.h> #include <linux/nmi.h> @@ -47,6 +48,7 @@ #include <asm/syscalls.h> #include <asm/irq_regs.h> #include <asm/smp.h> +#include <asm/pcr.h> #include "kstack.h" @@ -204,18 +206,22 @@ void show_regs(struct pt_regs *regs) show_stack(current, (unsigned long *) regs->u_regs[UREG_FP]); } -struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; -static DEFINE_SPINLOCK(global_reg_snapshot_lock); +union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; +static DEFINE_SPINLOCK(global_cpu_snapshot_lock); static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, int this_cpu) { + struct global_reg_snapshot *rp; + flushw_all(); - global_reg_snapshot[this_cpu].tstate = regs->tstate; - global_reg_snapshot[this_cpu].tpc = regs->tpc; - global_reg_snapshot[this_cpu].tnpc = regs->tnpc; - global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; + rp = &global_cpu_snapshot[this_cpu].reg; + + rp->tstate = regs->tstate; + rp->tpc = regs->tpc; + rp->tnpc = regs->tnpc; + rp->o7 = regs->u_regs[UREG_I7]; if (regs->tstate & TSTATE_PRIV) { struct reg_window *rw; @@ -223,17 +229,17 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, rw = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS); if (kstack_valid(tp, (unsigned long) rw)) { - global_reg_snapshot[this_cpu].i7 = rw->ins[7]; + rp->i7 = rw->ins[7]; rw = (struct reg_window *) (rw->ins[6] + STACK_BIAS); if (kstack_valid(tp, (unsigned long) rw)) - global_reg_snapshot[this_cpu].rpc = rw->ins[7]; + rp->rpc = rw->ins[7]; } } else { - global_reg_snapshot[this_cpu].i7 = 0; - global_reg_snapshot[this_cpu].rpc = 0; + rp->i7 = 0; + rp->rpc = 0; } - global_reg_snapshot[this_cpu].thread = tp; + rp->thread = tp; } /* In order to avoid hangs we do not try to synchronize with the @@ -261,9 +267,9 @@ void arch_trigger_all_cpu_backtrace(void) if (!regs) regs = tp->kregs; - spin_lock_irqsave(&global_reg_snapshot_lock, flags); + spin_lock_irqsave(&global_cpu_snapshot_lock, flags); - memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot)); + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); this_cpu = raw_smp_processor_id(); @@ -272,7 +278,7 @@ void arch_trigger_all_cpu_backtrace(void) smp_fetch_global_regs(); for_each_online_cpu(cpu) { - struct global_reg_snapshot *gp = &global_reg_snapshot[cpu]; + struct global_reg_snapshot *gp = &global_cpu_snapshot[cpu].reg; __global_reg_poll(gp); @@ -295,9 +301,9 @@ void arch_trigger_all_cpu_backtrace(void) } } - memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot)); + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); - spin_unlock_irqrestore(&global_reg_snapshot_lock, flags); + spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags); } #ifdef CONFIG_MAGIC_SYSRQ @@ -309,16 +315,90 @@ static void sysrq_handle_globreg(int key) static struct sysrq_key_op sparc_globalreg_op = { .handler = sysrq_handle_globreg, - .help_msg = "Globalregs", + .help_msg = "global-regs(Y)", .action_msg = "Show Global CPU Regs", }; -static int __init sparc_globreg_init(void) +static void __global_pmu_self(int this_cpu) +{ + struct global_pmu_snapshot *pp; + int i, num; + + pp = &global_cpu_snapshot[this_cpu].pmu; + + num = 1; + if (tlb_type == hypervisor && + sun4v_chip_type >= SUN4V_CHIP_NIAGARA4) + num = 4; + + for (i = 0; i < num; i++) { + pp->pcr[i] = pcr_ops->read_pcr(i); + pp->pic[i] = pcr_ops->read_pic(i); + } +} + +static void __global_pmu_poll(struct global_pmu_snapshot *pp) +{ + int limit = 0; + + while (!pp->pcr[0] && ++limit < 100) { + barrier(); + udelay(1); + } +} + +static void pmu_snapshot_all_cpus(void) +{ + unsigned long flags; + int this_cpu, cpu; + + spin_lock_irqsave(&global_cpu_snapshot_lock, flags); + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); + + this_cpu = raw_smp_processor_id(); + + __global_pmu_self(this_cpu); + + smp_fetch_global_pmu(); + + for_each_online_cpu(cpu) { + struct global_pmu_snapshot *pp = &global_cpu_snapshot[cpu].pmu; + + __global_pmu_poll(pp); + + printk("%c CPU[%3d]: PCR[%08lx:%08lx:%08lx:%08lx] PIC[%08lx:%08lx:%08lx:%08lx]\n", + (cpu == this_cpu ? '*' : ' '), cpu, + pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3], + pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]); + } + + memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot)); + + spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags); +} + +static void sysrq_handle_globpmu(int key) { - return register_sysrq_key('y', &sparc_globalreg_op); + pmu_snapshot_all_cpus(); } -core_initcall(sparc_globreg_init); +static struct sysrq_key_op sparc_globalpmu_op = { + .handler = sysrq_handle_globpmu, + .help_msg = "global-pmu(X)", + .action_msg = "Show Global PMU Regs", +}; + +static int __init sparc_sysrq_init(void) +{ + int ret = register_sysrq_key('y', &sparc_globalreg_op); + + if (!ret) + ret = register_sysrq_key('x', &sparc_globalpmu_op); + return ret; +} + +core_initcall(sparc_sysrq_init); #endif @@ -372,13 +452,16 @@ void flush_thread(void) /* It's a bit more tricky when 64-bit tasks are involved... */ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) { + bool stack_64bit = test_thread_64bit_stack(psp); unsigned long fp, distance, rval; - if (!(test_thread_flag(TIF_32BIT))) { + if (stack_64bit) { csp += STACK_BIAS; psp += STACK_BIAS; __get_user(fp, &(((struct reg_window __user *)psp)->ins[6])); fp += STACK_BIAS; + if (test_thread_flag(TIF_32BIT)) + fp &= 0xffffffff; } else __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6])); @@ -392,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) rval = (csp - distance); if (copy_in_user((void __user *) rval, (void __user *) psp, distance)) rval = 0; - else if (test_thread_flag(TIF_32BIT)) { + else if (!stack_64bit) { if (put_user(((u32)csp), &(((struct reg_window32 __user *)rval)->ins[6]))) rval = 0; @@ -427,18 +510,18 @@ void synchronize_user_stack(void) flush_user_windows(); if ((window = get_thread_wsaved()) != 0) { - int winsize = sizeof(struct reg_window); - int bias = 0; - - if (test_thread_flag(TIF_32BIT)) - winsize = sizeof(struct reg_window32); - else - bias = STACK_BIAS; - window -= 1; do { - unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; + int winsize = sizeof(struct reg_window); + unsigned long sp; + + sp = t->rwbuf_stkptrs[window]; + + if (test_thread_64bit_stack(sp)) + sp += STACK_BIAS; + else + winsize = sizeof(struct reg_window32); if (!copy_to_user((char __user *)sp, rwin, winsize)) { shift_window_buffer(window, get_thread_wsaved() - 1, t); @@ -464,13 +547,6 @@ void fault_in_user_windows(void) { struct thread_info *t = current_thread_info(); unsigned long window; - int winsize = sizeof(struct reg_window); - int bias = 0; - - if (test_thread_flag(TIF_32BIT)) - winsize = sizeof(struct reg_window32); - else - bias = STACK_BIAS; flush_user_windows(); window = get_thread_wsaved(); @@ -478,8 +554,16 @@ void fault_in_user_windows(void) if (likely(window != 0)) { window -= 1; do { - unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; + int winsize = sizeof(struct reg_window); + unsigned long sp; + + sp = t->rwbuf_stkptrs[window]; + + if (test_thread_64bit_stack(sp)) + sp += STACK_BIAS; + else + winsize = sizeof(struct reg_window32); if (unlikely(sp & 0x7UL)) stack_unaligned(sp); @@ -538,64 +622,55 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, * Child --> %o0 == parents pid, %o1 == 1 */ int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long unused, + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct thread_info *t = task_thread_info(p); struct sparc_stackf *parent_sf; unsigned long child_stack_sz; char *child_trap_frame; - int kernel_thread; - - kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0; - parent_sf = ((struct sparc_stackf *) regs) - 1; /* Calculate offset to stack_frame & pt_regs */ - child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) + - (kernel_thread ? STACKFRAME_SZ : 0)); + child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ); child_trap_frame = (task_stack_page(p) + (THREAD_SIZE - child_stack_sz)); - memcpy(child_trap_frame, parent_sf, child_stack_sz); - t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | - (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | - (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT); t->new_child = 1; t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; t->kregs = (struct pt_regs *) (child_trap_frame + sizeof(struct sparc_stackf)); t->fpsaved[0] = 0; - if (kernel_thread) { - struct sparc_stackf *child_sf = (struct sparc_stackf *) - (child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ)); - - /* Zero terminate the stack backtrace. */ - child_sf->fp = NULL; - t->kregs->u_regs[UREG_FP] = - ((unsigned long) child_sf) - STACK_BIAS; + if (unlikely(p->flags & PF_KTHREAD)) { + memset(child_trap_frame, 0, child_stack_sz); + __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = + (current_pt_regs()->tstate + 1) & TSTATE_CWP; + t->current_ds = ASI_P; + t->kregs->u_regs[UREG_G1] = sp; /* function */ + t->kregs->u_regs[UREG_G2] = arg; + return 0; + } - t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT); - t->kregs->u_regs[UREG_G6] = (unsigned long) t; - t->kregs->u_regs[UREG_G4] = (unsigned long) t->task; - } else { - if (t->flags & _TIF_32BIT) { - sp &= 0x00000000ffffffffUL; - regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; - } - t->kregs->u_regs[UREG_FP] = sp; - t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT); - if (sp != regs->u_regs[UREG_FP]) { - unsigned long csp; - - csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); - if (!csp) - return -EFAULT; - t->kregs->u_regs[UREG_FP] = csp; - } - if (t->utraps) - t->utraps[0]++; + parent_sf = ((struct sparc_stackf *) regs) - 1; + memcpy(child_trap_frame, parent_sf, child_stack_sz); + if (t->flags & _TIF_32BIT) { + sp &= 0x00000000ffffffffUL; + regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; } + t->kregs->u_regs[UREG_FP] = sp; + __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = + (regs->tstate + 1) & TSTATE_CWP; + t->current_ds = ASI_AIUS; + if (sp != regs->u_regs[UREG_FP]) { + unsigned long csp; + + csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); + if (!csp) + return -EFAULT; + t->kregs->u_regs[UREG_FP] = csp; + } + if (t->utraps) + t->utraps[0]++; /* Set the return value for the child. */ t->kregs->u_regs[UREG_I0] = current->pid; @@ -610,45 +685,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, return 0; } -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be freed until both the parent and the child have exited. - */ -pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - long retval; - - /* If the parent runs before fn(arg) is called by the child, - * the input registers of this function can be clobbered. - * So we stash 'fn' and 'arg' into global registers which - * will not be modified by the parent. - */ - __asm__ __volatile__("mov %4, %%g2\n\t" /* Save FN into global */ - "mov %5, %%g3\n\t" /* Save ARG into global */ - "mov %1, %%g1\n\t" /* Clone syscall nr. */ - "mov %2, %%o0\n\t" /* Clone flags. */ - "mov 0, %%o1\n\t" /* usp arg == 0 */ - "t 0x6d\n\t" /* Linux/Sparc clone(). */ - "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */ - " mov %%o0, %0\n\t" - "jmpl %%g2, %%o7\n\t" /* Call the function. */ - " mov %%g3, %%o0\n\t" /* Set arg in delay. */ - "mov %3, %%g1\n\t" - "t 0x6d\n\t" /* Linux/Sparc exit(). */ - /* Notreached by child. */ - "1:" : - "=r" (retval) : - "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), - "i" (__NR_exit), "r" (fn), "r" (arg) : - "g1", "g2", "g3", "o0", "o1", "memory", "cc"); - return retval; -} -EXPORT_SYMBOL(kernel_thread); - typedef struct { union { unsigned int pr_regs[32]; @@ -715,41 +751,6 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) } EXPORT_SYMBOL(dump_fpu); -/* - * sparc_execve() executes a new program after the asm stub has set - * things up for us. This should basically do what I want it to. - */ -asmlinkage int sparc_execve(struct pt_regs *regs) -{ - int error, base = 0; - struct filename *filename; - - /* User register window flush is done by entry.S */ - - /* Check for indirect call. */ - if (regs->u_regs[UREG_G1] == 0) - base = 1; - - filename = getname((char __user *)regs->u_regs[base + UREG_I0]); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename->name, - (const char __user *const __user *) - regs->u_regs[base + UREG_I1], - (const char __user *const __user *) - regs->u_regs[base + UREG_I2], regs); - putname(filename); - if (!error) { - fprs_write(0); - current_thread_info()->xfsr[0] = 0; - current_thread_info()->fpsaved[0] = 0; - regs->tstate &= ~TSTATE_PEF; - } -out: - return error; -} - unsigned long get_wchan(struct task_struct *task) { unsigned long pc, fp, bias = 0; diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c index 484dabac704..7ff45e4ba68 100644 --- a/arch/sparc/kernel/ptrace_64.c +++ b/arch/sparc/kernel/ptrace_64.c @@ -151,7 +151,7 @@ static int regwindow64_get(struct task_struct *target, { unsigned long rw_addr = regs->u_regs[UREG_I6]; - if (test_tsk_thread_flag(current, TIF_32BIT)) { + if (!test_thread_64bit_stack(rw_addr)) { struct reg_window32 win32; int i; @@ -176,7 +176,7 @@ static int regwindow64_set(struct task_struct *target, { unsigned long rw_addr = regs->u_regs[UREG_I6]; - if (test_tsk_thread_flag(current, TIF_32BIT)) { + if (!test_thread_64bit_stack(rw_addr)) { struct reg_window32 win32; int i; diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 0800e71d8a8..0eaf0059aae 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -316,6 +316,25 @@ static void __init popc_patch(void) } } +static void __init pause_patch(void) +{ + struct pause_patch_entry *p; + + p = &__pause_3insn_patch; + while (p < &__pause_3insn_patch_end) { + unsigned long i, addr = p->addr; + + for (i = 0; i < 3; i++) { + *(unsigned int *) (addr + (i * 4)) = p->insns[i]; + wmb(); + __asm__ __volatile__("flush %0" + : : "r" (addr + (i * 4))); + } + + p++; + } +} + #ifdef CONFIG_SMP void __init boot_cpu_id_too_large(int cpu) { @@ -528,6 +547,8 @@ static void __init init_sparc64_elf_hwcap(void) if (sparc64_elf_hwcap & AV_SPARC_POPC) popc_patch(); + if (sparc64_elf_hwcap & AV_SPARC_PAUSE) + pause_patch(); } void __init setup_arch(char **cmdline_p) diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 867de2f8189..689e1ba6280 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -295,9 +295,7 @@ void do_rt_sigreturn(struct pt_regs *regs) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); - err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); - - if (err) + if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT) goto segv; err |= __get_user(rwin_save, &sf->rwin_save); diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 781bcb10b8b..d94b878577b 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -852,6 +852,8 @@ extern unsigned long xcall_flush_tlb_mm; extern unsigned long xcall_flush_tlb_pending; extern unsigned long xcall_flush_tlb_kernel_range; extern unsigned long xcall_fetch_glob_regs; +extern unsigned long xcall_fetch_glob_pmu; +extern unsigned long xcall_fetch_glob_pmu_n4; extern unsigned long xcall_receive_signal; extern unsigned long xcall_new_mmu_context_version; #ifdef CONFIG_KGDB @@ -1000,6 +1002,15 @@ void smp_fetch_global_regs(void) smp_cross_call(&xcall_fetch_glob_regs, 0, 0, 0); } +void smp_fetch_global_pmu(void) +{ + if (tlb_type == hypervisor && + sun4v_chip_type >= SUN4V_CHIP_NIAGARA4) + smp_cross_call(&xcall_fetch_glob_pmu_n4, 0, 0, 0); + else + smp_cross_call(&xcall_fetch_glob_pmu, 0, 0, 0); +} + /* We know that the window frames of the user have been flushed * to the stack before we get here because all callers of us * are flush_tlb_*() routines, and these run after flush_cache_*() diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index c3239811a1b..03c7e929ec3 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c @@ -396,42 +396,6 @@ asmlinkage long compat_sys_rt_sigaction(int sig, return ret; } -/* - * sparc32_execve() executes a new program after the asm stub has set - * things up for us. This should basically do what I want it to. - */ -asmlinkage long sparc32_execve(struct pt_regs *regs) -{ - int error, base = 0; - struct filename *filename; - - /* User register window flush is done by entry.S */ - - /* Check for indirect call. */ - if ((u32)regs->u_regs[UREG_G1] == 0) - base = 1; - - filename = getname(compat_ptr(regs->u_regs[base + UREG_I0])); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = compat_do_execve(filename->name, - compat_ptr(regs->u_regs[base + UREG_I1]), - compat_ptr(regs->u_regs[base + UREG_I2]), regs); - - putname(filename); - - if (!error) { - fprs_write(0); - current_thread_info()->xfsr[0] = 0; - current_thread_info()->fpsaved[0] = 0; - regs->tstate &= ~TSTATE_PEF; - } -out: - return error; -} - #ifdef CONFIG_MODULES asmlinkage long sys32_init_module(void __user *umod, u32 len, diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 0c9b31b22e0..a8e6eb0a11d 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c @@ -258,27 +258,3 @@ out: up_read(&uts_sem); return err; } - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - long __res; - register long __g1 __asm__ ("g1") = __NR_execve; - register long __o0 __asm__ ("o0") = (long)(filename); - register long __o1 __asm__ ("o1") = (long)(argv); - register long __o2 __asm__ ("o2") = (long)(envp); - asm volatile ("t 0x10\n\t" - "bcc 1f\n\t" - "mov %%o0, %0\n\t" - "sub %%g0, %%o0, %0\n\t" - "1:\n\t" - : "=r" (__res), "=&r" (__o0) - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) - : "cc"); - return __res; -} diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 11c6c9603e7..51b85feb8b9 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -730,24 +730,7 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, return ret; } -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) +asmlinkage long sys_kern_features(void) { - long __res; - register long __g1 __asm__ ("g1") = __NR_execve; - register long __o0 __asm__ ("o0") = (long)(filename); - register long __o1 __asm__ ("o1") = (long)(argv); - register long __o2 __asm__ ("o2") = (long)(envp); - asm volatile ("t 0x6d\n\t" - "sub %%g0, %%o0, %0\n\t" - "movcc %%xcc, %%o0, %0\n\t" - : "=r" (__res), "=&r" (__o0) - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) - : "cc"); - return __res; + return KERN_FEATURE_MIXED_MODE_STACK; } diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index 7f5f65d0b3f..2ef41e67f0b 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -1,23 +1,19 @@ /* SunOS's execv() call only specifies the argv argument, the * environment settings are the same as the calling processes. */ -sys_execve: - sethi %hi(sparc_execve), %g1 - ba,pt %xcc, execve_merge - or %g1, %lo(sparc_execve), %g1 +sys64_execve: + set sys_execve, %g1 + jmpl %g1, %g0 + flushw #ifdef CONFIG_COMPAT sunos_execv: - stx %g0, [%sp + PTREGS_OFF + PT_V9_I2] + mov %g0, %o2 sys32_execve: - sethi %hi(sparc32_execve), %g1 - or %g1, %lo(sparc32_execve), %g1 -#endif - -execve_merge: - flushw + set compat_sys_execve, %g1 jmpl %g1, %g0 - add %sp, PTREGS_OFF, %o0 + flushw +#endif .align 32 sys_sparc_pipe: @@ -112,11 +108,16 @@ sys_clone: ret_from_syscall: /* Clear current_thread_info()->new_child. */ stb %g0, [%g6 + TI_NEW_CHILD] - ldx [%g6 + TI_FLAGS], %l0 call schedule_tail mov %g7, %o0 + ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 + brnz,pt %o0, ret_sys_call + ldx [%g6 + TI_FLAGS], %l0 + ldx [%sp + PTREGS_OFF + PT_V9_G1], %l1 + call %l1 + ldx [%sp + PTREGS_OFF + PT_V9_G2], %o0 ba,pt %xcc, ret_sys_call - ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 + mov 0, %o0 .globl sparc_exit .type sparc_exit,#function @@ -222,7 +223,6 @@ ret_sys_call: ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc 2: - stb %g0, [%g6 + TI_SYS_NOERROR] /* System call success, clear Carry condition code. */ andn %g3, %g2, %g3 3: diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 63402f9e9f5..5147f574f12 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S @@ -85,3 +85,4 @@ sys_call_table: /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime /*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev +/*340*/ .long sys_ni_syscall, sys_kcmp diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 3a58e0d66f5..ebb7f5fc58f 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -86,6 +86,7 @@ sys_call_table32: .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init /*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev +/*340*/ .word sys_kern_features, sys_kcmp #endif /* CONFIG_COMPAT */ @@ -106,7 +107,7 @@ sys_call_table: /*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid /*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl - .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve + .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys64_execve /*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall /*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect @@ -163,3 +164,4 @@ sys_call_table: .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev +/*340*/ .word sys_kern_features, sys_kcmp diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index b66a77968f3..e7ecf1507d9 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -2688,8 +2688,8 @@ void __init trap_init(void) TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) || TI_NEW_CHILD != offsetof(struct thread_info, new_child) || - TI_SYS_NOERROR != offsetof(struct thread_info, - syscall_noerror) || + TI_CURRENT_DS != offsetof(struct thread_info, + current_ds) || TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) || TI_KUNA_REGS != offsetof(struct thread_info, diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c index f81d038f734..8201c25e766 100644 --- a/arch/sparc/kernel/unaligned_64.c +++ b/arch/sparc/kernel/unaligned_64.c @@ -113,21 +113,24 @@ static inline long sign_extend_imm13(long imm) static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) { - unsigned long value; + unsigned long value, fp; if (reg < 16) return (!reg ? 0 : regs->u_regs[reg]); + + fp = regs->u_regs[UREG_FP]; + if (regs->tstate & TSTATE_PRIV) { struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window *)(fp + STACK_BIAS); value = win->locals[reg - 16]; - } else if (test_thread_flag(TIF_32BIT)) { + } else if (!test_thread_64bit_stack(fp)) { struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp)); get_user(value, &win32->locals[reg - 16]); } else { struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window __user *)(fp + STACK_BIAS); get_user(value, &win->locals[reg - 16]); } return value; @@ -135,19 +138,24 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) { + unsigned long fp; + if (reg < 16) return ®s->u_regs[reg]; + + fp = regs->u_regs[UREG_FP]; + if (regs->tstate & TSTATE_PRIV) { struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window *)(fp + STACK_BIAS); return &win->locals[reg - 16]; - } else if (test_thread_flag(TIF_32BIT)) { + } else if (!test_thread_64bit_stack(fp)) { struct reg_window32 *win32; - win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 *)((unsigned long)((u32)fp)); return (unsigned long *)&win32->locals[reg - 16]; } else { struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window *)(fp + STACK_BIAS); return &win->locals[reg - 16]; } } @@ -392,13 +400,15 @@ int handle_popc(u32 insn, struct pt_regs *regs) if (rd) regs->u_regs[rd] = ret; } else { - if (test_thread_flag(TIF_32BIT)) { + unsigned long fp = regs->u_regs[UREG_FP]; + + if (!test_thread_64bit_stack(fp)) { struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp)); put_user(ret, &win32->locals[rd - 16]); } else { struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window __user *)(fp + STACK_BIAS); put_user(ret, &win->locals[rd - 16]); } } @@ -554,7 +564,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs) reg[0] = 0; if ((insn & 0x780000) == 0x180000) reg[1] = 0; - } else if (test_thread_flag(TIF_32BIT)) { + } else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) { put_user(0, (int __user *) reg); if ((insn & 0x780000) == 0x180000) put_user(0, ((int __user *) reg) + 1); diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c index 08e074b7eb6..c096c624ac4 100644 --- a/arch/sparc/kernel/visemul.c +++ b/arch/sparc/kernel/visemul.c @@ -149,21 +149,24 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2, static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) { - unsigned long value; + unsigned long value, fp; if (reg < 16) return (!reg ? 0 : regs->u_regs[reg]); + + fp = regs->u_regs[UREG_FP]; + if (regs->tstate & TSTATE_PRIV) { struct reg_window *win; - win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window *)(fp + STACK_BIAS); value = win->locals[reg - 16]; - } else if (test_thread_flag(TIF_32BIT)) { + } else if (!test_thread_64bit_stack(fp)) { struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp)); get_user(value, &win32->locals[reg - 16]); } else { struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window __user *)(fp + STACK_BIAS); get_user(value, &win->locals[reg - 16]); } return value; @@ -172,16 +175,18 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs) static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg, struct pt_regs *regs) { + unsigned long fp = regs->u_regs[UREG_FP]; + BUG_ON(reg < 16); BUG_ON(regs->tstate & TSTATE_PRIV); - if (test_thread_flag(TIF_32BIT)) { + if (!test_thread_64bit_stack(fp)) { struct reg_window32 __user *win32; - win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); + win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp)); return (unsigned long __user *)&win32->locals[reg - 16]; } else { struct reg_window __user *win; - win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS); + win = (struct reg_window __user *)(fp + STACK_BIAS); return &win->locals[reg - 16]; } } @@ -204,7 +209,7 @@ static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd) } else { unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs); - if (test_thread_flag(TIF_32BIT)) + if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) __put_user((u32)val, (u32 __user *)rd_user); else __put_user(val, rd_user); diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 89c2c29f154..0bacceb1915 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -132,6 +132,11 @@ SECTIONS *(.popc_6insn_patch) __popc_6insn_patch_end = .; } + .pause_3insn_patch : { + __pause_3insn_patch = .; + *(.pause_3insn_patch) + __pause_3insn_patch_end = .; + } PERCPU_SECTION(SMP_CACHE_BYTES) . = ALIGN(PAGE_SIZE); diff --git a/arch/sparc/kernel/winfixup.S b/arch/sparc/kernel/winfixup.S index a6b0863c27d..1e67ce95836 100644 --- a/arch/sparc/kernel/winfixup.S +++ b/arch/sparc/kernel/winfixup.S @@ -43,6 +43,8 @@ spill_fixup_mna: spill_fixup_dax: TRAP_LOAD_THREAD_REG(%g6, %g1) ldx [%g6 + TI_FLAGS], %g1 + andcc %sp, 0x1, %g0 + movne %icc, 0, %g1 andcc %g1, _TIF_32BIT, %g0 ldub [%g6 + TI_WSAVED], %g1 sll %g1, 3, %g3 diff --git a/arch/sparc/lib/atomic_64.S b/arch/sparc/lib/atomic_64.S index 4d502da3de7..85c233d0a34 100644 --- a/arch/sparc/lib/atomic_64.S +++ b/arch/sparc/lib/atomic_64.S @@ -1,6 +1,6 @@ /* atomic.S: These things are too big to do inline. * - * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) + * Copyright (C) 1999, 2007 2012 David S. Miller (davem@davemloft.net) */ #include <linux/linkage.h> @@ -117,3 +117,17 @@ ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */ sub %g1, %o0, %o0 2: BACKOFF_SPIN(%o2, %o3, 1b) ENDPROC(atomic64_sub_ret) + +ENTRY(atomic64_dec_if_positive) /* %o0 = atomic_ptr */ + BACKOFF_SETUP(%o2) +1: ldx [%o0], %g1 + brlez,pn %g1, 3f + sub %g1, 1, %g7 + casx [%o0], %g1, %g7 + cmp %g1, %g7 + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) + nop +3: retl + sub %g1, 1, %o0 +2: BACKOFF_SPIN(%o2, %o3, 1b) +ENDPROC(atomic64_dec_if_positive) diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c index ee31b884c61..0c4e35e522f 100644 --- a/arch/sparc/lib/ksyms.c +++ b/arch/sparc/lib/ksyms.c @@ -116,6 +116,7 @@ EXPORT_SYMBOL(atomic64_add); EXPORT_SYMBOL(atomic64_add_ret); EXPORT_SYMBOL(atomic64_sub); EXPORT_SYMBOL(atomic64_sub_ret); +EXPORT_SYMBOL(atomic64_dec_if_positive); /* Atomic bit operations. */ EXPORT_SYMBOL(test_and_set_bit); diff --git a/arch/sparc/math-emu/math_64.c b/arch/sparc/math-emu/math_64.c index 1704068da92..034aadbff03 100644 --- a/arch/sparc/math-emu/math_64.c +++ b/arch/sparc/math-emu/math_64.c @@ -320,7 +320,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap) XR = 0; else if (freg < 16) XR = regs->u_regs[freg]; - else if (test_thread_flag(TIF_32BIT)) { + else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) { struct reg_window32 __user *win32; flushw_user (); win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP])); diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 9e28a118e6a..85be1ca539b 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -624,7 +624,7 @@ static void __init inherit_prom_mappings(void) void prom_world(int enter) { if (!enter) - set_fs((mm_segment_t) { get_thread_current_ds() }); + set_fs(get_fs()); __asm__ __volatile__("flushw"); } diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S index 874162a11ce..f8e13d421fc 100644 --- a/arch/sparc/mm/ultra.S +++ b/arch/sparc/mm/ultra.S @@ -481,8 +481,8 @@ xcall_sync_tick: .globl xcall_fetch_glob_regs xcall_fetch_glob_regs: - sethi %hi(global_reg_snapshot), %g1 - or %g1, %lo(global_reg_snapshot), %g1 + sethi %hi(global_cpu_snapshot), %g1 + or %g1, %lo(global_cpu_snapshot), %g1 __GET_CPUID(%g2) sllx %g2, 6, %g3 add %g1, %g3, %g1 @@ -509,6 +509,66 @@ xcall_fetch_glob_regs: stx %g3, [%g1 + GR_SNAP_THREAD] retry + .globl xcall_fetch_glob_pmu +xcall_fetch_glob_pmu: + sethi %hi(global_cpu_snapshot), %g1 + or %g1, %lo(global_cpu_snapshot), %g1 + __GET_CPUID(%g2) + sllx %g2, 6, %g3 + add %g1, %g3, %g1 + rd %pic, %g7 + stx %g7, [%g1 + (4 * 8)] + rd %pcr, %g7 + stx %g7, [%g1 + (0 * 8)] + retry + + .globl xcall_fetch_glob_pmu_n4 +xcall_fetch_glob_pmu_n4: + sethi %hi(global_cpu_snapshot), %g1 + or %g1, %lo(global_cpu_snapshot), %g1 + __GET_CPUID(%g2) + sllx %g2, 6, %g3 + add %g1, %g3, %g1 + + ldxa [%g0] ASI_PIC, %g7 + stx %g7, [%g1 + (4 * 8)] + mov 0x08, %g3 + ldxa [%g3] ASI_PIC, %g7 + stx %g7, [%g1 + (5 * 8)] + mov 0x10, %g3 + ldxa [%g3] ASI_PIC, %g7 + stx %g7, [%g1 + (6 * 8)] + mov 0x18, %g3 + ldxa [%g3] ASI_PIC, %g7 + stx %g7, [%g1 + (7 * 8)] + + mov %o0, %g2 + mov %o1, %g3 + mov %o5, %g7 + + mov HV_FAST_VT_GET_PERFREG, %o5 + mov 3, %o0 + ta HV_FAST_TRAP + stx %o1, [%g1 + (3 * 8)] + mov HV_FAST_VT_GET_PERFREG, %o5 + mov 2, %o0 + ta HV_FAST_TRAP + stx %o1, [%g1 + (2 * 8)] + mov HV_FAST_VT_GET_PERFREG, %o5 + mov 1, %o0 + ta HV_FAST_TRAP + stx %o1, [%g1 + (1 * 8)] + mov HV_FAST_VT_GET_PERFREG, %o5 + mov 0, %o0 + ta HV_FAST_TRAP + stx %o1, [%g1 + (0 * 8)] + + mov %g2, %o0 + mov %g3, %o1 + mov %g7, %o5 + + retry + #ifdef DCACHE_ALIASING_POSSIBLE .align 32 .globl xcall_flush_dcache_page_cheetah diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index 875d008828b..ea7f61e8bc9 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig @@ -21,6 +21,8 @@ config TILE select ARCH_HAVE_NMI_SAFE_CMPXCHG select GENERIC_CLOCKEVENTS select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE # FIXME: investigate whether we need/want these options. # select HAVE_IOREMAP_PROT diff --git a/arch/tile/Makefile b/arch/tile/Makefile index 55640cf9259..3d15364c607 100644 --- a/arch/tile/Makefile +++ b/arch/tile/Makefile @@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH)) endif endif +# The tile compiler may emit .eh_frame information for backtracing. +# In kernel modules, this causes load failures due to unsupported relocations. +KBUILD_CFLAGS += -fno-asynchronous-unwind-tables + ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"") KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS) endif diff --git a/arch/tile/include/arch/Kbuild b/arch/tile/include/arch/Kbuild index e69de29bb2d..3751c9fabcf 100644 --- a/arch/tile/include/arch/Kbuild +++ b/arch/tile/include/arch/Kbuild @@ -0,0 +1 @@ +# Tile arch headers diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index c68808a09da..6948015e08a 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild @@ -1,8 +1,6 @@ header-y += ../arch/ -header-y += ucontext.h - generic-y += bug.h generic-y += bugs.h generic-y += clkdev.h @@ -37,5 +35,4 @@ generic-y += statfs.h generic-y += termbits.h generic-y += termios.h generic-y += types.h -generic-y += ucontext.h generic-y += xor.h diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h index 3063e6fc8da..ca61fb4296b 100644 --- a/arch/tile/include/asm/compat.h +++ b/arch/tile/include/asm/compat.h @@ -275,18 +275,14 @@ extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, struct compat_sigaction; struct compat_siginfo; struct compat_sigaltstack; -long compat_sys_execve(const char __user *path, - compat_uptr_t __user *argv, - compat_uptr_t __user *envp, struct pt_regs *); long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, struct compat_sigaction __user *oact, size_t sigsetsize); long compat_sys_rt_sigqueueinfo(int pid, int sig, struct compat_siginfo __user *uinfo); -long compat_sys_rt_sigreturn(struct pt_regs *); +long compat_sys_rt_sigreturn(void); long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, - struct compat_sigaltstack __user *uoss_ptr, - struct pt_regs *); + struct compat_sigaltstack __user *uoss_ptr); long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high); long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high); long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, @@ -303,12 +299,7 @@ long compat_sys_fallocate(int fd, int mode, long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval); -/* These are the intvec_64.S trampolines. */ -long _compat_sys_execve(const char __user *path, - const compat_uptr_t __user *argv, - const compat_uptr_t __user *envp); -long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, - struct compat_sigaltstack __user *uoss_ptr); +/* Assembly trampoline to avoid clobbering r0. */ long _compat_sys_rt_sigreturn(void); #endif /* _ASM_TILE_COMPAT_H */ diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h index f8ccf08f693..b73e1039c91 100644 --- a/arch/tile/include/asm/elf.h +++ b/arch/tile/include/asm/elf.h @@ -148,6 +148,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm, #define compat_start_thread(regs, ip, usp) do { \ regs->pc = ptr_to_compat_reg((void *)(ip)); \ regs->sp = ptr_to_compat_reg((void *)(usp)); \ + single_step_execve(); \ } while (0) /* diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index 8c4dd9ff91e..879073e7658 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h @@ -211,6 +211,7 @@ static inline void start_thread(struct pt_regs *regs, { regs->pc = pc; regs->sp = usp; + single_step_execve(); } /* Free all resources held by a thread. */ @@ -239,6 +240,9 @@ unsigned long get_wchan(struct task_struct *p); #define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA) #define task_pt_regs(task) \ ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1) +#define current_pt_regs() \ + ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \ + (KSTK_PTREGS_GAP - 1)) - 1) #define task_sp(task) (task_pt_regs(task)->sp) #define task_pc(task) (task_pt_regs(task)->pc) /* Aliases for pc and sp (used in fs/proc/array.c) */ diff --git a/arch/tile/include/asm/switch_to.h b/arch/tile/include/asm/switch_to.h index 1d48c5fee8b..b8f888cbe6b 100644 --- a/arch/tile/include/asm/switch_to.h +++ b/arch/tile/include/asm/switch_to.h @@ -68,7 +68,10 @@ extern unsigned long get_switch_to_pc(void); /* Support function for forking a new task. */ void ret_from_fork(void); -/* Called from ret_from_fork() when a new process starts up. */ +/* Support function for forking a new kernel thread. */ +void ret_from_kernel_thread(void *fn, void *arg); + +/* Called from ret_from_xxx() when a new process starts up. */ struct task_struct *sim_notify_fork(struct task_struct *prev); #endif /* !__ASSEMBLY__ */ diff --git a/arch/tile/include/asm/syscalls.h b/arch/tile/include/asm/syscalls.h index 06f0464cfed..369696d63e7 100644 --- a/arch/tile/include/asm/syscalls.h +++ b/arch/tile/include/asm/syscalls.h @@ -51,8 +51,7 @@ long sys_cacheflush(unsigned long addr, unsigned long len, #ifndef __tilegx__ /* mm/fault.c */ -long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); -long _sys_cmpxchg_badaddr(unsigned long address); +long sys_cmpxchg_badaddr(unsigned long address); #endif #ifdef CONFIG_COMPAT @@ -63,14 +62,23 @@ long sys_truncate64(const char __user *path, loff_t length); long sys_ftruncate64(unsigned int fd, loff_t length); #endif +/* Provide versions of standard syscalls that use current_pt_regs(). */ +long sys_clone(unsigned long clone_flags, unsigned long newsp, + void __user *parent_tid, void __user *child_tid); +long sys_execve(const char __user *filename, + const char __user *const __user *argv, + const char __user *const __user *envp); +long sys_rt_sigreturn(void); +long sys_sigaltstack(const stack_t __user *, stack_t __user *); +#define sys_clone sys_clone +#define sys_execve sys_execve +#define sys_rt_sigreturn sys_rt_sigreturn +#define sys_sigaltstack sys_sigaltstack + /* These are the intvec*.S trampolines. */ -long _sys_sigaltstack(const stack_t __user *, stack_t __user *); long _sys_rt_sigreturn(void); long _sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid); -long _sys_execve(const char __user *filename, - const char __user *const __user *argv, - const char __user *const __user *envp); #include <asm-generic/syscalls.h> diff --git a/arch/tile/include/asm/unistd.h b/arch/tile/include/asm/unistd.h index 6e032a0a268..dab827dc8ac 100644 --- a/arch/tile/include/asm/unistd.h +++ b/arch/tile/include/asm/unistd.h @@ -16,4 +16,5 @@ #define __ARCH_WANT_SYS_LLSEEK #endif #define __ARCH_WANT_SYS_NEWFSTATAT +#define __ARCH_WANT_SYS_EXECVE #include <uapi/asm/unistd.h> diff --git a/arch/tile/include/uapi/asm/Kbuild b/arch/tile/include/uapi/asm/Kbuild index 5c6915fd30b..c20db8e428b 100644 --- a/arch/tile/include/uapi/asm/Kbuild +++ b/arch/tile/include/uapi/asm/Kbuild @@ -15,4 +15,7 @@ header-y += siginfo.h header-y += signal.h header-y += stat.h header-y += swab.h +header-y += ucontext.h header-y += unistd.h + +generic-y += ucontext.h diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c index d67459b9ac2..a2e805569d5 100644 --- a/arch/tile/kernel/compat.c +++ b/arch/tile/kernel/compat.c @@ -102,10 +102,9 @@ long compat_sys_sched_rr_get_interval(compat_pid_t pid, #define compat_sys_fadvise64_64 sys32_fadvise64_64 #define compat_sys_readahead sys32_readahead -/* Call the trampolines to manage pt_regs where necessary. */ -#define compat_sys_execve _compat_sys_execve -#define compat_sys_sigaltstack _compat_sys_sigaltstack +/* Call the assembly trampolines where necessary. */ #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn +#undef sys_clone #define sys_clone _sys_clone /* diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 08b4fe1717b..2e4cc69224a 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c @@ -197,8 +197,7 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) } long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, - struct compat_sigaltstack __user *uoss_ptr, - struct pt_regs *regs) + struct compat_sigaltstack __user *uoss_ptr) { stack_t uss, uoss; int ret; @@ -219,7 +218,7 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, set_fs(KERNEL_DS); ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL, (stack_t __user __force *)&uoss, - (unsigned long)compat_ptr(regs->sp)); + (unsigned long)compat_ptr(current_pt_regs()->sp)); set_fs(seg); if (ret >= 0 && uoss_ptr) { if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) || @@ -232,8 +231,9 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, } /* The assembly shim for this function arranges to ignore the return value. */ -long compat_sys_rt_sigreturn(struct pt_regs *regs) +long compat_sys_rt_sigreturn(void) { + struct pt_regs *regs = current_pt_regs(); struct compat_rt_sigframe __user *frame = (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); sigset_t set; @@ -248,7 +248,7 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs) if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; - if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) + if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) == -EFAULT) goto badframe; return 0; diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S index c31637baff2..f116cb0bce2 100644 --- a/arch/tile/kernel/entry.S +++ b/arch/tile/kernel/entry.S @@ -28,17 +28,6 @@ STD_ENTRY(current_text_addr) STD_ENDPROC(current_text_addr) /* - * Implement execve(). The i386 code has a note that forking from kernel - * space results in no copy on write until the execve, so we should be - * careful not to write to the stack here. - */ -STD_ENTRY(kernel_execve) - moveli TREG_SYSCALL_NR_NAME, __NR_execve - swint1 - jrp lr - STD_ENDPROC(kernel_execve) - -/* * We don't run this function directly, but instead copy it to a page * we map into every user process. See vdso_setup(). * diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index 6943515100f..f212bf7cea8 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S @@ -1291,6 +1291,21 @@ STD_ENTRY(ret_from_fork) } STD_ENDPROC(ret_from_fork) +STD_ENTRY(ret_from_kernel_thread) + jal sim_notify_fork + jal schedule_tail + FEEDBACK_REENTER(ret_from_fork) + { + move r0, r31 + jalr r30 + } + FEEDBACK_REENTER(ret_from_kernel_thread) + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } + STD_ENDPROC(ret_from_kernel_thread) + /* * Code for ill interrupt. */ @@ -1437,15 +1452,6 @@ STD_ENTRY_LOCAL(bad_intr) panic "Unhandled interrupt %#x: PC %#lx" STD_ENDPROC(bad_intr) -/* Put address of pt_regs in reg and jump. */ -#define PTREGS_SYSCALL(x, reg) \ - STD_ENTRY(_##x); \ - { \ - PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ - j x \ - }; \ - STD_ENDPROC(_##x) - /* * Special-case sigreturn to not write r0 to the stack on return. * This is technically more efficient, but it also avoids difficulties @@ -1461,12 +1467,9 @@ STD_ENTRY_LOCAL(bad_intr) }; \ STD_ENDPROC(_##x) -PTREGS_SYSCALL(sys_execve, r3) -PTREGS_SYSCALL(sys_sigaltstack, r2) PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) -PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) -/* Save additional callee-saves to pt_regs, put address in r4 and jump. */ +/* Save additional callee-saves to pt_regs and jump to standard function. */ STD_ENTRY(_sys_clone) push_extra_callee_saves r4 j sys_clone diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S index 7c06d597ffd..54bc9a6678e 100644 --- a/arch/tile/kernel/intvec_64.S +++ b/arch/tile/kernel/intvec_64.S @@ -1150,6 +1150,21 @@ STD_ENTRY(ret_from_fork) } STD_ENDPROC(ret_from_fork) +STD_ENTRY(ret_from_kernel_thread) + jal sim_notify_fork + jal schedule_tail + FEEDBACK_REENTER(ret_from_fork) + { + move r0, r31 + jalr r30 + } + FEEDBACK_REENTER(ret_from_kernel_thread) + { + movei r30, 0 /* not an NMI */ + j .Lresume_userspace /* jump into middle of interrupt_return */ + } + STD_ENDPROC(ret_from_kernel_thread) + /* Various stub interrupt handlers and syscall handlers */ STD_ENTRY_LOCAL(_kernel_double_fault) @@ -1166,15 +1181,6 @@ STD_ENTRY_LOCAL(bad_intr) panic "Unhandled interrupt %#x: PC %#lx" STD_ENDPROC(bad_intr) -/* Put address of pt_regs in reg and jump. */ -#define PTREGS_SYSCALL(x, reg) \ - STD_ENTRY(_##x); \ - { \ - PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ - j x \ - }; \ - STD_ENDPROC(_##x) - /* * Special-case sigreturn to not write r0 to the stack on return. * This is technically more efficient, but it also avoids difficulties @@ -1190,16 +1196,12 @@ STD_ENTRY_LOCAL(bad_intr) }; \ STD_ENDPROC(_##x) -PTREGS_SYSCALL(sys_execve, r3) -PTREGS_SYSCALL(sys_sigaltstack, r2) PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) #ifdef CONFIG_COMPAT -PTREGS_SYSCALL(compat_sys_execve, r3) -PTREGS_SYSCALL(compat_sys_sigaltstack, r2) PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0) #endif -/* Save additional callee-saves to pt_regs, put address in r4 and jump. */ +/* Save additional callee-saves to pt_regs and jump to standard function. */ STD_ENTRY(_sys_clone) push_extra_callee_saves r4 j sys_clone diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c index 001cbfa10ac..243ffebe38d 100644 --- a/arch/tile/kernel/module.c +++ b/arch/tile/kernel/module.c @@ -24,16 +24,6 @@ #include <asm/homecache.h> #include <arch/opcode.h> -#ifdef __tilegx__ -# define Elf_Rela Elf64_Rela -# define ELF_R_SYM ELF64_R_SYM -# define ELF_R_TYPE ELF64_R_TYPE -#else -# define Elf_Rela Elf32_Rela -# define ELF_R_SYM ELF32_R_SYM -# define ELF_R_TYPE ELF32_R_TYPE -#endif - #ifdef MODULE_DEBUG #define DEBUGP printk #else diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 307d010696c..1c20029d2f5 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -157,24 +157,44 @@ void arch_release_thread_info(struct thread_info *info) static void save_arch_state(struct thread_struct *t); int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long stack_size, - struct task_struct *p, struct pt_regs *regs) + unsigned long arg, + struct task_struct *p, struct pt_regs *unused) { - struct pt_regs *childregs; + struct pt_regs *childregs = task_pt_regs(p); unsigned long ksp; + unsigned long *callee_regs; /* - * When creating a new kernel thread we pass sp as zero. - * Assign it to a reasonable value now that we have the stack. + * Set up the stack and stack pointer appropriately for the + * new child to find itself woken up in __switch_to(). + * The callee-saved registers must be on the stack to be read; + * the new task will then jump to assembly support to handle + * calling schedule_tail(), etc., and (for userspace tasks) + * returning to the context set up in the pt_regs. */ - if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0)) - sp = KSTK_TOP(p); + ksp = (unsigned long) childregs; + ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ + ((long *)ksp)[0] = ((long *)ksp)[1] = 0; + ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); + callee_regs = (unsigned long *)ksp; + ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ + ((long *)ksp)[0] = ((long *)ksp)[1] = 0; + p->thread.ksp = ksp; - /* - * Do not clone step state from the parent; each thread - * must make its own lazily. - */ - task_thread_info(p)->step_state = NULL; + /* Record the pid of the task that created this one. */ + p->thread.creator_pid = current->pid; + + if (unlikely(p->flags & PF_KTHREAD)) { + /* kernel thread */ + memset(childregs, 0, sizeof(struct pt_regs)); + memset(&callee_regs[2], 0, + (CALLEE_SAVED_REGS_COUNT - 2) * sizeof(unsigned long)); + callee_regs[0] = sp; /* r30 = function */ + callee_regs[1] = arg; /* r31 = arg */ + childregs->ex1 = PL_ICS_EX1(KERNEL_PL, 0); + p->thread.pc = (unsigned long) ret_from_kernel_thread; + return 0; + } /* * Start new thread in ret_from_fork so it schedules properly @@ -182,46 +202,33 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, */ p->thread.pc = (unsigned long) ret_from_fork; - /* Save user stack top pointer so we can ID the stack vm area later. */ - p->thread.usp0 = sp; - - /* Record the pid of the process that created this one. */ - p->thread.creator_pid = current->pid; + /* + * Do not clone step state from the parent; each thread + * must make its own lazily. + */ + task_thread_info(p)->step_state = NULL; /* * Copy the registers onto the kernel stack so the * return-from-interrupt code will reload it into registers. */ - childregs = task_pt_regs(p); - *childregs = *regs; + *childregs = *current_pt_regs(); childregs->regs[0] = 0; /* return value is zero */ - childregs->sp = sp; /* override with new user stack pointer */ + if (sp) + childregs->sp = sp; /* override with new user stack pointer */ + memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG], + CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); + + /* Save user stack top pointer so we can ID the stack vm area later. */ + p->thread.usp0 = childregs->sp; /* * If CLONE_SETTLS is set, set "tp" in the new task to "r4", * which is passed in as arg #5 to sys_clone(). */ if (clone_flags & CLONE_SETTLS) - childregs->tp = regs->regs[4]; + childregs->tp = childregs->regs[4]; - /* - * Copy the callee-saved registers from the passed pt_regs struct - * into the context-switch callee-saved registers area. - * This way when we start the interrupt-return sequence, the - * callee-save registers will be correctly in registers, which - * is how we assume the compiler leaves them as we start doing - * the normal return-from-interrupt path after calling C code. - * Zero out the C ABI save area to mark the top of the stack. - */ - ksp = (unsigned long) childregs; - ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ - ((long *)ksp)[0] = ((long *)ksp)[1] = 0; - ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); - memcpy((void *)ksp, ®s->regs[CALLEE_SAVED_FIRST_REG], - CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); - ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ - ((long *)ksp)[0] = ((long *)ksp)[1] = 0; - p->thread.ksp = ksp; #if CHIP_HAS_TILE_DMA() /* @@ -578,61 +585,13 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) } /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ -SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, - void __user *, parent_tidptr, void __user *, child_tidptr, - struct pt_regs *, regs) +SYSCALL_DEFINE4(clone, unsigned long, clone_flags, unsigned long, newsp, + void __user *, parent_tidptr, void __user *, child_tidptr) { - if (!newsp) - newsp = regs->sp; - return do_fork(clone_flags, newsp, regs, 0, + return do_fork(clone_flags, newsp, current_pt_regs(), 0, parent_tidptr, child_tidptr); } -/* - * sys_execve() executes a new program. - */ -SYSCALL_DEFINE4(execve, const char __user *, path, - const char __user *const __user *, argv, - const char __user *const __user *, envp, - struct pt_regs *, regs) -{ - long error; - struct filename *filename; - - filename = getname(path); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename->name, argv, envp, regs); - putname(filename); - if (error == 0) - single_step_execve(); -out: - return error; -} - -#ifdef CONFIG_COMPAT -long compat_sys_execve(const char __user *path, - compat_uptr_t __user *argv, - compat_uptr_t __user *envp, - struct pt_regs *regs) -{ - long error; - struct filename *filename; - - filename = getname(path); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = compat_do_execve(filename->name, argv, envp, regs); - putname(filename); - if (error == 0) - single_step_execve(); -out: - return error; -} -#endif - unsigned long get_wchan(struct task_struct *p) { struct KBacktraceIterator kbt; @@ -650,37 +609,6 @@ unsigned long get_wchan(struct task_struct *p) return 0; } -/* - * We pass in lr as zero (cleared in kernel_thread) and the caller - * part of the backtrace ABI on the stack also zeroed (in copy_thread) - * so that backtraces will stop with this function. - * Note that we don't use r0, since copy_thread() clears it. - */ -static void start_kernel_thread(int dummy, int (*fn)(int), int arg) -{ - do_exit(fn(arg)); -} - -/* - * Create a kernel thread - */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0); /* run at kernel PL, no ICS */ - regs.pc = (long) start_kernel_thread; - regs.flags = PT_FLAGS_CALLER_SAVES; /* need to restore r1 and r2 */ - regs.regs[1] = (long) fn; /* function pointer */ - regs.regs[2] = (long) arg; /* parameter register */ - - /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, - 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - /* Flush thread state. */ void flush_thread(void) { diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index 67efb656d10..657a7ace4ab 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c @@ -37,10 +37,10 @@ #define DEBUG_SIG 0 -SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, - stack_t __user *, uoss, struct pt_regs *, regs) +SYSCALL_DEFINE2(sigaltstack, const stack_t __user *, uss, + stack_t __user *, uoss) { - return do_sigaltstack(uss, uoss, regs->sp); + return do_sigaltstack(uss, uoss, current_pt_regs()->sp); } @@ -83,8 +83,9 @@ void signal_fault(const char *type, struct pt_regs *regs, } /* The assembly shim for this function arranges to ignore the return value. */ -SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) +SYSCALL_DEFINE0(rt_sigreturn) { + struct pt_regs *regs = current_pt_regs(); struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->sp); sigset_t set; diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c index b08095b402d..02ff5c0ef77 100644 --- a/arch/tile/kernel/sys.c +++ b/arch/tile/kernel/sys.c @@ -106,14 +106,11 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, #define sys_readahead sys32_readahead #endif -/* Call the trampolines to manage pt_regs where necessary. */ -#define sys_execve _sys_execve -#define sys_sigaltstack _sys_sigaltstack +/* Call the assembly trampolines where necessary. */ +#undef sys_rt_sigreturn #define sys_rt_sigreturn _sys_rt_sigreturn +#undef sys_clone #define sys_clone _sys_clone -#ifndef __tilegx__ -#define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr -#endif /* * Note that we can't include <linux/unistd.h> here since the header diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c index fe811fa5f1b..3d2b81c163a 100644 --- a/arch/tile/mm/fault.c +++ b/arch/tile/mm/fault.c @@ -70,9 +70,10 @@ static noinline void force_sig_info_fault(const char *type, int si_signo, * Synthesize the fault a PL0 process would get by doing a word-load of * an unaligned address or a high kernel address. */ -SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address, - struct pt_regs *, regs) +SYSCALL_DEFINE1(cmpxchg_badaddr, unsigned long, address) { + struct pt_regs *regs = current_pt_regs(); + if (address >= PAGE_OFFSET) force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR, address, INT_DTLB_MISS, current, regs); diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 3a8ece7d09c..0d7103c9eff 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -32,13 +32,14 @@ void flush_thread(void) "err = %d\n", ret); force_sig(SIGKILL, current); } + get_safe_registers(current_pt_regs()->regs.gp, + current_pt_regs()->regs.fp); __switch_mm(¤t->mm->context.id); } void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) { - get_safe_registers(regs->regs.gp, regs->regs.fp); PT_REGS_IP(regs) = eip; PT_REGS_SP(regs) = esp; current->ptrace &= ~PT_DTRACE; diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index b6d699cdd55..c502c804e8b 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -171,7 +171,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, p->thread = (struct thread_struct) INIT_THREAD; if (!kthread) { - memcpy(&p->thread.regs.regs, ®s->regs, + memcpy(&p->thread.regs.regs, current_pt_regs(), sizeof(p->thread.regs.regs)); PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); if (sp != 0) diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index a81f3705e90..3a875226c8e 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -16,23 +16,19 @@ long sys_fork(void) { - return do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), + return do_fork(SIGCHLD, 0, ¤t->thread.regs, 0, NULL, NULL); } long sys_vfork(void) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, - UPT_SP(¤t->thread.regs.regs), + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, ¤t->thread.regs, 0, NULL, NULL); } long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid) { - if (!newsp) - newsp = UPT_SP(¤t->thread.regs.regs); - return do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, child_tid); } diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig index e5c5473e69c..c4fbb21e802 100644 --- a/arch/unicore32/Kconfig +++ b/arch/unicore32/Kconfig @@ -16,6 +16,8 @@ config UNICORE32 select ARCH_WANT_FRAME_POINTERS select GENERIC_IOMAP select MODULES_USE_ELF_REL + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE help UniCore-32 is 32-bit Instruction Set Architecture, including a series of low-power-consumption RISC chip @@ -64,6 +66,9 @@ config GENERIC_CALIBRATE_DELAY config ARCH_MAY_HAVE_PC_FDC bool +config ZONE_DMA + def_bool y + config NEED_DMA_MAP_STATE def_bool y @@ -216,7 +221,7 @@ config PUV3_GPIO bool depends on !ARCH_FPGA select GENERIC_GPIO - select GPIO_SYSFS if EXPERIMENTAL + select GPIO_SYSFS default y if PUV3_NB0916 diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index c910c9857e1..601e92f18af 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild @@ -1,4 +1,3 @@ -include include/asm-generic/Kbuild.asm generic-y += atomic.h generic-y += auxvec.h diff --git a/arch/unicore32/include/asm/bug.h b/arch/unicore32/include/asm/bug.h index b1ff8cadb08..93a56f3e234 100644 --- a/arch/unicore32/include/asm/bug.h +++ b/arch/unicore32/include/asm/bug.h @@ -19,9 +19,4 @@ extern void die(const char *msg, struct pt_regs *regs, int err); extern void uc32_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, unsigned long err, unsigned long trap); -extern asmlinkage void __backtrace(void); -extern asmlinkage void c_backtrace(unsigned long fp, int pmode); - -extern void __show_regs(struct pt_regs *); - #endif /* __UNICORE_BUG_H__ */ diff --git a/arch/unicore32/include/asm/cmpxchg.h b/arch/unicore32/include/asm/cmpxchg.h index df4d5acfd19..8e797ad4fa2 100644 --- a/arch/unicore32/include/asm/cmpxchg.h +++ b/arch/unicore32/include/asm/cmpxchg.h @@ -35,7 +35,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, : "memory", "cc"); break; default: - ret = __xchg_bad_pointer(); + __xchg_bad_pointer(); } return ret; diff --git a/arch/unicore32/include/asm/kvm_para.h b/arch/unicore32/include/asm/kvm_para.h deleted file mode 100644 index 14fab8f0b95..00000000000 --- a/arch/unicore32/include/asm/kvm_para.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/kvm_para.h> diff --git a/arch/unicore32/include/asm/processor.h b/arch/unicore32/include/asm/processor.h index 14382cb0965..4eaa4216766 100644 --- a/arch/unicore32/include/asm/processor.h +++ b/arch/unicore32/include/asm/processor.h @@ -72,11 +72,6 @@ unsigned long get_wchan(struct task_struct *p); #define cpu_relax() barrier() -/* - * Create a new kernel thread - */ -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); - #define task_pt_regs(p) \ ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) diff --git a/arch/unicore32/include/asm/ptrace.h b/arch/unicore32/include/asm/ptrace.h index b9caf9b0997..726749dab52 100644 --- a/arch/unicore32/include/asm/ptrace.h +++ b/arch/unicore32/include/asm/ptrace.h @@ -12,80 +12,10 @@ #ifndef __UNICORE_PTRACE_H__ #define __UNICORE_PTRACE_H__ -#define PTRACE_GET_THREAD_AREA 22 - -/* - * PSR bits - */ -#define USER_MODE 0x00000010 -#define REAL_MODE 0x00000011 -#define INTR_MODE 0x00000012 -#define PRIV_MODE 0x00000013 -#define ABRT_MODE 0x00000017 -#define EXTN_MODE 0x0000001b -#define SUSR_MODE 0x0000001f -#define MODE_MASK 0x0000001f -#define PSR_R_BIT 0x00000040 -#define PSR_I_BIT 0x00000080 -#define PSR_V_BIT 0x10000000 -#define PSR_C_BIT 0x20000000 -#define PSR_Z_BIT 0x40000000 -#define PSR_S_BIT 0x80000000 - -/* - * Groups of PSR bits - */ -#define PSR_f 0xff000000 /* Flags */ -#define PSR_c 0x000000ff /* Control */ +#include <uapi/asm/ptrace.h> #ifndef __ASSEMBLY__ -/* - * This struct defines the way the registers are stored on the - * stack during a system call. Note that sizeof(struct pt_regs) - * has to be a multiple of 8. - */ -struct pt_regs { - unsigned long uregs[34]; -}; - -#define UCreg_asr uregs[32] -#define UCreg_pc uregs[31] -#define UCreg_lr uregs[30] -#define UCreg_sp uregs[29] -#define UCreg_ip uregs[28] -#define UCreg_fp uregs[27] -#define UCreg_26 uregs[26] -#define UCreg_25 uregs[25] -#define UCreg_24 uregs[24] -#define UCreg_23 uregs[23] -#define UCreg_22 uregs[22] -#define UCreg_21 uregs[21] -#define UCreg_20 uregs[20] -#define UCreg_19 uregs[19] -#define UCreg_18 uregs[18] -#define UCreg_17 uregs[17] -#define UCreg_16 uregs[16] -#define UCreg_15 uregs[15] -#define UCreg_14 uregs[14] -#define UCreg_13 uregs[13] -#define UCreg_12 uregs[12] -#define UCreg_11 uregs[11] -#define UCreg_10 uregs[10] -#define UCreg_09 uregs[9] -#define UCreg_08 uregs[8] -#define UCreg_07 uregs[7] -#define UCreg_06 uregs[6] -#define UCreg_05 uregs[5] -#define UCreg_04 uregs[4] -#define UCreg_03 uregs[3] -#define UCreg_02 uregs[2] -#define UCreg_01 uregs[1] -#define UCreg_00 uregs[0] -#define UCreg_ORIG_00 uregs[33] - -#ifdef __KERNEL__ - #define user_mode(regs) \ (processor_mode(regs) == USER_MODE) @@ -125,9 +55,5 @@ static inline int valid_user_regs(struct pt_regs *regs) #define instruction_pointer(regs) ((regs)->UCreg_pc) -#endif /* __KERNEL__ */ - #endif /* __ASSEMBLY__ */ - #endif - diff --git a/arch/unicore32/include/uapi/asm/Kbuild b/arch/unicore32/include/uapi/asm/Kbuild index baebb3da1d4..0514d7ad685 100644 --- a/arch/unicore32/include/uapi/asm/Kbuild +++ b/arch/unicore32/include/uapi/asm/Kbuild @@ -1,3 +1,10 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm +header-y += byteorder.h +header-y += kvm_para.h +header-y += ptrace.h +header-y += sigcontext.h +header-y += unistd.h + +generic-y += kvm_para.h diff --git a/arch/unicore32/include/asm/byteorder.h b/arch/unicore32/include/uapi/asm/byteorder.h index ebe1b3fef3e..ebe1b3fef3e 100644 --- a/arch/unicore32/include/asm/byteorder.h +++ b/arch/unicore32/include/uapi/asm/byteorder.h diff --git a/arch/unicore32/include/uapi/asm/ptrace.h b/arch/unicore32/include/uapi/asm/ptrace.h new file mode 100644 index 00000000000..187aa2e98a5 --- /dev/null +++ b/arch/unicore32/include/uapi/asm/ptrace.h @@ -0,0 +1,90 @@ +/* + * linux/arch/unicore32/include/asm/ptrace.h + * + * Code specific to PKUnity SoC and UniCore ISA + * + * Copyright (C) 2001-2010 GUAN Xue-tao + * + * 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. + */ +#ifndef _UAPI__UNICORE_PTRACE_H__ +#define _UAPI__UNICORE_PTRACE_H__ + +#define PTRACE_GET_THREAD_AREA 22 + +/* + * PSR bits + */ +#define USER_MODE 0x00000010 +#define REAL_MODE 0x00000011 +#define INTR_MODE 0x00000012 +#define PRIV_MODE 0x00000013 +#define ABRT_MODE 0x00000017 +#define EXTN_MODE 0x0000001b +#define SUSR_MODE 0x0000001f +#define MODE_MASK 0x0000001f +#define PSR_R_BIT 0x00000040 +#define PSR_I_BIT 0x00000080 +#define PSR_V_BIT 0x10000000 +#define PSR_C_BIT 0x20000000 +#define PSR_Z_BIT 0x40000000 +#define PSR_S_BIT 0x80000000 + +/* + * Groups of PSR bits + */ +#define PSR_f 0xff000000 /* Flags */ +#define PSR_c 0x000000ff /* Control */ + +#ifndef __ASSEMBLY__ + +/* + * This struct defines the way the registers are stored on the + * stack during a system call. Note that sizeof(struct pt_regs) + * has to be a multiple of 8. + */ +struct pt_regs { + unsigned long uregs[34]; +}; + +#define UCreg_asr uregs[32] +#define UCreg_pc uregs[31] +#define UCreg_lr uregs[30] +#define UCreg_sp uregs[29] +#define UCreg_ip uregs[28] +#define UCreg_fp uregs[27] +#define UCreg_26 uregs[26] +#define UCreg_25 uregs[25] +#define UCreg_24 uregs[24] +#define UCreg_23 uregs[23] +#define UCreg_22 uregs[22] +#define UCreg_21 uregs[21] +#define UCreg_20 uregs[20] +#define UCreg_19 uregs[19] +#define UCreg_18 uregs[18] +#define UCreg_17 uregs[17] +#define UCreg_16 uregs[16] +#define UCreg_15 uregs[15] +#define UCreg_14 uregs[14] +#define UCreg_13 uregs[13] +#define UCreg_12 uregs[12] +#define UCreg_11 uregs[11] +#define UCreg_10 uregs[10] +#define UCreg_09 uregs[9] +#define UCreg_08 uregs[8] +#define UCreg_07 uregs[7] +#define UCreg_06 uregs[6] +#define UCreg_05 uregs[5] +#define UCreg_04 uregs[4] +#define UCreg_03 uregs[3] +#define UCreg_02 uregs[2] +#define UCreg_01 uregs[1] +#define UCreg_00 uregs[0] +#define UCreg_ORIG_00 uregs[33] + + +#endif /* __ASSEMBLY__ */ + +#endif /* _UAPI__UNICORE_PTRACE_H__ */ diff --git a/arch/unicore32/include/asm/sigcontext.h b/arch/unicore32/include/uapi/asm/sigcontext.h index 6a2d7671c05..6a2d7671c05 100644 --- a/arch/unicore32/include/asm/sigcontext.h +++ b/arch/unicore32/include/uapi/asm/sigcontext.h diff --git a/arch/unicore32/include/asm/unistd.h b/arch/unicore32/include/uapi/asm/unistd.h index 2abcf61c615..d18a3be89b3 100644 --- a/arch/unicore32/include/asm/unistd.h +++ b/arch/unicore32/include/uapi/asm/unistd.h @@ -12,3 +12,4 @@ /* Use the standard ABI for syscalls. */ #include <asm-generic/unistd.h> +#define __ARCH_WANT_SYS_EXECVE diff --git a/arch/unicore32/kernel/entry.S b/arch/unicore32/kernel/entry.S index dcb87ab19dd..7049350c790 100644 --- a/arch/unicore32/kernel/entry.S +++ b/arch/unicore32/kernel/entry.S @@ -573,17 +573,16 @@ ENDPROC(ret_to_user) */ ENTRY(ret_from_fork) b.l schedule_tail - get_thread_info tsk - ldw r1, [tsk+], #TI_FLAGS @ check for syscall tracing - mov why, #1 - cand.a r1, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? - beq ret_slow_syscall - mov r1, sp - mov r0, #1 @ trace exit [IP = 1] - b.l syscall_trace b ret_slow_syscall ENDPROC(ret_from_fork) +ENTRY(ret_from_kernel_thread) + b.l schedule_tail + mov r0, r5 + adr lr, ret_slow_syscall + mov pc, r4 +ENDPROC(ret_from_kernel_thread) + /*============================================================================= * SWI handler *----------------------------------------------------------------------------- @@ -669,11 +668,6 @@ __cr_alignment: #endif .ltorg -ENTRY(sys_execve) - add r3, sp, #S_OFF - b __sys_execve -ENDPROC(sys_execve) - ENTRY(sys_clone) add ip, sp, #S_OFF stw ip, [sp+], #4 diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c index b008586dad7..a8fe265ce2c 100644 --- a/arch/unicore32/kernel/process.c +++ b/arch/unicore32/kernel/process.c @@ -258,6 +258,7 @@ void release_thread(struct task_struct *dead_task) } asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); +asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); int copy_thread(unsigned long clone_flags, unsigned long stack_start, @@ -266,17 +267,22 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, struct thread_info *thread = task_thread_info(p); struct pt_regs *childregs = task_pt_regs(p); - *childregs = *regs; - childregs->UCreg_00 = 0; - childregs->UCreg_sp = stack_start; - memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); thread->cpu_context.sp = (unsigned long)childregs; - thread->cpu_context.pc = (unsigned long)ret_from_fork; - - if (clone_flags & CLONE_SETTLS) - childregs->UCreg_16 = regs->UCreg_03; + if (unlikely(!regs)) { + thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread; + thread->cpu_context.r4 = stack_start; + thread->cpu_context.r5 = stk_sz; + memset(childregs, 0, sizeof(struct pt_regs)); + } else { + thread->cpu_context.pc = (unsigned long)ret_from_fork; + *childregs = *regs; + childregs->UCreg_00 = 0; + childregs->UCreg_sp = stack_start; + if (clone_flags & CLONE_SETTLS) + childregs->UCreg_16 = regs->UCreg_03; + } return 0; } @@ -305,42 +311,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp) } EXPORT_SYMBOL(dump_fpu); -/* - * Shuffle the argument into the correct register before calling the - * thread function. r1 is the thread argument, r2 is the pointer to - * the thread function, and r3 points to the exit function. - */ -asm(".pushsection .text\n" -" .align\n" -" .type kernel_thread_helper, #function\n" -"kernel_thread_helper:\n" -" mov.a asr, r7\n" -" mov r0, r4\n" -" mov lr, r6\n" -" mov pc, r5\n" -" .size kernel_thread_helper, . - kernel_thread_helper\n" -" .popsection"); - -/* - * Create a kernel thread. - */ -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.UCreg_04 = (unsigned long)arg; - regs.UCreg_05 = (unsigned long)fn; - regs.UCreg_06 = (unsigned long)do_exit; - regs.UCreg_07 = PRIV_MODE; - regs.UCreg_pc = (unsigned long)kernel_thread_helper; - regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT; - - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - unsigned long get_wchan(struct task_struct *p) { struct stackframe frame; diff --git a/arch/unicore32/kernel/setup.h b/arch/unicore32/kernel/setup.h index f23955028a1..30f749da8f7 100644 --- a/arch/unicore32/kernel/setup.h +++ b/arch/unicore32/kernel/setup.h @@ -30,4 +30,10 @@ extern char __vectors_start[], __vectors_end[]; extern void kernel_thread_helper(void); extern void __init early_signal_init(void); + +extern asmlinkage void __backtrace(void); +extern asmlinkage void c_backtrace(unsigned long fp, int pmode); + +extern void __show_regs(struct pt_regs *); + #endif diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c index fabdee96110..9680134b31f 100644 --- a/arch/unicore32/kernel/sys.c +++ b/arch/unicore32/kernel/sys.c @@ -42,69 +42,6 @@ asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp, parent_tid, child_tid); } -/* sys_execve() executes a new program. - * This is called indirectly via a small wrapper - */ -asmlinkage long __sys_execve(const char __user *filename, - const char __user *const __user *argv, - const char __user *const __user *envp, - struct pt_regs *regs) -{ - int error; - struct filename *fn; - - fn = getname(filename); - error = PTR_ERR(fn); - if (IS_ERR(fn)) - goto out; - error = do_execve(fn->name, argv, envp, regs); - putname(fn); -out: - return error; -} - -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - struct pt_regs regs; - int ret; - - memset(®s, 0, sizeof(struct pt_regs)); - ret = do_execve(filename, - (const char __user *const __user *)argv, - (const char __user *const __user *)envp, ®s); - if (ret < 0) - goto out; - - /* - * Save argc to the register structure for userspace. - */ - regs.UCreg_00 = ret; - - /* - * We were successful. We won't be returning to our caller, but - * instead to user space by manipulating the kernel stack. - */ - asm("add r0, %0, %1\n\t" - "mov r1, %2\n\t" - "mov r2, %3\n\t" - "mov r22, #0\n\t" /* not a syscall */ - "mov r23, %0\n\t" /* thread structure */ - "b.l memmove\n\t" /* copy regs to top of stack */ - "mov sp, r0\n\t" /* reposition stack pointer */ - "b ret_to_user" - : - : "r" (current_thread_info()), - "Ir" (THREAD_START_SP - sizeof(regs)), - "r" (®s), - "Ir" (sizeof(regs)) - : "r0", "r1", "r2", "r3", "ip", "lr", "memory"); - - out: - return ret; -} - /* Note: used by the compat code even in 64-bit Linux. */ SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, diff --git a/arch/unicore32/mm/fault.c b/arch/unicore32/mm/fault.c index 2eeb9c04cab..f9b5c10bcce 100644 --- a/arch/unicore32/mm/fault.c +++ b/arch/unicore32/mm/fault.c @@ -168,7 +168,7 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma) } static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr, - struct task_struct *tsk) + unsigned int flags, struct task_struct *tsk) { struct vm_area_struct *vma; int fault; @@ -194,14 +194,7 @@ good_area: * 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, addr & PAGE_MASK, - (!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0); - if (unlikely(fault & VM_FAULT_ERROR)) - return fault; - if (fault & VM_FAULT_MAJOR) - tsk->maj_flt++; - else - tsk->min_flt++; + fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, flags); return fault; check_stack: @@ -216,6 +209,8 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs) struct task_struct *tsk; struct mm_struct *mm; int fault, sig, code; + unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | + ((!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0); tsk = current; mm = tsk->mm; @@ -236,6 +231,7 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs) if (!user_mode(regs) && !search_exception_tables(regs->UCreg_pc)) goto no_context; +retry: down_read(&mm->mmap_sem); } else { /* @@ -251,7 +247,28 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs) #endif } - fault = __do_pf(mm, addr, fsr, tsk); + fault = __do_pf(mm, addr, fsr, flags, tsk); + + /* If we need to retry but a fatal signal is pending, handle the + * signal first. We do not need to release the mmap_sem because + * it would already be released in __lock_page_or_retry in + * mm/filemap.c. */ + if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) + return 0; + + if (!(fault & VM_FAULT_ERROR) && (flags & FAULT_FLAG_ALLOW_RETRY)) { + if (fault & VM_FAULT_MAJOR) + tsk->maj_flt++; + else + tsk->min_flt++; + if (fault & VM_FAULT_RETRY) { + /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk + * of starvation. */ + flags &= ~FAULT_FLAG_ALLOW_RETRY; + goto retry; + } + } + up_read(&mm->mmap_sem); /* diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 58790bd85c1..05afcca66de 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -142,7 +142,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,) KBUILD_CFLAGS += $(mflags-y) KBUILD_AFLAGS += $(mflags-y) -archscripts: +archscripts: scripts_basic $(Q)$(MAKE) $(build)=arch/x86/tools relocs ### diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index c760e073963..e87b0cac14b 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -12,6 +12,8 @@ #include <asm/setup.h> #include <asm/desc.h> +#undef memcpy /* Use memcpy from misc.c */ + #include "eboot.h" static efi_system_table_t *sys_table; diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 2a017441b8b..8c132a625b9 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -476,6 +476,3 @@ die: setup_corrupt: .byte 7 .string "No setup signature found...\n" - - .data -dummy: .long 0 diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 7c04d0da709..1b9c22bea8a 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -515,6 +515,11 @@ static int xts_aesni_setkey(struct crypto_tfm *tfm, const u8 *key, } +static void aesni_xts_tweak(void *ctx, u8 *out, const u8 *in) +{ + aesni_enc(ctx, out, in); +} + static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes) { @@ -525,7 +530,7 @@ static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, .tbuflen = sizeof(buf), .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx), - .tweak_fn = XTS_TWEAK_CAST(aesni_enc), + .tweak_fn = aesni_xts_tweak, .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx), .crypt_fn = lrw_xts_encrypt_callback, }; @@ -550,7 +555,7 @@ static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, .tbuflen = sizeof(buf), .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx), - .tweak_fn = XTS_TWEAK_CAST(aesni_enc), + .tweak_fn = aesni_xts_tweak, .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx), .crypt_fn = lrw_xts_decrypt_callback, }; diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index c9dcc181d4d..6e8fdf5ad11 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -35,7 +35,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...); #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \ efi_call_virt(f, a1, a2, a3, a4, a5, a6) -#define efi_ioremap(addr, size, type) ioremap_cache(addr, size) +#define efi_ioremap(addr, size, type, attr) ioremap_cache(addr, size) #else /* !CONFIG_X86_32 */ @@ -89,7 +89,7 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3, (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6)) extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, - u32 type); + u32 type, u64 attribute); #endif /* CONFIG_X86_32 */ @@ -98,6 +98,8 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable); extern int efi_memblock_x86_reserve_range(void); extern void efi_call_phys_prelog(void); extern void efi_call_phys_epilog(void); +extern void efi_unmap_memmap(void); +extern void efi_memory_uc(u64 addr, unsigned long size); #ifndef CONFIG_EFI /* diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index dcfde52979c..19f16ebaf4f 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs) } #endif -/* - * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode - * when it traps. The previous stack will be directly underneath the saved - * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. - * - * This is valid only for kernel mode traps. - */ -static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) -{ #ifdef CONFIG_X86_32 - return (unsigned long)(®s->sp); +extern unsigned long kernel_stack_pointer(struct pt_regs *regs); #else +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ return regs->sp; -#endif } +#endif #define GET_IP(regs) ((regs)->ip) #define GET_FP(regs) ((regs)->bp) diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index 59c226d120c..c20d1ce62dc 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h @@ -359,18 +359,14 @@ HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val, return _hypercall4(int, update_va_mapping, va, new_val.pte, new_val.pte >> 32, flags); } +extern int __must_check xen_event_channel_op_compat(int, void *); static inline int HYPERVISOR_event_channel_op(int cmd, void *arg) { int rc = _hypercall2(int, event_channel_op, cmd, arg); - if (unlikely(rc == -ENOSYS)) { - struct evtchn_op op; - op.cmd = cmd; - memcpy(&op.u, arg, sizeof(op.u)); - rc = _hypercall1(int, event_channel_op_compat, &op); - memcpy(arg, &op.u, sizeof(op.u)); - } + if (unlikely(rc == -ENOSYS)) + rc = xen_event_channel_op_compat(cmd, arg); return rc; } @@ -386,17 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str) return _hypercall3(int, console_io, cmd, count, str); } +extern int __must_check HYPERVISOR_physdev_op_compat(int, void *); + static inline int HYPERVISOR_physdev_op(int cmd, void *arg) { int rc = _hypercall2(int, physdev_op, cmd, arg); - if (unlikely(rc == -ENOSYS)) { - struct physdev_op op; - op.cmd = cmd; - memcpy(&op.u, arg, sizeof(op.u)); - rc = _hypercall1(int, physdev_op_compat, &op); - memcpy(arg, &op.u, sizeof(op.u)); - } + if (unlikely(rc == -ENOSYS)) + rc = HYPERVISOR_physdev_op_compat(cmd, arg); return rc; } diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h index 66d0fff1ee8..125f344f06a 100644 --- a/arch/x86/include/asm/xen/hypervisor.h +++ b/arch/x86/include/asm/xen/hypervisor.h @@ -33,7 +33,6 @@ #ifndef _ASM_X86_XEN_HYPERVISOR_H #define _ASM_X86_XEN_HYPERVISOR_H -/* arch/i386/kernel/setup.c */ extern struct shared_info *HYPERVISOR_shared_info; extern struct start_info *xen_start_info; diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h index 6d2f75a82a1..54d52ff1304 100644 --- a/arch/x86/include/asm/xen/interface.h +++ b/arch/x86/include/asm/xen/interface.h @@ -51,14 +51,14 @@ * with Xen so that on ARM we can have one ABI that works for 32 and 64 * bit guests. */ typedef unsigned long xen_pfn_t; +#define PRI_xen_pfn "lx" typedef unsigned long xen_ulong_t; +#define PRI_xen_ulong "lx" /* Guest handles for primitive C types. */ __DEFINE_GUEST_HANDLE(uchar, unsigned char); __DEFINE_GUEST_HANDLE(uint, unsigned int); -__DEFINE_GUEST_HANDLE(ulong, unsigned long); DEFINE_GUEST_HANDLE(char); DEFINE_GUEST_HANDLE(int); -DEFINE_GUEST_HANDLE(long); DEFINE_GUEST_HANDLE(void); DEFINE_GUEST_HANDLE(uint64_t); DEFINE_GUEST_HANDLE(uint32_t); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index c265593ec2c..1817fa91102 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) continue; cfg = irq_cfg(irq); + if (!cfg) + continue; + raw_spin_lock(&desc->lock); /* diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index f7e98a2c0d1..1b7d1656a04 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -631,6 +631,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } } + /* + * The way access filter has a performance penalty on some workloads. + * Disable it on the affected CPUs. + */ + if ((c->x86 == 0x15) && + (c->x86_model >= 0x02) && (c->x86_model < 0x20)) { + u64 val; + + if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) { + val |= 0x1E; + wrmsrl_safe(0xc0011021, val); + } + } + cpu_detect_cache_sizes(c); /* Multi core CPU? */ diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 9a7c90d80bc..93c5451bdd5 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -991,7 +991,7 @@ static struct attribute ** __cpuinit amd_l3_attrs(void) if (attrs) return attrs; - n = sizeof (default_attrs) / sizeof (struct attribute *); + n = ARRAY_SIZE(default_attrs); if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) n += 2; diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 29e87d3b284..46cbf868969 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -2209,11 +2209,6 @@ static struct dev_ext_attribute dev_attr_cmci_disabled = { &mce_cmci_disabled }; -static struct dev_ext_attribute dev_attr_bios_cmci_threshold = { - __ATTR(bios_cmci_threshold, 0444, device_show_int, NULL), - &mce_bios_cmci_threshold -}; - static struct device_attribute *mce_device_attrs[] = { &dev_attr_tolerant.attr, &dev_attr_check_interval.attr, @@ -2222,7 +2217,6 @@ static struct device_attribute *mce_device_attrs[] = { &dev_attr_dont_log_ce.attr, &dev_attr_ignore_ce.attr, &dev_attr_cmci_disabled.attr, - &dev_attr_bios_cmci_threshold.attr, NULL }; diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index c4e916d7737..1ac581f38df 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -6,7 +6,7 @@ * * Written by Jacob Shin - AMD, Inc. * - * Support: borislav.petkov@amd.com + * Maintained by: Borislav Petkov <bp@alien8.de> * * April 2006 * - added support for AMD Family 0x10 processors @@ -576,12 +576,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) int err = 0; if (shared_bank[bank]) { - nb = node_to_amd_nb(amd_get_nb_id(cpu)); - WARN_ON(!nb); /* threshold descriptor already initialized on this node? */ - if (nb->bank4) { + if (nb && nb->bank4) { /* yes, use it */ b = nb->bank4; err = kobject_add(b->kobj, &dev->kobj, name); @@ -615,8 +613,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) atomic_set(&b->cpus, 1); /* nb is already initialized, see above */ - WARN_ON(nb->bank4); - nb->bank4 = b; + if (nb) { + WARN_ON(nb->bank4); + nb->bank4 = b; + } } err = allocate_threshold_blocks(cpu, bank, 0, diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index 5f88abf07e9..4f9a3cbfc4a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c @@ -285,34 +285,39 @@ void cmci_clear(void) raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); } +static long cmci_rediscover_work_func(void *arg) +{ + int banks; + + /* Recheck banks in case CPUs don't all have the same */ + if (cmci_supported(&banks)) + cmci_discover(banks); + + return 0; +} + /* * After a CPU went down cycle through all the others and rediscover * Must run in process context. */ void cmci_rediscover(int dying) { - int banks; - int cpu; - cpumask_var_t old; + int cpu, banks; if (!cmci_supported(&banks)) return; - if (!alloc_cpumask_var(&old, GFP_KERNEL)) - return; - cpumask_copy(old, ¤t->cpus_allowed); for_each_online_cpu(cpu) { if (cpu == dying) continue; - if (set_cpus_allowed_ptr(current, cpumask_of(cpu))) + + if (cpu == smp_processor_id()) { + cmci_rediscover_work_func(NULL); continue; - /* Recheck banks in case CPUs don't all have the same */ - if (cmci_supported(&banks)) - cmci_discover(banks); - } + } - set_cpus_allowed_ptr(current, old); - free_cpumask_var(old); + work_on_cpu(cpu, cmci_rediscover_work_func, NULL); + } } /* diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 915b876edd1..4a3374e61a9 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -208,12 +208,14 @@ static bool check_hw_exists(void) } /* - * Now write a value and read it back to see if it matches, - * this is needed to detect certain hardware emulators (qemu/kvm) - * that don't trap on the MSR access and always return 0s. + * Read the current value, change it and read it back to see if it + * matches, this is needed to detect certain hardware emulators + * (qemu/kvm) that don't trap on the MSR access and always return 0s. */ - val = 0xabcdUL; reg = x86_pmu_event_addr(0); + if (rdmsrl_safe(reg, &val)) + goto msr_fail; + val ^= 0xffffUL; ret = wrmsrl_safe(reg, val); ret |= rdmsrl_safe(reg, &val_new); if (ret || val != val_new) @@ -338,6 +340,9 @@ int x86_setup_perfctr(struct perf_event *event) /* BTS is currently only allowed for user-mode. */ if (!attr->exclude_kernel) return -EOPNOTSUPP; + + if (!attr->exclude_guest) + return -EOPNOTSUPP; } hwc->config |= config; @@ -380,6 +385,9 @@ int x86_pmu_hw_config(struct perf_event *event) if (event->attr.precise_ip) { int precise = 0; + if (!event->attr.exclude_guest) + return -EOPNOTSUPP; + /* Support for constant skid */ if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) { precise++; diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 99d96a4978b..3cf3d97cce3 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -118,22 +118,24 @@ static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box) { struct pci_dev *pdev = box->pci_dev; int box_ctl = uncore_pci_box_ctl(box); - u32 config; + u32 config = 0; - pci_read_config_dword(pdev, box_ctl, &config); - config |= SNBEP_PMON_BOX_CTL_FRZ; - pci_write_config_dword(pdev, box_ctl, config); + if (!pci_read_config_dword(pdev, box_ctl, &config)) { + config |= SNBEP_PMON_BOX_CTL_FRZ; + pci_write_config_dword(pdev, box_ctl, config); + } } static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box) { struct pci_dev *pdev = box->pci_dev; int box_ctl = uncore_pci_box_ctl(box); - u32 config; + u32 config = 0; - pci_read_config_dword(pdev, box_ctl, &config); - config &= ~SNBEP_PMON_BOX_CTL_FRZ; - pci_write_config_dword(pdev, box_ctl, config); + if (!pci_read_config_dword(pdev, box_ctl, &config)) { + config &= ~SNBEP_PMON_BOX_CTL_FRZ; + pci_write_config_dword(pdev, box_ctl, config); + } } static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event) @@ -156,7 +158,7 @@ static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct pe { struct pci_dev *pdev = box->pci_dev; struct hw_perf_event *hwc = &event->hw; - u64 count; + u64 count = 0; pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count); pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1); @@ -603,11 +605,12 @@ static struct pci_driver snbep_uncore_pci_driver = { /* * build pci bus to socket mapping */ -static void snbep_pci2phy_map_init(void) +static int snbep_pci2phy_map_init(void) { struct pci_dev *ubox_dev = NULL; int i, bus, nodeid; - u32 config; + int err = 0; + u32 config = 0; while (1) { /* find the UBOX device */ @@ -618,10 +621,14 @@ static void snbep_pci2phy_map_init(void) break; bus = ubox_dev->bus->number; /* get the Node ID of the local register */ - pci_read_config_dword(ubox_dev, 0x40, &config); + err = pci_read_config_dword(ubox_dev, 0x40, &config); + if (err) + break; nodeid = config; /* get the Node ID mapping */ - pci_read_config_dword(ubox_dev, 0x54, &config); + err = pci_read_config_dword(ubox_dev, 0x54, &config); + if (err) + break; /* * every three bits in the Node ID mapping register maps * to a particular node. @@ -633,7 +640,11 @@ static void snbep_pci2phy_map_init(void) } } }; - return; + + if (ubox_dev) + pci_dev_put(ubox_dev); + + return err ? pcibios_err_to_errno(err) : 0; } /* end of Sandy Bridge-EP uncore support */ @@ -1547,7 +1558,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; struct hw_perf_event_extra *reg1 = &hwc->extra_reg; - int port; /* adjust the main event selector and extra register index */ if (reg1->idx % 2) { @@ -1559,7 +1569,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event) } /* adjust extra register config */ - port = reg1->idx / 6 + box->pmu->pmu_idx * 4; switch (reg1->idx % 6) { case 2: /* shift the 8~15 bits to the 0~7 bits */ @@ -2578,9 +2587,11 @@ static int __init uncore_pci_init(void) switch (boot_cpu_data.x86_model) { case 45: /* Sandy Bridge-EP */ + ret = snbep_pci2phy_map_init(); + if (ret) + return ret; pci_uncores = snbep_pci_uncores; uncore_pci_driver = &snbep_uncore_pci_driver; - snbep_pci2phy_map_init(); break; default: return 0; @@ -2926,6 +2937,9 @@ static int __init intel_uncore_init(void) if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) return -ENODEV; + if (cpu_has_hypervisor) + return -ENODEV; + ret = uncore_pci_init(); if (ret) goto fail; diff --git a/arch/x86/kernel/cpu/perf_event_knc.c b/arch/x86/kernel/cpu/perf_event_knc.c index 7c46bfdbc37..4b7731bf23a 100644 --- a/arch/x86/kernel/cpu/perf_event_knc.c +++ b/arch/x86/kernel/cpu/perf_event_knc.c @@ -3,6 +3,8 @@ #include <linux/perf_event.h> #include <linux/types.h> +#include <asm/hardirq.h> + #include "perf_event.h" static const u64 knc_perfmon_event_map[] = @@ -173,30 +175,100 @@ static void knc_pmu_enable_all(int added) static inline void knc_pmu_disable_event(struct perf_event *event) { - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; u64 val; val = hwc->config; - if (cpuc->enabled) - val &= ~ARCH_PERFMON_EVENTSEL_ENABLE; + val &= ~ARCH_PERFMON_EVENTSEL_ENABLE; (void)wrmsrl_safe(hwc->config_base + hwc->idx, val); } static void knc_pmu_enable_event(struct perf_event *event) { - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; u64 val; val = hwc->config; - if (cpuc->enabled) - val |= ARCH_PERFMON_EVENTSEL_ENABLE; + val |= ARCH_PERFMON_EVENTSEL_ENABLE; (void)wrmsrl_safe(hwc->config_base + hwc->idx, val); } +static inline u64 knc_pmu_get_status(void) +{ + u64 status; + + rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status); + + return status; +} + +static inline void knc_pmu_ack_status(u64 ack) +{ + wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack); +} + +static int knc_pmu_handle_irq(struct pt_regs *regs) +{ + struct perf_sample_data data; + struct cpu_hw_events *cpuc; + int handled = 0; + int bit, loops; + u64 status; + + cpuc = &__get_cpu_var(cpu_hw_events); + + knc_pmu_disable_all(); + + status = knc_pmu_get_status(); + if (!status) { + knc_pmu_enable_all(0); + return handled; + } + + loops = 0; +again: + knc_pmu_ack_status(status); + if (++loops > 100) { + WARN_ONCE(1, "perf: irq loop stuck!\n"); + perf_event_print_debug(); + goto done; + } + + inc_irq_stat(apic_perf_irqs); + + for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { + struct perf_event *event = cpuc->events[bit]; + + handled++; + + if (!test_bit(bit, cpuc->active_mask)) + continue; + + if (!intel_pmu_save_and_restart(event)) + continue; + + perf_sample_data_init(&data, 0, event->hw.last_period); + + if (perf_event_overflow(event, &data, regs)) + x86_pmu_stop(event, 0); + } + + /* + * Repeat if there is more work to be done: + */ + status = knc_pmu_get_status(); + if (status) + goto again; + +done: + knc_pmu_enable_all(0); + + return handled; +} + + PMU_FORMAT_ATTR(event, "config:0-7" ); PMU_FORMAT_ATTR(umask, "config:8-15" ); PMU_FORMAT_ATTR(edge, "config:18" ); @@ -214,7 +286,7 @@ static struct attribute *intel_knc_formats_attr[] = { static __initconst struct x86_pmu knc_pmu = { .name = "knc", - .handle_irq = x86_pmu_handle_irq, + .handle_irq = knc_pmu_handle_irq, .disable_all = knc_pmu_disable_all, .enable_all = knc_pmu_enable_all, .enable = knc_pmu_enable_event, @@ -226,12 +298,11 @@ static __initconst struct x86_pmu knc_pmu = { .event_map = knc_pmu_event_map, .max_events = ARRAY_SIZE(knc_perfmon_event_map), .apic = 1, - .max_period = (1ULL << 31) - 1, + .max_period = (1ULL << 39) - 1, .version = 0, .num_counters = 2, - /* in theory 40 bits, early silicon is buggy though */ - .cntval_bits = 32, - .cntval_mask = (1ULL << 32) - 1, + .cntval_bits = 40, + .cntval_mask = (1ULL << 40) - 1, .get_event_constraints = x86_get_event_constraints, .event_constraints = knc_event_constraints, .format_attrs = intel_knc_formats_attr, diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index e4dd0f7a045..7d0270bd793 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -8,13 +8,106 @@ */ static const u64 p6_perfmon_event_map[] = { - [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, - [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, - [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e, - [PERF_COUNT_HW_CACHE_MISSES] = 0x012e, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, - [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, - [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, + [PERF_COUNT_HW_CPU_CYCLES] = 0x0079, /* CPU_CLK_UNHALTED */ + [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0, /* INST_RETIRED */ + [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0f2e, /* L2_RQSTS:M:E:S:I */ + [PERF_COUNT_HW_CACHE_MISSES] = 0x012e, /* L2_RQSTS:I */ + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c4, /* BR_INST_RETIRED */ + [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c5, /* BR_MISS_PRED_RETIRED */ + [PERF_COUNT_HW_BUS_CYCLES] = 0x0062, /* BUS_DRDY_CLOCKS */ + [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2, /* RESOURCE_STALLS */ + +}; + +static __initconst u64 p6_hw_cache_event_ids + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = +{ + [ C(L1D) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0043, /* DATA_MEM_REFS */ + [ C(RESULT_MISS) ] = 0x0045, /* DCU_LINES_IN */ + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0x0f29, /* L2_LD:M:E:S:I */ + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + [ C(L1I ) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0080, /* IFU_IFETCH */ + [ C(RESULT_MISS) ] = 0x0f28, /* L2_IFETCH:M:E:S:I */ + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + [ C(LL ) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0x0025, /* L2_M_LINES_INM */ + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + [ C(DTLB) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0043, /* DATA_MEM_REFS */ + [ C(RESULT_MISS) ] = 0, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = 0, + [ C(RESULT_MISS) ] = 0, + }, + }, + [ C(ITLB) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0080, /* IFU_IFETCH */ + [ C(RESULT_MISS) ] = 0x0085, /* ITLB_MISS */ + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, + [ C(BPU ) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED */ + [ C(RESULT_MISS) ] = 0x00c5, /* BR_MISS_PRED_RETIRED */ + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, }; static u64 p6_pmu_event_map(int hw_event) @@ -34,7 +127,7 @@ static struct event_constraint p6_event_constraints[] = { INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */ INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ - INTEL_EVENT_CONSTRAINT(0x11, 0x1), /* FP_ASSIST */ + INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */ INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */ INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */ INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */ @@ -64,25 +157,25 @@ static void p6_pmu_enable_all(int added) static inline void p6_pmu_disable_event(struct perf_event *event) { - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; u64 val = P6_NOP_EVENT; - if (cpuc->enabled) - val |= ARCH_PERFMON_EVENTSEL_ENABLE; - (void)wrmsrl_safe(hwc->config_base, val); } static void p6_pmu_enable_event(struct perf_event *event) { - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; u64 val; val = hwc->config; - if (cpuc->enabled) - val |= ARCH_PERFMON_EVENTSEL_ENABLE; + + /* + * p6 only has a global event enable, set on PerfEvtSel0 + * We "disable" events by programming P6_NOP_EVENT + * and we rely on p6_pmu_enable_all() being called + * to actually enable the events. + */ (void)wrmsrl_safe(hwc->config_base, val); } @@ -158,5 +251,9 @@ __init int p6_pmu_init(void) x86_pmu = p6_pmu; + memcpy(hw_cache_event_ids, p6_hw_cache_event_ids, + sizeof(hw_cache_event_ids)); + + return 0; } diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index ed858e9e9a7..df06ade26be 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void) memblock_add(ei->addr, ei->size); } + /* throw away partial pages */ + memblock_trim_memory(PAGE_SIZE); + memblock_dump_all(); } diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index a1193aef6d7..88b725aa1d5 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -1035,7 +1035,7 @@ ENTRY(xen_sysenter_target) ENTRY(xen_hypervisor_callback) CFI_STARTPROC - pushl_cfi $0 + pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL TRACE_IRQS_OFF @@ -1077,14 +1077,16 @@ ENTRY(xen_failsafe_callback) 2: mov 8(%esp),%es 3: mov 12(%esp),%fs 4: mov 16(%esp),%gs + /* EAX == 0 => Category 1 (Bad segment) + EAX != 0 => Category 2 (Bad IRET) */ testl %eax,%eax popl_cfi %eax lea 16(%esp),%esp CFI_ADJUST_CFA_OFFSET -16 jz 5f addl $16,%esp - jmp iret_exc # EAX != 0 => Category 2 (Bad IRET) -5: pushl_cfi $0 # EAX == 0 => Category 1 (Bad segment) + jmp iret_exc +5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL jmp ret_from_exception CFI_ENDPROC diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 0c58952d64e..1328fe49a3f 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -995,8 +995,8 @@ END(interrupt) */ .p2align CONFIG_X86_L1_CACHE_SHIFT common_interrupt: - ASM_CLAC XCPT_FRAME + ASM_CLAC addq $-0x80,(%rsp) /* Adjust vector to [-256,-1] range */ interrupt do_IRQ /* 0(%rsp): old_rsp-ARGOFFSET */ @@ -1135,8 +1135,8 @@ END(common_interrupt) */ .macro apicinterrupt num sym do_sym ENTRY(\sym) - ASM_CLAC INTR_FRAME + ASM_CLAC pushq_cfi $~(\num) .Lcommon_\sym: interrupt \do_sym @@ -1190,8 +1190,8 @@ apicinterrupt IRQ_WORK_VECTOR \ */ .macro zeroentry sym do_sym ENTRY(\sym) - ASM_CLAC INTR_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */ subq $ORIG_RAX-R15, %rsp @@ -1208,8 +1208,8 @@ END(\sym) .macro paranoidzeroentry sym do_sym ENTRY(\sym) - ASM_CLAC INTR_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */ subq $ORIG_RAX-R15, %rsp @@ -1227,8 +1227,8 @@ END(\sym) #define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8) .macro paranoidzeroentry_ist sym do_sym ist ENTRY(\sym) - ASM_CLAC INTR_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */ subq $ORIG_RAX-R15, %rsp @@ -1247,8 +1247,8 @@ END(\sym) .macro errorentry sym do_sym ENTRY(\sym) - ASM_CLAC XCPT_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME subq $ORIG_RAX-R15, %rsp CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 @@ -1266,8 +1266,8 @@ END(\sym) /* error code is on the stack already */ .macro paranoiderrorentry sym do_sym ENTRY(\sym) - ASM_CLAC XCPT_FRAME + ASM_CLAC PARAVIRT_ADJUST_EXCEPTION_FRAME subq $ORIG_RAX-R15, %rsp CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 @@ -1435,7 +1435,7 @@ ENTRY(xen_failsafe_callback) CFI_RESTORE r11 addq $0x30,%rsp CFI_ADJUST_CFA_OFFSET -0x30 - pushq_cfi $0 + pushq_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL jmp error_exit CFI_ENDPROC diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index b3e5e51bc90..4180a874c76 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -247,7 +247,10 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code) break; case KVM_PV_REASON_PAGE_NOT_PRESENT: /* page is swapped out by the host. */ + rcu_irq_enter(); + exit_idle(); kvm_async_pf_task_wait((u32)read_cr2()); + rcu_irq_exit(); break; case KVM_PV_REASON_PAGE_READY: rcu_irq_enter(); diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 7720ff5a9ee..efdec7cd8e0 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -8,8 +8,8 @@ * Tigran Aivazian <tigran@aivazian.fsnet.co.uk> * * Maintainers: - * Andreas Herrmann <andreas.herrmann3@amd.com> - * Borislav Petkov <borislav.petkov@amd.com> + * Andreas Herrmann <herrmann.der.user@googlemail.com> + * Borislav Petkov <bp@alien8.de> * * This driver allows to upgrade microcode on F10h AMD * CPUs and later. @@ -190,6 +190,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size, #define F1XH_MPB_MAX_SIZE 2048 #define F14H_MPB_MAX_SIZE 1824 #define F15H_MPB_MAX_SIZE 4096 +#define F16H_MPB_MAX_SIZE 3458 switch (c->x86) { case 0x14: @@ -198,6 +199,9 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size, case 0x15: max_size = F15H_MPB_MAX_SIZE; break; + case 0x16: + max_size = F16H_MPB_MAX_SIZE; + break; default: max_size = F1XH_MPB_MAX_SIZE; break; diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index b00b33a1839..5e0596b0632 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -22,6 +22,7 @@ #include <linux/perf_event.h> #include <linux/hw_breakpoint.h> #include <linux/rcupdate.h> +#include <linux/module.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -166,6 +167,35 @@ static inline bool invalid_selector(u16 value) #define FLAG_MASK FLAG_MASK_32 +/* + * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode + * when it traps. The previous stack will be directly underneath the saved + * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. + * + * Now, if the stack is empty, '®s->sp' is out of range. In this + * case we try to take the previous stack. To always return a non-null + * stack pointer we fall back to regs as stack if no previous stack + * exists. + * + * This is valid only for kernel mode traps. + */ +unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1); + unsigned long sp = (unsigned long)®s->sp; + struct thread_info *tinfo; + + if (context == (sp & ~(THREAD_SIZE - 1))) + return sp; + + tinfo = (struct thread_info *)context; + if (tinfo->previous_esp) + return tinfo->previous_esp; + + return (unsigned long)regs; +} +EXPORT_SYMBOL_GPL(kernel_stack_pointer); + static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 52190a938b4..4e8ba39eaf0 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -358,14 +358,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"), }, }, - { /* Handle problems with rebooting on CompuLab SBC-FITPC2 */ - .callback = set_bios_reboot, - .ident = "CompuLab SBC-FITPC2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "CompuLab"), - DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"), - }, - }, { /* Handle problems with rebooting on ASUS P4S800 */ .callback = set_bios_reboot, .ident = "ASUS P4S800", diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index a2bb18e0283..ca45696f30f 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -920,8 +920,22 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_X86_64 if (max_pfn > max_low_pfn) { - max_pfn_mapped = init_memory_mapping(1UL<<32, - max_pfn<<PAGE_SHIFT); + int i; + unsigned long start, end; + unsigned long start_pfn, end_pfn; + + for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, + NULL) { + + end = PFN_PHYS(end_pfn); + if (end <= (1UL<<32)) + continue; + + start = PFN_PHYS(start_pfn); + max_pfn_mapped = init_memory_mapping( + max((1UL<<32), start), end); + } + /* can we preseve max_low_pfn ?*/ max_low_pfn = max_pfn; } @@ -1035,6 +1049,18 @@ void __init setup_arch(char **cmdline_p) arch_init_ideal_nops(); register_refined_jiffies(CLOCK_TICK_RATE); + +#ifdef CONFIG_EFI + /* Once setup is done above, disable efi_enabled on mismatched + * firmware/kernel archtectures since there is no support for + * runtime services. + */ + if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { + pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); + efi_unmap_memmap(); + efi_enabled = 0; + } +#endif } #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 29ad351804e..70b27ee6118 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -824,10 +824,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) mce_notify_process(); #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ - if (thread_info_flags & _TIF_UPROBE) { - clear_thread_flag(TIF_UPROBE); + if (thread_info_flags & _TIF_UPROBE) uprobe_notify_resume(regs); - } /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 9538f00827a..aafa5557b39 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -651,31 +651,19 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) /* * Skip these instructions as per the currently known x86 ISA. - * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 } + * rep=0x66*; nop=0x90 */ static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) { int i; for (i = 0; i < MAX_UINSN_BYTES; i++) { - if ((auprobe->insn[i] == 0x66)) + if (auprobe->insn[i] == 0x66) continue; if (auprobe->insn[i] == 0x90) return true; - if (i == (MAX_UINSN_BYTES - 1)) - break; - - if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f)) - return true; - - if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19)) - return true; - - if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0)) - return true; - break; } return false; diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index a10e4601685..58fc5148882 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; + if (!static_cpu_has(X86_FEATURE_XSAVE)) + return 0; + best = kvm_find_cpuid_entry(vcpu, 1, 0); return best && (best->ecx & bit(X86_FEATURE_XSAVE)); } diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index c6e6b721b6e..43e9fadca5d 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1311,7 +1311,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value) vcpu->arch.apic_base = value; if (apic_x2apic_mode(apic)) { u32 id = kvm_apic_id(apic); - u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf)); + u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf)); kvm_apic_set_ldr(apic, ldr); } apic->base_address = apic->vcpu->arch.apic_base & diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index d289fee1ffb..6f85fe0bf95 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -2497,8 +2497,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, } } - if (!is_error_pfn(pfn)) - kvm_release_pfn_clean(pfn); + kvm_release_pfn_clean(pfn); } static void nonpaging_new_cr3(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index ad6b1dd06f8..f85815945fc 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -6549,19 +6549,22 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) } } - exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); /* Exposing INVPCID only when PCID is exposed */ best = kvm_find_cpuid_entry(vcpu, 0x7, 0); if (vmx_invpcid_supported() && best && (best->ebx & bit(X86_FEATURE_INVPCID)) && guest_cpuid_has_pcid(vcpu)) { + exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); exec_control |= SECONDARY_EXEC_ENABLE_INVPCID; vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control); } else { - exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; - vmcs_write32(SECONDARY_VM_EXEC_CONTROL, - exec_control); + if (cpu_has_secondary_exec_ctrls()) { + exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); + exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID; + vmcs_write32(SECONDARY_VM_EXEC_CONTROL, + exec_control); + } if (best) best->ebx &= ~bit(X86_FEATURE_INVPCID); } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1eefebe5d72..4f7641756be 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, { struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0]; - memcpy(vcpu->run->mmio.data, frag->data, frag->len); + memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len)); return X86EMUL_CONTINUE; } @@ -3832,18 +3832,11 @@ mmio: bytes -= handled; val += handled; - while (bytes) { - unsigned now = min(bytes, 8U); - - frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; - frag->gpa = gpa; - frag->data = val; - frag->len = now; - - gpa += now; - val += now; - bytes -= now; - } + WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS); + frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; + frag->gpa = gpa; + frag->data = val; + frag->len = bytes; return X86EMUL_CONTINUE; } @@ -3890,7 +3883,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr, vcpu->mmio_needed = 1; vcpu->mmio_cur_fragment = 0; - vcpu->run->mmio.len = vcpu->mmio_fragments[0].len; + vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len); vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write; vcpu->run->exit_reason = KVM_EXIT_MMIO; vcpu->run->mmio.phys_addr = gpa; @@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu) * * read: * for each fragment - * write gpa, len - * exit - * copy data + * for each mmio piece in the fragment + * write gpa, len + * exit + * copy data * execute insn * * write: * for each fragment - * write gpa, len - * copy data - * exit + * for each mmio piece in the fragment + * write gpa, len + * copy data + * exit */ static int complete_emulated_mmio(struct kvm_vcpu *vcpu) { struct kvm_run *run = vcpu->run; struct kvm_mmio_fragment *frag; + unsigned len; BUG_ON(!vcpu->mmio_needed); /* Complete previous fragment */ - frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++]; + frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment]; + len = min(8u, frag->len); if (!vcpu->mmio_is_write) - memcpy(frag->data, run->mmio.data, frag->len); + memcpy(frag->data, run->mmio.data, len); + + if (frag->len <= 8) { + /* Switch to the next fragment. */ + frag++; + vcpu->mmio_cur_fragment++; + } else { + /* Go forward to the next mmio piece. */ + frag->data += len; + frag->gpa += len; + frag->len -= len; + } + if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) { vcpu->mmio_needed = 0; if (vcpu->mmio_is_write) @@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu) vcpu->mmio_read_completed = 1; return complete_emulated_io(vcpu); } - /* Initiate next fragment */ - ++frag; + run->exit_reason = KVM_EXIT_MMIO; run->mmio.phys_addr = frag->gpa; if (vcpu->mmio_is_write) - memcpy(run->mmio.data, frag->data, frag->len); - run->mmio.len = frag->len; + memcpy(run->mmio.data, frag->data, min(8u, frag->len)); + run->mmio.len = min(8u, frag->len); run->mmio.is_write = vcpu->mmio_is_write; vcpu->arch.complete_userspace_io = complete_emulated_mmio; return 0; @@ -5773,6 +5781,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int pending_vec, max_bits, idx; struct desc_ptr dt; + if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE)) + return -EINVAL; + dt.size = sregs->idt.limit; dt.address = sregs->idt.base; kvm_x86_ops->set_idt(vcpu, &dt); diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index ab1f6a93b52..d7aea41563b 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -35,40 +35,44 @@ struct map_range { unsigned page_size_mask; }; -static void __init find_early_table_space(struct map_range *mr, unsigned long end, - int use_pse, int use_gbpages) +/* + * First calculate space needed for kernel direct mapping page tables to cover + * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB + * pages. Then find enough contiguous space for those page tables. + */ +static void __init find_early_table_space(struct map_range *mr, int nr_range) { - unsigned long puds, pmds, ptes, tables, start = 0, good_end = end; + int i; + unsigned long puds = 0, pmds = 0, ptes = 0, tables; + unsigned long start = 0, good_end; phys_addr_t base; - puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; - tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); - - if (use_gbpages) { - unsigned long extra; - - extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); - pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; - } else - pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; + for (i = 0; i < nr_range; i++) { + unsigned long range, extra; - tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); + range = mr[i].end - mr[i].start; + puds += (range + PUD_SIZE - 1) >> PUD_SHIFT; - if (use_pse) { - unsigned long extra; + if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) { + extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT); + pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT; + } else { + pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT; + } - extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); + if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) { + extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT); #ifdef CONFIG_X86_32 - extra += PMD_SIZE; + extra += PMD_SIZE; #endif - /* The first 2/4M doesn't use large pages. */ - if (mr->start < PMD_SIZE) - extra += mr->end - mr->start; - - ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; - } else - ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; + ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; + } else { + ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT; + } + } + tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); + tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); #ifdef CONFIG_X86_32 @@ -86,7 +90,7 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT); printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n", - end - 1, pgt_buf_start << PAGE_SHIFT, + mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT, (pgt_buf_top << PAGE_SHIFT) - 1); } @@ -267,7 +271,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, * nodes are discovered. */ if (!after_bootmem) - find_early_table_space(&mr[0], end, use_pse, use_gbpages); + find_early_table_space(mr, nr_range); for (i = 0; i < nr_range; i++) ret = kernel_physical_mapping_init(mr[i].start, mr[i].end, diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 2b6b4a3c8be..3baff255ada 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end, * these mappings are more intelligent. */ if (pte_val(*pte)) { - pages++; + if (!after_bootmem) + pages++; continue; } @@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end, * attributes. */ if (page_size_mask & (1 << PG_LEVEL_2M)) { + if (!after_bootmem) + pages++; last_map_addr = next; continue; } @@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end, * attributes. */ if (page_size_mask & (1 << PG_LEVEL_1G)) { + if (!after_bootmem) + pages++; last_map_addr = next; continue; } diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 0777f042e40..60f926cd8b0 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -197,7 +197,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, } if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1 - || vmflag == VM_HUGETLB) { + || vmflag & VM_HUGETLB) { local_flush_tlb(); goto flush_all; } diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 26b8a8514ee..48768df2471 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model, val |= counter_config->extra; event &= model->event_mask ? model->event_mask : 0xFF; val |= event & 0xFF; - val |= (event & 0x0F00) << 24; + val |= (u64)(event & 0x0F00) << 24; return val; } diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c index 41bd2a2d2c5..b914e20b5a0 100644 --- a/arch/x86/pci/ce4100.c +++ b/arch/x86/pci/ce4100.c @@ -115,6 +115,16 @@ static void sata_revid_read(struct sim_dev_reg *reg, u32 *value) reg_read(reg, value); } +static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&pci_config_lock, flags); + /* force interrupt pin value to 0 */ + *value = reg->sim_reg.value & 0xfff00ff; + raw_spin_unlock_irqrestore(&pci_config_lock, flags); +} + static struct sim_dev_reg bus1_fixups[] = { DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write) DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write) @@ -144,6 +154,7 @@ static struct sim_dev_reg bus1_fixups[] = { DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write) DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write) DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write) + DEFINE_REG(11, 7, 0x3c, 256, reg_init, reg_noirq_read, reg_write) DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write) DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write) @@ -161,8 +172,10 @@ static struct sim_dev_reg bus1_fixups[] = { DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write) DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write) + DEFINE_REG(16, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write) DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write) + DEFINE_REG(18, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write) }; static void __init init_sim_regs(void) diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c index 4c61b52191e..92525cb8e54 100644 --- a/arch/x86/platform/ce4100/ce4100.c +++ b/arch/x86/platform/ce4100/ce4100.c @@ -21,12 +21,25 @@ #include <asm/i8259.h> #include <asm/io.h> #include <asm/io_apic.h> +#include <asm/emergency-restart.h> static int ce4100_i8042_detect(void) { return 0; } +/* + * The CE4100 platform has an internal 8051 Microcontroller which is + * responsible for signaling to the external Power Management Unit the + * intention to reset, reboot or power off the system. This 8051 device has + * its command register mapped at I/O port 0xcf9 and the value 0x4 is used + * to power off the system. + */ +static void ce4100_power_off(void) +{ + outb(0x4, 0xcf9); +} + #ifdef CONFIG_SERIAL_8250 static unsigned int mem_serial_in(struct uart_port *p, int offset) @@ -139,8 +152,19 @@ void __init x86_ce4100_early_setup(void) x86_init.mpparse.find_smp_config = x86_init_noop; x86_init.pci.init = ce4100_pci_init; + /* + * By default, the reboot method is ACPI which is supported by the + * CE4100 bootloader CEFDK using FADT.ResetReg Address and ResetValue + * the bootloader will however issue a system power off instead of + * reboot. By using BOOT_KBD we ensure proper system reboot as + * expected. + */ + reboot_type = BOOT_KBD; + #ifdef CONFIG_X86_IO_APIC x86_init.pci.init_irq = sdv_pci_init; x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck; #endif + + pm_power_off = ce4100_power_off; } diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index aded2a91162..ad4439145f8 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -70,11 +70,15 @@ EXPORT_SYMBOL(efi); struct efi_memory_map memmap; bool efi_64bit; -static bool efi_native; static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; +static inline bool efi_is_native(void) +{ + return IS_ENABLED(CONFIG_X86_64) == efi_64bit; +} + static int __init setup_noefi(char *arg) { efi_enabled = 0; @@ -420,7 +424,7 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_unmap_memmap(void) +void __init efi_unmap_memmap(void) { if (memmap.map) { early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); @@ -432,7 +436,7 @@ void __init efi_free_boot_services(void) { void *p; - if (!efi_native) + if (!efi_is_native()) return; for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -684,12 +688,10 @@ void __init efi_init(void) return; } efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; - efi_native = !efi_64bit; #else efi_phys.systab = (efi_system_table_t *) (boot_params.efi_info.efi_systab | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); - efi_native = efi_64bit; #endif if (efi_systab_init(efi_phys.systab)) { @@ -723,7 +725,7 @@ void __init efi_init(void) * that doesn't match the kernel 32/64-bit mode. */ - if (!efi_native) + if (!efi_is_native()) pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); else if (efi_runtime_init()) { efi_enabled = 0; @@ -735,7 +737,7 @@ void __init efi_init(void) return; } #ifdef CONFIG_X86_32 - if (efi_native) { + if (efi_is_native()) { x86_platform.get_wallclock = efi_get_time; x86_platform.set_wallclock = efi_set_rtc_mmss; } @@ -810,6 +812,16 @@ void __iomem *efi_lookup_mapped_addr(u64 phys_addr) return NULL; } +void efi_memory_uc(u64 addr, unsigned long size) +{ + unsigned long page_shift = 1UL << EFI_PAGE_SHIFT; + u64 npages; + + npages = round_up(size, page_shift) / page_shift; + memrange_efi_to_native(&addr, &npages); + set_memory_uc(addr, npages); +} + /* * This function will switch the EFI runtime services to virtual mode. * Essentially, look through the EFI memmap and map every region that @@ -823,7 +835,7 @@ void __init efi_enter_virtual_mode(void) efi_memory_desc_t *md, *prev_md = NULL; efi_status_t status; unsigned long size; - u64 end, systab, addr, npages, end_pfn; + u64 end, systab, end_pfn; void *p, *va, *new_memmap = NULL; int count = 0; @@ -834,7 +846,7 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) { + if (!efi_is_native()) { efi_unmap_memmap(); return; } @@ -879,10 +891,14 @@ void __init efi_enter_virtual_mode(void) end_pfn = PFN_UP(end); if (end_pfn <= max_low_pfn_mapped || (end_pfn > (1UL << (32 - PAGE_SHIFT)) - && end_pfn <= max_pfn_mapped)) + && end_pfn <= max_pfn_mapped)) { va = __va(md->phys_addr); - else - va = efi_ioremap(md->phys_addr, size, md->type); + + if (!(md->attribute & EFI_MEMORY_WB)) + efi_memory_uc((u64)(unsigned long)va, size); + } else + va = efi_ioremap(md->phys_addr, size, + md->type, md->attribute); md->virt_addr = (u64) (unsigned long) va; @@ -892,13 +908,6 @@ void __init efi_enter_virtual_mode(void) continue; } - if (!(md->attribute & EFI_MEMORY_WB)) { - addr = md->virt_addr; - npages = md->num_pages; - memrange_efi_to_native(&addr, &npages); - set_memory_uc(addr, npages); - } - systab = (u64) (unsigned long) efi_phys.systab; if (md->phys_addr <= systab && systab < end) { systab += md->virt_addr - md->phys_addr; diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index ac3aa54e265..95fd505dfeb 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -82,7 +82,7 @@ void __init efi_call_phys_epilog(void) } void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, - u32 type) + u32 type, u64 attribute) { unsigned long last_map_pfn; @@ -92,8 +92,11 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size); if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) { unsigned long top = last_map_pfn << PAGE_SHIFT; - efi_ioremap(top, size - (top - phys_addr), type); + efi_ioremap(top, size - (top - phys_addr), type, attribute); } + if (!(attribute & EFI_MEMORY_WB)) + efi_memory_uc((u64)(unsigned long)__va(phys_addr), size); + return (void __iomem *)__va(phys_addr); } diff --git a/arch/x86/realmode/rm/wakeup_asm.S b/arch/x86/realmode/rm/wakeup_asm.S index e56479e5805..9e7e14797a7 100644 --- a/arch/x86/realmode/rm/wakeup_asm.S +++ b/arch/x86/realmode/rm/wakeup_asm.S @@ -74,18 +74,9 @@ ENTRY(wakeup_start) lidtl wakeup_idt - /* Clear the EFLAGS but remember if we have EFLAGS.ID */ - movl $X86_EFLAGS_ID, %ecx - pushl %ecx - popfl - pushfl - popl %edi + /* Clear the EFLAGS */ pushl $0 popfl - pushfl - popl %edx - xorl %edx, %edi - andl %ecx, %edi /* %edi is zero iff CPUID & %cr4 are missing */ /* Check header signature... */ movl signature, %eax @@ -120,12 +111,12 @@ ENTRY(wakeup_start) movl %eax, %cr3 btl $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi - jz 1f + jnc 1f movl pmode_cr4, %eax movl %eax, %cr4 1: btl $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi - jz 1f + jnc 1f movl pmode_efer, %eax movl pmode_efer + 4, %edx movl $MSR_EFER, %ecx diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index e3497f240ea..586d83812b6 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -81,8 +81,6 @@ #include "smp.h" #include "multicalls.h" -#include <xen/events.h> - EXPORT_SYMBOL_GPL(hypercall_page); DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 6226c99729b..dcf5f2dd91e 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void) return this_cpu_read(xen_vcpu_info.arch.cr2); } +void xen_flush_tlb_all(void) +{ + struct mmuext_op *op; + struct multicall_space mcs; + + trace_xen_mmu_flush_tlb_all(0); + + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); + + op = mcs.args; + op->cmd = MMUEXT_TLB_FLUSH_ALL; + MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + + xen_mc_issue(PARAVIRT_LAZY_MMU); + + preempt_enable(); +} static void xen_flush_tlb(void) { struct mmuext_op *op; @@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, err = 0; out: - flush_tlb_all(); + xen_flush_tlb_all(); return err; } diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index cdcb48adee4..0d1f36a22c9 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -13,6 +13,8 @@ config XTENSA select GENERIC_CPU_DEVICES select MODULES_USE_ELF_RELA select GENERIC_PCI_IOMAP + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE select ARCH_WANT_OPTIONAL_GPIOLIB help Xtensa processors are 32-bit RISC machines designed by Tensilica diff --git a/arch/xtensa/boot/boot-redboot/bootstrap.S b/arch/xtensa/boot/boot-redboot/bootstrap.S index 4c316cd28a5..86c34dbc9cd 100644 --- a/arch/xtensa/boot/boot-redboot/bootstrap.S +++ b/arch/xtensa/boot/boot-redboot/bootstrap.S @@ -51,17 +51,17 @@ _start: /* 'reset' window registers */ movi a4, 1 - wsr a4, PS + wsr a4, ps rsync - rsr a5, WINDOWBASE + rsr a5, windowbase ssl a5 sll a4, a4 - wsr a4, WINDOWSTART + wsr a4, windowstart rsync movi a4, 0x00040000 - wsr a4, PS + wsr a4, ps rsync /* copy the loader to its address diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index fccd81eddff..6d130278999 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -1,4 +1,28 @@ -include include/asm-generic/Kbuild.asm - +generic-y += bitsperlong.h +generic-y += bug.h generic-y += clkdev.h +generic-y += cputime.h +generic-y += device.h +generic-y += div64.h +generic-y += emergency-restart.h +generic-y += errno.h generic-y += exec.h +generic-y += fcntl.h +generic-y += futex.h +generic-y += hardirq.h +generic-y += ioctl.h +generic-y += irq_regs.h +generic-y += kdebug.h +generic-y += kmap_types.h +generic-y += kvm_para.h +generic-y += local.h +generic-y += local64.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 += termios.h +generic-y += topology.h +generic-y += xor.h diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h index b4098930877..24f50cada70 100644 --- a/arch/xtensa/include/asm/atomic.h +++ b/arch/xtensa/include/asm/atomic.h @@ -73,7 +73,7 @@ static inline void atomic_add(int i, atomic_t * v) "l32i %0, %2, 0 \n\t" "add %0, %0, %1 \n\t" "s32i %0, %2, 0 \n\t" - "wsr a15, "__stringify(PS)" \n\t" + "wsr a15, ps \n\t" "rsync \n" : "=&a" (vval) : "a" (i), "a" (v) @@ -97,7 +97,7 @@ static inline void atomic_sub(int i, atomic_t *v) "l32i %0, %2, 0 \n\t" "sub %0, %0, %1 \n\t" "s32i %0, %2, 0 \n\t" - "wsr a15, "__stringify(PS)" \n\t" + "wsr a15, ps \n\t" "rsync \n" : "=&a" (vval) : "a" (i), "a" (v) @@ -118,7 +118,7 @@ static inline int atomic_add_return(int i, atomic_t * v) "l32i %0, %2, 0 \n\t" "add %0, %0, %1 \n\t" "s32i %0, %2, 0 \n\t" - "wsr a15, "__stringify(PS)" \n\t" + "wsr a15, ps \n\t" "rsync \n" : "=&a" (vval) : "a" (i), "a" (v) @@ -137,7 +137,7 @@ static inline int atomic_sub_return(int i, atomic_t * v) "l32i %0, %2, 0 \n\t" "sub %0, %0, %1 \n\t" "s32i %0, %2, 0 \n\t" - "wsr a15, "__stringify(PS)" \n\t" + "wsr a15, ps \n\t" "rsync \n" : "=&a" (vval) : "a" (i), "a" (v) @@ -260,7 +260,7 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) "xor %1, %4, %3 \n\t" "and %0, %0, %4 \n\t" "s32i %0, %2, 0 \n\t" - "wsr a15, "__stringify(PS)" \n\t" + "wsr a15, ps \n\t" "rsync \n" : "=&a" (vval), "=a" (mask) : "a" (v), "a" (all_f), "1" (mask) @@ -277,7 +277,7 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v) "l32i %0, %2, 0 \n\t" "or %0, %0, %1 \n\t" "s32i %0, %2, 0 \n\t" - "wsr a15, "__stringify(PS)" \n\t" + "wsr a15, ps \n\t" "rsync \n" : "=&a" (vval) : "a" (mask), "a" (v) diff --git a/arch/xtensa/include/asm/bitsperlong.h b/arch/xtensa/include/asm/bitsperlong.h deleted file mode 100644 index 6dc0bb0c13b..00000000000 --- a/arch/xtensa/include/asm/bitsperlong.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/bitsperlong.h> diff --git a/arch/xtensa/include/asm/bug.h b/arch/xtensa/include/asm/bug.h deleted file mode 100644 index 3e52d72712f..00000000000 --- a/arch/xtensa/include/asm/bug.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * include/asm-xtensa/bug.h - * - * Macros to cause a 'bug' message. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_BUG_H -#define _XTENSA_BUG_H - -#include <asm-generic/bug.h> - -#endif /* _XTENSA_BUG_H */ diff --git a/arch/xtensa/include/asm/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h index 376cd9d5f45..569fec4f9a2 100644 --- a/arch/xtensa/include/asm/cacheflush.h +++ b/arch/xtensa/include/asm/cacheflush.h @@ -165,7 +165,7 @@ extern void copy_from_user_page(struct vm_area_struct*, struct page*, static inline u32 xtensa_get_cacheattr(void) { u32 r; - asm volatile(" rsr %0, CACHEATTR" : "=a"(r)); + asm volatile(" rsr %0, cacheattr" : "=a"(r)); return r; } diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h index e32149063d8..64dad04a9d2 100644 --- a/arch/xtensa/include/asm/cmpxchg.h +++ b/arch/xtensa/include/asm/cmpxchg.h @@ -27,7 +27,7 @@ __cmpxchg_u32(volatile int *p, int old, int new) "bne %0, %2, 1f \n\t" "s32i %3, %1, 0 \n\t" "1: \n\t" - "wsr a15, "__stringify(PS)" \n\t" + "wsr a15, ps \n\t" "rsync \n\t" : "=&a" (old) : "a" (p), "a" (old), "r" (new) @@ -97,7 +97,7 @@ static inline unsigned long xchg_u32(volatile int * m, unsigned long val) __asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t" "l32i %0, %1, 0 \n\t" "s32i %2, %1, 0 \n\t" - "wsr a15, "__stringify(PS)" \n\t" + "wsr a15, ps \n\t" "rsync \n\t" : "=&a" (tmp) : "a" (m), "a" (val) diff --git a/arch/xtensa/include/asm/coprocessor.h b/arch/xtensa/include/asm/coprocessor.h index 75c94a1658b..677501b32df 100644 --- a/arch/xtensa/include/asm/coprocessor.h +++ b/arch/xtensa/include/asm/coprocessor.h @@ -94,11 +94,10 @@ #if XCHAL_HAVE_CP #define RSR_CPENABLE(x) do { \ - __asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \ + __asm__ __volatile__("rsr %0, cpenable" : "=a" (x)); \ } while(0); #define WSR_CPENABLE(x) do { \ - __asm__ __volatile__("wsr %0," __stringify(CPENABLE) "; rsync" \ - :: "a" (x)); \ + __asm__ __volatile__("wsr %0, cpenable; rsync" :: "a" (x)); \ } while(0); #endif /* XCHAL_HAVE_CP */ diff --git a/arch/xtensa/include/asm/cputime.h b/arch/xtensa/include/asm/cputime.h deleted file mode 100644 index a7fb864a50a..00000000000 --- a/arch/xtensa/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _XTENSA_CPUTIME_H -#define _XTENSA_CPUTIME_H - -#include <asm-generic/cputime.h> - -#endif /* _XTENSA_CPUTIME_H */ diff --git a/arch/xtensa/include/asm/delay.h b/arch/xtensa/include/asm/delay.h index e1d8c9e010c..58c0a4fd400 100644 --- a/arch/xtensa/include/asm/delay.h +++ b/arch/xtensa/include/asm/delay.h @@ -27,7 +27,7 @@ static inline void __delay(unsigned long loops) static __inline__ u32 xtensa_get_ccount(void) { u32 ccount; - asm volatile ("rsr %0, 234; # CCOUNT\n" : "=r" (ccount)); + asm volatile ("rsr %0, ccount\n" : "=r" (ccount)); return ccount; } diff --git a/arch/xtensa/include/asm/device.h b/arch/xtensa/include/asm/device.h deleted file mode 100644 index d8f9872b0e2..00000000000 --- a/arch/xtensa/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/xtensa/include/asm/div64.h b/arch/xtensa/include/asm/div64.h deleted file mode 100644 index f35678cb0a9..00000000000 --- a/arch/xtensa/include/asm/div64.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/div64.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2007 Tensilica Inc. - */ - -#ifndef _XTENSA_DIV64_H -#define _XTENSA_DIV64_H - -#include <asm-generic/div64.h> - -#endif /* _XTENSA_DIV64_H */ diff --git a/arch/xtensa/include/asm/emergency-restart.h b/arch/xtensa/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c48e42..00000000000 --- a/arch/xtensa/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/xtensa/include/asm/errno.h b/arch/xtensa/include/asm/errno.h deleted file mode 100644 index a0f3b96b79b..00000000000 --- a/arch/xtensa/include/asm/errno.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/errno.h - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file "COPYING" in the main directory of - * this archive for more details. - * - * Copyright (C) 2002 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_ERRNO_H -#define _XTENSA_ERRNO_H - -#include <asm-generic/errno.h> - -#endif /* _XTENSA_ERRNO_H */ diff --git a/arch/xtensa/include/asm/fcntl.h b/arch/xtensa/include/asm/fcntl.h deleted file mode 100644 index 46ab12db573..00000000000 --- a/arch/xtensa/include/asm/fcntl.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/fcntl.h> diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h deleted file mode 100644 index 0b745828f42..00000000000 --- a/arch/xtensa/include/asm/futex.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/futex.h> diff --git a/arch/xtensa/include/asm/hardirq.h b/arch/xtensa/include/asm/hardirq.h deleted file mode 100644 index 91695a13549..00000000000 --- a/arch/xtensa/include/asm/hardirq.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/hardirq.h - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file "COPYING" in the main directory of - * this archive for more details. - * - * Copyright (C) 2002 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_HARDIRQ_H -#define _XTENSA_HARDIRQ_H - -#include <asm-generic/hardirq.h> - -#endif /* _XTENSA_HARDIRQ_H */ diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h index e6be5b9091c..700c2e6f2d2 100644 --- a/arch/xtensa/include/asm/io.h +++ b/arch/xtensa/include/asm/io.h @@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size) static inline void iounmap(volatile void __iomem *addr) { } + +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt + #endif /* CONFIG_MMU */ /* diff --git a/arch/xtensa/include/asm/ioctl.h b/arch/xtensa/include/asm/ioctl.h deleted file mode 100644 index b279fe06dfe..00000000000 --- a/arch/xtensa/include/asm/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/ioctl.h> diff --git a/arch/xtensa/include/asm/irq_regs.h b/arch/xtensa/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b7027..00000000000 --- a/arch/xtensa/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/irq_regs.h> diff --git a/arch/xtensa/include/asm/irqflags.h b/arch/xtensa/include/asm/irqflags.h index dae9a8bdcb1..f865b1c1eae 100644 --- a/arch/xtensa/include/asm/irqflags.h +++ b/arch/xtensa/include/asm/irqflags.h @@ -16,7 +16,7 @@ static inline unsigned long arch_local_save_flags(void) { unsigned long flags; - asm volatile("rsr %0,"__stringify(PS) : "=a" (flags)); + asm volatile("rsr %0, ps" : "=a" (flags)); return flags; } @@ -41,7 +41,7 @@ static inline void arch_local_irq_enable(void) static inline void arch_local_irq_restore(unsigned long flags) { - asm volatile("wsr %0, "__stringify(PS)" ; rsync" + asm volatile("wsr %0, ps; rsync" :: "a" (flags) : "memory"); } diff --git a/arch/xtensa/include/asm/kdebug.h b/arch/xtensa/include/asm/kdebug.h deleted file mode 100644 index 6ece1b03766..00000000000 --- a/arch/xtensa/include/asm/kdebug.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/kdebug.h> diff --git a/arch/xtensa/include/asm/kmap_types.h b/arch/xtensa/include/asm/kmap_types.h deleted file mode 100644 index 11c687e527f..00000000000 --- a/arch/xtensa/include/asm/kmap_types.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _XTENSA_KMAP_TYPES_H -#define _XTENSA_KMAP_TYPES_H - -#include <asm-generic/kmap_types.h> - -#endif /* _XTENSA_KMAP_TYPES_H */ diff --git a/arch/xtensa/include/asm/kvm_para.h b/arch/xtensa/include/asm/kvm_para.h deleted file mode 100644 index 14fab8f0b95..00000000000 --- a/arch/xtensa/include/asm/kvm_para.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/kvm_para.h> diff --git a/arch/xtensa/include/asm/local.h b/arch/xtensa/include/asm/local.h deleted file mode 100644 index 48723e550d1..00000000000 --- a/arch/xtensa/include/asm/local.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/local.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_LOCAL_H -#define _XTENSA_LOCAL_H - -#include <asm-generic/local.h> - -#endif /* _XTENSA_LOCAL_H */ diff --git a/arch/xtensa/include/asm/local64.h b/arch/xtensa/include/asm/local64.h deleted file mode 100644 index 36c93b5cc23..00000000000 --- a/arch/xtensa/include/asm/local64.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/local64.h> diff --git a/arch/xtensa/include/asm/mmu_context.h b/arch/xtensa/include/asm/mmu_context.h index dbd8731a876..feb10af9651 100644 --- a/arch/xtensa/include/asm/mmu_context.h +++ b/arch/xtensa/include/asm/mmu_context.h @@ -51,14 +51,14 @@ extern unsigned long asid_cache; static inline void set_rasid_register (unsigned long val) { - __asm__ __volatile__ (" wsr %0, "__stringify(RASID)"\n\t" + __asm__ __volatile__ (" wsr %0, rasid\n\t" " isync\n" : : "a" (val)); } static inline unsigned long get_rasid_register (void) { unsigned long tmp; - __asm__ __volatile__ (" rsr %0,"__stringify(RASID)"\n\t" : "=a" (tmp)); + __asm__ __volatile__ (" rsr %0, rasid\n\t" : "=a" (tmp)); return tmp; } diff --git a/arch/xtensa/include/asm/param.h b/arch/xtensa/include/asm/param.h index ba03d5aeab6..0a70e780ef2 100644 --- a/arch/xtensa/include/asm/param.h +++ b/arch/xtensa/include/asm/param.h @@ -7,28 +7,12 @@ * * Copyright (C) 2001 - 2005 Tensilica Inc. */ - #ifndef _XTENSA_PARAM_H #define _XTENSA_PARAM_H -#ifdef __KERNEL__ +#include <uapi/asm/param.h> + # define HZ CONFIG_HZ /* internal timer frequency */ # define USER_HZ 100 /* for user interfaces in "ticks" */ # define CLOCKS_PER_SEC (USER_HZ) /* frequnzy at which times() counts */ -#else -# define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NGROUPS -#define NGROUPS 32 -#endif - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - #endif /* _XTENSA_PARAM_H */ diff --git a/arch/xtensa/include/asm/percpu.h b/arch/xtensa/include/asm/percpu.h deleted file mode 100644 index 6d2bc2ada9d..00000000000 --- a/arch/xtensa/include/asm/percpu.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * linux/include/asm-xtensa/percpu.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_PERCPU__ -#define _XTENSA_PERCPU__ - -#include <asm-generic/percpu.h> - -#endif /* _XTENSA_PERCPU__ */ diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index 5c371d8d452..2d630e7399c 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h @@ -152,6 +152,7 @@ struct thread_struct { /* Clearing a0 terminates the backtrace. */ #define start_thread(regs, new_pc, new_sp) \ + memset(regs, 0, sizeof(*regs)); \ regs->pc = new_pc; \ regs->ps = USER_PS_VALUE; \ regs->areg[1] = new_sp; \ @@ -168,9 +169,6 @@ struct mm_struct; /* Free all resources held by a thread. */ #define release_thread(thread) do { } while(0) -/* Create a kernel thread without removing it from tasklists */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - /* Copy and release all segment info associated with a VM */ #define copy_segments(p, mm) do { } while(0) #define release_segments(mm) do { } while(0) diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h index d85d38da8ee..da21c17f23a 100644 --- a/arch/xtensa/include/asm/ptrace.h +++ b/arch/xtensa/include/asm/ptrace.h @@ -7,73 +7,11 @@ * * Copyright (C) 2001 - 2005 Tensilica Inc. */ - #ifndef _XTENSA_PTRACE_H #define _XTENSA_PTRACE_H -/* - * Kernel stack - * - * +-----------------------+ -------- STACK_SIZE - * | register file | | - * +-----------------------+ | - * | struct pt_regs | | - * +-----------------------+ | ------ PT_REGS_OFFSET - * double : 16 bytes spill area : | ^ - * excetion :- - - - - - - - - - - -: | | - * frame : struct pt_regs : | | - * :- - - - - - - - - - - -: | | - * | | | | - * | memory stack | | | - * | | | | - * ~ ~ ~ ~ - * ~ ~ ~ ~ - * | | | | - * | | | | - * +-----------------------+ | | --- STACK_BIAS - * | struct task_struct | | | ^ - * current --> +-----------------------+ | | | - * | struct thread_info | | | | - * +-----------------------+ -------- - */ - -#define KERNEL_STACK_SIZE (2 * PAGE_SIZE) - -/* Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */ - -#define EXC_TABLE_KSTK 0x004 /* Kernel Stack */ -#define EXC_TABLE_DOUBLE_SAVE 0x008 /* Double exception save area for a0 */ -#define EXC_TABLE_FIXUP 0x00c /* Fixup handler */ -#define EXC_TABLE_PARAM 0x010 /* For passing a parameter to fixup */ -#define EXC_TABLE_SYSCALL_SAVE 0x014 /* For fast syscall handler */ -#define EXC_TABLE_FAST_USER 0x100 /* Fast user exception handler */ -#define EXC_TABLE_FAST_KERNEL 0x200 /* Fast kernel exception handler */ -#define EXC_TABLE_DEFAULT 0x300 /* Default C-Handler */ -#define EXC_TABLE_SIZE 0x400 +#include <uapi/asm/ptrace.h> -/* Registers used by strace */ - -#define REG_A_BASE 0x0000 -#define REG_AR_BASE 0x0100 -#define REG_PC 0x0020 -#define REG_PS 0x02e6 -#define REG_WB 0x0248 -#define REG_WS 0x0249 -#define REG_LBEG 0x0200 -#define REG_LEND 0x0201 -#define REG_LCOUNT 0x0202 -#define REG_SAR 0x0203 - -#define SYSCALL_NR 0x00ff - -/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */ - -#define PTRACE_GETREGS 12 -#define PTRACE_SETREGS 13 -#define PTRACE_GETXTREGS 18 -#define PTRACE_SETXTREGS 19 - -#ifdef __KERNEL__ #ifndef __ASSEMBLY__ @@ -132,6 +70,4 @@ struct pt_regs { #endif /* !__ASSEMBLY__ */ -#endif /* __KERNEL__ */ - #endif /* _XTENSA_PTRACE_H */ diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h index a3075b12aff..8a8aa61ccc8 100644 --- a/arch/xtensa/include/asm/regs.h +++ b/arch/xtensa/include/asm/regs.h @@ -27,52 +27,15 @@ /* Special registers. */ -#define LBEG 0 -#define LEND 1 -#define LCOUNT 2 -#define SAR 3 -#define BR 4 -#define SCOMPARE1 12 -#define ACCHI 16 -#define ACCLO 17 -#define MR 32 -#define WINDOWBASE 72 -#define WINDOWSTART 73 -#define PTEVADDR 83 -#define RASID 90 -#define ITLBCFG 91 -#define DTLBCFG 92 -#define IBREAKENABLE 96 -#define DDR 104 -#define IBREAKA 128 -#define DBREAKA 144 -#define DBREAKC 160 -#define EPC 176 -#define EPC_1 177 -#define DEPC 192 -#define EPS 192 -#define EPS_1 193 -#define EXCSAVE 208 -#define EXCSAVE_1 209 -#define INTERRUPT 226 -#define INTENABLE 228 -#define PS 230 -#define THREADPTR 231 -#define EXCCAUSE 232 -#define DEBUGCAUSE 233 -#define CCOUNT 234 -#define PRID 235 -#define ICOUNT 236 -#define ICOUNTLEVEL 237 -#define EXCVADDR 238 -#define CCOMPARE 240 -#define MISC_SR 244 - -/* Special names for read-only and write-only interrupt registers. */ - -#define INTREAD 226 -#define INTSET 226 -#define INTCLEAR 227 +#define SREG_MR 32 +#define SREG_IBREAKA 128 +#define SREG_DBREAKA 144 +#define SREG_DBREAKC 160 +#define SREG_EPC 176 +#define SREG_EPS 192 +#define SREG_EXCSAVE 208 +#define SREG_CCOMPARE 240 +#define SREG_MISC 244 /* EXCCAUSE register fields */ diff --git a/arch/xtensa/include/asm/resource.h b/arch/xtensa/include/asm/resource.h deleted file mode 100644 index 17b5ab31177..00000000000 --- a/arch/xtensa/include/asm/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/resource.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_RESOURCE_H -#define _XTENSA_RESOURCE_H - -#include <asm-generic/resource.h> - -#endif /* _XTENSA_RESOURCE_H */ diff --git a/arch/xtensa/include/asm/scatterlist.h b/arch/xtensa/include/asm/scatterlist.h deleted file mode 100644 index a0421a61d9e..00000000000 --- a/arch/xtensa/include/asm/scatterlist.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/scatterlist.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_SCATTERLIST_H -#define _XTENSA_SCATTERLIST_H - -#include <asm-generic/scatterlist.h> - -#endif /* _XTENSA_SCATTERLIST_H */ diff --git a/arch/xtensa/include/asm/sections.h b/arch/xtensa/include/asm/sections.h deleted file mode 100644 index 40b5191b55a..00000000000 --- a/arch/xtensa/include/asm/sections.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/sections.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_SECTIONS_H -#define _XTENSA_SECTIONS_H - -#include <asm-generic/sections.h> - -#endif /* _XTENSA_SECTIONS_H */ diff --git a/arch/xtensa/include/asm/siginfo.h b/arch/xtensa/include/asm/siginfo.h deleted file mode 100644 index 6916248295d..00000000000 --- a/arch/xtensa/include/asm/siginfo.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/siginfo.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_SIGINFO_H -#define _XTENSA_SIGINFO_H - -#include <asm-generic/siginfo.h> - -#endif /* _XTENSA_SIGINFO_H */ diff --git a/arch/xtensa/include/asm/signal.h b/arch/xtensa/include/asm/signal.h index 7f201b9d419..72fd44c85b7 100644 --- a/arch/xtensa/include/asm/signal.h +++ b/arch/xtensa/include/asm/signal.h @@ -9,117 +9,12 @@ * * Copyright (C) 2001 - 2005 Tensilica Inc. */ - #ifndef _XTENSA_SIGNAL_H #define _XTENSA_SIGNAL_H - -#define _NSIG 64 -#define _NSIG_BPW 32 -#define _NSIG_WORDS (_NSIG / _NSIG_BPW) - -#ifndef __ASSEMBLY__ - -#include <linux/types.h> - -/* Avoid too many header ordering problems. */ -struct siginfo; -typedef unsigned long old_sigset_t; /* at least 32 bits */ -typedef struct { - unsigned long sig[_NSIG_WORDS]; -} sigset_t; - -#endif - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* #define SIGLOST 29 */ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP 0x00000001 -#define SA_NOCLDWAIT 0x00000002 /* not supported yet */ -#define SA_SIGINFO 0x00000004 -#define SA_ONSTACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_NODEFER 0x40000000 -#define SA_RESETHAND 0x80000000 - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -#define SA_RESTORER 0x04000000 - -/* - * sigaltstack controls - */ -#define SS_ONSTACK 1 -#define SS_DISABLE 2 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 +#include <uapi/asm/signal.h> #ifndef __ASSEMBLY__ - -#define SIG_BLOCK 0 /* for blocking signals */ -#define SIG_UNBLOCK 1 /* for unblocking signals */ -#define SIG_SETMASK 2 /* for setting the signal mask */ - -/* Type of a signal handler. */ -typedef void (*__sighandler_t)(int); - -#define SIG_DFL ((__sighandler_t)0) /* default signal handling */ -#define SIG_IGN ((__sighandler_t)1) /* ignore signal */ -#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ - -#ifdef __KERNEL__ struct sigaction { __sighandler_t sa_handler; unsigned long sa_flags; @@ -131,35 +26,8 @@ struct k_sigaction { struct sigaction sa; }; -#else - -/* Here we must cater to libcs that poke about in kernel headers. */ - -struct sigaction { - union { - __sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo *, void *); - } _u; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -#define sa_handler _u._sa_handler -#define sa_sigaction _u._sa_sigaction - -#endif /* __KERNEL__ */ - -typedef struct sigaltstack { - void *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -#ifdef __KERNEL__ #include <asm/sigcontext.h> #define ptrace_signal_deliver(regs, cookie) do { } while (0) -#endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ #endif /* _XTENSA_SIGNAL_H */ diff --git a/arch/xtensa/include/asm/statfs.h b/arch/xtensa/include/asm/statfs.h deleted file mode 100644 index 9c3d1a21313..00000000000 --- a/arch/xtensa/include/asm/statfs.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * include/asm-xtensa/statfs.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_STATFS_H -#define _XTENSA_STATFS_H - -#include <asm-generic/statfs.h> - -#endif /* _XTENSA_STATFS_H */ - diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index c1dacca312f..124aeee0d38 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h @@ -10,7 +10,7 @@ struct pt_regs; struct sigaction; -asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*); +asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*); asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); asmlinkage long xtensa_ptrace(long, long, long, long); asmlinkage long xtensa_sigreturn(struct pt_regs*); diff --git a/arch/xtensa/include/asm/termios.h b/arch/xtensa/include/asm/termios.h deleted file mode 100644 index 4673f42f88a..00000000000 --- a/arch/xtensa/include/asm/termios.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * include/asm-xtensa/termios.h - * - * Copied from SH. - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_TERMIOS_H -#define _XTENSA_TERMIOS_H - -#include <asm/termbits.h> -#include <asm/ioctls.h> - -struct winsize { - unsigned short ws_row; - unsigned short ws_col; - unsigned short ws_xpixel; - unsigned short ws_ypixel; -}; - -#define NCC 8 -struct termio { - unsigned short c_iflag; /* input mode flags */ - unsigned short c_oflag; /* output mode flags */ - unsigned short c_cflag; /* control mode flags */ - unsigned short c_lflag; /* local mode flags */ - unsigned char c_line; /* line discipline */ - unsigned char c_cc[NCC]; /* control characters */ -}; - -/* Modem lines */ - -#define TIOCM_LE 0x001 -#define TIOCM_DTR 0x002 -#define TIOCM_RTS 0x004 -#define TIOCM_ST 0x008 -#define TIOCM_SR 0x010 -#define TIOCM_CTS 0x020 -#define TIOCM_CAR 0x040 -#define TIOCM_RNG 0x080 -#define TIOCM_DSR 0x100 -#define TIOCM_CD TIOCM_CAR -#define TIOCM_RI TIOCM_RNG -#define TIOCM_OUT1 0x2000 -#define TIOCM_OUT2 0x4000 -#define TIOCM_LOOP 0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ - -#ifdef __KERNEL__ - -/* intr=^C quit=^\ erase=del kill=^U - eof=^D vtime=\0 vmin=\1 sxtc=\0 - start=^Q stop=^S susp=^Z eol=\0 - reprint=^R discard=^U werase=^W lnext=^V - eol2=\0 -*/ -#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" - -/* - * Translate a "termio" structure into a "termios". Ugh. - */ - -#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ - unsigned short __tmp; \ - get_user(__tmp,&(termio)->x); \ - *(unsigned short *) &(termios)->x = __tmp; \ -} - -#define user_termio_to_kernel_termios(termios, termio) \ -({ \ - SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \ - copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ -}) - -/* - * Translate a "termios" structure into a "termio". Ugh. - */ - -#define kernel_termios_to_user_termio(termio, termios) \ -({ \ - put_user((termios)->c_iflag, &(termio)->c_iflag); \ - put_user((termios)->c_oflag, &(termio)->c_oflag); \ - put_user((termios)->c_cflag, &(termio)->c_cflag); \ - put_user((termios)->c_lflag, &(termio)->c_lflag); \ - put_user((termios)->c_line, &(termio)->c_line); \ - copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ -}) - -#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2)) -#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2)) -#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios)) -#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios)) - -#endif /* __KERNEL__ */ - -#endif /* _XTENSA_TERMIOS_H */ diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h index 053bc427210..175b3d5e1b0 100644 --- a/arch/xtensa/include/asm/timex.h +++ b/arch/xtensa/include/asm/timex.h @@ -63,10 +63,10 @@ extern cycles_t cacheflush_time; * Register access. */ -#define WSR_CCOUNT(r) asm volatile ("wsr %0,"__stringify(CCOUNT) :: "a" (r)) -#define RSR_CCOUNT(r) asm volatile ("rsr %0,"__stringify(CCOUNT) : "=a" (r)) -#define WSR_CCOMPARE(x,r) asm volatile ("wsr %0,"__stringify(CCOMPARE)"+"__stringify(x) :: "a"(r)) -#define RSR_CCOMPARE(x,r) asm volatile ("rsr %0,"__stringify(CCOMPARE)"+"__stringify(x) : "=a"(r)) +#define WSR_CCOUNT(r) asm volatile ("wsr %0, ccount" :: "a" (r)) +#define RSR_CCOUNT(r) asm volatile ("rsr %0, ccount" : "=a" (r)) +#define WSR_CCOMPARE(x,r) asm volatile ("wsr %0,"__stringify(SREG_CCOMPARE)"+"__stringify(x) :: "a"(r)) +#define RSR_CCOMPARE(x,r) asm volatile ("rsr %0,"__stringify(SREG_CCOMPARE)"+"__stringify(x) : "=a"(r)) static inline unsigned long get_ccount (void) { diff --git a/arch/xtensa/include/asm/tlbflush.h b/arch/xtensa/include/asm/tlbflush.h index 46d240074f7..43dd348a5a4 100644 --- a/arch/xtensa/include/asm/tlbflush.h +++ b/arch/xtensa/include/asm/tlbflush.h @@ -86,26 +86,26 @@ static inline void invalidate_dtlb_entry_no_isync (unsigned entry) static inline void set_itlbcfg_register (unsigned long val) { - __asm__ __volatile__("wsr %0, "__stringify(ITLBCFG)"\n\t" "isync\n\t" + __asm__ __volatile__("wsr %0, itlbcfg\n\t" "isync\n\t" : : "a" (val)); } static inline void set_dtlbcfg_register (unsigned long val) { - __asm__ __volatile__("wsr %0, "__stringify(DTLBCFG)"; dsync\n\t" + __asm__ __volatile__("wsr %0, dtlbcfg; dsync\n\t" : : "a" (val)); } static inline void set_ptevaddr_register (unsigned long val) { - __asm__ __volatile__(" wsr %0, "__stringify(PTEVADDR)"; isync\n" + __asm__ __volatile__(" wsr %0, ptevaddr; isync\n" : : "a" (val)); } static inline unsigned long read_ptevaddr_register (void) { unsigned long tmp; - __asm__ __volatile__("rsr %0, "__stringify(PTEVADDR)"\n\t" : "=a" (tmp)); + __asm__ __volatile__("rsr %0, ptevaddr\n\t" : "=a" (tmp)); return tmp; } diff --git a/arch/xtensa/include/asm/topology.h b/arch/xtensa/include/asm/topology.h deleted file mode 100644 index 7309e38a0cc..00000000000 --- a/arch/xtensa/include/asm/topology.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/topology.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_TOPOLOGY_H -#define _XTENSA_TOPOLOGY_H - -#include <asm-generic/topology.h> - -#endif /* _XTENSA_TOPOLOGY_H */ diff --git a/arch/xtensa/include/asm/types.h b/arch/xtensa/include/asm/types.h index 6d4db7e8ffa..2b410b8c7f7 100644 --- a/arch/xtensa/include/asm/types.h +++ b/arch/xtensa/include/asm/types.h @@ -7,30 +7,17 @@ * * Copyright (C) 2001 - 2005 Tensilica Inc. */ - #ifndef _XTENSA_TYPES_H #define _XTENSA_TYPES_H -#include <asm-generic/int-ll64.h> - -#ifdef __ASSEMBLY__ -# define __XTENSA_UL(x) (x) -# define __XTENSA_UL_CONST(x) x -#else -# define __XTENSA_UL(x) ((unsigned long)(x)) -# define __XTENSA_UL_CONST(x) x##UL -#endif +#include <uapi/asm/types.h> #ifndef __ASSEMBLY__ - /* * These aren't exported outside the kernel to avoid name space clashes */ -#ifdef __KERNEL__ #define BITS_PER_LONG 32 -#endif /* __KERNEL__ */ #endif - #endif /* _XTENSA_TYPES_H */ diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index bc7e005faa6..f4e6eaa40d1 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -1,712 +1,8 @@ -/* - * include/asm-xtensa/unistd.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - #ifndef _XTENSA_UNISTD_H #define _XTENSA_UNISTD_H -#ifndef __SYSCALL -# define __SYSCALL(nr,func,nargs) -#endif - -#define __NR_spill 0 -__SYSCALL( 0, sys_ni_syscall, 0) -#define __NR_xtensa 1 -__SYSCALL( 1, sys_ni_syscall, 0) -#define __NR_available4 2 -__SYSCALL( 2, sys_ni_syscall, 0) -#define __NR_available5 3 -__SYSCALL( 3, sys_ni_syscall, 0) -#define __NR_available6 4 -__SYSCALL( 4, sys_ni_syscall, 0) -#define __NR_available7 5 -__SYSCALL( 5, sys_ni_syscall, 0) -#define __NR_available8 6 -__SYSCALL( 6, sys_ni_syscall, 0) -#define __NR_available9 7 -__SYSCALL( 7, sys_ni_syscall, 0) - -/* File Operations */ - -#define __NR_open 8 -__SYSCALL( 8, sys_open, 3) -#define __NR_close 9 -__SYSCALL( 9, sys_close, 1) -#define __NR_dup 10 -__SYSCALL( 10, sys_dup, 1) -#define __NR_dup2 11 -__SYSCALL( 11, sys_dup2, 2) -#define __NR_read 12 -__SYSCALL( 12, sys_read, 3) -#define __NR_write 13 -__SYSCALL( 13, sys_write, 3) -#define __NR_select 14 -__SYSCALL( 14, sys_select, 5) -#define __NR_lseek 15 -__SYSCALL( 15, sys_lseek, 3) -#define __NR_poll 16 -__SYSCALL( 16, sys_poll, 3) -#define __NR__llseek 17 -__SYSCALL( 17, sys_llseek, 5) -#define __NR_epoll_wait 18 -__SYSCALL( 18, sys_epoll_wait, 4) -#define __NR_epoll_ctl 19 -__SYSCALL( 19, sys_epoll_ctl, 4) -#define __NR_epoll_create 20 -__SYSCALL( 20, sys_epoll_create, 1) -#define __NR_creat 21 -__SYSCALL( 21, sys_creat, 2) -#define __NR_truncate 22 -__SYSCALL( 22, sys_truncate, 2) -#define __NR_ftruncate 23 -__SYSCALL( 23, sys_ftruncate, 2) -#define __NR_readv 24 -__SYSCALL( 24, sys_readv, 3) -#define __NR_writev 25 -__SYSCALL( 25, sys_writev, 3) -#define __NR_fsync 26 -__SYSCALL( 26, sys_fsync, 1) -#define __NR_fdatasync 27 -__SYSCALL( 27, sys_fdatasync, 1) -#define __NR_truncate64 28 -__SYSCALL( 28, sys_truncate64, 2) -#define __NR_ftruncate64 29 -__SYSCALL( 29, sys_ftruncate64, 2) -#define __NR_pread64 30 -__SYSCALL( 30, sys_pread64, 6) -#define __NR_pwrite64 31 -__SYSCALL( 31, sys_pwrite64, 6) - -#define __NR_link 32 -__SYSCALL( 32, sys_link, 2) -#define __NR_rename 33 -__SYSCALL( 33, sys_rename, 2) -#define __NR_symlink 34 -__SYSCALL( 34, sys_symlink, 2) -#define __NR_readlink 35 -__SYSCALL( 35, sys_readlink, 3) -#define __NR_mknod 36 -__SYSCALL( 36, sys_mknod, 3) -#define __NR_pipe 37 -__SYSCALL( 37, sys_pipe, 1) -#define __NR_unlink 38 -__SYSCALL( 38, sys_unlink, 1) -#define __NR_rmdir 39 -__SYSCALL( 39, sys_rmdir, 1) - -#define __NR_mkdir 40 -__SYSCALL( 40, sys_mkdir, 2) -#define __NR_chdir 41 -__SYSCALL( 41, sys_chdir, 1) -#define __NR_fchdir 42 -__SYSCALL( 42, sys_fchdir, 1) -#define __NR_getcwd 43 -__SYSCALL( 43, sys_getcwd, 2) - -#define __NR_chmod 44 -__SYSCALL( 44, sys_chmod, 2) -#define __NR_chown 45 -__SYSCALL( 45, sys_chown, 3) -#define __NR_stat 46 -__SYSCALL( 46, sys_newstat, 2) -#define __NR_stat64 47 -__SYSCALL( 47, sys_stat64, 2) - -#define __NR_lchown 48 -__SYSCALL( 48, sys_lchown, 3) -#define __NR_lstat 49 -__SYSCALL( 49, sys_newlstat, 2) -#define __NR_lstat64 50 -__SYSCALL( 50, sys_lstat64, 2) -#define __NR_available51 51 -__SYSCALL( 51, sys_ni_syscall, 0) - -#define __NR_fchmod 52 -__SYSCALL( 52, sys_fchmod, 2) -#define __NR_fchown 53 -__SYSCALL( 53, sys_fchown, 3) -#define __NR_fstat 54 -__SYSCALL( 54, sys_newfstat, 2) -#define __NR_fstat64 55 -__SYSCALL( 55, sys_fstat64, 2) - -#define __NR_flock 56 -__SYSCALL( 56, sys_flock, 2) -#define __NR_access 57 -__SYSCALL( 57, sys_access, 2) -#define __NR_umask 58 -__SYSCALL( 58, sys_umask, 1) -#define __NR_getdents 59 -__SYSCALL( 59, sys_getdents, 3) -#define __NR_getdents64 60 -__SYSCALL( 60, sys_getdents64, 3) -#define __NR_fcntl64 61 -__SYSCALL( 61, sys_fcntl64, 3) -#define __NR_available62 62 -__SYSCALL( 62, sys_ni_syscall, 0) -#define __NR_fadvise64_64 63 -__SYSCALL( 63, xtensa_fadvise64_64, 6) -#define __NR_utime 64 /* glibc 2.3.3 ?? */ -__SYSCALL( 64, sys_utime, 2) -#define __NR_utimes 65 -__SYSCALL( 65, sys_utimes, 2) -#define __NR_ioctl 66 -__SYSCALL( 66, sys_ioctl, 3) -#define __NR_fcntl 67 -__SYSCALL( 67, sys_fcntl, 3) - -#define __NR_setxattr 68 -__SYSCALL( 68, sys_setxattr, 5) -#define __NR_getxattr 69 -__SYSCALL( 69, sys_getxattr, 4) -#define __NR_listxattr 70 -__SYSCALL( 70, sys_listxattr, 3) -#define __NR_removexattr 71 -__SYSCALL( 71, sys_removexattr, 2) -#define __NR_lsetxattr 72 -__SYSCALL( 72, sys_lsetxattr, 5) -#define __NR_lgetxattr 73 -__SYSCALL( 73, sys_lgetxattr, 4) -#define __NR_llistxattr 74 -__SYSCALL( 74, sys_llistxattr, 3) -#define __NR_lremovexattr 75 -__SYSCALL( 75, sys_lremovexattr, 2) -#define __NR_fsetxattr 76 -__SYSCALL( 76, sys_fsetxattr, 5) -#define __NR_fgetxattr 77 -__SYSCALL( 77, sys_fgetxattr, 4) -#define __NR_flistxattr 78 -__SYSCALL( 78, sys_flistxattr, 3) -#define __NR_fremovexattr 79 -__SYSCALL( 79, sys_fremovexattr, 2) - -/* File Map / Shared Memory Operations */ - -#define __NR_mmap2 80 -__SYSCALL( 80, sys_mmap_pgoff, 6) -#define __NR_munmap 81 -__SYSCALL( 81, sys_munmap, 2) -#define __NR_mprotect 82 -__SYSCALL( 82, sys_mprotect, 3) -#define __NR_brk 83 -__SYSCALL( 83, sys_brk, 1) -#define __NR_mlock 84 -__SYSCALL( 84, sys_mlock, 2) -#define __NR_munlock 85 -__SYSCALL( 85, sys_munlock, 2) -#define __NR_mlockall 86 -__SYSCALL( 86, sys_mlockall, 1) -#define __NR_munlockall 87 -__SYSCALL( 87, sys_munlockall, 0) -#define __NR_mremap 88 -__SYSCALL( 88, sys_mremap, 4) -#define __NR_msync 89 -__SYSCALL( 89, sys_msync, 3) -#define __NR_mincore 90 -__SYSCALL( 90, sys_mincore, 3) -#define __NR_madvise 91 -__SYSCALL( 91, sys_madvise, 3) -#define __NR_shmget 92 -__SYSCALL( 92, sys_shmget, 4) -#define __NR_shmat 93 -__SYSCALL( 93, xtensa_shmat, 4) -#define __NR_shmctl 94 -__SYSCALL( 94, sys_shmctl, 4) -#define __NR_shmdt 95 -__SYSCALL( 95, sys_shmdt, 4) - -/* Socket Operations */ - -#define __NR_socket 96 -__SYSCALL( 96, sys_socket, 3) -#define __NR_setsockopt 97 -__SYSCALL( 97, sys_setsockopt, 5) -#define __NR_getsockopt 98 -__SYSCALL( 98, sys_getsockopt, 5) -#define __NR_shutdown 99 -__SYSCALL( 99, sys_shutdown, 2) - -#define __NR_bind 100 -__SYSCALL(100, sys_bind, 3) -#define __NR_connect 101 -__SYSCALL(101, sys_connect, 3) -#define __NR_listen 102 -__SYSCALL(102, sys_listen, 2) -#define __NR_accept 103 -__SYSCALL(103, sys_accept, 3) - -#define __NR_getsockname 104 -__SYSCALL(104, sys_getsockname, 3) -#define __NR_getpeername 105 -__SYSCALL(105, sys_getpeername, 3) -#define __NR_sendmsg 106 -__SYSCALL(106, sys_sendmsg, 3) -#define __NR_recvmsg 107 -__SYSCALL(107, sys_recvmsg, 3) -#define __NR_send 108 -__SYSCALL(108, sys_send, 4) -#define __NR_recv 109 -__SYSCALL(109, sys_recv, 4) -#define __NR_sendto 110 -__SYSCALL(110, sys_sendto, 6) -#define __NR_recvfrom 111 -__SYSCALL(111, sys_recvfrom, 6) - -#define __NR_socketpair 112 -__SYSCALL(112, sys_socketpair, 4) -#define __NR_sendfile 113 -__SYSCALL(113, sys_sendfile, 4) -#define __NR_sendfile64 114 -__SYSCALL(114, sys_sendfile64, 4) -#define __NR_available115 115 -__SYSCALL(115, sys_ni_syscall, 0) - -/* Process Operations */ - -#define __NR_clone 116 -__SYSCALL(116, xtensa_clone, 5) -#define __NR_execve 117 -__SYSCALL(117, xtensa_execve, 3) -#define __NR_exit 118 -__SYSCALL(118, sys_exit, 1) -#define __NR_exit_group 119 -__SYSCALL(119, sys_exit_group, 1) -#define __NR_getpid 120 -__SYSCALL(120, sys_getpid, 0) -#define __NR_wait4 121 -__SYSCALL(121, sys_wait4, 4) -#define __NR_waitid 122 -__SYSCALL(122, sys_waitid, 5) -#define __NR_kill 123 -__SYSCALL(123, sys_kill, 2) -#define __NR_tkill 124 -__SYSCALL(124, sys_tkill, 2) -#define __NR_tgkill 125 -__SYSCALL(125, sys_tgkill, 3) -#define __NR_set_tid_address 126 -__SYSCALL(126, sys_set_tid_address, 1) -#define __NR_gettid 127 -__SYSCALL(127, sys_gettid, 0) -#define __NR_setsid 128 -__SYSCALL(128, sys_setsid, 0) -#define __NR_getsid 129 -__SYSCALL(129, sys_getsid, 1) -#define __NR_prctl 130 -__SYSCALL(130, sys_prctl, 5) -#define __NR_personality 131 -__SYSCALL(131, sys_personality, 1) -#define __NR_getpriority 132 -__SYSCALL(132, sys_getpriority, 2) -#define __NR_setpriority 133 -__SYSCALL(133, sys_setpriority, 3) -#define __NR_setitimer 134 -__SYSCALL(134, sys_setitimer, 3) -#define __NR_getitimer 135 -__SYSCALL(135, sys_getitimer, 2) -#define __NR_setuid 136 -__SYSCALL(136, sys_setuid, 1) -#define __NR_getuid 137 -__SYSCALL(137, sys_getuid, 0) -#define __NR_setgid 138 -__SYSCALL(138, sys_setgid, 1) -#define __NR_getgid 139 -__SYSCALL(139, sys_getgid, 0) -#define __NR_geteuid 140 -__SYSCALL(140, sys_geteuid, 0) -#define __NR_getegid 141 -__SYSCALL(141, sys_getegid, 0) -#define __NR_setreuid 142 -__SYSCALL(142, sys_setreuid, 2) -#define __NR_setregid 143 -__SYSCALL(143, sys_setregid, 2) -#define __NR_setresuid 144 -__SYSCALL(144, sys_setresuid, 3) -#define __NR_getresuid 145 -__SYSCALL(145, sys_getresuid, 3) -#define __NR_setresgid 146 -__SYSCALL(146, sys_setresgid, 3) -#define __NR_getresgid 147 -__SYSCALL(147, sys_getresgid, 3) -#define __NR_setpgid 148 -__SYSCALL(148, sys_setpgid, 2) -#define __NR_getpgid 149 -__SYSCALL(149, sys_getpgid, 1) -#define __NR_getppid 150 -__SYSCALL(150, sys_getppid, 0) -#define __NR_getpgrp 151 -__SYSCALL(151, sys_getpgrp, 0) - -#define __NR_reserved152 152 /* set_thread_area */ -__SYSCALL(152, sys_ni_syscall, 0) -#define __NR_reserved153 153 /* get_thread_area */ -__SYSCALL(153, sys_ni_syscall, 0) -#define __NR_times 154 -__SYSCALL(154, sys_times, 1) -#define __NR_acct 155 -__SYSCALL(155, sys_acct, 1) -#define __NR_sched_setaffinity 156 -__SYSCALL(156, sys_sched_setaffinity, 3) -#define __NR_sched_getaffinity 157 -__SYSCALL(157, sys_sched_getaffinity, 3) -#define __NR_capget 158 -__SYSCALL(158, sys_capget, 2) -#define __NR_capset 159 -__SYSCALL(159, sys_capset, 2) -#define __NR_ptrace 160 -__SYSCALL(160, sys_ptrace, 4) -#define __NR_semtimedop 161 -__SYSCALL(161, sys_semtimedop, 5) -#define __NR_semget 162 -__SYSCALL(162, sys_semget, 4) -#define __NR_semop 163 -__SYSCALL(163, sys_semop, 4) -#define __NR_semctl 164 -__SYSCALL(164, sys_semctl, 4) -#define __NR_available165 165 -__SYSCALL(165, sys_ni_syscall, 0) -#define __NR_msgget 166 -__SYSCALL(166, sys_msgget, 4) -#define __NR_msgsnd 167 -__SYSCALL(167, sys_msgsnd, 4) -#define __NR_msgrcv 168 -__SYSCALL(168, sys_msgrcv, 4) -#define __NR_msgctl 169 -__SYSCALL(169, sys_msgctl, 4) -#define __NR_available170 170 -__SYSCALL(170, sys_ni_syscall, 0) -#define __NR_available171 171 -__SYSCALL(171, sys_ni_syscall, 0) - -/* File System */ - -#define __NR_mount 172 -__SYSCALL(172, sys_mount, 5) -#define __NR_swapon 173 -__SYSCALL(173, sys_swapon, 2) -#define __NR_chroot 174 -__SYSCALL(174, sys_chroot, 1) -#define __NR_pivot_root 175 -__SYSCALL(175, sys_pivot_root, 2) -#define __NR_umount 176 -__SYSCALL(176, sys_umount, 2) -#define __NR_swapoff 177 -__SYSCALL(177, sys_swapoff, 1) -#define __NR_sync 178 -__SYSCALL(178, sys_sync, 0) -#define __NR_available179 179 -__SYSCALL(179, sys_ni_syscall, 0) -#define __NR_setfsuid 180 -__SYSCALL(180, sys_setfsuid, 1) -#define __NR_setfsgid 181 -__SYSCALL(181, sys_setfsgid, 1) -#define __NR_sysfs 182 -__SYSCALL(182, sys_sysfs, 3) -#define __NR_ustat 183 -__SYSCALL(183, sys_ustat, 2) -#define __NR_statfs 184 -__SYSCALL(184, sys_statfs, 2) -#define __NR_fstatfs 185 -__SYSCALL(185, sys_fstatfs, 2) -#define __NR_statfs64 186 -__SYSCALL(186, sys_statfs64, 3) -#define __NR_fstatfs64 187 -__SYSCALL(187, sys_fstatfs64, 3) - -/* System */ - -#define __NR_setrlimit 188 -__SYSCALL(188, sys_setrlimit, 2) -#define __NR_getrlimit 189 -__SYSCALL(189, sys_getrlimit, 2) -#define __NR_getrusage 190 -__SYSCALL(190, sys_getrusage, 2) -#define __NR_futex 191 -__SYSCALL(191, sys_futex, 5) -#define __NR_gettimeofday 192 -__SYSCALL(192, sys_gettimeofday, 2) -#define __NR_settimeofday 193 -__SYSCALL(193, sys_settimeofday, 2) -#define __NR_adjtimex 194 -__SYSCALL(194, sys_adjtimex, 1) -#define __NR_nanosleep 195 -__SYSCALL(195, sys_nanosleep, 2) -#define __NR_getgroups 196 -__SYSCALL(196, sys_getgroups, 2) -#define __NR_setgroups 197 -__SYSCALL(197, sys_setgroups, 2) -#define __NR_sethostname 198 -__SYSCALL(198, sys_sethostname, 2) -#define __NR_setdomainname 199 -__SYSCALL(199, sys_setdomainname, 2) -#define __NR_syslog 200 -__SYSCALL(200, sys_syslog, 3) -#define __NR_vhangup 201 -__SYSCALL(201, sys_vhangup, 0) -#define __NR_uselib 202 -__SYSCALL(202, sys_uselib, 1) -#define __NR_reboot 203 -__SYSCALL(203, sys_reboot, 3) -#define __NR_quotactl 204 -__SYSCALL(204, sys_quotactl, 4) -#define __NR_nfsservctl 205 -__SYSCALL(205, sys_ni_syscall, 0) -#define __NR__sysctl 206 -__SYSCALL(206, sys_sysctl, 1) -#define __NR_bdflush 207 -__SYSCALL(207, sys_bdflush, 2) -#define __NR_uname 208 -__SYSCALL(208, sys_newuname, 1) -#define __NR_sysinfo 209 -__SYSCALL(209, sys_sysinfo, 1) -#define __NR_init_module 210 -__SYSCALL(210, sys_init_module, 2) -#define __NR_delete_module 211 -__SYSCALL(211, sys_delete_module, 1) - -#define __NR_sched_setparam 212 -__SYSCALL(212, sys_sched_setparam, 2) -#define __NR_sched_getparam 213 -__SYSCALL(213, sys_sched_getparam, 2) -#define __NR_sched_setscheduler 214 -__SYSCALL(214, sys_sched_setscheduler, 3) -#define __NR_sched_getscheduler 215 -__SYSCALL(215, sys_sched_getscheduler, 1) -#define __NR_sched_get_priority_max 216 -__SYSCALL(216, sys_sched_get_priority_max, 1) -#define __NR_sched_get_priority_min 217 -__SYSCALL(217, sys_sched_get_priority_min, 1) -#define __NR_sched_rr_get_interval 218 -__SYSCALL(218, sys_sched_rr_get_interval, 2) -#define __NR_sched_yield 219 -__SYSCALL(219, sys_sched_yield, 0) -#define __NR_available222 222 -__SYSCALL(222, sys_ni_syscall, 0) - -/* Signal Handling */ - -#define __NR_restart_syscall 223 -__SYSCALL(223, sys_restart_syscall, 0) -#define __NR_sigaltstack 224 -__SYSCALL(224, xtensa_sigaltstack, 2) -#define __NR_rt_sigreturn 225 -__SYSCALL(225, xtensa_rt_sigreturn, 1) -#define __NR_rt_sigaction 226 -__SYSCALL(226, sys_rt_sigaction, 4) -#define __NR_rt_sigprocmask 227 -__SYSCALL(227, sys_rt_sigprocmask, 4) -#define __NR_rt_sigpending 228 -__SYSCALL(228, sys_rt_sigpending, 2) -#define __NR_rt_sigtimedwait 229 -__SYSCALL(229, sys_rt_sigtimedwait, 4) -#define __NR_rt_sigqueueinfo 230 -__SYSCALL(230, sys_rt_sigqueueinfo, 3) -#define __NR_rt_sigsuspend 231 -__SYSCALL(231, sys_rt_sigsuspend, 2) - -/* Message */ - -#define __NR_mq_open 232 -__SYSCALL(232, sys_mq_open, 4) -#define __NR_mq_unlink 233 -__SYSCALL(233, sys_mq_unlink, 1) -#define __NR_mq_timedsend 234 -__SYSCALL(234, sys_mq_timedsend, 5) -#define __NR_mq_timedreceive 235 -__SYSCALL(235, sys_mq_timedreceive, 5) -#define __NR_mq_notify 236 -__SYSCALL(236, sys_mq_notify, 2) -#define __NR_mq_getsetattr 237 -__SYSCALL(237, sys_mq_getsetattr, 3) -#define __NR_available238 238 -__SYSCALL(238, sys_ni_syscall, 0) - -/* IO */ - -#define __NR_io_setup 239 -__SYSCALL(239, sys_io_setup, 2) -#define __NR_io_destroy 240 -__SYSCALL(240, sys_io_destroy, 1) -#define __NR_io_submit 241 -__SYSCALL(241, sys_io_submit, 3) -#define __NR_io_getevents 242 -__SYSCALL(242, sys_io_getevents, 5) -#define __NR_io_cancel 243 -__SYSCALL(243, sys_io_cancel, 3) -#define __NR_clock_settime 244 -__SYSCALL(244, sys_clock_settime, 2) -#define __NR_clock_gettime 245 -__SYSCALL(245, sys_clock_gettime, 2) -#define __NR_clock_getres 246 -__SYSCALL(246, sys_clock_getres, 2) -#define __NR_clock_nanosleep 247 -__SYSCALL(247, sys_clock_nanosleep, 4) - -/* Timer */ - -#define __NR_timer_create 248 -__SYSCALL(248, sys_timer_create, 3) -#define __NR_timer_delete 249 -__SYSCALL(249, sys_timer_delete, 1) -#define __NR_timer_settime 250 -__SYSCALL(250, sys_timer_settime, 4) -#define __NR_timer_gettime 251 -__SYSCALL(251, sys_timer_gettime, 2) -#define __NR_timer_getoverrun 252 -__SYSCALL(252, sys_timer_getoverrun, 1) - -/* System */ - -#define __NR_reserved244 253 -__SYSCALL(253, sys_ni_syscall, 0) -#define __NR_lookup_dcookie 254 -__SYSCALL(254, sys_lookup_dcookie, 4) -#define __NR_available255 255 -__SYSCALL(255, sys_ni_syscall, 0) -#define __NR_add_key 256 -__SYSCALL(256, sys_add_key, 5) -#define __NR_request_key 257 -__SYSCALL(257, sys_request_key, 5) -#define __NR_keyctl 258 -__SYSCALL(258, sys_keyctl, 5) -#define __NR_available259 259 -__SYSCALL(259, sys_ni_syscall, 0) - - -#define __NR_readahead 260 -__SYSCALL(260, sys_readahead, 5) -#define __NR_remap_file_pages 261 -__SYSCALL(261, sys_remap_file_pages, 5) -#define __NR_migrate_pages 262 -__SYSCALL(262, sys_migrate_pages, 0) -#define __NR_mbind 263 -__SYSCALL(263, sys_mbind, 6) -#define __NR_get_mempolicy 264 -__SYSCALL(264, sys_get_mempolicy, 5) -#define __NR_set_mempolicy 265 -__SYSCALL(265, sys_set_mempolicy, 3) -#define __NR_unshare 266 -__SYSCALL(266, sys_unshare, 1) -#define __NR_move_pages 267 -__SYSCALL(267, sys_move_pages, 0) -#define __NR_splice 268 -__SYSCALL(268, sys_splice, 0) -#define __NR_tee 269 -__SYSCALL(269, sys_tee, 0) -#define __NR_vmsplice 270 -__SYSCALL(270, sys_vmsplice, 0) -#define __NR_available271 271 -__SYSCALL(271, sys_ni_syscall, 0) - -#define __NR_pselect6 272 -__SYSCALL(272, sys_pselect6, 0) -#define __NR_ppoll 273 -__SYSCALL(273, sys_ppoll, 0) -#define __NR_epoll_pwait 274 -__SYSCALL(274, sys_epoll_pwait, 0) -#define __NR_available275 275 -__SYSCALL(275, sys_ni_syscall, 0) - -#define __NR_inotify_init 276 -__SYSCALL(276, sys_inotify_init, 0) -#define __NR_inotify_add_watch 277 -__SYSCALL(277, sys_inotify_add_watch, 3) -#define __NR_inotify_rm_watch 278 -__SYSCALL(278, sys_inotify_rm_watch, 2) -#define __NR_available279 279 -__SYSCALL(279, sys_ni_syscall, 0) - -#define __NR_getcpu 280 -__SYSCALL(280, sys_getcpu, 0) -#define __NR_kexec_load 281 -__SYSCALL(281, sys_ni_syscall, 0) - -#define __NR_ioprio_set 282 -__SYSCALL(282, sys_ioprio_set, 2) -#define __NR_ioprio_get 283 -__SYSCALL(283, sys_ioprio_get, 3) - -#define __NR_set_robust_list 284 -__SYSCALL(284, sys_set_robust_list, 3) -#define __NR_get_robust_list 285 -__SYSCALL(285, sys_get_robust_list, 3) -#define __NR_reserved286 286 /* sync_file_rangeX */ -__SYSCALL(286, sys_ni_syscall, 3) -#define __NR_available287 287 -__SYSCALL(287, sys_faccessat, 0) - -/* Relative File Operations */ - -#define __NR_openat 288 -__SYSCALL(288, sys_openat, 4) -#define __NR_mkdirat 289 -__SYSCALL(289, sys_mkdirat, 3) -#define __NR_mknodat 290 -__SYSCALL(290, sys_mknodat, 4) -#define __NR_unlinkat 291 -__SYSCALL(291, sys_unlinkat, 3) -#define __NR_renameat 292 -__SYSCALL(292, sys_renameat, 4) -#define __NR_linkat 293 -__SYSCALL(293, sys_linkat, 5) -#define __NR_symlinkat 294 -__SYSCALL(294, sys_symlinkat, 3) -#define __NR_readlinkat 295 -__SYSCALL(295, sys_readlinkat, 4) -#define __NR_utimensat 296 -__SYSCALL(296, sys_utimensat, 0) -#define __NR_fchownat 297 -__SYSCALL(297, sys_fchownat, 5) -#define __NR_futimesat 298 -__SYSCALL(298, sys_futimesat, 4) -#define __NR_fstatat64 299 -__SYSCALL(299, sys_fstatat64, 0) -#define __NR_fchmodat 300 -__SYSCALL(300, sys_fchmodat, 4) -#define __NR_faccessat 301 -__SYSCALL(301, sys_faccessat, 4) -#define __NR_available302 302 -__SYSCALL(302, sys_ni_syscall, 0) -#define __NR_available303 303 -__SYSCALL(303, sys_ni_syscall, 0) - -#define __NR_signalfd 304 -__SYSCALL(304, sys_signalfd, 3) -/* 305 was __NR_timerfd */ -__SYSCALL(305, sys_ni_syscall, 0) -#define __NR_eventfd 306 -__SYSCALL(306, sys_eventfd, 1) -#define __NR_recvmmsg 307 -__SYSCALL(307, sys_recvmmsg, 5) -#define __NR_setns 308 -__SYSCALL(308, sys_setns, 2) - -#define __NR_syscall_count 309 - -/* - * sysxtensa syscall handler - * - * int sysxtensa (SYS_XTENSA_ATOMIC_SET, ptr, val, unused); - * int sysxtensa (SYS_XTENSA_ATOMIC_ADD, ptr, val, unused); - * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val, unused); - * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval); - * a2 a6 a3 a4 a5 - */ - -#define SYS_XTENSA_RESERVED 0 /* don't use this */ -#define SYS_XTENSA_ATOMIC_SET 1 /* set variable */ -#define SYS_XTENSA_ATOMIC_EXG_ADD 2 /* exchange memory and add */ -#define SYS_XTENSA_ATOMIC_ADD 3 /* add to memory */ -#define SYS_XTENSA_ATOMIC_CMP_SWP 4 /* compare and swap */ - -#define SYS_XTENSA_COUNT 5 /* count */ - -#ifdef __KERNEL__ +#define __ARCH_WANT_SYS_EXECVE +#include <uapi/asm/unistd.h> /* * "Conditional" syscalls @@ -735,5 +31,4 @@ __SYSCALL(308, sys_setns, 2) #define __IGNORE_vfork /* use clone */ #define __IGNORE_fadvise64 /* use fadvise64_64 */ -#endif /* __KERNEL__ */ -#endif /* _XTENSA_UNISTD_H */ +#endif /* _XTENSA_UNISTD_H */ diff --git a/arch/xtensa/include/asm/xor.h b/arch/xtensa/include/asm/xor.h deleted file mode 100644 index e7b1f083991..00000000000 --- a/arch/xtensa/include/asm/xor.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * include/asm-xtensa/xor.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ - -#ifndef _XTENSA_XOR_H -#define _XTENSA_XOR_H - -#include <asm-generic/xor.h> - -#endif diff --git a/arch/xtensa/include/uapi/asm/Kbuild b/arch/xtensa/include/uapi/asm/Kbuild index baebb3da1d4..56aad54e7fb 100644 --- a/arch/xtensa/include/uapi/asm/Kbuild +++ b/arch/xtensa/include/uapi/asm/Kbuild @@ -1,3 +1,25 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm +header-y += auxvec.h +header-y += byteorder.h +header-y += ioctls.h +header-y += ipcbuf.h +header-y += mman.h +header-y += msgbuf.h +header-y += param.h +header-y += poll.h +header-y += posix_types.h +header-y += ptrace.h +header-y += sembuf.h +header-y += setup.h +header-y += shmbuf.h +header-y += sigcontext.h +header-y += signal.h +header-y += socket.h +header-y += sockios.h +header-y += stat.h +header-y += swab.h +header-y += termbits.h +header-y += types.h +header-y += unistd.h diff --git a/arch/xtensa/include/asm/auxvec.h b/arch/xtensa/include/uapi/asm/auxvec.h index 257dec75c5a..257dec75c5a 100644 --- a/arch/xtensa/include/asm/auxvec.h +++ b/arch/xtensa/include/uapi/asm/auxvec.h diff --git a/arch/xtensa/include/asm/byteorder.h b/arch/xtensa/include/uapi/asm/byteorder.h index 54eb6315349..54eb6315349 100644 --- a/arch/xtensa/include/asm/byteorder.h +++ b/arch/xtensa/include/uapi/asm/byteorder.h diff --git a/arch/xtensa/include/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h index 2aa4cd9f0ce..2aa4cd9f0ce 100644 --- a/arch/xtensa/include/asm/ioctls.h +++ b/arch/xtensa/include/uapi/asm/ioctls.h diff --git a/arch/xtensa/include/asm/ipcbuf.h b/arch/xtensa/include/uapi/asm/ipcbuf.h index c33aa6a4214..c33aa6a4214 100644 --- a/arch/xtensa/include/asm/ipcbuf.h +++ b/arch/xtensa/include/uapi/asm/ipcbuf.h diff --git a/arch/xtensa/include/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h index 25bc6c1309c..25bc6c1309c 100644 --- a/arch/xtensa/include/asm/mman.h +++ b/arch/xtensa/include/uapi/asm/mman.h diff --git a/arch/xtensa/include/asm/msgbuf.h b/arch/xtensa/include/uapi/asm/msgbuf.h index 693c9675528..693c9675528 100644 --- a/arch/xtensa/include/asm/msgbuf.h +++ b/arch/xtensa/include/uapi/asm/msgbuf.h diff --git a/arch/xtensa/include/uapi/asm/param.h b/arch/xtensa/include/uapi/asm/param.h new file mode 100644 index 00000000000..87bc2eae630 --- /dev/null +++ b/arch/xtensa/include/uapi/asm/param.h @@ -0,0 +1,30 @@ +/* + * include/asm-xtensa/param.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2005 Tensilica Inc. + */ + +#ifndef _UAPI_XTENSA_PARAM_H +#define _UAPI_XTENSA_PARAM_H + +#ifndef __KERNEL__ +# define HZ 100 +#endif + +#define EXEC_PAGESIZE 4096 + +#ifndef NGROUPS +#define NGROUPS 32 +#endif + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif /* _UAPI_XTENSA_PARAM_H */ diff --git a/arch/xtensa/include/asm/poll.h b/arch/xtensa/include/uapi/asm/poll.h index 9d2d5993f06..9d2d5993f06 100644 --- a/arch/xtensa/include/asm/poll.h +++ b/arch/xtensa/include/uapi/asm/poll.h diff --git a/arch/xtensa/include/asm/posix_types.h b/arch/xtensa/include/uapi/asm/posix_types.h index 6e96be0d02d..6e96be0d02d 100644 --- a/arch/xtensa/include/asm/posix_types.h +++ b/arch/xtensa/include/uapi/asm/posix_types.h diff --git a/arch/xtensa/include/uapi/asm/ptrace.h b/arch/xtensa/include/uapi/asm/ptrace.h new file mode 100644 index 00000000000..ee17aa842fd --- /dev/null +++ b/arch/xtensa/include/uapi/asm/ptrace.h @@ -0,0 +1,77 @@ +/* + * include/asm-xtensa/ptrace.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2005 Tensilica Inc. + */ + +#ifndef _UAPI_XTENSA_PTRACE_H +#define _UAPI_XTENSA_PTRACE_H + +/* + * Kernel stack + * + * +-----------------------+ -------- STACK_SIZE + * | register file | | + * +-----------------------+ | + * | struct pt_regs | | + * +-----------------------+ | ------ PT_REGS_OFFSET + * double : 16 bytes spill area : | ^ + * excetion :- - - - - - - - - - - -: | | + * frame : struct pt_regs : | | + * :- - - - - - - - - - - -: | | + * | | | | + * | memory stack | | | + * | | | | + * ~ ~ ~ ~ + * ~ ~ ~ ~ + * | | | | + * | | | | + * +-----------------------+ | | --- STACK_BIAS + * | struct task_struct | | | ^ + * current --> +-----------------------+ | | | + * | struct thread_info | | | | + * +-----------------------+ -------- + */ + +#define KERNEL_STACK_SIZE (2 * PAGE_SIZE) + +/* Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */ + +#define EXC_TABLE_KSTK 0x004 /* Kernel Stack */ +#define EXC_TABLE_DOUBLE_SAVE 0x008 /* Double exception save area for a0 */ +#define EXC_TABLE_FIXUP 0x00c /* Fixup handler */ +#define EXC_TABLE_PARAM 0x010 /* For passing a parameter to fixup */ +#define EXC_TABLE_SYSCALL_SAVE 0x014 /* For fast syscall handler */ +#define EXC_TABLE_FAST_USER 0x100 /* Fast user exception handler */ +#define EXC_TABLE_FAST_KERNEL 0x200 /* Fast kernel exception handler */ +#define EXC_TABLE_DEFAULT 0x300 /* Default C-Handler */ +#define EXC_TABLE_SIZE 0x400 + +/* Registers used by strace */ + +#define REG_A_BASE 0x0000 +#define REG_AR_BASE 0x0100 +#define REG_PC 0x0020 +#define REG_PS 0x02e6 +#define REG_WB 0x0248 +#define REG_WS 0x0249 +#define REG_LBEG 0x0200 +#define REG_LEND 0x0201 +#define REG_LCOUNT 0x0202 +#define REG_SAR 0x0203 + +#define SYSCALL_NR 0x00ff + +/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */ + +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETXTREGS 18 +#define PTRACE_SETXTREGS 19 + + +#endif /* _UAPI_XTENSA_PTRACE_H */ diff --git a/arch/xtensa/include/asm/sembuf.h b/arch/xtensa/include/uapi/asm/sembuf.h index c15870493b3..c15870493b3 100644 --- a/arch/xtensa/include/asm/sembuf.h +++ b/arch/xtensa/include/uapi/asm/sembuf.h diff --git a/arch/xtensa/include/asm/setup.h b/arch/xtensa/include/uapi/asm/setup.h index 9fa8ad97936..9fa8ad97936 100644 --- a/arch/xtensa/include/asm/setup.h +++ b/arch/xtensa/include/uapi/asm/setup.h diff --git a/arch/xtensa/include/asm/shmbuf.h b/arch/xtensa/include/uapi/asm/shmbuf.h index ad4b0121782..ad4b0121782 100644 --- a/arch/xtensa/include/asm/shmbuf.h +++ b/arch/xtensa/include/uapi/asm/shmbuf.h diff --git a/arch/xtensa/include/asm/sigcontext.h b/arch/xtensa/include/uapi/asm/sigcontext.h index 03383af8c3b..03383af8c3b 100644 --- a/arch/xtensa/include/asm/sigcontext.h +++ b/arch/xtensa/include/uapi/asm/sigcontext.h diff --git a/arch/xtensa/include/uapi/asm/signal.h b/arch/xtensa/include/uapi/asm/signal.h new file mode 100644 index 00000000000..b88ce96f2af --- /dev/null +++ b/arch/xtensa/include/uapi/asm/signal.h @@ -0,0 +1,148 @@ +/* + * include/asm-xtensa/signal.h + * + * Swiped from SH. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2005 Tensilica Inc. + */ + +#ifndef _UAPI_XTENSA_SIGNAL_H +#define _UAPI_XTENSA_SIGNAL_H + + +#define _NSIG 64 +#define _NSIG_BPW 32 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> + +/* Avoid too many header ordering problems. */ +struct siginfo; +typedef unsigned long old_sigset_t; /* at least 32 bits */ +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +#endif + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +/* #define SIGLOST 29 */ +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED 31 + +/* These should not be considered constants from userland. */ +#define SIGRTMIN 32 +#define SIGRTMAX (_NSIG-1) + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP 0x00000001 +#define SA_NOCLDWAIT 0x00000002 /* not supported yet */ +#define SA_SIGINFO 0x00000004 +#define SA_ONSTACK 0x08000000 +#define SA_RESTART 0x10000000 +#define SA_NODEFER 0x40000000 +#define SA_RESETHAND 0x80000000 + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND + +#define SA_RESTORER 0x04000000 + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 + +#ifndef __ASSEMBLY__ + +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */ + +/* Type of a signal handler. */ +typedef void (*__sighandler_t)(int); + +#define SIG_DFL ((__sighandler_t)0) /* default signal handling */ +#define SIG_IGN ((__sighandler_t)1) /* ignore signal */ +#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ + +#ifndef __KERNEL__ + +/* Here we must cater to libcs that poke about in kernel headers. */ + +struct sigaction { + union { + __sighandler_t _sa_handler; + void (*_sa_sigaction)(int, struct siginfo *, void *); + } _u; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; + +#define sa_handler _u._sa_handler +#define sa_sigaction _u._sa_sigaction + +#endif /* __KERNEL__ */ + +typedef struct sigaltstack { + void *ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +#endif /* __ASSEMBLY__ */ +#endif /* _UAPI_XTENSA_SIGNAL_H */ diff --git a/arch/xtensa/include/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h index e36c6818492..e36c6818492 100644 --- a/arch/xtensa/include/asm/socket.h +++ b/arch/xtensa/include/uapi/asm/socket.h diff --git a/arch/xtensa/include/asm/sockios.h b/arch/xtensa/include/uapi/asm/sockios.h index efe0af379f0..efe0af379f0 100644 --- a/arch/xtensa/include/asm/sockios.h +++ b/arch/xtensa/include/uapi/asm/sockios.h diff --git a/arch/xtensa/include/asm/stat.h b/arch/xtensa/include/uapi/asm/stat.h index c4992038cee..c4992038cee 100644 --- a/arch/xtensa/include/asm/stat.h +++ b/arch/xtensa/include/uapi/asm/stat.h diff --git a/arch/xtensa/include/asm/swab.h b/arch/xtensa/include/uapi/asm/swab.h index 226a3916231..226a3916231 100644 --- a/arch/xtensa/include/asm/swab.h +++ b/arch/xtensa/include/uapi/asm/swab.h diff --git a/arch/xtensa/include/asm/termbits.h b/arch/xtensa/include/uapi/asm/termbits.h index 0d6c8715b24..0d6c8715b24 100644 --- a/arch/xtensa/include/asm/termbits.h +++ b/arch/xtensa/include/uapi/asm/termbits.h diff --git a/arch/xtensa/include/uapi/asm/types.h b/arch/xtensa/include/uapi/asm/types.h new file mode 100644 index 00000000000..87ec7ae73cb --- /dev/null +++ b/arch/xtensa/include/uapi/asm/types.h @@ -0,0 +1,28 @@ +/* + * include/asm-xtensa/types.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 - 2005 Tensilica Inc. + */ + +#ifndef _UAPI_XTENSA_TYPES_H +#define _UAPI_XTENSA_TYPES_H + +#include <asm-generic/int-ll64.h> + +#ifdef __ASSEMBLY__ +# define __XTENSA_UL(x) (x) +# define __XTENSA_UL_CONST(x) x +#else +# define __XTENSA_UL(x) ((unsigned long)(x)) +# define __XTENSA_UL_CONST(x) x##UL +#endif + +#ifndef __ASSEMBLY__ + +#endif + +#endif /* _UAPI_XTENSA_TYPES_H */ diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h new file mode 100644 index 00000000000..9f36d0e3e0a --- /dev/null +++ b/arch/xtensa/include/uapi/asm/unistd.h @@ -0,0 +1,754 @@ +#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL) +#define _UAPI_XTENSA_UNISTD_H + +#ifndef __SYSCALL +# define __SYSCALL(nr,func,nargs) +#endif + +#define __NR_spill 0 +__SYSCALL( 0, sys_ni_syscall, 0) +#define __NR_xtensa 1 +__SYSCALL( 1, sys_ni_syscall, 0) +#define __NR_available4 2 +__SYSCALL( 2, sys_ni_syscall, 0) +#define __NR_available5 3 +__SYSCALL( 3, sys_ni_syscall, 0) +#define __NR_available6 4 +__SYSCALL( 4, sys_ni_syscall, 0) +#define __NR_available7 5 +__SYSCALL( 5, sys_ni_syscall, 0) +#define __NR_available8 6 +__SYSCALL( 6, sys_ni_syscall, 0) +#define __NR_available9 7 +__SYSCALL( 7, sys_ni_syscall, 0) + +/* File Operations */ + +#define __NR_open 8 +__SYSCALL( 8, sys_open, 3) +#define __NR_close 9 +__SYSCALL( 9, sys_close, 1) +#define __NR_dup 10 +__SYSCALL( 10, sys_dup, 1) +#define __NR_dup2 11 +__SYSCALL( 11, sys_dup2, 2) +#define __NR_read 12 +__SYSCALL( 12, sys_read, 3) +#define __NR_write 13 +__SYSCALL( 13, sys_write, 3) +#define __NR_select 14 +__SYSCALL( 14, sys_select, 5) +#define __NR_lseek 15 +__SYSCALL( 15, sys_lseek, 3) +#define __NR_poll 16 +__SYSCALL( 16, sys_poll, 3) +#define __NR__llseek 17 +__SYSCALL( 17, sys_llseek, 5) +#define __NR_epoll_wait 18 +__SYSCALL( 18, sys_epoll_wait, 4) +#define __NR_epoll_ctl 19 +__SYSCALL( 19, sys_epoll_ctl, 4) +#define __NR_epoll_create 20 +__SYSCALL( 20, sys_epoll_create, 1) +#define __NR_creat 21 +__SYSCALL( 21, sys_creat, 2) +#define __NR_truncate 22 +__SYSCALL( 22, sys_truncate, 2) +#define __NR_ftruncate 23 +__SYSCALL( 23, sys_ftruncate, 2) +#define __NR_readv 24 +__SYSCALL( 24, sys_readv, 3) +#define __NR_writev 25 +__SYSCALL( 25, sys_writev, 3) +#define __NR_fsync 26 +__SYSCALL( 26, sys_fsync, 1) +#define __NR_fdatasync 27 +__SYSCALL( 27, sys_fdatasync, 1) +#define __NR_truncate64 28 +__SYSCALL( 28, sys_truncate64, 2) +#define __NR_ftruncate64 29 +__SYSCALL( 29, sys_ftruncate64, 2) +#define __NR_pread64 30 +__SYSCALL( 30, sys_pread64, 6) +#define __NR_pwrite64 31 +__SYSCALL( 31, sys_pwrite64, 6) + +#define __NR_link 32 +__SYSCALL( 32, sys_link, 2) +#define __NR_rename 33 +__SYSCALL( 33, sys_rename, 2) +#define __NR_symlink 34 +__SYSCALL( 34, sys_symlink, 2) +#define __NR_readlink 35 +__SYSCALL( 35, sys_readlink, 3) +#define __NR_mknod 36 +__SYSCALL( 36, sys_mknod, 3) +#define __NR_pipe 37 +__SYSCALL( 37, sys_pipe, 1) +#define __NR_unlink 38 +__SYSCALL( 38, sys_unlink, 1) +#define __NR_rmdir 39 +__SYSCALL( 39, sys_rmdir, 1) + +#define __NR_mkdir 40 +__SYSCALL( 40, sys_mkdir, 2) +#define __NR_chdir 41 +__SYSCALL( 41, sys_chdir, 1) +#define __NR_fchdir 42 +__SYSCALL( 42, sys_fchdir, 1) +#define __NR_getcwd 43 +__SYSCALL( 43, sys_getcwd, 2) + +#define __NR_chmod 44 +__SYSCALL( 44, sys_chmod, 2) +#define __NR_chown 45 +__SYSCALL( 45, sys_chown, 3) +#define __NR_stat 46 +__SYSCALL( 46, sys_newstat, 2) +#define __NR_stat64 47 +__SYSCALL( 47, sys_stat64, 2) + +#define __NR_lchown 48 +__SYSCALL( 48, sys_lchown, 3) +#define __NR_lstat 49 +__SYSCALL( 49, sys_newlstat, 2) +#define __NR_lstat64 50 +__SYSCALL( 50, sys_lstat64, 2) +#define __NR_available51 51 +__SYSCALL( 51, sys_ni_syscall, 0) + +#define __NR_fchmod 52 +__SYSCALL( 52, sys_fchmod, 2) +#define __NR_fchown 53 +__SYSCALL( 53, sys_fchown, 3) +#define __NR_fstat 54 +__SYSCALL( 54, sys_newfstat, 2) +#define __NR_fstat64 55 +__SYSCALL( 55, sys_fstat64, 2) + +#define __NR_flock 56 +__SYSCALL( 56, sys_flock, 2) +#define __NR_access 57 +__SYSCALL( 57, sys_access, 2) +#define __NR_umask 58 +__SYSCALL( 58, sys_umask, 1) +#define __NR_getdents 59 +__SYSCALL( 59, sys_getdents, 3) +#define __NR_getdents64 60 +__SYSCALL( 60, sys_getdents64, 3) +#define __NR_fcntl64 61 +__SYSCALL( 61, sys_fcntl64, 3) +#define __NR_fallocate 62 +__SYSCALL( 62, sys_fallocate, 6) +#define __NR_fadvise64_64 63 +__SYSCALL( 63, xtensa_fadvise64_64, 6) +#define __NR_utime 64 /* glibc 2.3.3 ?? */ +__SYSCALL( 64, sys_utime, 2) +#define __NR_utimes 65 +__SYSCALL( 65, sys_utimes, 2) +#define __NR_ioctl 66 +__SYSCALL( 66, sys_ioctl, 3) +#define __NR_fcntl 67 +__SYSCALL( 67, sys_fcntl, 3) + +#define __NR_setxattr 68 +__SYSCALL( 68, sys_setxattr, 5) +#define __NR_getxattr 69 +__SYSCALL( 69, sys_getxattr, 4) +#define __NR_listxattr 70 +__SYSCALL( 70, sys_listxattr, 3) +#define __NR_removexattr 71 +__SYSCALL( 71, sys_removexattr, 2) +#define __NR_lsetxattr 72 +__SYSCALL( 72, sys_lsetxattr, 5) +#define __NR_lgetxattr 73 +__SYSCALL( 73, sys_lgetxattr, 4) +#define __NR_llistxattr 74 +__SYSCALL( 74, sys_llistxattr, 3) +#define __NR_lremovexattr 75 +__SYSCALL( 75, sys_lremovexattr, 2) +#define __NR_fsetxattr 76 +__SYSCALL( 76, sys_fsetxattr, 5) +#define __NR_fgetxattr 77 +__SYSCALL( 77, sys_fgetxattr, 4) +#define __NR_flistxattr 78 +__SYSCALL( 78, sys_flistxattr, 3) +#define __NR_fremovexattr 79 +__SYSCALL( 79, sys_fremovexattr, 2) + +/* File Map / Shared Memory Operations */ + +#define __NR_mmap2 80 +__SYSCALL( 80, sys_mmap_pgoff, 6) +#define __NR_munmap 81 +__SYSCALL( 81, sys_munmap, 2) +#define __NR_mprotect 82 +__SYSCALL( 82, sys_mprotect, 3) +#define __NR_brk 83 +__SYSCALL( 83, sys_brk, 1) +#define __NR_mlock 84 +__SYSCALL( 84, sys_mlock, 2) +#define __NR_munlock 85 +__SYSCALL( 85, sys_munlock, 2) +#define __NR_mlockall 86 +__SYSCALL( 86, sys_mlockall, 1) +#define __NR_munlockall 87 +__SYSCALL( 87, sys_munlockall, 0) +#define __NR_mremap 88 +__SYSCALL( 88, sys_mremap, 4) +#define __NR_msync 89 +__SYSCALL( 89, sys_msync, 3) +#define __NR_mincore 90 +__SYSCALL( 90, sys_mincore, 3) +#define __NR_madvise 91 +__SYSCALL( 91, sys_madvise, 3) +#define __NR_shmget 92 +__SYSCALL( 92, sys_shmget, 4) +#define __NR_shmat 93 +__SYSCALL( 93, xtensa_shmat, 4) +#define __NR_shmctl 94 +__SYSCALL( 94, sys_shmctl, 4) +#define __NR_shmdt 95 +__SYSCALL( 95, sys_shmdt, 4) + +/* Socket Operations */ + +#define __NR_socket 96 +__SYSCALL( 96, sys_socket, 3) +#define __NR_setsockopt 97 +__SYSCALL( 97, sys_setsockopt, 5) +#define __NR_getsockopt 98 +__SYSCALL( 98, sys_getsockopt, 5) +#define __NR_shutdown 99 +__SYSCALL( 99, sys_shutdown, 2) + +#define __NR_bind 100 +__SYSCALL(100, sys_bind, 3) +#define __NR_connect 101 +__SYSCALL(101, sys_connect, 3) +#define __NR_listen 102 +__SYSCALL(102, sys_listen, 2) +#define __NR_accept 103 +__SYSCALL(103, sys_accept, 3) + +#define __NR_getsockname 104 +__SYSCALL(104, sys_getsockname, 3) +#define __NR_getpeername 105 +__SYSCALL(105, sys_getpeername, 3) +#define __NR_sendmsg 106 +__SYSCALL(106, sys_sendmsg, 3) +#define __NR_recvmsg 107 +__SYSCALL(107, sys_recvmsg, 3) +#define __NR_send 108 +__SYSCALL(108, sys_send, 4) +#define __NR_recv 109 +__SYSCALL(109, sys_recv, 4) +#define __NR_sendto 110 +__SYSCALL(110, sys_sendto, 6) +#define __NR_recvfrom 111 +__SYSCALL(111, sys_recvfrom, 6) + +#define __NR_socketpair 112 +__SYSCALL(112, sys_socketpair, 4) +#define __NR_sendfile 113 +__SYSCALL(113, sys_sendfile, 4) +#define __NR_sendfile64 114 +__SYSCALL(114, sys_sendfile64, 4) +#define __NR_sendmmsg 115 +__SYSCALL(115, sys_sendmmsg, 4) + +/* Process Operations */ + +#define __NR_clone 116 +__SYSCALL(116, xtensa_clone, 5) +#define __NR_execve 117 +__SYSCALL(117, sys_execve, 3) +#define __NR_exit 118 +__SYSCALL(118, sys_exit, 1) +#define __NR_exit_group 119 +__SYSCALL(119, sys_exit_group, 1) +#define __NR_getpid 120 +__SYSCALL(120, sys_getpid, 0) +#define __NR_wait4 121 +__SYSCALL(121, sys_wait4, 4) +#define __NR_waitid 122 +__SYSCALL(122, sys_waitid, 5) +#define __NR_kill 123 +__SYSCALL(123, sys_kill, 2) +#define __NR_tkill 124 +__SYSCALL(124, sys_tkill, 2) +#define __NR_tgkill 125 +__SYSCALL(125, sys_tgkill, 3) +#define __NR_set_tid_address 126 +__SYSCALL(126, sys_set_tid_address, 1) +#define __NR_gettid 127 +__SYSCALL(127, sys_gettid, 0) +#define __NR_setsid 128 +__SYSCALL(128, sys_setsid, 0) +#define __NR_getsid 129 +__SYSCALL(129, sys_getsid, 1) +#define __NR_prctl 130 +__SYSCALL(130, sys_prctl, 5) +#define __NR_personality 131 +__SYSCALL(131, sys_personality, 1) +#define __NR_getpriority 132 +__SYSCALL(132, sys_getpriority, 2) +#define __NR_setpriority 133 +__SYSCALL(133, sys_setpriority, 3) +#define __NR_setitimer 134 +__SYSCALL(134, sys_setitimer, 3) +#define __NR_getitimer 135 +__SYSCALL(135, sys_getitimer, 2) +#define __NR_setuid 136 +__SYSCALL(136, sys_setuid, 1) +#define __NR_getuid 137 +__SYSCALL(137, sys_getuid, 0) +#define __NR_setgid 138 +__SYSCALL(138, sys_setgid, 1) +#define __NR_getgid 139 +__SYSCALL(139, sys_getgid, 0) +#define __NR_geteuid 140 +__SYSCALL(140, sys_geteuid, 0) +#define __NR_getegid 141 +__SYSCALL(141, sys_getegid, 0) +#define __NR_setreuid 142 +__SYSCALL(142, sys_setreuid, 2) +#define __NR_setregid 143 +__SYSCALL(143, sys_setregid, 2) +#define __NR_setresuid 144 +__SYSCALL(144, sys_setresuid, 3) +#define __NR_getresuid 145 +__SYSCALL(145, sys_getresuid, 3) +#define __NR_setresgid 146 +__SYSCALL(146, sys_setresgid, 3) +#define __NR_getresgid 147 +__SYSCALL(147, sys_getresgid, 3) +#define __NR_setpgid 148 +__SYSCALL(148, sys_setpgid, 2) +#define __NR_getpgid 149 +__SYSCALL(149, sys_getpgid, 1) +#define __NR_getppid 150 +__SYSCALL(150, sys_getppid, 0) +#define __NR_getpgrp 151 +__SYSCALL(151, sys_getpgrp, 0) + +#define __NR_reserved152 152 /* set_thread_area */ +__SYSCALL(152, sys_ni_syscall, 0) +#define __NR_reserved153 153 /* get_thread_area */ +__SYSCALL(153, sys_ni_syscall, 0) +#define __NR_times 154 +__SYSCALL(154, sys_times, 1) +#define __NR_acct 155 +__SYSCALL(155, sys_acct, 1) +#define __NR_sched_setaffinity 156 +__SYSCALL(156, sys_sched_setaffinity, 3) +#define __NR_sched_getaffinity 157 +__SYSCALL(157, sys_sched_getaffinity, 3) +#define __NR_capget 158 +__SYSCALL(158, sys_capget, 2) +#define __NR_capset 159 +__SYSCALL(159, sys_capset, 2) +#define __NR_ptrace 160 +__SYSCALL(160, sys_ptrace, 4) +#define __NR_semtimedop 161 +__SYSCALL(161, sys_semtimedop, 5) +#define __NR_semget 162 +__SYSCALL(162, sys_semget, 4) +#define __NR_semop 163 +__SYSCALL(163, sys_semop, 4) +#define __NR_semctl 164 +__SYSCALL(164, sys_semctl, 4) +#define __NR_available165 165 +__SYSCALL(165, sys_ni_syscall, 0) +#define __NR_msgget 166 +__SYSCALL(166, sys_msgget, 4) +#define __NR_msgsnd 167 +__SYSCALL(167, sys_msgsnd, 4) +#define __NR_msgrcv 168 +__SYSCALL(168, sys_msgrcv, 4) +#define __NR_msgctl 169 +__SYSCALL(169, sys_msgctl, 4) +#define __NR_available170 170 +__SYSCALL(170, sys_ni_syscall, 0) + +/* File System */ + +#define __NR_umount2 171 +__SYSCALL(171, sys_umount, 2) +#define __NR_mount 172 +__SYSCALL(172, sys_mount, 5) +#define __NR_swapon 173 +__SYSCALL(173, sys_swapon, 2) +#define __NR_chroot 174 +__SYSCALL(174, sys_chroot, 1) +#define __NR_pivot_root 175 +__SYSCALL(175, sys_pivot_root, 2) +#define __NR_umount 176 +__SYSCALL(176, sys_umount, 2) +#define __NR_swapoff 177 +__SYSCALL(177, sys_swapoff, 1) +#define __NR_sync 178 +__SYSCALL(178, sys_sync, 0) +#define __NR_syncfs 179 +__SYSCALL(179, sys_syncfs, 1) +#define __NR_setfsuid 180 +__SYSCALL(180, sys_setfsuid, 1) +#define __NR_setfsgid 181 +__SYSCALL(181, sys_setfsgid, 1) +#define __NR_sysfs 182 +__SYSCALL(182, sys_sysfs, 3) +#define __NR_ustat 183 +__SYSCALL(183, sys_ustat, 2) +#define __NR_statfs 184 +__SYSCALL(184, sys_statfs, 2) +#define __NR_fstatfs 185 +__SYSCALL(185, sys_fstatfs, 2) +#define __NR_statfs64 186 +__SYSCALL(186, sys_statfs64, 3) +#define __NR_fstatfs64 187 +__SYSCALL(187, sys_fstatfs64, 3) + +/* System */ + +#define __NR_setrlimit 188 +__SYSCALL(188, sys_setrlimit, 2) +#define __NR_getrlimit 189 +__SYSCALL(189, sys_getrlimit, 2) +#define __NR_getrusage 190 +__SYSCALL(190, sys_getrusage, 2) +#define __NR_futex 191 +__SYSCALL(191, sys_futex, 5) +#define __NR_gettimeofday 192 +__SYSCALL(192, sys_gettimeofday, 2) +#define __NR_settimeofday 193 +__SYSCALL(193, sys_settimeofday, 2) +#define __NR_adjtimex 194 +__SYSCALL(194, sys_adjtimex, 1) +#define __NR_nanosleep 195 +__SYSCALL(195, sys_nanosleep, 2) +#define __NR_getgroups 196 +__SYSCALL(196, sys_getgroups, 2) +#define __NR_setgroups 197 +__SYSCALL(197, sys_setgroups, 2) +#define __NR_sethostname 198 +__SYSCALL(198, sys_sethostname, 2) +#define __NR_setdomainname 199 +__SYSCALL(199, sys_setdomainname, 2) +#define __NR_syslog 200 +__SYSCALL(200, sys_syslog, 3) +#define __NR_vhangup 201 +__SYSCALL(201, sys_vhangup, 0) +#define __NR_uselib 202 +__SYSCALL(202, sys_uselib, 1) +#define __NR_reboot 203 +__SYSCALL(203, sys_reboot, 3) +#define __NR_quotactl 204 +__SYSCALL(204, sys_quotactl, 4) +#define __NR_nfsservctl 205 +__SYSCALL(205, sys_ni_syscall, 0) /* old nfsservctl */ +#define __NR__sysctl 206 +__SYSCALL(206, sys_sysctl, 1) +#define __NR_bdflush 207 +__SYSCALL(207, sys_bdflush, 2) +#define __NR_uname 208 +__SYSCALL(208, sys_newuname, 1) +#define __NR_sysinfo 209 +__SYSCALL(209, sys_sysinfo, 1) +#define __NR_init_module 210 +__SYSCALL(210, sys_init_module, 2) +#define __NR_delete_module 211 +__SYSCALL(211, sys_delete_module, 1) + +#define __NR_sched_setparam 212 +__SYSCALL(212, sys_sched_setparam, 2) +#define __NR_sched_getparam 213 +__SYSCALL(213, sys_sched_getparam, 2) +#define __NR_sched_setscheduler 214 +__SYSCALL(214, sys_sched_setscheduler, 3) +#define __NR_sched_getscheduler 215 +__SYSCALL(215, sys_sched_getscheduler, 1) +#define __NR_sched_get_priority_max 216 +__SYSCALL(216, sys_sched_get_priority_max, 1) +#define __NR_sched_get_priority_min 217 +__SYSCALL(217, sys_sched_get_priority_min, 1) +#define __NR_sched_rr_get_interval 218 +__SYSCALL(218, sys_sched_rr_get_interval, 2) +#define __NR_sched_yield 219 +__SYSCALL(219, sys_sched_yield, 0) +#define __NR_available222 222 +__SYSCALL(222, sys_ni_syscall, 0) + +/* Signal Handling */ + +#define __NR_restart_syscall 223 +__SYSCALL(223, sys_restart_syscall, 0) +#define __NR_sigaltstack 224 +__SYSCALL(224, xtensa_sigaltstack, 2) +#define __NR_rt_sigreturn 225 +__SYSCALL(225, xtensa_rt_sigreturn, 1) +#define __NR_rt_sigaction 226 +__SYSCALL(226, sys_rt_sigaction, 4) +#define __NR_rt_sigprocmask 227 +__SYSCALL(227, sys_rt_sigprocmask, 4) +#define __NR_rt_sigpending 228 +__SYSCALL(228, sys_rt_sigpending, 2) +#define __NR_rt_sigtimedwait 229 +__SYSCALL(229, sys_rt_sigtimedwait, 4) +#define __NR_rt_sigqueueinfo 230 +__SYSCALL(230, sys_rt_sigqueueinfo, 3) +#define __NR_rt_sigsuspend 231 +__SYSCALL(231, sys_rt_sigsuspend, 2) + +/* Message */ + +#define __NR_mq_open 232 +__SYSCALL(232, sys_mq_open, 4) +#define __NR_mq_unlink 233 +__SYSCALL(233, sys_mq_unlink, 1) +#define __NR_mq_timedsend 234 +__SYSCALL(234, sys_mq_timedsend, 5) +#define __NR_mq_timedreceive 235 +__SYSCALL(235, sys_mq_timedreceive, 5) +#define __NR_mq_notify 236 +__SYSCALL(236, sys_mq_notify, 2) +#define __NR_mq_getsetattr 237 +__SYSCALL(237, sys_mq_getsetattr, 3) +#define __NR_available238 238 +__SYSCALL(238, sys_ni_syscall, 0) + +/* IO */ + +#define __NR_io_setup 239 +__SYSCALL(239, sys_io_setup, 2) +#define __NR_io_destroy 240 +__SYSCALL(240, sys_io_destroy, 1) +#define __NR_io_submit 241 +__SYSCALL(241, sys_io_submit, 3) +#define __NR_io_getevents 242 +__SYSCALL(242, sys_io_getevents, 5) +#define __NR_io_cancel 243 +__SYSCALL(243, sys_io_cancel, 3) +#define __NR_clock_settime 244 +__SYSCALL(244, sys_clock_settime, 2) +#define __NR_clock_gettime 245 +__SYSCALL(245, sys_clock_gettime, 2) +#define __NR_clock_getres 246 +__SYSCALL(246, sys_clock_getres, 2) +#define __NR_clock_nanosleep 247 +__SYSCALL(247, sys_clock_nanosleep, 4) + +/* Timer */ + +#define __NR_timer_create 248 +__SYSCALL(248, sys_timer_create, 3) +#define __NR_timer_delete 249 +__SYSCALL(249, sys_timer_delete, 1) +#define __NR_timer_settime 250 +__SYSCALL(250, sys_timer_settime, 4) +#define __NR_timer_gettime 251 +__SYSCALL(251, sys_timer_gettime, 2) +#define __NR_timer_getoverrun 252 +__SYSCALL(252, sys_timer_getoverrun, 1) + +/* System */ + +#define __NR_reserved253 253 +__SYSCALL(253, sys_ni_syscall, 0) +#define __NR_lookup_dcookie 254 +__SYSCALL(254, sys_lookup_dcookie, 4) +#define __NR_available255 255 +__SYSCALL(255, sys_ni_syscall, 0) +#define __NR_add_key 256 +__SYSCALL(256, sys_add_key, 5) +#define __NR_request_key 257 +__SYSCALL(257, sys_request_key, 5) +#define __NR_keyctl 258 +__SYSCALL(258, sys_keyctl, 5) +#define __NR_available259 259 +__SYSCALL(259, sys_ni_syscall, 0) + + +#define __NR_readahead 260 +__SYSCALL(260, sys_readahead, 5) +#define __NR_remap_file_pages 261 +__SYSCALL(261, sys_remap_file_pages, 5) +#define __NR_migrate_pages 262 +__SYSCALL(262, sys_migrate_pages, 0) +#define __NR_mbind 263 +__SYSCALL(263, sys_mbind, 6) +#define __NR_get_mempolicy 264 +__SYSCALL(264, sys_get_mempolicy, 5) +#define __NR_set_mempolicy 265 +__SYSCALL(265, sys_set_mempolicy, 3) +#define __NR_unshare 266 +__SYSCALL(266, sys_unshare, 1) +#define __NR_move_pages 267 +__SYSCALL(267, sys_move_pages, 0) +#define __NR_splice 268 +__SYSCALL(268, sys_splice, 0) +#define __NR_tee 269 +__SYSCALL(269, sys_tee, 0) +#define __NR_vmsplice 270 +__SYSCALL(270, sys_vmsplice, 0) +#define __NR_available271 271 +__SYSCALL(271, sys_ni_syscall, 0) + +#define __NR_pselect6 272 +__SYSCALL(272, sys_pselect6, 0) +#define __NR_ppoll 273 +__SYSCALL(273, sys_ppoll, 0) +#define __NR_epoll_pwait 274 +__SYSCALL(274, sys_epoll_pwait, 0) +#define __NR_epoll_create1 275 +__SYSCALL(275, sys_epoll_create1, 1) + +#define __NR_inotify_init 276 +__SYSCALL(276, sys_inotify_init, 0) +#define __NR_inotify_add_watch 277 +__SYSCALL(277, sys_inotify_add_watch, 3) +#define __NR_inotify_rm_watch 278 +__SYSCALL(278, sys_inotify_rm_watch, 2) +#define __NR_inotify_init1 279 +__SYSCALL(279, sys_inotify_init1, 1) + +#define __NR_getcpu 280 +__SYSCALL(280, sys_getcpu, 0) +#define __NR_kexec_load 281 +__SYSCALL(281, sys_ni_syscall, 0) + +#define __NR_ioprio_set 282 +__SYSCALL(282, sys_ioprio_set, 2) +#define __NR_ioprio_get 283 +__SYSCALL(283, sys_ioprio_get, 3) + +#define __NR_set_robust_list 284 +__SYSCALL(284, sys_set_robust_list, 3) +#define __NR_get_robust_list 285 +__SYSCALL(285, sys_get_robust_list, 3) +#define __NR_available286 286 +__SYSCALL(286, sys_ni_syscall, 0) +#define __NR_available287 287 +__SYSCALL(287, sys_ni_syscall, 0) + +/* Relative File Operations */ + +#define __NR_openat 288 +__SYSCALL(288, sys_openat, 4) +#define __NR_mkdirat 289 +__SYSCALL(289, sys_mkdirat, 3) +#define __NR_mknodat 290 +__SYSCALL(290, sys_mknodat, 4) +#define __NR_unlinkat 291 +__SYSCALL(291, sys_unlinkat, 3) +#define __NR_renameat 292 +__SYSCALL(292, sys_renameat, 4) +#define __NR_linkat 293 +__SYSCALL(293, sys_linkat, 5) +#define __NR_symlinkat 294 +__SYSCALL(294, sys_symlinkat, 3) +#define __NR_readlinkat 295 +__SYSCALL(295, sys_readlinkat, 4) +#define __NR_utimensat 296 +__SYSCALL(296, sys_utimensat, 0) +#define __NR_fchownat 297 +__SYSCALL(297, sys_fchownat, 5) +#define __NR_futimesat 298 +__SYSCALL(298, sys_futimesat, 4) +#define __NR_fstatat64 299 +__SYSCALL(299, sys_fstatat64, 0) +#define __NR_fchmodat 300 +__SYSCALL(300, sys_fchmodat, 4) +#define __NR_faccessat 301 +__SYSCALL(301, sys_faccessat, 4) +#define __NR_available302 302 +__SYSCALL(302, sys_ni_syscall, 0) +#define __NR_available303 303 +__SYSCALL(303, sys_ni_syscall, 0) + +#define __NR_signalfd 304 +__SYSCALL(304, sys_signalfd, 3) +/* 305 was __NR_timerfd */ +__SYSCALL(305, sys_ni_syscall, 0) +#define __NR_eventfd 306 +__SYSCALL(306, sys_eventfd, 1) +#define __NR_recvmmsg 307 +__SYSCALL(307, sys_recvmmsg, 5) + +#define __NR_setns 308 +__SYSCALL(308, sys_setns, 2) +#define __NR_signalfd4 309 +__SYSCALL(309, sys_signalfd4, 4) +#define __NR_dup3 310 +__SYSCALL(310, sys_dup3, 3) +#define __NR_pipe2 311 +__SYSCALL(311, sys_pipe2, 2) + +#define __NR_timerfd_create 312 +__SYSCALL(312, sys_timerfd_create, 2) +#define __NR_timerfd_settime 313 +__SYSCALL(313, sys_timerfd_settime, 4) +#define __NR_timerfd_gettime 314 +__SYSCALL(314, sys_timerfd_gettime, 2) +#define __NR_available315 315 +__SYSCALL(315, sys_ni_syscall, 0) + +#define __NR_eventfd2 316 +__SYSCALL(316, sys_eventfd2, 2) +#define __NR_preadv 317 +__SYSCALL(317, sys_preadv, 5) +#define __NR_pwritev 318 +__SYSCALL(318, sys_pwritev, 5) +#define __NR_available319 319 +__SYSCALL(319, sys_ni_syscall, 0) + +#define __NR_fanotify_init 320 +__SYSCALL(320, sys_fanotify_init, 2) +#define __NR_fanotify_mark 321 +__SYSCALL(321, sys_fanotify_mark, 6) +#define __NR_process_vm_readv 322 +__SYSCALL(322, sys_process_vm_readv, 6) +#define __NR_process_vm_writev 323 +__SYSCALL(323, sys_process_vm_writev, 6) + +#define __NR_name_to_handle_at 324 +__SYSCALL(324, sys_name_to_handle_at, 5) +#define __NR_open_by_handle_at 325 +__SYSCALL(325, sys_open_by_handle_at, 3) +#define __NR_sync_file_range 326 +__SYSCALL(326, sys_sync_file_range2, 6) +#define __NR_perf_event_open 327 +__SYSCALL(327, sys_perf_event_open, 5) + +#define __NR_rt_tgsigqueueinfo 328 +__SYSCALL(328, sys_rt_tgsigqueueinfo, 4) +#define __NR_clock_adjtime 329 +__SYSCALL(329, sys_clock_adjtime, 2) +#define __NR_prlimit64 330 +__SYSCALL(330, sys_prlimit64, 4) +#define __NR_kcmp 331 +__SYSCALL(331, sys_kcmp, 5) + + +#define __NR_syscall_count 332 + +/* + * sysxtensa syscall handler + * + * int sysxtensa (SYS_XTENSA_ATOMIC_SET, ptr, val, unused); + * int sysxtensa (SYS_XTENSA_ATOMIC_ADD, ptr, val, unused); + * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val, unused); + * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval); + * a2 a6 a3 a4 a5 + */ + +#define SYS_XTENSA_RESERVED 0 /* don't use this */ +#define SYS_XTENSA_ATOMIC_SET 1 /* set variable */ +#define SYS_XTENSA_ATOMIC_EXG_ADD 2 /* exchange memory and add */ +#define SYS_XTENSA_ATOMIC_ADD 3 /* add to memory */ +#define SYS_XTENSA_ATOMIC_CMP_SWP 4 /* compare and swap */ + +#define SYS_XTENSA_COUNT 5 /* count */ + +#undef __SYSCALL + +#endif /* _UAPI_XTENSA_UNISTD_H */ diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S index 33d6e9d2e83..934ae58e2c7 100644 --- a/arch/xtensa/kernel/align.S +++ b/arch/xtensa/kernel/align.S @@ -170,15 +170,15 @@ ENTRY(fast_unaligned) s32i a7, a2, PT_AREG7 s32i a8, a2, PT_AREG8 - rsr a0, DEPC - xsr a3, EXCSAVE_1 + rsr a0, depc + xsr a3, excsave1 s32i a0, a2, PT_AREG2 s32i a3, a2, PT_AREG3 /* Keep value of SAR in a0 */ - rsr a0, SAR - rsr a8, EXCVADDR # load unaligned memory address + rsr a0, sar + rsr a8, excvaddr # load unaligned memory address /* Now, identify one of the following load/store instructions. * @@ -197,7 +197,7 @@ ENTRY(fast_unaligned) /* Extract the instruction that caused the unaligned access. */ - rsr a7, EPC_1 # load exception address + rsr a7, epc1 # load exception address movi a3, ~3 and a3, a3, a7 # mask lower bits @@ -275,16 +275,16 @@ ENTRY(fast_unaligned) 1: #if XCHAL_HAVE_LOOPS - rsr a5, LEND # check if we reached LEND + rsr a5, lend # check if we reached LEND bne a7, a5, 1f - rsr a5, LCOUNT # and LCOUNT != 0 + rsr a5, lcount # and LCOUNT != 0 beqz a5, 1f addi a5, a5, -1 # decrement LCOUNT and set - rsr a7, LBEG # set PC to LBEGIN - wsr a5, LCOUNT + rsr a7, lbeg # set PC to LBEGIN + wsr a5, lcount #endif -1: wsr a7, EPC_1 # skip load instruction +1: wsr a7, epc1 # skip load instruction extui a4, a4, INSN_T, 4 # extract target register movi a5, .Lload_table addx8 a4, a4, a5 @@ -355,16 +355,16 @@ ENTRY(fast_unaligned) 1: #if XCHAL_HAVE_LOOPS - rsr a4, LEND # check if we reached LEND + rsr a4, lend # check if we reached LEND bne a7, a4, 1f - rsr a4, LCOUNT # and LCOUNT != 0 + rsr a4, lcount # and LCOUNT != 0 beqz a4, 1f addi a4, a4, -1 # decrement LCOUNT and set - rsr a7, LBEG # set PC to LBEGIN - wsr a4, LCOUNT + rsr a7, lbeg # set PC to LBEGIN + wsr a4, lcount #endif -1: wsr a7, EPC_1 # skip store instruction +1: wsr a7, epc1 # skip store instruction movi a4, ~3 and a4, a4, a8 # align memory address @@ -406,7 +406,7 @@ ENTRY(fast_unaligned) .Lexit: movi a4, 0 - rsr a3, EXCSAVE_1 + rsr a3, excsave1 s32i a4, a3, EXC_TABLE_FIXUP /* Restore working register */ @@ -420,7 +420,7 @@ ENTRY(fast_unaligned) /* restore SAR and return */ - wsr a0, SAR + wsr a0, sar l32i a0, a2, PT_AREG0 l32i a2, a2, PT_AREG2 rfe @@ -438,10 +438,10 @@ ENTRY(fast_unaligned) l32i a6, a2, PT_AREG6 l32i a5, a2, PT_AREG5 l32i a4, a2, PT_AREG4 - wsr a0, SAR + wsr a0, sar mov a1, a2 - rsr a0, PS + rsr a0, ps bbsi.l a2, PS_UM_BIT, 1f # jump if user mode movi a0, _kernel_exception diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S index 2bc1e145c0a..54c3be313bf 100644 --- a/arch/xtensa/kernel/coprocessor.S +++ b/arch/xtensa/kernel/coprocessor.S @@ -43,7 +43,7 @@ /* IO protection is currently unsupported. */ ENTRY(fast_io_protect) - wsr a0, EXCSAVE_1 + wsr a0, excsave1 movi a0, unrecoverable_exception callx0 a0 @@ -220,7 +220,7 @@ ENTRY(coprocessor_restore) */ ENTRY(fast_coprocessor_double) - wsr a0, EXCSAVE_1 + wsr a0, excsave1 movi a0, unrecoverable_exception callx0 a0 @@ -229,13 +229,13 @@ ENTRY(fast_coprocessor) /* Save remaining registers a1-a3 and SAR */ - xsr a3, EXCSAVE_1 + xsr a3, excsave1 s32i a3, a2, PT_AREG3 - rsr a3, SAR + rsr a3, sar s32i a1, a2, PT_AREG1 s32i a3, a2, PT_SAR mov a1, a2 - rsr a2, DEPC + rsr a2, depc s32i a2, a1, PT_AREG2 /* @@ -248,17 +248,17 @@ ENTRY(fast_coprocessor) /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */ - rsr a3, EXCCAUSE + rsr a3, exccause addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED /* Set corresponding CPENABLE bit -> (sar:cp-index, a3: 1<<cp-index)*/ ssl a3 # SAR: 32 - coprocessor_number movi a2, 1 - rsr a0, CPENABLE + rsr a0, cpenable sll a2, a2 or a0, a0, a2 - wsr a0, CPENABLE + wsr a0, cpenable rsync /* Retrieve previous owner. (a3 still holds CP number) */ @@ -291,7 +291,7 @@ ENTRY(fast_coprocessor) /* Note that only a0 and a1 were preserved. */ -2: rsr a3, EXCCAUSE +2: rsr a3, exccause addi a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED movi a0, coprocessor_owner addx4 a0, a3, a0 @@ -321,7 +321,7 @@ ENTRY(fast_coprocessor) l32i a0, a1, PT_SAR l32i a3, a1, PT_AREG3 l32i a2, a1, PT_AREG2 - wsr a0, SAR + wsr a0, sar l32i a0, a1, PT_AREG0 l32i a1, a1, PT_AREG1 diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 7e623607339..90bfc1dbc13 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -112,8 +112,8 @@ ENTRY(user_exception) /* Save a2, a3, and depc, restore excsave_1 and set SP. */ - xsr a3, EXCSAVE_1 - rsr a0, DEPC + xsr a3, excsave1 + rsr a0, depc s32i a1, a2, PT_AREG1 s32i a0, a2, PT_AREG2 s32i a3, a2, PT_AREG3 @@ -125,16 +125,16 @@ _user_exception: /* Save SAR and turn off single stepping */ movi a2, 0 - rsr a3, SAR - xsr a2, ICOUNTLEVEL + rsr a3, sar + xsr a2, icountlevel s32i a3, a1, PT_SAR s32i a2, a1, PT_ICOUNTLEVEL /* Rotate ws so that the current windowbase is at bit0. */ /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ - rsr a2, WINDOWBASE - rsr a3, WINDOWSTART + rsr a2, windowbase + rsr a3, windowstart ssr a2 s32i a2, a1, PT_WINDOWBASE s32i a3, a1, PT_WINDOWSTART @@ -205,12 +205,12 @@ _user_exception: /* WINDOWBASE still in SAR! */ - rsr a2, SAR # original WINDOWBASE + rsr a2, sar # original WINDOWBASE movi a3, 1 ssl a2 sll a3, a3 - wsr a3, WINDOWSTART # set corresponding WINDOWSTART bit - wsr a2, WINDOWBASE # and WINDOWSTART + wsr a3, windowstart # set corresponding WINDOWSTART bit + wsr a2, windowbase # and WINDOWSTART rsync /* We are back to the original stack pointer (a1) */ @@ -252,8 +252,8 @@ ENTRY(kernel_exception) /* Save a0, a2, a3, DEPC and set SP. */ - xsr a3, EXCSAVE_1 # restore a3, excsave_1 - rsr a0, DEPC # get a2 + xsr a3, excsave1 # restore a3, excsave_1 + rsr a0, depc # get a2 s32i a1, a2, PT_AREG1 s32i a0, a2, PT_AREG2 s32i a3, a2, PT_AREG3 @@ -265,16 +265,16 @@ _kernel_exception: /* Save SAR and turn off single stepping */ movi a2, 0 - rsr a3, SAR - xsr a2, ICOUNTLEVEL + rsr a3, sar + xsr a2, icountlevel s32i a3, a1, PT_SAR s32i a2, a1, PT_ICOUNTLEVEL /* Rotate ws so that the current windowbase is at bit0. */ /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */ - rsr a2, WINDOWBASE # don't need to save these, we only - rsr a3, WINDOWSTART # need shifted windowstart: windowmask + rsr a2, windowbase # don't need to save these, we only + rsr a3, windowstart # need shifted windowstart: windowmask ssr a2 slli a2, a3, 32-WSBITS src a2, a3, a2 @@ -323,24 +323,24 @@ common_exception: /* Save some registers, disable loops and clear the syscall flag. */ - rsr a2, DEBUGCAUSE - rsr a3, EPC_1 + rsr a2, debugcause + rsr a3, epc1 s32i a2, a1, PT_DEBUGCAUSE s32i a3, a1, PT_PC movi a2, -1 - rsr a3, EXCVADDR + rsr a3, excvaddr s32i a2, a1, PT_SYSCALL movi a2, 0 s32i a3, a1, PT_EXCVADDR - xsr a2, LCOUNT + xsr a2, lcount s32i a2, a1, PT_LCOUNT /* It is now save to restore the EXC_TABLE_FIXUP variable. */ - rsr a0, EXCCAUSE + rsr a0, exccause movi a3, 0 - rsr a2, EXCSAVE_1 + rsr a2, excsave1 s32i a0, a1, PT_EXCCAUSE s32i a3, a2, EXC_TABLE_FIXUP @@ -352,22 +352,22 @@ common_exception: * (interrupts disabled) and if this exception is not an interrupt. */ - rsr a3, PS + rsr a3, ps addi a0, a0, -4 movi a2, 1 extui a3, a3, 0, 1 # a3 = PS.INTLEVEL[0] moveqz a3, a2, a0 # a3 = 1 iff interrupt exception movi a2, 1 << PS_WOE_BIT or a3, a3, a2 - rsr a0, EXCCAUSE - xsr a3, PS + rsr a0, exccause + xsr a3, ps s32i a3, a1, PT_PS # save ps - /* Save LBEG, LEND */ + /* Save lbeg, lend */ - rsr a2, LBEG - rsr a3, LEND + rsr a2, lbeg + rsr a3, lend s32i a2, a1, PT_LBEG s32i a3, a1, PT_LEND @@ -432,7 +432,7 @@ common_exception_return: load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT - wsr a3, PS /* disable interrupts */ + wsr a3, ps /* disable interrupts */ _bbci.l a3, PS_UM_BIT, kernel_exception_exit @@ -444,12 +444,12 @@ user_exception_exit: l32i a2, a1, PT_WINDOWBASE l32i a3, a1, PT_WINDOWSTART - wsr a1, DEPC # use DEPC as temp storage - wsr a3, WINDOWSTART # restore WINDOWSTART + wsr a1, depc # use DEPC as temp storage + wsr a3, windowstart # restore WINDOWSTART ssr a2 # preserve user's WB in the SAR - wsr a2, WINDOWBASE # switch to user's saved WB + wsr a2, windowbase # switch to user's saved WB rsync - rsr a1, DEPC # restore stack pointer + rsr a1, depc # restore stack pointer l32i a2, a1, PT_WMASK # register frames saved (in bits 4...9) rotw -1 # we restore a4..a7 _bltui a6, 16, 1f # only have to restore current window? @@ -475,8 +475,8 @@ user_exception_exit: /* Clear unrestored registers (don't leak anything to user-land */ -1: rsr a0, WINDOWBASE - rsr a3, SAR +1: rsr a0, windowbase + rsr a3, sar sub a3, a0, a3 beqz a3, 2f extui a3, a3, 0, WBBITS @@ -556,7 +556,7 @@ kernel_exception_exit: /* Test WINDOWSTART now. If spilled, do the movsp */ - rsr a3, WINDOWSTART + rsr a3, windowstart addi a0, a3, -1 and a3, a3, a0 _bnez a3, common_exception_exit @@ -604,24 +604,24 @@ common_exception_exit: 1: l32i a2, a1, PT_PC l32i a3, a1, PT_SAR - wsr a2, EPC_1 - wsr a3, SAR + wsr a2, epc1 + wsr a3, sar /* Restore LBEG, LEND, LCOUNT */ l32i a2, a1, PT_LBEG l32i a3, a1, PT_LEND - wsr a2, LBEG + wsr a2, lbeg l32i a2, a1, PT_LCOUNT - wsr a3, LEND - wsr a2, LCOUNT + wsr a3, lend + wsr a2, lcount /* We control single stepping through the ICOUNTLEVEL register. */ l32i a2, a1, PT_ICOUNTLEVEL movi a3, -2 - wsr a2, ICOUNTLEVEL - wsr a3, ICOUNT + wsr a2, icountlevel + wsr a3, icount /* Check if it was double exception. */ @@ -636,7 +636,7 @@ common_exception_exit: l32i a1, a1, PT_AREG1 rfe -1: wsr a0, DEPC +1: wsr a0, depc l32i a0, a1, PT_AREG0 l32i a1, a1, PT_AREG1 rfde @@ -651,25 +651,25 @@ common_exception_exit: ENTRY(debug_exception) - rsr a0, EPS + XCHAL_DEBUGLEVEL + rsr a0, SREG_EPS + XCHAL_DEBUGLEVEL bbsi.l a0, PS_EXCM_BIT, 1f # exception mode - /* Set EPC_1 and EXCCAUSE */ + /* Set EPC1 and EXCCAUSE */ - wsr a2, DEPC # save a2 temporarily - rsr a2, EPC + XCHAL_DEBUGLEVEL - wsr a2, EPC_1 + wsr a2, depc # save a2 temporarily + rsr a2, SREG_EPC + XCHAL_DEBUGLEVEL + wsr a2, epc1 movi a2, EXCCAUSE_MAPPED_DEBUG - wsr a2, EXCCAUSE + wsr a2, exccause /* Restore PS to the value before the debug exc but with PS.EXCM set.*/ movi a2, 1 << PS_EXCM_BIT or a2, a0, a2 movi a0, debug_exception # restore a3, debug jump vector - wsr a2, PS - xsr a0, EXCSAVE + XCHAL_DEBUGLEVEL + wsr a2, ps + xsr a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL /* Switch to kernel/user stack, restore jump vector, and save a0 */ @@ -680,19 +680,19 @@ ENTRY(debug_exception) movi a0, 0 s32i a1, a2, PT_AREG1 s32i a0, a2, PT_DEPC # mark it as a regular exception - xsr a0, DEPC + xsr a0, depc s32i a3, a2, PT_AREG3 s32i a0, a2, PT_AREG2 mov a1, a2 j _kernel_exception -2: rsr a2, EXCSAVE_1 +2: rsr a2, excsave1 l32i a2, a2, EXC_TABLE_KSTK # load kernel stack pointer s32i a0, a2, PT_AREG0 movi a0, 0 s32i a1, a2, PT_AREG1 s32i a0, a2, PT_DEPC - xsr a0, DEPC + xsr a0, depc s32i a3, a2, PT_AREG3 s32i a0, a2, PT_AREG2 mov a1, a2 @@ -732,12 +732,12 @@ ENTRY(unrecoverable_exception) movi a0, 1 movi a1, 0 - wsr a0, WINDOWSTART - wsr a1, WINDOWBASE + wsr a0, windowstart + wsr a1, windowbase rsync movi a1, (1 << PS_WOE_BIT) | 1 - wsr a1, PS + wsr a1, ps rsync movi a1, init_task @@ -793,7 +793,7 @@ ENTRY(fast_alloca) l32i a0, a2, PT_DEPC _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, .Lunhandled_double - rsr a0, DEPC # get a2 + rsr a0, depc # get a2 s32i a4, a2, PT_AREG4 # save a4 and s32i a0, a2, PT_AREG2 # a2 to stack @@ -804,8 +804,8 @@ ENTRY(fast_alloca) /* Restore a3, excsave_1 */ - xsr a3, EXCSAVE_1 # make sure excsave_1 is valid for dbl. - rsr a4, EPC_1 # get exception address + xsr a3, excsave1 # make sure excsave_1 is valid for dbl. + rsr a4, epc1 # get exception address s32i a3, a2, PT_AREG3 # save a3 to stack #ifdef ALLOCA_EXCEPTION_IN_IRAM @@ -820,7 +820,7 @@ ENTRY(fast_alloca) jx a3 .Lunhandled_double: - wsr a0, EXCSAVE_1 + wsr a0, excsave1 movi a0, unrecoverable_exception callx0 a0 @@ -852,7 +852,7 @@ ENTRY(fast_alloca) #endif addi a4, a4, 3 # step over movsp _EXTUI_MOVSP_DST(a0) # extract destination register - wsr a4, EPC_1 # save new epc_1 + wsr a4, epc1 # save new epc_1 _bnei a0, 1, 1f # no 'movsp a1, ax': jump @@ -953,14 +953,14 @@ ENTRY(fast_syscall_kernel) /* Skip syscall. */ - rsr a0, EPC_1 + rsr a0, epc1 addi a0, a0, 3 - wsr a0, EPC_1 + wsr a0, epc1 l32i a0, a2, PT_DEPC bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable - rsr a0, DEPC # get syscall-nr + rsr a0, depc # get syscall-nr _beqz a0, fast_syscall_spill_registers _beqi a0, __NR_xtensa, fast_syscall_xtensa @@ -970,14 +970,14 @@ ENTRY(fast_syscall_user) /* Skip syscall. */ - rsr a0, EPC_1 + rsr a0, epc1 addi a0, a0, 3 - wsr a0, EPC_1 + wsr a0, epc1 l32i a0, a2, PT_DEPC bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable - rsr a0, DEPC # get syscall-nr + rsr a0, depc # get syscall-nr _beqz a0, fast_syscall_spill_registers _beqi a0, __NR_xtensa, fast_syscall_xtensa @@ -988,10 +988,10 @@ ENTRY(fast_syscall_unrecoverable) /* Restore all states. */ l32i a0, a2, PT_AREG0 # restore a0 - xsr a2, DEPC # restore a2, depc - rsr a3, EXCSAVE_1 + xsr a2, depc # restore a2, depc + rsr a3, excsave1 - wsr a0, EXCSAVE_1 + wsr a0, excsave1 movi a0, unrecoverable_exception callx0 a0 @@ -1047,7 +1047,7 @@ ENTRY(fast_syscall_unrecoverable) ENTRY(fast_syscall_xtensa) - xsr a3, EXCSAVE_1 # restore a3, excsave1 + xsr a3, excsave1 # restore a3, excsave1 s32i a7, a2, PT_AREG7 # we need an additional register movi a7, 4 # sizeof(unsigned int) @@ -1124,13 +1124,13 @@ ENTRY(fast_syscall_spill_registers) movi a0, fast_syscall_spill_registers_fixup s32i a0, a3, EXC_TABLE_FIXUP - rsr a0, WINDOWBASE + rsr a0, windowbase s32i a0, a3, EXC_TABLE_PARAM /* Save a3 and SAR on stack. */ - rsr a0, SAR - xsr a3, EXCSAVE_1 # restore a3 and excsave_1 + rsr a0, sar + xsr a3, excsave1 # restore a3 and excsave_1 s32i a3, a2, PT_AREG3 s32i a4, a2, PT_AREG4 s32i a0, a2, PT_AREG5 # store SAR to PT_AREG5 @@ -1148,7 +1148,7 @@ ENTRY(fast_syscall_spill_registers) l32i a3, a2, PT_AREG5 l32i a4, a2, PT_AREG4 l32i a0, a2, PT_AREG0 - wsr a3, SAR + wsr a3, sar l32i a3, a2, PT_AREG3 /* Restore clobbered registers. */ @@ -1173,8 +1173,8 @@ ENTRY(fast_syscall_spill_registers) fast_syscall_spill_registers_fixup: - rsr a2, WINDOWBASE # get current windowbase (a2 is saved) - xsr a0, DEPC # restore depc and a0 + rsr a2, windowbase # get current windowbase (a2 is saved) + xsr a0, depc # restore depc and a0 ssl a2 # set shift (32 - WB) /* We need to make sure the current registers (a0-a3) are preserved. @@ -1182,12 +1182,12 @@ fast_syscall_spill_registers_fixup: * in WS, so that the exception handlers save them to the task stack. */ - rsr a3, EXCSAVE_1 # get spill-mask + rsr a3, excsave1 # get spill-mask slli a2, a3, 1 # shift left by one slli a3, a2, 32-WSBITS src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy...... - wsr a2, WINDOWSTART # set corrected windowstart + wsr a2, windowstart # set corrected windowstart movi a3, exc_table l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2 @@ -1201,7 +1201,7 @@ fast_syscall_spill_registers_fixup: * excsave_1: a3 */ - wsr a3, WINDOWBASE + wsr a3, windowbase rsync /* We are now in the original frame when we entered _spill_registers: @@ -1227,7 +1227,7 @@ fast_syscall_spill_registers_fixup: /* Jump to the exception handler. */ movi a3, exc_table - rsr a0, EXCCAUSE + rsr a0, exccause addx4 a0, a0, a3 # find entry in table l32i a0, a0, EXC_TABLE_FAST_USER # load handler jx a0 @@ -1236,28 +1236,28 @@ fast_syscall_spill_registers_fixup_return: /* When we return here, all registers have been restored (a2: DEPC) */ - wsr a2, DEPC # exception address + wsr a2, depc # exception address /* Restore fixup handler. */ - xsr a3, EXCSAVE_1 + xsr a3, excsave1 movi a2, fast_syscall_spill_registers_fixup s32i a2, a3, EXC_TABLE_FIXUP - rsr a2, WINDOWBASE + rsr a2, windowbase s32i a2, a3, EXC_TABLE_PARAM l32i a2, a3, EXC_TABLE_KSTK /* Load WB at the time the exception occurred. */ - rsr a3, SAR # WB is still in SAR + rsr a3, sar # WB is still in SAR neg a3, a3 - wsr a3, WINDOWBASE + wsr a3, windowbase rsync /* Restore a3 and return. */ movi a3, exc_table - xsr a3, EXCSAVE_1 + xsr a3, excsave1 rfde @@ -1283,8 +1283,8 @@ ENTRY(_spill_registers) * Rotate ws right so that a4 = yyxxxwww1. */ - rsr a4, WINDOWBASE - rsr a3, WINDOWSTART # a3 = xxxwww1yy + rsr a4, windowbase + rsr a3, windowstart # a3 = xxxwww1yy ssr a4 # holds WB slli a4, a3, WSBITS or a3, a3, a4 # a3 = xxxwww1yyxxxwww1yy @@ -1302,7 +1302,7 @@ ENTRY(_spill_registers) /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */ - wsr a3, WINDOWSTART # save shifted windowstart + wsr a3, windowstart # save shifted windowstart neg a4, a3 and a3, a4, a3 # first bit set from right: 000010000 @@ -1311,12 +1311,12 @@ ENTRY(_spill_registers) sub a4, a3, a4 # WSBITS-a4:number of 0-bits from right ssr a4 # save in SAR for later. - rsr a3, WINDOWBASE + rsr a3, windowbase add a3, a3, a4 - wsr a3, WINDOWBASE + wsr a3, windowbase rsync - rsr a3, WINDOWSTART + rsr a3, windowstart srl a3, a3 # shift windowstart /* WB is now just one frame below the oldest frame in the register @@ -1364,11 +1364,11 @@ ENTRY(_spill_registers) .Lexit: /* Done. Do the final rotation, set WS, and return. */ rotw 1 - rsr a3, WINDOWBASE + rsr a3, windowbase ssl a3 movi a3, 1 sll a3, a3 - wsr a3, WINDOWSTART + wsr a3, windowstart ret .Lc4: s32e a4, a9, -16 @@ -1429,7 +1429,7 @@ ENTRY(_spill_registers) * however, this condition is unrecoverable in kernel space. */ - rsr a0, PS + rsr a0, ps _bbci.l a0, PS_UM_BIT, 1f /* User space: Setup a dummy frame and kill application. @@ -1439,18 +1439,18 @@ ENTRY(_spill_registers) movi a0, 1 movi a1, 0 - wsr a0, WINDOWSTART - wsr a1, WINDOWBASE + wsr a0, windowstart + wsr a1, windowbase rsync movi a0, 0 movi a3, exc_table l32i a1, a3, EXC_TABLE_KSTK - wsr a3, EXCSAVE_1 + wsr a3, excsave1 movi a4, (1 << PS_WOE_BIT) | 1 - wsr a4, PS + wsr a4, ps rsync movi a6, SIGSEGV @@ -1459,7 +1459,7 @@ ENTRY(_spill_registers) 1: /* Kernel space: PANIC! */ - wsr a0, EXCSAVE_1 + wsr a0, excsave1 movi a0, unrecoverable_exception callx0 a0 # should not return 1: j 1b @@ -1524,7 +1524,7 @@ ENTRY(fast_second_level_miss) /* We deliberately destroy a3 that holds the exception table. */ -8: rsr a3, EXCVADDR # fault address +8: rsr a3, excvaddr # fault address _PGD_OFFSET(a0, a3, a1) l32i a0, a0, 0 # read pmdval beqz a0, 2f @@ -1542,7 +1542,7 @@ ENTRY(fast_second_level_miss) * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY */ - movi a1, -PAGE_OFFSET + movi a1, (-PAGE_OFFSET) & 0xffffffff add a0, a0, a1 # pmdval - PAGE_OFFSET extui a1, a0, 0, PAGE_SHIFT # ... & PAGE_MASK xor a0, a0, a1 @@ -1561,7 +1561,7 @@ ENTRY(fast_second_level_miss) */ extui a3, a3, 28, 2 # addr. bit 28 and 29 0,1,2,3 - rsr a1, PTEVADDR + rsr a1, ptevaddr addx2 a3, a3, a3 # -> 0,3,6,9 srli a1, a1, PAGE_SHIFT extui a3, a3, 2, 2 # -> 0,0,1,2 @@ -1583,18 +1583,18 @@ ENTRY(fast_second_level_miss) l32i a0, a2, PT_AREG0 l32i a1, a2, PT_AREG1 l32i a2, a2, PT_DEPC - xsr a3, EXCSAVE_1 + xsr a3, excsave1 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f /* Restore excsave1 and return. */ - rsr a2, DEPC + rsr a2, depc rfe /* Return from double exception. */ -1: xsr a2, DEPC +1: xsr a2, depc esync rfde @@ -1618,7 +1618,7 @@ ENTRY(fast_second_level_miss) /* Make sure the exception originated in the special functions */ movi a0, __tlbtemp_mapping_start - rsr a3, EPC_1 + rsr a3, epc1 bltu a3, a0, 2f movi a0, __tlbtemp_mapping_end bgeu a3, a0, 2f @@ -1626,7 +1626,7 @@ ENTRY(fast_second_level_miss) /* Check if excvaddr was in one of the TLBTEMP_BASE areas. */ movi a3, TLBTEMP_BASE_1 - rsr a0, EXCVADDR + rsr a0, excvaddr bltu a0, a3, 2f addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT)) @@ -1635,7 +1635,7 @@ ENTRY(fast_second_level_miss) /* Check if we have to restore an ITLB mapping. */ movi a1, __tlbtemp_mapping_itlb - rsr a3, EPC_1 + rsr a3, epc1 sub a3, a3, a1 /* Calculate VPN */ @@ -1671,13 +1671,13 @@ ENTRY(fast_second_level_miss) 2: /* Invalid PGD, default exception handling */ movi a3, exc_table - rsr a1, DEPC - xsr a3, EXCSAVE_1 + rsr a1, depc + xsr a3, excsave1 s32i a1, a2, PT_AREG2 s32i a3, a2, PT_AREG3 mov a1, a2 - rsr a2, PS + rsr a2, ps bbsi.l a2, PS_UM_BIT, 1f j _kernel_exception 1: j _user_exception @@ -1712,7 +1712,7 @@ ENTRY(fast_store_prohibited) l32i a0, a1, TASK_MM # tsk->mm beqz a0, 9f -8: rsr a1, EXCVADDR # fault address +8: rsr a1, excvaddr # fault address _PGD_OFFSET(a0, a1, a4) l32i a0, a0, 0 beqz a0, 2f @@ -1725,7 +1725,7 @@ ENTRY(fast_store_prohibited) movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE or a4, a4, a1 - rsr a1, EXCVADDR + rsr a1, excvaddr s32i a4, a0, 0 /* We need to flush the cache if we have page coloring. */ @@ -1749,15 +1749,15 @@ ENTRY(fast_store_prohibited) /* Restore excsave1 and a3. */ - xsr a3, EXCSAVE_1 + xsr a3, excsave1 bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f - rsr a2, DEPC + rsr a2, depc rfe /* Double exception. Restore FIXUP handler and return. */ -1: xsr a2, DEPC +1: xsr a2, depc esync rfde @@ -1766,14 +1766,14 @@ ENTRY(fast_store_prohibited) 2: /* If there was a problem, handle fault in C */ - rsr a4, DEPC # still holds a2 - xsr a3, EXCSAVE_1 + rsr a4, depc # still holds a2 + xsr a3, excsave1 s32i a4, a2, PT_AREG2 s32i a3, a2, PT_AREG3 l32i a4, a2, PT_AREG4 mov a1, a2 - rsr a2, PS + rsr a2, ps bbsi.l a2, PS_UM_BIT, 1f j _kernel_exception 1: j _user_exception @@ -1833,50 +1833,6 @@ ENTRY(system_call) /* - * Create a kernel thread - * - * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) - * a2 a2 a3 a4 - */ - -ENTRY(kernel_thread) - entry a1, 16 - - mov a5, a2 # preserve fn over syscall - mov a7, a3 # preserve args over syscall - - movi a3, _CLONE_VM | _CLONE_UNTRACED - movi a2, __NR_clone - or a6, a4, a3 # arg0: flags - mov a3, a1 # arg1: sp - syscall - - beq a3, a1, 1f # branch if parent - mov a6, a7 # args - callx4 a5 # fn(args) - - movi a2, __NR_exit - syscall # return value of fn(args) still in a6 - -1: retw - -/* - * Do a system call from kernel instead of calling sys_execve, so we end up - * with proper pt_regs. - * - * int kernel_execve(const char *fname, char *const argv[], charg *const envp[]) - * a2 a2 a3 a4 - */ - -ENTRY(kernel_execve) - entry a1, 16 - mov a6, a2 # arg0 is in a6 - movi a2, __NR_execve - syscall - - retw - -/* * Task switch. * * struct task* _switch_to (struct task* prev, struct task* next) @@ -1901,8 +1857,8 @@ ENTRY(_switch_to) /* Disable ints while we manipulate the stack pointer. */ movi a14, (1 << PS_EXCM_BIT) | LOCKLEVEL - xsr a14, PS - rsr a3, EXCSAVE_1 + xsr a14, ps + rsr a3, excsave1 rsync s32i a3, a3, EXC_TABLE_FIXUP /* enter critical section */ @@ -1910,7 +1866,7 @@ ENTRY(_switch_to) #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) l32i a3, a5, THREAD_CPENABLE - xsr a3, CPENABLE + xsr a3, cpenable s32i a3, a4, THREAD_CPENABLE #endif @@ -1924,7 +1880,7 @@ ENTRY(_switch_to) * we return from kernel space. */ - rsr a3, EXCSAVE_1 # exc_table + rsr a3, excsave1 # exc_table movi a6, 0 addi a7, a5, PT_REGS_OFFSET s32i a6, a3, EXC_TABLE_FIXUP @@ -1937,7 +1893,7 @@ ENTRY(_switch_to) load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER - wsr a14, PS + wsr a14, ps mov a2, a12 # return 'prev' rsync @@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork) j common_exception_return +/* + * Kernel thread creation helper + * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg + * left from _switch_to: a6 = prev + */ +ENTRY(ret_from_kernel_thread) + + call4 schedule_tail + mov a6, a3 + callx4 a2 + j common_exception_return + +ENDPROC(ret_from_kernel_thread) diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index 3ef91a73652..bdc50788f35 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S @@ -61,18 +61,18 @@ _startup: /* Disable interrupts and exceptions. */ movi a0, LOCKLEVEL - wsr a0, PS + wsr a0, ps /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */ - wsr a2, EXCSAVE_1 + wsr a2, excsave1 /* Start with a fresh windowbase and windowstart. */ movi a1, 1 movi a0, 0 - wsr a1, WINDOWSTART - wsr a0, WINDOWBASE + wsr a1, windowstart + wsr a0, windowbase rsync /* Set a0 to 0 for the remaining initialization. */ @@ -82,46 +82,46 @@ _startup: /* Clear debugging registers. */ #if XCHAL_HAVE_DEBUG - wsr a0, IBREAKENABLE - wsr a0, ICOUNT + wsr a0, ibreakenable + wsr a0, icount movi a1, 15 - wsr a0, ICOUNTLEVEL + wsr a0, icountlevel .set _index, 0 .rept XCHAL_NUM_DBREAK - 1 - wsr a0, DBREAKC + _index + wsr a0, SREG_DBREAKC + _index .set _index, _index + 1 .endr #endif /* Clear CCOUNT (not really necessary, but nice) */ - wsr a0, CCOUNT # not really necessary, but nice + wsr a0, ccount # not really necessary, but nice /* Disable zero-loops. */ #if XCHAL_HAVE_LOOPS - wsr a0, LCOUNT + wsr a0, lcount #endif /* Disable all timers. */ .set _index, 0 .rept XCHAL_NUM_TIMERS - 1 - wsr a0, CCOMPARE + _index + wsr a0, SREG_CCOMPARE + _index .set _index, _index + 1 .endr /* Interrupt initialization. */ movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE - wsr a0, INTENABLE - wsr a2, INTCLEAR + wsr a0, intenable + wsr a2, intclear /* Disable coprocessors. */ #if XCHAL_CP_NUM > 0 - wsr a0, CPENABLE + wsr a0, cpenable #endif /* Set PS.INTLEVEL=1, PS.WOE=0, kernel stack, PS.EXCM=0 @@ -132,7 +132,7 @@ _startup: */ movi a1, 1 - wsr a1, PS + wsr a1, ps rsync /* Initialize the caches. @@ -206,18 +206,18 @@ _startup: addi a1, a1, KERNEL_STACK_SIZE movi a2, 0x00040001 # WOE=1, INTLEVEL=1, UM=0 - wsr a2, PS # (enable reg-windows; progmode stack) + wsr a2, ps # (enable reg-windows; progmode stack) rsync /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/ movi a2, debug_exception - wsr a2, EXCSAVE + XCHAL_DEBUGLEVEL + wsr a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL /* Set up EXCSAVE[1] to point to the exc_table. */ movi a6, exc_table - xsr a6, EXCSAVE_1 + xsr a6, excsave1 /* init_arch kick-starts the linux kernel */ diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index 98e77c3ef1c..a6ce3e56373 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c @@ -72,13 +72,13 @@ int arch_show_interrupts(struct seq_file *p, int prec) static void xtensa_irq_mask(struct irq_data *d) { cached_irq_mask &= ~(1 << d->irq); - set_sr (cached_irq_mask, INTENABLE); + set_sr (cached_irq_mask, intenable); } static void xtensa_irq_unmask(struct irq_data *d) { cached_irq_mask |= 1 << d->irq; - set_sr (cached_irq_mask, INTENABLE); + set_sr (cached_irq_mask, intenable); } static void xtensa_irq_enable(struct irq_data *d) @@ -95,7 +95,7 @@ static void xtensa_irq_disable(struct irq_data *d) static void xtensa_irq_ack(struct irq_data *d) { - set_sr(1 << d->irq, INTCLEAR); + set_sr(1 << d->irq, intclear); } static int xtensa_irq_retrigger(struct irq_data *d) diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index bc020825cce..09ae7bfab9a 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -45,6 +45,7 @@ #include <asm/regs.h> extern void ret_from_fork(void); +extern void ret_from_kernel_thread(void); struct task_struct *current_set[NR_CPUS] = {&init_task, }; @@ -158,64 +159,123 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) /* * Copy thread. * + * There are two modes in which this function is called: + * 1) Userspace thread creation, + * regs != NULL, usp_thread_fn is userspace stack pointer. + * It is expected to copy parent regs (in case CLONE_VM is not set + * in the clone_flags) and set up passed usp in the childregs. + * 2) Kernel thread creation, + * regs == NULL, usp_thread_fn is the function to run in the new thread + * and thread_fn_arg is its parameter. + * childregs are not used for the kernel threads. + * * The stack layout for the new thread looks like this: * - * +------------------------+ <- sp in childregs (= tos) + * +------------------------+ * | childregs | * +------------------------+ <- thread.sp = sp in dummy-frame * | dummy-frame | (saved in dummy-frame spill-area) * +------------------------+ * - * We create a dummy frame to return to ret_from_fork: - * a0 points to ret_from_fork (simulating a call4) + * We create a dummy frame to return to either ret_from_fork or + * ret_from_kernel_thread: + * a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4) * sp points to itself (thread.sp) - * a2, a3 are unused. + * a2, a3 are unused for userspace threads, + * a2 points to thread_fn, a3 holds thread_fn arg for kernel threads. * * Note: This is a pristine frame, so we don't need any spill region on top of * childregs. + * + * The fun part: if we're keeping the same VM (i.e. cloning a thread, + * not an entire process), we're normally given a new usp, and we CANNOT share + * any live address register windows. If we just copy those live frames over, + * the two threads (parent and child) will overflow the same frames onto the + * parent stack at different times, likely corrupting the parent stack (esp. + * if the parent returns from functions that called clone() and calls new + * ones, before the child overflows its now old copies of its parent windows). + * One solution is to spill windows to the parent stack, but that's fairly + * involved. Much simpler to just not copy those live frames across. */ -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct * p, struct pt_regs * regs) +int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, + unsigned long thread_fn_arg, + struct task_struct *p, struct pt_regs *unused) { - struct pt_regs *childregs; - struct thread_info *ti; - unsigned long tos; - int user_mode = user_mode(regs); - - /* Set up new TSS. */ - tos = (unsigned long)task_stack_page(p) + THREAD_SIZE; - if (user_mode) - childregs = (struct pt_regs*)(tos - PT_USER_SIZE); - else - childregs = (struct pt_regs*)tos - 1; + struct pt_regs *childregs = task_pt_regs(p); - *childregs = *regs; +#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) + struct thread_info *ti; +#endif /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ *((int*)childregs - 3) = (unsigned long)childregs; *((int*)childregs - 4) = 0; - childregs->areg[1] = tos; - childregs->areg[2] = 0; - p->set_child_tid = p->clear_child_tid = NULL; - p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1); p->thread.sp = (unsigned long)childregs; - if (user_mode(regs)) { + if (!(p->flags & PF_KTHREAD)) { + struct pt_regs *regs = current_pt_regs(); + unsigned long usp = usp_thread_fn ? + usp_thread_fn : regs->areg[1]; - int len = childregs->wmask & ~0xf; + p->thread.ra = MAKE_RA_FOR_CALL( + (unsigned long)ret_from_fork, 0x1); + + /* This does not copy all the regs. + * In a bout of brilliance or madness, + * ARs beyond a0-a15 exist past the end of the struct. + */ + *childregs = *regs; childregs->areg[1] = usp; - memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], - ®s->areg[XCHAL_NUM_AREGS - len/4], len); + childregs->areg[2] = 0; + + /* When sharing memory with the parent thread, the child + usually starts on a pristine stack, so we have to reset + windowbase, windowstart and wmask. + (Note that such a new thread is required to always create + an initial call4 frame) + The exception is vfork, where the new thread continues to + run on the parent's stack until it calls execve. This could + be a call8 or call12, which requires a legal stack frame + of the previous caller for the overflow handlers to work. + (Note that it's always legal to overflow live registers). + In this case, ensure to spill at least the stack pointer + of that frame. */ + + if (clone_flags & CLONE_VM) { + /* check that caller window is live and same stack */ + int len = childregs->wmask & ~0xf; + if (regs->areg[1] == usp && len != 0) { + int callinc = (regs->areg[0] >> 30) & 3; + int caller_ars = XCHAL_NUM_AREGS - callinc * 4; + put_user(regs->areg[caller_ars+1], + (unsigned __user*)(usp - 12)); + } + childregs->wmask = 1; + childregs->windowstart = 1; + childregs->windowbase = 0; + } else { + int len = childregs->wmask & ~0xf; + memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], + ®s->areg[XCHAL_NUM_AREGS - len/4], len); + } // FIXME: we need to set THREADPTR in thread_info... if (clone_flags & CLONE_SETTLS) childregs->areg[2] = childregs->areg[6]; - } else { - /* In kernel space, we start a new thread with a new stack. */ - childregs->wmask = 1; + p->thread.ra = MAKE_RA_FOR_CALL( + (unsigned long)ret_from_kernel_thread, 1); + + /* pass parameters to ret_from_kernel_thread: + * a2 = thread_fn, a3 = thread_fn arg + */ + *((int *)childregs - 1) = thread_fn_arg; + *((int *)childregs - 2) = usp_thread_fn; + + /* Childregs are only used when we're going to userspace + * in which case start_thread will set them up. + */ } #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) @@ -311,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp, void __user *child_tid, long a5, struct pt_regs *regs) { - if (!newsp) - newsp = regs->areg[1]; return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); } - -/* - * xtensa_execve() executes a new program. - */ - -asmlinkage -long xtensa_execve(const char __user *name, - const char __user *const __user *argv, - const char __user *const __user *envp, - long a3, long a4, long a5, - struct pt_regs *regs) -{ - long error; - struct filename *filename; - - filename = getname(name); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename->name, argv, envp, regs); - putname(filename); -out: - return error; -} - diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 270360d9806..b237988ba6d 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -100,7 +100,7 @@ typedef struct tagtable { } tagtable_t; #define __tagtable(tag, fn) static tagtable_t __tagtable_##fn \ - __attribute__((unused, __section__(".taglist"))) = { tag, fn } + __attribute__((used, section(".taglist"))) = { tag, fn } /* parse current tag */ @@ -120,7 +120,7 @@ static int __init parse_tag_mem(const bp_tag_t *tag) } sysmem.bank[sysmem.nr_banks].type = mi->type; sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start); - sysmem.bank[sysmem.nr_banks].end = mi->end & PAGE_SIZE; + sysmem.bank[sysmem.nr_banks].end = mi->end & PAGE_MASK; sysmem.nr_banks++; return 0; diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index 05b3f093d5d..5702065f472 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c @@ -32,11 +32,8 @@ typedef void (*syscall_t)(void); syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= { [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall, -#undef __SYSCALL #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol, -#undef _XTENSA_UNISTD_H -#undef __KERNEL_SYSCALLS__ -#include <asm/unistd.h> +#include <uapi/asm/unistd.h> }; asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) @@ -50,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) return (long)ret; } -asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len) +asmlinkage long xtensa_fadvise64_64(int fd, int advice, + unsigned long long offset, unsigned long long len) { return sys_fadvise64_64(fd, offset, len, advice); } diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index bc1e14cf936..5caf2b64d43 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -97,7 +97,7 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = { /* EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */ /* EXCCAUSE_PRIVILEGED unhandled */ #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION -#ifdef CONFIG_UNALIGNED_USER +#ifdef CONFIG_XTENSA_UNALIGNED_USER { EXCCAUSE_UNALIGNED, USER, fast_unaligned }, #else { EXCCAUSE_UNALIGNED, 0, do_unaligned_user }, @@ -202,8 +202,8 @@ extern void do_IRQ(int, struct pt_regs *); void do_interrupt (struct pt_regs *regs) { - unsigned long intread = get_sr (INTREAD); - unsigned long intenable = get_sr (INTENABLE); + unsigned long intread = get_sr (interrupt); + unsigned long intenable = get_sr (intenable); int i, mask; /* Handle all interrupts (no priorities). @@ -213,7 +213,7 @@ void do_interrupt (struct pt_regs *regs) for (i=0, mask = 1; i < XCHAL_NUM_INTERRUPTS; i++, mask <<= 1) { if (mask & (intread & intenable)) { - set_sr (mask, INTCLEAR); + set_sr (mask, intclear); do_IRQ (i,regs); } } @@ -244,7 +244,7 @@ do_illegal_instruction(struct pt_regs *regs) */ #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION -#ifndef CONFIG_UNALIGNED_USER +#ifndef CONFIG_XTENSA_UNALIGNED_USER void do_unaligned_user (struct pt_regs *regs) { @@ -339,7 +339,7 @@ void __init trap_init(void) /* Initialize EXCSAVE_1 to hold the address of the exception table. */ i = (unsigned long)exc_table; - __asm__ __volatile__("wsr %0, "__stringify(EXCSAVE_1)"\n" : : "a" (i)); + __asm__ __volatile__("wsr %0, excsave1\n" : : "a" (i)); } /* @@ -386,16 +386,16 @@ static inline void spill_registers(void) unsigned int a0, ps; __asm__ __volatile__ ( - "movi a14," __stringify (PS_EXCM_BIT) " | 1\n\t" + "movi a14, " __stringify(PS_EXCM_BIT | 1) "\n\t" "mov a12, a0\n\t" - "rsr a13," __stringify(SAR) "\n\t" - "xsr a14," __stringify(PS) "\n\t" + "rsr a13, sar\n\t" + "xsr a14, ps\n\t" "movi a0, _spill_registers\n\t" "rsync\n\t" "callx0 a0\n\t" "mov a0, a12\n\t" - "wsr a13," __stringify(SAR) "\n\t" - "wsr a14," __stringify(PS) "\n\t" + "wsr a13, sar\n\t" + "wsr a14, ps\n\t" :: "a" (&a0), "a" (&ps) : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory"); } diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S index 70066e3582d..4462c1e595c 100644 --- a/arch/xtensa/kernel/vectors.S +++ b/arch/xtensa/kernel/vectors.S @@ -69,11 +69,11 @@ ENTRY(_UserExceptionVector) - xsr a3, EXCSAVE_1 # save a3 and get dispatch table - wsr a2, DEPC # save a2 + xsr a3, excsave1 # save a3 and get dispatch table + wsr a2, depc # save a2 l32i a2, a3, EXC_TABLE_KSTK # load kernel stack to a2 s32i a0, a2, PT_AREG0 # save a0 to ESF - rsr a0, EXCCAUSE # retrieve exception cause + rsr a0, exccause # retrieve exception cause s32i a0, a2, PT_DEPC # mark it as a regular exception addx4 a0, a0, a3 # find entry in table l32i a0, a0, EXC_TABLE_FAST_USER # load handler @@ -93,11 +93,11 @@ ENTRY(_UserExceptionVector) ENTRY(_KernelExceptionVector) - xsr a3, EXCSAVE_1 # save a3, and get dispatch table - wsr a2, DEPC # save a2 + xsr a3, excsave1 # save a3, and get dispatch table + wsr a2, depc # save a2 addi a2, a1, -16-PT_SIZE # adjust stack pointer s32i a0, a2, PT_AREG0 # save a0 to ESF - rsr a0, EXCCAUSE # retrieve exception cause + rsr a0, exccause # retrieve exception cause s32i a0, a2, PT_DEPC # mark it as a regular exception addx4 a0, a0, a3 # find entry in table l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address @@ -205,17 +205,17 @@ ENTRY(_DoubleExceptionVector) /* Deliberately destroy excsave (don't assume it's value was valid). */ - wsr a3, EXCSAVE_1 # save a3 + wsr a3, excsave1 # save a3 /* Check for kernel double exception (usually fatal). */ - rsr a3, PS + rsr a3, ps _bbci.l a3, PS_UM_BIT, .Lksp /* Check if we are currently handling a window exception. */ /* Note: We don't need to indicate that we enter a critical section. */ - xsr a0, DEPC # get DEPC, save a0 + xsr a0, depc # get DEPC, save a0 movi a3, XCHAL_WINDOW_VECTORS_VADDR _bltu a0, a3, .Lfixup @@ -243,21 +243,21 @@ ENTRY(_DoubleExceptionVector) * Note: We can trash the current window frame (a0...a3) and depc! */ - wsr a2, DEPC # save stack pointer temporarily - rsr a0, PS + wsr a2, depc # save stack pointer temporarily + rsr a0, ps extui a0, a0, PS_OWB_SHIFT, 4 - wsr a0, WINDOWBASE + wsr a0, windowbase rsync /* We are now in the previous window frame. Save registers again. */ - xsr a2, DEPC # save a2 and get stack pointer + xsr a2, depc # save a2 and get stack pointer s32i a0, a2, PT_AREG0 - wsr a3, EXCSAVE_1 # save a3 + wsr a3, excsave1 # save a3 movi a3, exc_table - rsr a0, EXCCAUSE + rsr a0, exccause s32i a0, a2, PT_DEPC # mark it as a regular exception addx4 a0, a0, a3 l32i a0, a0, EXC_TABLE_FAST_USER @@ -290,14 +290,14 @@ ENTRY(_DoubleExceptionVector) /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */ - xsr a3, DEPC + xsr a3, depc s32i a0, a2, PT_DEPC s32i a3, a2, PT_AREG0 /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */ movi a3, exc_table - rsr a0, EXCCAUSE + rsr a0, exccause addx4 a0, a0, a3 l32i a0, a0, EXC_TABLE_FAST_USER jx a0 @@ -312,7 +312,7 @@ ENTRY(_DoubleExceptionVector) .Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */ - rsr a3, EXCCAUSE + rsr a3, exccause beqi a3, EXCCAUSE_ITLB_MISS, 1f addi a3, a3, -EXCCAUSE_DTLB_MISS bnez a3, .Lunrecoverable @@ -328,11 +328,11 @@ ENTRY(_DoubleExceptionVector) .Lunrecoverable_fixup: l32i a2, a3, EXC_TABLE_DOUBLE_SAVE - xsr a0, DEPC + xsr a0, depc .Lunrecoverable: - rsr a3, EXCSAVE_1 - wsr a0, EXCSAVE_1 + rsr a3, excsave1 + wsr a0, excsave1 movi a0, unrecoverable_exception callx0 a0 @@ -349,7 +349,7 @@ ENTRY(_DoubleExceptionVector) .section .DebugInterruptVector.text, "ax" ENTRY(_DebugInterruptVector) - xsr a0, EXCSAVE + XCHAL_DEBUGLEVEL + xsr a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL jx a0 diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index a8b9f1fd1e1..afe058b24e6 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user); EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(copy_page); -EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(empty_zero_page); /* diff --git a/arch/xtensa/lib/memcopy.S b/arch/xtensa/lib/memcopy.S index ea59dcd0386..c48b80acb5f 100644 --- a/arch/xtensa/lib/memcopy.S +++ b/arch/xtensa/lib/memcopy.S @@ -6,7 +6,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2002 - 2005 Tensilica Inc. + * Copyright (C) 2002 - 2012 Tensilica Inc. */ #include <variant/core.h> @@ -27,14 +27,11 @@ #endif .endm - /* * void *memcpy(void *dst, const void *src, size_t len); - * void *memmove(void *dst, const void *src, size_t len); - * void *bcopy(const void *src, void *dst, size_t len); * * This function is intended to do the same thing as the standard - * library function memcpy() (or bcopy()) for most cases. + * library function memcpy() for most cases. * However, where the source and/or destination references * an instruction RAM or ROM or a data RAM or ROM, that * source and/or destination will always be accessed with @@ -45,9 +42,6 @@ * !!!!!!! Handling of IRAM/IROM has not yet * !!!!!!! been implemented. * - * The bcopy version is provided here to avoid the overhead - * of an extra call, for callers that require this convention. - * * The (general case) algorithm is as follows: * If destination is unaligned, align it by conditionally * copying 1 and 2 bytes. @@ -76,17 +70,6 @@ */ .text - .align 4 - .global bcopy - .type bcopy,@function -bcopy: - entry sp, 16 # minimal stack frame - # a2=src, a3=dst, a4=len - mov a5, a3 # copy dst so that a2 is return value - mov a3, a2 - mov a2, a5 - j .Lcommon # go to common code for memcpy+bcopy - /* * Byte by byte copy @@ -107,7 +90,7 @@ bcopy: s8i a6, a5, 0 addi a5, a5, 1 #if !XCHAL_HAVE_LOOPS - blt a3, a7, .Lnextbyte + bne a3, a7, .Lnextbyte # continue loop if $a3:src != $a7:src_end #endif /* !XCHAL_HAVE_LOOPS */ .Lbytecopydone: retw @@ -144,9 +127,6 @@ bcopy: .global memcpy .type memcpy,@function memcpy: - .global memmove - .type memmove,@function -memmove: entry sp, 16 # minimal stack frame # a2/ dst, a3/ src, a4/ len @@ -182,7 +162,7 @@ memmove: s32i a7, a5, 12 addi a5, a5, 16 #if !XCHAL_HAVE_LOOPS - blt a3, a8, .Loop1 + bne a3, a8, .Loop1 # continue loop if a3:src != a8:src_end #endif /* !XCHAL_HAVE_LOOPS */ .Loop1done: bbci.l a4, 3, .L2 @@ -260,7 +240,7 @@ memmove: s32i a9, a5, 12 addi a5, a5, 16 #if !XCHAL_HAVE_LOOPS - blt a3, a10, .Loop2 + bne a3, a10, .Loop2 # continue loop if a3:src != a10:src_end #endif /* !XCHAL_HAVE_LOOPS */ .Loop2done: bbci.l a4, 3, .L12 @@ -305,6 +285,285 @@ memmove: l8ui a6, a3, 0 s8i a6, a5, 0 retw + + +/* + * void bcopy(const void *src, void *dest, size_t n); + */ + .align 4 + .global bcopy + .type bcopy,@function +bcopy: + entry sp, 16 # minimal stack frame + # a2=src, a3=dst, a4=len + mov a5, a3 + mov a3, a2 + mov a2, a5 + j .Lmovecommon # go to common code for memmove+bcopy + +/* + * void *memmove(void *dst, const void *src, size_t len); + * + * This function is intended to do the same thing as the standard + * library function memmove() for most cases. + * However, where the source and/or destination references + * an instruction RAM or ROM or a data RAM or ROM, that + * source and/or destination will always be accessed with + * 32-bit load and store instructions (as required for these + * types of devices). + * + * !!!!!!! XTFIXME: + * !!!!!!! Handling of IRAM/IROM has not yet + * !!!!!!! been implemented. + * + * The (general case) algorithm is as follows: + * If end of source doesn't overlap destination then use memcpy. + * Otherwise do memcpy backwards. + * + * Register use: + * a0/ return address + * a1/ stack pointer + * a2/ return value + * a3/ src + * a4/ length + * a5/ dst + * a6/ tmp + * a7/ tmp + * a8/ tmp + * a9/ tmp + * a10/ tmp + * a11/ tmp + */ + +/* + * Byte by byte copy + */ + .align 4 + .byte 0 # 1 mod 4 alignment for LOOPNEZ + # (0 mod 4 alignment for LBEG) +.Lbackbytecopy: +#if XCHAL_HAVE_LOOPS + loopnez a4, .Lbackbytecopydone +#else /* !XCHAL_HAVE_LOOPS */ + beqz a4, .Lbackbytecopydone + sub a7, a3, a4 # a7 = start address for source +#endif /* !XCHAL_HAVE_LOOPS */ +.Lbacknextbyte: + addi a3, a3, -1 + l8ui a6, a3, 0 + addi a5, a5, -1 + s8i a6, a5, 0 +#if !XCHAL_HAVE_LOOPS + bne a3, a7, .Lbacknextbyte # continue loop if + # $a3:src != $a7:src_start +#endif /* !XCHAL_HAVE_LOOPS */ +.Lbackbytecopydone: + retw + +/* + * Destination is unaligned + */ + + .align 4 +.Lbackdst1mod2: # dst is only byte aligned + _bltui a4, 7, .Lbackbytecopy # do short copies byte by byte + + # copy 1 byte + addi a3, a3, -1 + l8ui a6, a3, 0 + addi a5, a5, -1 + s8i a6, a5, 0 + addi a4, a4, -1 + _bbci.l a5, 1, .Lbackdstaligned # if dst is now aligned, then + # return to main algorithm +.Lbackdst2mod4: # dst 16-bit aligned + # copy 2 bytes + _bltui a4, 6, .Lbackbytecopy # do short copies byte by byte + addi a3, a3, -2 + l8ui a6, a3, 0 + l8ui a7, a3, 1 + addi a5, a5, -2 + s8i a6, a5, 0 + s8i a7, a5, 1 + addi a4, a4, -2 + j .Lbackdstaligned # dst is now aligned, + # return to main algorithm + + .align 4 + .global memmove + .type memmove,@function +memmove: + + entry sp, 16 # minimal stack frame + # a2/ dst, a3/ src, a4/ len + mov a5, a2 # copy dst so that a2 is return value +.Lmovecommon: + sub a6, a5, a3 + bgeu a6, a4, .Lcommon + + add a5, a5, a4 + add a3, a3, a4 + + _bbsi.l a5, 0, .Lbackdst1mod2 # if dst is 1 mod 2 + _bbsi.l a5, 1, .Lbackdst2mod4 # if dst is 2 mod 4 +.Lbackdstaligned: # return here from .Lbackdst?mod? once dst is aligned + srli a7, a4, 4 # number of loop iterations with 16B + # per iteration + movi a8, 3 # if source is not aligned, + _bany a3, a8, .Lbacksrcunaligned # then use shifting copy + /* + * Destination and source are word-aligned, use word copy. + */ + # copy 16 bytes per iteration for word-aligned dst and word-aligned src +#if XCHAL_HAVE_LOOPS + loopnez a7, .backLoop1done +#else /* !XCHAL_HAVE_LOOPS */ + beqz a7, .backLoop1done + slli a8, a7, 4 + sub a8, a3, a8 # a8 = start of first 16B source chunk +#endif /* !XCHAL_HAVE_LOOPS */ +.backLoop1: + addi a3, a3, -16 + l32i a7, a3, 12 + l32i a6, a3, 8 + addi a5, a5, -16 + s32i a7, a5, 12 + l32i a7, a3, 4 + s32i a6, a5, 8 + l32i a6, a3, 0 + s32i a7, a5, 4 + s32i a6, a5, 0 +#if !XCHAL_HAVE_LOOPS + bne a3, a8, .backLoop1 # continue loop if a3:src != a8:src_start +#endif /* !XCHAL_HAVE_LOOPS */ +.backLoop1done: + bbci.l a4, 3, .Lback2 + # copy 8 bytes + addi a3, a3, -8 + l32i a6, a3, 0 + l32i a7, a3, 4 + addi a5, a5, -8 + s32i a6, a5, 0 + s32i a7, a5, 4 +.Lback2: + bbsi.l a4, 2, .Lback3 + bbsi.l a4, 1, .Lback4 + bbsi.l a4, 0, .Lback5 + retw +.Lback3: + # copy 4 bytes + addi a3, a3, -4 + l32i a6, a3, 0 + addi a5, a5, -4 + s32i a6, a5, 0 + bbsi.l a4, 1, .Lback4 + bbsi.l a4, 0, .Lback5 + retw +.Lback4: + # copy 2 bytes + addi a3, a3, -2 + l16ui a6, a3, 0 + addi a5, a5, -2 + s16i a6, a5, 0 + bbsi.l a4, 0, .Lback5 + retw +.Lback5: + # copy 1 byte + addi a3, a3, -1 + l8ui a6, a3, 0 + addi a5, a5, -1 + s8i a6, a5, 0 + retw + +/* + * Destination is aligned, Source is unaligned + */ + + .align 4 +.Lbacksrcunaligned: + _beqz a4, .Lbackdone # avoid loading anything for zero-length copies + # copy 16 bytes per iteration for word-aligned dst and unaligned src + ssa8 a3 # set shift amount from byte offset +#define SIM_CHECKS_ALIGNMENT 1 /* set to 1 when running on ISS with + * the lint or ferret client, or 0 + * to save a few cycles */ +#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT + and a11, a3, a8 # save unalignment offset for below + sub a3, a3, a11 # align a3 +#endif + l32i a6, a3, 0 # load first word +#if XCHAL_HAVE_LOOPS + loopnez a7, .backLoop2done +#else /* !XCHAL_HAVE_LOOPS */ + beqz a7, .backLoop2done + slli a10, a7, 4 + sub a10, a3, a10 # a10 = start of first 16B source chunk +#endif /* !XCHAL_HAVE_LOOPS */ +.backLoop2: + addi a3, a3, -16 + l32i a7, a3, 12 + l32i a8, a3, 8 + addi a5, a5, -16 + src_b a6, a7, a6 + s32i a6, a5, 12 + l32i a9, a3, 4 + src_b a7, a8, a7 + s32i a7, a5, 8 + l32i a6, a3, 0 + src_b a8, a9, a8 + s32i a8, a5, 4 + src_b a9, a6, a9 + s32i a9, a5, 0 +#if !XCHAL_HAVE_LOOPS + bne a3, a10, .backLoop2 # continue loop if a3:src != a10:src_start +#endif /* !XCHAL_HAVE_LOOPS */ +.backLoop2done: + bbci.l a4, 3, .Lback12 + # copy 8 bytes + addi a3, a3, -8 + l32i a7, a3, 4 + l32i a8, a3, 0 + addi a5, a5, -8 + src_b a6, a7, a6 + s32i a6, a5, 4 + src_b a7, a8, a7 + s32i a7, a5, 0 + mov a6, a8 +.Lback12: + bbci.l a4, 2, .Lback13 + # copy 4 bytes + addi a3, a3, -4 + l32i a7, a3, 0 + addi a5, a5, -4 + src_b a6, a7, a6 + s32i a6, a5, 0 + mov a6, a7 +.Lback13: +#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT + add a3, a3, a11 # readjust a3 with correct misalignment +#endif + bbsi.l a4, 1, .Lback14 + bbsi.l a4, 0, .Lback15 +.Lbackdone: + retw +.Lback14: + # copy 2 bytes + addi a3, a3, -2 + l8ui a6, a3, 0 + l8ui a7, a3, 1 + addi a5, a5, -2 + s8i a6, a5, 0 + s8i a7, a5, 1 + bbsi.l a4, 0, .Lback15 + retw +.Lback15: + # copy 1 byte + addi a3, a3, -1 + addi a5, a5, -1 + l8ui a6, a3, 0 + s8i a6, a5, 0 + retw + /* * Local Variables: diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index 2c2f710ed1d..245b08f7eaf 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c @@ -6,7 +6,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001 - 2005 Tensilica Inc. + * Copyright (C) 2001 - 2010 Tensilica Inc. * * Chris Zankel <chris@zankel.net> * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> @@ -186,6 +186,7 @@ do_sigbus: /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) bad_page_fault(regs, address, SIGBUS); + return; vmalloc_fault: { diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 8ab47edd7c8..7e74895eee0 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -91,7 +91,7 @@ static int rs_write(struct tty_struct * tty, { /* see drivers/char/serialX.c to reference original version */ - __simc (SYS_write, 1, (unsigned long)buf, count, 0, 0); + simc_write(1, buf, count); return count; } @@ -122,12 +122,7 @@ static void rs_poll(unsigned long priv) static int rs_put_char(struct tty_struct *tty, unsigned char ch) { - char buf[2]; - - buf[0] = ch; - buf[1] = '\0'; /* Is this NULL necessary? */ - __simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0); - return 1; + return rs_write(tty, &ch, 1); } static void rs_flush_chars(struct tty_struct *tty) diff --git a/arch/xtensa/platforms/iss/include/platform/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h index 8c43bfea05e..bd78192e2fc 100644 --- a/arch/xtensa/platforms/iss/include/platform/simcall.h +++ b/arch/xtensa/platforms/iss/include/platform/simcall.h @@ -78,8 +78,9 @@ static inline int __simc(int a, int b, int c, int d, int e, int f) return ret; } -static inline int simc_open(char *file, int flags, int mode) +static inline int simc_open(const char *file, int flags, int mode) { + wmb(); return __simc(SYS_open, (int) file, flags, mode, 0, 0); } @@ -90,16 +91,19 @@ static inline int simc_close(int fd) static inline int simc_ioctl(int fd, int request, void *arg) { + wmb(); return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0); } static inline int simc_read(int fd, void *buf, size_t count) { + rmb(); return __simc(SYS_read, fd, (int) buf, count, 0, 0); } -static inline int simc_write(int fd, void *buf, size_t count) +static inline int simc_write(int fd, const void *buf, size_t count) { + wmb(); return __simc(SYS_write, fd, (int) buf, count, 0, 0); } @@ -107,6 +111,7 @@ static inline int simc_poll(int fd) { struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; + wmb(); return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv, 0, 0); } diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c index 927acf378ea..e1700102f35 100644 --- a/arch/xtensa/platforms/iss/setup.c +++ b/arch/xtensa/platforms/iss/setup.c @@ -61,13 +61,13 @@ void platform_restart(void) * jump to the reset vector. */ __asm__ __volatile__("movi a2, 15\n\t" - "wsr a2, " __stringify(ICOUNTLEVEL) "\n\t" + "wsr a2, icountlevel\n\t" "movi a2, 0\n\t" - "wsr a2, " __stringify(ICOUNT) "\n\t" - "wsr a2, " __stringify(IBREAKENABLE) "\n\t" - "wsr a2, " __stringify(LCOUNT) "\n\t" + "wsr a2, icount\n\t" + "wsr a2, ibreakenable\n\t" + "wsr a2, lcount\n\t" "movi a2, 0x1f\n\t" - "wsr a2, " __stringify(PS) "\n\t" + "wsr a2, ps\n\t" "isync\n\t" "jx %0\n\t" : diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c index 9e83940ac26..c7d90f17886 100644 --- a/arch/xtensa/platforms/xt2000/setup.c +++ b/arch/xtensa/platforms/xt2000/setup.c @@ -66,13 +66,13 @@ void platform_restart(void) * jump to the reset vector. */ __asm__ __volatile__ ("movi a2, 15\n\t" - "wsr a2, " __stringify(ICOUNTLEVEL) "\n\t" + "wsr a2, icountlevel\n\t" "movi a2, 0\n\t" - "wsr a2, " __stringify(ICOUNT) "\n\t" - "wsr a2, " __stringify(IBREAKENABLE) "\n\t" - "wsr a2, " __stringify(LCOUNT) "\n\t" + "wsr a2, icount\n\t" + "wsr a2, ibreakenable\n\t" + "wsr a2, lcount\n\t" "movi a2, 0x1f\n\t" - "wsr a2, " __stringify(PS) "\n\t" + "wsr a2, ps\n\t" "isync\n\t" "jx %0\n\t" : diff --git a/block/Kconfig b/block/Kconfig index 09acf1b3990..a7e40a7c821 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY config BLK_DEV_THROTTLING bool "Block layer bio throttling support" - depends on BLK_CGROUP=y && EXPERIMENTAL + depends on BLK_CGROUP=y default n ---help--- Block layer bio throttling support. It can be used to limit diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index cafcd743118..d0b770391ad 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q) blkg_destroy(blkg); spin_unlock(&blkcg->lock); } + + /* + * root blkg is destroyed. Just clear the pointer since + * root_rl does not take reference on root blkg. + */ + q->root_blkg = NULL; + q->root_rl.blkg = NULL; } static void blkg_rcu_free(struct rcu_head *rcu_head) @@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl, */ if (rl == &q->root_rl) { ent = &q->blkg_list; + /* There are no more block groups, hence no request lists */ + if (list_empty(ent)) + return NULL; } else { blkg = container_of(rl, struct blkcg_gq, rl); ent = &blkg->q_node; diff --git a/block/blk-core.c b/block/blk-core.c index a33870b1847..3c95c4d6e31 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2868,7 +2868,8 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b) struct request *rqa = container_of(a, struct request, queuelist); struct request *rqb = container_of(b, struct request, queuelist); - return !(rqa->q <= rqb->q); + return !(rqa->q < rqb->q || + (rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb))); } /* diff --git a/block/blk-exec.c b/block/blk-exec.c index 8b6dc5bd4dd..f71eac35c1b 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -52,11 +52,17 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, rq_end_io_fn *done) { int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; + bool is_pm_resume; WARN_ON(irqs_disabled()); rq->rq_disk = bd_disk; rq->end_io = done; + /* + * need to check this before __blk_run_queue(), because rq can + * be freed before that returns. + */ + is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME; spin_lock_irq(q->queue_lock); @@ -71,7 +77,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, __elv_add_request(q, rq, where); __blk_run_queue(q); /* the queue is stopped so it won't be run */ - if (rq->cmd_type == REQ_TYPE_PM_RESUME) + if (is_pm_resume) q->request_fn(q); spin_unlock_irq(q->queue_lock); } diff --git a/crypto/cryptd.c b/crypto/cryptd.c index 671d4d6d14d..7bdd61b867c 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work) struct crypto_async_request *req, *backlog; cpu_queue = container_of(work, struct cryptd_cpu_queue, work); - /* Only handle one request at a time to avoid hogging crypto - * workqueue. preempt_disable/enable is used to prevent - * being preempted by cryptd_enqueue_request() */ + /* + * Only handle one request at a time to avoid hogging crypto workqueue. + * preempt_disable/enable is used to prevent being preempted by + * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent + * cryptd_enqueue_request() being accessed from software interrupts. + */ + local_bh_disable(); preempt_disable(); backlog = crypto_get_backlog(&cpu_queue->queue); req = crypto_dequeue_request(&cpu_queue->queue); preempt_enable(); + local_bh_enable(); if (!req) return; diff --git a/drivers/Makefile b/drivers/Makefile index 03da5b663ae..a16a8d001ae 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -17,6 +17,10 @@ obj-$(CONFIG_PARISC) += parisc/ obj-$(CONFIG_RAPIDIO) += rapidio/ obj-y += video/ obj-y += idle/ + +# IPMI must come before ACPI in order to provide IPMI opregion support +obj-$(CONFIG_IPMI_HANDLER) += char/ipmi/ + obj-$(CONFIG_ACPI) += acpi/ obj-$(CONFIG_SFI) += sfi/ # PnP must come after ACPI since it will eventually need to check if acpi diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 47199e2a913..82422fe90f8 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -47,6 +47,10 @@ acpi-y += video_detect.o endif # These are (potentially) separate modules + +# IPMI may be used by other drivers, so it has to initialise before them +obj-$(CONFIG_ACPI_IPMI) += acpi_ipmi.o + obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_FAN) += fan.o @@ -70,6 +74,5 @@ processor-y += processor_idle.o processor_thermal.o processor-$(CONFIG_CPU_FREQ) += processor_perflib.o obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o -obj-$(CONFIG_ACPI_IPMI) += acpi_ipmi.o obj-$(CONFIG_ACPI_APEI) += apei/ diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index d1a2d74033e..08373086cd7 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -159,6 +159,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) { retval = -ENOSPC; mutex_unlock(&acpi_dev->physical_node_lock); + kfree(physical_node); goto err; } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index e78c2a52ea4..bd4e5dca3ff 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -409,6 +409,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event) acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); + break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index f94d4c818fc..0230cb6cbb3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1345,12 +1345,15 @@ static int acpi_video_bus_get_devices(struct acpi_video_bus *video, struct acpi_device *device) { - int status; + int status = 0; struct acpi_device *dev; - status = acpi_video_device_enumerate(video); - if (status) - return status; + /* + * There are systems where video module known to work fine regardless + * of broken _DOD and ignoring returned value here doesn't cause + * any issues later. + */ + acpi_video_device_enumerate(video); list_for_each_entry(dev, &device->children, node) { diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index b1ae48054dc..b7078afddb7 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -238,7 +238,7 @@ static int __devexit ahci_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int ahci_suspend(struct device *dev) { struct ahci_platform_data *pdata = dev_get_platdata(dev); diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index fd9ecf74e63..5b0ba3f20ed 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev, struct acpi_device *acpi_dev; struct acpi_device_power_state *states; - if (ap->flags & ATA_FLAG_ACPI_SATA) - ata_dev = &ap->link.device[sdev->channel]; - else + if (ap->flags & ATA_FLAG_ACPI_SATA) { + if (!sata_pmp_attached(ap)) + ata_dev = &ap->link.device[sdev->id]; + else + ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id]; + } + else { ata_dev = &ap->link.device[sdev->id]; + } *handle = ata_dev_acpi_handle(ata_dev); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3cc7096cfda..f46fbd3bd3f 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2942,6 +2942,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode) if (xfer_mode == t->mode) return t; + + WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n", + __func__, xfer_mode); + return NULL; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index e3bda074fa1..a6df6a351d6 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1052,6 +1052,8 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) { sdev->use_10_for_rw = 1; sdev->use_10_for_ms = 1; + sdev->no_report_opcodes = 1; + sdev->no_write_same = 1; /* Schedule policy is determined by ->qc_defer() callback and * it needs to see every deferred qc. Set dev_blocked to 1 to diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 26201ebef3c..371fd2c698b 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -317,6 +317,12 @@ static int cf_init(struct arasan_cf_dev *acdev) return ret; } + ret = clk_set_rate(acdev->clk, 166000000); + if (ret) { + dev_warn(acdev->host->dev, "clock set rate failed"); + return ret; + } + spin_lock_irqsave(&acdev->host->lock, flags); /* configure CF interface clock */ writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk : @@ -908,7 +914,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int arasan_cf_suspend(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index 0d7c4c2cd26..400bf1c3e98 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c @@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = { }; MODULE_DEVICE_TABLE(of, ahci_of_match); -static int __init ahci_highbank_probe(struct platform_device *pdev) +static int __devinit ahci_highbank_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ahci_host_priv *hpriv; @@ -378,7 +378,7 @@ static int __devexit ahci_highbank_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int ahci_highbank_suspend(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 44a4256533e..08608de87e4 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link, return 0; } +static int k2_sata_softreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return ata_sff_softreset(link, class, deadline); +} + +static int k2_sata_hardreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return sata_sff_hardreset(link, class, deadline); +} static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) { @@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = { static struct ata_port_operations k2_sata_ops = { .inherits = &ata_bmdma_port_ops, + .softreset = k2_sata_softreset, + .hardreset = k2_sata_hardreset, .sff_tf_load = k2_sata_tf_load, .sff_tf_read = k2_sata_tf_read, .sff_check_status = k2_stat_check_status, diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 08b4c520938..b34b5cda5ae 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -236,7 +236,7 @@ config CMA_SIZE_PERCENTAGE choice prompt "Selected region size" - default CMA_SIZE_SEL_ABSOLUTE + default CMA_SIZE_SEL_MBYTES config CMA_SIZE_SEL_MBYTES bool "Use mega bytes value only" diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 560a7173f81..bc256b64102 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -191,9 +191,8 @@ EXPORT_SYMBOL(dma_release_from_coherent); * This checks whether the memory was allocated from the per-device * coherent memory pool and if so, maps that memory to the provided vma. * - * Returns 1 if we correctly mapped the memory, or 0 if - * dma_release_coherent() should proceed with mapping memory from - * generic pools. + * Returns 1 if we correctly mapped the memory, or 0 if the caller should + * proceed with mapping memory from generic pools. */ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, void *vaddr, size_t size, int *ret) diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 9a1469474f5..612afcc5a93 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -27,15 +27,12 @@ #include <linux/mm.h> #include <linux/mutex.h> #include <linux/page-isolation.h> +#include <linux/sizes.h> #include <linux/slab.h> #include <linux/swap.h> #include <linux/mm_types.h> #include <linux/dma-contiguous.h> -#ifndef SZ_1M -#define SZ_1M (1 << 20) -#endif - struct cma { unsigned long base_pfn; unsigned long count; diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 81541452887..8945f4e489e 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -36,68 +36,6 @@ MODULE_AUTHOR("Manuel Estrada Sainz"); MODULE_DESCRIPTION("Multi purpose firmware loading support"); MODULE_LICENSE("GPL"); -static const char *fw_path[] = { - "/lib/firmware/updates/" UTS_RELEASE, - "/lib/firmware/updates", - "/lib/firmware/" UTS_RELEASE, - "/lib/firmware" -}; - -/* Don't inline this: 'struct kstat' is biggish */ -static noinline long fw_file_size(struct file *file) -{ - struct kstat st; - if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) - return -1; - if (!S_ISREG(st.mode)) - return -1; - if (st.size != (long)st.size) - return -1; - return st.size; -} - -static bool fw_read_file_contents(struct file *file, struct firmware *fw) -{ - long size; - char *buf; - - size = fw_file_size(file); - if (size < 0) - return false; - buf = vmalloc(size); - if (!buf) - return false; - if (kernel_read(file, 0, buf, size) != size) { - vfree(buf); - return false; - } - fw->data = buf; - fw->size = size; - return true; -} - -static bool fw_get_filesystem_firmware(struct firmware *fw, const char *name) -{ - int i; - bool success = false; - char *path = __getname(); - - for (i = 0; i < ARRAY_SIZE(fw_path); i++) { - struct file *file; - snprintf(path, PATH_MAX, "%s/%s", fw_path[i], name); - - file = filp_open(path, O_RDONLY, 0); - if (IS_ERR(file)) - continue; - success = fw_read_file_contents(file, fw); - fput(file); - if (success) - break; - } - __putname(path); - return success; -} - /* Builtin firmware support */ #ifdef CONFIG_FW_LOADER @@ -150,6 +88,11 @@ enum { FW_STATUS_ABORT, }; +enum fw_buf_fmt { + VMALLOC_BUF, /* used in direct loading */ + PAGE_BUF, /* used in loading via userspace */ +}; + static int loading_timeout = 60; /* In seconds */ static inline long firmware_loading_timeout(void) @@ -173,8 +116,6 @@ struct firmware_cache { spinlock_t name_lock; struct list_head fw_names; - wait_queue_head_t wait_queue; - int cnt; struct delayed_work work; struct notifier_block pm_notify; @@ -187,6 +128,7 @@ struct firmware_buf { struct completion completion; struct firmware_cache *fwc; unsigned long status; + enum fw_buf_fmt fmt; void *data; size_t size; struct page **pages; @@ -240,6 +182,7 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name, strcpy(buf->fw_id, fw_name); buf->fwc = fwc; init_completion(&buf->completion); + buf->fmt = VMALLOC_BUF; pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf); @@ -307,10 +250,14 @@ static void __fw_free_buf(struct kref *ref) list_del(&buf->list); spin_unlock(&fwc->lock); - vunmap(buf->data); - for (i = 0; i < buf->nr_pages; i++) - __free_page(buf->pages[i]); - kfree(buf->pages); + + if (buf->fmt == PAGE_BUF) { + vunmap(buf->data); + for (i = 0; i < buf->nr_pages; i++) + __free_page(buf->pages[i]); + kfree(buf->pages); + } else + vfree(buf->data); kfree(buf); } @@ -319,6 +266,69 @@ static void fw_free_buf(struct firmware_buf *buf) kref_put(&buf->ref, __fw_free_buf); } +/* direct firmware loading support */ +static const char *fw_path[] = { + "/lib/firmware/updates/" UTS_RELEASE, + "/lib/firmware/updates", + "/lib/firmware/" UTS_RELEASE, + "/lib/firmware" +}; + +/* Don't inline this: 'struct kstat' is biggish */ +static noinline long fw_file_size(struct file *file) +{ + struct kstat st; + if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st)) + return -1; + if (!S_ISREG(st.mode)) + return -1; + if (st.size != (long)st.size) + return -1; + return st.size; +} + +static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) +{ + long size; + char *buf; + + size = fw_file_size(file); + if (size < 0) + return false; + buf = vmalloc(size); + if (!buf) + return false; + if (kernel_read(file, 0, buf, size) != size) { + vfree(buf); + return false; + } + fw_buf->data = buf; + fw_buf->size = size; + return true; +} + +static bool fw_get_filesystem_firmware(struct firmware_buf *buf) +{ + int i; + bool success = false; + char *path = __getname(); + + for (i = 0; i < ARRAY_SIZE(fw_path); i++) { + struct file *file; + snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id); + + file = filp_open(path, O_RDONLY, 0); + if (IS_ERR(file)) + continue; + success = fw_read_file_contents(file, buf); + fput(file); + if (success) + break; + } + __putname(path); + return success; +} + static struct firmware_priv *to_firmware_priv(struct device *dev) { return container_of(dev, struct firmware_priv, dev); @@ -423,6 +433,21 @@ static void firmware_free_data(const struct firmware *fw) #ifndef PAGE_KERNEL_RO #define PAGE_KERNEL_RO PAGE_KERNEL #endif + +/* one pages buffer should be mapped/unmapped only once */ +static int fw_map_pages_buf(struct firmware_buf *buf) +{ + if (buf->fmt != PAGE_BUF) + return 0; + + if (buf->data) + vunmap(buf->data); + buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); + if (!buf->data) + return -ENOMEM; + return 0; +} + /** * firmware_loading_store - set value in the 'loading' control file * @dev: device pointer @@ -467,6 +492,14 @@ static ssize_t firmware_loading_store(struct device *dev, if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) { set_bit(FW_STATUS_DONE, &fw_buf->status); clear_bit(FW_STATUS_LOADING, &fw_buf->status); + + /* + * Several loading requests may be pending on + * one same firmware buf, so let all requests + * see the mapped 'buf->data' once the loading + * is completed. + * */ + fw_map_pages_buf(fw_buf); complete_all(&fw_buf->completion); break; } @@ -670,15 +703,6 @@ exit: return fw_priv; } -/* one pages buffer is mapped/unmapped only once */ -static int fw_map_pages_buf(struct firmware_buf *buf) -{ - buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO); - if (!buf->data) - return -ENOMEM; - return 0; -} - /* store the pages buffer info firmware from buf */ static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw) { @@ -778,11 +802,6 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name, return NULL; } - if (fw_get_filesystem_firmware(firmware, name)) { - dev_dbg(device, "firmware: direct-loading firmware %s\n", name); - return NULL; - } - ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf); if (!ret) fw_priv = fw_create_instance(firmware, name, device, @@ -832,6 +851,21 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, struct device *f_dev = &fw_priv->dev; struct firmware_buf *buf = fw_priv->buf; struct firmware_cache *fwc = &fw_cache; + int direct_load = 0; + + /* try direct loading from fs first */ + if (fw_get_filesystem_firmware(buf)) { + dev_dbg(f_dev->parent, "firmware: direct-loading" + " firmware %s\n", buf->fw_id); + + set_bit(FW_STATUS_DONE, &buf->status); + complete_all(&buf->completion); + direct_load = 1; + goto handle_fw; + } + + /* fall back on userspace loading */ + buf->fmt = PAGE_BUF; dev_set_uevent_suppress(f_dev, true); @@ -870,6 +904,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, del_timer_sync(&fw_priv->timeout); +handle_fw: mutex_lock(&fw_lock); if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status)) retval = -ENOENT; @@ -884,9 +919,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, if (!retval && f_dev->parent) fw_add_devm_name(f_dev->parent, buf->fw_id); - if (!retval) - retval = fw_map_pages_buf(buf); - /* * After caching firmware image is started, let it piggyback * on request firmware. @@ -902,6 +934,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent, fw_priv->buf = NULL; mutex_unlock(&fw_lock); + if (direct_load) + goto err_put_dev; + device_remove_file(f_dev, &dev_attr_loading); err_del_bin_attr: device_remove_bin_file(f_dev, &firmware_attr_data); @@ -1129,6 +1164,8 @@ int uncache_firmware(const char *fw_name) } #ifdef CONFIG_PM_SLEEP +static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain); + static struct fw_cache_entry *alloc_fw_cache_entry(const char *name) { struct fw_cache_entry *fce; @@ -1142,17 +1179,27 @@ exit: return fce; } -static int fw_cache_piggyback_on_request(const char *name) +static int __fw_entry_found(const char *name) { struct firmware_cache *fwc = &fw_cache; struct fw_cache_entry *fce; - int ret = 0; - spin_lock(&fwc->name_lock); list_for_each_entry(fce, &fwc->fw_names, list) { if (!strcmp(fce->name, name)) - goto found; + return 1; } + return 0; +} + +static int fw_cache_piggyback_on_request(const char *name) +{ + struct firmware_cache *fwc = &fw_cache; + struct fw_cache_entry *fce; + int ret = 0; + + spin_lock(&fwc->name_lock); + if (__fw_entry_found(name)) + goto found; fce = alloc_fw_cache_entry(name); if (fce) { @@ -1185,12 +1232,6 @@ static void __async_dev_cache_fw_image(void *fw_entry, free_fw_cache_entry(fce); } - - spin_lock(&fwc->name_lock); - fwc->cnt--; - spin_unlock(&fwc->name_lock); - - wake_up(&fwc->wait_queue); } /* called with dev->devres_lock held */ @@ -1229,11 +1270,19 @@ static void dev_cache_fw_image(struct device *dev, void *data) list_del(&fce->list); spin_lock(&fwc->name_lock); - fwc->cnt++; - list_add(&fce->list, &fwc->fw_names); + /* only one cache entry for one firmware */ + if (!__fw_entry_found(fce->name)) { + list_add(&fce->list, &fwc->fw_names); + } else { + free_fw_cache_entry(fce); + fce = NULL; + } spin_unlock(&fwc->name_lock); - async_schedule(__async_dev_cache_fw_image, (void *)fce); + if (fce) + async_schedule_domain(__async_dev_cache_fw_image, + (void *)fce, + &fw_cache_domain); } } @@ -1275,6 +1324,9 @@ static void device_cache_fw_images(void) pr_debug("%s\n", __func__); + /* cancel uncache work */ + cancel_delayed_work_sync(&fwc->work); + /* * use small loading timeout for caching devices' firmware * because all these firmware images have been loaded @@ -1292,21 +1344,7 @@ static void device_cache_fw_images(void) mutex_unlock(&fw_lock); /* wait for completion of caching firmware for all devices */ - spin_lock(&fwc->name_lock); - for (;;) { - prepare_to_wait(&fwc->wait_queue, &wait, - TASK_UNINTERRUPTIBLE); - if (!fwc->cnt) - break; - - spin_unlock(&fwc->name_lock); - - schedule(); - - spin_lock(&fwc->name_lock); - } - spin_unlock(&fwc->name_lock); - finish_wait(&fwc->wait_queue, &wait); + async_synchronize_full_domain(&fw_cache_domain); loading_timeout = old_timeout; } @@ -1394,9 +1432,7 @@ static void __init fw_cache_init(void) #ifdef CONFIG_PM_SLEEP spin_lock_init(&fw_cache.name_lock); INIT_LIST_HEAD(&fw_cache.fw_names); - fw_cache.cnt = 0; - init_waitqueue_head(&fw_cache.wait_queue); INIT_DELAYED_WORK(&fw_cache.work, device_uncache_fw_images_work); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 8727e9c5eea..72c776f2a1f 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -83,9 +83,16 @@ EXPORT_SYMBOL_GPL(platform_get_resource); */ int platform_get_irq(struct platform_device *dev, unsigned int num) { +#ifdef CONFIG_SPARC + /* sparc does not have irqs represented as IORESOURCE_IRQ resources */ + if (!dev || num >= dev->archdata.num_irqs) + return -ENXIO; + return dev->archdata.irqs[num]; +#else struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); return r ? r->start : -ENXIO; +#endif } EXPORT_SYMBOL_GPL(platform_get_irq); diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index c22b869245d..96b71b6536d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1862,7 +1862,7 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) cpuidle_drv = cpuidle_driver_ref(); if (!cpuidle_drv) { ret = -ENODEV; - goto out; + goto err_drv; } if (cpuidle_drv->state_count <= state) { ret = -EINVAL; @@ -1884,6 +1884,9 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state) err: cpuidle_driver_unref(); + + err_drv: + kfree(cpu_data); goto out; } diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 74a67e0019a..fbbd4ed2edf 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -451,7 +451,7 @@ int dev_pm_qos_add_ancestor_request(struct device *dev, if (ancestor) error = dev_pm_qos_add_request(ancestor, req, value); - if (error) + if (error < 0) req->dev = NULL; return error; diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 6be390bd8bd..f0d30543fcc 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -3,7 +3,7 @@ # subsystems should select the appropriate symbols. config REGMAP - default y if (REGMAP_I2C || REGMAP_SPI) + default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ) select LZO_COMPRESS select LZO_DECOMPRESS select IRQ_DOMAIN if REGMAP_IRQ diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 432aeeedfd5..d865470bc95 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -158,9 +158,10 @@ static int bcma_register_cores(struct bcma_bus *bus) static void bcma_unregister_cores(struct bcma_bus *bus) { - struct bcma_device *core; + struct bcma_device *core, *tmp; - list_for_each_entry(core, &bus->cores, list) { + list_for_each_entry_safe(core, tmp, &bus->cores, list) { + list_del(&core->list); if (core->dev_registered) device_unregister(&core->dev); } diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index f529407db93..824e09c4d0d 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -131,6 +131,7 @@ config BLK_CPQ_DA config BLK_CPQ_CISS_DA tristate "Compaq Smart Array 5xxx support" depends on PCI + select CHECK_SIGNATURE help This is the driver for Compaq Smart Array 5xxx controllers. Everyone using these boards should say Y here. @@ -166,8 +167,8 @@ config BLK_DEV_DAC960 module will be called DAC960. config BLK_DEV_UMEM - tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL + tristate "Micro Memory MM5415 Battery Backed RAM support" + depends on PCI ---help--- Saying Y here will include support for the MM5415 family of battery backed (Non-volatile) RAM cards. @@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS a disc is opened for writing. config CDROM_PKTCDVD_WCACHE - bool "Enable write caching (EXPERIMENTAL)" - depends on CDROM_PKTCDVD && EXPERIMENTAL + bool "Enable write caching" + depends on CDROM_PKTCDVD help If enabled, write caching will be set for the CD-R/W device. For now this option is dangerous unless the CD-RW media is known good, as we @@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND config VIRTIO_BLK - tristate "Virtio block driver (EXPERIMENTAL)" - depends on EXPERIMENTAL && VIRTIO + tristate "Virtio block driver" + depends on VIRTIO ---help--- This is the virtual block driver for virtio. It can be used with lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. @@ -528,7 +529,7 @@ config BLK_DEV_HD config BLK_DEV_RBD tristate "Rados block device (RBD)" - depends on INET && EXPERIMENTAL && BLOCK + depends on INET && BLOCK select CEPH_LIB select LIBCRC32C select CRYPTO_AES diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 3804a0af3ef..9fe4f186555 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -935,7 +935,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) /* cf. http://lkml.org/lkml/2006/10/31/28 */ if (!fastfail) - q->request_fn(q); + __blk_run_queue(q); } static void diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b0f553b26d0..ca83f96756a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev) return; } /* write all data in the battery backed cache to disk */ - memset(flush_buf, 0, 4); return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf, 4, 0, CTLR_LUNID, TYPE_CMD); kfree(flush_buf); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 17c675c5229..2ddd64a9ffd 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = { static struct platform_device floppy_device[N_DRIVE]; +static bool floppy_available(int drive) +{ + if (!(allowed_drive_mask & (1 << drive))) + return false; + if (fdc_state[FDC(drive)].version == FDC_NONE) + return false; + return true; +} + static struct kobject *floppy_find(dev_t dev, int *part, void *data) { int drive = (*part & 3) | ((*part & 0x80) >> 5); - if (drive >= N_DRIVE || - !(allowed_drive_mask & (1 << drive)) || - fdc_state[FDC(drive)].version == FDC_NONE) + if (drive >= N_DRIVE || !floppy_available(drive)) return NULL; if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) return NULL; @@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) static int __init do_floppy_init(void) { - int i, unit, drive; - int err, dr; + int i, unit, drive, err; set_debugt(); interruptjiffies = resultjiffies = jiffies; @@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void) raw_cmd = NULL; - for (dr = 0; dr < N_DRIVE; dr++) { - disks[dr] = alloc_disk(1); - if (!disks[dr]) { - err = -ENOMEM; - goto out_put_disk; - } + floppy_wq = alloc_ordered_workqueue("floppy", 0); + if (!floppy_wq) + return -ENOMEM; - floppy_wq = alloc_ordered_workqueue("floppy", 0); - if (!floppy_wq) { + for (drive = 0; drive < N_DRIVE; drive++) { + disks[drive] = alloc_disk(1); + if (!disks[drive]) { err = -ENOMEM; goto out_put_disk; } - disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); - if (!disks[dr]->queue) { + disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock); + if (!disks[drive]->queue) { err = -ENOMEM; - goto out_destroy_workq; + goto out_put_disk; } - blk_queue_max_hw_sectors(disks[dr]->queue, 64); - disks[dr]->major = FLOPPY_MAJOR; - disks[dr]->first_minor = TOMINOR(dr); - disks[dr]->fops = &floppy_fops; - sprintf(disks[dr]->disk_name, "fd%d", dr); + blk_queue_max_hw_sectors(disks[drive]->queue, 64); + disks[drive]->major = FLOPPY_MAJOR; + disks[drive]->first_minor = TOMINOR(drive); + disks[drive]->fops = &floppy_fops; + sprintf(disks[drive]->disk_name, "fd%d", drive); - init_timer(&motor_off_timer[dr]); - motor_off_timer[dr].data = dr; - motor_off_timer[dr].function = motor_off_callback; + init_timer(&motor_off_timer[drive]); + motor_off_timer[drive].data = drive; + motor_off_timer[drive].function = motor_off_callback; } err = register_blkdev(FLOPPY_MAJOR, "fd"); @@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void) } for (drive = 0; drive < N_DRIVE; drive++) { - if (!(allowed_drive_mask & (1 << drive))) - continue; - if (fdc_state[FDC(drive)].version == FDC_NONE) + if (!floppy_available(drive)) continue; floppy_device[drive].name = floppy_device_name; @@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void) err = platform_device_register(&floppy_device[drive]); if (err) - goto out_release_dma; + goto out_remove_drives; err = device_create_file(&floppy_device[drive].dev, &dev_attr_cmos); @@ -4311,28 +4313,33 @@ static int __init do_floppy_init(void) out_unreg_platform_dev: platform_device_unregister(&floppy_device[drive]); +out_remove_drives: + while (drive--) { + if (floppy_available(drive)) { + del_gendisk(disks[drive]); + device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); + platform_device_unregister(&floppy_device[drive]); + } + } out_release_dma: if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); out_unreg_region: blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); platform_driver_unregister(&floppy_driver); -out_destroy_workq: - destroy_workqueue(floppy_wq); out_unreg_blkdev: unregister_blkdev(FLOPPY_MAJOR, "fd"); out_put_disk: - while (dr--) { - del_timer_sync(&motor_off_timer[dr]); - if (disks[dr]->queue) { - blk_cleanup_queue(disks[dr]->queue); - /* - * put_disk() is not paired with add_disk() and - * will put queue reference one extra time. fix it. - */ - disks[dr]->queue = NULL; + destroy_workqueue(floppy_wq); + for (drive = 0; drive < N_DRIVE; drive++) { + if (!disks[drive]) + break; + if (disks[drive]->queue) { + del_timer_sync(&motor_off_timer[drive]); + blk_cleanup_queue(disks[drive]->queue); + disks[drive]->queue = NULL; } - put_disk(disks[dr]); + put_disk(disks[drive]); } return err; } @@ -4548,11 +4555,12 @@ static void __exit floppy_module_exit(void) unregister_blkdev(FLOPPY_MAJOR, "fd"); platform_driver_unregister(&floppy_driver); + destroy_workqueue(floppy_wq); + for (drive = 0; drive < N_DRIVE; drive++) { del_timer_sync(&motor_off_timer[drive]); - if ((allowed_drive_mask & (1 << drive)) && - fdc_state[FDC(drive)].version != FDC_NONE) { + if (floppy_available(drive)) { del_gendisk(disks[drive]); device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); platform_device_unregister(&floppy_device[drive]); @@ -4572,7 +4580,6 @@ static void __exit floppy_module_exit(void) cancel_delayed_work_sync(&fd_timeout); cancel_delayed_work_sync(&fd_timer); - destroy_workqueue(floppy_wq); if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e9d594fd12c..54046e51160 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo) if (lo->lo_state != Lo_bound) return -ENXIO; - if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */ - return -EBUSY; + /* + * If we've explicitly asked to tear down the loop device, + * and it has an elevated reference count, set it for auto-teardown when + * the last reference goes away. This stops $!~#$@ udev from + * preventing teardown because it decided that it needs to run blkid on + * the loopback device whenever they appear. xfstests is notorious for + * failing tests because blkid via udev races with a losetup + * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d + * command to fail with EBUSY. + */ + if (lo->lo_refcnt > 1) { + lo->lo_flags |= LO_FLAGS_AUTOCLEAR; + mutex_unlock(&lo->lo_ctl_mutex); + return 0; + } if (filp == NULL) return -EINVAL; diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index f946d31d691..9694dd99bbb 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -559,7 +559,7 @@ static void mtip_timeout_function(unsigned long int data) struct mtip_cmd *command; int tag, cmdto_cnt = 0; unsigned int bit, group; - unsigned int num_command_slots = port->dd->slot_groups * 32; + unsigned int num_command_slots; unsigned long to, tagaccum[SLOTBITS_IN_LONGS]; if (unlikely(!port)) @@ -572,6 +572,7 @@ static void mtip_timeout_function(unsigned long int data) } /* clear the tag accumulator */ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); + num_command_slots = port->dd->slot_groups * 32; for (tag = 0; tag < num_command_slots; tag++) { /* @@ -2035,8 +2036,9 @@ static unsigned int implicit_sector(unsigned char command, } return rv; } - -static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) +static void mtip_set_timeout(struct driver_data *dd, + struct host_to_dev_fis *fis, + unsigned int *timeout, u8 erasemode) { switch (fis->command) { case ATA_CMD_DOWNLOAD_MICRO: @@ -2044,7 +2046,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) break; case ATA_CMD_SEC_ERASE_UNIT: case 0xFC: - *timeout = 240000; /* 4 minutes */ + if (erasemode) + *timeout = ((*(dd->port->identify + 90) * 2) * 60000); + else + *timeout = ((*(dd->port->identify + 89) * 2) * 60000); break; case ATA_CMD_STANDBYNOW1: *timeout = 120000; /* 2 minutes */ @@ -2087,6 +2092,7 @@ static int exec_drive_taskfile(struct driver_data *dd, unsigned int transfer_size; unsigned long task_file_data; int intotal = outtotal + req_task->out_size; + int erasemode = 0; taskout = req_task->out_size; taskin = req_task->in_size; @@ -2212,7 +2218,13 @@ static int exec_drive_taskfile(struct driver_data *dd, fis.lba_hi, fis.device); - mtip_set_timeout(&fis, &timeout); + /* check for erase mode support during secure erase.*/ + if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) && outbuf && + (outbuf[0] & MTIP_SEC_ERASE_MODE)) { + erasemode = 1; + } + + mtip_set_timeout(dd, &fis, &timeout, erasemode); /* Determine the correct transfer size.*/ if (force_single_sector) @@ -2428,7 +2440,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, * return value * None */ -static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, +static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector, int nsect, int nents, int tag, void *callback, void *data, int dir) { @@ -2436,6 +2448,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, struct mtip_port *port = dd->port; struct mtip_cmd *command = &port->commands[tag]; int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + u64 start = sector; /* Map the scatter list for DMA access */ nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir); @@ -2454,8 +2467,12 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, fis->opts = 1 << 7; fis->command = (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE); - *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF); - *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF); + fis->lba_low = start & 0xFF; + fis->lba_mid = (start >> 8) & 0xFF; + fis->lba_hi = (start >> 16) & 0xFF; + fis->lba_low_ex = (start >> 24) & 0xFF; + fis->lba_mid_ex = (start >> 32) & 0xFF; + fis->lba_hi_ex = (start >> 40) & 0xFF; fis->device = 1 << 6; fis->features = nsect & 0xFF; fis->features_ex = (nsect >> 8) & 0xFF; diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 18627a1d04c..b1742640556 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -33,6 +33,9 @@ /* offset of Device Control register in PCIe extended capabilites space */ #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48 +/* check for erase mode support during secure erase */ +#define MTIP_SEC_ERASE_MODE 0x2 + /* # of times to retry timed out/failed IOs */ #define MTIP_MAX_RETRIES 2 @@ -152,14 +155,14 @@ enum { MTIP_DDF_REBUILD_FAILED_BIT = 8, }; -__packed struct smart_attr{ +struct smart_attr { u8 attr_id; u16 flags; u8 cur; u8 worst; u32 data; u8 res[3]; -}; +} __packed; /* Register Frame Information Structure (FIS), host to device. */ struct host_to_dev_fis { diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 9ad3b5ec1dc..9a54623e52d 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -158,8 +158,8 @@ struct xen_vbd { struct block_device *bdev; /* Cached size parameter. */ sector_t size; - bool flush_support; - bool discard_secure; + unsigned int flush_support:1; + unsigned int discard_secure:1; }; struct backend_info; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 4f66171c668..f58434c2617 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) { struct xen_blkif *blkif; - blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL); + blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL); if (!blkif) return ERR_PTR(-ENOMEM); - memset(blkif, 0, sizeof(*blkif)); blkif->domid = domid; spin_lock_init(&blkif->blk_ring_lock); atomic_set(&blkif->refcnt, 1); @@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif) } } -void xen_blkif_free(struct xen_blkif *blkif) +static void xen_blkif_free(struct xen_blkif *blkif) { if (!atomic_dec_and_test(&blkif->refcnt)) BUG(); @@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = { VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor); VBD_SHOW(mode, "%s\n", be->mode); -int xenvbd_sysfs_addif(struct xenbus_device *dev) +static int xenvbd_sysfs_addif(struct xenbus_device *dev) { int error; @@ -281,7 +280,7 @@ fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); return error; } -void xenvbd_sysfs_delif(struct xenbus_device *dev) +static void xenvbd_sysfs_delif(struct xenbus_device *dev) { sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group); device_remove_file(&dev->dev, &dev_attr_mode); diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index fc2de5528dc..b00000e8aef 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -67,6 +67,7 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3304) }, { USB_DEVICE(0x0930, 0x0215) }, { USB_DEVICE(0x0489, 0xE03D) }, + { USB_DEVICE(0x0489, 0xE027) }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03F0, 0x311D) }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index debda27df9b..ee82f2fb65f 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -124,6 +124,7 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c index ff63560b846..0c48b0e05ed 100644 --- a/drivers/bus/omap-ocp2scp.c +++ b/drivers/bus/omap-ocp2scp.c @@ -22,6 +22,26 @@ #include <linux/pm_runtime.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_data/omap_ocp2scp.h> + +/** + * _count_resources - count for the number of resources + * @res: struct resource * + * + * Count and return the number of resources populated for the device that is + * connected to ocp2scp. + */ +static unsigned _count_resources(struct resource *res) +{ + int cnt = 0; + + while (res->start != res->end) { + cnt++; + res++; + } + + return cnt; +} static int ocp2scp_remove_devices(struct device *dev, void *c) { @@ -34,20 +54,62 @@ static int ocp2scp_remove_devices(struct device *dev, void *c) static int __devinit omap_ocp2scp_probe(struct platform_device *pdev) { - int ret; - struct device_node *np = pdev->dev.of_node; + int ret; + unsigned res_cnt, i; + struct device_node *np = pdev->dev.of_node; + struct platform_device *pdev_child; + struct omap_ocp2scp_platform_data *pdata = pdev->dev.platform_data; + struct omap_ocp2scp_dev *dev; if (np) { ret = of_platform_populate(np, NULL, NULL, &pdev->dev); if (ret) { - dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n"); + dev_err(&pdev->dev, + "failed to add resources for ocp2scp child\n"); goto err0; } + } else if (pdata) { + for (i = 0, dev = *pdata->devices; i < pdata->dev_cnt; i++, + dev++) { + res_cnt = _count_resources(dev->res); + + pdev_child = platform_device_alloc(dev->drv_name, + PLATFORM_DEVID_AUTO); + if (!pdev_child) { + dev_err(&pdev->dev, + "failed to allocate mem for ocp2scp child\n"); + goto err0; + } + + ret = platform_device_add_resources(pdev_child, + dev->res, res_cnt); + if (ret) { + dev_err(&pdev->dev, + "failed to add resources for ocp2scp child\n"); + goto err1; + } + + pdev_child->dev.parent = &pdev->dev; + + ret = platform_device_add(pdev_child); + if (ret) { + dev_err(&pdev->dev, + "failed to register ocp2scp child device\n"); + goto err1; + } + } + } else { + dev_err(&pdev->dev, "OCP2SCP initialized without plat data\n"); + return -EINVAL; } + pm_runtime_enable(&pdev->dev); return 0; +err1: + platform_device_put(pdev_child); + err0: device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices); diff --git a/drivers/char/Makefile b/drivers/char/Makefile index d0b27a39f1d..7ff1d0d208a 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -52,7 +52,6 @@ obj-$(CONFIG_TELCLOCK) += tlclk.o obj-$(CONFIG_MWAVE) += mwave/ obj-$(CONFIG_AGP) += agp/ obj-$(CONFIG_PCMCIA) += pcmcia/ -obj-$(CONFIG_IPMI_HANDLER) += ipmi/ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o obj-$(CONFIG_TCG_TPM) += tpm/ diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index e01f5eaaec8..38390f7c6ab 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -667,7 +667,7 @@ static int intel_gtt_init(void) gtt_map_size = intel_private.base.gtt_total_entries * 4; intel_private.gtt = NULL; - if (INTEL_GTT_GEN < 6) + if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2) intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr, gtt_map_size); if (intel_private.gtt == NULL) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 2c29942b132..a0c84bb3085 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -1880,7 +1880,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user, struct ipmi_recv_msg *supplied_recv, int priority) { - unsigned char saddr, lun; + unsigned char saddr = 0, lun = 0; int rv; if (!user) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 83f85cf7fb1..32a6c7e256b 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2424,6 +2424,38 @@ static void ipmi_pci_cleanup(struct smi_info *info) pci_disable_device(pdev); } +static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info) +{ + if (info->si_type == SI_KCS) { + unsigned char status; + int regspacing; + + info->io.regsize = DEFAULT_REGSIZE; + info->io.regshift = 0; + info->io_size = 2; + info->handlers = &kcs_smi_handlers; + + /* detect 1, 4, 16byte spacing */ + for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) { + info->io.regspacing = regspacing; + if (info->io_setup(info)) { + dev_err(info->dev, + "Could not setup I/O space\n"); + return DEFAULT_REGSPACING; + } + /* write invalid cmd */ + info->io.outputb(&info->io, 1, 0x10); + /* read status back */ + status = info->io.inputb(&info->io, 1); + info->io_cleanup(info); + if (status) + return regspacing; + regspacing *= 4; + } + } + return DEFAULT_REGSPACING; +} + static int __devinit ipmi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2476,8 +2508,8 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, } info->io.addr_data = pci_resource_start(pdev, 0); - info->io.regspacing = DEFAULT_REGSPACING; - info->io.regsize = DEFAULT_REGSPACING; + info->io.regspacing = ipmi_pci_probe_regspacing(info); + info->io.regsize = DEFAULT_REGSIZE; info->io.regshift = 0; info->irq = pdev->irq; diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 320debbe32f..9b4f0116ff2 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -1456,7 +1456,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int old_camera_power; static int sonypi_suspend(struct device *dev) diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c index ca4a25ed844..e2c17d187d9 100644 --- a/drivers/clk/ux500/u8500_clk.c +++ b/drivers/clk/ux500/u8500_clk.c @@ -40,7 +40,7 @@ void u8500_clk_init(void) CLK_IS_ROOT|CLK_IGNORE_UNUSED, 32768); clk_register_clkdev(clk, "clk32k", NULL); - clk_register_clkdev(clk, NULL, "rtc-pl031"); + clk_register_clkdev(clk, "apb_pclk", "rtc-pl031"); /* PRCMU clocks */ fw_version = prcmu_get_fw_version(); @@ -228,10 +228,17 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE, BIT(2), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1"); + clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE, BIT(3), 0); + clk_register_clkdev(clk, "apb_pclk", "msp0"); + clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0"); + clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE, BIT(4), 0); + clk_register_clkdev(clk, "apb_pclk", "msp1"); + clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1"); clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE, BIT(5), 0); @@ -239,6 +246,7 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE, BIT(6), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2"); clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE, BIT(7), 0); @@ -246,6 +254,7 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE, BIT(8), 0); + clk_register_clkdev(clk, "apb_pclk", "slimbus0"); clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE, BIT(9), 0); @@ -255,11 +264,16 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE, BIT(10), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4"); + clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE, BIT(11), 0); + clk_register_clkdev(clk, "apb_pclk", "msp3"); + clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3"); clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE, BIT(0), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3"); clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE, BIT(1), 0); @@ -279,12 +293,13 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE, BIT(5), 0); + clk_register_clkdev(clk, "apb_pclk", "msp2"); + clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2"); clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE, BIT(6), 0); clk_register_clkdev(clk, "apb_pclk", "sdi1"); - clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE, BIT(7), 0); clk_register_clkdev(clk, "apb_pclk", "sdi3"); @@ -316,10 +331,15 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE, BIT(1), 0); + clk_register_clkdev(clk, "apb_pclk", "ssp0"); + clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE, BIT(2), 0); + clk_register_clkdev(clk, "apb_pclk", "ssp1"); + clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE, BIT(3), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0"); clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE, BIT(4), 0); @@ -401,10 +421,17 @@ void u8500_clk_init(void) clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk", U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.1"); + clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk", U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "msp0"); + clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0"); + clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk", U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "msp1"); + clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1"); clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk", U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE); @@ -412,17 +439,25 @@ void u8500_clk_init(void) clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk", U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.2"); + clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk", - U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE); - /* FIXME: Redefinition of BIT(3). */ + U8500_CLKRST1_BASE, BIT(8), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "slimbus0"); + clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk", U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.4"); + clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk", U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "msp3"); + clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3"); /* Periph2 */ clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk", U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.3"); clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk", U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE); @@ -430,6 +465,8 @@ void u8500_clk_init(void) clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk", U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "msp2"); + clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2"); clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk", U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE); @@ -450,10 +487,15 @@ void u8500_clk_init(void) /* Periph3 */ clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk", U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "ssp0"); + clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk", U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "ssp1"); + clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk", U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.0"); clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk", U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE); diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index b40ee1403be..399831690fe 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -328,6 +328,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, cpufreq_update_policy(cpu); break; case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: cpufreq_stats_free_sysfs(cpu); break; case CPU_DEAD: diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 129e80bfff2..e3ebb4fa2c3 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -5,7 +5,7 @@ * http://www.gnu.org/licenses/gpl.html * * Maintainer: - * Andreas Herrmann <andreas.herrmann3@amd.com> + * Andreas Herrmann <herrmann.der.user@googlemail.com> * * Based on the powernow-k7.c module written by Dave Jones. * (C) 2003 Dave Jones on behalf of SuSE Labs @@ -1052,14 +1052,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, .relation = relation }; - /* - * Must run on @pol->cpu. cpufreq core is responsible for ensuring - * that we're bound to the current CPU and pol->cpu stays online. - */ - if (smp_processor_id() == pol->cpu) - return powernowk8_target_fn(&pta); - else - return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); + return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); } /* Driver entry point to verify the policy and range of frequencies */ diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 677cd6e4e1a..d4c12180c65 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -90,6 +90,17 @@ config DW_DMAC Support the Synopsys DesignWare AHB DMA controller. This can be integrated in chips such as the Atmel AT32ap7000. +config DW_DMAC_BIG_ENDIAN_IO + bool "Use big endian I/O register access" + default y if AVR32 + depends on DW_DMAC + help + Say yes here to use big endian I/O access when reading and writing + to the DMA controller registers. This is needed on some platforms, + like the Atmel AVR32 architecture. + + If unsure, use the default setting. + config AT_HDMAC tristate "Atmel AHB DMA support" depends on ARCH_AT91 diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index ff39fa6cd2b..88965597b7d 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -98,9 +98,17 @@ struct dw_dma_regs { u32 DW_PARAMS; }; +#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO +#define dma_readl_native ioread32be +#define dma_writel_native iowrite32be +#else +#define dma_readl_native readl +#define dma_writel_native writel +#endif + /* To access the registers in early stage of probe */ #define dma_read_byaddr(addr, name) \ - readl((addr) + offsetof(struct dw_dma_regs, name)) + dma_readl_native((addr) + offsetof(struct dw_dma_regs, name)) /* Bitfields in DW_PARAMS */ #define DW_PARAMS_NR_CHAN 8 /* number of channels */ @@ -216,9 +224,9 @@ __dwc_regs(struct dw_dma_chan *dwc) } #define channel_readl(dwc, name) \ - readl(&(__dwc_regs(dwc)->name)) + dma_readl_native(&(__dwc_regs(dwc)->name)) #define channel_writel(dwc, name, val) \ - writel((val), &(__dwc_regs(dwc)->name)) + dma_writel_native((val), &(__dwc_regs(dwc)->name)) static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan) { @@ -246,9 +254,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw) } #define dma_readl(dw, name) \ - readl(&(__dw_regs(dw)->name)) + dma_readl_native(&(__dw_regs(dw)->name)) #define dma_writel(dw, name, val) \ - writel((val), &(__dw_regs(dw)->name)) + dma_writel_native((val), &(__dw_regs(dw)->name)) #define channel_set_bit(dw, reg, mask) \ dma_writel(dw, reg, ((mask) << 8) | (mask)) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index f11b5b2b1a1..7d9554cc497 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -474,8 +474,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) slot = i; break; } - if (slot < 0) + if (slot < 0) { + spin_unlock_irqrestore(&imxdma->lock, flags); return -EBUSY; + } imxdma->slots_2d[slot].xsr = d->x; imxdma->slots_2d[slot].ysr = d->y; diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 64385cde044..d451caace80 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan) sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc, node); /* Move the first queued descriptor to active list */ - list_move_tail(&schan->queued, &schan->active); + list_move_tail(&sdesc->node, &schan->active); /* Start the DMA transfer */ writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 + @@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved( unsigned long iflags; int ret; - if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) { + if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) { ret = -EINVAL; goto err_dir; } diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 5a297a26211..cc8e7c78a23 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) * memory controller and apply to register. Search for the first * bandwidth entry that is greater or equal than the setting requested * and program that. If at last entry, turn off DRAM scrubbing. + * + * If no suitable bandwidth is found, turn off DRAM scrubbing entirely + * by falling back to the last element in scrubrates[]. */ - for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { + for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) { /* * skip scrub rates which aren't recommended * (see F10 BKDG, F3x58) @@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) if (scrubrates[i].bandwidth <= new_bw) break; - - /* - * if no suitable bandwidth found, turn off DRAM scrubbing - * entirely by falling back to the last element in the - * scrubrates array. - */ } scrubval = scrubrates[i].scrubval; diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 8d4804732ba..8c4139647ef 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -33,7 +33,7 @@ * detection. The mods to Rev F required more family * information detection. * - * Changes/Fixes by Borislav Petkov <borislav.petkov@amd.com>: + * Changes/Fixes by Borislav Petkov <bp@alien8.de>: * - misc fixes and code cleanups * * This module is based on the following documents diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c index 6c86f6e5455..351945fa2ec 100644 --- a/drivers/edac/edac_stub.c +++ b/drivers/edac/edac_stub.c @@ -5,7 +5,7 @@ * * 2007 (c) MontaVista Software, Inc. * 2010 (c) Advanced Micro Devices Inc. - * Borislav Petkov <borislav.petkov@amd.com> + * Borislav Petkov <bp@alien8.de> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c index 66b5151c108..2ae78f20cc2 100644 --- a/drivers/edac/mce_amd_inj.c +++ b/drivers/edac/mce_amd_inj.c @@ -6,7 +6,7 @@ * This file may be distributed under the terms of the GNU General Public * License version 2. * - * Copyright (c) 2010: Borislav Petkov <borislav.petkov@amd.com> + * Copyright (c) 2010: Borislav Petkov <bp@alien8.de> * Advanced Micro Devices Inc. */ @@ -168,6 +168,6 @@ module_init(edac_init_mce_inject); module_exit(edac_exit_mce_inject); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>"); +MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>"); MODULE_AUTHOR("AMD Inc."); MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding"); diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c index 725eb5aa8d8..e87196f6d2d 100644 --- a/drivers/extcon/extcon-adc-jack.c +++ b/drivers/extcon/extcon-adc-jack.c @@ -14,6 +14,7 @@ * */ +#include <linux/module.h> #include <linux/slab.h> #include <linux/device.h> #include <linux/platform_device.h> @@ -161,13 +162,12 @@ static int __devinit adc_jack_probe(struct platform_device *pdev) err = request_any_context_irq(data->irq, adc_jack_irq_thread, pdata->irq_flags, pdata->name, data); - if (err) { + if (err < 0) { dev_err(&pdev->dev, "error: irq %d\n", data->irq); - err = -EINVAL; goto err_irq; } - goto out; + return 0; err_irq: extcon_dev_unregister(&data->edev); @@ -196,3 +196,7 @@ static struct platform_driver adc_jack_driver = { }; module_platform_driver(adc_jack_driver); + +MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); +MODULE_DESCRIPTION("ADC Jack extcon driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 946a3188b2b..d398821097f 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -41,7 +41,7 @@ * every single port-type of the following cable names. Please choose cable * names that are actually used in your extcon device. */ -const char *extcon_cable_name[] = { +const char extcon_cable_name[][CABLE_NAME_MAX + 1] = { [EXTCON_USB] = "USB", [EXTCON_USB_HOST] = "USB-Host", [EXTCON_TA] = "TA", @@ -62,8 +62,6 @@ const char *extcon_cable_name[] = { [EXTCON_VIDEO_IN] = "Video-in", [EXTCON_VIDEO_OUT] = "Video-out", [EXTCON_MECHANICAL] = "Mechanical", - - NULL, }; static struct class *extcon_class; @@ -91,17 +89,13 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state) return 0; for (i = 0; edev->mutually_exclusive[i]; i++) { - int count = 0, j; + int weight; u32 correspondants = new_state & edev->mutually_exclusive[i]; - u32 exp = 1; - - for (j = 0; j < 32; j++) { - if (exp & correspondants) - count++; - if (count > 1) - return i + 1; - exp <<= 1; - } + + /* calculate the total number of bits set */ + weight = hweight32(correspondants); + if (weight > 1) + return i + 1; } return 0; @@ -362,7 +356,7 @@ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name) EXPORT_SYMBOL_GPL(extcon_get_cable_state); /** - * extcon_get_cable_state_() - Set the status of a specific cable. + * extcon_set_cable_state_() - Set the status of a specific cable. * @edev: the extcon device that has the cable. * @index: cable index that can be retrieved by extcon_find_cable_index(). * @cable_state: the new cable status. The default semantics is @@ -382,7 +376,7 @@ int extcon_set_cable_state_(struct extcon_dev *edev, EXPORT_SYMBOL_GPL(extcon_set_cable_state_); /** - * extcon_get_cable_state() - Set the status of a specific cable. + * extcon_set_cable_state() - Set the status of a specific cable. * @edev: the extcon device that has the cable. * @cable_name: cable name. * @cable_state: the new cable status. The default semantics is @@ -447,6 +441,8 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val, * extcon device. * @obj: an empty extcon_specific_cable_nb object to be returned. * @extcon_name: the name of extcon device. + * if NULL, extcon_register_interest will register + * every cable with the target cable_name given. * @cable_name: the target cable name. * @nb: the notifier block to get notified. * @@ -466,22 +462,44 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj, const char *extcon_name, const char *cable_name, struct notifier_block *nb) { - if (!obj || !extcon_name || !cable_name || !nb) + if (!obj || !cable_name || !nb) return -EINVAL; - obj->edev = extcon_get_extcon_dev(extcon_name); - if (!obj->edev) - return -ENODEV; + if (extcon_name) { + obj->edev = extcon_get_extcon_dev(extcon_name); + if (!obj->edev) + return -ENODEV; - obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); - if (obj->cable_index < 0) - return -ENODEV; + obj->cable_index = extcon_find_cable_index(obj->edev, cable_name); + if (obj->cable_index < 0) + return -ENODEV; + + obj->user_nb = nb; - obj->user_nb = nb; + obj->internal_nb.notifier_call = _call_per_cable; - obj->internal_nb.notifier_call = _call_per_cable; + return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); + } else { + struct class_dev_iter iter; + struct extcon_dev *extd; + struct device *dev; + + if (!extcon_class) + return -ENODEV; + class_dev_iter_init(&iter, extcon_class, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) { + extd = (struct extcon_dev *)dev_get_drvdata(dev); + + if (extcon_find_cable_index(extd, cable_name) < 0) + continue; + + class_dev_iter_exit(&iter); + return extcon_register_interest(obj, extd->name, + cable_name, nb); + } - return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb); + return -ENODEV; + } } /** @@ -551,43 +569,9 @@ static int create_extcon_class(void) return 0; } -static void extcon_cleanup(struct extcon_dev *edev, bool skip) -{ - mutex_lock(&extcon_dev_list_lock); - list_del(&edev->entry); - mutex_unlock(&extcon_dev_list_lock); - - if (!skip && get_device(edev->dev)) { - int index; - - if (edev->mutually_exclusive && edev->max_supported) { - for (index = 0; edev->mutually_exclusive[index]; - index++) - kfree(edev->d_attrs_muex[index].attr.name); - kfree(edev->d_attrs_muex); - kfree(edev->attrs_muex); - } - - for (index = 0; index < edev->max_supported; index++) - kfree(edev->cables[index].attr_g.name); - - if (edev->max_supported) { - kfree(edev->extcon_dev_type.groups); - kfree(edev->cables); - } - - device_unregister(edev->dev); - put_device(edev->dev); - } - - kfree(edev->dev); -} - static void extcon_dev_release(struct device *dev) { - struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev); - - extcon_cleanup(edev, true); + kfree(dev); } static const char *muex_name = "mutually_exclusive"; @@ -813,7 +797,40 @@ EXPORT_SYMBOL_GPL(extcon_dev_register); */ void extcon_dev_unregister(struct extcon_dev *edev) { - extcon_cleanup(edev, false); + int index; + + mutex_lock(&extcon_dev_list_lock); + list_del(&edev->entry); + mutex_unlock(&extcon_dev_list_lock); + + if (IS_ERR_OR_NULL(get_device(edev->dev))) { + dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n", + dev_name(edev->dev)); + return; + } + + if (edev->mutually_exclusive && edev->max_supported) { + for (index = 0; edev->mutually_exclusive[index]; + index++) + kfree(edev->d_attrs_muex[index].attr.name); + kfree(edev->d_attrs_muex); + kfree(edev->attrs_muex); + } + + for (index = 0; index < edev->max_supported; index++) + kfree(edev->cables[index].attr_g.name); + + if (edev->max_supported) { + kfree(edev->extcon_dev_type.groups); + kfree(edev->cables); + } + +#if defined(CONFIG_ANDROID) + if (switch_class) + class_compat_remove_link(switch_class, edev->dev, NULL); +#endif + device_unregister(edev->dev); + put_device(edev->dev); } EXPORT_SYMBOL_GPL(extcon_dev_unregister); @@ -825,6 +842,9 @@ module_init(extcon_class_init); static void __exit extcon_class_exit(void) { +#if defined(CONFIG_ANDROID) + class_compat_unregister(switch_class); +#endif class_destroy(extcon_class); } module_exit(extcon_class_exit); diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 3cc152e690b..71d3ab7b3d8 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -26,7 +26,6 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <linux/extcon.h> #include <linux/workqueue.h> #include <linux/gpio.h> #include <linux/extcon.h> diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index e21387e2da5..a17d0d91ada 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -239,25 +239,19 @@ const char *max77693_extcon_cable[] = { static int max77693_muic_set_debounce_time(struct max77693_muic_info *info, enum max77693_muic_adc_debounce_time time) { - int ret = 0; - u8 ctrl3; + int ret; switch (time) { case ADC_DEBOUNCE_TIME_5MS: case ADC_DEBOUNCE_TIME_10MS: case ADC_DEBOUNCE_TIME_25MS: case ADC_DEBOUNCE_TIME_38_62MS: - ret = max77693_read_reg(info->max77693->regmap_muic, - MAX77693_MUIC_REG_CTRL3, &ctrl3); - ctrl3 &= ~CONTROL3_ADCDBSET_MASK; - ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT); - - ret = max77693_write_reg(info->max77693->regmap_muic, - MAX77693_MUIC_REG_CTRL3, ctrl3); - if (ret) { + ret = max77693_update_reg(info->max77693->regmap_muic, + MAX77693_MUIC_REG_CTRL3, + time << CONTROL3_ADCDBSET_SHIFT, + CONTROL3_ADCDBSET_MASK); + if (ret) dev_err(info->dev, "failed to set ADC debounce time\n"); - ret = -EINVAL; - } break; default: dev_err(info->dev, "invalid ADC debounce time\n"); @@ -657,6 +651,8 @@ out: static int __devinit max77693_muic_probe(struct platform_device *pdev) { struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent); + struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); + struct max77693_muic_platform_data *muic_pdata = pdata->muic_data; struct max77693_muic_info *info; int ret, i; u8 id; @@ -727,6 +723,31 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev) goto err_extcon; } + /* Initialize MUIC register by using platform data */ + for (i = 0 ; i < muic_pdata->num_init_data ; i++) { + enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR; + + max77693_write_reg(info->max77693->regmap_muic, + muic_pdata->init_data[i].addr, + muic_pdata->init_data[i].data); + + switch (muic_pdata->init_data[i].addr) { + case MAX77693_MUIC_REG_INTMASK1: + irq_src = MUIC_INT1; + break; + case MAX77693_MUIC_REG_INTMASK2: + irq_src = MUIC_INT2; + break; + case MAX77693_MUIC_REG_INTMASK3: + irq_src = MUIC_INT3; + break; + } + + if (irq_src < MAX77693_IRQ_GROUP_NR) + info->max77693->irq_masks_cur[irq_src] + = muic_pdata->init_data[i].data; + } + /* Check revision number of MUIC device*/ ret = max77693_read_reg(info->max77693->regmap_muic, MAX77693_MUIC_REG_ID, &id); @@ -762,6 +783,7 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev) free_irq(muic_irqs[i].virq, info); cancel_work_sync(&info->irq_work); extcon_dev_unregister(info->edev); + kfree(info->edev); kfree(info); return 0; diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index ef9090a4271..77b66b0cc8f 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -271,8 +271,6 @@ out: static int max8997_muic_handle_charger_type_detach( struct max8997_muic_info *info) { - int ret = 0; - switch (info->pre_charger_type) { case MAX8997_CHARGER_TYPE_USB: extcon_set_cable_state(info->edev, "USB", false); @@ -290,11 +288,11 @@ static int max8997_muic_handle_charger_type_detach( extcon_set_cable_state(info->edev, "Fast-charger", false); break; default: - ret = -EINVAL; + return -EINVAL; break; } - return ret; + return 0; } static int max8997_muic_handle_charger_type(struct max8997_muic_info *info, diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 1162d6b3bf8..bb1b392f5cd 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -1546,6 +1546,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) struct sbp2_logical_unit *lu = sdev->hostdata; sdev->use_10_for_rw = 1; + sdev->no_report_opcodes = 1; + sdev->no_write_same = 1; if (sbp2_param_exclusive_login) sdev->manage_start_stop = 1; diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c index c1cdc923666..90723e65b08 100644 --- a/drivers/firmware/memmap.c +++ b/drivers/firmware/memmap.c @@ -237,7 +237,7 @@ static ssize_t memmap_attr_show(struct kobject *kobj, * firmware_map_add() or firmware_map_add_early() afterwards, the entries * are not added to sysfs. */ -static int __init memmap_init(void) +static int __init firmware_memmap_init(void) { struct firmware_map_entry *entry; @@ -246,5 +246,5 @@ static int __init memmap_init(void) return 0; } -late_initcall(memmap_init); +late_initcall(firmware_memmap_init); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d055cee3694..47150f5ded0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -47,7 +47,7 @@ if GPIOLIB config OF_GPIO def_bool y - depends on OF && !SPARC + depends on OF config DEBUG_GPIO bool "Debug GPIO calls" @@ -466,7 +466,7 @@ config GPIO_ADP5588_IRQ config GPIO_ADNP tristate "Avionic Design N-bit GPIO expander" - depends on I2C && OF + depends on I2C && OF_GPIO help This option enables support for N GPIOs found on Avionic Design I2C GPIO expanders. The register space will be extended by powers diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index ed3e55161bd..f05e54258ff 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi) } chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers; - chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL); + chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL); if (!chip->buffer) { ret = -ENOMEM; goto exit_destroy; diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 0f425189de1..ce1c8476007 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -77,7 +77,7 @@ struct mcp23s08_driver_data { /*----------------------------------------------------------------------*/ -#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg) { @@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, break; #endif /* CONFIG_SPI_MASTER */ -#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) case MCP_TYPE_008: mcp->ops = &mcp23008_ops; mcp->chip.ngpio = 8; @@ -473,7 +473,7 @@ fail: /*----------------------------------------------------------------------*/ -#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) static int __devinit mcp230xx_probe(struct i2c_client *client, const struct i2c_device_id *id) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 902af437eaf..be65c0451ad 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip) return mvchip->membase + GPIO_OUT_OFF; } +static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) +{ + return mvchip->membase + GPIO_BLINK_EN_OFF; +} + static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) { return mvchip->membase + GPIO_IO_CONF_OFF; @@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin) return (u >> pin) & 1; } +static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value) +{ + struct mvebu_gpio_chip *mvchip = + container_of(chip, struct mvebu_gpio_chip, chip); + unsigned long flags; + u32 u; + + spin_lock_irqsave(&mvchip->lock, flags); + u = readl_relaxed(mvebu_gpioreg_blink(mvchip)); + if (value) + u |= 1 << pin; + else + u &= ~(1 << pin); + writel_relaxed(u, mvebu_gpioreg_blink(mvchip)); + spin_unlock_irqrestore(&mvchip->lock, flags); +} + static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin) { struct mvebu_gpio_chip *mvchip = @@ -244,6 +266,9 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, if (ret) return ret; + mvebu_gpio_blink(chip, pin, 0); + mvebu_gpio_set(chip, pin, value); + spin_lock_irqsave(&mvchip->lock, flags); u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); u &= ~(1 << pin); @@ -381,11 +406,13 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); u &= ~(1 << pin); writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); + break; case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_LEVEL_LOW: u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); u |= 1 << pin; writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); + break; case IRQ_TYPE_EDGE_BOTH: { u32 v; @@ -401,6 +428,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) else u &= ~(1 << pin); /* rising */ writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); + break; } } return 0; @@ -641,7 +669,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev) ct->handler = handle_edge_irq; ct->chip.name = mvchip->chip.label; - irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE, + irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0, IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); /* Setup irq domain on top of the generic chip. */ diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 94cbc842fbc..d335af1d4d8 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, } } +/** + * _clear_gpio_debounce - clear debounce settings for a gpio + * @bank: the gpio bank we're acting upon + * @gpio: the gpio number on this @gpio + * + * If a gpio is using debounce, then clear the debounce enable bit and if + * this is the only gpio in this bank using debounce, then clear the debounce + * time too. The debounce clock will also be disabled when calling this function + * if this is the only gpio in the bank using debounce. + */ +static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio) +{ + u32 gpio_bit = GPIO_BIT(bank, gpio); + + if (!bank->dbck_flag) + return; + + if (!(bank->dbck_enable_mask & gpio_bit)) + return; + + bank->dbck_enable_mask &= ~gpio_bit; + bank->context.debounce_en &= ~gpio_bit; + __raw_writel(bank->context.debounce_en, + bank->base + bank->regs->debounce_en); + + if (!bank->dbck_enable_mask) { + bank->context.debounce = 0; + __raw_writel(bank->context.debounce, bank->base + + bank->regs->debounce); + clk_disable(bank->dbck); + bank->dbck_enabled = false; + } +} + static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, unsigned trigger) { @@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio) _set_gpio_irqenable(bank, gpio, 0); _clear_gpio_irqstatus(bank, gpio); _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); + _clear_gpio_debounce(bank, gpio); } /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 031c6adf5b6..1a3e2b9b477 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier &= ~(1 << offset); + tgpio->last_ier &= ~(1UL << offset); iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } @@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier |= 1 << offset; + tgpio->last_ier |= 1UL << offset; iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5d6c71edc73..1c8d9e3380e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class, */ status = gpio_request(gpio, "sysfs"); - if (status < 0) + if (status < 0) { + if (status == -EPROBE_DEFER) + status = -ENODEV; goto done; - + } status = gpio_export(gpio, true); if (status < 0) gpio_free(gpio); @@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label) spin_lock_irqsave(&gpio_lock, flags); - if (!gpio_is_valid(gpio)) + if (!gpio_is_valid(gpio)) { + status = -EINVAL; goto done; + } desc = &gpio_desc[gpio]; chip = desc->chip; if (chip == NULL) diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 09e11a5d921..fd9d0af4d53 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -206,7 +206,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, size_t size; int ret; - DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n", + DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n", sizes->surface_width, sizes->surface_height, sizes->surface_bpp); @@ -220,7 +220,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, size = mode_cmd.pitches[0] * mode_cmd.height; obj = drm_gem_cma_create(dev, size); - if (!obj) + if (IS_ERR(obj)) return -ENOMEM; fbi = framebuffer_alloc(0, dev->dev); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 7ef1b673e1b..133b4132983 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp) int minor_id = iminor(inode); struct drm_minor *minor; int retcode = 0; + int need_setup = 0; + struct address_space *old_mapping; minor = idr_find(&drm_minors_idr, minor_id); if (!minor) @@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp) if (drm_device_is_unplugged(dev)) return -ENODEV; + if (!dev->open_count++) + need_setup = 1; + mutex_lock(&dev->struct_mutex); + old_mapping = dev->dev_mapping; + if (old_mapping == NULL) + dev->dev_mapping = &inode->i_data; + /* ihold ensures nobody can remove inode with our i_data */ + ihold(container_of(dev->dev_mapping, struct inode, i_data)); + inode->i_mapping = dev->dev_mapping; + filp->f_mapping = dev->dev_mapping; + mutex_unlock(&dev->struct_mutex); + retcode = drm_open_helper(inode, filp, dev); - if (!retcode) { - atomic_inc(&dev->counts[_DRM_STAT_OPENS]); - if (!dev->open_count++) - retcode = drm_setup(dev); - } - if (!retcode) { - mutex_lock(&dev->struct_mutex); - if (dev->dev_mapping == NULL) - dev->dev_mapping = &inode->i_data; - /* ihold ensures nobody can remove inode with our i_data */ - ihold(container_of(dev->dev_mapping, struct inode, i_data)); - inode->i_mapping = dev->dev_mapping; - filp->f_mapping = dev->dev_mapping; - mutex_unlock(&dev->struct_mutex); + if (retcode) + goto err_undo; + atomic_inc(&dev->counts[_DRM_STAT_OPENS]); + if (need_setup) { + retcode = drm_setup(dev); + if (retcode) + goto err_undo; } + return 0; +err_undo: + mutex_lock(&dev->struct_mutex); + filp->f_mapping = old_mapping; + inode->i_mapping = old_mapping; + iput(container_of(dev->dev_mapping, struct inode, i_data)); + dev->dev_mapping = old_mapping; + mutex_unlock(&dev->struct_mutex); + dev->open_count--; return retcode; } EXPORT_SYMBOL(drm_open); diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index cdf8b1e7602..d4b20ceda3f 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -205,8 +205,6 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data) struct drm_gem_object *obj = ptr; struct seq_file *m = data; - seq_printf(m, "name %d size %zd\n", obj->name, obj->size); - seq_printf(m, "%6d %8zd %7d %8d\n", obj->name, obj->size, atomic_read(&obj->handle_count), @@ -239,7 +237,7 @@ int drm_vma_info(struct seq_file *m, void *data) mutex_lock(&dev->struct_mutex); seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n", atomic_read(&dev->vma_count), - high_memory, (void *)virt_to_phys(high_memory)); + high_memory, (void *)(unsigned long)virt_to_phys(high_memory)); list_for_each_entry(pt, &dev->vmalist, head) { vma = pt->vma; diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index aaeb6f8d69c..b8a282ea875 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c @@ -64,7 +64,6 @@ int drm_get_platform_dev(struct platform_device *platdev, } if (drm_core_check_feature(dev, DRIVER_MODESET)) { - dev_set_drvdata(&platdev->dev, dev); ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); if (ret) goto err_g1; diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 59a26e577b5..fc345d4ebb0 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -1,6 +1,6 @@ config DRM_EXYNOS tristate "DRM Support for Samsung SoC EXYNOS Series" - depends on DRM && PLAT_SAMSUNG + depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM) select DRM_KMS_HELPER select FB_CFB_FILLRECT select FB_CFB_COPYAREA diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 18c271862ca..0f68a287267 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, exynos_connector->encoder_id = encoder->base.id; exynos_connector->manager = manager; exynos_connector->dpms = DRM_MODE_DPMS_OFF; + connector->dpms = DRM_MODE_DPMS_OFF; connector->encoder = encoder; err = drm_mode_connector_attach_encoder(connector, encoder); diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index e51503fbaf2..241ad1eeec6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -43,12 +43,14 @@ * @manager: specific encoder has its own manager to control a hardware * appropriately and we can access a hardware drawing on this manager. * @dpms: store the encoder dpms value. + * @updated: indicate whether overlay data updating is needed or not. */ struct exynos_drm_encoder { struct drm_crtc *old_crtc; struct drm_encoder drm_encoder; struct exynos_drm_manager *manager; - int dpms; + int dpms; + bool updated; }; static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode) @@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) switch (mode) { case DRM_MODE_DPMS_ON: if (manager_ops && manager_ops->apply) - manager_ops->apply(manager->dev); + if (!exynos_encoder->updated) + manager_ops->apply(manager->dev); + exynos_drm_connector_power(encoder, mode); exynos_encoder->dpms = mode; break; @@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_OFF: exynos_drm_connector_power(encoder, mode); exynos_encoder->dpms = mode; + exynos_encoder->updated = false; break; default: DRM_ERROR("unspecified mode %d\n", mode); @@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder) static void exynos_drm_encoder_commit(struct drm_encoder *encoder) { - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); + struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); + struct exynos_drm_manager *manager = exynos_encoder->manager; struct exynos_drm_manager_ops *manager_ops = manager->ops; DRM_DEBUG_KMS("%s\n", __FILE__); if (manager_ops && manager_ops->commit) manager_ops->commit(manager->dev); + + /* + * this will avoid one issue that overlay data is updated to + * real hardware two times. + * And this variable will be used to check if the data was + * already updated or not by exynos_drm_encoder_dpms function. + */ + exynos_encoder->updated = true; } static void exynos_drm_encoder_disable(struct drm_encoder *encoder) @@ -401,19 +415,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data) manager_ops->dpms(manager->dev, mode); /* - * set current mode to new one so that data aren't updated into - * registers by drm_helper_connector_dpms two times. - * - * in case that drm_crtc_helper_set_mode() is called, - * overlay_ops->commit() and manager_ops->commit() callbacks - * can be called two times, first at drm_crtc_helper_set_mode() - * and second at drm_helper_connector_dpms(). - * so with this setting, when drm_helper_connector_dpms() is called - * encoder->funcs->dpms() will be ignored. - */ - exynos_encoder->dpms = mode; - - /* * if this condition is ok then it means that the crtc is already * detached from encoder and last function for detaching is properly * done, so clear pipe from manager to prevent repeated call. diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 614b2e9ac46..e7fbb823fd8 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev) const struct of_device_id *match; match = of_match_node(of_match_ptr(mixer_match_types), pdev->dev.of_node); - drv = match->data; + drv = (struct mixer_drv_data *)match->data; } else { drv = (struct mixer_drv_data *) platform_get_device_id(pdev)->driver_data; diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index 38f3a6cb8c7..3edd981e077 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c @@ -303,10 +303,10 @@ static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo) ch7xxx_readb(dvo, CH7xxx_PM, &val); - if (val & CH7xxx_PM_FPD) - return false; - else + if (val & (CH7xxx_PM_DVIL | CH7xxx_PM_DVIP)) return true; + else + return false; } static void ch7xxx_dump_regs(struct intel_dvo_device *dvo) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c9bfd83dde6..61ae104dca8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto put_gmch; } - i915_kick_out_firmware_fb(dev_priv); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + i915_kick_out_firmware_fb(dev_priv); pci_set_master(dev->pdev); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index aac4e5e1a5b..6770ee6084b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -118,6 +118,13 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600); MODULE_PARM_DESC(i915_enable_ppgtt, "Enable PPGTT (default: true)"); +unsigned int i915_preliminary_hw_support __read_mostly = 0; +module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600); +MODULE_PARM_DESC(preliminary_hw_support, + "Enable preliminary hardware support. " + "Enable Haswell and ValleyView Support. " + "(default: false)"); + static struct drm_driver driver; extern int intel_agp_enabled; @@ -826,6 +833,12 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct intel_device_info *intel_info = (struct intel_device_info *) ent->driver_data; + if (intel_info->is_haswell || intel_info->is_valleyview) + if(!i915_preliminary_hw_support) { + DRM_ERROR("Preliminary hardware support disabled\n"); + return -ENODEV; + } + /* Only bind to function 0 of the device. Early generations * used function 1 as a placeholder for multi-head. This causes * us confusion instead, especially on the systems where both diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4f2831aa5fe..f511fa2f416 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1217,6 +1217,7 @@ extern int i915_enable_rc6 __read_mostly; extern int i915_enable_fbc __read_mostly; extern bool i915_enable_hangcheck __read_mostly; extern int i915_enable_ppgtt __read_mostly; +extern unsigned int i915_preliminary_hw_support __read_mostly; extern int i915_suspend(struct drm_device *dev, pm_message_t state); extern int i915_resume(struct drm_device *dev); @@ -1341,9 +1342,14 @@ int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj); static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n) { struct scatterlist *sg = obj->pages->sgl; - while (n >= SG_MAX_SINGLE_ALLOC) { + int nents = obj->pages->nents; + while (nents > SG_MAX_SINGLE_ALLOC) { + if (n < SG_MAX_SINGLE_ALLOC - 1) + break; + sg = sg_chain_ptr(sg + SG_MAX_SINGLE_ALLOC - 1); n -= SG_MAX_SINGLE_ALLOC - 1; + nents -= SG_MAX_SINGLE_ALLOC - 1; } return sg_page(sg+n); } @@ -1427,7 +1433,7 @@ int __must_check i915_gpu_idle(struct drm_device *dev); int __must_check i915_gem_idle(struct drm_device *dev); int i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file, - struct drm_i915_gem_request *request); + u32 *seqno); int __must_check i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 19dbdd7dd56..107f09befe9 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1407,8 +1407,10 @@ out: return VM_FAULT_NOPAGE; case -ENOMEM: return VM_FAULT_OOM; + case -ENOSPC: + return VM_FAULT_SIGBUS; default: - WARN_ON_ONCE(ret); + WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret); return VM_FAULT_SIGBUS; } } @@ -1822,10 +1824,11 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) sg_set_page(sg, page, PAGE_SIZE, 0); } + obj->pages = st; + if (i915_gem_object_needs_bit17_swizzle(obj)) i915_gem_object_do_bit_17_swizzle(obj); - obj->pages = st; return 0; err_pages: @@ -1955,11 +1958,12 @@ i915_gem_next_request_seqno(struct intel_ring_buffer *ring) int i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file, - struct drm_i915_gem_request *request) + u32 *out_seqno) { drm_i915_private_t *dev_priv = ring->dev->dev_private; - uint32_t seqno; + struct drm_i915_gem_request *request; u32 request_ring_position; + u32 seqno; int was_empty; int ret; @@ -1974,11 +1978,9 @@ i915_add_request(struct intel_ring_buffer *ring, if (ret) return ret; - if (request == NULL) { - request = kmalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - } + request = kmalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; seqno = i915_gem_next_request_seqno(ring); @@ -2030,6 +2032,8 @@ i915_add_request(struct intel_ring_buffer *ring, } } + if (out_seqno) + *out_seqno = seqno; return 0; } @@ -3959,6 +3963,9 @@ i915_gem_init_hw(struct drm_device *dev) if (!intel_enable_gtt()) return -EIO; + if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1)) + I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000); + i915_gem_l3_remap(dev); i915_gem_init_swizzling(dev); @@ -4098,7 +4105,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, } BUG_ON(!list_empty(&dev_priv->mm.active_list)); - BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); mutex_unlock(&dev->struct_mutex); ret = drm_irq_install(dev); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 64c1be0a9cf..a4162ddff6c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -521,7 +521,7 @@ */ # define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14) #define _3D_CHICKEN3 0x02090 -#define _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL (1 << 5) +#define _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL (1 << 5) #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 893f30164b7..6345878ae1e 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -143,7 +143,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) int old_dpms; /* PCH platforms and VLV only support on/off. */ - if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON) + if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) @@ -219,20 +219,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, intel_encoder_to_crt(to_intel_encoder(encoder)); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_i915_private *dev_priv = dev->dev_private; - int dpll_md_reg; - u32 adpa, dpll_md; - - dpll_md_reg = DPLL_MD(intel_crtc->pipe); - - /* - * Disable separate mode multiplier used when cloning SDVO to CRT - * XXX this needs to be adjusted when we really are cloning - */ - if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { - dpll_md = I915_READ(dpll_md_reg); - I915_WRITE(dpll_md_reg, - dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); - } + u32 adpa; adpa = ADPA_HOTPLUG_BITS; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -742,7 +729,7 @@ void intel_crt_init(struct drm_device *dev) crt->base.type = INTEL_OUTPUT_ANALOG; crt->base.cloneable = true; - if (IS_HASWELL(dev)) + if (IS_HASWELL(dev) || IS_I830(dev)) crt->base.crtc_mask = (1 << 0); else crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2b6ce9b2674..4154bcd7a07 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3253,6 +3253,16 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) if (HAS_PCH_CPT(dev)) intel_cpt_verify_modeset(dev, intel_crtc->pipe); + + /* + * There seems to be a race in PCH platform hw (at least on some + * outputs) where an enabled pipe still completes any pageflip right + * away (as if the pipe is off) instead of waiting for vblank. As soon + * as the first vblank happend, everything works as expected. Hence just + * wait for one vblank before returning to avoid strange things + * happening. + */ + intel_wait_for_vblank(dev, intel_crtc->pipe); } static void ironlake_crtc_disable(struct drm_crtc *crtc) @@ -3831,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, } } + 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; + } + /* * HDMI is either 12 or 8, so if the display lets 10bpc sneak * through, clamp it down. (Note: >12bpc will be caught below.) @@ -7882,6 +7903,34 @@ struct intel_quirk { void (*hook)(struct drm_device *dev); }; +/* For systems that don't have a meaningful PCI subdevice/subvendor ID */ +struct intel_dmi_quirk { + void (*hook)(struct drm_device *dev); + const struct dmi_system_id (*dmi_id_list)[]; +}; + +static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) +{ + DRM_INFO("Backlight polarity reversed on %s\n", id->ident); + return 1; +} + +static const struct intel_dmi_quirk intel_dmi_quirks[] = { + { + .dmi_id_list = &(const struct dmi_system_id[]) { + { + .callback = intel_dmi_reverse_brightness, + .ident = "NCR Corporation", + .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, ""), + }, + }, + { } /* terminating entry */ + }, + .hook = quirk_invert_brightness, + }, +}; + static struct intel_quirk intel_quirks[] = { /* HP Mini needs pipe A force quirk (LP: #322104) */ { 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, @@ -7892,8 +7941,7 @@ static struct intel_quirk intel_quirks[] = { /* ThinkPad T60 needs pipe A force quirk (bug #16494) */ { 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, - /* 855 & before need to leave pipe A & dpll A up */ - { 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, + /* 830/845 need to leave pipe A & dpll A up */ { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, @@ -7922,6 +7970,10 @@ static void intel_init_quirks(struct drm_device *dev) q->subsystem_device == PCI_ANY_ID)) q->hook(dev); } + for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) { + if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0) + intel_dmi_quirks[i].hook(dev); + } } /* Disable the VGA plane that we never use */ @@ -8049,29 +8101,42 @@ static void intel_enable_pipe_a(struct drm_device *dev) } +static bool +intel_check_plane_mapping(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + u32 reg, val; + + if (dev_priv->num_pipe == 1) + return true; + + reg = DSPCNTR(!crtc->plane); + val = I915_READ(reg); + + if ((val & DISPLAY_PLANE_ENABLE) && + (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) + return false; + + return true; +} + static void intel_sanitize_crtc(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 reg, val; + u32 reg; /* Clear any frame start delays used for debugging left by the BIOS */ reg = PIPECONF(crtc->pipe); I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); /* We need to sanitize the plane -> pipe mapping first because this will - * disable the crtc (and hence change the state) if it is wrong. */ - if (!HAS_PCH_SPLIT(dev)) { + * disable the crtc (and hence change the state) if it is wrong. Note + * that gen4+ has a fixed plane -> pipe mapping. */ + if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) { struct intel_connector *connector; bool plane; - reg = DSPCNTR(crtc->plane); - val = I915_READ(reg); - - if ((val & DISPLAY_PLANE_ENABLE) == 0 && - (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) - goto ok; - DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n", crtc->base.base.id); @@ -8095,7 +8160,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) WARN_ON(crtc->active); crtc->base.enabled = false; } -ok: if (dev_priv->quirks & QUIRK_PIPEA_FORCE && crtc->pipe == PIPE_A && !crtc->active) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d1e8ddb2d6c..368ed8ef160 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1797,7 +1797,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) break; if (i == intel_dp->lane_count && voltage_tries == 5) { - if (++loop_tries == 5) { + ++loop_tries; + if (loop_tries == 5) { DRM_DEBUG_KMS("too many full retries, give up\n"); break; } @@ -1807,11 +1808,15 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) } /* Check to see if we've tried the same voltage 5 times */ - if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { - voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; - voltage_tries = 0; - } else + if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { ++voltage_tries; + if (voltage_tries == 5) { + DRM_DEBUG_KMS("too many voltage retries, give up\n"); + break; + } + } else + voltage_tries = 0; + voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; /* Compute new intel_dp->train_set as requested by target */ intel_get_adjust_train(intel_dp, link_status); @@ -2369,8 +2374,9 @@ static void intel_dp_destroy(struct drm_connector *connector) { struct drm_device *dev = connector->dev; + struct intel_dp *intel_dp = intel_attached_dp(connector); - if (intel_dpd_is_edp(dev)) + if (is_edp(intel_dp)) intel_panel_destroy_backlight(dev); drm_sysfs_connector_remove(connector); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index e3166df55da..edba93b3474 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -777,6 +777,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "D525TUD"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Supermicro X7SPA-H", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), + DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"), + }, + }, { } /* terminating entry */ }; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index ebff850a9ab..d7bc817f51a 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -209,7 +209,6 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay, } static int intel_overlay_do_wait_request(struct intel_overlay *overlay, - struct drm_i915_gem_request *request, void (*tail)(struct intel_overlay *)) { struct drm_device *dev = overlay->dev; @@ -218,12 +217,10 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, int ret; BUG_ON(overlay->last_flip_req); - ret = i915_add_request(ring, NULL, request); - if (ret) { - kfree(request); - return ret; - } - overlay->last_flip_req = request->seqno; + ret = i915_add_request(ring, NULL, &overlay->last_flip_req); + if (ret) + return ret; + overlay->flip_tail = tail; ret = i915_wait_seqno(ring, overlay->last_flip_req); if (ret) @@ -240,7 +237,6 @@ static int intel_overlay_on(struct intel_overlay *overlay) struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; - struct drm_i915_gem_request *request; int ret; BUG_ON(overlay->active); @@ -248,17 +244,9 @@ static int intel_overlay_on(struct intel_overlay *overlay) WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) { - ret = -ENOMEM; - goto out; - } - ret = intel_ring_begin(ring, 4); - if (ret) { - kfree(request); - goto out; - } + if (ret) + return ret; intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON); intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE); @@ -266,9 +254,7 @@ static int intel_overlay_on(struct intel_overlay *overlay) intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); - ret = intel_overlay_do_wait_request(overlay, request, NULL); -out: - return ret; + return intel_overlay_do_wait_request(overlay, NULL); } /* overlay needs to be enabled in OCMD reg */ @@ -278,17 +264,12 @@ static int intel_overlay_continue(struct intel_overlay *overlay, struct drm_device *dev = overlay->dev; drm_i915_private_t *dev_priv = dev->dev_private; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; - struct drm_i915_gem_request *request; u32 flip_addr = overlay->flip_addr; u32 tmp; int ret; BUG_ON(!overlay->active); - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - if (load_polyphase_filter) flip_addr |= OFC_UPDATE; @@ -298,22 +279,14 @@ static int intel_overlay_continue(struct intel_overlay *overlay, DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); ret = intel_ring_begin(ring, 2); - if (ret) { - kfree(request); + if (ret) return ret; - } + intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); intel_ring_emit(ring, flip_addr); intel_ring_advance(ring); - ret = i915_add_request(ring, NULL, request); - if (ret) { - kfree(request); - return ret; - } - - overlay->last_flip_req = request->seqno; - return 0; + return i915_add_request(ring, NULL, &overlay->last_flip_req); } static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) @@ -349,15 +322,10 @@ static int intel_overlay_off(struct intel_overlay *overlay) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; u32 flip_addr = overlay->flip_addr; - struct drm_i915_gem_request *request; int ret; BUG_ON(!overlay->active); - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - /* According to intel docs the overlay hw may hang (when switching * off) without loading the filter coeffs. It is however unclear whether * this applies to the disabling of the overlay or to the switching off @@ -365,22 +333,28 @@ static int intel_overlay_off(struct intel_overlay *overlay) flip_addr |= OFC_UPDATE; ret = intel_ring_begin(ring, 6); - if (ret) { - kfree(request); + if (ret) return ret; - } + /* wait for overlay to go idle */ intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); intel_ring_emit(ring, flip_addr); intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); /* turn overlay off */ - intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); - intel_ring_emit(ring, flip_addr); - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + if (IS_I830(dev)) { + /* Workaround: Don't disable the overlay fully, since otherwise + * it dies on the next OVERLAY_ON cmd. */ + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_NOOP); + } else { + intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); + intel_ring_emit(ring, flip_addr); + intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + } intel_ring_advance(ring); - return intel_overlay_do_wait_request(overlay, request, - intel_overlay_off_tail); + return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); } /* recover from an interruption due to a signal @@ -425,24 +399,16 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) return 0; if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { - struct drm_i915_gem_request *request; - /* synchronous slowpath */ - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return -ENOMEM; - ret = intel_ring_begin(ring, 2); - if (ret) { - kfree(request); + if (ret) return ret; - } intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); intel_ring_emit(ring, MI_NOOP); intel_ring_advance(ring); - ret = intel_overlay_do_wait_request(overlay, request, + ret = intel_overlay_do_wait_request(overlay, intel_overlay_release_old_vid_tail); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e019b236986..e2aacd32954 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev) props.type = BACKLIGHT_RAW; props.max_brightness = _intel_panel_get_max_backlight(dev); if (props.max_brightness == 0) { - DRM_ERROR("Failed to get maximum backlight value\n"); + DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n"); return -ENODEV; } dev_priv->backlight = diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b3b4b6cea8b..72f41aaa71f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3442,8 +3442,8 @@ static void gen6_init_clock_gating(struct drm_device *dev) GEN6_RCCUNIT_CLOCK_GATE_DISABLE); /* Bspec says we need to always set all mask bits. */ - I915_WRITE(_3D_CHICKEN, (0xFFFF << 16) | - _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL); + I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) | + _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL); /* * According to the spec the following bits should be diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 0007a4d9bf6..c600fb06e25 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -139,6 +139,11 @@ struct intel_sdvo { /* DDC bus used by this SDVO encoder */ uint8_t ddc_bus; + + /* + * the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd + */ + uint8_t dtd_sdvo_flags; }; struct intel_sdvo_connector { @@ -889,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) } #endif +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, + unsigned if_index, uint8_t tx_rate, + uint8_t *data, unsigned length) +{ + uint8_t set_buf_index[2] = { if_index, 0 }; + uint8_t hbuf_size, tmp[8]; + int i; + + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_INDEX, + set_buf_index, 2)) + return false; + + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, + &hbuf_size, 1)) + return false; + + /* Buffer size is 0 based, hooray! */ + hbuf_size++; + + DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", + if_index, length, hbuf_size); + + for (i = 0; i < hbuf_size; i += 8) { + memset(tmp, 0, 8); + if (i < length) + memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); + + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_DATA, + tmp, 8)) + return false; + } + + return intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_TXRATE, + &tx_rate, 1); +} + static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) { struct dip_infoframe avi_if = { @@ -896,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) .ver = DIP_VERSION_AVI, .len = DIP_LEN_AVI, }; - uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; - uint8_t set_buf_index[2] = { 1, 0 }; uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; - uint64_t *data = (uint64_t *)sdvo_data; - unsigned i; intel_dip_infoframe_csum(&avi_if); @@ -910,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) sdvo_data[3] = avi_if.checksum; memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_INDEX, - set_buf_index, 2)) - return false; - - for (i = 0; i < sizeof(sdvo_data); i += 8) { - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_DATA, - data, 8)) - return false; - data++; - } - - return intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_HBUF_TXRATE, - &tx_rate, 1); + return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, + SDVO_HBUF_TX_VSYNC, + sdvo_data, sizeof(sdvo_data)); } static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) @@ -984,6 +1011,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, return false; intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd); + intel_sdvo->dtd_sdvo_flags = input_dtd.part2.sdvo_flags; return true; } @@ -1092,6 +1120,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, * adjusted_mode. */ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); + if (intel_sdvo->is_tv || intel_sdvo->is_lvds) + input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags; if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) DRM_INFO("Setting input timings on %s failed\n", SDVO_NAME(intel_sdvo)); @@ -2277,10 +2307,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; } - /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling, - * as opposed to native LVDS, where we upscale with the panel-fitter - * (and hence only the native LVDS resolution could be cloned). */ - intel_sdvo->base.cloneable = true; + /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */ + intel_sdvo->base.cloneable = false; intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) @@ -2354,6 +2382,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) return true; } +static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo) +{ + struct drm_device *dev = intel_sdvo->base.base.dev; + struct drm_connector *connector, *tmp; + + list_for_each_entry_safe(connector, tmp, + &dev->mode_config.connector_list, head) { + if (intel_attached_encoder(connector) == &intel_sdvo->base) + intel_sdvo_destroy(connector); + } +} + static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector, int type) @@ -2677,7 +2717,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", SDVO_NAME(intel_sdvo)); - goto err; + /* Output_setup can leave behind connectors! */ + goto err_output; } /* Only enable the hotplug irq if we need it, to work around noisy @@ -2690,12 +2731,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) - goto err; + goto err_output; if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, &intel_sdvo->pixel_clock_min, &intel_sdvo->pixel_clock_max)) - goto err; + goto err_output; DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " "clock range %dMHz - %dMHz, " @@ -2715,6 +2756,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); return true; +err_output: + intel_sdvo_output_cleanup(intel_sdvo); + err: drm_encoder_cleanup(&intel_encoder->base); i2c_del_adapter(&intel_sdvo->ddc); diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 9d030142ee4..770bdd6ecd9 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg { #define SDVO_CMD_SET_AUDIO_STAT 0x91 #define SDVO_CMD_GET_AUDIO_STAT 0x92 #define SDVO_CMD_SET_HBUF_INDEX 0x93 + #define SDVO_HBUF_INDEX_ELD 0 + #define SDVO_HBUF_INDEX_AVI_IF 1 #define SDVO_CMD_GET_HBUF_INDEX 0x94 #define SDVO_CMD_GET_HBUF_INFO 0x95 #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 diff --git a/drivers/gpu/drm/nouveau/core/core/gpuobj.c b/drivers/gpu/drm/nouveau/core/core/gpuobj.c index 1f34549aff1..70586fde69c 100644 --- a/drivers/gpu/drm/nouveau/core/core/gpuobj.c +++ b/drivers/gpu/drm/nouveau/core/core/gpuobj.c @@ -39,6 +39,11 @@ nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj) nv_wo32(gpuobj, i, 0x00000000); } + if (gpuobj->node) { + nouveau_mm_free(&nv_gpuobj(gpuobj->parent)->heap, + &gpuobj->node); + } + if (gpuobj->heap.block_size) nouveau_mm_fini(&gpuobj->heap); diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index bfddf87926d..a6d3cd6490f 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.c @@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block) node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) return -ENOMEM; - node->offset = roundup(offset, mm->block_size); - node->length = rounddown(offset + length, mm->block_size) - node->offset; + + if (length) { + node->offset = roundup(offset, mm->block_size); + node->length = rounddown(offset + length, mm->block_size); + node->length -= node->offset; + } list_add_tail(&node->nl_entry, &mm->nodes); list_add_tail(&node->fl_entry, &mm->free); mm->heap_nodes++; - mm->heap_size += length; return 0; } @@ -236,7 +239,7 @@ nouveau_mm_fini(struct nouveau_mm *mm) int nodes = 0; list_for_each_entry(node, &mm->nodes, nl_entry) { - if (nodes++ == mm->heap_nodes) + if (WARN_ON(nodes++ == mm->heap_nodes)) return -EBUSY; } diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 16a9afb1060..15b182c84ce 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -22,6 +22,8 @@ * Authors: Ben Skeggs */ +#include <subdev/bar.h> + #include <engine/software.h> #include <engine/disp.h> @@ -37,6 +39,7 @@ nv50_disp_sclass[] = { static void nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) { + struct nouveau_bar *bar = nouveau_bar(priv); struct nouveau_disp *disp = &priv->base; struct nouveau_software_chan *chan, *temp; unsigned long flags; @@ -46,19 +49,25 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) if (chan->vblank.crtc != crtc) continue; - nv_wr32(priv, 0x001704, chan->vblank.channel); - nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); - - if (nv_device(priv)->chipset == 0x50) { - nv_wr32(priv, 0x001570, chan->vblank.offset); - nv_wr32(priv, 0x001574, chan->vblank.value); + if (nv_device(priv)->chipset >= 0xc0) { + nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); + bar->flush(bar); + nv_wr32(priv, 0x06000c, + upper_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060010, + lower_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060014, chan->vblank.value); } else { - if (nv_device(priv)->chipset >= 0xc0) { - nv_wr32(priv, 0x06000c, - upper_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x001704, chan->vblank.channel); + nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); + bar->flush(bar); + if (nv_device(priv)->chipset == 0x50) { + nv_wr32(priv, 0x001570, chan->vblank.offset); + nv_wr32(priv, 0x001574, chan->vblank.value); + } else { + nv_wr32(priv, 0x060010, chan->vblank.offset); + nv_wr32(priv, 0x060014, chan->vblank.value); } - nv_wr32(priv, 0x060010, chan->vblank.offset); - nv_wr32(priv, 0x060014, chan->vblank.value); } list_del(&chan->vblank.head); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c index e45035efb8c..7bbb1e1b7a8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c @@ -669,21 +669,27 @@ nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem) }); } -void +int nv40_grctx_init(struct nouveau_device *device, u32 *size) { - u32 ctxprog[256], i; + u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i; struct nouveau_grctx ctx = { .device = device, .mode = NOUVEAU_GRCTX_PROG, .data = ctxprog, - .ctxprog_max = ARRAY_SIZE(ctxprog) + .ctxprog_max = 256, }; + if (!ctxprog) + return -ENOMEM; + nv40_grctx_generate(&ctx); nv_wr32(device, 0x400324, 0); for (i = 0; i < ctx.ctxprog_len; i++) nv_wr32(device, 0x400328, ctxprog[i]); *size = ctx.ctxvals_pos * 4; + + kfree(ctxprog); + return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 8d0021049ec..cc6574eeb80 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent, static int nv40_graph_context_fini(struct nouveau_object *object, bool suspend) { - struct nv04_graph_priv *priv = (void *)object->engine; - struct nv04_graph_chan *chan = (void *)object; + struct nv40_graph_priv *priv = (void *)object->engine; + struct nv40_graph_chan *chan = (void *)object; u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4; int ret = 0; @@ -346,7 +346,9 @@ nv40_graph_init(struct nouveau_object *object) return ret; /* generate and upload context program */ - nv40_grctx_init(nv_device(priv), &priv->size); + ret = nv40_grctx_init(nv_device(priv), &priv->size); + if (ret) + return ret; /* No context present currently */ nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h index d2ac975afc2..7da35a4e797 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h @@ -15,7 +15,7 @@ nv44_graph_class(void *priv) return !(0x0baf & (1 << (device->chipset & 0x0f))); } -void nv40_grctx_init(struct nouveau_device *, u32 *size); +int nv40_grctx_init(struct nouveau_device *, u32 *size); void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *); #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c index 12418574efe..f7c581ad199 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c @@ -38,7 +38,7 @@ struct nv40_mpeg_priv { }; struct nv40_mpeg_chan { - struct nouveau_mpeg base; + struct nouveau_mpeg_chan base; }; /******************************************************************************* diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h index 9ee9bf4028c..975137ba34a 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/mm.h +++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h @@ -19,7 +19,6 @@ struct nouveau_mm { u32 block_size; int heap_nodes; - u32 heap_size; }; int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); diff --git a/drivers/gpu/drm/nouveau/core/include/core/object.h b/drivers/gpu/drm/nouveau/core/include/core/object.h index 818feabbf4a..486f1a9217f 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/object.h +++ b/drivers/gpu/drm/nouveau/core/include/core/object.h @@ -175,14 +175,18 @@ nv_mo32(void *obj, u32 addr, u32 mask, u32 data) return temp; } -static inline bool -nv_strncmp(void *obj, u32 addr, u32 len, const char *str) +static inline int +nv_memcmp(void *obj, u32 addr, const char *str, u32 len) { + unsigned char c1, c2; + while (len--) { - if (nv_ro08(obj, addr++) != *(str++)) - return false; + c1 = nv_ro08(obj, addr++); + c2 = *(str++); + if (c1 != c2) + return c1 - c2; } - return true; + return 0; } #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h index 39e73b91d36..41b7a6a76f1 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h @@ -54,6 +54,7 @@ int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, int clk, struct nouveau_pll_vals *); int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1, struct nouveau_pll_vals *); - +int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, + int clk, struct nouveau_pll_vals *); #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index dcb5c2befc9..70ca7d5a1aa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios) } data = of_get_property(dn, "NVDA,BMP", &size); - if (data) { + if (data && size) { bios->size = size; bios->data = kmalloc(bios->size, GFP_KERNEL); if (bios->data) @@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios) goto out; bios->size = nv_rd08(bios, 0x700002) * 512; + if (!bios->size) + goto out; + bios->data = kmalloc(bios->size, GFP_KERNEL); if (bios->data) { for (i = 0; i < bios->size; i++) @@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) /* read entire bios image to system memory */ bios->size = nv_rd08(bios, 0x300002) * 512; + if (!bios->size) + goto out; + bios->data = kmalloc(bios->size, GFP_KERNEL); if (bios->data) { for (i = 0; i < bios->size; i++) @@ -186,14 +192,22 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios) { struct pci_dev *pdev = nv_device(bios)->pdev; int ret, cnt, i; - u8 data[3]; - if (!nouveau_acpi_rom_supported(pdev)) + if (!nouveau_acpi_rom_supported(pdev)) { + bios->data = NULL; return; + } bios->size = 0; - if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3) - bios->size = data[2] * 512; + bios->data = kmalloc(4096, GFP_KERNEL); + if (bios->data) { + if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096) + bios->size = bios->data[2] * 512; + kfree(bios->data); + } + + if (!bios->size) + return; bios->data = kmalloc(bios->size, GFP_KERNEL); for (i = 0; bios->data && i < bios->size; i += cnt) { @@ -229,12 +243,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios) static int nouveau_bios_score(struct nouveau_bios *bios, const bool writeable) { - if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) { + if (bios->size < 3 || !bios->data || bios->data[0] != 0x55 || + bios->data[1] != 0xAA) { nv_info(bios, "... signature not found\n"); return 0; } - if (nvbios_checksum(bios->data, bios->data[2] * 512)) { + if (nvbios_checksum(bios->data, + min_t(u32, bios->data[2] * 512, bios->size))) { nv_info(bios, "... checksum invalid\n"); /* if a ro image is somewhat bad, it's probably all rubbish */ return writeable ? 2 : 1; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c index 9ed6e728a94..c5119715774 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c @@ -43,7 +43,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) *ver = nv_ro08(bios, dcb); if (*ver >= 0x41) { - nv_warn(bios, "DCB *ver 0x%02x unknown\n", *ver); + nv_warn(bios, "DCB version 0x%02x unknown\n", *ver); return 0x0000; } else if (*ver >= 0x30) { @@ -64,7 +64,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) } } else if (*ver >= 0x15) { - if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) { + if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) { u16 i2c = nv_ro16(bios, dcb + 2); *hdr = 4; *cnt = (i2c - dcb) / 10; diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c index 5e5f4cddae3..f835501203e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/pll.c @@ -157,11 +157,10 @@ pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len) while (map->reg) { if (map->reg == reg && *ver >= 0x20) { u16 addr = (data += hdr); + *type = map->type; while (cnt--) { - if (nv_ro32(bios, data) == map->reg) { - *type = map->type; + if (nv_ro32(bios, data) == map->reg) return data; - } data += *len; } return addr; @@ -200,11 +199,10 @@ pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len) while (map->reg) { if (map->type == type && *ver >= 0x20) { u16 addr = (data += hdr); + *reg = map->reg; while (cnt--) { - if (nv_ro32(bios, data) == map->reg) { - *reg = map->reg; + if (nv_ro32(bios, data) == map->reg) return data; - } data += *len; } return addr; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c index cc8d7d162d7..9068c98b96f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c @@ -66,6 +66,24 @@ nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) return ret; } +int +nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, + int clk, struct nouveau_pll_vals *pv) +{ + int ret, N, M, P; + + ret = nva3_pll_calc(clock, info, clk, &N, NULL, &M, &P); + + if (ret > 0) { + pv->refclk = info->refclk; + pv->N1 = N; + pv->M1 = M; + pv->log2P = P; + } + return ret; +} + + static int nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -80,6 +98,7 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nva3_clock_pll_set; + priv->base.pll_calc = nva3_clock_pll_calc; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index 5ccce0b17bf..f6962c9b6c3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c @@ -79,6 +79,7 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nvc0_clock_pll_set; + priv->base.pll_calc = nva3_clock_pll_calc; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 436e9efe7ef..5f570806143 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, ((priv->base.ram.size & 0x000000ff) << 32); tags = nv_rd32(priv, 0x100320); - if (tags) { - ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); - if (ret) - return ret; + ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); + if (ret) + return ret; - nv_debug(priv, "%d compression tags\n", tags); - } + nv_debug(priv, "%d compression tags\n", tags); size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; switch (device->chipset) { @@ -237,6 +235,7 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12; + priv->base.ram.type = NV_MEM_TYPE_STOLEN; break; default: ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size, @@ -277,7 +276,6 @@ nv50_fb_dtor(struct nouveau_object *object) __free_page(priv->r100c08_page); } - nouveau_mm_fini(&priv->base.vram); nouveau_fb_destroy(&priv->base); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 3d2c88310f9..dbfc2abf0cf 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, case DCB_I2C_NVIO_BIT: port->drive = info.drive & 0x0f; if (device->card_type < NV_D0) { - if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) + if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) break; port->drive = nv50_i2c_port[port->drive]; port->sense = port->drive; diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index b29237970fa..52317868518 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c @@ -134,7 +134,7 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm) end = ptimer->read(ptimer); if (cycles == 5) { - tach = (u64)60000000000; + tach = (u64)60000000000ULL; do_div(tach, (end - start)); return tach; } else diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index 0203e1e12ca..9474cfca6e4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) static void nv41_vm_flush(struct nouveau_vm *vm) { - struct nv04_vm_priv *priv = (void *)vm->vmm; + struct nv04_vmmgr_priv *priv = (void *)vm->vmm; mutex_lock(&nv_subdev(priv)->mutex); nv_wr32(priv, 0x100810, 0x00000022); @@ -92,7 +92,8 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv04_vmmgr_priv *priv; int ret; - if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { + if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) || + !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass, data, size, pobject); } diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c index 0ac18d05a14..aa8131436e3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c @@ -163,7 +163,8 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv04_vmmgr_priv *priv; int ret; - if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { + if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) || + !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) { return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass, data, size, pobject); } diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index cc79c796afe..cbf1fc60a38 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -241,6 +241,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) if (unlikely(!abi16)) return -ENOMEM; + + if (!drm->channel) + return nouveau_abi16_put(abi16, -ENODEV); + client = nv_client(abi16->client); if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 259e5f1adf4..35ac57f0aab 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -456,6 +456,7 @@ static struct ttm_tt * nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, uint32_t page_flags, struct page *dummy_read) { +#if __OS_HAS_AGP struct nouveau_drm *drm = nouveau_bdev(bdev); struct drm_device *dev = drm->dev; @@ -463,6 +464,7 @@ nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, return ttm_agp_tt_create(bdev, dev->agp->bridge, size, page_flags, dummy_read); } +#endif return nouveau_sgdma_create_ttm(bdev, size, page_flags, dummy_read); } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 9a6e2cb282d..d3595b23434 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * valid - it's not (rh#613284) */ if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { - if (!(nv_connector->edid = nouveau_acpi_edid(dev, connector))) { + if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) { status = connector_status_connected; goto out; } diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 8f98e5a8c48..86124b131f4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_disp *pdisp = nouveau_disp(drm->device); struct nouveau_display *disp; + u32 pclass = dev->pdev->class >> 8; int ret, gen; disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); @@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev) drm_kms_helper_poll_init(dev); drm_kms_helper_poll_disable(dev); - if (nv_device(drm->device)->card_type < NV_50) - ret = nv04_display_create(dev); - else - if (nv_device(drm->device)->card_type < NV_D0) - ret = nv50_display_create(dev); - else - ret = nvd0_display_create(dev); - if (ret) - goto disp_create_err; - - if (dev->mode_config.num_crtc) { - ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (nouveau_modeset == 1 || + (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) { + if (nv_device(drm->device)->card_type < NV_50) + ret = nv04_display_create(dev); + else + if (nv_device(drm->device)->card_type < NV_D0) + ret = nv50_display_create(dev); + else + ret = nvd0_display_create(dev); if (ret) - goto vblank_err; + goto disp_create_err; + + if (dev->mode_config.num_crtc) { + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); + if (ret) + goto vblank_err; + } + + nouveau_backlight_init(dev); } - nouveau_backlight_init(dev); return 0; vblank_err: @@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev) nouveau_backlight_exit(dev); drm_vblank_cleanup(dev); - disp->dtor(dev); + if (disp->dtor) + disp->dtor(dev); drm_kms_helper_poll_fini(dev); drm_mode_config_cleanup(dev); @@ -530,9 +536,11 @@ nouveau_page_flip_reserve(struct nouveau_bo *old_bo, if (ret) goto fail; - ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); - if (ret) - goto fail_unreserve; + if (likely(old_bo != new_bo)) { + ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); + if (ret) + goto fail_unreserve; + } return 0; @@ -551,8 +559,10 @@ nouveau_page_flip_unreserve(struct nouveau_bo *old_bo, nouveau_bo_fence(new_bo, fence); ttm_bo_unreserve(&new_bo->bo); - nouveau_bo_fence(old_bo, fence); - ttm_bo_unreserve(&old_bo->bo); + if (likely(old_bo != new_bo)) { + nouveau_bo_fence(old_bo, fence); + ttm_bo_unreserve(&old_bo->bo); + } nouveau_bo_unpin(old_bo); } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index ccae8c26ae2..8503b2ea570 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration"); static int nouveau_noaccel = 0; module_param_named(noaccel, nouveau_noaccel, int, 0400); -MODULE_PARM_DESC(modeset, "enable driver"); -static int nouveau_modeset = -1; +MODULE_PARM_DESC(modeset, "enable driver (default: auto, " + "0 = disabled, 1 = enabled, 2 = headless)"); +int nouveau_modeset = -1; module_param_named(modeset, nouveau_modeset, int, 0400); static struct drm_driver driver; @@ -128,7 +129,8 @@ nouveau_accel_init(struct nouveau_drm *drm) /* initialise synchronisation routines */ if (device->card_type < NV_10) ret = nv04_fence_create(drm); - else if (device->chipset < 0x84) ret = nv10_fence_create(drm); + else if (device->card_type < NV_50) ret = nv10_fence_create(drm); + else if (device->chipset < 0x84) ret = nv50_fence_create(drm); else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); else ret = nvc0_fence_create(drm); if (ret) { @@ -363,7 +365,8 @@ nouveau_drm_unload(struct drm_device *dev) nouveau_pm_fini(dev); - nouveau_display_fini(dev); + if (dev->mode_config.num_crtc) + nouveau_display_fini(dev); nouveau_display_destroy(dev); nouveau_irq_fini(dev); @@ -403,13 +406,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) pm_state.event == PM_EVENT_PRETHAW) return 0; - NV_INFO(drm, "suspending fbcon...\n"); - nouveau_fbcon_set_suspend(dev, 1); + if (dev->mode_config.num_crtc) { + NV_INFO(drm, "suspending fbcon...\n"); + nouveau_fbcon_set_suspend(dev, 1); - NV_INFO(drm, "suspending display...\n"); - ret = nouveau_display_suspend(dev); - if (ret) - return ret; + NV_INFO(drm, "suspending display...\n"); + ret = nouveau_display_suspend(dev); + if (ret) + return ret; + } NV_INFO(drm, "evicting buffers...\n"); ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); @@ -445,8 +450,10 @@ fail_client: nouveau_client_init(&cli->base); } - NV_INFO(drm, "resuming display...\n"); - nouveau_display_resume(dev); + if (dev->mode_config.num_crtc) { + NV_INFO(drm, "resuming display...\n"); + nouveau_display_resume(dev); + } return ret; } @@ -486,8 +493,10 @@ nouveau_drm_resume(struct pci_dev *pdev) nouveau_irq_postinstall(dev); nouveau_pm_resume(dev); - NV_INFO(drm, "resuming display...\n"); - nouveau_display_resume(dev); + if (dev->mode_config.num_crtc) { + NV_INFO(drm, "resuming display...\n"); + nouveau_display_resume(dev); + } return 0; } @@ -662,9 +671,7 @@ nouveau_drm_init(void) #ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force()) nouveau_modeset = 0; - else #endif - nouveau_modeset = 1; } if (!nouveau_modeset) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 81947121754..a1016992708 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *); nv_info((cli), fmt, ##args); \ } while (0) +extern int nouveau_modeset; + #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 9ca8afdb554..1d8cb506a28 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS) nv_subdev(pmc)->intr(nv_subdev(pmc)); - if (device->card_type >= NV_D0) { - if (nv_rd32(device, 0x000100) & 0x04000000) - nvd0_display_intr(dev); - } else - if (device->card_type >= NV_50) { - if (nv_rd32(device, 0x000100) & 0x04000000) - nv50_display_intr(dev); + if (dev->mode_config.num_crtc) { + if (device->card_type >= NV_D0) { + if (nv_rd32(device, 0x000100) & 0x04000000) + nvd0_display_intr(dev); + } else + if (device->card_type >= NV_50) { + if (nv_rd32(device, 0x000100) & 0x04000000) + nv50_display_intr(dev); + } } return IRQ_HANDLED; diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 0bf64c90aa2..5566172774d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -52,7 +52,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_pm *pm = nouveau_pm(dev); - struct nouveau_therm *therm = nouveau_therm(drm); + struct nouveau_therm *therm = nouveau_therm(drm->device); int ret; /*XXX: not on all boards, we should control based on temperature @@ -64,7 +64,6 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, ret = therm->fan_set(therm, perflvl->fanspeed); if (ret && ret != -ENODEV) { NV_ERROR(drm, "fanspeed set failed: %d\n", ret); - return ret; } } @@ -706,8 +705,7 @@ nouveau_hwmon_init(struct drm_device *dev) struct device *hwmon_dev; int ret = 0; - if (!therm || !therm->temp_get || !therm->attr_get || - !therm->attr_set || therm->temp_get(therm) < 0) + if (!therm || !therm->temp_get || !therm->attr_get || !therm->attr_set) return -ENODEV; hwmon_dev = hwmon_device_register(&dev->pdev->dev); diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 347a3bd78d0..64f7020fb60 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -220,7 +220,7 @@ out: NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); if (blue == 0x18) { - NV_INFO(drm, "Load detected on head A\n"); + NV_DEBUG(drm, "Load detected on head A\n"); return connector_status_connected; } @@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) if (nv17_dac_sample_load(encoder) & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { - NV_INFO(drm, "Load detected on output %c\n", - '@' + ffs(dcb->or)); + NV_DEBUG(drm, "Load detected on output %c\n", + '@' + ffs(dcb->or)); return connector_status_connected; } else { return connector_status_disconnected; @@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), - nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); + NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) @@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n", + mode, nv_encoder->dcb->index); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); } diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index da55d7642c8..184cdf80676 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), - nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); + NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) @@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", + mode, nv_encoder->dcb->index); if (was_powersaving && is_powersaving_dpms(mode)) return; @@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", + mode, nv_encoder->dcb->index); nv04_dfp_update_backlight(encoder, mode); nv04_dfp_update_fp_control(encoder, mode); diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 099fbeda6e2..62e826a139b 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; uint8_t crtc1A; - NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", - mode, nv_encoder->dcb->index); + NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n", + mode, nv_encoder->dcb->index); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", - drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, - '@' + ffs(nv_encoder->dcb->or)); + NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } static void nv04_tv_destroy(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 96184d02c8d..3bce0299f64 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1690,41 +1690,49 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) } /* all other cases */ pll_in_use = radeon_get_pll_use_mask(crtc); - if (!(pll_in_use & (1 << ATOM_PPLL2))) - return ATOM_PPLL2; if (!(pll_in_use & (1 << ATOM_PPLL1))) return ATOM_PPLL1; + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; DRM_ERROR("unable to allocate a PPLL\n"); return ATOM_PPLL_INVALID; - } else { - if (ASIC_IS_AVIVO(rdev)) { - /* in DP mode, the DP ref clock can come from either PPLL - * depending on the asic: - * DCE3: PPLL1 or PPLL2 - */ - if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { - /* use the same PPLL for all DP monitors */ - pll = radeon_get_shared_dp_ppll(crtc); - if (pll != ATOM_PPLL_INVALID) - return pll; - } else { - /* use the same PPLL for all monitors with the same clock */ - pll = radeon_get_shared_nondp_ppll(crtc); - if (pll != ATOM_PPLL_INVALID) - return pll; - } - /* all other cases */ - pll_in_use = radeon_get_pll_use_mask(crtc); + } else if (ASIC_IS_AVIVO(rdev)) { + /* in DP mode, the DP ref clock can come from either PPLL + * depending on the asic: + * DCE3: PPLL1 or PPLL2 + */ + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } else { + /* use the same PPLL for all monitors with the same clock */ + pll = radeon_get_shared_nondp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + /* all other cases */ + pll_in_use = radeon_get_pll_use_mask(crtc); + /* the order shouldn't matter here, but we probably + * need this until we have atomic modeset + */ + if (rdev->flags & RADEON_IS_IGP) { + if (!(pll_in_use & (1 << ATOM_PPLL1))) + return ATOM_PPLL1; + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; + } else { if (!(pll_in_use & (1 << ATOM_PPLL2))) return ATOM_PPLL2; if (!(pll_in_use & (1 << ATOM_PPLL1))) return ATOM_PPLL1; - DRM_ERROR("unable to allocate a PPLL\n"); - return ATOM_PPLL_INVALID; - } else { - /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ - return radeon_crtc->crtc_id; } + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; + } else { + /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ + return radeon_crtc->crtc_id; } } diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 49cbb3795a1..010bae19554 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -184,6 +184,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, struct radeon_backlight_privdata *pdata; struct radeon_encoder_atom_dig *dig; u8 backlight_level; + char bl_name[16]; if (!radeon_encoder->enc_priv) return; @@ -203,7 +204,9 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder, memset(&props, 0, sizeof(props)); props.max_brightness = RADEON_MAX_BL_LEVEL; props.type = BACKLIGHT_RAW; - bd = backlight_device_register("radeon_bl", &drm_connector->kdev, + snprintf(bl_name, sizeof(bl_name), + "radeon_bl%d", dev->primary->index); + bd = backlight_device_register(bl_name, &drm_connector->kdev, pdata, &radeon_atom_backlight_ops, &props); if (IS_ERR(bd)) { DRM_ERROR("Backlight registration failed\n"); @@ -1622,7 +1625,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index a1f49c5fd74..219942c660d 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1330,6 +1330,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav break; udelay(1); } + } else { + save->crtc_enabled[i] = false; } } @@ -1372,7 +1374,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); for (i = 0; i < rdev->num_crtc; i++) { - if (save->crtc_enabled) { + if (save->crtc_enabled[i]) { if (ASIC_IS_DCE6(rdev)) { tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; @@ -3431,9 +3433,14 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev) if (!(mask & DRM_PCIE_SPEED_50)) return; + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + if (speed_cntl & LC_CURRENT_DATA_RATE) { + DRM_INFO("PCIE gen 2 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); - speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) || (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 573ed1bc6cf..c042e497e45 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, /* macro tile width & height */ palign = (8 * surf->bankw * track->npipes) * surf->mtilea; halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; - mtileb = (palign / 8) * (halign / 8) * tileb;; + mtileb = (palign / 8) * (halign / 8) * tileb; mtile_pr = surf->nbx / palign; mtile_ps = (mtile_pr * surf->nby) / halign; surf->layer_size = mtile_ps * mtileb * slice_pt; @@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: + case CP_COHER_CNTL: + case CP_COHER_SIZE: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_GS_VERTEX_REUSE: @@ -2829,6 +2832,7 @@ static bool evergreen_vm_reg_valid(u32 reg) case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: return true; default: + DRM_ERROR("Invalid register 0x%x in CS\n", reg); return false; } } diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index df542f1a5df..2bc0f6a1b42 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -91,6 +91,10 @@ #define FB_READ_EN (1 << 0) #define FB_WRITE_EN (1 << 1) +#define CP_STRMOUT_CNTL 0x84FC + +#define CP_COHER_CNTL 0x85F0 +#define CP_COHER_SIZE 0x85F4 #define CP_COHER_BASE 0x85F8 #define CP_STALLED_STAT1 0x8674 #define CP_STALLED_STAT2 0x8678 diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 8bcb554ea0c..81e6a568c29 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -770,9 +770,13 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev) WREG32(0x15DC, 0); /* empty context1-7 */ + /* Assign the pt base to something valid for now; the pts used for + * the VMs are determined by the application and setup and assigned + * on the fly in the vm part of radeon_gart.c + */ for (i = 1; i < 8; i++) { WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); - WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), 0); + WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn); WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), rdev->gart.table_addr >> 12); } @@ -1534,26 +1538,31 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe, { struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index]; uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); - int i; - radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, 1 + count * 2)); - radeon_ring_write(ring, pe); - radeon_ring_write(ring, upper_32_bits(pe) & 0xff); - for (i = 0; i < count; ++i) { - uint64_t value = 0; - if (flags & RADEON_VM_PAGE_SYSTEM) { - value = radeon_vm_map_gart(rdev, addr); - value &= 0xFFFFFFFFFFFFF000ULL; - addr += incr; - - } else if (flags & RADEON_VM_PAGE_VALID) { - value = addr; - addr += incr; - } + while (count) { + unsigned ndw = 1 + count * 2; + if (ndw > 0x3FFF) + ndw = 0x3FFF; + + radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw)); + radeon_ring_write(ring, pe); + radeon_ring_write(ring, upper_32_bits(pe) & 0xff); + for (; ndw > 1; ndw -= 2, --count, pe += 8) { + uint64_t value = 0; + if (flags & RADEON_VM_PAGE_SYSTEM) { + value = radeon_vm_map_gart(rdev, addr); + value &= 0xFFFFFFFFFFFFF000ULL; + addr += incr; + + } else if (flags & RADEON_VM_PAGE_VALID) { + value = addr; + addr += incr; + } - value |= r600_flags; - radeon_ring_write(ring, value); - radeon_ring_write(ring, upper_32_bits(value)); + value |= r600_flags; + radeon_ring_write(ring, value); + radeon_ring_write(ring, upper_32_bits(value)); + } } } @@ -1572,12 +1581,6 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) if (vm == NULL) return; - radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (vm->id << 2), 0)); - radeon_ring_write(ring, 0); - - radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (vm->id << 2), 0)); - radeon_ring_write(ring, vm->last_pfn); - radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0)); radeon_ring_write(ring, vm->pd_gpu_addr >> 12); @@ -1588,4 +1591,8 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) /* bits 0-7 are the VM contexts0-7 */ radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0)); radeon_ring_write(ring, 1 << vm->id); + + /* sync PFP to ME, otherwise we might get invalid PFP reads */ + radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); + radeon_ring_write(ring, 0x0); } diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 2423d1b5d38..cbef6815907 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -502,6 +502,7 @@ #define PACKET3_MPEG_INDEX 0x3A #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D +#define PACKET3_PFP_SYNC_ME 0x42 #define PACKET3_SURFACE_SYNC 0x43 # define PACKET3_CB0_DEST_BASE_ENA (1 << 6) # define PACKET3_CB1_DEST_BASE_ENA (1 << 7) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 70c800ff619..cda280d157d 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3703,6 +3703,12 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) if (!(mask & DRM_PCIE_SPEED_50)) return; + speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL); + if (speed_cntl & LC_CURRENT_DATA_RATE) { + DRM_INFO("PCIE gen 2 link speeds already enabled\n"); + return; + } + DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); /* 55 nm r6xx asics */ diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index b04c06444d8..8c42d54c2e2 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -663,9 +663,14 @@ struct radeon_vm { struct list_head list; struct list_head va; unsigned id; - unsigned last_pfn; - u64 pd_gpu_addr; - struct radeon_sa_bo *sa_bo; + + /* contains the page directory */ + struct radeon_sa_bo *page_directory; + uint64_t pd_gpu_addr; + + /* array of page tables, one for each page directory entry */ + struct radeon_sa_bo **page_tables; + struct mutex mutex; /* last fence for cs using this vm */ struct radeon_fence *fence; @@ -1843,9 +1848,10 @@ extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size */ int radeon_vm_manager_init(struct radeon_device *rdev); void radeon_vm_manager_fini(struct radeon_device *rdev); -int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); +void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm); void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm); int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm); +void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm); struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev, struct radeon_vm *vm, int ring); void radeon_vm_fence(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/radeon_acpi.c b/drivers/gpu/drm/radeon/radeon_acpi.c index b0a5688c67f..196d28d9957 100644 --- a/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/drivers/gpu/drm/radeon/radeon_acpi.c @@ -201,7 +201,7 @@ static int radeon_atif_verify_interface(acpi_handle handle, size = *(u16 *) info->buffer.pointer; if (size < 12) { - DRM_INFO("ATIF buffer is too small: %lu\n", size); + DRM_INFO("ATIF buffer is too small: %zu\n", size); err = -EINVAL; goto out; } @@ -370,6 +370,7 @@ int radeon_atif_handler(struct radeon_device *rdev, radeon_set_backlight_level(rdev, enc, req.backlight_level); +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) if (rdev->is_atom_bios) { struct radeon_encoder_atom_dig *dig = enc->enc_priv; backlight_force_update(dig->bl_dev, @@ -379,6 +380,7 @@ int radeon_atif_handler(struct radeon_device *rdev, backlight_force_update(dig->bl_dev, BACKLIGHT_UPDATE_HOTKEY); } +#endif } } /* TODO: check other events */ @@ -485,7 +487,7 @@ static int radeon_atcs_verify_interface(acpi_handle handle, size = *(u16 *) info->buffer.pointer; if (size < 8) { - DRM_INFO("ATCS buffer is too small: %lu\n", size); + DRM_INFO("ATCS buffer is too small: %zu\n", size); err = -EINVAL; goto out; } diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index 10ea17a6b2a..42433344cb1 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -69,9 +69,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, PCI_VENDOR_ID_DELL, 0x00e3, 2}, - /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */ + /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, PCI_VENDOR_ID_DELL, 0x0149, 1}, + /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, + PCI_VENDOR_ID_IBM, 0x0531, 1}, /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 0x1025, 0x0061, 1}, diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 582e99449c1..15f5ded65e0 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -87,7 +87,7 @@ static union acpi_object *radeon_atpx_call(acpi_handle handle, int function, atpx_arg_elements[1].integer.value = 0; } - status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer); + status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer); /* Fail only if calling the method fails and ATPX is supported */ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { @@ -148,7 +148,7 @@ static int radeon_atpx_verify_interface(struct radeon_atpx *atpx) size = *(u16 *) info->buffer.pointer; if (size < 8) { - printk("ATPX buffer is too small: %lu\n", size); + printk("ATPX buffer is too small: %zu\n", size); err = -EINVAL; goto out; } @@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id) } /** - * radeon_atpx_switchto - switch to the requested GPU + * radeon_atpx_power_state - power down/up the requested GPU * - * @id: GPU to switch to + * @id: GPU to power down/up * @state: requested power state (0 = off, 1 = on) * * Execute the necessary ATPX function to power down/up the discrete GPU @@ -373,11 +373,11 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, } /** - * radeon_atpx_pci_probe_handle - look up the ATRM and ATPX handles + * radeon_atpx_pci_probe_handle - look up the ATPX handle * * @pdev: pci device * - * Look up the ATPX and ATRM handles (all asics). + * Look up the ATPX handles (all asics). * Returns true if the handles are found, false if not. */ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 67cfc1795ec..b884c362a8c 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) struct drm_mode_object *obj; int i; enum drm_connector_status ret = connector_status_disconnected; - bool dret = false; + bool dret = false, broken_edid = false; if (!force && radeon_check_hpd_status_unchanged(connector)) return connector->status; @@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) ret = connector_status_disconnected; DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); radeon_connector->ddc_bus = NULL; + } else { + ret = connector_status_connected; + broken_edid = true; /* defer use_digital to later */ } } else { radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); @@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) encoder_funcs = encoder->helper_private; if (encoder_funcs->detect) { - if (ret != connector_status_connected) { - ret = encoder_funcs->detect(encoder, connector); - if (ret == connector_status_connected) { - radeon_connector->use_digital = false; + if (!broken_edid) { + if (ret != connector_status_connected) { + /* deal with analog monitors without DDC */ + ret = encoder_funcs->detect(encoder, connector); + if (ret == connector_status_connected) { + radeon_connector->use_digital = false; + } + if (ret != connector_status_disconnected) + radeon_connector->detected_by_load = true; } - if (ret != connector_status_disconnected) - radeon_connector->detected_by_load = true; + } else { + enum drm_connector_status lret; + /* assume digital unless load detected otherwise */ + radeon_connector->use_digital = true; + lret = encoder_funcs->detect(encoder, connector); + DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret); + if (lret == connector_status_connected) + radeon_connector->use_digital = false; } break; } diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index cb7b7c062fe..41672cc563f 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -478,6 +478,7 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, } out: + radeon_vm_add_to_lru(rdev, vm); mutex_unlock(&vm->mutex); mutex_unlock(&rdev->vm_manager.lock); return r; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 64a42647f08..e2f5f888c37 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -355,6 +355,8 @@ int radeon_wb_init(struct radeon_device *rdev) */ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base) { + uint64_t limit = (uint64_t)radeon_vram_limit << 20; + mc->vram_start = base; if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) { dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); @@ -368,8 +370,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 mc->mc_vram_size = mc->aper_size; } mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; - if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size) - mc->real_vram_size = radeon_vram_limit; + if (limit && limit < mc->real_vram_size) + mc->real_vram_size = limit; dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n", mc->mc_vram_size >> 20, mc->vram_start, mc->vram_end, mc->real_vram_size >> 20); @@ -835,6 +837,19 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state) } /** + * radeon_check_pot_argument - check that argument is a power of two + * + * @arg: value to check + * + * Validates that a certain argument is a power of two (all asics). + * Returns true if argument is valid. + */ +static bool radeon_check_pot_argument(int arg) +{ + return (arg & (arg - 1)) == 0; +} + +/** * radeon_check_arguments - validate module params * * @rdev: radeon_device pointer @@ -845,52 +860,25 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state) static void radeon_check_arguments(struct radeon_device *rdev) { /* vramlimit must be a power of two */ - switch (radeon_vram_limit) { - case 0: - case 4: - case 8: - case 16: - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - case 2048: - case 4096: - break; - default: + if (!radeon_check_pot_argument(radeon_vram_limit)) { dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n", radeon_vram_limit); radeon_vram_limit = 0; - break; } - radeon_vram_limit = radeon_vram_limit << 20; + /* gtt size must be power of two and greater or equal to 32M */ - switch (radeon_gart_size) { - case 4: - case 8: - case 16: + if (radeon_gart_size < 32) { dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n", radeon_gart_size); radeon_gart_size = 512; - break; - case 32: - case 64: - case 128: - case 256: - case 512: - case 1024: - case 2048: - case 4096: - break; - default: + + } else if (!radeon_check_pot_argument(radeon_gart_size)) { dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", radeon_gart_size); radeon_gart_size = 512; - break; } - rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; + /* AGP mode can only be -1, 1, 2, 4, 8 */ switch (radeon_agpmode) { case -1: @@ -1018,6 +1006,10 @@ int radeon_device_init(struct radeon_device *rdev, return r; /* initialize vm here */ mutex_init(&rdev->vm_manager.lock); + /* Adjust VM size here. + * Currently set to 4GB ((1 << 20) 4k pages). + * Max GPUVM size for cayman and SI is 40 bits. + */ rdev->vm_manager.max_pfn = 1 << 20; INIT_LIST_HEAD(&rdev->vm_manager.lru_vm); diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index f0c06d196b7..4debd60e5aa 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -355,14 +355,13 @@ int radeon_gart_init(struct radeon_device *rdev) DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages); /* Allocate pages table */ - rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages, - GFP_KERNEL); + rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages); if (rdev->gart.pages == NULL) { radeon_gart_fini(rdev); return -ENOMEM; } - rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) * - rdev->gart.num_cpu_pages, GFP_KERNEL); + rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) * + rdev->gart.num_cpu_pages); if (rdev->gart.pages_addr == NULL) { radeon_gart_fini(rdev); return -ENOMEM; @@ -388,8 +387,8 @@ void radeon_gart_fini(struct radeon_device *rdev) radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); } rdev->gart.ready = false; - kfree(rdev->gart.pages); - kfree(rdev->gart.pages_addr); + vfree(rdev->gart.pages); + vfree(rdev->gart.pages_addr); rdev->gart.pages = NULL; rdev->gart.pages_addr = NULL; @@ -423,6 +422,18 @@ void radeon_gart_fini(struct radeon_device *rdev) */ /** + * radeon_vm_num_pde - return the number of page directory entries + * + * @rdev: radeon_device pointer + * + * Calculate the number of page directory entries (cayman+). + */ +static unsigned radeon_vm_num_pdes(struct radeon_device *rdev) +{ + return rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE; +} + +/** * radeon_vm_directory_size - returns the size of the page directory in bytes * * @rdev: radeon_device pointer @@ -431,7 +442,7 @@ void radeon_gart_fini(struct radeon_device *rdev) */ static unsigned radeon_vm_directory_size(struct radeon_device *rdev) { - return (rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE) * 8; + return RADEON_GPU_PAGE_ALIGN(radeon_vm_num_pdes(rdev) * 8); } /** @@ -451,11 +462,11 @@ int radeon_vm_manager_init(struct radeon_device *rdev) if (!rdev->vm_manager.enabled) { /* allocate enough for 2 full VM pts */ - size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev)); - size += RADEON_GPU_PAGE_ALIGN(rdev->vm_manager.max_pfn * 8); + size = radeon_vm_directory_size(rdev); + size += rdev->vm_manager.max_pfn * 8; size *= 2; r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, - size, + RADEON_GPU_PAGE_ALIGN(size), RADEON_GEM_DOMAIN_VRAM); if (r) { dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", @@ -476,7 +487,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev) /* restore page table */ list_for_each_entry(vm, &rdev->vm_manager.lru_vm, list) { - if (vm->sa_bo == NULL) + if (vm->page_directory == NULL) continue; list_for_each_entry(bo_va, &vm->va, vm_list) { @@ -500,16 +511,25 @@ static void radeon_vm_free_pt(struct radeon_device *rdev, struct radeon_vm *vm) { struct radeon_bo_va *bo_va; + int i; - if (!vm->sa_bo) + if (!vm->page_directory) return; list_del_init(&vm->list); - radeon_sa_bo_free(rdev, &vm->sa_bo, vm->fence); + radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence); list_for_each_entry(bo_va, &vm->va, vm_list) { bo_va->valid = false; } + + if (vm->page_tables == NULL) + return; + + for (i = 0; i < radeon_vm_num_pdes(rdev); i++) + radeon_sa_bo_free(rdev, &vm->page_tables[i], vm->fence); + + kfree(vm->page_tables); } /** @@ -546,63 +566,106 @@ void radeon_vm_manager_fini(struct radeon_device *rdev) } /** + * radeon_vm_evict - evict page table to make room for new one + * + * @rdev: radeon_device pointer + * @vm: VM we want to allocate something for + * + * Evict a VM from the lru, making sure that it isn't @vm. (cayman+). + * Returns 0 for success, -ENOMEM for failure. + * + * Global and local mutex must be locked! + */ +static int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm) +{ + struct radeon_vm *vm_evict; + + if (list_empty(&rdev->vm_manager.lru_vm)) + return -ENOMEM; + + vm_evict = list_first_entry(&rdev->vm_manager.lru_vm, + struct radeon_vm, list); + if (vm_evict == vm) + return -ENOMEM; + + mutex_lock(&vm_evict->mutex); + radeon_vm_free_pt(rdev, vm_evict); + mutex_unlock(&vm_evict->mutex); + return 0; +} + +/** * radeon_vm_alloc_pt - allocates a page table for a VM * * @rdev: radeon_device pointer * @vm: vm to bind * * Allocate a page table for the requested vm (cayman+). - * Also starts to populate the page table. * Returns 0 for success, error for failure. * * Global and local mutex must be locked! */ int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm) { - struct radeon_vm *vm_evict; - int r; + unsigned pd_size, pts_size; u64 *pd_addr; - int tables_size; + int r; if (vm == NULL) { return -EINVAL; } - /* allocate enough to cover the current VM size */ - tables_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev)); - tables_size += RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8); - - if (vm->sa_bo != NULL) { - /* update lru */ - list_del_init(&vm->list); - list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); + if (vm->page_directory != NULL) { return 0; } retry: - r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, &vm->sa_bo, - tables_size, RADEON_GPU_PAGE_SIZE, false); + pd_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev)); + r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, + &vm->page_directory, pd_size, + RADEON_GPU_PAGE_SIZE, false); if (r == -ENOMEM) { - if (list_empty(&rdev->vm_manager.lru_vm)) { + r = radeon_vm_evict(rdev, vm); + if (r) return r; - } - vm_evict = list_first_entry(&rdev->vm_manager.lru_vm, struct radeon_vm, list); - mutex_lock(&vm_evict->mutex); - radeon_vm_free_pt(rdev, vm_evict); - mutex_unlock(&vm_evict->mutex); goto retry; } else if (r) { return r; } - pd_addr = radeon_sa_bo_cpu_addr(vm->sa_bo); - vm->pd_gpu_addr = radeon_sa_bo_gpu_addr(vm->sa_bo); - memset(pd_addr, 0, tables_size); + vm->pd_gpu_addr = radeon_sa_bo_gpu_addr(vm->page_directory); + + /* Initially clear the page directory */ + pd_addr = radeon_sa_bo_cpu_addr(vm->page_directory); + memset(pd_addr, 0, pd_size); + + pts_size = radeon_vm_num_pdes(rdev) * sizeof(struct radeon_sa_bo *); + vm->page_tables = kzalloc(pts_size, GFP_KERNEL); + + if (vm->page_tables == NULL) { + DRM_ERROR("Cannot allocate memory for page table array\n"); + radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence); + return -ENOMEM; + } + + return 0; +} +/** + * radeon_vm_add_to_lru - add VMs page table to LRU list + * + * @rdev: radeon_device pointer + * @vm: vm to add to LRU + * + * Add the allocated page table to the LRU list (cayman+). + * + * Global mutex must be locked! + */ +void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm) +{ + list_del_init(&vm->list); list_add_tail(&vm->list, &rdev->vm_manager.lru_vm); - return radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo, - &rdev->ring_tmp_bo.bo->tbo.mem); } /** @@ -793,20 +856,6 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, } mutex_lock(&vm->mutex); - if (last_pfn > vm->last_pfn) { - /* release mutex and lock in right order */ - mutex_unlock(&vm->mutex); - mutex_lock(&rdev->vm_manager.lock); - mutex_lock(&vm->mutex); - /* and check again */ - if (last_pfn > vm->last_pfn) { - /* grow va space 32M by 32M */ - unsigned align = ((32 << 20) >> 12) - 1; - radeon_vm_free_pt(rdev, vm); - vm->last_pfn = (last_pfn + align) & ~align; - } - mutex_unlock(&rdev->vm_manager.lock); - } head = &vm->va; last_offset = 0; list_for_each_entry(tmp, &vm->va, vm_list) { @@ -865,6 +914,154 @@ uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr) } /** + * radeon_vm_update_pdes - make sure that page directory is valid + * + * @rdev: radeon_device pointer + * @vm: requested vm + * @start: start of GPU address range + * @end: end of GPU address range + * + * Allocates new page tables if necessary + * and updates the page directory (cayman+). + * Returns 0 for success, error for failure. + * + * Global and local mutex must be locked! + */ +static int radeon_vm_update_pdes(struct radeon_device *rdev, + struct radeon_vm *vm, + uint64_t start, uint64_t end) +{ + static const uint32_t incr = RADEON_VM_PTE_COUNT * 8; + + uint64_t last_pde = ~0, last_pt = ~0; + unsigned count = 0; + uint64_t pt_idx; + int r; + + start = (start / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE; + end = (end / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE; + + /* walk over the address space and update the page directory */ + for (pt_idx = start; pt_idx <= end; ++pt_idx) { + uint64_t pde, pt; + + if (vm->page_tables[pt_idx]) + continue; + +retry: + r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, + &vm->page_tables[pt_idx], + RADEON_VM_PTE_COUNT * 8, + RADEON_GPU_PAGE_SIZE, false); + + if (r == -ENOMEM) { + r = radeon_vm_evict(rdev, vm); + if (r) + return r; + goto retry; + } else if (r) { + return r; + } + + pde = vm->pd_gpu_addr + pt_idx * 8; + + pt = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]); + + if (((last_pde + 8 * count) != pde) || + ((last_pt + incr * count) != pt)) { + + if (count) { + radeon_asic_vm_set_page(rdev, last_pde, + last_pt, count, incr, + RADEON_VM_PAGE_VALID); + } + + count = 1; + last_pde = pde; + last_pt = pt; + } else { + ++count; + } + } + + if (count) { + radeon_asic_vm_set_page(rdev, last_pde, last_pt, count, + incr, RADEON_VM_PAGE_VALID); + + } + + return 0; +} + +/** + * radeon_vm_update_ptes - make sure that page tables are valid + * + * @rdev: radeon_device pointer + * @vm: requested vm + * @start: start of GPU address range + * @end: end of GPU address range + * @dst: destination address to map to + * @flags: mapping flags + * + * Update the page tables in the range @start - @end (cayman+). + * + * Global and local mutex must be locked! + */ +static void radeon_vm_update_ptes(struct radeon_device *rdev, + struct radeon_vm *vm, + uint64_t start, uint64_t end, + uint64_t dst, uint32_t flags) +{ + static const uint64_t mask = RADEON_VM_PTE_COUNT - 1; + + uint64_t last_pte = ~0, last_dst = ~0; + unsigned count = 0; + uint64_t addr; + + start = start / RADEON_GPU_PAGE_SIZE; + end = end / RADEON_GPU_PAGE_SIZE; + + /* walk over the address space and update the page tables */ + for (addr = start; addr < end; ) { + uint64_t pt_idx = addr >> RADEON_VM_BLOCK_SIZE; + unsigned nptes; + uint64_t pte; + + if ((addr & ~mask) == (end & ~mask)) + nptes = end - addr; + else + nptes = RADEON_VM_PTE_COUNT - (addr & mask); + + pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]); + pte += (addr & mask) * 8; + + if ((last_pte + 8 * count) != pte) { + + if (count) { + radeon_asic_vm_set_page(rdev, last_pte, + last_dst, count, + RADEON_GPU_PAGE_SIZE, + flags); + } + + count = nptes; + last_pte = pte; + last_dst = dst; + } else { + count += nptes; + } + + addr += nptes; + dst += nptes * RADEON_GPU_PAGE_SIZE; + } + + if (count) { + radeon_asic_vm_set_page(rdev, last_pte, last_dst, count, + RADEON_GPU_PAGE_SIZE, flags); + } +} + +/** * radeon_vm_bo_update_pte - map a bo into the vm page table * * @rdev: radeon_device pointer @@ -887,12 +1084,11 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, struct radeon_semaphore *sem = NULL; struct radeon_bo_va *bo_va; unsigned nptes, npdes, ndw; - uint64_t pe, addr; - uint64_t pfn; + uint64_t addr; int r; /* nothing to do if vm isn't bound */ - if (vm->sa_bo == NULL) + if (vm->page_directory == NULL) return 0; bo_va = radeon_vm_bo_find(vm, bo); @@ -939,25 +1135,29 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, } } - /* estimate number of dw needed */ - /* reserve space for 32-bit padding */ - ndw = 32; - nptes = radeon_bo_ngpu_pages(bo); - pfn = (bo_va->soffset / RADEON_GPU_PAGE_SIZE); + /* assume two extra pdes in case the mapping overlaps the borders */ + npdes = (nptes >> RADEON_VM_BLOCK_SIZE) + 2; - /* handle cases where a bo spans several pdes */ - npdes = (ALIGN(pfn + nptes, RADEON_VM_PTE_COUNT) - - (pfn & ~(RADEON_VM_PTE_COUNT - 1))) >> RADEON_VM_BLOCK_SIZE; + /* estimate number of dw needed */ + /* semaphore, fence and padding */ + ndw = 32; + + if (RADEON_VM_BLOCK_SIZE > 11) + /* reserve space for one header for every 2k dwords */ + ndw += (nptes >> 11) * 4; + else + /* reserve space for one header for + every (1 << BLOCK_SIZE) entries */ + ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4; - /* reserve space for one header for every 2k dwords */ - ndw += (nptes >> 11) * 3; /* reserve space for pte addresses */ ndw += nptes * 2; /* reserve space for one header for every 2k dwords */ - ndw += (npdes >> 11) * 3; + ndw += (npdes >> 11) * 4; + /* reserve space for pde addresses */ ndw += npdes * 2; @@ -971,22 +1171,14 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, radeon_fence_note_sync(vm->fence, ridx); } - /* update page table entries */ - pe = vm->pd_gpu_addr; - pe += radeon_vm_directory_size(rdev); - pe += (bo_va->soffset / RADEON_GPU_PAGE_SIZE) * 8; - - radeon_asic_vm_set_page(rdev, pe, addr, nptes, - RADEON_GPU_PAGE_SIZE, bo_va->flags); - - /* update page directory entries */ - addr = pe; - - pe = vm->pd_gpu_addr; - pe += ((bo_va->soffset / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE) * 8; + r = radeon_vm_update_pdes(rdev, vm, bo_va->soffset, bo_va->eoffset); + if (r) { + radeon_ring_unlock_undo(rdev, ring); + return r; + } - radeon_asic_vm_set_page(rdev, pe, addr, npdes, - RADEON_VM_PTE_COUNT * 8, RADEON_VM_PAGE_VALID); + radeon_vm_update_ptes(rdev, vm, bo_va->soffset, bo_va->eoffset, + addr, bo_va->flags); radeon_fence_unref(&vm->fence); r = radeon_fence_emit(rdev, &vm->fence, ridx); @@ -997,6 +1189,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev, radeon_ring_unlock_commit(rdev, ring); radeon_semaphore_free(rdev, &sem, vm->fence); radeon_fence_unref(&vm->last_flush); + return 0; } @@ -1056,31 +1249,15 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, * @rdev: radeon_device pointer * @vm: requested vm * - * Init @vm (cayman+). - * Map the IB pool and any other shared objects into the VM - * by default as it's used by all VMs. - * Returns 0 for success, error for failure. + * Init @vm fields (cayman+). */ -int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) +void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) { - struct radeon_bo_va *bo_va; - int r; - vm->id = 0; vm->fence = NULL; - vm->last_pfn = 0; mutex_init(&vm->mutex); INIT_LIST_HEAD(&vm->list); INIT_LIST_HEAD(&vm->va); - - /* map the ib pool buffer at 0 in virtual address space, set - * read only - */ - bo_va = radeon_vm_bo_add(rdev, vm, rdev->ring_tmp_bo.bo); - r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, - RADEON_VM_PAGE_READABLE | - RADEON_VM_PAGE_SNOOPED); - return r; } /** @@ -1102,17 +1279,6 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) radeon_vm_free_pt(rdev, vm); mutex_unlock(&rdev->vm_manager.lock); - /* 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_vm_bo_find(vm, rdev->ring_tmp_bo.bo); - list_del_init(&bo_va->bo_list); - list_del_init(&bo_va->vm_list); - radeon_bo_unreserve(rdev->ring_tmp_bo.bo); - kfree(bo_va); - } if (!list_empty(&vm->va)) { dev_err(rdev->dev, "still active bo inside vm\n"); } diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index f38fbcc4693..fe5c1f6b795 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -53,6 +53,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, struct drm_gem_object **obj) { struct radeon_bo *robj; + unsigned long max_size; int r; *obj = NULL; @@ -60,11 +61,26 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size, if (alignment < PAGE_SIZE) { alignment = PAGE_SIZE; } + + /* maximun bo size is the minimun btw visible vram and gtt size */ + max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); + if (size > max_size) { + printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n", + __func__, __LINE__, size >> 20, max_size >> 20); + return -ENOMEM; + } + +retry: r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj); if (r) { - if (r != -ERESTARTSYS) + if (r != -ERESTARTSYS) { + if (initial_domain == RADEON_GEM_DOMAIN_VRAM) { + initial_domain |= RADEON_GEM_DOMAIN_GTT; + goto retry; + } DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n", size, initial_domain, alignment, r); + } return r; } *obj = &robj->gem_base; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 83b8d8aa71c..dc781c49b96 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -419,6 +419,7 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN) { struct radeon_fpriv *fpriv; + struct radeon_bo_va *bo_va; int r; fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); @@ -426,7 +427,15 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) return -ENOMEM; } - r = radeon_vm_init(rdev, &fpriv->vm); + radeon_vm_init(rdev, &fpriv->vm); + + /* map the ib pool buffer read only into + * virtual address space */ + bo_va = radeon_vm_bo_add(rdev, &fpriv->vm, + rdev->ring_tmp_bo.bo); + r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET, + RADEON_VM_PAGE_READABLE | + RADEON_VM_PAGE_SNOOPED); if (r) { radeon_vm_fini(rdev, &fpriv->vm); kfree(fpriv); @@ -454,6 +463,17 @@ void radeon_driver_postclose_kms(struct drm_device *dev, /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) { struct radeon_fpriv *fpriv = file_priv->driver_priv; + struct radeon_bo_va *bo_va; + int r; + + r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); + if (!r) { + bo_va = radeon_vm_bo_find(&fpriv->vm, + rdev->ring_tmp_bo.bo); + if (bo_va) + radeon_vm_bo_rmv(rdev, bo_va); + radeon_bo_unreserve(rdev->ring_tmp_bo.bo); + } radeon_vm_fini(rdev, &fpriv->vm); kfree(fpriv); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 5677a424b58..6857cb4efb7 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + uint32_t crtc_ext_cntl = 0; uint32_t mask; if (radeon_crtc->crtc_id) @@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS); + /* + * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC. + * Therefore it is set in the DAC DMPS function. + * This is different for GPU's with a single CRTC but a primary and a + * TV DAC: here it controls the single CRTC no matter where it is + * routed. Therefore we set it here. + */ + if (rdev->flags & RADEON_SINGLE_CRTC) + crtc_ext_cntl = RADEON_CRTC_CRT_ON; + switch (mode) { case DRM_MODE_DPMS_ON: radeon_crtc->enabled = true; @@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); - WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); + WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl)); } drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); radeon_crtc_load_lut(crtc); @@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); - WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); + WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl)); } radeon_crtc->enabled = false; /* adjust pm to dpms changes AFTER disabling crtcs */ diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 92487e61477..f5ba2241dac 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -269,27 +269,6 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = { .disable = radeon_legacy_encoder_disable, }; -#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) - -static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd) -{ - struct radeon_backlight_privdata *pdata = bl_get_data(bd); - uint8_t level; - - /* Convert brightness to hardware level */ - if (bd->props.brightness < 0) - level = 0; - else if (bd->props.brightness > RADEON_MAX_BL_LEVEL) - level = RADEON_MAX_BL_LEVEL; - else - level = bd->props.brightness; - - if (pdata->negative) - level = RADEON_MAX_BL_LEVEL - level; - - return level; -} - u8 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder) { @@ -331,6 +310,27 @@ radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 leve radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode); } +#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) + +static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd) +{ + struct radeon_backlight_privdata *pdata = bl_get_data(bd); + uint8_t level; + + /* Convert brightness to hardware level */ + if (bd->props.brightness < 0) + level = 0; + else if (bd->props.brightness > RADEON_MAX_BL_LEVEL) + level = RADEON_MAX_BL_LEVEL; + else + level = bd->props.brightness; + + if (pdata->negative) + level = RADEON_MAX_BL_LEVEL - level; + + return level; +} + static int radeon_legacy_backlight_update_status(struct backlight_device *bd) { struct radeon_backlight_privdata *pdata = bl_get_data(bd); @@ -370,6 +370,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, struct backlight_properties props; struct radeon_backlight_privdata *pdata; uint8_t backlight_level; + char bl_name[16]; if (!radeon_encoder->enc_priv) return; @@ -389,7 +390,9 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, memset(&props, 0, sizeof(props)); props.max_brightness = RADEON_MAX_BL_LEVEL; props.type = BACKLIGHT_RAW; - bd = backlight_device_register("radeon_bl", &drm_connector->kdev, + snprintf(bl_name, sizeof(bl_name), + "radeon_bl%d", dev->primary->index); + bd = backlight_device_register(bl_name, &drm_connector->kdev, pdata, &radeon_backlight_ops, &props); if (IS_ERR(bd)) { DRM_ERROR("Backlight registration failed\n"); @@ -534,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode break; } - WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + /* handled in radeon_crtc_dpms() */ + if (!(rdev->flags & RADEON_SINGLE_CRTC)) + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); WREG32(RADEON_DAC_CNTL, dac_cntl); WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); @@ -659,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc if (ASIC_IS_R300(rdev)) tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else if (ASIC_IS_RV100(rdev)) + tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT); else tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); @@ -668,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; WREG32(RADEON_DAC_CNTL, tmp); + tmp = dac_macro_cntl; tmp &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B); @@ -991,11 +999,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; - if (tmds) { - if (tmds->i2c_bus) - radeon_i2c_destroy(tmds->i2c_bus); - } + /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */ kfree(radeon_encoder->enc_priv); drm_encoder_cleanup(encoder); kfree(radeon_encoder); @@ -1093,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) } else { if (is_tv) WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); - else + /* handled in radeon_crtc_dpms() */ + else if (!(rdev->flags & RADEON_SINGLE_CRTC)) WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); } @@ -1417,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder, return found; } +static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; + uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; + uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; + uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; + uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; + bool found = false; + int i; + + /* save the regs we need */ + gpio_monid = RREG32(RADEON_GPIO_MONID); + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A); + disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B); + disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C); + disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D); + disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E); + disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F); + crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP); + crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP); + crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID); + crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID); + + tmp = RREG32(RADEON_GPIO_MONID); + tmp &= ~RADEON_GPIO_A_0; + WREG32(RADEON_GPIO_MONID, tmp); + + WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON | + RADEON_FP2_PANEL_FORMAT | + R200_FP2_SOURCE_SEL_TRANS_UNIT | + RADEON_FP2_DVO_EN | + R200_FP2_DVO_RATE_SEL_SDR)); + + WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX | + RADEON_DISP_TRANS_MATRIX_GRAPHICS)); + + WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN | + RADEON_CRTC2_DISP_REQ_EN_B)); + + WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + + WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + tmp = RREG32(RADEON_GPIO_MONID); + if (tmp & RADEON_GPIO_Y_0) + found = true; + + if (found) + break; + + if (!drm_can_sleep()) + mdelay(1); + else + msleep(1); + } + + /* restore the regs we used */ + WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); + WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); + WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); + WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); + WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + WREG32(RADEON_GPIO_MONID, gpio_monid); + + return found; +} + static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; - uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; - uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; + uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl; + uint32_t gpiopad_a = 0, pixclks_cntl, tmp; + uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0; enum drm_connector_status found = connector_status_disconnected; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; @@ -1460,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder return connector_status_disconnected; } + /* R200 uses an external DAC for secondary DAC */ + if (rdev->family == CHIP_R200) { + if (radeon_legacy_ext_dac_detect(encoder, connector)) + found = connector_status_connected; + return found; + } + /* save the regs we need */ pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); - gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0; - disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0; - disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG); - crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + + if (rdev->flags & RADEON_SINGLE_CRTC) { + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + } else { + if (ASIC_IS_R300(rdev)) { + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + } else { + disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); + } + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + } tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); dac_cntl2 = RREG32(RADEON_DAC_CNTL2); @@ -1474,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder | RADEON_PIX2CLK_DAC_ALWAYS_ONb); WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); - if (ASIC_IS_R300(rdev)) - WREG32_P(RADEON_GPIOPAD_A, 1, ~1); - - tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; - tmp |= RADEON_CRTC2_CRT2_ON | - (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); - - WREG32(RADEON_CRTC2_GEN_CNTL, tmp); - - if (ASIC_IS_R300(rdev)) { - tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; - tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; - WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); + if (rdev->flags & RADEON_SINGLE_CRTC) { + tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; + WREG32(RADEON_CRTC_EXT_CNTL, tmp); } else { - tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; - WREG32(RADEON_DISP_HW_DEBUG, tmp); + tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; + tmp |= RADEON_CRTC2_CRT2_ON | + (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); + WREG32(RADEON_CRTC2_GEN_CNTL, tmp); + + if (ASIC_IS_R300(rdev)) { + WREG32_P(RADEON_GPIOPAD_A, 1, ~1); + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); + } else { + tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; + WREG32(RADEON_DISP_HW_DEBUG, tmp); + } } tmp = RADEON_TV_DAC_NBLANK | @@ -1531,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder WREG32(RADEON_DAC_CNTL2, dac_cntl2); WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); - WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); - if (ASIC_IS_R300(rdev)) { - WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); - WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); + if (rdev->flags & RADEON_SINGLE_CRTC) { + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); } else { - WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + if (ASIC_IS_R300(rdev)) { + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); + } else { + WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); + } } + WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); return found; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 8b27dd6e314..b91118ccef8 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -105,7 +105,6 @@ int radeon_bo_create(struct radeon_device *rdev, struct radeon_bo *bo; enum ttm_bo_type type; unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT; - unsigned long max_size = 0; size_t acc_size; int r; @@ -121,18 +120,9 @@ int radeon_bo_create(struct radeon_device *rdev, } *bo_ptr = NULL; - /* maximun bo size is the minimun btw visible vram and gtt size */ - max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size); - if ((page_align << PAGE_SHIFT) >= max_size) { - printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n", - __func__, __LINE__, page_align >> (20 - PAGE_SHIFT), max_size >> 20); - return -ENOMEM; - } - 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; @@ -154,15 +144,6 @@ retry: acc_size, sg, &radeon_ttm_bo_destroy); up_read(&rdev->pm.mclk_lock); if (unlikely(r != 0)) { - if (r != -ERESTARTSYS) { - if (domain == RADEON_GEM_DOMAIN_VRAM) { - domain |= RADEON_GEM_DOMAIN_GTT; - goto retry; - } - dev_err(rdev->dev, - "object_init failed for (%lu, 0x%08X)\n", - size, domain); - } return r; } *bo_ptr = bo; diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index bba66902c83..47634f27f2e 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -305,7 +305,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v) { #if DRM_DEBUG_CODE if (ring->count_dw <= 0) { - DRM_ERROR("radeon: writting more dword to ring than expected !\n"); + DRM_ERROR("radeon: writing more dwords to the ring than expected!\n"); } #endif ring->ring[ring->wptr++] = v; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index f79633a036c..4422d630b33 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2407,12 +2407,13 @@ static int si_pcie_gart_enable(struct radeon_device *rdev) WREG32(0x15DC, 0); /* empty context1-15 */ - /* FIXME start with 4G, once using 2 level pt switch to full - * vm size space - */ /* set vm size, must be a multiple of 4 */ WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); + /* Assign the pt base to something valid for now; the pts used for + * the VMs are determined by the application and setup and assigned + * on the fly in the vm part of radeon_gart.c + */ for (i = 1; i < 16; i++) { if (i < 8) WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), @@ -2473,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_ESGS_RING_SIZE: @@ -2807,26 +2809,31 @@ void si_vm_set_page(struct radeon_device *rdev, uint64_t pe, { struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index]; uint32_t r600_flags = cayman_vm_page_flags(rdev, flags); - int i; - uint64_t value; - radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 2 + count * 2)); - radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | - WRITE_DATA_DST_SEL(1))); - radeon_ring_write(ring, pe); - radeon_ring_write(ring, upper_32_bits(pe)); - for (i = 0; i < count; ++i) { - if (flags & RADEON_VM_PAGE_SYSTEM) { - value = radeon_vm_map_gart(rdev, addr); - value &= 0xFFFFFFFFFFFFF000ULL; - } else if (flags & RADEON_VM_PAGE_VALID) - value = addr; - else - value = 0; - addr += incr; - value |= r600_flags; - radeon_ring_write(ring, value); - radeon_ring_write(ring, upper_32_bits(value)); + while (count) { + unsigned ndw = 2 + count * 2; + if (ndw > 0x3FFE) + ndw = 0x3FFE; + + radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, ndw)); + radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | + WRITE_DATA_DST_SEL(1))); + radeon_ring_write(ring, pe); + radeon_ring_write(ring, upper_32_bits(pe)); + for (; ndw > 2; ndw -= 2, --count, pe += 8) { + uint64_t value; + if (flags & RADEON_VM_PAGE_SYSTEM) { + value = radeon_vm_map_gart(rdev, addr); + value &= 0xFFFFFFFFFFFFF000ULL; + } else if (flags & RADEON_VM_PAGE_VALID) + value = addr; + else + value = 0; + addr += incr; + value |= r600_flags; + radeon_ring_write(ring, value); + radeon_ring_write(ring, upper_32_bits(value)); + } } } @@ -2867,6 +2874,10 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); radeon_ring_write(ring, 0); radeon_ring_write(ring, 1 << vm->id); + + /* sync PFP to ME, otherwise we might get invalid PFP reads */ + radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); + radeon_ring_write(ring, 0x0); } /* diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 7d2a20e5657..a8871afc5b4 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -424,6 +424,7 @@ # define RDERR_INT_ENABLE (1 << 0) # define GUI_IDLE_INT_ENABLE (1 << 19) +#define CP_STRMOUT_CNTL 0x84FC #define SCRATCH_REG0 0x8500 #define SCRATCH_REG1 0x8504 #define SCRATCH_REG2 0x8508 diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index c71d493fd0c..1c350fc4e44 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -201,6 +201,8 @@ static int shmob_drm_load(struct drm_device *dev, unsigned long flags) goto done; } + platform_set_drvdata(pdev, sdev); + done: if (ret) shmob_drm_unload(dev); @@ -299,11 +301,9 @@ static struct drm_driver shmob_drm_driver = { #if CONFIG_PM_SLEEP static int shmob_drm_pm_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct drm_device *ddev = platform_get_drvdata(pdev); - struct shmob_drm_device *sdev = ddev->dev_private; + struct shmob_drm_device *sdev = dev_get_drvdata(dev); - drm_kms_helper_poll_disable(ddev); + drm_kms_helper_poll_disable(sdev->ddev); shmob_drm_crtc_suspend(&sdev->crtc); return 0; @@ -311,9 +311,7 @@ static int shmob_drm_pm_suspend(struct device *dev) static int shmob_drm_pm_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct drm_device *ddev = platform_get_drvdata(pdev); - struct shmob_drm_device *sdev = ddev->dev_private; + struct shmob_drm_device *sdev = dev_get_drvdata(dev); mutex_lock(&sdev->ddev->mode_config.mutex); shmob_drm_crtc_resume(&sdev->crtc); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 402ab69f9f9..bf6e4b5a73b 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -580,6 +580,7 @@ retry: if (unlikely(ret != 0)) return ret; +retry_reserve: spin_lock(&glob->lru_lock); if (unlikely(list_empty(&bo->ddestroy))) { @@ -587,14 +588,20 @@ retry: return 0; } - ret = ttm_bo_reserve_locked(bo, interruptible, - no_wait_reserve, false, 0); + ret = ttm_bo_reserve_locked(bo, false, true, false, 0); - if (unlikely(ret != 0)) { + if (unlikely(ret == -EBUSY)) { spin_unlock(&glob->lru_lock); - return ret; + if (likely(!no_wait_reserve)) + ret = ttm_bo_wait_unreserved(bo, interruptible); + if (unlikely(ret != 0)) + return ret; + + goto retry_reserve; } + BUG_ON(ret != 0); + /** * We can re-check for sync object without taking * the bo::lock since setting the sync object requires @@ -811,17 +818,14 @@ retry: no_wait_reserve, no_wait_gpu); kref_put(&bo->list_kref, ttm_bo_release_list); - if (likely(ret == 0 || ret == -ERESTARTSYS)) - return ret; - - goto retry; + return ret; } - ret = ttm_bo_reserve_locked(bo, false, no_wait_reserve, false, 0); + ret = ttm_bo_reserve_locked(bo, false, true, false, 0); if (unlikely(ret == -EBUSY)) { spin_unlock(&glob->lru_lock); - if (likely(!no_wait_gpu)) + if (likely(!no_wait_reserve)) ret = ttm_bo_wait_unreserved(bo, interruptible); kref_put(&bo->list_kref, ttm_bo_release_list); diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 860dc4813e9..bd2a3b40cd1 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags, /* clear the pages coming from the pool if requested */ if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { list_for_each_entry(p, &plist, lru) { - clear_page(page_address(p)); + if (PageHighMem(p)) + clear_highpage(p); + else + clear_page(page_address(p)); } } diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index bf8260133ea..7d759a43029 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -308,9 +308,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm) if (unlikely(to_page == NULL)) goto out_err; - preempt_disable(); copy_highpage(to_page, from_page); - preempt_enable(); page_cache_release(from_page); } @@ -358,9 +356,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) ret = PTR_ERR(to_page); goto out_err; } - preempt_disable(); copy_highpage(to_page, from_page); - preempt_enable(); set_page_dirty(to_page); mark_page_accessed(to_page); page_cache_release(to_page); diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index fccd361f7b5..87aa5f5d3c8 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev, int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, u32 byte_width, int *ident_ptr, int *sent_ptr); int udl_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 69a2b16f42a..d4ab3beaada 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info, list_for_each_entry(cur, &fbdefio->pagelist, lru) { if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), - &urb, (char *) info->fix.smem_start, - &cmd, cur->index << PAGE_SHIFT, - PAGE_SIZE, &bytes_identical, &bytes_sent)) + &urb, (char *) info->fix.smem_start, + &cmd, cur->index << PAGE_SHIFT, + cur->index << PAGE_SHIFT, + PAGE_SIZE, &bytes_identical, &bytes_sent)) goto error; bytes_rendered += PAGE_SIZE; } @@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, for (i = y; i < y + height ; i++) { const int line_offset = fb->base.pitches[0] * i; const int byte_offset = line_offset + (x * bpp); - + const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); if (udl_render_hline(dev, bpp, &urb, (char *) fb->obj->vmapping, - &cmd, byte_offset, width * bpp, + &cmd, byte_offset, dev_byte_offset, + width * bpp, &bytes_identical, &bytes_sent)) goto error; } diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index dc095526ffb..142fee5f983 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -213,11 +213,12 @@ static void udl_compress_hline16( */ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, + u32 byte_width, int *ident_ptr, int *sent_ptr) { const u8 *line_start, *line_end, *next_pixel; - u32 base16 = 0 + (byte_offset / bpp) * 2; + u32 base16 = 0 + (device_byte_offset / bpp) * 2; struct urb *urb = *urb_ptr; u8 *cmd = *urb_buf_ptr; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c index 3ce68a2e312..d1498bfd787 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c @@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) BUG_ON(!atomic_read(&bo->reserved)); BUG_ON(old_mem_type != TTM_PL_VRAM && - old_mem_type != VMW_PL_FLAG_GMR); + old_mem_type != VMW_PL_GMR); pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; if (pin) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ed3c1e7ddde..2dd185e42f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev) struct drm_device *dev = pci_get_drvdata(pdev); struct vmw_private *dev_priv = vmw_priv(dev); + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); + (void) vmw_read(dev_priv, SVGA_REG_ID); + mutex_unlock(&dev_priv->hw_mutex); + /** * Reclaim 3d reference held by fbdev and potentially * start fifo. diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index b07ca2e4d04..7290811f89b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -110,6 +110,8 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size); ret = copy_to_user(buffer, bounce, size); + if (ret) + ret = -EFAULT; vfree(bounce); if (unlikely(ret != 0)) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 06ebdbb6ea0..fd7722aecf7 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index bd3971bf31b..f4109fd657f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 269b50912a4..9d7a42857ea 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -118,6 +118,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 3acdcfcc17d..6fcd466d082 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -28,22 +28,30 @@ #define MS_RDESC 0x08 #define MS_NOGET 0x10 #define MS_DUPLICATE_USAGES 0x20 +#define MS_RDESC_3K 0x40 -/* - * Microsoft Wireless Desktop Receiver (Model 1028) has - * 'Usage Min/Max' where it ought to have 'Physical Min/Max' - */ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + /* + * Microsoft Wireless Desktop Receiver (Model 1028) has + * 'Usage Min/Max' where it ought to have 'Physical Min/Max' + */ if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && rdesc[559] == 0x29) { hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); rdesc[557] = 0x35; rdesc[559] = 0x45; } + /* the same as above (s/usage/physical/) */ + if ((quirks & MS_RDESC_3K) && *rsize == 106 && rdesc[94] == 0x19 && + rdesc[95] == 0x00 && rdesc[96] == 0x29 && + rdesc[97] == 0xff) { + rdesc[94] = 0x35; + rdesc[96] = 0x45; + } return rdesc; } @@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), .driver_data = MS_PRESENTER }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), - .driver_data = MS_ERGONOMY }, + .driver_data = MS_ERGONOMY | MS_RDESC_3K }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 3eb02b94fc8..7867d69f0ef 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = { }, { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | - MT_QUIRK_SLOT_IS_CONTACTNUMBER, - .maxcontacts = 10 + MT_QUIRK_SLOT_IS_CONTACTNUMBER }, { .name = MT_CLS_FLATFROG, @@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, * contact max are global to the report */ td->last_field_index = field->index; return -1; - } case HID_DG_TOUCH: /* Legacy devices use TIPSWITCH and not TOUCH. * Let's just ignore this field. */ return -1; + } /* let hid-input decide for the others */ return 0; diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 17d15bb610d..7c47fc3f7b2 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -42,7 +42,6 @@ static struct cdev hidraw_cdev; static struct class *hidraw_class; static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; static DEFINE_MUTEX(minors_lock); -static void drop_ref(struct hidraw *hid, int exists_bit); static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { @@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, __u8 *buf; int ret = 0; - if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { + if (!hidraw_table[minor]) { ret = -ENODEV; goto out; } @@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file) } mutex_lock(&minors_lock); - if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { + if (!hidraw_table[minor]) { err = -ENODEV; goto out_unlock; } @@ -299,12 +298,36 @@ out: static int hidraw_release(struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); + struct hidraw *dev; struct hidraw_list *list = file->private_data; + int ret; + int i; + + mutex_lock(&minors_lock); + if (!hidraw_table[minor]) { + ret = -ENODEV; + goto unlock; + } - drop_ref(hidraw_table[minor], 0); list_del(&list->node); + dev = hidraw_table[minor]; + if (!--dev->open) { + if (list->hidraw->exist) { + hid_hw_power(dev->hid, PM_HINT_NORMAL); + hid_hw_close(dev->hid); + } else { + kfree(list->hidraw); + } + } + + for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i) + kfree(list->buffer[i].value); kfree(list); - return 0; + ret = 0; +unlock: + mutex_unlock(&minors_lock); + + return ret; } static long hidraw_ioctl(struct file *file, unsigned int cmd, @@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect); void hidraw_disconnect(struct hid_device *hid) { struct hidraw *hidraw = hid->hidraw; - drop_ref(hidraw, 1); + + mutex_lock(&minors_lock); + hidraw->exist = 0; + + device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); + + hidraw_table[hidraw->minor] = NULL; + + if (hidraw->open) { + hid_hw_close(hid); + wake_up_interruptible(&hidraw->wait); + } else { + kfree(hidraw); + } + mutex_unlock(&minors_lock); } EXPORT_SYMBOL_GPL(hidraw_disconnect); @@ -555,23 +592,3 @@ void hidraw_exit(void) unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); } - -static void drop_ref(struct hidraw *hidraw, int exists_bit) -{ - mutex_lock(&minors_lock); - if (exists_bit) { - hid_hw_close(hidraw->hid); - hidraw->exist = 0; - if (hidraw->open) - wake_up_interruptible(&hidraw->wait); - } else { - --hidraw->open; - } - - if (!hidraw->open && !hidraw->exist) { - device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); - hidraw_table[hidraw->minor] = NULL; - kfree(hidraw); - } - mutex_unlock(&minors_lock); -} diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 406537420ff..f4c3d28cd1f 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } ret = hv_ringbuffer_init( &newchannel->inbound, in, recv_ringbuffer_size); if (ret != 0) { err = ret; - goto errorout; + goto error0; } @@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } /* Create and init the channel open message */ @@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, GFP_KERNEL); if (!open_info) { err = -ENOMEM; - goto errorout; + goto error0; } init_completion(&open_info->waitevent); @@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (userdatalen > MAX_USER_DEFINED_BYTES) { err = -EINVAL; - goto errorout; + goto error0; } if (userdatalen) @@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, sizeof(struct vmbus_channel_open_channel)); if (ret != 0) - goto cleanup; + goto error1; t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); if (t == 0) { err = -ETIMEDOUT; - goto errorout; + goto error1; } if (open_info->response.open_result.status) err = open_info->response.open_result.status; -cleanup: spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&open_info->msglistentry); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); @@ -228,9 +227,12 @@ cleanup: kfree(open_info); return err; -errorout: - hv_ringbuffer_cleanup(&newchannel->outbound); - hv_ringbuffer_cleanup(&newchannel->inbound); +error1: + spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); + list_del(&open_info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + +error0: free_pages((unsigned long)out, get_order(send_ringbuffer_size + recv_ringbuffer_size)); kfree(open_info); diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index a227be47149..520e5bf4f76 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -32,7 +32,7 @@ * ASB100-A supports pwm1, while plain ASB100 does not. There is no known * way for the driver to tell which one is there. * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * asb100 7 3 1 4 0x31 0x0694 yes no */ diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 984a3f13923..47b8d84b489 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -205,8 +205,11 @@ static const struct tjmax __cpuinitconst tjmax_table[] = { { "CPU N455", 100000 }, { "CPU N470", 100000 }, { "CPU N475", 100000 }, - { "CPU 230", 100000 }, - { "CPU 330", 125000 }, + { "CPU 230", 100000 }, /* Model 0x1c, stepping 2 */ + { "CPU 330", 125000 }, /* Model 0x1c, stepping 2 */ + { "CPU CE4110", 110000 }, /* Model 0x1c, stepping 10 */ + { "CPU CE4150", 110000 }, /* Model 0x1c, stepping 10 */ + { "CPU CE4170", 110000 }, /* Model 0x1c, stepping 10 */ }; static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 68ad7d25551..4f411040738 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -2,7 +2,7 @@ * fam15h_power.c - AMD Family 15h processor power monitoring * * Copyright (c) 2011 Advanced Micro Devices, Inc. - * Author: Andreas Herrmann <andreas.herrmann3@amd.com> + * Author: Andreas Herrmann <herrmann.der.user@googlemail.com> * * * This driver is free software; you can redistribute it and/or @@ -28,7 +28,7 @@ #include <asm/processor.h> MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); -MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>"); +MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>"); MODULE_LICENSE("GPL"); /* D18F3 */ diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 36509ae3208..1381a2e3bbd 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = { .driver = { .name = "gpio-fan", .pm = GPIO_FAN_PM, +#ifdef CONFIG_OF_GPIO .of_match_table = of_match_ptr(of_gpio_fan_match), +#endif }, }; diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 2ca6a5a4f5a..60745a53582 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -4,7 +4,7 @@ menuconfig PMBUS tristate "PMBus support" - depends on I2C && EXPERIMENTAL + depends on I2C default n help Say yes here if you want to enable PMBus support. diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 1821b7423d5..de3c7e04c3b 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) mutex_init(&data->lock); mutex_init(&data->update_lock); data->name = w83627ehf_device_names[sio_data->kind]; + data->bank = 0xff; /* Force initial bank selection */ platform_set_drvdata(pdev, data); /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 5b1a6a66644..af158990870 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -25,7 +25,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) * w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) * w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 5a5046d94c3..20f11d31da4 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -24,7 +24,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * as99127f 7 3 0 3 0x31 0x12c3 yes no * as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no * w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 39ab7bcc616..ed397c64519 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -22,7 +22,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83791d 10 5 5 3 0x71 0x5ca3 yes no * * The w83791d chip appears to be part way between the 83781d and the diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 053645279f3..301942d0845 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -31,7 +31,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83792d 9 7 7 3 0x7a 0x5ca3 yes no */ diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index f0e8286c3c7..79710bcac2f 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -20,7 +20,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no */ diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index beee6b2d361..1722f50f247 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-y += algos/ busses/ muxes/ +obj-$(CONFIG_I2C_STUB) += i2c-stub.o ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG CFLAGS_i2c-core.o := -Wno-deprecated-declarations diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 65dd599a026..e9df4612b7e 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -81,7 +81,6 @@ config I2C_I801 tristate "Intel 82801 (ICH/PCH)" depends on PCI select CHECK_SIGNATURE if X86 && DMI - select GPIOLIB if I2C_MUX help If you say yes to this option, support will be included for the Intel 801 family of mainboard I2C interfaces. Specifically, the following diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 2d33d62952c..395b516ffa0 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o -obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index aa59a254be2..c02bf208084 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -39,6 +39,7 @@ #define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */ #define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */ #define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */ +#define AT91_TWI_QUICK 0x0040 /* SMBus quick command */ #define AT91_TWI_SWRST 0x0080 /* Software Reset */ #define AT91_TWI_MMR 0x0004 /* Master Mode Register */ @@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) INIT_COMPLETION(dev->cmd_complete); dev->transfer_status = 0; - if (dev->msg->flags & I2C_M_RD) { + + if (!dev->buf_len) { + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK); + at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + } else if (dev->msg->flags & I2C_M_RD) { unsigned start_flags = AT91_TWI_START; if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) { diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 37793156bd9..6abc00d5988 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -82,7 +82,8 @@ #include <linux/wait.h> #include <linux/err.h> -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI #include <linux/gpio.h> #include <linux/i2c-mux-gpio.h> #include <linux/platform_device.h> @@ -192,7 +193,8 @@ struct i801_priv { int len; u8 *data; -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI const struct i801_mux_config *mux_drvdata; struct platform_device *mux_pdev; #endif @@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {} static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {} #endif /* CONFIG_X86 && CONFIG_DMI */ -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ + defined CONFIG_DMI static struct i801_mux_config i801_mux_config_asus_z8_d12 = { .gpio_chip = "gpio_ich", .values = { 0x02, 0x03 }, @@ -1059,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv) id = dmi_first_match(mux_dmi_table); if (id) { - /* Remove from branch classes from trunk */ + /* Remove branch classes from trunk */ mux_config = id->driver_data; for (i = 0; i < mux_config->n_values; i++) class &= ~mux_config->classes[i]; diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1f58197062c..0670da79ee5 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -1,7 +1,7 @@ /* * Freescale MXS I2C bus driver * - * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. + * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K. * * based on a (non-working) driver which was: * @@ -35,10 +35,6 @@ #define DRIVER_NAME "mxs-i2c" -static bool use_pioqueue; -module_param(use_pioqueue, bool, 0); -MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA"); - #define MXS_I2C_CTRL0 (0x00) #define MXS_I2C_CTRL0_SET (0x04) @@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA"); MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \ MXS_I2C_CTRL1_SLAVE_IRQ) -#define MXS_I2C_QUEUECTRL (0x60) -#define MXS_I2C_QUEUECTRL_SET (0x64) -#define MXS_I2C_QUEUECTRL_CLR (0x68) - -#define MXS_I2C_QUEUECTRL_QUEUE_RUN 0x20 -#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE 0x04 - -#define MXS_I2C_QUEUESTAT (0x70) -#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000 -#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F - -#define MXS_I2C_QUEUECMD (0x80) - -#define MXS_I2C_QUEUEDATA (0x90) - -#define MXS_I2C_DATA (0xa0) - #define MXS_CMD_I2C_SELECT (MXS_I2C_CTRL0_RETAIN_CLOCK | \ MXS_I2C_CTRL0_PRE_SEND_START | \ @@ -153,7 +132,6 @@ struct mxs_i2c_dev { const struct mxs_i2c_speed_config *speed; /* DMA support components */ - bool dma_mode; int dma_channel; struct dma_chan *dmach; struct mxs_dma_data dma_data; @@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2); writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); - if (i2c->dma_mode) - writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, - i2c->regs + MXS_I2C_QUEUECTRL_CLR); - else - writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, - i2c->regs + MXS_I2C_QUEUECTRL_SET); -} - -static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len, - int flags) -{ - u32 data; - - writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD); - - data = (addr << 1) | I2C_SMBUS_READ; - writel(data, i2c->regs + MXS_I2C_DATA); - - data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags; - writel(data, i2c->regs + MXS_I2C_QUEUECMD); -} - -static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c, - u8 addr, u8 *buf, int len, int flags) -{ - u32 data; - int i, shifts_left; - - data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags; - writel(data, i2c->regs + MXS_I2C_QUEUECMD); - - /* - * We have to copy the slave address (u8) and buffer (arbitrary number - * of u8) into the data register (u32). To achieve that, the u8 are put - * into the MSBs of 'data' which is then shifted for the next u8. When - * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32 - * looks like this: - * - * 3 2 1 0 - * 10987654|32109876|54321098|76543210 - * --------+--------+--------+-------- - * buffer+2|buffer+1|buffer+0|slave_addr - */ - - data = ((addr << 1) | I2C_SMBUS_WRITE) << 24; - - for (i = 0; i < len; i++) { - data >>= 8; - data |= buf[i] << 24; - if ((i & 3) == 2) - writel(data, i2c->regs + MXS_I2C_DATA); - } - - /* Write out the remaining bytes if any */ - shifts_left = 24 - (i & 3) * 8; - if (shifts_left) - writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA); -} - -/* - * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the - * rd_threshold to 1). Couldn't get this to work, though. - */ -static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - - while (readl(i2c->regs + MXS_I2C_QUEUESTAT) - & MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) { - if (time_after(jiffies, timeout)) - return -ETIMEDOUT; - cond_resched(); - } - - return 0; -} - -static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len) -{ - u32 uninitialized_var(data); - int i; - - for (i = 0; i < len; i++) { - if ((i & 3) == 0) { - if (mxs_i2c_wait_for_data(i2c)) - return -ETIMEDOUT; - data = readl(i2c->regs + MXS_I2C_QUEUEDATA); - } - buf[i] = data & 0xff; - data >>= 8; - } - - return 0; } static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c) @@ -402,12 +287,14 @@ read_init_dma_fail: select_init_dma_fail: dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE); select_init_pio_fail: + dmaengine_terminate_all(i2c->dmach); return -EINVAL; /* Write failpath. */ write_init_dma_fail: dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE); write_init_pio_fail: + dmaengine_terminate_all(i2c->dmach); return -EINVAL; } @@ -432,39 +319,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, init_completion(&i2c->cmd_complete); i2c->cmd_err = 0; - if (i2c->dma_mode) { - ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); - if (ret) - return ret; - } else { - if (msg->flags & I2C_M_RD) { - mxs_i2c_pioq_setup_read(i2c, msg->addr, - msg->len, flags); - } else { - mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, - msg->len, flags); - } - - writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, - i2c->regs + MXS_I2C_QUEUECTRL_SET); - } + ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); + if (ret) + return ret; ret = wait_for_completion_timeout(&i2c->cmd_complete, msecs_to_jiffies(1000)); if (ret == 0) goto timeout; - if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) { - ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len); - if (ret) - goto timeout; - } - if (i2c->cmd_err == -ENXIO) mxs_i2c_reset(i2c); - else - writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, - i2c->regs + MXS_I2C_QUEUECTRL_CLR); dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err); @@ -472,8 +337,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, timeout: dev_dbg(i2c->dev, "Timeout!\n"); - if (i2c->dma_mode) - mxs_i2c_dma_finish(i2c); + mxs_i2c_dma_finish(i2c); mxs_i2c_reset(i2c); return -ETIMEDOUT; } @@ -502,7 +366,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) { struct mxs_i2c_dev *i2c = dev_id; u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK; - bool is_last_cmd; if (!stat) return IRQ_NONE; @@ -515,14 +378,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */ i2c->cmd_err = -EIO; - if (!i2c->dma_mode) { - is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) & - MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0; - - if (is_last_cmd || i2c->cmd_err) - complete(&i2c->cmd_complete); - } - writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR); return IRQ_HANDLED; @@ -556,23 +411,14 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) int ret; /* - * The MXS I2C DMA mode is prefered and enabled by default. - * The PIO mode is still supported, but should be used only - * for debuging purposes etc. - */ - i2c->dma_mode = !use_pioqueue; - if (!i2c->dma_mode) - dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n"); - - /* * TODO: This is a temporary solution and should be changed * to use generic DMA binding later when the helpers get in. */ ret = of_property_read_u32(node, "fsl,i2c-dma-channel", &i2c->dma_channel); if (ret) { - dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n"); - i2c->dma_mode = 0; + dev_err(dev, "Failed to get DMA channel!\n"); + return -ENODEV; } ret = of_property_read_u32(node, "clock-frequency", &speed); @@ -634,15 +480,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) } /* Setup the DMA */ - if (i2c->dma_mode) { - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - i2c->dma_data.chan_irq = dmairq; - i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); - if (!i2c->dmach) { - dev_err(dev, "Failed to request dma\n"); - return -ENODEV; - } + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + i2c->dma_data.chan_irq = dmairq; + i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); + if (!i2c->dmach) { + dev_err(dev, "Failed to request dma\n"); + return -ENODEV; } platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 698d7acb0f0..02c3115a2df 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, pm_runtime_get_sync(&dev->adev->dev); - clk_enable(dev->clk); + status = clk_prepare_enable(dev->clk); + if (status) { + dev_err(&dev->adev->dev, "can't prepare_enable clock\n"); + goto out_clk; + } status = init_hw(dev); if (status) @@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, } out: - clk_disable(dev->clk); + clk_disable_unprepare(dev->clk); +out_clk: pm_runtime_put_sync(&dev->adev->dev); dev->busy = false; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index db31eaed6ea..3525c9e62cb 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -43,7 +43,6 @@ #include <linux/slab.h> #include <linux/i2c-omap.h> #include <linux/pm_runtime.h> -#include <linux/pm_qos.h> /* I2C controller revisions */ #define OMAP_I2C_OMAP1_REV_2 0x20 @@ -187,8 +186,9 @@ struct omap_i2c_dev { int reg_shift; /* bit shift for I2C register addresses */ struct completion cmd_complete; struct resource *ioarea; - u32 latency; /* maximum MPU wkup latency */ - struct pm_qos_request pm_qos_request; + u32 latency; /* maximum mpu wkup latency */ + void (*set_mpu_wkup_lat)(struct device *dev, + long latency); u32 speed; /* Speed of bus in kHz */ u32 dtrev; /* extra revision from DT */ u32 flags; @@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx) dev->b_hw = 1; /* Enable hardware fixes */ /* calculate wakeup latency constraint for MPU */ - dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8); + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->threshold) / + (1000 * dev->speed / 8); } /* @@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf = msg->buf; dev->buf_len = msg->len; + /* make sure writes to dev->buf_len are ordered */ + barrier(); + omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); /* Clear the FIFO Buffers */ @@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, */ timeout = wait_for_completion_timeout(&dev->cmd_complete, OMAP_I2C_TIMEOUT); - dev->buf_len = 0; if (timeout == 0) { dev_err(dev->dev, "controller timed out\n"); omap_i2c_init(dev); @@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (r < 0) goto out; - /* - * When waiting for completion of a i2c transfer, we need to - * set a wake up latency constraint for the MPU. This is to - * ensure quick enough wakeup from idle, when transfer - * completes. - */ - if (dev->latency) - pm_qos_add_request(&dev->pm_qos_request, - PM_QOS_CPU_DMA_LATENCY, - dev->latency); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, dev->latency); for (i = 0; i < num; i++) { r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1))); @@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) break; } - if (dev->latency) - pm_qos_remove_request(&dev->pm_qos_request); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, -1); if (r == 0) r = num; @@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev) } else if (pdata != NULL) { dev->speed = pdata->clkrate; dev->flags = pdata->flags; + dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; dev->dtrev = pdata->rev; } @@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev) dev->b_hw = 1; /* Enable hardware fixes */ /* calculate wakeup latency constraint for MPU */ - dev->latency = (1000000 * dev->fifo_size) / - (1000 * dev->speed / 8); + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->fifo_size) / + (1000 * dev->speed / 8); } /* reset ASAP, clearing any IRQs */ diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 3e0335f1fc6..9d902725bac 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio); goto free_gpio; } + i2c->gpios[idx] = gpio; ret = gpio_request(gpio, "i2c-bus"); if (ret) { diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f981ac4e678..dcea77bf6f5 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) } ret = devm_request_irq(&pdev->dev, i2c_dev->irq, - tegra_i2c_isr, 0, pdev->name, i2c_dev); + tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev); if (ret) { dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); return ret; diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/i2c-stub.c index b1b3447942c..d0a9c590c3c 100644 --- a/drivers/i2c/busses/i2c-stub.c +++ b/drivers/i2c/i2c-stub.c @@ -2,7 +2,7 @@ i2c-stub.c - I2C/SMBus chip emulator Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com> - Copyright (C) 2007 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org> 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 @@ -51,8 +51,8 @@ struct stub_chip { static struct stub_chip *stub_chips; /* Return negative errno on error. */ -static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, union i2c_smbus_data * data) +static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, + char read_write, u8 command, int size, union i2c_smbus_data *data) { s32 ret; int i, len; @@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, case I2C_SMBUS_BYTE: if (read_write == I2C_SMBUS_WRITE) { chip->pointer = command; - dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " - "wrote 0x%02x.\n", - addr, command); + dev_dbg(&adap->dev, + "smbus byte - addr 0x%02x, wrote 0x%02x.\n", + addr, command); } else { data->byte = chip->words[chip->pointer++] & 0xff; - dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " - "read 0x%02x.\n", - addr, data->byte); + dev_dbg(&adap->dev, + "smbus byte - addr 0x%02x, read 0x%02x.\n", + addr, data->byte); } ret = 0; @@ -95,14 +95,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, if (read_write == I2C_SMBUS_WRITE) { chip->words[command] &= 0xff00; chip->words[command] |= data->byte; - dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " - "wrote 0x%02x at 0x%02x.\n", - addr, data->byte, command); + dev_dbg(&adap->dev, + "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n", + addr, data->byte, command); } else { data->byte = chip->words[command] & 0xff; - dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " - "read 0x%02x at 0x%02x.\n", - addr, data->byte, command); + dev_dbg(&adap->dev, + "smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n", + addr, data->byte, command); } chip->pointer = command + 1; @@ -112,14 +112,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, case I2C_SMBUS_WORD_DATA: if (read_write == I2C_SMBUS_WRITE) { chip->words[command] = data->word; - dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " - "wrote 0x%04x at 0x%02x.\n", - addr, data->word, command); + dev_dbg(&adap->dev, + "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n", + addr, data->word, command); } else { data->word = chip->words[command]; - dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " - "read 0x%04x at 0x%02x.\n", - addr, data->word, command); + dev_dbg(&adap->dev, + "smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n", + addr, data->word, command); } ret = 0; @@ -132,17 +132,17 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, chip->words[command + i] &= 0xff00; chip->words[command + i] |= data->block[1 + i]; } - dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " - "wrote %d bytes at 0x%02x.\n", - addr, len, command); + dev_dbg(&adap->dev, + "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n", + addr, len, command); } else { for (i = 0; i < len; i++) { data->block[1 + i] = chip->words[command + i] & 0xff; } - dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " - "read %d bytes at 0x%02x.\n", - addr, len, command); + dev_dbg(&adap->dev, + "i2c block data - addr 0x%02x, read %d bytes at 0x%02x.\n", + addr, len, command); } ret = 0; @@ -179,25 +179,24 @@ static int __init i2c_stub_init(void) int i, ret; if (!chip_addr[0]) { - printk(KERN_ERR "i2c-stub: Please specify a chip address\n"); + pr_err("i2c-stub: Please specify a chip address\n"); return -ENODEV; } for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { - printk(KERN_ERR "i2c-stub: Invalid chip address " - "0x%02x\n", chip_addr[i]); + pr_err("i2c-stub: Invalid chip address 0x%02x\n", + chip_addr[i]); return -EINVAL; } - printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", - chip_addr[i]); + pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]); } /* Allocate memory for all chips at once */ stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL); if (!stub_chips) { - printk(KERN_ERR "i2c-stub: Out of memory\n"); + pr_err("i2c-stub: Out of memory\n"); return -ENOMEM; } @@ -219,4 +218,3 @@ MODULE_LICENSE("GPL"); module_init(i2c_stub_init); module_exit(i2c_stub_exit); - diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 5f097f309b9..7fa5b24b16d 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -169,7 +169,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev) mux->busses = devm_kzalloc(&pdev->dev, sizeof(mux->busses) * mux->pdata->bus_count, GFP_KERNEL); - if (!mux->states) { + if (!mux->busses) { dev_err(&pdev->dev, "Cannot allocate busses\n"); ret = -ENOMEM; goto err; diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index 6e3f143fc71..fc937aca71f 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -62,7 +62,6 @@ source "drivers/iio/frequency/Kconfig" source "drivers/iio/dac/Kconfig" source "drivers/iio/common/Kconfig" source "drivers/iio/gyro/Kconfig" -source "drivers/iio/light/Kconfig" source "drivers/iio/magnetometer/Kconfig" endif # IIO diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index f7fa3c0867b..761f2b65ac5 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -18,5 +18,4 @@ obj-y += frequency/ obj-y += dac/ obj-y += common/ obj-y += gyro/ -obj-y += light/ obj-y += magnetometer/ diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index 57e07c61ace..afd81790ab3 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -468,7 +468,7 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd, ret = alloc_pbl(mhp, npages); if (ret) { kfree(page_list); - goto err_pbl; + goto err; } ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr, diff --git a/drivers/infiniband/hw/mlx4/alias_GUID.c b/drivers/infiniband/hw/mlx4/alias_GUID.c index d2fb38d4357..2f215b93db6 100644 --- a/drivers/infiniband/hw/mlx4/alias_GUID.c +++ b/drivers/infiniband/hw/mlx4/alias_GUID.c @@ -107,7 +107,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index { if (index >= NUM_ALIAS_GUID_PER_PORT) { pr_err("%s: ERROR: asked for index:%d\n", __func__, index); - return (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL); + return (__force __be64) -1; } return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index]; } diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 21a794152d1..0a903c129f0 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c @@ -409,38 +409,45 @@ int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid) } -static int get_pkey_phys_indices(struct mlx4_ib_dev *ibdev, u8 port, u8 ph_pkey_ix, - u8 *full_pk_ix, u8 *partial_pk_ix, - int *is_full_member) +static int find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave, + u8 port, u16 pkey, u16 *ix) { - u16 search_pkey; - int fm; - int err = 0; - u16 pk; + int i, ret; + u8 unassigned_pkey_ix, pkey_ix, partial_ix = 0xFF; + u16 slot_pkey; - err = ib_get_cached_pkey(&ibdev->ib_dev, port, ph_pkey_ix, &search_pkey); - if (err) - return err; + if (slave == mlx4_master_func_num(dev->dev)) + return ib_find_cached_pkey(&dev->ib_dev, port, pkey, ix); - fm = (search_pkey & 0x8000) ? 1 : 0; - if (fm) { - *full_pk_ix = ph_pkey_ix; - search_pkey &= 0x7FFF; - } else { - *partial_pk_ix = ph_pkey_ix; - search_pkey |= 0x8000; - } + unassigned_pkey_ix = dev->dev->phys_caps.pkey_phys_table_len[port] - 1; - if (ib_find_exact_cached_pkey(&ibdev->ib_dev, port, search_pkey, &pk)) - pk = 0xFFFF; + for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) { + if (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == unassigned_pkey_ix) + continue; - if (fm) - *partial_pk_ix = (pk & 0xFF); - else - *full_pk_ix = (pk & 0xFF); + pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][i]; - *is_full_member = fm; - return err; + ret = ib_get_cached_pkey(&dev->ib_dev, port, pkey_ix, &slot_pkey); + if (ret) + continue; + if ((slot_pkey & 0x7FFF) == (pkey & 0x7FFF)) { + if (slot_pkey & 0x8000) { + *ix = (u16) pkey_ix; + return 0; + } else { + /* take first partial pkey index found */ + if (partial_ix == 0xFF) + partial_ix = pkey_ix; + } + } + } + + if (partial_ix < 0xFF) { + *ix = (u16) partial_ix; + return 0; + } + + return -EINVAL; } int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, @@ -458,10 +465,8 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, unsigned tun_tx_ix = 0; int dqpn; int ret = 0; - int i; - int is_full_member = 0; u16 tun_pkey_ix; - u8 ph_pkey_ix, full_pk_ix = 0, partial_pk_ix = 0; + u16 cached_pkey; if (dest_qpt > IB_QPT_GSI) return -EINVAL; @@ -481,27 +486,17 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port, else tun_qp = &tun_ctx->qp[1]; - /* compute pkey index for slave */ - /* get physical pkey -- virtualized Dom0 pkey to phys*/ + /* compute P_Key index to put in tunnel header for slave */ if (dest_qpt) { - ph_pkey_ix = - dev->pkeys.virt2phys_pkey[mlx4_master_func_num(dev->dev)][port - 1][wc->pkey_index]; - - /* now, translate this to the slave pkey index */ - ret = get_pkey_phys_indices(dev, port, ph_pkey_ix, &full_pk_ix, - &partial_pk_ix, &is_full_member); + u16 pkey_ix; + ret = ib_get_cached_pkey(&dev->ib_dev, port, wc->pkey_index, &cached_pkey); if (ret) return -EINVAL; - for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) { - if ((dev->pkeys.virt2phys_pkey[slave][port - 1][i] == full_pk_ix) || - (is_full_member && - (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == partial_pk_ix))) - break; - } - if (i == dev->dev->caps.pkey_table_len[port]) + ret = find_slave_port_pkey_ix(dev, slave, port, cached_pkey, &pkey_ix); + if (ret) return -EINVAL; - tun_pkey_ix = i; + tun_pkey_ix = pkey_ix; } else tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0]; diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c index 3c3b54c3fdd..25b2cdff00f 100644 --- a/drivers/infiniband/hw/mlx4/mcg.c +++ b/drivers/infiniband/hw/mlx4/mcg.c @@ -233,7 +233,8 @@ static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx, ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr); - wc.pkey_index = 0; + if (ib_find_cached_pkey(&dev->ib_dev, ctx->port, IB_DEFAULT_PKEY_FULL, &wc.pkey_index)) + return -EINVAL; wc.sl = 0; wc.dlid_path_bits = 0; wc.port_num = ctx->port; @@ -1074,10 +1075,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy unsigned long end; int count; - if (ctx->flushing) - return; - - ctx->flushing = 1; for (i = 0; i < MAX_VFS; ++i) clean_vf_mcast(ctx, i); @@ -1107,9 +1104,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy force_clean_group(group); } mutex_unlock(&ctx->mcg_table_lock); - - if (!destroy_wq) - ctx->flushing = 0; } struct clean_work { @@ -1123,6 +1117,7 @@ static void mcg_clean_task(struct work_struct *work) struct clean_work *cw = container_of(work, struct clean_work, work); _mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq); + cw->ctx->flushing = 0; kfree(cw); } @@ -1130,13 +1125,20 @@ void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq) { struct clean_work *work; + if (ctx->flushing) + return; + + ctx->flushing = 1; + if (destroy_wq) { _mlx4_ib_mcg_port_cleanup(ctx, destroy_wq); + ctx->flushing = 0; return; } work = kmalloc(sizeof *work, GFP_KERNEL); if (!work) { + ctx->flushing = 0; mcg_warn("failed allocating work for cleanup\n"); return; } diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 6ae2ac47c9c..f0f8928b3c8 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file) kfree(client); evdev_close_device(evdev); - put_device(&evdev->dev); return 0; } @@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file) file->private_data = client; nonseekable_open(inode, file); - get_device(&evdev->dev); return 0; err_free_client: @@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, goto err_free_evdev; cdev_init(&evdev->cdev, &evdev_fops); + evdev->cdev.kobj.parent = &evdev->dev.kobj; error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); if (error) goto err_unregister_handle; diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index c0ec7d42c3b..1abbc170d8b 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -26,10 +26,14 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) * input_mt_init_slots() - initialize MT input slots * @dev: input device supporting MT events and finger tracking * @num_slots: number of slots used by the device + * @flags: mt tasks to handle in core * * This function allocates all necessary memory for MT slot handling * in the input device, prepares the ABS_MT_SLOT and * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers. + * Depending on the flags set, it also performs pointer emulation and + * frame synchronization. + * * May be called repeatedly. Returns -EINVAL if attempting to * reinitialize with a different number of slots. */ diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index b62b5891f39..f362883c94e 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file) kfree(client); joydev_close_device(joydev); - put_device(&joydev->dev); return 0; } @@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file) file->private_data = client; nonseekable_open(inode, file); - get_device(&joydev->dev); return 0; err_free_client: @@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, goto err_free_joydev; cdev_init(&joydev->cdev, &joydev_fops); + joydev->cdev.kobj.parent = &joydev->dev.kobj; error = cdev_add(&joydev->cdev, joydev->dev.devt, 1); if (error) goto err_unregister_handle; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b4b65af8612..de0874054e9 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO config KEYBOARD_LPC32XX tristate "LPC32XX matrix key scanner support" depends on ARCH_LPC32XX && OF + select INPUT_MATRIXKMAP help Say Y here if you want to use NXP LPC32XX SoC key scanner interface, connected to a key matrix. diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 803ff6fe021..cad9d5dd597 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) unsigned int mask = 0, direct_key_num = 0; unsigned long kpc = 0; + /* clear pending interrupt bit */ + keypad_readl(KPC); + /* enable matrix keys with automatic scan */ if (pdata->matrix_key_rows && pdata->matrix_key_cols) { kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL; diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 02ca8680ea5..6f7d9901303 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev, case XenbusStateReconfiguring: case XenbusStateReconfigured: case XenbusStateUnknown: - case XenbusStateClosed: break; case XenbusStateInitWait: @@ -350,6 +349,10 @@ InitWait: break; + case XenbusStateClosed: + if (dev->state == XenbusStateClosed) + break; + /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 3a78f235fa3..2baff1b79a5 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -84,6 +84,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263 #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264 +/* MacbookPro10,2 (unibody, October 2012) */ +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), + /* MacbookPro10,2 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), /* Terminating entry */ {} }; @@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = { { SN_COORD, -150, 6730 }, { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS, + HAS_INTEGRATED_BUTTON, + 0x84, sizeof(struct bt_data), + 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + { SN_PRESSURE, 0, 300 }, + { SN_WIDTH, 0, 2048 }, + { SN_COORD, -4750, 5280 }, + { SN_COORD, -150, 6730 }, + { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } + }, {} }; diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index a1b4c37956b..4c842c320c2 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -12,8 +12,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define MOUSEDEV_MINOR_BASE 32 -#define MOUSEDEV_MINORS 32 -#define MOUSEDEV_MIX 31 +#define MOUSEDEV_MINORS 31 +#define MOUSEDEV_MIX 63 #include <linux/sched.h> #include <linux/slab.h> @@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file) kfree(client); mousedev_close_device(mousedev); - put_device(&mousedev->dev); return 0; } @@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file) file->private_data = client; nonseekable_open(inode, file); - get_device(&mousedev->dev); return 0; err_free_client: @@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev, } cdev_init(&mousedev->cdev, &mousedev_fops); + mousedev->cdev.kobj.parent = &mousedev->dev.kobj; error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1); if (error) goto err_unregister_handle; diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 9edf9806cff..858ad446de9 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf, features->pktlen = WACOM_PKGLEN_TPC2FG; } - if (features->type == MTSCREEN) + if (features->type == MTSCREEN || features->type == WACOM_24HDT) features->pktlen = WACOM_PKGLEN_MTOUCH; if (features->type == BAMBOO_PT) { @@ -402,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf, features->x_max = get_unaligned_le16(&report[i + 8]); i += 15; + } else if (features->type == WACOM_24HDT) { + features->x_max = + get_unaligned_le16(&report[i + 3]); + features->x_phy = + get_unaligned_le16(&report[i + 8]); + features->unit = report[i - 1]; + features->unitExpo = report[i - 3]; + i += 12; } else { features->x_max = get_unaligned_le16(&report[i + 3]); @@ -434,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf, features->y_phy = get_unaligned_le16(&report[i + 6]); i += 7; + } else if (type == WACOM_24HDT) { + features->y_max = + get_unaligned_le16(&report[i + 3]); + features->y_phy = + get_unaligned_le16(&report[i - 2]); + i += 7; } else if (type == BAMBOO_PT) { features->y_phy = get_unaligned_le16(&report[i + 3]); @@ -541,6 +555,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat /* MT Tablet PC touch */ return wacom_set_device_mode(intf, 3, 4, 4); } + else if (features->type == WACOM_24HDT) { + return wacom_set_device_mode(intf, 18, 3, 2); + } } else if (features->device_type == BTN_TOOL_PEN) { if (features->type <= BAMBOO_PT && features->type != WIRELESS) { return wacom_set_device_mode(intf, 2, 2, 2); @@ -613,6 +630,30 @@ struct wacom_usbdev_data { static LIST_HEAD(wacom_udev_list); static DEFINE_MUTEX(wacom_udev_list_lock); +static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product) +{ + int port1; + struct usb_device *sibling; + + if (vendor == 0 && product == 0) + return dev; + + if (dev->parent == NULL) + return NULL; + + usb_hub_for_each_child(dev->parent, port1, sibling) { + struct usb_device_descriptor *d; + if (sibling == NULL) + continue; + + d = &sibling->descriptor; + if (d->idVendor == vendor && d->idProduct == product) + return sibling; + } + + return NULL; +} + static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev) { struct wacom_usbdev_data *data; @@ -1257,13 +1298,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { + struct usb_device *other_dev; + /* Append the device type to the name */ strlcat(wacom_wac->name, features->device_type == BTN_TOOL_PEN ? " Pen" : " Finger", sizeof(wacom_wac->name)); - error = wacom_add_shared_data(wacom_wac, dev); + + other_dev = wacom_get_sibling(dev, features->oVid, features->oPid); + if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL) + other_dev = dev; + error = wacom_add_shared_data(wacom_wac, other_dev); if (error) goto fail3; } diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index c3468c8dbd8..0a67031ffc1 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -806,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid) return -1; } +static int int_dist(int x1, int y1, int x2, int y2) +{ + int x = x2 - x1; + int y = y2 - y1; + + return int_sqrt(x*x + y*y); +} + +static int wacom_24hdt_irq(struct wacom_wac *wacom) +{ + struct input_dev *input = wacom->input; + char *data = wacom->data; + int i; + int current_num_contacts = data[61]; + int contacts_to_send = 0; + + /* + * First packet resets the counter since only the first + * packet in series will have non-zero current_num_contacts. + */ + if (current_num_contacts) + wacom->num_contacts_left = current_num_contacts; + + /* There are at most 4 contacts per packet */ + contacts_to_send = min(4, wacom->num_contacts_left); + + for (i = 0; i < contacts_to_send; i++) { + int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1; + bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity; + int id = data[offset + 1]; + int slot = find_slot_from_contactid(wacom, id); + + if (slot < 0) + continue; + input_mt_slot(input, slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + + if (touch) { + int t_x = le16_to_cpup((__le16 *)&data[offset + 2]); + int c_x = le16_to_cpup((__le16 *)&data[offset + 4]); + int t_y = le16_to_cpup((__le16 *)&data[offset + 6]); + int c_y = le16_to_cpup((__le16 *)&data[offset + 8]); + int w = le16_to_cpup((__le16 *)&data[offset + 10]); + int h = le16_to_cpup((__le16 *)&data[offset + 12]); + + input_report_abs(input, ABS_MT_POSITION_X, t_x); + input_report_abs(input, ABS_MT_POSITION_Y, t_y); + input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h)); + input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y)); + input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); + input_report_abs(input, ABS_MT_ORIENTATION, w > h); + } + wacom->slots[slot] = touch ? id : -1; + } + + input_mt_report_pointer_emulation(input, true); + + wacom->num_contacts_left -= contacts_to_send; + if (wacom->num_contacts_left <= 0) + wacom->num_contacts_left = 0; + + return 1; +} + static int wacom_mt_touch(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; @@ -1255,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_intuos_irq(wacom_wac); break; + case WACOM_24HDT: + sync = wacom_24hdt_irq(wacom_wac); + break; + case INTUOS5S: case INTUOS5: case INTUOS5L: @@ -1340,7 +1408,8 @@ void wacom_setup_device_quirks(struct wacom_features *features) /* these device have multiple inputs */ if (features->type >= WIRELESS || - (features->type >= INTUOS5S && features->type <= INTUOS5L)) + (features->type >= INTUOS5S && features->type <= INTUOS5L) || + (features->oVid && features->oPid)) features->quirks |= WACOM_QUIRK_MULTI_INPUT; /* quirk for bamboo touch with 2 low res touches */ @@ -1449,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); + + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + wacom_setup_cintiq(wacom_wac); break; @@ -1575,6 +1647,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_POINTER, input_dev->propbit); break; + case WACOM_24HDT: + if (features->device_type == BTN_TOOL_FINGER) { + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); + } + /* fall through */ + case MTSCREEN: if (features->device_type == BTN_TOOL_FINGER) { wacom_wac->slots = kmalloc(features->touch_max * @@ -1869,8 +1950,11 @@ static const struct wacom_features wacom_features_0xF4 = { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xF8 = - { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, - 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, /* Pen */ + 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; +static const struct wacom_features wacom_features_0xF6 = + { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 }; static const struct wacom_features wacom_features_0x3F = { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; @@ -2113,6 +2197,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, { USB_DEVICE_WACOM(0xF8) }, + { USB_DEVICE_WACOM(0xF6) }, { USB_DEVICE_WACOM(0xFA) }, { USB_DEVICE_LENOVO(0x6004) }, { } diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 96c185cc301..345f1e76975 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -29,6 +29,7 @@ /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 +#define WACOM_BYTES_PER_24HDT_PACKET 14 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -49,6 +50,7 @@ #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 #define WACOM_REPORT_TPC1FGE 18 +#define WACOM_REPORT_24HDT 1 /* device quirks */ #define WACOM_QUIRK_MULTI_INPUT 0x0001 @@ -81,6 +83,7 @@ enum { WACOM_MO, WIRELESS, BAMBOO_PT, + WACOM_24HDT, TABLETPC, /* add new TPC below */ TABLETPCE, TABLETPC2FG, @@ -109,6 +112,8 @@ struct wacom_features { int distance_fuzz; unsigned quirks; unsigned touch_max; + int oVid; + int oPid; }; struct wacom_shared { diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 1ba232cbc09..f7668b24c37 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI config TOUCHSCREEN_EGALAX tristate "EETI eGalax multi-touch panel support" - depends on I2C + depends on I2C && OF help Say Y here to enable support for I2C connected EETI eGalax multi-touch panels. diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index f02028ec3db..78e5d9ab0ba 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -955,7 +955,8 @@ static int ads7846_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); -static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts) +static int __devinit ads7846_setup_pendown(struct spi_device *spi, + struct ads7846 *ts) { struct ads7846_platform_data *pdata = spi->dev.platform_data; int err; @@ -981,6 +982,9 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784 ts->gpio_pendown = pdata->gpio_pendown; + if (pdata->gpio_pendown_debounce) + gpio_set_debounce(pdata->gpio_pendown, + pdata->gpio_pendown_debounce); } else { dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); return -EINVAL; diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index c1e3460f119..13fa62fdfb0 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -28,6 +28,7 @@ #include <linux/slab.h> #include <linux/bitops.h> #include <linux/input/mt.h> +#include <linux/of_gpio.h> /* * Mouse Mode: some panel may configure the controller to mouse mode, @@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) /* wake up controller by an falling edge of interrupt gpio. */ static int egalax_wake_up_device(struct i2c_client *client) { - int gpio = irq_to_gpio(client->irq); + struct device_node *np = client->dev.of_node; + int gpio; int ret; + if (!np) + return -ENODEV; + + gpio = of_get_named_gpio(np, "wakeup-gpios", 0); + if (!gpio_is_valid(gpio)) + return -ENODEV; + ret = gpio_request(gpio, "egalax_irq"); if (ret < 0) { dev_err(&client->dev, @@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client, ts->input_dev = input_dev; /* controller may be in sleep, wake it up. */ - egalax_wake_up_device(client); + error = egalax_wake_up_device(client); + if (error) { + dev_err(&client->dev, "Failed to wake up the controller\n"); + goto err_free_dev; + } ret = egalax_firmware_version(client); if (ret < 0) { @@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume); +static struct of_device_id egalax_ts_dt_ids[] = { + { .compatible = "eeti,egalax_ts" }, + { /* sentinel */ } +}; + static struct i2c_driver egalax_ts_driver = { .driver = { .name = "egalax_ts", .owner = THIS_MODULE, .pm = &egalax_ts_pm_ops, + .of_match_table = of_match_ptr(egalax_ts_dt_ids), }, .id_table = egalax_ts_id, .probe = egalax_ts_probe, diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 63209aaa55f..eb96f168fb9 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv) __set_bit(BTN_TOUCH, input_dev->keybit); input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0); input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); - input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0); serio_set_drvdata(serio, ptsc); diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 18b0d99bd4d..81837b0710a 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1599,21 +1599,46 @@ static void __init free_on_init_error(void) #endif } +/* SB IOAPIC is always on this device in AMD systems */ +#define IOAPIC_SB_DEVID ((0x00 << 8) | PCI_DEVFN(0x14, 0)) + static bool __init check_ioapic_information(void) { + bool ret, has_sb_ioapic; int idx; - for (idx = 0; idx < nr_ioapics; idx++) { - int id = mpc_ioapic_id(idx); + has_sb_ioapic = false; + ret = false; - if (get_ioapic_devid(id) < 0) { - pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id); - pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n"); - return false; + for (idx = 0; idx < nr_ioapics; idx++) { + int devid, id = mpc_ioapic_id(idx); + + devid = get_ioapic_devid(id); + if (devid < 0) { + pr_err(FW_BUG "AMD-Vi: IOAPIC[%d] not in IVRS table\n", id); + ret = false; + } else if (devid == IOAPIC_SB_DEVID) { + has_sb_ioapic = true; + ret = true; } } - return true; + if (!has_sb_ioapic) { + /* + * We expect the SB IOAPIC to be listed in the IVRS + * table. The system timer is connected to the SB IOAPIC + * and if we don't have it in the list the system will + * panic at boot time. This situation usually happens + * when the BIOS is buggy and provides us the wrong + * device id for the IOAPIC in the system. + */ + pr_err(FW_BUG "AMD-Vi: No southbridge IOAPIC found in IVRS table\n"); + } + + if (!ret) + pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug(s)\n"); + + return ret; } static void __init free_dma_resources(void) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d4a4cd445ca..0badfa48b32 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4108,7 +4108,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to) static int intel_iommu_add_device(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct pci_dev *bridge, *dma_pdev; + struct pci_dev *bridge, *dma_pdev = NULL; struct iommu_group *group; int ret; @@ -4122,7 +4122,7 @@ static int intel_iommu_add_device(struct device *dev) dma_pdev = pci_get_domain_bus_and_slot( pci_domain_nr(pdev->bus), bridge->subordinate->number, 0); - else + if (!dma_pdev) dma_pdev = pci_dev_get(bridge); } else dma_pdev = pci_dev_get(pdev); diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 0b4d62e0c64..c0f7a426626 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -200,7 +200,7 @@ enum { #define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12) #define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22) -#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22) +#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << 22) #define _READABLE (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT) #define _WRITABLE (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT) @@ -1054,6 +1054,7 @@ static int smmu_debugfs_stats_show(struct seq_file *s, void *v) stats[i], val, offs); } seq_printf(s, "\n"); + dput(dent); return 0; } diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c index dc670ccc697..16c78f1c5ef 100644 --- a/drivers/irqchip/irq-bcm2835.c +++ b/drivers/irqchip/irq-bcm2835.c @@ -168,7 +168,8 @@ static int __init armctrl_of_init(struct device_node *node, } static struct of_device_id irq_of_match[] __initconst = { - { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init } + { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init }, + { } }; void __init bcm2835_init_irq(void) diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig index a233ed53913..86cd75a0e84 100644 --- a/drivers/isdn/Kconfig +++ b/drivers/isdn/Kconfig @@ -4,7 +4,7 @@ menuconfig ISDN bool "ISDN support" - depends on NET + depends on NET && NETDEVICES depends on !S390 && !UML ---help--- ISDN ("Integrated Services Digital Network", called RNIS in France) diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 52758870894..c44950d3eb7 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -617,7 +617,13 @@ static void int_in_work(struct work_struct *work) if (rc == 0) /* success, resubmit interrupt read URB */ rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc != 0 && rc != -ENODEV) { + + switch (rc) { + case 0: /* success */ + case -ENODEV: /* device gone */ + case -EINVAL: /* URB already resubmitted, or terminal badness */ + break; + default: /* failure: try to recover by resetting the device */ dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc)); rc = usb_lock_device_for_reset(ucs->udev, ucs->interface); if (rc == 0) { @@ -2442,7 +2448,9 @@ static void gigaset_disconnect(struct usb_interface *interface) } /* gigaset_suspend - * This function is called before the USB connection is suspended. + * This function is called before the USB connection is suspended + * or before the USB device is reset. + * In the latter case, message == PMSG_ON. */ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) { @@ -2498,7 +2506,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) del_timer_sync(&ucs->timer_atrdy); del_timer_sync(&ucs->timer_cmd_in); del_timer_sync(&ucs->timer_int_in); - cancel_work_sync(&ucs->int_in_wq); + + /* don't try to cancel int_in_wq from within reset as it + * might be the one requesting the reset + */ + if (message.event != PM_EVENT_ON) + cancel_work_sync(&ucs->int_in_wq); gig_dbg(DEBUG_SUSPEND, "suspend complete"); return 0; diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 2302fbe70ac..9c6650ea848 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -6,7 +6,7 @@ if ISDN_I4L config ISDN_PPP bool "Support synchronous PPP" - depends on INET && NETDEVICES + depends on INET select SLHC help Over digital connections such as ISDN, there is no need to diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 8c610fa6782..e2a945ee9f0 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1312,7 +1312,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) } else return -EINVAL; break; -#ifdef CONFIG_NETDEVICES case IIOCNETGPN: /* Get peer phone number of a connected * isdn network interface */ @@ -1322,7 +1321,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) return isdn_net_getpeer(&phone, argp); } else return -EINVAL; -#endif default: return -EINVAL; } @@ -1352,7 +1350,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) case IIOCNETLCR: printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n"); return -ENODEV; -#ifdef CONFIG_NETDEVICES case IIOCNETAIF: /* Add a network-interface */ if (arg) { @@ -1491,7 +1488,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) return -EFAULT; return isdn_net_force_hangup(name); break; -#endif /* CONFIG_NETDEVICES */ case IIOCSETVER: dev->net_verbose = arg; printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose); diff --git a/drivers/leds/ledtrig-cpu.c b/drivers/leds/ledtrig-cpu.c index b312056da14..4239b3955ff 100644 --- a/drivers/leds/ledtrig-cpu.c +++ b/drivers/leds/ledtrig-cpu.c @@ -33,8 +33,6 @@ struct led_trigger_cpu { char name[MAX_NAME_LEN]; struct led_trigger *_trig; - struct mutex lock; - int lock_is_inited; }; static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); @@ -50,12 +48,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt) { struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig); - /* mutex lock should be initialized before calling mutex_call() */ - if (!trig->lock_is_inited) - return; - - mutex_lock(&trig->lock); - /* Locate the correct CPU LED */ switch (ledevt) { case CPU_LED_IDLE_END: @@ -75,8 +67,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt) /* Will leave the LED as it is */ break; } - - mutex_unlock(&trig->lock); } EXPORT_SYMBOL(ledtrig_cpu); @@ -117,14 +107,9 @@ static int __init ledtrig_cpu_init(void) for_each_possible_cpu(cpu) { struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu); - mutex_init(&trig->lock); - snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu); - mutex_lock(&trig->lock); led_trigger_register_simple(trig->name, &trig->_trig); - trig->lock_is_inited = 1; - mutex_unlock(&trig->lock); } register_syscore_ops(&ledtrig_cpu_syscore_ops); @@ -142,15 +127,9 @@ static void __exit ledtrig_cpu_exit(void) for_each_possible_cpu(cpu) { struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu); - mutex_lock(&trig->lock); - led_trigger_unregister_simple(trig->_trig); trig->_trig = NULL; memset(trig->name, 0, MAX_NAME_LEN); - trig->lock_is_inited = 0; - - mutex_unlock(&trig->lock); - mutex_destroy(&trig->lock); } unregister_syscore_ops(&ledtrig_cpu_syscore_ops); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 02db9183ca0..77e6eff41ca 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -740,8 +740,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue) if (!md_in_flight(md)) wake_up(&md->wait); + /* + * Run this off this callpath, as drivers could invoke end_io while + * inside their request_fn (and holding the queue lock). Calling + * back into ->request_fn() could deadlock attempting to grab the + * queue lock again. + */ if (run_queue) - blk_run_queue(md->queue); + blk_run_queue_async(md->queue); /* * dm_put() must be at the end of this function. See the comment above diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 45135f69509..5e7dc772f5d 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -315,8 +315,11 @@ static int run(struct mddev *mddev) } conf->nfaults = 0; - rdev_for_each(rdev, mddev) + rdev_for_each(rdev, mddev) { conf->rdev = rdev; + disk_stack_limits(mddev->gendisk, rdev->bdev, + rdev->data_offset << 9); + } md_set_array_sectors(mddev, faulty_size(mddev, 0, 0)); mddev->private = conf; diff --git a/drivers/md/md.c b/drivers/md/md.c index 9ab768acfb6..61200717687 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1817,10 +1817,10 @@ retry: memset(bbp, 0xff, PAGE_SIZE); for (i = 0 ; i < bb->count ; i++) { - u64 internal_bb = *p++; + u64 internal_bb = p[i]; u64 store_bb = ((BB_OFFSET(internal_bb) << 10) | BB_LEN(internal_bb)); - *bbp++ = cpu_to_le64(store_bb); + bbp[i] = cpu_to_le64(store_bb); } bb->changed = 0; if (read_seqretry(&bb->lock, seq)) @@ -5294,7 +5294,7 @@ void md_stop_writes(struct mddev *mddev) } EXPORT_SYMBOL_GPL(md_stop_writes); -void md_stop(struct mddev *mddev) +static void __md_stop(struct mddev *mddev) { mddev->ready = 0; mddev->pers->stop(mddev); @@ -5304,6 +5304,18 @@ void md_stop(struct mddev *mddev) mddev->pers = NULL; clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); } + +void md_stop(struct mddev *mddev) +{ + /* stop the array and free an attached data structures. + * This is called from dm-raid + */ + __md_stop(mddev); + bitmap_destroy(mddev); + if (mddev->bio_set) + bioset_free(mddev->bio_set); +} + EXPORT_SYMBOL_GPL(md_stop); static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) @@ -5364,7 +5376,7 @@ static int do_md_stop(struct mddev * mddev, int mode, set_disk_ro(disk, 0); __md_stop_writes(mddev); - md_stop(mddev); + __md_stop(mddev); mddev->queue->merge_bvec_fn = NULL; mddev->queue->backing_dev_info.congested_fn = NULL; @@ -7936,9 +7948,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, sector_t *first_bad, int *bad_sectors) { int hi; - int lo = 0; + int lo; u64 *p = bb->page; - int rv = 0; + int rv; sector_t target = s + sectors; unsigned seq; @@ -7953,7 +7965,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, retry: seq = read_seqbegin(&bb->lock); - + lo = 0; + rv = 0; hi = bb->count; /* Binary search between lo and hi for 'target' diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 8034fbd6190..636bae0405e 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev) || disk_idx < 0) continue; if (test_bit(Replacement, &rdev->flags)) - disk = conf->mirrors + conf->raid_disks + disk_idx; + disk = conf->mirrors + mddev->raid_disks + disk_idx; else disk = conf->mirrors + disk_idx; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 906ccbd0f7d..0d5d0ff2c0f 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -499,7 +499,7 @@ static void raid10_end_write_request(struct bio *bio, int error) */ one_write_done(r10_bio); if (dec_rdev) - rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); + rdev_dec_pending(rdev, conf->mddev); } /* @@ -1334,18 +1334,21 @@ retry_write: blocked_rdev = rrdev; break; } + if (rdev && (test_bit(Faulty, &rdev->flags) + || test_bit(Unmerged, &rdev->flags))) + rdev = NULL; if (rrdev && (test_bit(Faulty, &rrdev->flags) || test_bit(Unmerged, &rrdev->flags))) rrdev = NULL; r10_bio->devs[i].bio = NULL; r10_bio->devs[i].repl_bio = NULL; - if (!rdev || test_bit(Faulty, &rdev->flags) || - test_bit(Unmerged, &rdev->flags)) { + + if (!rdev && !rrdev) { set_bit(R10BIO_Degraded, &r10_bio->state); continue; } - if (test_bit(WriteErrorSeen, &rdev->flags)) { + if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) { sector_t first_bad; sector_t dev_sector = r10_bio->devs[i].addr; int bad_sectors; @@ -1387,8 +1390,10 @@ retry_write: max_sectors = good_sectors; } } - r10_bio->devs[i].bio = bio; - atomic_inc(&rdev->nr_pending); + if (rdev) { + r10_bio->devs[i].bio = bio; + atomic_inc(&rdev->nr_pending); + } if (rrdev) { r10_bio->devs[i].repl_bio = bio; atomic_inc(&rrdev->nr_pending); @@ -1444,69 +1449,71 @@ retry_write: for (i = 0; i < conf->copies; i++) { struct bio *mbio; int d = r10_bio->devs[i].devnum; - if (!r10_bio->devs[i].bio) - continue; + if (r10_bio->devs[i].bio) { + struct md_rdev *rdev = conf->mirrors[d].rdev; + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr+ + choose_data_offset(r10_bio, + rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; + mbio->bi_private = r10_bio; - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].bio = mbio; + atomic_inc(&r10_bio->remaining); - mbio->bi_sector = (r10_bio->devs[i].addr+ - choose_data_offset(r10_bio, - conf->mirrors[d].rdev)); - mbio->bi_bdev = conf->mirrors[d].rdev->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; - mbio->bi_private = r10_bio; + cb = blk_check_plugged(raid10_unplug, mddev, + sizeof(*plug)); + if (cb) + plug = container_of(cb, struct raid10_plug_cb, + cb); + else + plug = NULL; + spin_lock_irqsave(&conf->device_lock, flags); + if (plug) { + bio_list_add(&plug->pending, mbio); + plug->pending_cnt++; + } else { + bio_list_add(&conf->pending_bio_list, mbio); + conf->pending_count++; + } + spin_unlock_irqrestore(&conf->device_lock, flags); + if (!plug) + md_wakeup_thread(mddev->thread); + } - atomic_inc(&r10_bio->remaining); + if (r10_bio->devs[i].repl_bio) { + struct md_rdev *rdev = conf->mirrors[d].replacement; + if (rdev == NULL) { + /* Replacement just got moved to main 'rdev' */ + smp_mb(); + rdev = conf->mirrors[d].rdev; + } + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].repl_bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr + + choose_data_offset( + r10_bio, rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; + mbio->bi_private = r10_bio; - cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug)); - if (cb) - plug = container_of(cb, struct raid10_plug_cb, cb); - else - plug = NULL; - spin_lock_irqsave(&conf->device_lock, flags); - if (plug) { - bio_list_add(&plug->pending, mbio); - plug->pending_cnt++; - } else { + atomic_inc(&r10_bio->remaining); + spin_lock_irqsave(&conf->device_lock, flags); bio_list_add(&conf->pending_bio_list, mbio); conf->pending_count++; + spin_unlock_irqrestore(&conf->device_lock, flags); + if (!mddev_check_plugged(mddev)) + md_wakeup_thread(mddev->thread); } - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!plug) - md_wakeup_thread(mddev->thread); - - if (!r10_bio->devs[i].repl_bio) - continue; - - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].repl_bio = mbio; - - /* We are actively writing to the original device - * so it cannot disappear, so the replacement cannot - * become NULL here - */ - mbio->bi_sector = (r10_bio->devs[i].addr + - choose_data_offset( - r10_bio, - conf->mirrors[d].replacement)); - mbio->bi_bdev = conf->mirrors[d].replacement->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; - mbio->bi_private = r10_bio; - - atomic_inc(&r10_bio->remaining); - spin_lock_irqsave(&conf->device_lock, flags); - bio_list_add(&conf->pending_bio_list, mbio); - conf->pending_count++; - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!mddev_check_plugged(mddev)) - md_wakeup_thread(mddev->thread); } /* Don't remove the bias on 'remaining' (one_write_done) until @@ -1783,7 +1790,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) clear_bit(Unmerged, &rdev->flags); } md_integrity_add_rdev(rdev, mddev); - if (blk_queue_discard(bdev_get_queue(rdev->bdev))) + if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev))) queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); print_conf(conf); @@ -3613,11 +3620,14 @@ static int run(struct mddev *mddev) discard_supported = true; } - if (discard_supported) - queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); - else - queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); - + if (mddev->queue) { + if (discard_supported) + queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, + mddev->queue); + else + queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, + mddev->queue); + } /* need to check that every block has at least one working mirror */ if (!enough(conf, -1)) { printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n", diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index c5439dce029..a4502686e7a 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2774,10 +2774,12 @@ static void handle_stripe_clean_event(struct r5conf *conf, dev = &sh->dev[i]; if (!test_bit(R5_LOCKED, &dev->flags) && (test_bit(R5_UPTODATE, &dev->flags) || - test_and_clear_bit(R5_Discard, &dev->flags))) { + test_bit(R5_Discard, &dev->flags))) { /* We can return any write requests */ struct bio *wbi, *wbi2; pr_debug("Return write for disc %d\n", i); + if (test_and_clear_bit(R5_Discard, &dev->flags)) + clear_bit(R5_UPTODATE, &dev->flags); wbi = dev->written; dev->written = NULL; while (wbi && wbi->bi_sector < @@ -2795,7 +2797,8 @@ static void handle_stripe_clean_event(struct r5conf *conf, !test_bit(STRIPE_DEGRADED, &sh->state), 0); } - } + } else if (test_bit(R5_Discard, &sh->dev[i].flags)) + clear_bit(R5_Discard, &sh->dev[i].flags); if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state)) if (atomic_dec_and_test(&conf->pending_full_writes)) @@ -3490,40 +3493,6 @@ static void handle_stripe(struct stripe_head *sh) handle_failed_sync(conf, sh, &s); } - /* - * might be able to return some write requests if the parity blocks - * are safe, or on a failed drive - */ - pdev = &sh->dev[sh->pd_idx]; - s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx) - || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx); - qdev = &sh->dev[sh->qd_idx]; - s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx) - || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx) - || conf->level < 6; - - if (s.written && - (s.p_failed || ((test_bit(R5_Insync, &pdev->flags) - && !test_bit(R5_LOCKED, &pdev->flags) - && (test_bit(R5_UPTODATE, &pdev->flags) || - test_bit(R5_Discard, &pdev->flags))))) && - (s.q_failed || ((test_bit(R5_Insync, &qdev->flags) - && !test_bit(R5_LOCKED, &qdev->flags) - && (test_bit(R5_UPTODATE, &qdev->flags) || - test_bit(R5_Discard, &qdev->flags)))))) - handle_stripe_clean_event(conf, sh, disks, &s.return_bi); - - /* Now we might consider reading some blocks, either to check/generate - * parity, or to satisfy requests - * or to load a block that is being partially written. - */ - if (s.to_read || s.non_overwrite - || (conf->level == 6 && s.to_write && s.failed) - || (s.syncing && (s.uptodate + s.compute < disks)) - || s.replacing - || s.expanding) - handle_stripe_fill(sh, &s, disks); - /* Now we check to see if any write operations have recently * completed */ @@ -3561,6 +3530,40 @@ static void handle_stripe(struct stripe_head *sh) s.dec_preread_active = 1; } + /* + * might be able to return some write requests if the parity blocks + * are safe, or on a failed drive + */ + pdev = &sh->dev[sh->pd_idx]; + s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx) + || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx); + qdev = &sh->dev[sh->qd_idx]; + s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx) + || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx) + || conf->level < 6; + + if (s.written && + (s.p_failed || ((test_bit(R5_Insync, &pdev->flags) + && !test_bit(R5_LOCKED, &pdev->flags) + && (test_bit(R5_UPTODATE, &pdev->flags) || + test_bit(R5_Discard, &pdev->flags))))) && + (s.q_failed || ((test_bit(R5_Insync, &qdev->flags) + && !test_bit(R5_LOCKED, &qdev->flags) + && (test_bit(R5_UPTODATE, &qdev->flags) || + test_bit(R5_Discard, &qdev->flags)))))) + handle_stripe_clean_event(conf, sh, disks, &s.return_bi); + + /* Now we might consider reading some blocks, either to check/generate + * parity, or to satisfy requests + * or to load a block that is being partially written. + */ + if (s.to_read || s.non_overwrite + || (conf->level == 6 && s.to_write && s.failed) + || (s.syncing && (s.uptodate + s.compute < disks)) + || s.replacing + || s.expanding) + handle_stripe_fill(sh, &s, disks); + /* Now to consider new write requests and what else, if anything * should be read. We do not handle new writes when: * 1/ A 'write' operation (copy+xor) is already in flight. @@ -5529,6 +5532,10 @@ static int run(struct mddev *mddev) * discard data disk but write parity disk */ stripe = stripe * PAGE_SIZE; + /* Round up to power of 2, as discard handling + * currently assumes that */ + while ((stripe-1) & stripe) + stripe = (stripe | (stripe-1)) + 1; mddev->queue->limits.discard_alignment = stripe; mddev->queue->limits.discard_granularity = stripe; /* diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index dd13e3a4c27..4ef0d80b57f 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -163,19 +163,21 @@ source "drivers/media/common/Kconfig" # config MEDIA_SUBDRV_AUTOSELECT - bool "Autoselect analog and hybrid tuner modules to build" - depends on MEDIA_TUNER + bool "Autoselect tuners and i2c modules to build" + depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT default y help - By default, a TV driver auto-selects all possible tuners - thar could be used by the driver. + By default, a media driver auto-selects all possible i2c + devices that are used by any of the supported devices. This is generally the right thing to do, except when there - are strict constraints with regards to the kernel size. + are strict constraints with regards to the kernel size, + like on embedded systems. - Use this option with care, as deselecting tuner drivers which - are in fact necessary will result in TV devices which cannot - be tuned due to lack of the tuning driver. + Use this option with care, as deselecting ancillary drivers which + are, in fact, necessary will result in the lack of the needed + functionality for your device (it may not tune or may not have + the need demodulers). If unsure say Y. diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 660bbc52886..4d50da61816 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = { MMC_CAP_CMD23, }; -static struct dw_mci_drv_data exynos5250_drv_data = { +static const struct dw_mci_drv_data exynos5250_drv_data = { .caps = exynos5250_dwmmc_caps, .init = dw_mci_exynos_priv_init, .setup_clock = dw_mci_exynos_setup_clock, @@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = { static const struct of_device_id dw_mci_exynos_match[] = { { .compatible = "samsung,exynos5250-dw-mshc", - .data = (void *)&exynos5250_drv_data, }, + .data = &exynos5250_drv_data, }, {}, }; -MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); +MODULE_DEVICE_TABLE(of, dw_mci_exynos_match); int dw_mci_exynos_probe(struct platform_device *pdev) { - struct dw_mci_drv_data *drv_data; + const struct dw_mci_drv_data *drv_data; const struct of_device_id *match; match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index c960ca7ffbe..917936bee5d 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -24,7 +24,7 @@ #include "dw_mmc.h" int dw_mci_pltfm_register(struct platform_device *pdev, - struct dw_mci_drv_data *drv_data) + const struct dw_mci_drv_data *drv_data) { struct dw_mci *host; struct resource *regs; @@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev, if (!host->regs) return -ENOMEM; - if (host->drv_data->init) { - ret = host->drv_data->init(host); + if (drv_data && drv_data->init) { + ret = drv_data->init(host); if (ret) return ret; } diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h index 301f24541fc..2ac37b81de4 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.h +++ b/drivers/mmc/host/dw_mmc-pltfm.h @@ -13,7 +13,7 @@ #define _DW_MMC_PLTFM_H_ extern int dw_mci_pltfm_register(struct platform_device *pdev, - struct dw_mci_drv_data *drv_data); + const struct dw_mci_drv_data *drv_data); extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev); extern const struct dev_pm_ops dw_mci_pltfm_pmops; diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index c2828f35c3b..c0667c8af2b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) { struct mmc_data *data; struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci_drv_data *drv_data = slot->host->drv_data; u32 cmdr; cmd->error = -EINPROGRESS; @@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) cmdr |= SDMMC_CMD_DAT_WR; } - if (slot->host->drv_data->prepare_command) - slot->host->drv_data->prepare_command(slot->host, &cmdr); + if (drv_data && drv_data->prepare_command) + drv_data->prepare_command(slot->host, &cmdr); return cmdr; } @@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host) return 0; } -static struct dw_mci_dma_ops dw_mci_idmac_ops = { +static const struct dw_mci_dma_ops dw_mci_idmac_ops = { .init = dw_mci_idmac_init, .start = dw_mci_idmac_start_dma, .stop = dw_mci_idmac_stop_dma, @@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci_drv_data *drv_data = slot->host->drv_data; u32 regs; /* set default 1 bit mode */ @@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) slot->clock = ios->clock; } - if (slot->host->drv_data->set_ios) - slot->host->drv_data->set_ios(slot->host, ios); + if (drv_data && drv_data->set_ios) + drv_data->set_ios(slot->host, ios); switch (ios->power_mode) { case MMC_POWER_UP: @@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) { struct mmc_host *mmc; struct dw_mci_slot *slot; + struct dw_mci_drv_data *drv_data = host->drv_data; int ctrl_id, ret; u8 bus_width; @@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) } else { ctrl_id = to_platform_device(host->dev)->id; } - if (host->drv_data && host->drv_data->caps) - mmc->caps |= host->drv_data->caps[ctrl_id]; + if (drv_data && drv_data->caps) + mmc->caps |= drv_data->caps[ctrl_id]; if (host->pdata->caps2) mmc->caps2 = host->pdata->caps2; @@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) else bus_width = 1; - if (host->drv_data->setup_bus) { + if (drv_data && drv_data->setup_bus) { struct device_node *slot_np; slot_np = dw_mci_of_find_slot_node(host->dev, slot->id); - ret = host->drv_data->setup_bus(host, slot_np, bus_width); + ret = drv_data->setup_bus(host, slot_np, bus_width); if (ret) goto err_setup_bus; } @@ -1968,7 +1971,7 @@ static void dw_mci_init_dma(struct dw_mci *host) /* Determine which DMA interface to use */ #ifdef CONFIG_MMC_DW_IDMAC host->dma_ops = &dw_mci_idmac_ops; - dev_info(&host->dev, "Using internal DMA controller.\n"); + dev_info(host->dev, "Using internal DMA controller.\n"); #endif if (!host->dma_ops) @@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) struct dw_mci_board *pdata; struct device *dev = host->dev; struct device_node *np = dev->of_node; + struct dw_mci_drv_data *drv_data = host->drv_data; int idx, ret; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); @@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); - if (host->drv_data->parse_dt) { - ret = host->drv_data->parse_dt(host); + if (drv_data && drv_data->parse_dt) { + ret = drv_data->parse_dt(host); if (ret) return ERR_PTR(ret); } @@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) int dw_mci_probe(struct dw_mci *host) { + struct dw_mci_drv_data *drv_data = host->drv_data; int width, i, ret = 0; u32 fifo_size; int init_slots = 0; @@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host) else host->bus_hz = clk_get_rate(host->ciu_clk); - if (host->drv_data->setup_clock) { - ret = host->drv_data->setup_clock(host); + if (drv_data && drv_data->setup_clock) { + ret = drv_data->setup_clock(host); if (ret) { dev_err(host->dev, "implementation specific clock setup failed\n"); @@ -2228,6 +2233,21 @@ int dw_mci_probe(struct dw_mci *host) else host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; + /* + * Enable interrupts for command done, data over, data empty, card det, + * receive ready and error such as transmit, receive timeout, crc error + */ + mci_writel(host, RINTSTS, 0xFFFFFFFF); + mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | + SDMMC_INT_TXDR | SDMMC_INT_RXDR | + DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); + mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ + + dev_info(host->dev, "DW MMC controller at irq %d, " + "%d bit host data width, " + "%u deep fifo\n", + host->irq, width, fifo_size); + /* We need at least one slot to succeed */ for (i = 0; i < host->num_slots; i++) { ret = dw_mci_init_slot(host, i); @@ -2257,20 +2277,6 @@ int dw_mci_probe(struct dw_mci *host) else host->data_offset = DATA_240A_OFFSET; - /* - * Enable interrupts for command done, data over, data empty, card det, - * receive ready and error such as transmit, receive timeout, crc error - */ - mci_writel(host, RINTSTS, 0xFFFFFFFF); - mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | - SDMMC_INT_TXDR | SDMMC_INT_RXDR | - DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); - mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ - - dev_info(host->dev, "DW MMC controller at irq %d, " - "%d bit host data width, " - "%u deep fifo\n", - host->irq, width, fifo_size); if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 565c2e4fac7..6290b7f1ccf 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -1134,4 +1134,4 @@ module_platform_driver(mxcmci_driver); MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); MODULE_AUTHOR("Sascha Hauer, Pengutronix"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-mmc"); +MODULE_ALIAS("platform:mxc-mmc"); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 54bfd0cc106..fedd258cc4e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -178,7 +178,8 @@ struct omap_hsmmc_host { static int omap_hsmmc_card_detect(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; /* NOTE: assumes card detect signal is active-low */ return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -186,7 +187,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) static int omap_hsmmc_get_wp(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; /* NOTE: assumes write protect signal is active-high */ return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); @@ -194,7 +196,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot) static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; /* NOTE: assumes card detect signal is active-low */ return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -204,7 +207,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; disable_irq(mmc->slots[0].card_detect_irq); return 0; @@ -212,7 +216,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; enable_irq(mmc->slots[0].card_detect_irq); return 0; @@ -2009,9 +2014,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev) clk_put(host->dbclk); } - mmc_free_host(host->mmc); + omap_hsmmc_gpio_free(host->pdata); iounmap(host->base); - omap_hsmmc_gpio_free(pdev->dev.platform_data); + mmc_free_host(host->mmc); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 90140eb03e3..8fd50a21103 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -19,6 +19,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/err.h> #include <linux/io.h> #include <linux/clk.h> #include <linux/err.h> @@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev) struct sdhci_dove_priv *priv; int ret; - ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); - if (ret) - goto sdhci_dove_register_fail; - priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), GFP_KERNEL); if (!priv) { dev_err(&pdev->dev, "unable to allocate private data"); - ret = -ENOMEM; - goto sdhci_dove_allocate_fail; + return -ENOMEM; } + priv->clk = clk_get(&pdev->dev, NULL); + if (!IS_ERR(priv->clk)) + clk_prepare_enable(priv->clk); + + ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); + if (ret) + goto sdhci_dove_register_fail; + host = platform_get_drvdata(pdev); pltfm_host = sdhci_priv(host); pltfm_host->priv = priv; - priv->clk = clk_get(&pdev->dev, NULL); - if (!IS_ERR(priv->clk)) - clk_prepare_enable(priv->clk); return 0; -sdhci_dove_allocate_fail: - sdhci_pltfm_unregister(pdev); sdhci_dove_register_fail: + if (!IS_ERR(priv->clk)) { + clk_disable_unprepare(priv->clk); + clk_put(priv->clk); + } return ret; } @@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_dove_priv *priv = pltfm_host->priv; - if (priv->clk) { - if (!IS_ERR(priv->clk)) { - clk_disable_unprepare(priv->clk); - clk_put(priv->clk); - } - devm_kfree(&pdev->dev, priv->clk); + sdhci_pltfm_unregister(pdev); + + if (!IS_ERR(priv->clk)) { + clk_disable_unprepare(priv->clk); + clk_put(priv->clk); } - return sdhci_pltfm_unregister(pdev); + return 0; } static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index ae5fcbfa1ee..63d219f57ca 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host) } #endif +static void esdhc_of_platform_init(struct sdhci_host *host) +{ + u32 vvn; + + vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); + vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; + if (vvn == VENDOR_V_22) + host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; +} + static struct sdhci_ops sdhci_esdhc_ops = { .read_l = esdhc_readl, .read_w = esdhc_readw, @@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { .enable_dma = esdhc_of_enable_dma, .get_max_clock = esdhc_of_get_max_clock, .get_min_clock = esdhc_of_get_min_clock, + .platform_init = esdhc_of_platform_init, #ifdef CONFIG_PM .platform_suspend = esdhc_of_suspend, .platform_resume = esdhc_of_resume, diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 4bb74b042a0..04936f353ce 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -1196,7 +1196,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( return ERR_PTR(-ENODEV); } - if (pci_resource_len(pdev, bar) != 0x100) { + if (pci_resource_len(pdev, bar) < 0x100) { dev_err(&pdev->dev, "Invalid iomem size. You may " "experience problems.\n"); } diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 65551a9709c..27164457f86 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -150,6 +150,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, goto err_remap; } + /* + * Some platforms need to probe the controller to be able to + * determine which caps should be used. + */ + if (host->ops && host->ops->platform_init) + host->ops->platform_init(host); + platform_set_drvdata(pdev, host); return host; diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 2903949594c..a54dd5d7a5f 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -211,8 +211,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) if (ourhost->cur_clk != best_src) { struct clk *clk = ourhost->clk_bus[best_src]; - clk_enable(clk); - clk_disable(ourhost->clk_bus[ourhost->cur_clk]); + clk_prepare_enable(clk); + clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); /* turn clock off to card before changing clock source */ writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); @@ -607,7 +607,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) } /* enable the local io clock and keep it running for the moment. */ - clk_enable(sc->clk_io); + clk_prepare_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; @@ -638,7 +638,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) } #ifndef CONFIG_PM_RUNTIME - clk_enable(sc->clk_bus[sc->cur_clk]); + clk_prepare_enable(sc->clk_bus[sc->cur_clk]); #endif res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -747,13 +747,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) sdhci_s3c_setup_card_detect_gpio(sc); #ifdef CONFIG_PM_RUNTIME - clk_disable(sc->clk_io); + if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) + clk_disable_unprepare(sc->clk_io); #endif return 0; err_req_regs: #ifndef CONFIG_PM_RUNTIME - clk_disable(sc->clk_bus[sc->cur_clk]); + clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); #endif for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { @@ -762,7 +763,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) } err_no_busclks: - clk_disable(sc->clk_io); + clk_disable_unprepare(sc->clk_io); clk_put(sc->clk_io); err_io_clk: @@ -794,7 +795,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) gpio_free(sc->ext_cd_gpio); #ifdef CONFIG_PM_RUNTIME - clk_enable(sc->clk_io); + if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) + clk_prepare_enable(sc->clk_io); #endif sdhci_remove_host(host, 1); @@ -802,14 +804,14 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); #ifndef CONFIG_PM_RUNTIME - clk_disable(sc->clk_bus[sc->cur_clk]); + clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); #endif for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { clk_put(sc->clk_bus[ptr]); } } - clk_disable(sc->clk_io); + clk_disable_unprepare(sc->clk_io); clk_put(sc->clk_io); if (pdev->dev.of_node) { @@ -849,8 +851,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev) ret = sdhci_runtime_suspend_host(host); - clk_disable(ourhost->clk_bus[ourhost->cur_clk]); - clk_disable(busclk); + clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); + clk_disable_unprepare(busclk); return ret; } @@ -861,8 +863,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev) struct clk *busclk = ourhost->clk_io; int ret; - clk_enable(busclk); - clk_enable(ourhost->clk_bus[ourhost->cur_clk]); + clk_prepare_enable(busclk); + clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]); ret = sdhci_runtime_resume_host(host); return ret; } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7922adb4238..c7851c0aabc 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1315,16 +1315,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) */ if ((host->flags & SDHCI_NEEDS_RETUNING) && !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { - /* eMMC uses cmd21 while sd and sdio use cmd19 */ - tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? - MMC_SEND_TUNING_BLOCK_HS200 : - MMC_SEND_TUNING_BLOCK; - spin_unlock_irqrestore(&host->lock, flags); - sdhci_execute_tuning(mmc, tuning_opcode); - spin_lock_irqsave(&host->lock, flags); - - /* Restore original mmc_request structure */ - host->mrq = mrq; + if (mmc->card) { + /* eMMC uses cmd21 but sd and sdio use cmd19 */ + tuning_opcode = + mmc->card->type == MMC_TYPE_MMC ? + MMC_SEND_TUNING_BLOCK_HS200 : + MMC_SEND_TUNING_BLOCK; + spin_unlock_irqrestore(&host->lock, flags); + sdhci_execute_tuning(mmc, tuning_opcode); + spin_lock_irqsave(&host->lock, flags); + + /* Restore original mmc_request structure */ + host->mrq = mrq; + } } if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) @@ -2837,6 +2840,9 @@ int sdhci_add_host(struct sdhci_host *host) if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) mmc->caps |= MMC_CAP_4_BIT_DATA; + if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) + mmc->caps &= ~MMC_CAP_CMD23; + if (caps[0] & SDHCI_CAN_DO_HISPD) mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; @@ -2846,9 +2852,12 @@ int sdhci_add_host(struct sdhci_host *host) /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); - if (IS_ERR(host->vqmmc)) { - pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc)); - host->vqmmc = NULL; + if (IS_ERR_OR_NULL(host->vqmmc)) { + if (PTR_ERR(host->vqmmc) < 0) { + pr_info("%s: no vqmmc regulator found\n", + mmc_hostname(mmc)); + host->vqmmc = NULL; + } } else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000)) regulator_enable(host->vqmmc); @@ -2904,9 +2913,12 @@ int sdhci_add_host(struct sdhci_host *host) ocr_avail = 0; host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); - if (IS_ERR(host->vmmc)) { - pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); - host->vmmc = NULL; + if (IS_ERR_OR_NULL(host->vmmc)) { + if (PTR_ERR(host->vmmc) < 0) { + pr_info("%s: no vmmc regulator found\n", + mmc_hostname(mmc)); + host->vmmc = NULL; + } } else regulator_enable(host->vmmc); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 97653ea8942..71a4a7ed46c 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -278,6 +278,7 @@ struct sdhci_ops { void (*hw_reset)(struct sdhci_host *host); void (*platform_suspend)(struct sdhci_host *host); void (*platform_resume)(struct sdhci_host *host); + void (*platform_init)(struct sdhci_host *host); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 11d2bc3b51d..d25bc97dc5c 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1466,9 +1466,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); + clk_disable(host->hclk); mmc_free_host(host->mmc); pm_runtime_put_sync(&pdev->dev); - clk_disable(host->hclk); pm_runtime_disable(&pdev->dev); return 0; diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 8f52fc858e4..5a5cd2ace4a 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) if (*(szlength) != '+') { devlength = simple_strtoul(szlength, &buffer, 0); - devlength = handle_unit(devlength, buffer) - devstart; + devlength = handle_unit(devlength, buffer); if (devlength < devstart) goto err_out; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ec6841d8e95..1a03b7f673c 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2983,13 +2983,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, /* * Field definitions are in the following datasheets: * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) - * New style (6 byte ID): Samsung K9GAG08U0F (p.44) + * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) * Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) * - * Check for ID length, cell type, and Hynix/Samsung ID to decide what - * to do. + * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung + * ID to decide what to do. */ - if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) { + if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && + (chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + id_data[5] != 0x00) { /* Calc pagesize */ mtd->writesize = 2048 << (extid & 0x03); extid >>= 2; diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 64be8f0848b..d9127e2ed80 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, nr_parts = plen / sizeof(part[0]); *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); - if (!pparts) + if (!*pparts) return -ENOMEM; names = of_get_property(dp, "partition-names", &plen); diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 7153e0d2710..b3f41f20062 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int * flexonenand_set_boundary - Writes the SLC boundary * @param mtd - mtd info structure */ -int flexonenand_set_boundary(struct mtd_info *mtd, int die, +static int flexonenand_set_boundary(struct mtd_info *mtd, int die, int boundary, int lock) { struct onenand_chip *this = mtd->priv; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b721902bb6b..5f5b69f37d2 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1379,6 +1379,8 @@ static void bond_compute_features(struct bonding *bond) struct net_device *bond_dev = bond->dev; netdev_features_t vlan_features = BOND_VLAN_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; + unsigned int gso_max_size = GSO_MAX_SIZE; + u16 gso_max_segs = GSO_MAX_SEGS; int i; unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE; @@ -1394,11 +1396,16 @@ static void bond_compute_features(struct bonding *bond) dst_release_flag &= slave->dev->priv_flags; if (slave->dev->hard_header_len > max_hard_header_len) max_hard_header_len = slave->dev->hard_header_len; + + gso_max_size = min(gso_max_size, slave->dev->gso_max_size); + gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs); } done: bond_dev->vlan_features = vlan_features; bond_dev->hard_header_len = max_hard_header_len; + bond_dev->gso_max_segs = gso_max_segs; + netif_set_gso_max_size(bond_dev, gso_max_size); flags = bond_dev->priv_flags & ~IFF_XMIT_DST_RELEASE; bond_dev->priv_flags = flags | dst_release_flag; @@ -1519,7 +1526,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* no need to lock since we're protected by rtnl_lock */ if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); - if (bond_vlan_used(bond)) { + if (vlan_uses_dev(bond_dev)) { pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n", bond_dev->name, slave_dev->name, bond_dev->name); return -EPERM; diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index dc15d248443..ef8d2a080d1 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d, goto out; } - sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ + sscanf(buf, "%15s", ifname); /* IFNAMSIZ */ /* check to see if we are clearing primary */ if (!strlen(ifname) || buf[0] == '\n') { @@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d, goto out; } - sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ + sscanf(buf, "%15s", ifname); /* IFNAMSIZ */ /* check to see if we are clearing active */ if (!strlen(ifname) || buf[0] == '\n') { diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index c78ecfca1e4..a412bf6d73e 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -144,9 +144,22 @@ #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) -/* FLEXCAN hardware feature flags */ +/* + * FLEXCAN hardware feature flags + * + * Below is some version info we got: + * SOC Version IP-Version Glitch- [TR]WRN_INT + * Filter? connected? + * MX25 FlexCAN2 03.00.00.00 no no + * MX28 FlexCAN2 03.00.04.00 yes yes + * MX35 FlexCAN2 03.00.00.00 no no + * MX53 FlexCAN2 03.00.00.00 yes no + * MX6s FlexCAN3 10.00.12.00 yes yes + * + * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. + */ #define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ -#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* Broken error state handling */ +#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ /* Structure of the message buffer */ struct flexcan_mb { @@ -205,7 +218,7 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = { }; static struct flexcan_devtype_data fsl_imx28_devtype_data; static struct flexcan_devtype_data fsl_imx6q_devtype_data = { - .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE, + .features = FLEXCAN_HAS_V10_FEATURES, }; static const struct can_bittiming_const flexcan_bittiming_const = { diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index f5b82aeb254..6525dbcca4e 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -30,9 +30,10 @@ #include "sja1000.h" -MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>"); +MODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>"); MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards"); MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards"); +MODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards"); MODULE_LICENSE("GPL v2"); #define DRV_NAME "peak_pci" @@ -64,7 +65,11 @@ struct peak_pci_chan { #define PEAK_PCI_DEVICE_ID 0x0001 /* for PCI/PCIe slot cards */ #define PEAK_PCIEC_DEVICE_ID 0x0002 /* for ExpressCard slot cards */ #define PEAK_PCIE_DEVICE_ID 0x0003 /* for nextgen PCIe slot cards */ -#define PEAK_MPCI_DEVICE_ID 0x0008 /* The miniPCI slot cards */ +#define PEAK_CPCI_DEVICE_ID 0x0004 /* for nextgen cPCI slot cards */ +#define PEAK_MPCI_DEVICE_ID 0x0005 /* for nextgen miniPCI slot cards */ +#define PEAK_PC_104P_DEVICE_ID 0x0006 /* PCAN-PC/104+ cards */ +#define PEAK_PCI_104E_DEVICE_ID 0x0007 /* PCAN-PCI/104 Express cards */ +#define PEAK_MPCIE_DEVICE_ID 0x0008 /* The miniPCIe slot cards */ #define PEAK_PCI_CHAN_MAX 4 @@ -76,6 +81,10 @@ static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = { {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, #ifdef CONFIG_CAN_PEAK_PCIEC {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, #endif diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c index d04911d33b6..47618e50535 100644 --- a/drivers/net/ethernet/8390/ne.c +++ b/drivers/net/ethernet/8390/ne.c @@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev) dev->irq = irq[this_dev]; dev->mem_end = bad[this_dev]; } + SET_NETDEV_DEV(dev, &pdev->dev); err = do_ne_probe(dev); if (err) { free_netdev(dev); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 24220992413..4833b6a9031 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -2957,9 +2957,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_shinfo(skb)->nr_frags + BDS_PER_TX_PKT + NEXT_CNT_PER_TX_PKT(MAX_BDS_PER_TX_PKT))) { - bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++; - netif_tx_stop_queue(txq); - BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); + /* Handle special storage cases separately */ + if (txdata->tx_ring_size != 0) { + BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); + bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++; + netif_tx_stop_queue(txq); + } + return NETDEV_TX_BUSY; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c65295dded3..6e5bdd1a31d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1702,7 +1702,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata) SHMEM_EEE_ADV_STATUS_SHIFT); if ((advertised != (eee_cfg & SHMEM_EEE_ADV_STATUS_MASK))) { DP(BNX2X_MSG_ETHTOOL, - "Direct manipulation of EEE advertisment is not supported\n"); + "Direct manipulation of EEE advertisement is not supported\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index e2e45ee5df3..f6cfdc6cf20 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -137,7 +137,16 @@ #define LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD #define LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD - +#define LINK_UPDATE_MASK \ + (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \ + LINK_STATUS_LINK_UP | \ + LINK_STATUS_PHYSICAL_LINK_FLAG | \ + LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \ + LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \ + LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \ + LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \ + LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \ + LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE) #define SFP_EEPROM_CON_TYPE_ADDR 0x2 #define SFP_EEPROM_CON_TYPE_VAL_LC 0x7 @@ -3295,6 +3304,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port) DEFAULT_PHY_DEV_ADDR); } +static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy, + struct link_params *params, + u32 action) +{ + struct bnx2x *bp = params->bp; + switch (action) { + case PHY_INIT: + /* Set correct devad */ + REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0); + REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18, + phy->def_md_devad); + break; + } +} + static void bnx2x_xgxs_deassert(struct link_params *params) { struct bnx2x *bp = params->bp; @@ -3309,10 +3333,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params) REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val); udelay(500); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); - - REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0); - REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, - params->phy[INT_PHY].def_md_devad); + bnx2x_xgxs_specific_func(¶ms->phy[INT_PHY], params, + PHY_INIT); } static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy, @@ -3545,14 +3567,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy, static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, struct link_params *params, struct link_vars *vars) { - u16 val16 = 0, lane, i; + u16 lane, i, cl72_ctrl, an_adv = 0; + u16 ucode_ver; struct bnx2x *bp = params->bp; static struct bnx2x_reg_set reg_set[] = { {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, - {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0}, - {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0}, - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff}, - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555}, {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0}, {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415}, {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190}, @@ -3565,12 +3584,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl); + cl72_ctrl &= 0xf8ff; + cl72_ctrl |= 0x3800; + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl); + /* Check adding advertisement for 1G KX */ if (((vars->line_speed == SPEED_AUTO_NEG) && (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || (vars->line_speed == SPEED_1000)) { u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2; - val16 |= (1<<5); + an_adv |= (1<<5); /* Enable CL37 1G Parallel Detect */ bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1); @@ -3580,11 +3606,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) || (vars->line_speed == SPEED_10000)) { /* Check adding advertisement for 10G KR */ - val16 |= (1<<7); + an_adv |= (1<<7); /* Enable 10G Parallel Detect */ + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, 0); + bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 1); - + bnx2x_set_aer_mmd(params, phy); DP(NETIF_MSG_LINK, "Advertize 10G\n"); } @@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, /* Advertised speeds */ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, - MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16); + MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv); /* Advertised and set FEC (Forward Error Correction) */ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, @@ -3628,9 +3657,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, /* Set KR Autoneg Work-Around flag for Warpcore version older than D108 */ bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_UC_INFO_B1_VERSION, &val16); - if (val16 < 0xd108) { - DP(NETIF_MSG_LINK, "Enable AN KR work-around\n"); + MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver); + if (ucode_ver < 0xd108) { + DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n", + ucode_ver); vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY; } bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, @@ -3651,21 +3681,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, struct link_vars *vars) { struct bnx2x *bp = params->bp; - u16 i; + u16 val16, i, lane; static struct bnx2x_reg_set reg_set[] = { /* Disable Autoneg */ {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, - {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0}, {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0x3f00}, {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0}, {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa}, - /* Disable CL36 PCS Tx */ - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0}, - /* Double Wide Single Data Rate @ pll rate */ - {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF}, /* Leave cl72 training enable, needed for KR */ {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150, @@ -3676,11 +3701,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg, reg_set[i].val); - /* Leave CL72 enabled */ - bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, - MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, - 0x3800); + lane = bnx2x_get_warpcore_lane(phy, params); + /* Global registers */ + CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, + MDIO_AER_BLOCK_AER_REG, 0); + /* Disable CL36 PCS Tx */ + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); + val16 &= ~(0x0011 << lane); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); + val16 |= (0x0303 << (lane << 1)); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); + /* Restore AER */ + bnx2x_set_aer_mmd(params, phy); /* Set speed via PMA/PMD register */ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040); @@ -4303,7 +4341,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy, struct link_params *params) { struct bnx2x *bp = params->bp; - u16 val16; + u16 val16, lane; bnx2x_sfp_e3_set_transmitter(params, phy, 0); bnx2x_set_mdio_clk(bp, params->chip_id, params->port); bnx2x_set_aer_mmd(params, phy); @@ -4340,6 +4378,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy, MDIO_WC_REG_XGXSBLK1_LANECTRL2, val16 & 0xff00); + lane = bnx2x_get_warpcore_lane(phy, params); + /* Disable CL36 PCS Tx */ + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); + val16 |= (0x11 << lane); + if (phy->flags & FLAGS_WC_DUAL_MODE) + val16 |= (0x22 << lane); + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); + + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); + val16 &= ~(0x0303 << (lane << 1)); + val16 |= (0x0101 << (lane << 1)); + if (phy->flags & FLAGS_WC_DUAL_MODE) { + val16 &= ~(0x0c0c << (lane << 1)); + val16 |= (0x0404 << (lane << 1)); + } + + bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); + /* Restore AER */ + bnx2x_set_aer_mmd(params, phy); + } static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy, @@ -6296,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params, vars->mac_type = MAC_TYPE_NONE; /* Update shared memory */ - vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK | - LINK_STATUS_LINK_UP | - LINK_STATUS_PHYSICAL_LINK_FLAG | - LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | - LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | - LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | - LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | - LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | - LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE); + vars->link_status &= ~LINK_UPDATE_MASK; vars->line_speed = 0; bnx2x_update_mng(params, vars->link_status); @@ -6452,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars) u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed; u8 active_external_phy = INT_PHY; vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; + vars->link_status &= ~LINK_UPDATE_MASK; for (phy_index = INT_PHY; phy_index < params->num_phys; phy_index++) { phy_vars[phy_index].flow_ctrl = 0; @@ -7579,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params, static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy, struct link_params *params, u16 addr, u8 byte_cnt, - u8 *o_buf) + u8 *o_buf, u8 is_init) { int rc = 0; u8 i, j = 0, cnt = 0; @@ -7596,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy, /* 4 byte aligned address */ addr32 = addr & (~0x3); do { - if (cnt == I2C_WA_PWR_ITER) { + if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) { bnx2x_warpcore_power_module(params, phy, 0); /* Note that 100us are not enough here */ - usleep_range(1000,1000); + usleep_range(1000, 2000); bnx2x_warpcore_power_module(params, phy, 1); } rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt, @@ -7719,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy, break; case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr, - byte_cnt, o_buf); + byte_cnt, o_buf, 0); break; } return rc; @@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, { u8 val; + int rc; struct bnx2x *bp = params->bp; u16 timeout; /* Initialization time after hot-plug may take up to 300ms for @@ -7930,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, */ for (timeout = 0; timeout < 60; timeout++) { - if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val) - == 0) { + if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) + rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, + params, 1, + 1, &val, 1); + else + rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, + &val); + if (rc == 0) { DP(NETIF_MSG_LINK, "SFP+ module initialization took %d ms\n", timeout * 5); @@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, } usleep_range(5000, 10000); } - return -EINVAL; + rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val); + return rc; } static void bnx2x_8727_power_module(struct bnx2x *bp, @@ -9878,7 +9941,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, else rc = bnx2x_8483x_disable_eee(phy, params, vars); if (rc) { - DP(NETIF_MSG_LINK, "Failed to set EEE advertisment\n"); + DP(NETIF_MSG_LINK, "Failed to set EEE advertisement\n"); return rc; } } else { @@ -10993,7 +11056,7 @@ static struct bnx2x_phy phy_xgxs = { .format_fw_ver = (format_fw_ver_t)NULL, .hw_reset = (hw_reset_t)NULL, .set_link_led = (set_link_led_t)NULL, - .phy_specific_func = (phy_specific_func_t)NULL + .phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func }; static struct bnx2x_phy phy_warpcore = { .type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, @@ -11465,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, phy->media_type = ETH_PHY_BASE_T; break; case PORT_HW_CFG_NET_SERDES_IF_XFI: + phy->supported &= (SUPPORTED_1000baseT_Full | + SUPPORTED_10000baseT_Full | + SUPPORTED_FIBRE | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause); phy->media_type = ETH_PHY_XFP_FIBER; break; case PORT_HW_CFG_NET_SERDES_IF_SFI: @@ -12919,7 +12987,7 @@ static u8 bnx2x_analyze_link_error(struct link_params *params, DP(NETIF_MSG_LINK, "Analyze TX Fault\n"); break; default: - DP(NETIF_MSG_LINK, "Analyze UNKOWN\n"); + DP(NETIF_MSG_LINK, "Analyze UNKNOWN\n"); } DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up, old_status, status); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index d5648fc666b..01611b33a93 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp) bnx2x_init_block(bp, BLOCK_DORQ, init_phase); + bnx2x_init_block(bp, BLOCK_BRB1, init_phase); + if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) { - bnx2x_init_block(bp, BLOCK_BRB1, init_phase); if (IS_MF(bp)) low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246); @@ -9544,10 +9545,13 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) */ static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp) { - u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); - if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { - BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); - REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp)); + if (!CHIP_IS_E1x(bp)) { + u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); + if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { + BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); + REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, + 1 << BP_FUNC(bp)); + } } } @@ -11902,7 +11906,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, /* disable FCOE L2 queue for E1x */ if (CHIP_IS_E1x(bp)) bp->flags |= NO_FCOE_FLAG; - + /* disable FCOE for 57840 device, until FW supports it */ + switch (ent->driver_data) { + case BCM57840_O: + case BCM57840_4_10: + case BCM57840_2_20: + case BCM57840_MFO: + case BCM57840_MF: + bp->flags |= NO_FCOE_FLAG; + } #endif diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 71971a161bd..614981c0226 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -126,7 +126,7 @@ static inline int bnx2x_exe_queue_add(struct bnx2x *bp, /* Check if this request is ok */ rc = o->validate(bp, o->owner, elem); if (rc) { - BNX2X_ERR("Preamble failed: %d\n", rc); + DP(BNX2X_MSG_SP, "Preamble failed: %d\n", rc); goto free_and_exit; } } diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index a4da893ac1e..378988b5709 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -251,6 +251,8 @@ struct adapter_params { unsigned char rev; /* chip revision */ unsigned char offload; + unsigned char bypass; + unsigned int ofldq_wr_cred; }; @@ -642,6 +644,23 @@ extern int dbfifo_int_thresh; #define for_each_port(adapter, iter) \ for (iter = 0; iter < (adapter)->params.nports; ++iter) +static inline int is_bypass(struct adapter *adap) +{ + return adap->params.bypass; +} + +static inline int is_bypass_device(int device) +{ + /* this should be set based upon device capabilities */ + switch (device) { + case 0x440b: + case 0x440c: + return 1; + default: + return 0; + } +} + static inline unsigned int core_ticks_per_usec(const struct adapter *adap) { return adap->params.vpd.cclk / 1000; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 604f4f87f55..0df1284df49 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3416,16 +3416,6 @@ static int adap_init0_config(struct adapter *adapter, int reset) finicsum, cfcsum); /* - * If we're a pure NIC driver then disable all offloading facilities. - * This will allow the firmware to optimize aspects of the hardware - * configuration which will result in improved performance. - */ - caps_cmd.ofldcaps = 0; - caps_cmd.iscsicaps = 0; - caps_cmd.rdmacaps = 0; - caps_cmd.fcoecaps = 0; - - /* * And now tell the firmware to use the configuration we just loaded. */ caps_cmd.op_to_write = @@ -3513,18 +3503,6 @@ static int adap_init0_no_config(struct adapter *adapter, int reset) if (ret < 0) goto bye; -#ifndef CONFIG_CHELSIO_T4_OFFLOAD - /* - * If we're a pure NIC driver then disable all offloading facilities. - * This will allow the firmware to optimize aspects of the hardware - * configuration which will result in improved performance. - */ - caps_cmd.ofldcaps = 0; - caps_cmd.iscsicaps = 0; - caps_cmd.rdmacaps = 0; - caps_cmd.fcoecaps = 0; -#endif - if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) { if (!vf_acls) caps_cmd.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM); @@ -3745,6 +3723,7 @@ static int adap_init0(struct adapter *adap) u32 v, port_vec; enum dev_state state; u32 params[7], val[7]; + struct fw_caps_config_cmd caps_cmd; int reset = 1, j; /* @@ -3898,6 +3877,9 @@ static int adap_init0(struct adapter *adap) goto bye; } + if (is_bypass_device(adap->pdev->device)) + adap->params.bypass = 1; + /* * Grab some of our basic fundamental operating parameters. */ @@ -3940,13 +3922,12 @@ static int adap_init0(struct adapter *adap) adap->tids.aftid_end = val[1]; } -#ifdef CONFIG_CHELSIO_T4_OFFLOAD /* * Get device capabilities so we can determine what resources we need * to manage. */ memset(&caps_cmd, 0, sizeof(caps_cmd)); - caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | + caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | FW_CMD_REQUEST | FW_CMD_READ); caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd)); ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd), @@ -3991,15 +3972,6 @@ static int adap_init0(struct adapter *adap) adap->vres.ddp.size = val[4] - val[3] + 1; adap->params.ofldq_wr_cred = val[5]; - params[0] = FW_PARAM_PFVF(ETHOFLD_START); - params[1] = FW_PARAM_PFVF(ETHOFLD_END); - ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, - params, val); - if ((val[0] != val[1]) && (ret >= 0)) { - adap->tids.uotid_base = val[0]; - adap->tids.nuotids = val[1] - val[0] + 1; - } - adap->params.offload = 1; } if (caps_cmd.rdmacaps) { @@ -4048,7 +4020,6 @@ static int adap_init0(struct adapter *adap) } #undef FW_PARAM_PFVF #undef FW_PARAM_DEV -#endif /* CONFIG_CHELSIO_T4_OFFLOAD */ /* * These are finalized by FW initialization, load their values now. diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 1b899fea1a9..39bec73ff87 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -102,6 +102,9 @@ struct tid_info { unsigned int ftid_base; unsigned int aftid_base; unsigned int aftid_end; + /* Server filter region */ + unsigned int sftid_base; + unsigned int nsftids; spinlock_t atid_lock ____cacheline_aligned_in_smp; union aopen_entry *afree; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 32eec15fe4c..730ae2cfa49 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -2519,6 +2519,7 @@ int t4_fw_bye(struct adapter *adap, unsigned int mbox) { struct fw_bye_cmd c; + memset(&c, 0, sizeof(c)); INIT_CMD(c, BYE, WRITE); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -2535,6 +2536,7 @@ int t4_early_init(struct adapter *adap, unsigned int mbox) { struct fw_initialize_cmd c; + memset(&c, 0, sizeof(c)); INIT_CMD(c, INITIALIZE, WRITE); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -2551,6 +2553,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset) { struct fw_reset_cmd c; + memset(&c, 0, sizeof(c)); INIT_CMD(c, RESET, WRITE); c.val = htonl(reset); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); @@ -2828,7 +2831,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size, HOSTPAGESIZEPF7(sge_hps)); t4_set_reg_field(adap, SGE_CONTROL, - INGPADBOUNDARY(INGPADBOUNDARY_MASK) | + INGPADBOUNDARY_MASK | EGRSTATUSPAGESIZE_MASK, INGPADBOUNDARY(fl_align_log - 5) | EGRSTATUSPAGESIZE(stat_len != 64)); @@ -3278,6 +3281,7 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid, { struct fw_vi_enable_cmd c; + memset(&c, 0, sizeof(c)); c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST | FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid)); c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c)); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 1d03dcdd5e5..19ac096cb07 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1353,8 +1353,11 @@ static int gfar_restore(struct device *dev) struct gfar_private *priv = dev_get_drvdata(dev); struct net_device *ndev = priv->ndev; - if (!netif_running(ndev)) + if (!netif_running(ndev)) { + netif_device_attach(ndev); + return 0; + } gfar_init_bds(ndev); init_registers(ndev); diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c index b9db0e04056..2e5daee0438 100644 --- a/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -478,7 +478,7 @@ static int gianfar_ptp_probe(struct platform_device *dev) pr_err("no resource\n"); goto no_resource; } - if (request_resource(&ioport_resource, etsects->rsrc)) { + if (request_resource(&iomem_resource, etsects->rsrc)) { pr_err("resource busy\n"); goto no_resource; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 56b20d17d0e..116f0e901be 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev, case ixgbe_mac_X540: case ixgbe_mac_82599EB: info->so_timestamping = + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index f8064df10cc..60ac46f4ac0 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -1860,10 +1860,14 @@ jme_open(struct net_device *netdev) jme_clear_pm(jme); JME_NAPI_ENABLE(jme); - tasklet_enable(&jme->linkch_task); - tasklet_enable(&jme->txclean_task); - tasklet_hi_enable(&jme->rxclean_task); - tasklet_hi_enable(&jme->rxempty_task); + tasklet_init(&jme->linkch_task, jme_link_change_tasklet, + (unsigned long) jme); + tasklet_init(&jme->txclean_task, jme_tx_clean_tasklet, + (unsigned long) jme); + tasklet_init(&jme->rxclean_task, jme_rx_clean_tasklet, + (unsigned long) jme); + tasklet_init(&jme->rxempty_task, jme_rx_empty_tasklet, + (unsigned long) jme); rc = jme_request_irq(jme); if (rc) @@ -1948,10 +1952,10 @@ jme_close(struct net_device *netdev) JME_NAPI_DISABLE(jme); - tasklet_disable(&jme->linkch_task); - tasklet_disable(&jme->txclean_task); - tasklet_disable(&jme->rxclean_task); - tasklet_disable(&jme->rxempty_task); + tasklet_kill(&jme->linkch_task); + tasklet_kill(&jme->txclean_task); + tasklet_kill(&jme->rxclean_task); + tasklet_kill(&jme->rxempty_task); jme_disable_rx_engine(jme); jme_disable_tx_engine(jme); @@ -3079,22 +3083,6 @@ jme_init_one(struct pci_dev *pdev, tasklet_init(&jme->pcc_task, jme_pcc_tasklet, (unsigned long) jme); - tasklet_init(&jme->linkch_task, - jme_link_change_tasklet, - (unsigned long) jme); - tasklet_init(&jme->txclean_task, - jme_tx_clean_tasklet, - (unsigned long) jme); - tasklet_init(&jme->rxclean_task, - jme_rx_clean_tasklet, - (unsigned long) jme); - tasklet_init(&jme->rxempty_task, - jme_rx_empty_tasklet, - (unsigned long) jme); - tasklet_disable_nosync(&jme->linkch_task); - tasklet_disable_nosync(&jme->txclean_task); - tasklet_disable_nosync(&jme->rxclean_task); - tasklet_disable_nosync(&jme->rxempty_task); jme->dpi.cur = PCC_P1; jme->reg_ghc = 0; diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 9b9c2ac5c4c..d19a143aa5a 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -4026,7 +4026,7 @@ static void __devexit skge_remove(struct pci_dev *pdev) dev0 = hw->dev[0]; unregister_netdev(dev0); - tasklet_disable(&hw->phy_task); + tasklet_kill(&hw->phy_task); spin_lock_irq(&hw->hw_lock); hw->intr_mask = 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index c10e3a6de09..b35094c590b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -143,7 +143,6 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, mlx4_bf_free(mdev->dev, &ring->bf); mlx4_qp_remove(mdev->dev, &ring->qp); mlx4_qp_free(mdev->dev, &ring->qp); - mlx4_qp_release_range(mdev->dev, ring->qpn, 1); mlx4_en_unmap_buffer(&ring->wqres.buf); mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size); kfree(ring->bounce_buf); @@ -712,7 +711,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) if (bounce) tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size); - if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) { + if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tx_tag_present(skb)) { *(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn); op_own |= htonl((bf_index & 0xffff) << 8); /* Ensure new descirptor hits memory diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 51c764901ad..b84a88bc44d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -329,9 +329,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave, ctx = &priv->mfunc.master.slave_state[slave]; spin_lock_irqsave(&ctx->lock, flags); - mlx4_dbg(dev, "%s: slave: %d, current state: %d new event :%d\n", - __func__, slave, cur_state, event); - switch (cur_state) { case SLAVE_PORT_DOWN: if (MLX4_PORT_STATE_DEV_EVENT_PORT_UP == event) @@ -366,9 +363,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave, goto out; } ret = mlx4_get_slave_port_state(dev, slave, port); - mlx4_dbg(dev, "%s: slave: %d, current state: %d new event" - " :%d gen_event: %d\n", - __func__, slave, cur_state, event, *gen_event); out: spin_unlock_irqrestore(&ctx->lock, flags); @@ -843,6 +837,18 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq) return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4); } +static void mlx4_unmap_uar(struct mlx4_dev *dev) +{ + struct mlx4_priv *priv = mlx4_priv(dev); + int i; + + for (i = 0; i < mlx4_num_eq_uar(dev); ++i) + if (priv->eq_table.uar_map[i]) { + iounmap(priv->eq_table.uar_map[i]); + priv->eq_table.uar_map[i] = NULL; + } +} + static int mlx4_create_eq(struct mlx4_dev *dev, int nent, u8 intr, struct mlx4_eq *eq) { @@ -1207,6 +1213,7 @@ err_out_unmap: mlx4_free_irqs(dev); err_out_bitmap: + mlx4_unmap_uar(dev); mlx4_bitmap_cleanup(&priv->eq_table.bitmap); err_out_free: @@ -1231,10 +1238,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev) if (!mlx4_is_slave(dev)) mlx4_unmap_clr_int(dev); - for (i = 0; i < mlx4_num_eq_uar(dev); ++i) - if (priv->eq_table.uar_map[i]) - iounmap(priv->eq_table.uar_map[i]); - + mlx4_unmap_uar(dev); mlx4_bitmap_cleanup(&priv->eq_table.bitmap); kfree(priv->eq_table.uar_map); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 80df2ab0177..2aa80afd98d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1405,7 +1405,10 @@ unmap_bf: unmap_bf_area(dev); err_close: - mlx4_close_hca(dev); + if (mlx4_is_slave(dev)) + mlx4_slave_exit(dev); + else + mlx4_CLOSE_HCA(dev, 0); err_free_icm: if (!mlx4_is_slave(dev)) diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 926c911c0ac..b05705f50f0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -330,9 +330,6 @@ static void update_pkey_index(struct mlx4_dev *dev, int slave, new_index = priv->virt2phys_pkey[slave][port - 1][orig_index]; *(u8 *)(inbox->buf + 35) = new_index; - - mlx4_dbg(dev, "port = %d, orig pkey index = %d, " - "new pkey index = %d\n", port, orig_index, new_index); } static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox, @@ -351,9 +348,6 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox, if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH) qp_ctx->alt_path.mgid_index = slave & 0x7F; } - - mlx4_dbg(dev, "slave %d, new gid index: 0x%x ", - slave, qp_ctx->pri_path.mgid_index); } static int mpt_mask(struct mlx4_dev *dev) diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 318fee91c79..69e01977a1d 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -5407,8 +5407,8 @@ static int netdev_close(struct net_device *dev) /* Delay for receive task to stop scheduling itself. */ msleep(2000 / HZ); - tasklet_disable(&hw_priv->rx_tasklet); - tasklet_disable(&hw_priv->tx_tasklet); + tasklet_kill(&hw_priv->rx_tasklet); + tasklet_kill(&hw_priv->tx_tasklet); free_irq(dev->irq, hw_priv->dev); transmit_cleanup(hw_priv, 0); @@ -5459,8 +5459,10 @@ static int prepare_hardware(struct net_device *dev) rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev); if (rc) return rc; - tasklet_enable(&hw_priv->rx_tasklet); - tasklet_enable(&hw_priv->tx_tasklet); + tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, + (unsigned long) hw_priv); + tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, + (unsigned long) hw_priv); hw->promiscuous = 0; hw->all_multi = 0; @@ -7033,16 +7035,6 @@ static int __devinit pcidev_init(struct pci_dev *pdev, spin_lock_init(&hw_priv->hwlock); mutex_init(&hw_priv->lock); - /* tasklet is enabled. */ - tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, - (unsigned long) hw_priv); - tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, - (unsigned long) hw_priv); - - /* tasklet_enable will decrement the atomic counter. */ - tasklet_disable(&hw_priv->rx_tasklet); - tasklet_disable(&hw_priv->tx_tasklet); - for (i = 0; i < TOTAL_PORT_NUM; i++) init_waitqueue_head(&hw_priv->counter[i].counter); diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 53743f7a2ca..af8b4142088 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) pldat->dma_buff_base_p); free_irq(ndev->irq, ndev); iounmap(pldat->net_base); + mdiobus_unregister(pldat->mii_bus); mdiobus_free(pldat->mii_bus); clk_disable(pldat->clk); clk_put(pldat->clk); diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index b2a94d02a52..4c4fe5b1a29 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -339,26 +339,6 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit) } /** - * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context - * @reg: Pointer of register - * @busy: Busy bit - */ -static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit) -{ - u32 tmp; - int ret = -1; - /* wait busy */ - tmp = 20; - while ((ioread32(reg) & bit) && --tmp) - udelay(5); - if (!tmp) - pr_err("Error: busy bit is not cleared\n"); - else - ret = 0; - return ret; -} - -/** * pch_gbe_mac_mar_set - Set MAC address register * @hw: Pointer to the HW structure * @addr: Pointer to the MAC address @@ -409,15 +389,20 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw) return; } -static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw) +static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw) { - /* Read the MAC addresses. and store to the private data */ - pch_gbe_mac_read_mac_addr(hw); - iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET); - pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST); - /* Setup the MAC addresses */ - pch_gbe_mac_mar_set(hw, hw->mac.addr, 0); - return; + u32 rctl; + /* Disables Receive MAC */ + rctl = ioread32(&hw->reg->MAC_RX_EN); + iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); +} + +static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw) +{ + u32 rctl; + /* Enables Receive MAC */ + rctl = ioread32(&hw->reg->MAC_RX_EN); + iowrite32((rctl | PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); } /** @@ -913,7 +898,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter) static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) { struct pch_gbe_hw *hw = &adapter->hw; - u32 rdba, rdlen, rctl, rxdma; + u32 rdba, rdlen, rxdma; pr_debug("dma adr = 0x%08llx size = 0x%08x\n", (unsigned long long)adapter->rx_ring->dma, @@ -921,9 +906,7 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter) pch_gbe_mac_force_mac_fc(hw); - /* Disables Receive MAC */ - rctl = ioread32(&hw->reg->MAC_RX_EN); - iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN); + pch_gbe_disable_mac_rx(hw); /* Disables Receive DMA */ rxdma = ioread32(&hw->reg->DMA_CTRL); @@ -1316,38 +1299,17 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter) spin_unlock_irqrestore(&adapter->stats_lock, flags); } -static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter) +static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw) { - struct pch_gbe_hw *hw = &adapter->hw; u32 rxdma; - u16 value; - int ret; /* Disable Receive DMA */ rxdma = ioread32(&hw->reg->DMA_CTRL); rxdma &= ~PCH_GBE_RX_DMA_EN; iowrite32(rxdma, &hw->reg->DMA_CTRL); - /* Wait Rx DMA BUS is IDLE */ - ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK); - if (ret) { - /* Disable Bus master */ - pci_read_config_word(adapter->pdev, PCI_COMMAND, &value); - value &= ~PCI_COMMAND_MASTER; - pci_write_config_word(adapter->pdev, PCI_COMMAND, value); - /* Stop Receive */ - pch_gbe_mac_reset_rx(hw); - /* Enable Bus master */ - value |= PCI_COMMAND_MASTER; - pci_write_config_word(adapter->pdev, PCI_COMMAND, value); - } else { - /* Stop Receive */ - pch_gbe_mac_reset_rx(hw); - } - /* reprogram multicast address register after reset */ - pch_gbe_set_multi(adapter->netdev); } -static void pch_gbe_start_receive(struct pch_gbe_hw *hw) +static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw) { u32 rxdma; @@ -1355,9 +1317,6 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw) rxdma = ioread32(&hw->reg->DMA_CTRL); rxdma |= PCH_GBE_RX_DMA_EN; iowrite32(rxdma, &hw->reg->DMA_CTRL); - /* Enables Receive */ - iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN); - return; } /** @@ -1393,7 +1352,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data) int_en = ioread32(&hw->reg->INT_EN); iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR), &hw->reg->INT_EN); - pch_gbe_stop_receive(adapter); + pch_gbe_disable_dma_rx(&adapter->hw); int_st |= ioread32(&hw->reg->INT_ST); int_st = int_st & ioread32(&hw->reg->INT_EN); } @@ -1971,12 +1930,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) struct net_device *netdev = adapter->netdev; struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring; struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring; - int err; + int err = -EINVAL; /* Ensure we have a valid MAC */ if (!is_valid_ether_addr(adapter->hw.mac.addr)) { pr_err("Error: Invalid MAC address\n"); - return -EINVAL; + goto out; } /* hardware has been reset, we need to reload some things */ @@ -1989,18 +1948,19 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) err = pch_gbe_request_irq(adapter); if (err) { - pr_err("Error: can't bring device up\n"); - return err; + pr_err("Error: can't bring device up - irq request failed\n"); + goto out; } err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count); if (err) { - pr_err("Error: can't bring device up\n"); - return err; + pr_err("Error: can't bring device up - alloc rx buffers pool failed\n"); + goto freeirq; } pch_gbe_alloc_tx_buffers(adapter, tx_ring); pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count); adapter->tx_queue_len = netdev->tx_queue_len; - pch_gbe_start_receive(&adapter->hw); + pch_gbe_enable_dma_rx(&adapter->hw); + pch_gbe_enable_mac_rx(&adapter->hw); mod_timer(&adapter->watchdog_timer, jiffies); @@ -2009,6 +1969,11 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter) netif_start_queue(adapter->netdev); return 0; + +freeirq: + pch_gbe_free_irq(adapter); +out: + return err; } /** @@ -2405,7 +2370,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) int work_done = 0; bool poll_end_flag = false; bool cleaned = false; - u32 int_en; pr_debug("budget : %d\n", budget); @@ -2422,19 +2386,13 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget) if (poll_end_flag) { napi_complete(napi); - if (adapter->rx_stop_flag) { - adapter->rx_stop_flag = false; - pch_gbe_start_receive(&adapter->hw); - } pch_gbe_irq_enable(adapter); - } else - if (adapter->rx_stop_flag) { - adapter->rx_stop_flag = false; - pch_gbe_start_receive(&adapter->hw); - int_en = ioread32(&adapter->hw.reg->INT_EN); - iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR), - &adapter->hw.reg->INT_EN); - } + } + + if (adapter->rx_stop_flag) { + adapter->rx_stop_flag = false; + pch_gbe_enable_dma_rx(&adapter->hw); + } pr_debug("poll_end_flag : %d work_done : %d budget : %d\n", poll_end_flag, work_done, budget); diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index df09b1cb742..6407d0d77e8 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -2525,6 +2525,13 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) qdev->req_q_size = (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req)); + qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb); + + /* The barrier is required to ensure request and response queue + * addr writes to the registers. + */ + wmb(); + qdev->req_q_virt_addr = pci_alloc_consistent(qdev->pdev, (size_t) qdev->req_q_size, @@ -2536,8 +2543,6 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) return -ENOMEM; } - qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb); - qdev->rsp_q_virt_addr = pci_alloc_consistent(qdev->pdev, (size_t) qdev->rsp_q_size, diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 1c818254b7b..b01f83a044c 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp) cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); - cpw32_f(HiTxRingAddr, 0); - cpw32_f(HiTxRingAddr + 4, 0); - - ring_dma = cp->ring_dma; - cpw32_f(RxRingAddr, ring_dma & 0xffffffff); - cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); - - ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; - cpw32_f(TxRingAddr, ring_dma & 0xffffffff); - cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); - cp_start_hw(cp); cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ @@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp) cpw8(Config5, cpr8(Config5) & PMEStatus); + cpw32_f(HiTxRingAddr, 0); + cpw32_f(HiTxRingAddr + 4, 0); + + ring_dma = cp->ring_dma; + cpw32_f(RxRingAddr, ring_dma & 0xffffffff); + cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); + + ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; + cpw32_f(TxRingAddr, ring_dma & 0xffffffff); + cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); + cpw16(MultiIntr, 0); cpw8_f(Cfg9346, Cfg9346_Lock); diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e7ff886e804..927aa33d434 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3827,6 +3827,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_25: + case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_29: case RTL_GIGA_MAC_VER_30: case RTL_GIGA_MAC_VER_32: @@ -4519,6 +4521,9 @@ static void rtl_set_rx_mode(struct net_device *dev) mc_filter[1] = swab32(data); } + if (tp->mac_version == RTL_GIGA_MAC_VER_35) + mc_filter[1] = mc_filter[0] = 0xffffffff; + RTL_W32(MAR0 + 4, mc_filter[1]); RTL_W32(MAR0 + 0, mc_filter[0]); diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index fb9f6b38511..edf5edb1314 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -2479,7 +2479,7 @@ static int sis900_resume(struct pci_dev *pci_dev) netif_start_queue(net_dev); /* Workaround for EDB */ - sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); + sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); /* Enable all known interrupts by setting the interrupt mask. */ sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 62d1baf111e..c53c0f4e2ce 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2110,7 +2110,7 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev) static int __devinit smsc911x_init(struct net_device *dev) { struct smsc911x_data *pdata = netdev_priv(dev); - unsigned int byte_test; + unsigned int byte_test, mask; unsigned int to = 100; SMSC_TRACE(pdata, probe, "Driver Parameters:"); @@ -2130,9 +2130,22 @@ static int __devinit smsc911x_init(struct net_device *dev) /* * poll the READY bit in PMT_CTRL. Any other access to the device is * forbidden while this bit isn't set. Try for 100ms + * + * Note that this test is done before the WORD_SWAP register is + * programmed. So in some configurations the READY bit is at 16 before + * WORD_SWAP is written to. This issue is worked around by waiting + * until either bit 0 or bit 16 gets set in PMT_CTRL. + * + * SMSC has confirmed that checking bit 16 (marked as reserved in + * the datasheet) is fine since these bits "will either never be set + * or can only go high after READY does (so also indicate the device + * is ready)". */ - while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to) + + mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_); + while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to) udelay(1000); + if (to == 0) { pr_err("Device not READY in 100ms aborting\n"); return -ENODEV; diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index b26cbda5efa..2c41894d547 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_TI bool "Texas Instruments (TI) devices" default y - depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3)) + depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX)) ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 4e2a1628484..66e025ad5df 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -917,7 +917,7 @@ static int tile_net_setup_interrupts(struct net_device *dev) ingress_irq = rc; tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU); rc = request_irq(ingress_irq, tile_net_handle_ingress_irq, - 0, NULL, NULL); + 0, "tile_net", NULL); if (rc != 0) { netdev_err(dev, "request_irq failed: %d\n", rc); destroy_irq(ingress_irq); @@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb) { struct skb_shared_info *sh = skb_shinfo(skb); unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; + unsigned int data_len = skb->len - sh_len; unsigned int p_len = sh->gso_size; long f_id = -1; /* id of the current fragment */ - long f_size = skb->hdr_len; /* size of the current fragment */ - long f_used = sh_len; /* bytes used from the current fragment */ + long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ + long f_used = 0; /* bytes used from the current fragment */ long n; /* size of the current piece of payload */ int num_edescs = 0; int segment; @@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb) /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = sh->frags[f_id].size; + f_size = skb_frag_size(&sh->frags[f_id]); f_used = 0; } @@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, struct iphdr *ih; struct tcphdr *th; unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; + unsigned int data_len = skb->len - sh_len; unsigned char *data = skb->data; unsigned int ih_off, th_off, p_len; unsigned int isum_seed, tsum_seed, id, seq; long f_id = -1; /* id of the current fragment */ - long f_size = skb->hdr_len; /* size of the current fragment */ - long f_used = sh_len; /* bytes used from the current fragment */ + long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ + long f_used = 0; /* bytes used from the current fragment */ long n; /* size of the current piece of payload */ int segment; @@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, isum_seed = ((0xFFFF - ih->check) + (0xFFFF - ih->tot_len) + (0xFFFF - ih->id)); - tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len)); + tsum_seed = th->check + (0xFFFF ^ htons(skb->len)); id = ntohs(ih->id); seq = ntohl(th->seq); @@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers, /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = sh->frags[f_id].size; + f_size = skb_frag_size(&sh->frags[f_id]); f_used = 0; } @@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, struct tile_net_priv *priv = netdev_priv(dev); struct skb_shared_info *sh = skb_shinfo(skb); unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - unsigned int data_len = skb->data_len + skb->hdr_len - sh_len; + unsigned int data_len = skb->len - sh_len; unsigned int p_len = sh->gso_size; gxio_mpipe_edesc_t edesc_head = { { 0 } }; gxio_mpipe_edesc_t edesc_body = { { 0 } }; long f_id = -1; /* id of the current fragment */ - long f_size = skb->hdr_len; /* size of the current fragment */ - long f_used = sh_len; /* bytes used from the current fragment */ - void *f_data = skb->data; + long f_size = skb_headlen(skb) - sh_len; /* current fragment size */ + long f_used = 0; /* bytes used from the current fragment */ + void *f_data = skb->data + sh_len; long n; /* size of the current piece of payload */ unsigned long tx_packets = 0, tx_bytes = 0; unsigned int csum_start; @@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, /* Egress the payload. */ while (p_used < p_len) { + void *va; /* Advance as needed. */ while (f_used >= f_size) { f_id++; - f_size = sh->frags[f_id].size; - f_used = 0; + f_size = skb_frag_size(&sh->frags[f_id]); f_data = tile_net_frag_buf(&sh->frags[f_id]); + f_used = 0; } + va = f_data + f_used; + /* Use bytes from the current fragment. */ n = p_len - p_used; if (n > f_size - f_used) @@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue, p_used += n; /* Egress a piece of the payload. */ - edesc_body.va = va_to_tile_io_addr(f_data) + f_used; + edesc_body.va = va_to_tile_io_addr(va); edesc_body.xfer_size = n; edesc_body.bound = !(p_used < p_len); gxio_mpipe_equeue_put_at(equeue, edesc_body, slot); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 0793299bd39..a788501e978 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -894,6 +894,8 @@ out: return IRQ_HANDLED; } +static void axienet_dma_err_handler(unsigned long data); + /** * axienet_open - Driver open routine. * @ndev: Pointer to net_device structure @@ -942,6 +944,10 @@ static int axienet_open(struct net_device *ndev) phy_start(lp->phy_dev); } + /* Enable tasklets for Axi DMA error handling */ + tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler, + (unsigned long) lp); + /* Enable interrupts for Axi DMA Tx */ ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev); if (ret) @@ -950,8 +956,7 @@ static int axienet_open(struct net_device *ndev) ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev); if (ret) goto err_rx_irq; - /* Enable tasklets for Axi DMA error handling */ - tasklet_enable(&lp->dma_err_tasklet); + return 0; err_rx_irq: @@ -960,6 +965,7 @@ err_tx_irq: if (lp->phy_dev) phy_disconnect(lp->phy_dev); lp->phy_dev = NULL; + tasklet_kill(&lp->dma_err_tasklet); dev_err(lp->dev, "request_irq() failed\n"); return ret; } @@ -990,7 +996,7 @@ static int axienet_stop(struct net_device *ndev) axienet_setoptions(ndev, lp->options & ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); - tasklet_disable(&lp->dma_err_tasklet); + tasklet_kill(&lp->dma_err_tasklet); free_irq(lp->tx_irq, ndev); free_irq(lp->rx_irq, ndev); @@ -1613,10 +1619,6 @@ static int __devinit axienet_of_probe(struct platform_device *op) goto err_iounmap_2; } - tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler, - (unsigned long) lp); - tasklet_disable(&lp->dma_err_tasklet); - return 0; err_iounmap_2: diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index 98934bdf6ac..477d6729b17 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1102,10 +1102,12 @@ static int init_queues(struct port *port) { int i; - if (!ports_open) - if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, - POOL_ALLOC_SIZE, 32, 0))) + if (!ports_open) { + dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev, + POOL_ALLOC_SIZE, 32, 0); + if (!dma_pool) return -ENOMEM; + } if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, &port->desc_tab_phys))) diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 5039f08f5a5..43e9ab4f4d7 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work) break; case SIRDEV_STATE_DONGLE_SPEED: - if (dev->dongle_drv->reset) { + if (dev->dongle_drv->set_speed) { ret = dev->dongle_drv->set_speed(dev, fsm->param); if (ret < 0) { fsm->result = ret; diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 983bbf4d5ef..961f0b29391 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -15,6 +15,11 @@ if PHYLIB comment "MII PHY device drivers" +config AT803X_PHY + tristate "Drivers for Atheros AT803X PHYs" + ---help--- + Currently supports the AT8030 and AT8035 model + config AMD_PHY tristate "Drivers for the AMD PHYs" ---help--- diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 426674debae..9645e389a58 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_MICREL_PHY) += micrel.o obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o +obj-$(CONFIG_AT803X_PHY) += at803x.o obj-$(CONFIG_AMD_PHY) += amd.o obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c new file mode 100644 index 00000000000..45cbc10de01 --- /dev/null +++ b/drivers/net/phy/at803x.c @@ -0,0 +1,176 @@ +/* + * drivers/net/phy/at803x.c + * + * Driver for Atheros 803x PHY + * + * Author: Matus Ujhelyi <ujhelyi.m@gmail.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. + */ + +#include <linux/phy.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> + +#define AT803X_INTR_ENABLE 0x12 +#define AT803X_INTR_STATUS 0x13 +#define AT803X_WOL_ENABLE 0x01 +#define AT803X_DEVICE_ADDR 0x03 +#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C +#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B +#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A +#define AT803X_MMD_ACCESS_CONTROL 0x0D +#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E +#define AT803X_FUNC_DATA 0x4003 + +MODULE_DESCRIPTION("Atheros 803x PHY driver"); +MODULE_AUTHOR("Matus Ujhelyi"); +MODULE_LICENSE("GPL"); + +static void at803x_set_wol_mac_addr(struct phy_device *phydev) +{ + struct net_device *ndev = phydev->attached_dev; + const u8 *mac; + unsigned int i, offsets[] = { + AT803X_LOC_MAC_ADDR_32_47_OFFSET, + AT803X_LOC_MAC_ADDR_16_31_OFFSET, + AT803X_LOC_MAC_ADDR_0_15_OFFSET, + }; + + if (!ndev) + return; + + mac = (const u8 *) ndev->dev_addr; + + if (!is_valid_ether_addr(mac)) + return; + + for (i = 0; i < 3; i++) { + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, + AT803X_DEVICE_ADDR); + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, + offsets[i]); + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL, + AT803X_FUNC_DATA); + phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA, + mac[(i * 2) + 1] | (mac[(i * 2)] << 8)); + } +} + +static int at803x_config_init(struct phy_device *phydev) +{ + int val; + u32 features; + int status; + + features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI | + SUPPORTED_FIBRE | SUPPORTED_BNC; + + val = phy_read(phydev, MII_BMSR); + if (val < 0) + return val; + + if (val & BMSR_ANEGCAPABLE) + features |= SUPPORTED_Autoneg; + if (val & BMSR_100FULL) + features |= SUPPORTED_100baseT_Full; + if (val & BMSR_100HALF) + features |= SUPPORTED_100baseT_Half; + if (val & BMSR_10FULL) + features |= SUPPORTED_10baseT_Full; + if (val & BMSR_10HALF) + features |= SUPPORTED_10baseT_Half; + + if (val & BMSR_ESTATEN) { + val = phy_read(phydev, MII_ESTATUS); + if (val < 0) + return val; + + if (val & ESTATUS_1000_TFULL) + features |= SUPPORTED_1000baseT_Full; + if (val & ESTATUS_1000_THALF) + features |= SUPPORTED_1000baseT_Half; + } + + phydev->supported = features; + phydev->advertising = features; + + /* enable WOL */ + at803x_set_wol_mac_addr(phydev); + status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE); + status = phy_read(phydev, AT803X_INTR_STATUS); + + return 0; +} + +/* ATHEROS 8035 */ +static struct phy_driver at8035_driver = { + .phy_id = 0x004dd072, + .name = "Atheros 8035 ethernet", + .phy_id_mask = 0xffffffef, + .config_init = at803x_config_init, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { + .owner = THIS_MODULE, + }, +}; + +/* ATHEROS 8030 */ +static struct phy_driver at8030_driver = { + .phy_id = 0x004dd076, + .name = "Atheros 8030 ethernet", + .phy_id_mask = 0xffffffef, + .config_init = at803x_config_init, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .driver = { + .owner = THIS_MODULE, + }, +}; + +static int __init atheros_init(void) +{ + int ret; + + ret = phy_driver_register(&at8035_driver); + if (ret) + goto err1; + + ret = phy_driver_register(&at8030_driver); + if (ret) + goto err2; + + return 0; + +err2: + phy_driver_unregister(&at8035_driver); +err1: + return ret; +} + +static void __exit atheros_exit(void) +{ + phy_driver_unregister(&at8035_driver); + phy_driver_unregister(&at8030_driver); +} + +module_init(atheros_init); +module_exit(atheros_exit); + +static struct mdio_device_id __maybe_unused atheros_tbl[] = { + { 0x004dd076, 0xffffffef }, + { 0x004dd072, 0xffffffef }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, atheros_tbl); diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 899274f2f9b..2ed1140df3e 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -185,17 +185,20 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev) { struct mdio_gpio_platform_data *pdata; struct mii_bus *new_bus; - int ret; + int ret, bus_id; - if (pdev->dev.of_node) + if (pdev->dev.of_node) { pdata = mdio_gpio_of_get_data(pdev); - else + bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio"); + } else { pdata = pdev->dev.platform_data; + bus_id = pdev->id; + } if (!pdata) return -ENODEV; - new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id); + new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, bus_id); if (!new_bus) return -ENODEV; diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c index 9db0171e936..c5db428e73f 100644 --- a/drivers/net/team/team_mode_broadcast.c +++ b/drivers/net/team/team_mode_broadcast.c @@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) if (last) { skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2) { - ret = team_dev_queue_xmit(team, last, - skb2); + ret = !team_dev_queue_xmit(team, last, + skb2); if (!sum_ret) sum_ret = ret; } @@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) } } if (last) { - ret = team_dev_queue_xmit(team, last, skb); + ret = !team_dev_queue_xmit(team, last, skb); if (!sum_ret) sum_ret = ret; } diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index c81e278629f..08d55b6bf27 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c @@ -31,6 +31,7 @@ #include <linux/usb/cdc.h> #include <linux/usb/usbnet.h> #include <linux/gfp.h> +#include <linux/if_vlan.h> /* @@ -92,7 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf) /* no jumbogram (16K) support for now */ - dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN; + dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; return 0; diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index a03de719704..d0129827602 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -592,6 +592,32 @@ static const struct usb_device_id products [] = { .driver_info = 0, }, +/* Novatel USB551L and MC551 - handled by qmi_wwan */ +{ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = NOVATEL_VENDOR_ID, + .idProduct = 0xB001, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = 0, +}, + +/* Novatel E362 - handled by qmi_wwan */ +{ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_PRODUCT + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = NOVATEL_VENDOR_ID, + .idProduct = 0x9010, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bInterfaceProtocol = USB_CDC_PROTO_NONE, + .driver_info = 0, +}, + /* * WHITELIST!!! * @@ -604,21 +630,6 @@ static const struct usb_device_id products [] = { * because of bugs/quirks in a given product (like Zaurus, above). */ { - /* Novatel USB551L */ - /* This match must come *before* the generic CDC-ETHER match so that - * we get FLAG_WWAN set on the device, since it's descriptors are - * generic CDC-ETHER. - */ - .match_flags = USB_DEVICE_ID_MATCH_VENDOR - | USB_DEVICE_ID_MATCH_PRODUCT - | USB_DEVICE_ID_MATCH_INT_INFO, - .idVendor = NOVATEL_VENDOR_ID, - .idProduct = 0xB001, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, - .bInterfaceProtocol = USB_CDC_PROTO_NONE, - .driver_info = (unsigned long)&wwan_info, -}, { /* ZTE (Vodafone) K3805-Z */ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4cd582a4f62..74fab1a4015 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -540,10 +540,12 @@ advance: (ctx->ether_desc == NULL) || (ctx->control != intf)) goto error; - /* claim interfaces, if any */ - temp = usb_driver_claim_interface(driver, ctx->data, dev); - if (temp) - goto error; + /* claim data interface, if different from control */ + if (ctx->data != ctx->control) { + temp = usb_driver_claim_interface(driver, ctx->data, dev); + if (temp) + goto error; + } iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; @@ -623,6 +625,10 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf) tasklet_kill(&ctx->bh); + /* handle devices with combined control and data interface */ + if (ctx->control == ctx->data) + ctx->data = NULL; + /* disconnect master --> disconnect slave */ if (intf == ctx->control && ctx->data) { usb_set_intfdata(ctx->data, NULL); @@ -1245,6 +1251,14 @@ static const struct usb_device_id cdc_devs[] = { .driver_info = (unsigned long) &wwan_info, }, + /* Huawei NCM devices disguised as vendor specific */ + { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16), + .driver_info = (unsigned long)&wwan_info, + }, + { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46), + .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/ipheth.c b/drivers/net/usb/ipheth.c index a28a983d465..534d8becbbd 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -62,6 +62,7 @@ #define USB_PRODUCT_IPAD 0x129a #define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4S 0x12a0 +#define USB_PRODUCT_IPHONE_5 0x12a8 #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6883c371c59..3b566fa0f8e 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -369,18 +369,73 @@ static const struct usb_device_id products[] = { USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff), .driver_info = (unsigned long)&qmi_wwan_info, }, + { /* Novatel USB551L and MC551 */ + USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&qmi_wwan_info, + }, + { /* Novatel E362 */ + USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&qmi_wwan_info, + }, /* 3. Combined interface devices matching on interface number */ + {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0017, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0021, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0025, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0031, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0042, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0049, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0052, 4)}, {QMI_FIXED_INTF(0x19d2, 0x0055, 1)}, /* ZTE (Vodafone) K3520-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0058, 4)}, {QMI_FIXED_INTF(0x19d2, 0x0063, 4)}, /* ZTE (Vodafone) K3565-Z */ {QMI_FIXED_INTF(0x19d2, 0x0104, 4)}, /* ZTE (Vodafone) K4505-Z */ + {QMI_FIXED_INTF(0x19d2, 0x0113, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0118, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0121, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0123, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0124, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0125, 6)}, + {QMI_FIXED_INTF(0x19d2, 0x0126, 5)}, + {QMI_FIXED_INTF(0x19d2, 0x0130, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0133, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0141, 5)}, {QMI_FIXED_INTF(0x19d2, 0x0157, 5)}, /* ZTE MF683 */ + {QMI_FIXED_INTF(0x19d2, 0x0158, 3)}, {QMI_FIXED_INTF(0x19d2, 0x0167, 4)}, /* ZTE MF820D */ + {QMI_FIXED_INTF(0x19d2, 0x0168, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x0176, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0178, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x0191, 4)}, /* ZTE EuFi890 */ + {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ + {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, + {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ {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, 0x1012, 4)}, {QMI_FIXED_INTF(0x19d2, 0x1018, 3)}, /* ZTE (Vodafone) K5006-Z */ + {QMI_FIXED_INTF(0x19d2, 0x1021, 2)}, + {QMI_FIXED_INTF(0x19d2, 0x1245, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1247, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1252, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1254, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1255, 3)}, + {QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, + {QMI_FIXED_INTF(0x19d2, 0x1401, 2)}, {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ + {QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, + {QMI_FIXED_INTF(0x19d2, 0x1425, 2)}, + {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ {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 */ diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 7479a5761d0..362cb8cfeb9 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -184,7 +184,7 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx) /* set the address, index & direction (read from PHY) */ phy_id &= dev->mii.phy_id_mask; idx &= dev->mii.reg_num_mask; - addr = (phy_id << 11) | (idx << 6) | MII_READ_; + addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_; ret = smsc95xx_write_reg(dev, MII_ADDR, addr); check_warn_goto_done(ret, "Error writing MII_ADDR"); @@ -221,7 +221,7 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx, /* set the address, index & direction (write to PHY) */ phy_id &= dev->mii.phy_id_mask; idx &= dev->mii.reg_num_mask; - addr = (phy_id << 11) | (idx << 6) | MII_WRITE_; + addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_; ret = smsc95xx_write_reg(dev, MII_ADDR, addr); check_warn_goto_done(ret, "Error writing MII_ADDR"); @@ -1344,6 +1344,7 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, } else { u32 csum_preamble = smsc95xx_calc_csum_preamble(skb); skb_push(skb, 4); + cpu_to_le32s(&csum_preamble); memcpy(skb->data, &csum_preamble, 4); } } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index f9819d10b1f..edb81ed0695 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -359,10 +359,12 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb, void usbnet_defer_kevent (struct usbnet *dev, int work) { set_bit (work, &dev->flags); - if (!schedule_work (&dev->kevent)) - netdev_err(dev->net, "kevent %d may have been dropped\n", work); - else + if (!schedule_work (&dev->kevent)) { + if (net_ratelimit()) + netdev_err(dev->net, "kevent %d may have been dropped\n", work); + } else { netdev_dbg(dev->net, "kevent %d scheduled\n", work); + } } EXPORT_SYMBOL_GPL(usbnet_defer_kevent); @@ -1158,6 +1160,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, usb_anchor_urb(urb, &dev->deferred); /* no use to process more packets */ netif_stop_queue(net); + usb_put_urb(urb); spin_unlock_irqrestore(&dev->txq.lock, flags); netdev_dbg(dev->net, "Delaying transmission for resumption\n"); goto deferred; @@ -1310,6 +1313,8 @@ void usbnet_disconnect (struct usb_interface *intf) cancel_work_sync(&dev->kevent); + usb_scuttle_anchored_urbs(&dev->deferred); + if (dev->driver_info->unbind) dev->driver_info->unbind (dev, intf); diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index ce9d4f2c977..0ae1bcc6da7 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + u32 buf_size; - tbi = tq->buf_info + tq->tx_ring.next2fill; - tbi->map_type = VMXNET3_MAP_PAGE; - tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag, - 0, skb_frag_size(frag), - DMA_TO_DEVICE); + buf_offset = 0; + len = skb_frag_size(frag); + while (len) { + tbi = tq->buf_info + tq->tx_ring.next2fill; + if (len < VMXNET3_MAX_TX_BUF_SIZE) { + buf_size = len; + dw2 |= len; + } else { + buf_size = VMXNET3_MAX_TX_BUF_SIZE; + /* spec says that for TxDesc.len, 0 == 2^14 */ + } + tbi->map_type = VMXNET3_MAP_PAGE; + tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag, + buf_offset, buf_size, + DMA_TO_DEVICE); - tbi->len = skb_frag_size(frag); + tbi->len = buf_size; - gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; - BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); + gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; + BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); - gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); - gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag)); - gdesc->dword[3] = 0; + gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); + gdesc->dword[2] = cpu_to_le32(dw2); + gdesc->dword[3] = 0; - dev_dbg(&adapter->netdev->dev, - "txd[%u]: 0x%llu %u %u\n", - tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr), - le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]); - vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); - dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; + dev_dbg(&adapter->netdev->dev, + "txd[%u]: 0x%llu %u %u\n", + tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr), + le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]); + vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); + dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; + + len -= buf_size; + buf_offset += buf_size; + } } ctx->eop_txd = gdesc; @@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb, } } +static int txd_estimate(const struct sk_buff *skb) +{ + int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1; + int i; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + + count += VMXNET3_TXD_NEEDED(skb_frag_size(frag)); + } + return count; +} /* * Transmits a pkt thru a given tq @@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq, union Vmxnet3_GenericDesc tempTxDesc; #endif - /* conservatively estimate # of descriptors to use */ - count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + - skb_shinfo(skb)->nr_frags + 1; + count = txd_estimate(skb); ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP)); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 607976c0016..8b5c6191707 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1,5 +1,5 @@ /* - * VXLAN: Virtual eXtensiable Local Area Network + * VXLAN: Virtual eXtensible Local Area Network * * Copyright (c) 2012 Vyatta Inc. * @@ -50,8 +50,8 @@ #define VXLAN_N_VID (1u << 24) #define VXLAN_VID_MASK (VXLAN_N_VID - 1) -/* VLAN + IP header + UDP + VXLAN */ -#define VXLAN_HEADROOM (4 + 20 + 8 + 8) +/* IP header + UDP + VXLAN + Ethernet header */ +#define VXLAN_HEADROOM (20 + 8 + 8 + 14) #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */ @@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg) = container_of(p, struct vxlan_fdb, hlist); unsigned long timeout; - if (f->state == NUD_PERMANENT) + if (f->state & NUD_PERMANENT) continue; timeout = f->used + vxlan->age_interval * HZ; @@ -1102,6 +1102,10 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, if (!tb[IFLA_MTU]) dev->mtu = lowerdev->mtu - VXLAN_HEADROOM; + + /* update header length based on lower device */ + dev->hard_header_len = lowerdev->hard_header_len + + VXLAN_HEADROOM; } if (data[IFLA_VXLAN_TOS]) diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 3f575afd8cf..e9a3da588e9 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -969,10 +969,12 @@ static int init_hdlc_queues(struct port *port) { int i; - if (!ports_open) - if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, - POOL_ALLOC_SIZE, 32, 0))) + if (!ports_open) { + dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev, + POOL_ALLOC_SIZE, 32, 0); + if (!dma_pool) return -ENOMEM; + } if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, &port->desc_tab_phys))) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 89bf94d4d8a..6f7cf49eff4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, - {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, - {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, - {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, - {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, + {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, + {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, + {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, + {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, + {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, + {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, + {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, + {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, + {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, + {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, + {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, + {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, + {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, + {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, + {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, + {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, + {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, + {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, + {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, + {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, + {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, + {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, - {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, - {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, + {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, + {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, + {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, + {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, + {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, + {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, + {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, + {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, + {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, + {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, + {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, + {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, + {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, + {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, + {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, + {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, + {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, + {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, + {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, + {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, - {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, - {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, - {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, + {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, + {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, + {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 924c4616c3d..f5dda84176c 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ + { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */ { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ { USB_DEVICE(0x0cf3, 0x7015), diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8e1559aba49..1829b445d0b 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1456,7 +1456,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) switch (type) { case ATH9K_RESET_POWER_ON: ret = ath9k_hw_set_reset_power_on(ah); - if (!ret) + if (ret) ah->reset_power_on = true; break; case ATH9K_RESET_WARM: diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 378bd70256b..741918a2027 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) } bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + bf->bf_next = NULL; list_del(&bf->list); spin_unlock_bh(&sc->tx.txbuflock); @@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; - bool rc_update = true; + bool rc_update = true, isba; struct ieee80211_tx_rate rates[4]; struct ath_frame_info *fi; int nframes; @@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; tid = ATH_AN_2_TID(an, tidno); seq_first = tid->seq_start; + isba = ts->ts_flags & ATH9K_TX_BA; /* * The hardware occasionally sends a tx status for the wrong TID. * In this case, the BA status cannot be considered valid and all * subframes need to be retransmitted + * + * Only BlockAcks have a TID and therefore normal Acks cannot be + * checked */ - if (tidno != ts->tid) + if (isba && tidno != ts->tid) txok = false; isaggr = bf_isaggr(bf); @@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, list_add_tail(&bf->list, &bf_head); bf->bf_state.bf_type = 0; + bf->bf_next = NULL; bf->bf_lastbf = bf; ath_tx_fill_desc(sc, bf, txq, fi->framelen); ath_tx_txqaddbuf(sc, txq, &bf_head, false); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 73730e94e0a..c5a99c8c816 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); + if (!wldev->fw.ucode.data) + return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev && wl->hw_registred) { b43_leds_stop(wldev); ieee80211_unregister_hw(wl->hw); @@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); + if (!wldev->fw.ucode.data) + return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev && wl->hw_registred) { b43_leds_stop(wldev); ieee80211_unregister_hw(wl->hw); diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index 192251adf98..282eedec675 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c @@ -382,7 +382,7 @@ static void cancel_transfers(struct b43legacy_pioqueue *queue) { struct b43legacy_pio_txpacket *packet, *tmp_packet; - tasklet_disable(&queue->txtask); + tasklet_kill(&queue->txtask); list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) free_txpacket(packet, 0); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a2b4b1e7101..7a6dfdc67b6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -1339,7 +1339,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo, } ret = brcmf_bus_start(dev); - if (ret == -ENOLINK) { + if (ret) { brcmf_dbg(ERROR, "dongle is not responding\n"); brcmf_detach(dev); goto fail; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index c1abaa6db59..481345c23de 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3569,7 +3569,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, if (!request || !request->n_ssids || !request->n_match_sets) { WL_ERR("Invalid sched scan req!! n_ssids:%d\n", - request->n_ssids); + request ? request->n_ssids : 0); return -EINVAL; } @@ -3972,7 +3972,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, u8 *iovar_ie_buf; u8 *curr_ie_buf; u8 *mgmt_ie_buf = NULL; - u32 mgmt_ie_buf_len = 0; + int mgmt_ie_buf_len; u32 *mgmt_ie_len = 0; u32 del_add_ie_buf_len = 0; u32 total_ie_buf_len = 0; @@ -3982,7 +3982,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, struct parsed_vndr_ie_info *vndrie_info; s32 i; u8 *ptr; - u32 remained_buf_len; + int remained_buf_len; WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag); iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); @@ -4401,7 +4401,7 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode) static void brcmf_wiphy_pno_params(struct wiphy *wiphy) { -#ifndef CONFIG_BRCMFISCAN +#ifndef CONFIG_BRCMISCAN /* scheduled scan settings */ wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; @@ -4606,12 +4606,13 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); struct wiphy *wiphy = cfg_to_wiphy(cfg); - struct brcmf_channel_info_le channel_le; - struct ieee80211_channel *notify_channel; + struct ieee80211_channel *notify_channel = NULL; struct ieee80211_supported_band *band; + struct brcmf_bss_info_le *bi; u32 freq; s32 err = 0; u32 target_channel; + u8 *buf; WL_TRACE("Enter\n"); @@ -4619,11 +4620,22 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, memcpy(profile->bssid, e->addr, ETH_ALEN); brcmf_update_bss_info(cfg); - brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, - sizeof(channel_le)); + buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); + if (buf == NULL) { + err = -ENOMEM; + goto done; + } - target_channel = le32_to_cpu(channel_le.target_channel); - WL_CONN("Roamed to channel %d\n", target_channel); + /* data sent to dongle has to be little endian */ + *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); + err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); + + if (err) + goto done; + + bi = (struct brcmf_bss_info_le *)(buf + 4); + target_channel = bi->ctl_ch ? bi->ctl_ch : + CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); if (target_channel <= CH_MAX_2G_CHANNEL) band = wiphy->bands[IEEE80211_BAND_2GHZ]; @@ -4633,6 +4645,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, freq = ieee80211_channel_to_frequency(target_channel, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); +done: + kfree(buf); cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid, conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); @@ -5186,41 +5200,6 @@ brcmf_cfg80211_event(struct net_device *ndev, schedule_work(&cfg->event_work); } -static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) -{ - s32 infra = 0; - s32 err = 0; - - switch (iftype) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_WDS: - WL_ERR("type (%d) : currently we do not support this mode\n", - iftype); - err = -EINVAL; - return err; - case NL80211_IFTYPE_ADHOC: - infra = 0; - break; - case NL80211_IFTYPE_STATION: - infra = 1; - break; - case NL80211_IFTYPE_AP: - infra = 1; - break; - default: - err = -EINVAL; - WL_ERR("invalid type (%d)\n", iftype); - return err; - } - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); - if (err) { - WL_ERR("WLC_SET_INFRA error (%d)\n", err); - return err; - } - - return 0; -} - static s32 brcmf_dongle_eventmsg(struct net_device *ndev) { /* Room for "event_msgs" + '\0' + bitvec */ @@ -5439,7 +5418,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) WL_BEACON_TIMEOUT); if (err) goto default_conf_out; - err = brcmf_dongle_mode(ndev, wdev->iftype); + err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, + NULL, NULL); if (err && err != -EINPROGRESS) goto default_conf_out; err = brcmf_dongle_probecap(cfg); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 935120fc8c9..768bf612533 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, } else len = src->len; - dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC); + dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC); if (!dst) continue; diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 349c205d5f6..da586206419 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c @@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, * See iwlagn_mac_channel_switch. */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl6000_channel_switch_cmd cmd; + struct iwl6000_channel_switch_cmd *cmd; u32 switch_time_in_usec, ucode_switch_time; u16 ch; u32 tsf_low; @@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = { sizeof(cmd), }, + .len = { sizeof(*cmd), }, .flags = CMD_SYNC, - .data = { &cmd, }, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, }; + int err; - cmd.band = priv->band == IEEE80211_BAND_2GHZ; + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + hcmd.data[0] = cmd; + + cmd->band = priv->band == IEEE80211_BAND_2GHZ; ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", ctx->active.channel, ch); - cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = ctx->staging.flags; - cmd.rxon_filter_flags = ctx->staging.filter_flags; + cmd->channel = cpu_to_le16(ch); + cmd->rxon_flags = ctx->staging.flags; + cmd->rxon_filter_flags = ctx->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, switch_count = 0; } if (switch_count <= 1) - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); + cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); else { switch_time_in_usec = vif->bss_conf.beacon_int * switch_count * TIME_UNIT; ucode_switch_time = iwl_usecs_to_beacons(priv, switch_time_in_usec, beacon_interval); - cmd.switch_time = iwl_add_beacon_time(priv, - priv->ucode_beacon_time, - ucode_switch_time, - beacon_interval); + cmd->switch_time = iwl_add_beacon_time(priv, + priv->ucode_beacon_time, + ucode_switch_time, + beacon_interval); } IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", - cmd.switch_time); - cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; + cmd->switch_time); + cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; - return iwl_dvm_send_cmd(priv, &hcmd); + err = iwl_dvm_send_cmd(priv, &hcmd); + kfree(cmd); + return err; } struct iwl_lib_ops iwl6000_lib = { diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index ff8162d4c45..2d9eee93c74 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -521,7 +521,7 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); if (iwlagn_tx_skb(priv, control->sta, skb)) - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, @@ -1354,6 +1354,20 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, vif_priv->ctx = ctx; ctx->vif = vif; + /* + * In SNIFFER device type, the firmware reports the FCS to + * the host, rather than snipping it off. Unfortunately, + * mac80211 doesn't (yet) provide a per-packet flag for + * this, so that we have to set the hardware flag based + * on the interfaces added. As the monitor interface can + * only be present by itself, and will be removed before + * other interfaces are added, this is safe. + */ + if (vif->type == NL80211_IFTYPE_MONITOR) + priv->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS; + else + priv->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; + err = iwl_setup_interface(priv, ctx); if (!err || reset) goto out; diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 7ff3f143067..408132cf83c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c @@ -2114,7 +2114,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) info = IEEE80211_SKB_CB(skb); iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); - dev_kfree_skb_any(skb); + ieee80211_free_txskb(priv->hw, skb); } static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 17c8e5d8268..bb69f8f90b3 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -321,6 +321,14 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) dma_map_page(trans->dev, page, 0, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); + if (dma_mapping_error(trans->dev, rxb->page_dma)) { + rxb->page = NULL; + spin_lock_irqsave(&rxq->lock, flags); + list_add(&rxb->list, &rxq->rx_used); + spin_unlock_irqrestore(&rxq->lock, flags); + __free_pages(page, trans_pcie->rx_page_order); + return; + } /* dma address must be no more than 36 bits */ BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); /* and also 256 byte aligned! */ @@ -488,8 +496,19 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, dma_map_page(trans->dev, rxb->page, 0, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; + if (dma_mapping_error(trans->dev, rxb->page_dma)) { + /* + * free the page(s) as well to not break + * the invariant that the items on the used + * list have no page(s) + */ + __free_pages(rxb->page, trans_pcie->rx_page_order); + rxb->page = NULL; + list_add_tail(&rxb->list, &rxq->rx_used); + } else { + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; + } } else list_add_tail(&rxb->list, &rxq->rx_used); spin_unlock_irqrestore(&rxq->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 105e3af3c62..79a4ddc002d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u16 rd_ptr, wr_ptr; - int n_bd = trans_pcie->txq[txq_id].q.n_bd; if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { WARN_ONCE(1, "queue %d not used", txq_id); return; } - rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); - wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); - - WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", - txq_id, rd_ptr, wr_ptr); - iwl_txq_set_inactive(trans, txq_id); IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); } diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0679458a1ba..780d3e16829 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1825,8 +1825,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } - priv->scan_request = request; - priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); if (!priv->user_scan_cfg) { @@ -1834,6 +1832,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return -ENOMEM; } + priv->scan_request = request; + priv->user_scan_cfg->num_ssids = request->n_ssids; priv->user_scan_cfg->ssid_list = request->ssids; @@ -1870,6 +1870,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, ret = mwifiex_scan_networks(priv, priv->user_scan_cfg); if (ret) { dev_err(priv->adapter->dev, "scan failed: %d\n", ret); + priv->scan_request = NULL; + kfree(priv->user_scan_cfg); + priv->user_scan_cfg = NULL; return ret; } diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 8d465107f52..ae9010ed58d 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -890,9 +890,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) return; } cmd_node = adapter->curr_cmd; - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -ETIMEDOUT; - if (cmd_node) { adapter->dbg.timeout_cmd_id = adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; @@ -938,6 +935,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context) dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", adapter->ps_mode, adapter->ps_state); + + if (cmd_node->wait_q_enabled) { + adapter->cmd_wait_q.status = -ETIMEDOUT; + wake_up_interruptible(&adapter->cmd_wait_q.wait); + mwifiex_cancel_pending_ioctl(adapter); + /* reset cmd_sent flag to unblock new commands */ + adapter->cmd_sent = false; + } } if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) mwifiex_init_fw_complete(adapter); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 00b658d3b6e..9171aaedbcc 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1843,21 +1843,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, struct cfg80211_ssid *req_ssid) { struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; + int ret; struct mwifiex_user_scan_cfg *scan_cfg; - if (!req_ssid) - return -1; - if (adapter->scan_processing) { - dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); - return ret; + dev_err(adapter->dev, "cmd: Scan already in process...\n"); + return -EBUSY; } if (priv->scan_block) { - dev_dbg(adapter->dev, + dev_err(adapter->dev, "cmd: Scan is blocked during association...\n"); - return ret; + return -EBUSY; } scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index fc8a9bfa124..82cf0fa2d9f 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -161,7 +161,6 @@ static int mwifiex_sdio_suspend(struct device *dev) struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; - int hs_actived = 0; int i; int ret = 0; @@ -188,12 +187,14 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; /* Enable the Host Sleep */ - hs_actived = mwifiex_enable_hs(adapter); - if (hs_actived) { - pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (!mwifiex_enable_hs(adapter)) { + dev_err(adapter->dev, "cmd: failed to suspend\n"); + return -EFAULT; } + dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + /* Indicate device suspended */ adapter->is_suspended = true; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index a12e84f892b..6b2e1e431dd 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = { .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, + .reset_resume = rt2x00usb_resume, .disable_hub_initiated_lpm = 1, }; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 01dc8891070..59474ae0aec 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) /* * Check if temperature compensation is supported. */ - if (tssi_bounds[4] == 0xff) + if (tssi_bounds[4] == 0xff || step == 0xff) return 0; /* diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index c9e9370eb78..3b8fb5a603f 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = { .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, + .reset_resume = rt2x00usb_resume, .disable_hub_initiated_lpm = 1, }; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e5eb43b3eee..24eec66e9fd 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = { .disconnect = rt2x00usb_disconnect, .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, + .reset_resume = rt2x00usb_resume, .disable_hub_initiated_lpm = 1, }; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 9970c2b1b19..b7e6607e6b6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { /*=== Customer ID ===*/ /****** 8188CU ********/ {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ + {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 030beb45d8b..e3ea4b34688 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw) set_hal_start(rtlhal); /* Start bulk IN */ - _rtl_usb_receive(hw); + err = _rtl_usb_receive(hw); } return err; diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index caa011008cd..fc24eb9b394 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -452,29 +452,85 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, /* Grant backend access to each skb fragment page. */ for (i = 0; i < frags; i++) { skb_frag_t *frag = skb_shinfo(skb)->frags + i; + struct page *page = skb_frag_page(frag); - tx->flags |= XEN_NETTXF_more_data; + len = skb_frag_size(frag); + offset = frag->page_offset; - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); - np->tx_skbs[id].skb = skb_get(skb); - tx = RING_GET_REQUEST(&np->tx, prod++); - tx->id = id; - ref = gnttab_claim_grant_reference(&np->gref_tx_head); - BUG_ON((signed short)ref < 0); + /* Data must not cross a page boundary. */ + BUG_ON(len + offset > PAGE_SIZE<<compound_order(page)); - mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag))); - gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, - mfn, GNTMAP_readonly); + /* Skip unused frames from start of page */ + page += offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; - tx->gref = np->grant_tx_ref[id] = ref; - tx->offset = frag->page_offset; - tx->size = skb_frag_size(frag); - tx->flags = 0; + while (len > 0) { + unsigned long bytes; + + BUG_ON(offset >= PAGE_SIZE); + + bytes = PAGE_SIZE - offset; + if (bytes > len) + bytes = len; + + tx->flags |= XEN_NETTXF_more_data; + + id = get_id_from_freelist(&np->tx_skb_freelist, + np->tx_skbs); + np->tx_skbs[id].skb = skb_get(skb); + tx = RING_GET_REQUEST(&np->tx, prod++); + tx->id = id; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + + mfn = pfn_to_mfn(page_to_pfn(page)); + gnttab_grant_foreign_access_ref(ref, + np->xbdev->otherend_id, + mfn, GNTMAP_readonly); + + tx->gref = np->grant_tx_ref[id] = ref; + tx->offset = offset; + tx->size = bytes; + tx->flags = 0; + + offset += bytes; + len -= bytes; + + /* Next frame */ + if (offset == PAGE_SIZE && len) { + BUG_ON(!PageCompound(page)); + page++; + offset = 0; + } + } } np->tx.req_prod_pvt = prod; } +/* + * Count how many ring slots are required to send the frags of this + * skb. Each frag might be a compound page. + */ +static int xennet_count_skb_frag_slots(struct sk_buff *skb) +{ + int i, frags = skb_shinfo(skb)->nr_frags; + int pages = 0; + + for (i = 0; i < frags; i++) { + skb_frag_t *frag = skb_shinfo(skb)->frags + i; + unsigned long size = skb_frag_size(frag); + unsigned long offset = frag->page_offset; + + /* Skip unused frames from start of page */ + offset &= ~PAGE_MASK; + + pages += PFN_UP(offset + size); + } + + return pages; +} + static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned short id; @@ -487,23 +543,23 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) grant_ref_t ref; unsigned long mfn; int notify; - int frags = skb_shinfo(skb)->nr_frags; + int slots; unsigned int offset = offset_in_page(data); unsigned int len = skb_headlen(skb); unsigned long flags; - frags += DIV_ROUND_UP(offset + len, PAGE_SIZE); - if (unlikely(frags > MAX_SKB_FRAGS + 1)) { - printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n", - frags); - dump_stack(); + slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) + + xennet_count_skb_frag_slots(skb); + if (unlikely(slots > MAX_SKB_FRAGS + 1)) { + net_alert_ratelimited( + "xennet: skb rides the rocket: %d slots\n", slots); goto drop; } spin_lock_irqsave(&np->tx_lock, flags); if (unlikely(!netif_carrier_ok(dev) || - (frags > 1 && !xennet_can_sg(dev)) || + (slots > 1 && !xennet_can_sg(dev)) || netif_needs_gso(skb, netif_skb_features(skb)))) { spin_unlock_irqrestore(&np->tx_lock, flags); goto drop; diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 97c440a8cd6..30ae18a03a9 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -698,13 +698,14 @@ static void pn533_wq_cmd(struct work_struct *work) cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue); + list_del(&cmd->queue); + mutex_unlock(&dev->cmd_lock); __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, cmd->in_frame_len, cmd->cmd_complete, cmd->arg, cmd->flags); - list_del(&cmd->queue); kfree(cmd); } @@ -1678,11 +1679,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { - struct pn533_cmd_jump_dep *cmd; struct pn533_cmd_jump_dep_response *resp; struct nfc_target nfc_target; u8 target_gt_len; int rc; + struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg; + u8 active = cmd->active; + + kfree(arg); if (params_len == -ENOENT) { nfc_dev_dbg(&dev->interface->dev, ""); @@ -1704,7 +1708,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, } resp = (struct pn533_cmd_jump_dep_response *) params; - cmd = (struct pn533_cmd_jump_dep *) arg; rc = resp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { nfc_dev_err(&dev->interface->dev, @@ -1734,7 +1737,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (rc == 0) rc = nfc_dep_link_is_up(dev->nfc_dev, dev->nfc_dev->targets[0].idx, - !cmd->active, NFC_RF_INITIATOR); + !active, NFC_RF_INITIATOR); return 0; } @@ -1819,12 +1822,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, dev->in_maxlen, pn533_in_dep_link_up_complete, cmd, GFP_KERNEL); - if (rc) - goto out; - - -out: - kfree(cmd); + if (rc < 0) + kfree(cmd); return rc; } @@ -2078,8 +2077,12 @@ error: static int pn533_tm_send_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { + struct sk_buff *skb_out = arg; + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_kfree_skb(skb_out); + if (params_len < 0) { nfc_dev_err(&dev->interface->dev, "Error %d when sending data", @@ -2117,7 +2120,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, dev->in_maxlen, pn533_tm_send_complete, - NULL, GFP_KERNEL); + skb, GFP_KERNEL); if (rc) { nfc_dev_err(&dev->interface->dev, "Error %d when trying to send data", rc); diff --git a/drivers/of/address.c b/drivers/of/address.c index 72e496f1e9b..0125524c08c 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -37,9 +37,9 @@ struct of_bus { int (*match)(struct device_node *parent); void (*count_cells)(struct device_node *child, int *addrc, int *sizec); - u64 (*map)(u32 *addr, const __be32 *range, + u64 (*map)(__be32 *addr, const __be32 *range, int na, int ns, int pna); - int (*translate)(u32 *addr, u64 offset, int na); + int (*translate)(__be32 *addr, u64 offset, int na); unsigned int (*get_flags)(const __be32 *addr); }; @@ -56,7 +56,7 @@ static void of_bus_default_count_cells(struct device_node *dev, *sizec = of_n_size_cells(dev); } -static u64 of_bus_default_map(u32 *addr, const __be32 *range, +static u64 of_bus_default_map(__be32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; @@ -82,7 +82,7 @@ static u64 of_bus_default_map(u32 *addr, const __be32 *range, return da - cp; } -static int of_bus_default_translate(u32 *addr, u64 offset, int na) +static int of_bus_default_translate(__be32 *addr, u64 offset, int na) { u64 a = of_read_number(addr, na); memset(addr, 0, na * 4); @@ -138,7 +138,7 @@ static unsigned int of_bus_pci_get_flags(const __be32 *addr) return flags; } -static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns, +static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; @@ -165,7 +165,7 @@ static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns, return da - cp; } -static int of_bus_pci_translate(u32 *addr, u64 offset, int na) +static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) { return of_bus_default_translate(addr + 1, offset, na - 1); } @@ -247,7 +247,7 @@ static void of_bus_isa_count_cells(struct device_node *child, *sizec = 1; } -static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns, +static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns, int pna) { u64 cp, s, da; @@ -270,7 +270,7 @@ static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns, return da - cp; } -static int of_bus_isa_translate(u32 *addr, u64 offset, int na) +static int of_bus_isa_translate(__be32 *addr, u64 offset, int na) { return of_bus_default_translate(addr + 1, offset, na - 1); } @@ -338,7 +338,7 @@ static struct of_bus *of_match_bus(struct device_node *np) } static int of_translate_one(struct device_node *parent, struct of_bus *bus, - struct of_bus *pbus, u32 *addr, + struct of_bus *pbus, __be32 *addr, int na, int ns, int pna, const char *rprop) { const __be32 *ranges; @@ -409,12 +409,12 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things */ -u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr, - const char *rprop) +static u64 __of_translate_address(struct device_node *dev, + const __be32 *in_addr, const char *rprop) { struct device_node *parent = NULL; struct of_bus *bus, *pbus; - u32 addr[OF_MAX_ADDR_CELLS]; + __be32 addr[OF_MAX_ADDR_CELLS]; int na, ns, pna, pns; u64 result = OF_BAD_ADDR; diff --git a/drivers/of/irq.c b/drivers/of/irq.c index a23ec777999..a3c1c5aae6a 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -192,11 +192,13 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, /* Compare specifiers */ match = 1; for (i = 0; i < addrsize && match; ++i) { - u32 mask = imask ? imask[i] : 0xffffffffu; + __be32 mask = imask ? imask[i] + : cpu_to_be32(0xffffffffu); match = ((addr[i] ^ imap[i]) & mask) == 0; } for (; i < (addrsize + intsize) && match; ++i) { - u32 mask = imask ? imask[i] : 0xffffffffu; + __be32 mask = imask ? imask[i] + : cpu_to_be32(0xffffffffu); match = ((intspec[i-addrsize] ^ imap[i]) & mask) == 0; } @@ -465,7 +467,7 @@ void __init of_irq_init(const struct of_device_id *matches) pr_debug("of_irq_init: init %s @ %p, parent %p\n", match->compatible, desc->dev, desc->interrupt_parent); - irq_init_cb = match->data; + irq_init_cb = (of_irq_init_cb_t)match->data; ret = irq_init_cb(desc->dev, desc->interrupt_parent); if (ret) { kfree(desc); diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 9bdeaf30b17..b80891b4381 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -76,7 +76,7 @@ void of_device_make_bus_id(struct device *dev) { static atomic_t bus_no_reg_magic; struct device_node *node = dev->of_node; - const u32 *reg; + const __be32 *reg; u64 addr; const __be32 *addrp; int magic; diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 6241fd05bd4..a543746fb35 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -320,10 +320,7 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), } else next = dev->bus_list.next; - /* Run device routines with the device locked */ - device_lock(&dev->dev); retval = cb(dev, userdata); - device_unlock(&dev->dev); if (retval) break; } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 94c6e2aa03d..6c94fc9489e 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -398,6 +398,8 @@ static void pci_device_shutdown(struct device *dev) struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_driver *drv = pci_dev->driver; + pm_runtime_resume(dev); + if (drv && drv->shutdown) drv->shutdown(pci_dev); pci_msi_shutdown(pci_dev); @@ -408,16 +410,6 @@ static void pci_device_shutdown(struct device *dev) * continue to do DMA */ pci_disable_device(pci_dev); - - /* - * Devices may be enabled to wake up by runtime PM, but they need not - * be supposed to wake up the system from its "power off" state (e.g. - * ACPI S5). Therefore disable wakeup for all devices that aren't - * supposed to wake up the system at this point. The state argument - * will be ignored by pci_enable_wake(). - */ - if (!device_may_wakeup(dev)) - pci_enable_wake(pci_dev, PCI_UNKNOWN, false); } #ifdef CONFIG_PM diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 02d107b1528..f39378d9da1 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) } struct device_attribute vga_attr = __ATTR_RO(boot_vga); -static void -pci_config_pm_runtime_get(struct pci_dev *pdev) -{ - struct device *dev = &pdev->dev; - struct device *parent = dev->parent; - - if (parent) - pm_runtime_get_sync(parent); - pm_runtime_get_noresume(dev); - /* - * pdev->current_state is set to PCI_D3cold during suspending, - * so wait until suspending completes - */ - pm_runtime_barrier(dev); - /* - * Only need to resume devices in D3cold, because config - * registers are still accessible for devices suspended but - * not in D3cold. - */ - if (pdev->current_state == PCI_D3cold) - pm_runtime_resume(dev); -} - -static void -pci_config_pm_runtime_put(struct pci_dev *pdev) -{ - struct device *dev = &pdev->dev; - struct device *parent = dev->parent; - - pm_runtime_put(dev); - if (parent) - pm_runtime_put_sync(parent); -} - static ssize_t pci_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 54858838f09..aabf64798bd 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_dev_run_wake); +void pci_config_pm_runtime_get(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + if (parent) + pm_runtime_get_sync(parent); + pm_runtime_get_noresume(dev); + /* + * pdev->current_state is set to PCI_D3cold during suspending, + * so wait until suspending completes + */ + pm_runtime_barrier(dev); + /* + * Only need to resume devices in D3cold, because config + * registers are still accessible for devices suspended but + * not in D3cold. + */ + if (pdev->current_state == PCI_D3cold) + pm_runtime_resume(dev); +} + +void pci_config_pm_runtime_put(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + pm_runtime_put(dev); + if (parent) + pm_runtime_put_sync(parent); +} + /** * pci_pm_init - Initialize PM functions of given PCI device * @dev: PCI device to handle. diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index bacbcba69cf..fd92aab9904 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(struct pci_dev *dev); extern int pci_finish_runtime_suspend(struct pci_dev *dev); extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); extern void pci_wakeup_bus(struct pci_bus *bus); +extern void pci_config_pm_runtime_get(struct pci_dev *dev); +extern void pci_config_pm_runtime_put(struct pci_dev *dev); extern void pci_pm_init(struct pci_dev *dev); extern void platform_pci_wakeup_init(struct pci_dev *dev); extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 06bad96af41..af4e31cd3a3 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -213,6 +213,7 @@ static int report_error_detected(struct pci_dev *dev, void *data) struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; + device_lock(&dev->dev); dev->error_state = result_data->state; if (!dev->driver || @@ -231,12 +232,14 @@ static int report_error_detected(struct pci_dev *dev, void *data) dev->driver ? "no AER-aware driver" : "no driver"); } - return 0; + goto out; } err_handler = dev->driver->err_handler; vote = err_handler->error_detected(dev, result_data->state); result_data->result = merge_result(result_data->result, vote); +out: + device_unlock(&dev->dev); return 0; } @@ -247,14 +250,17 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data) struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; + device_lock(&dev->dev); if (!dev->driver || !dev->driver->err_handler || !dev->driver->err_handler->mmio_enabled) - return 0; + goto out; err_handler = dev->driver->err_handler; vote = err_handler->mmio_enabled(dev); result_data->result = merge_result(result_data->result, vote); +out: + device_unlock(&dev->dev); return 0; } @@ -265,14 +271,17 @@ static int report_slot_reset(struct pci_dev *dev, void *data) struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; + device_lock(&dev->dev); if (!dev->driver || !dev->driver->err_handler || !dev->driver->err_handler->slot_reset) - return 0; + goto out; err_handler = dev->driver->err_handler; vote = err_handler->slot_reset(dev); result_data->result = merge_result(result_data->result, vote); +out: + device_unlock(&dev->dev); return 0; } @@ -280,15 +289,18 @@ static int report_resume(struct pci_dev *dev, void *data) { const struct pci_error_handlers *err_handler; + device_lock(&dev->dev); dev->error_state = pci_channel_io_normal; if (!dev->driver || !dev->driver->err_handler || !dev->driver->err_handler->resume) - return 0; + goto out; err_handler = dev->driver->err_handler; err_handler->resume(dev); +out: + device_unlock(&dev->dev); return 0; } diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index d03a7a39b2d..ed129b41462 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -272,7 +272,8 @@ static int get_port_device_capability(struct pci_dev *dev) } /* Hot-Plug Capable */ - if (cap_mask & PCIE_PORT_SERVICE_HP) { + if ((cap_mask & PCIE_PORT_SERVICE_HP) && + dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) { pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, ®32); if (reg32 & PCI_EXP_SLTCAP_HPC) { services |= PCIE_PORT_SERVICE_HP; diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index eb907a8faf2..9b8505ccc56 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp if (!access_ok(VERIFY_WRITE, buf, cnt)) return -EINVAL; + pci_config_pm_runtime_get(dev); + if ((pos & 1) && cnt) { unsigned char val; pci_user_read_config_byte(dev, pos, &val); @@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp cnt--; } + pci_config_pm_runtime_put(dev); + *ppos = pos; return nbytes; } @@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof if (!access_ok(VERIFY_READ, buf, cnt)) return -EINVAL; + pci_config_pm_runtime_get(dev); + if ((pos & 1) && cnt) { unsigned char val; __get_user(val, buf); @@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof cnt--; } + pci_config_pm_runtime_put(dev); + *ppos = pos; i_size_write(ino, dp->size); return nbytes; diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index b066273b6b4..7dd879ce514 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -194,7 +194,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) sharpsl_pcmcia_init_reset(skt); } -static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = { +static struct pcmcia_low_level sharpsl_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = sharpsl_pcmcia_hw_init, .socket_state = sharpsl_pcmcia_socket_state, diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7bf914df6e9..aeecf0f72ca 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -178,12 +178,14 @@ config PINCTRL_COH901 ports of 8 GPIO pins each. config PINCTRL_SAMSUNG - bool "Samsung pinctrl driver" + bool + depends on OF && GPIOLIB select PINMUX select PINCONF config PINCTRL_EXYNOS4 bool "Pinctrl driver data for Exynos4 SoC" + depends on OF && GPIOLIB select PINCTRL_SAMSUNG config PINCTRL_MVEBU diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 0f1ec9e8ff1..2e39c04fc16 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1061,8 +1061,10 @@ static int pinctrl_groups_show(struct seq_file *s, void *what) seq_printf(s, "group: %s\n", gname); for (i = 0; i < num_pins; i++) { pname = pin_get_name(pctldev, pins[i]); - if (WARN_ON(!pname)) + if (WARN_ON(!pname)) { + mutex_unlock(&pinctrl_mutex); return -EINVAL; + } seq_printf(s, "pin %d (%s)\n", pins[i], pname); } seq_puts(s, "\n"); diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 43f474cdc11..baee2cc46a1 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -537,8 +537,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what) seq_puts(s, "Pin config settings per pin group\n"); seq_puts(s, "Format: group (name): configs\n"); - mutex_lock(&pinctrl_mutex); - while (selector < ngroups) { const char *gname = pctlops->get_group_name(pctldev, selector); @@ -549,8 +547,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what) selector++; } - mutex_unlock(&pinctrl_mutex); - return 0; } diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c index a4adee633fa..7e9be18ec2d 100644 --- a/drivers/pinctrl/pinctrl-bcm2835.c +++ b/drivers/pinctrl/pinctrl-bcm2835.c @@ -29,7 +29,6 @@ #include <linux/irq.h> #include <linux/irqdesc.h> #include <linux/irqdomain.h> -#include <linux/irq.h> #include <linux/module.h> #include <linux/of_address.h> #include <linux/of.h> @@ -960,7 +959,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev) return err; } - pc->base = devm_request_and_ioremap(&pdev->dev, &iomem); + pc->base = devm_request_and_ioremap(dev, &iomem); if (!pc->base) return -EADDRNOTAVAIL; @@ -1032,7 +1031,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev) pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc); if (!pc->pctl_dev) { gpiochip_remove(&pc->gpio_chip); - return PTR_ERR(pc->pctl_dev); + return -EINVAL; } pc->gpio_range = bcm2835_pinctrl_gpio_range; diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index fec9c30133d..cf82d9ce4de 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -30,7 +30,20 @@ #include <linux/pinctrl/pinconf.h> /* Since we request GPIOs from ourself */ #include <linux/pinctrl/consumer.h> +/* + * For the U8500 archs, use the PRCMU register interface, for the older + * Nomadik, provide some stubs. The functions using these will only be + * called on the U8500 series. + */ +#ifdef CONFIG_ARCH_U8500 #include <linux/mfd/dbx500-prcmu.h> +#else +static inline u32 prcmu_read(unsigned int reg) { + return 0; +} +static inline void prcmu_write(unsigned int reg, u32 value) {} +static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {} +#endif #include <asm/mach/irq.h> @@ -1043,7 +1056,7 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); - return irq_find_mapping(nmk_chip->domain, offset); + return irq_create_mapping(nmk_chip->domain, offset); } #ifdef CONFIG_DEBUG_FS @@ -1268,6 +1281,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) struct clk *clk; int secondary_irq; void __iomem *base; + int irq_start = 0; int irq; int ret; @@ -1371,19 +1385,11 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) platform_set_drvdata(dev, nmk_chip); - if (np) { - /* The DT case will just grab a set of IRQ numbers */ - nmk_chip->domain = irq_domain_add_linear(np, NMK_GPIO_PER_CHIP, - &nmk_gpio_irq_simple_ops, nmk_chip); - } else { - /* Non-DT legacy mode, use hardwired IRQ numbers */ - int irq_start; - + if (!np) irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio); - nmk_chip->domain = irq_domain_add_simple(NULL, + nmk_chip->domain = irq_domain_add_simple(np, NMK_GPIO_PER_CHIP, irq_start, &nmk_gpio_irq_simple_ops, nmk_chip); - } if (!nmk_chip->domain) { dev_err(&dev->dev, "failed to create irqdomain\n"); ret = -ENOSYS; diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index dd108a94acf..861cd5f04d5 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -513,7 +513,7 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset, * Parse the pin names listed in the 'samsung,pins' property and convert it * into a list of gpio numbers are create a pin group from it. */ -static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev, +static int __devinit samsung_pinctrl_parse_dt_pins(struct platform_device *pdev, struct device_node *cfg_np, struct pinctrl_desc *pctl, unsigned int **pin_list, unsigned int *npins) { @@ -560,7 +560,7 @@ static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev, * from device node of the pin-controller. A pin group is formed with all * the pins listed in the "samsung,pins" property. */ -static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev, +static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev, struct samsung_pinctrl_drv_data *drvdata) { struct device *dev = &pdev->dev; @@ -655,7 +655,7 @@ static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev, } /* register the pinctrl interface with the pinctrl subsystem */ -static int __init samsung_pinctrl_register(struct platform_device *pdev, +static int __devinit samsung_pinctrl_register(struct platform_device *pdev, struct samsung_pinctrl_drv_data *drvdata) { struct pinctrl_desc *ctrldesc = &drvdata->pctl; @@ -729,7 +729,7 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev, } /* register the gpiolib interface with the gpiolib subsystem */ -static int __init samsung_gpiolib_register(struct platform_device *pdev, +static int __devinit samsung_gpiolib_register(struct platform_device *pdev, struct samsung_pinctrl_drv_data *drvdata) { struct gpio_chip *gc; @@ -762,7 +762,7 @@ static int __init samsung_gpiolib_register(struct platform_device *pdev, } /* unregister the gpiolib interface with the gpiolib subsystem */ -static int __init samsung_gpiolib_unregister(struct platform_device *pdev, +static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev, struct samsung_pinctrl_drv_data *drvdata) { int ret = gpiochip_remove(drvdata->gc); diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index 675497c1514..9ecacf3d0a7 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c @@ -1323,41 +1323,6 @@ static inline struct sirfsoc_gpio_bank *sirfsoc_gpio_to_bank(unsigned int gpio) return &sgpio_bank[gpio / SIRFSOC_GPIO_BANK_SIZE]; } -void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode) -{ - struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(gpio); - int idx = sirfsoc_gpio_to_offset(gpio); - u32 val, offset; - unsigned long flags; - - offset = SIRFSOC_GPIO_CTRL(bank->id, idx); - - spin_lock_irqsave(&sgpio_lock, flags); - - val = readl(bank->chip.regs + offset); - - switch (mode) { - case SIRFSOC_GPIO_PULL_NONE: - val &= ~SIRFSOC_GPIO_CTL_PULL_MASK; - break; - case SIRFSOC_GPIO_PULL_UP: - val |= SIRFSOC_GPIO_CTL_PULL_MASK; - val |= SIRFSOC_GPIO_CTL_PULL_HIGH; - break; - case SIRFSOC_GPIO_PULL_DOWN: - val |= SIRFSOC_GPIO_CTL_PULL_MASK; - val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH; - break; - default: - break; - } - - writel(val, bank->chip.regs + offset); - - spin_unlock_irqrestore(&sgpio_lock, flags); -} -EXPORT_SYMBOL(sirfsoc_gpio_set_pull); - static inline struct sirfsoc_gpio_bank *sirfsoc_irqchip_to_bank(struct gpio_chip *chip) { return container_of(to_of_mm_gpio_chip(chip), struct sirfsoc_gpio_bank, chip); diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index 729b686c3ad..7da0b371fd6 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -464,7 +464,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx, *bank = g->drv_bank; *reg = g->drv_reg; *bit = g->lpmd_bit; - *width = 1; + *width = 2; break; case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH: *bank = g->drv_bank; diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index 0386fdf0da1..7894f14c705 100644 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ b/drivers/pinctrl/pinctrl-tegra30.c @@ -3345,10 +3345,10 @@ static const struct tegra_function tegra30_functions[] = { FUNCTION(vi_alt3), }; -#define MUXCTL_REG_A 0x3000 -#define PINGROUP_REG_A 0x868 +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ -#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A) +#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A) #define PINGROUP_REG_N(r) -1 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior) \ @@ -3364,25 +3364,25 @@ static const struct tegra_function tegra30_functions[] = { }, \ .func_safe = TEGRA_MUX_ ## f_safe, \ .mux_reg = PINGROUP_REG_Y(r), \ - .mux_bank = 0, \ + .mux_bank = 1, \ .mux_bit = 0, \ .pupd_reg = PINGROUP_REG_Y(r), \ - .pupd_bank = 0, \ + .pupd_bank = 1, \ .pupd_bit = 2, \ .tri_reg = PINGROUP_REG_Y(r), \ - .tri_bank = 0, \ + .tri_bank = 1, \ .tri_bit = 4, \ .einput_reg = PINGROUP_REG_Y(r), \ - .einput_bank = 0, \ + .einput_bank = 1, \ .einput_bit = 5, \ .odrain_reg = PINGROUP_REG_##od(r), \ - .odrain_bank = 0, \ + .odrain_bank = 1, \ .odrain_bit = 6, \ .lock_reg = PINGROUP_REG_Y(r), \ - .lock_bank = 0, \ + .lock_bank = 1, \ .lock_bit = 7, \ .ioreset_reg = PINGROUP_REG_##ior(r), \ - .ioreset_bank = 0, \ + .ioreset_bank = 1, \ .ioreset_bit = 8, \ .drv_reg = -1, \ } @@ -3401,8 +3401,8 @@ static const struct tegra_function tegra30_functions[] = { .odrain_reg = -1, \ .lock_reg = -1, \ .ioreset_reg = -1, \ - .drv_reg = ((r) - PINGROUP_REG_A), \ - .drv_bank = 1, \ + .drv_reg = ((r) - DRV_PINGROUP_REG_A), \ + .drv_bank = 0, \ .hsm_bit = hsm_b, \ .schmitt_bit = schmitt_b, \ .lpmd_bit = lpmd_b, \ diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c index f8d917d40c9..b9bcaec6622 100644 --- a/drivers/pinctrl/pinctrl-xway.c +++ b/drivers/pinctrl/pinctrl-xway.c @@ -17,8 +17,6 @@ #include <linux/ioport.h> #include <linux/io.h> #include <linux/device.h> -#include <linux/module.h> -#include <linux/io.h> #include <linux/platform_device.h> #include "pinctrl-lantiq.h" diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index 5d4f44f462f..b1fd6ee33c6 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -244,7 +244,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev, else temp = ~muxreg->val; - val |= temp; + val |= muxreg->mask & temp; pmx_writel(pmx, val, muxreg->reg); } } diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c index d6cca8c81b9..0436fc7895d 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1310.c +++ b/drivers/pinctrl/spear/pinctrl-spear1310.c @@ -25,8 +25,8 @@ static const struct pinctrl_pin_desc spear1310_pins[] = { }; /* registers */ -#define PERIP_CFG 0x32C - #define MCIF_SEL_SHIFT 3 +#define PERIP_CFG 0x3B0 + #define MCIF_SEL_SHIFT 5 #define MCIF_SEL_SD (0x1 << MCIF_SEL_SHIFT) #define MCIF_SEL_CF (0x2 << MCIF_SEL_SHIFT) #define MCIF_SEL_XD (0x3 << MCIF_SEL_SHIFT) @@ -164,6 +164,10 @@ static const struct pinctrl_pin_desc spear1310_pins[] = { #define PMX_SSP0_CS0_MASK (1 << 29) #define PMX_SSP0_CS1_2_MASK (1 << 30) +#define PAD_DIRECTION_SEL_0 0x65C +#define PAD_DIRECTION_SEL_1 0x660 +#define PAD_DIRECTION_SEL_2 0x664 + /* combined macros */ #define PMX_GMII_MASK (PMX_GMIICLK_MASK | \ PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK | \ @@ -237,6 +241,10 @@ static struct spear_muxreg i2c0_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2C0_MASK, .val = PMX_I2C0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2C0_MASK, + .val = PMX_I2C0_MASK, }, }; @@ -269,6 +277,10 @@ static struct spear_muxreg ssp0_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_SSP0_MASK, .val = PMX_SSP0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_SSP0_MASK, + .val = PMX_SSP0_MASK, }, }; @@ -294,6 +306,10 @@ static struct spear_muxreg ssp0_cs0_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_SSP0_CS0_MASK, .val = PMX_SSP0_CS0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_SSP0_CS0_MASK, + .val = PMX_SSP0_CS0_MASK, }, }; @@ -319,6 +335,10 @@ static struct spear_muxreg ssp0_cs1_2_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_SSP0_CS1_2_MASK, .val = PMX_SSP0_CS1_2_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_SSP0_CS1_2_MASK, + .val = PMX_SSP0_CS1_2_MASK, }, }; @@ -352,6 +372,10 @@ static struct spear_muxreg i2s0_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2S0_MASK, .val = PMX_I2S0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2S0_MASK, + .val = PMX_I2S0_MASK, }, }; @@ -384,6 +408,10 @@ static struct spear_muxreg i2s1_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_I2S1_MASK, .val = PMX_I2S1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_I2S1_MASK, + .val = PMX_I2S1_MASK, }, }; @@ -418,6 +446,10 @@ static struct spear_muxreg clcd_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK, .val = PMX_CLCD1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK, + .val = PMX_CLCD1_MASK, }, }; @@ -443,6 +475,10 @@ static struct spear_muxreg clcd_high_res_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_CLCD2_MASK, .val = PMX_CLCD2_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_CLCD2_MASK, + .val = PMX_CLCD2_MASK, }, }; @@ -461,7 +497,7 @@ static struct spear_pingroup clcd_high_res_pingroup = { .nmodemuxs = ARRAY_SIZE(clcd_high_res_modemux), }; -static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res" }; +static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res_grp" }; static struct spear_function clcd_function = { .name = "clcd", .groups = clcd_grps, @@ -479,6 +515,14 @@ static struct spear_muxreg arm_gpio_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_EGPIO_1_GRP_MASK, .val = PMX_EGPIO_1_GRP_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_EGPIO_0_GRP_MASK, + .val = PMX_EGPIO_0_GRP_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_EGPIO_1_GRP_MASK, + .val = PMX_EGPIO_1_GRP_MASK, }, }; @@ -511,6 +555,10 @@ static struct spear_muxreg smi_2_chips_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_SMI_MASK, .val = PMX_SMI_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_SMI_MASK, + .val = PMX_SMI_MASK, }, }; @@ -539,6 +587,14 @@ static struct spear_muxreg smi_4_chips_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_SMI_MASK, + .val = PMX_SMI_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, + .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, }, }; @@ -573,6 +629,10 @@ static struct spear_muxreg gmii_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_GMII_MASK, .val = PMX_GMII_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_GMII_MASK, + .val = PMX_GMII_MASK, }, }; @@ -615,6 +675,18 @@ static struct spear_muxreg rgmii_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_RGMII_REG2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_RGMII_REG0_MASK, + .val = PMX_RGMII_REG0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_RGMII_REG1_MASK, + .val = PMX_RGMII_REG1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_RGMII_REG2_MASK, + .val = PMX_RGMII_REG2_MASK, }, }; @@ -649,6 +721,10 @@ static struct spear_muxreg smii_0_1_2_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_SMII_0_1_2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_SMII_0_1_2_MASK, + .val = PMX_SMII_0_1_2_MASK, }, }; @@ -681,6 +757,10 @@ static struct spear_muxreg ras_mii_txclk_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NFCE2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NFCE2_MASK, + .val = PMX_NFCE2_MASK, }, }; @@ -721,6 +801,14 @@ static struct spear_muxreg nand_8bit_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NAND8BIT_1_MASK, .val = PMX_NAND8BIT_1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_NAND8BIT_0_MASK, + .val = PMX_NAND8BIT_0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NAND8BIT_1_MASK, + .val = PMX_NAND8BIT_1_MASK, }, }; @@ -747,6 +835,10 @@ static struct spear_muxreg nand_16bit_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NAND16BIT_1_MASK, .val = PMX_NAND16BIT_1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NAND16BIT_1_MASK, + .val = PMX_NAND16BIT_1_MASK, }, }; @@ -772,6 +864,10 @@ static struct spear_muxreg nand_4_chips_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NAND_4CHIPS_MASK, .val = PMX_NAND_4CHIPS_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NAND_4CHIPS_MASK, + .val = PMX_NAND_4CHIPS_MASK, }, }; @@ -833,6 +929,10 @@ static struct spear_muxreg keyboard_rowcol6_8_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_KBD_ROWCOL68_MASK, .val = PMX_KBD_ROWCOL68_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_KBD_ROWCOL68_MASK, + .val = PMX_KBD_ROWCOL68_MASK, }, }; @@ -866,6 +966,10 @@ static struct spear_muxreg uart0_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_UART0_MASK, .val = PMX_UART0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_UART0_MASK, + .val = PMX_UART0_MASK, }, }; @@ -891,6 +995,10 @@ static struct spear_muxreg uart0_modem_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_UART0_MODEM_MASK, .val = PMX_UART0_MODEM_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_UART0_MODEM_MASK, + .val = PMX_UART0_MODEM_MASK, }, }; @@ -923,6 +1031,10 @@ static struct spear_muxreg gpt0_tmr0_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_GPT0_TMR0_MASK, .val = PMX_GPT0_TMR0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_GPT0_TMR0_MASK, + .val = PMX_GPT0_TMR0_MASK, }, }; @@ -948,6 +1060,10 @@ static struct spear_muxreg gpt0_tmr1_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_GPT0_TMR1_MASK, .val = PMX_GPT0_TMR1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_GPT0_TMR1_MASK, + .val = PMX_GPT0_TMR1_MASK, }, }; @@ -980,6 +1096,10 @@ static struct spear_muxreg gpt1_tmr0_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_GPT1_TMR0_MASK, .val = PMX_GPT1_TMR0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_GPT1_TMR0_MASK, + .val = PMX_GPT1_TMR0_MASK, }, }; @@ -1005,6 +1125,10 @@ static struct spear_muxreg gpt1_tmr1_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_GPT1_TMR1_MASK, .val = PMX_GPT1_TMR1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_GPT1_TMR1_MASK, + .val = PMX_GPT1_TMR1_MASK, }, }; @@ -1049,6 +1173,20 @@ static const unsigned mcif_pins[] = { 86, 87, 88, 89, 90, 91, 92, 93, 213, 214, .reg = PAD_FUNCTION_EN_2, \ .mask = PMX_MCIFALL_2_MASK, \ .val = PMX_MCIFALL_2_MASK, \ + }, { \ + .reg = PAD_DIRECTION_SEL_0, \ + .mask = PMX_MCI_DATA8_15_MASK, \ + .val = PMX_MCI_DATA8_15_MASK, \ + }, { \ + .reg = PAD_DIRECTION_SEL_1, \ + .mask = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK | \ + PMX_NFWPRT2_MASK, \ + .val = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK | \ + PMX_NFWPRT2_MASK, \ + }, { \ + .reg = PAD_DIRECTION_SEL_2, \ + .mask = PMX_MCIFALL_2_MASK, \ + .val = PMX_MCIFALL_2_MASK, \ } /* sdhci device */ @@ -1154,6 +1292,10 @@ static struct spear_muxreg touch_xy_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_TOUCH_XY_MASK, .val = PMX_TOUCH_XY_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_TOUCH_XY_MASK, + .val = PMX_TOUCH_XY_MASK, }, }; @@ -1187,6 +1329,10 @@ static struct spear_muxreg uart1_dis_i2c_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2C0_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2C0_MASK, + .val = PMX_I2C0_MASK, }, }; @@ -1213,6 +1359,12 @@ static struct spear_muxreg uart1_dis_sd_muxreg[] = { .mask = PMX_MCIDATA1_MASK | PMX_MCIDATA2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_MCIDATA1_MASK | + PMX_MCIDATA2_MASK, + .val = PMX_MCIDATA1_MASK | + PMX_MCIDATA2_MASK, }, }; @@ -1246,6 +1398,10 @@ static struct spear_muxreg uart2_3_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2S0_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2S0_MASK, + .val = PMX_I2S0_MASK, }, }; @@ -1278,6 +1434,10 @@ static struct spear_muxreg uart4_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK, + .val = PMX_I2S0_MASK | PMX_CLCD1_MASK, }, }; @@ -1310,6 +1470,10 @@ static struct spear_muxreg uart5_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK, + .val = PMX_CLCD1_MASK, }, }; @@ -1344,6 +1508,10 @@ static struct spear_muxreg rs485_0_1_tdm_0_1_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK, + .val = PMX_CLCD1_MASK, }, }; @@ -1376,6 +1544,10 @@ static struct spear_muxreg i2c_1_2_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK, + .val = PMX_CLCD1_MASK, }, }; @@ -1409,6 +1581,10 @@ static struct spear_muxreg i2c3_dis_smi_clcd_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK | PMX_SMI_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK | PMX_SMI_MASK, + .val = PMX_CLCD1_MASK | PMX_SMI_MASK, }, }; @@ -1435,6 +1611,10 @@ static struct spear_muxreg i2c3_dis_sd_i2s0_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK, + .val = PMX_I2S1_MASK | PMX_MCIDATA3_MASK, }, }; @@ -1469,6 +1649,10 @@ static struct spear_muxreg i2c_4_5_dis_smi_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_SMI_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_SMI_MASK, + .val = PMX_SMI_MASK, }, }; @@ -1499,6 +1683,14 @@ static struct spear_muxreg i2c4_dis_sd_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_MCIDATA5_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_MCIDATA4_MASK, + .val = PMX_MCIDATA4_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIDATA5_MASK, + .val = PMX_MCIDATA5_MASK, }, }; @@ -1526,6 +1718,12 @@ static struct spear_muxreg i2c5_dis_sd_muxreg[] = { .mask = PMX_MCIDATA6_MASK | PMX_MCIDATA7_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIDATA6_MASK | + PMX_MCIDATA7_MASK, + .val = PMX_MCIDATA6_MASK | + PMX_MCIDATA7_MASK, }, }; @@ -1560,6 +1758,10 @@ static struct spear_muxreg i2c_6_7_dis_kbd_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_KBD_ROWCOL25_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_KBD_ROWCOL25_MASK, + .val = PMX_KBD_ROWCOL25_MASK, }, }; @@ -1587,6 +1789,12 @@ static struct spear_muxreg i2c6_dis_sd_muxreg[] = { .mask = PMX_MCIIORDRE_MASK | PMX_MCIIOWRWE_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIIORDRE_MASK | + PMX_MCIIOWRWE_MASK, + .val = PMX_MCIIORDRE_MASK | + PMX_MCIIOWRWE_MASK, }, }; @@ -1613,6 +1821,12 @@ static struct spear_muxreg i2c7_dis_sd_muxreg[] = { .mask = PMX_MCIRESETCF_MASK | PMX_MCICS0CE_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIRESETCF_MASK | + PMX_MCICS0CE_MASK, + .val = PMX_MCIRESETCF_MASK | + PMX_MCICS0CE_MASK, }, }; @@ -1651,6 +1865,14 @@ static struct spear_muxreg can0_dis_nor_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NFRSTPWDWN3_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_NFRSTPWDWN2_MASK, + .val = PMX_NFRSTPWDWN2_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NFRSTPWDWN3_MASK, + .val = PMX_NFRSTPWDWN3_MASK, }, }; @@ -1677,6 +1899,10 @@ static struct spear_muxreg can0_dis_sd_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK, + .val = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK, }, }; @@ -1711,6 +1937,10 @@ static struct spear_muxreg can1_dis_sd_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK, + .val = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK, }, }; @@ -1737,6 +1967,10 @@ static struct spear_muxreg can1_dis_kbd_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_KBD_ROWCOL25_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_KBD_ROWCOL25_MASK, + .val = PMX_KBD_ROWCOL25_MASK, }, }; @@ -1763,29 +1997,64 @@ static struct spear_function can1_function = { .ngroups = ARRAY_SIZE(can1_grps), }; -/* Pad multiplexing for pci device */ -static const unsigned pci_sata_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18, +/* Pad multiplexing for (ras-ip) pci device */ +static const unsigned pci_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; -#define PCI_SATA_MUXREG \ - { \ - .reg = PAD_FUNCTION_EN_0, \ - .mask = PMX_MCI_DATA8_15_MASK, \ - .val = 0, \ - }, { \ - .reg = PAD_FUNCTION_EN_1, \ - .mask = PMX_PCI_REG1_MASK, \ - .val = 0, \ - }, { \ - .reg = PAD_FUNCTION_EN_2, \ - .mask = PMX_PCI_REG2_MASK, \ - .val = 0, \ - } -/* pad multiplexing for pcie0 device */ +static struct spear_muxreg pci_muxreg[] = { + { + .reg = PAD_FUNCTION_EN_0, + .mask = PMX_MCI_DATA8_15_MASK, + .val = 0, + }, { + .reg = PAD_FUNCTION_EN_1, + .mask = PMX_PCI_REG1_MASK, + .val = 0, + }, { + .reg = PAD_FUNCTION_EN_2, + .mask = PMX_PCI_REG2_MASK, + .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_MCI_DATA8_15_MASK, + .val = PMX_MCI_DATA8_15_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_PCI_REG1_MASK, + .val = PMX_PCI_REG1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_PCI_REG2_MASK, + .val = PMX_PCI_REG2_MASK, + }, +}; + +static struct spear_modemux pci_modemux[] = { + { + .muxregs = pci_muxreg, + .nmuxregs = ARRAY_SIZE(pci_muxreg), + }, +}; + +static struct spear_pingroup pci_pingroup = { + .name = "pci_grp", + .pins = pci_pins, + .npins = ARRAY_SIZE(pci_pins), + .modemuxs = pci_modemux, + .nmodemuxs = ARRAY_SIZE(pci_modemux), +}; + +static const char *const pci_grps[] = { "pci_grp" }; +static struct spear_function pci_function = { + .name = "pci", + .groups = pci_grps, + .ngroups = ARRAY_SIZE(pci_grps), +}; + +/* pad multiplexing for (fix-part) pcie0 device */ static struct spear_muxreg pcie0_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = PCIE_CFG_VAL(0), @@ -1802,15 +2071,12 @@ static struct spear_modemux pcie0_modemux[] = { static struct spear_pingroup pcie0_pingroup = { .name = "pcie0_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = pcie0_modemux, .nmodemuxs = ARRAY_SIZE(pcie0_modemux), }; -/* pad multiplexing for pcie1 device */ +/* pad multiplexing for (fix-part) pcie1 device */ static struct spear_muxreg pcie1_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = PCIE_CFG_VAL(1), @@ -1827,15 +2093,12 @@ static struct spear_modemux pcie1_modemux[] = { static struct spear_pingroup pcie1_pingroup = { .name = "pcie1_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = pcie1_modemux, .nmodemuxs = ARRAY_SIZE(pcie1_modemux), }; -/* pad multiplexing for pcie2 device */ +/* pad multiplexing for (fix-part) pcie2 device */ static struct spear_muxreg pcie2_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = PCIE_CFG_VAL(2), @@ -1852,22 +2115,20 @@ static struct spear_modemux pcie2_modemux[] = { static struct spear_pingroup pcie2_pingroup = { .name = "pcie2_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = pcie2_modemux, .nmodemuxs = ARRAY_SIZE(pcie2_modemux), }; -static const char *const pci_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" }; -static struct spear_function pci_function = { - .name = "pci", - .groups = pci_grps, - .ngroups = ARRAY_SIZE(pci_grps), +static const char *const pcie_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" +}; +static struct spear_function pcie_function = { + .name = "pci_express", + .groups = pcie_grps, + .ngroups = ARRAY_SIZE(pcie_grps), }; /* pad multiplexing for sata0 device */ static struct spear_muxreg sata0_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = SATA_CFG_VAL(0), @@ -1884,15 +2145,12 @@ static struct spear_modemux sata0_modemux[] = { static struct spear_pingroup sata0_pingroup = { .name = "sata0_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = sata0_modemux, .nmodemuxs = ARRAY_SIZE(sata0_modemux), }; /* pad multiplexing for sata1 device */ static struct spear_muxreg sata1_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = SATA_CFG_VAL(1), @@ -1909,15 +2167,12 @@ static struct spear_modemux sata1_modemux[] = { static struct spear_pingroup sata1_pingroup = { .name = "sata1_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = sata1_modemux, .nmodemuxs = ARRAY_SIZE(sata1_modemux), }; /* pad multiplexing for sata2 device */ static struct spear_muxreg sata2_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = SATA_CFG_VAL(2), @@ -1934,8 +2189,6 @@ static struct spear_modemux sata2_modemux[] = { static struct spear_pingroup sata2_pingroup = { .name = "sata2_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = sata2_modemux, .nmodemuxs = ARRAY_SIZE(sata2_modemux), }; @@ -1957,6 +2210,14 @@ static struct spear_muxreg ssp1_dis_kbd_muxreg[] = { PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK | PMX_NFCE2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK | + PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK | + PMX_NFCE2_MASK, + .val = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK | + PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK | + PMX_NFCE2_MASK, }, }; @@ -1983,6 +2244,12 @@ static struct spear_muxreg ssp1_dis_sd_muxreg[] = { .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK | PMX_MCICECF_MASK | PMX_MCICEXD_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK | + PMX_MCICECF_MASK | PMX_MCICEXD_MASK, + .val = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK | + PMX_MCICECF_MASK | PMX_MCICEXD_MASK, }, }; @@ -2017,6 +2284,12 @@ static struct spear_muxreg gpt64_muxreg[] = { .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK | PMX_MCILEDS_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK + | PMX_MCILEDS_MASK, + .val = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK + | PMX_MCILEDS_MASK, }, }; @@ -2093,6 +2366,7 @@ static struct spear_pingroup *spear1310_pingroups[] = { &can0_dis_sd_pingroup, &can1_dis_sd_pingroup, &can1_dis_kbd_pingroup, + &pci_pingroup, &pcie0_pingroup, &pcie1_pingroup, &pcie2_pingroup, @@ -2138,6 +2412,7 @@ static struct spear_function *spear1310_functions[] = { &can0_function, &can1_function, &pci_function, + &pcie_function, &sata_function, &ssp1_function, &gpt64_function, diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c index a0eb057e55b..0606b8cf3f2 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1340.c +++ b/drivers/pinctrl/spear/pinctrl-spear1340.c @@ -213,7 +213,7 @@ static const struct pinctrl_pin_desc spear1340_pins[] = { * Pad multiplexing for making all pads as gpio's. This is done to override the * values passed from bootloader and start from scratch. */ -static const unsigned pads_as_gpio_pins[] = { 251 }; +static const unsigned pads_as_gpio_pins[] = { 12, 88, 89, 251 }; static struct spear_muxreg pads_as_gpio_muxreg[] = { { .reg = PAD_FUNCTION_EN_1, @@ -1692,7 +1692,43 @@ static struct spear_pingroup clcd_pingroup = { .nmodemuxs = ARRAY_SIZE(clcd_modemux), }; -static const char *const clcd_grps[] = { "clcd_grp" }; +/* Disable cld runtime to save panel damage */ +static struct spear_muxreg clcd_sleep_muxreg[] = { + { + .reg = PAD_SHARED_IP_EN_1, + .mask = ARM_TRACE_MASK | MIPHY_DBG_MASK, + .val = 0, + }, { + .reg = PAD_FUNCTION_EN_5, + .mask = CLCD_REG4_MASK | CLCD_AND_ARM_TRACE_REG4_MASK, + .val = 0x0, + }, { + .reg = PAD_FUNCTION_EN_6, + .mask = CLCD_AND_ARM_TRACE_REG5_MASK, + .val = 0x0, + }, { + .reg = PAD_FUNCTION_EN_7, + .mask = CLCD_AND_ARM_TRACE_REG6_MASK, + .val = 0x0, + }, +}; + +static struct spear_modemux clcd_sleep_modemux[] = { + { + .muxregs = clcd_sleep_muxreg, + .nmuxregs = ARRAY_SIZE(clcd_sleep_muxreg), + }, +}; + +static struct spear_pingroup clcd_sleep_pingroup = { + .name = "clcd_sleep_grp", + .pins = clcd_pins, + .npins = ARRAY_SIZE(clcd_pins), + .modemuxs = clcd_sleep_modemux, + .nmodemuxs = ARRAY_SIZE(clcd_sleep_modemux), +}; + +static const char *const clcd_grps[] = { "clcd_grp", "clcd_sleep_grp" }; static struct spear_function clcd_function = { .name = "clcd", .groups = clcd_grps, @@ -1893,6 +1929,7 @@ static struct spear_pingroup *spear1340_pingroups[] = { &sdhci_pingroup, &cf_pingroup, &xd_pingroup, + &clcd_sleep_pingroup, &clcd_pingroup, &arm_trace_pingroup, &miphy_dbg_pingroup, diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c index 020b1e0bdb3..ca47b0e5078 100644 --- a/drivers/pinctrl/spear/pinctrl-spear320.c +++ b/drivers/pinctrl/spear/pinctrl-spear320.c @@ -2240,6 +2240,10 @@ static struct spear_muxreg pwm2_pin_34_muxreg[] = { .mask = PMX_SSP_CS_MASK, .val = 0, }, { + .reg = MODE_CONFIG_REG, + .mask = PMX_PWM_MASK, + .val = PMX_PWM_MASK, + }, { .reg = IP_SEL_PAD_30_39_REG, .mask = PMX_PL_34_MASK, .val = PMX_PWM2_PL_34_VAL, @@ -2956,9 +2960,9 @@ static struct spear_function mii2_function = { }; /* Pad multiplexing for cadence mii 1_2 as smii or rmii device */ -static const unsigned smii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, +static const unsigned rmii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }; -static const unsigned rmii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 }; +static const unsigned smii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 }; static struct spear_muxreg mii0_1_muxreg[] = { { .reg = PMX_CONFIG_REG, diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.h b/drivers/pinctrl/spear/pinctrl-spear3xx.h index 31f44347f17..7860b36053c 100644 --- a/drivers/pinctrl/spear/pinctrl-spear3xx.h +++ b/drivers/pinctrl/spear/pinctrl-spear3xx.h @@ -15,6 +15,7 @@ #include "pinctrl-spear.h" /* pad mux declarations */ +#define PMX_PWM_MASK (1 << 16) #define PMX_FIRDA_MASK (1 << 14) #define PMX_I2C_MASK (1 << 13) #define PMX_SSP_CS_MASK (1 << 12) diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index c17ae22567e..0c6fcb461fa 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -401,7 +401,7 @@ EXPORT_SYMBOL_GPL(rio_release_inb_pwrite); /** * rio_map_inb_region -- Map inbound memory region. * @mport: Master port. - * @lstart: physical address of memory region to be mapped + * @local: physical address of memory region to be mapped * @rbase: RIO base address assigned to this window * @size: Size of the memory region * @rflags: Flags for mapping. diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5c4829cba6a..e872c8be080 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1381,22 +1381,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id) } EXPORT_SYMBOL_GPL(regulator_get_exclusive); -/** - * regulator_put - "free" the regulator source - * @regulator: regulator source - * - * Note: drivers must ensure that all regulator_enable calls made on this - * regulator source are balanced by regulator_disable calls prior to calling - * this function. - */ -void regulator_put(struct regulator *regulator) +/* Locks held by regulator_put() */ +static void _regulator_put(struct regulator *regulator) { struct regulator_dev *rdev; if (regulator == NULL || IS_ERR(regulator)) return; - mutex_lock(®ulator_list_mutex); rdev = regulator->rdev; debugfs_remove_recursive(regulator->debugfs); @@ -1412,6 +1404,20 @@ void regulator_put(struct regulator *regulator) rdev->exclusive = 0; module_put(rdev->owner); +} + +/** + * regulator_put - "free" the regulator source + * @regulator: regulator source + * + * Note: drivers must ensure that all regulator_enable calls made on this + * regulator source are balanced by regulator_disable calls prior to calling + * this function. + */ +void regulator_put(struct regulator *regulator) +{ + mutex_lock(®ulator_list_mutex); + _regulator_put(regulator); mutex_unlock(®ulator_list_mutex); } EXPORT_SYMBOL_GPL(regulator_put); @@ -1974,7 +1980,7 @@ int regulator_is_supported_voltage(struct regulator *regulator, if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { ret = regulator_get_voltage(regulator); if (ret >= 0) - return (min_uV >= ret && ret <= max_uV); + return (min_uV <= ret && ret <= max_uV); else return ret; } @@ -3365,7 +3371,7 @@ regulator_register(const struct regulator_desc *regulator_desc, if (ret != 0) { rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", config->ena_gpio, ret); - goto clean; + goto wash; } rdev->ena_gpio = config->ena_gpio; @@ -3445,10 +3451,11 @@ unset_supplies: scrub: if (rdev->supply) - regulator_put(rdev->supply); + _regulator_put(rdev->supply); if (rdev->ena_gpio) gpio_free(rdev->ena_gpio); kfree(rdev->constraints); +wash: device_unregister(&rdev->dev); /* device core frees rdev */ rdev = ERR_PTR(ret); diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 891cd6c61d0..4eed51044c5 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev) if (imxdi->ioaddr == NULL) return -ENOMEM; + spin_lock_init(&imxdi->irq_lock); + imxdi->irq = platform_get_irq(pdev, 0); if (imxdi->irq < 0) return imxdi->irq; diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 9ffb6d5f17a..4ed343e4eb4 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -44,7 +44,6 @@ #define RAW3215_NR_CCWS 3 #define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ -#define RAW3215_FIXED 1 /* 3215 console device is not be freed */ #define RAW3215_WORKING 4 /* set if a request is being worked on */ #define RAW3215_THROTTLED 8 /* set if reading is disabled */ #define RAW3215_STOPPED 16 /* set if writing is disabled */ @@ -339,8 +338,10 @@ static void raw3215_wakeup(unsigned long data) struct tty_struct *tty; tty = tty_port_tty_get(&raw->port); - tty_wakeup(tty); - tty_kref_put(tty); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); + } } /* @@ -629,8 +630,7 @@ static void raw3215_shutdown(struct raw3215_info *raw) DECLARE_WAITQUEUE(wait, current); unsigned long flags; - if (!(raw->port.flags & ASYNC_INITIALIZED) || - (raw->flags & RAW3215_FIXED)) + if (!(raw->port.flags & ASYNC_INITIALIZED)) return; /* Wait for outstanding requests, then free irq */ spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); @@ -926,8 +926,6 @@ static int __init con3215_init(void) dev_set_drvdata(&cdev->dev, raw); cdev->handler = raw3215_irq; - raw->flags |= RAW3215_FIXED; - /* Request the console irq */ if (raw3215_startup(raw) != 0) { raw3215_free_info(raw); diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index b4d572f65f0..fd00afd8b85 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -377,7 +377,11 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow) /* Will be done on the slow path. */ return -EAGAIN; } - if (stsch_err(schid, &schib) || !css_sch_is_valid(&schib)) { + if (stsch_err(schid, &schib)) { + /* Subchannel is not provided. */ + return -ENXIO; + } + if (!css_sch_is_valid(&schib)) { /* Unusable - ignore. */ return 0; } @@ -536,6 +540,7 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data) case -ENOMEM: case -EIO: /* These should abort looping */ + idset_sch_del_subseq(slow_subchannel_set, schid); break; default: rc = 0; diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 33bb4d891e1..4af3dfe70ef 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -112,9 +112,6 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); extern void css_reiterate_subchannels(void); void css_update_ssd_info(struct subchannel *sch); -#define __MAX_SUBCHANNEL 65535 -#define __MAX_SSID 3 - struct channel_subsystem { u8 cssid; int valid; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index fc916f5d731..fd3143c291c 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1424,7 +1424,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) } if (device_is_disconnected(cdev)) return IO_SCH_REPROBE; - if (cdev->online) + if (cdev->online && !cdev->private->flags.resuming) return IO_SCH_VERIFY; if (cdev->private->state == DEV_STATE_NOT_OPER) return IO_SCH_UNREG_ATTACH; @@ -1469,12 +1469,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) rc = 0; goto out_unlock; case IO_SCH_VERIFY: - if (cdev->private->flags.resuming == 1) { - if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) { - ccw_device_set_notoper(cdev); - break; - } - } /* Trigger path verification. */ io_subchannel_verify(sch); rc = 0; diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c index e6d5f8c4952..65d13e38803 100644 --- a/drivers/s390/cio/idset.c +++ b/drivers/s390/cio/idset.c @@ -1,9 +1,10 @@ /* - * Copyright IBM Corp. 2007 + * Copyright IBM Corp. 2007, 2012 * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> */ #include <linux/vmalloc.h> +#include <linux/bitmap.h> #include <linux/bitops.h> #include "idset.h" #include "css.h" @@ -89,6 +90,14 @@ void idset_sch_del(struct idset *set, struct subchannel_id schid) idset_del(set, schid.ssid, schid.sch_no); } +/* Clear ids starting from @schid up to end of subchannel set. */ +void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid) +{ + int pos = schid.ssid * set->num_id + schid.sch_no; + + bitmap_clear(set->bitmap, pos, set->num_id - schid.sch_no); +} + int idset_sch_contains(struct idset *set, struct subchannel_id schid) { return idset_contains(set, schid.ssid, schid.sch_no); @@ -111,20 +120,12 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid) int idset_is_empty(struct idset *set) { - int bitnum; - - bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id); - if (bitnum >= set->num_ssid * set->num_id) - return 1; - return 0; + return bitmap_empty(set->bitmap, set->num_ssid * set->num_id); } void idset_add_set(struct idset *to, struct idset *from) { - unsigned long i, len; + int len = min(to->num_ssid * to->num_id, from->num_ssid * from->num_id); - len = min(__BITOPS_WORDS(to->num_ssid * to->num_id), - __BITOPS_WORDS(from->num_ssid * from->num_id)); - for (i = 0; i < len ; i++) - to->bitmap[i] |= from->bitmap[i]; + bitmap_or(to->bitmap, to->bitmap, from->bitmap, len); } diff --git a/drivers/s390/cio/idset.h b/drivers/s390/cio/idset.h index 3d943f03591..06d3bc01bb0 100644 --- a/drivers/s390/cio/idset.h +++ b/drivers/s390/cio/idset.h @@ -1,5 +1,5 @@ /* - * Copyright IBM Corp. 2007 + * Copyright IBM Corp. 2007, 2012 * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> */ @@ -17,6 +17,7 @@ void idset_fill(struct idset *set); struct idset *idset_sch_new(void); void idset_sch_add(struct idset *set, struct subchannel_id id); void idset_sch_del(struct idset *set, struct subchannel_id id); +void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid); int idset_sch_contains(struct idset *set, struct subchannel_id id); int idset_sch_get_first(struct idset *set, struct subchannel_id *id); int idset_is_empty(struct idset *set); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3e25d315045..4d6ba00d004 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2942,13 +2942,33 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, QETH_DBF_TEXT(SETUP, 2, "qipasscb"); cmd = (struct qeth_ipa_cmd *) data; + + switch (cmd->hdr.return_code) { + case IPA_RC_NOTSUPP: + case IPA_RC_L2_UNSUPPORTED_CMD: + QETH_DBF_TEXT(SETUP, 2, "ipaunsup"); + card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS; + card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS; + return -0; + default: + if (cmd->hdr.return_code) { + QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled " + "rc=%d\n", + dev_name(&card->gdev->dev), + cmd->hdr.return_code); + return 0; + } + } + if (cmd->hdr.prot_version == QETH_PROT_IPV4) { card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; - } else { + } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) { card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; - } + } else + QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected" + "\n", dev_name(&card->gdev->dev)); QETH_DBF_TEXT(SETUP, 2, "suppenbl"); QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported); QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 2db409330c2..fddb62654b6 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -626,10 +626,13 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) QETH_DBF_TEXT(SETUP, 2, "doL2init"); QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card)); - rc = qeth_query_setadapterparms(card); - if (rc) { - QETH_DBF_MESSAGE(2, "could not query adapter parameters on " - "device %s: x%x\n", CARD_BUS_ID(card), rc); + if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) { + rc = qeth_query_setadapterparms(card); + if (rc) { + QETH_DBF_MESSAGE(2, "could not query adapter " + "parameters on device %s: x%x\n", + CARD_BUS_ID(card), rc); + } } if (card->info.type == QETH_CARD_TYPE_IQD || @@ -676,7 +679,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) return -ERESTARTSYS; } rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]); - if (!rc) + if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND)) rc = qeth_l2_send_setmac(card, addr->sa_data); return rc ? -EINVAL : 0; } @@ -1141,11 +1144,12 @@ static int qeth_l2_recover(void *ptr) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); else { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - dev_warn(&card->gdev->dev, "The qeth device driver " - "failed to recover an error on the device\n"); + if (rtnl_trylock()) { + dev_close(card->dev); + rtnl_unlock(); + dev_warn(&card->gdev->dev, "The qeth device driver " + "failed to recover an error on the device\n"); + } } qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 4cd310cb5bd..5ba39065849 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -3510,11 +3510,12 @@ static int qeth_l3_recover(void *ptr) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); else { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - dev_warn(&card->gdev->dev, "The qeth device driver " - "failed to recover an error on the device\n"); + if (rtnl_trylock()) { + dev_close(card->dev); + rtnl_unlock(); + dev_warn(&card->gdev->dev, "The qeth device driver " + "failed to recover an error on the device\n"); + } } qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 207b7d74244..d8f990b6b33 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -157,7 +157,7 @@ static int smsg_pm_restore_thaw(struct device *dev) #ifdef CONFIG_PM_DEBUG printk(KERN_WARNING "smsg_pm_restore_thaw\n"); #endif - if (smsg_path && iucv_path_connected) { + if (smsg_path && !iucv_path_connected) { memset(smsg_path, 0, sizeof(*smsg_path)); smsg_path->msglim = 255; smsg_path->flags = 0; diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index 6206a666a8e..737554c37d9 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -179,6 +179,7 @@ static void print_SCp(struct scsi_pointer *SCp, const char *prefix, const char * SCp->buffers_residual, suffix); } +#ifdef CHECK_STRUCTURE static void fas216_dumpinfo(FAS216_Info *info) { static int used = 0; @@ -223,7 +224,6 @@ static void fas216_dumpinfo(FAS216_Info *info) info->internal_done, info->magic_end); } -#ifdef CHECK_STRUCTURE static void __fas216_checkmagic(FAS216_Info *info, const char *func) { int corruption = 0; diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index d25f944b59c..fc6a5aabf66 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -21,6 +21,7 @@ /*#define PSEUDO_DMA*/ #define OAKSCSI_PUBLIC_RELEASE 1 +#define DONT_USE_INTR #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) #define NCR5380_local_declare() void __iomem *_base diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index c1bafc3f3fb..9594ab62702 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1972,7 +1972,7 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_index, (void **)&frame_buffer); - sci_controller_copy_sata_response(&ireq->stp.req, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index bd4708a422c..20fd974f903 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) int qla24xx_disable_vp(scsi_qla_host_t *vha) { + unsigned long flags; int ret; ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); @@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha) atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); /* Remove port id from vp target map */ + spin_lock_irqsave(&vha->hw->vport_slock, flags); qlt_update_vp_map(vha, RESET_AL_PA); + spin_unlock_irqrestore(&vha->hw->vport_slock, flags); qla2x00_mark_vp_devices_dead(vha); atomic_set(&vha->vp_state, VP_FAILED); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 0e09d8f433d..62aa5584f64 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha, int pmap_len; fc_port_t *fcport; int global_resets; + unsigned long flags; retry: global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); @@ -625,10 +626,10 @@ retry: sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain, fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + spin_lock_irqsave(&ha->hardware_lock, flags); + ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, + (fcport->flags & FCF_CONF_COMP_SUPPORTED)); + spin_unlock_irqrestore(&ha->hardware_lock, flags); res = true; @@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess( qlt_undelete_sess(sess); kref_get(&sess->se_sess->sess_kref); - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, + (fcport->flags & FCF_CONF_COMP_SUPPORTED)); + if (sess->local && !local) sess->local = 0; spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess( */ kref_get(&sess->se_sess->sess_kref); - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED); BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); @@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007, "Reappeared sess %p\n", sess); } - sess->s_id = fcport->d_id; - sess->loop_id = fcport->loop_id; - sess->conf_compl_supported = !!(fcport->flags & - FCF_CONF_COMP_SUPPORTED); + ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, + (fcport->flags & FCF_CONF_COMP_SUPPORTED)); } if (sess && sess->local) { diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 170af157121..bad749561ec 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl { int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *, void *, uint8_t *, uint16_t); + void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool); struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *, const uint16_t); struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 2358c16c4c8..3d74f2f39ae 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) struct tcm_qla2xxx_tpg, se_tpg); struct tcm_qla2xxx_lport *lport = tpg->lport; - return &lport->lport_name[0]; + return lport->lport_naa_name; } static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) @@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl( return 0; } +static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, + uint16_t loop_id, bool conf_compl_supported) +{ + struct qla_tgt *tgt = sess->tgt; + struct qla_hw_data *ha = tgt->ha; + struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr; + struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; + struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, + struct tcm_qla2xxx_nacl, se_node_acl); + u32 key; + + + if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24) + pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n", + sess, + sess->port_name[0], sess->port_name[1], + sess->port_name[2], sess->port_name[3], + sess->port_name[4], sess->port_name[5], + sess->port_name[6], sess->port_name[7], + sess->loop_id, loop_id, + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, + s_id.b.domain, s_id.b.area, s_id.b.al_pa); + + if (sess->loop_id != loop_id) { + /* + * Because we can shuffle loop IDs around and we + * update different sessions non-atomically, we might + * have overwritten this session's old loop ID + * already, and we might end up overwriting some other + * session that will be updated later. So we have to + * be extra careful and we can't warn about those things... + */ + if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl) + lport->lport_loopid_map[sess->loop_id].se_nacl = NULL; + + lport->lport_loopid_map[loop_id].se_nacl = se_nacl; + + sess->loop_id = loop_id; + } + + if (sess->s_id.b24 != s_id.b24) { + key = (((u32) sess->s_id.b.domain << 16) | + ((u32) sess->s_id.b.area << 8) | + ((u32) sess->s_id.b.al_pa)); + + if (btree_lookup32(&lport->lport_fcport_map, key)) + WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl, + "Found wrong se_nacl when updating s_id %x:%x:%x\n", + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); + else + WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n", + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); + + key = (((u32) s_id.b.domain << 16) | + ((u32) s_id.b.area << 8) | + ((u32) s_id.b.al_pa)); + + if (btree_lookup32(&lport->lport_fcport_map, key)) { + WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n", + s_id.b.domain, s_id.b.area, s_id.b.al_pa); + btree_update32(&lport->lport_fcport_map, key, se_nacl); + } else { + btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC); + } + + sess->s_id = s_id; + nacl->nport_id = key; + } + + sess->conf_compl_supported = conf_compl_supported; +} + /* * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path. */ @@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = { .free_cmd = tcm_qla2xxx_free_cmd, .free_mcmd = tcm_qla2xxx_free_mcmd, .free_session = tcm_qla2xxx_free_session, + .update_sess = tcm_qla2xxx_update_sess, .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl, .find_sess_by_s_id = tcm_qla2xxx_find_sess_by_s_id, .find_sess_by_loop_id = tcm_qla2xxx_find_sess_by_loop_id, @@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport( lport->lport_wwpn = wwpn; tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN, wwpn); + sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn); ret = tcm_qla2xxx_init_lport(lport); if (ret != 0) @@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport( lport->lport_npiv_wwnn = npiv_wwnn; tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0], TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); + sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn); /* FIXME: tcm_qla2xxx_npiv_make_lport */ ret = -ENOSYS; diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h index 82549810335..9ba075fe978 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h @@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport { u64 lport_npiv_wwnn; /* ASCII formatted WWPN for FC Target Lport */ char lport_name[TCM_QLA2XXX_NAMELEN]; + /* ASCII formatted naa WWPN for VPD page 83 etc */ + char lport_naa_name[TCM_QLA2XXX_NAMELEN]; /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */ char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN]; /* map for fc_port pointers in 24-bit FC Port ID space */ diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index b191dd54920..71fddbc60f1 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -1294,26 +1294,19 @@ static struct scsi_host_template qpti_template = { static const struct of_device_id qpti_match[]; static int __devinit qpti_sbus_probe(struct platform_device *op) { - const struct of_device_id *match; - struct scsi_host_template *tpnt; struct device_node *dp = op->dev.of_node; struct Scsi_Host *host; struct qlogicpti *qpti; static int nqptis; const char *fcode; - match = of_match_device(qpti_match, &op->dev); - if (!match) - return -EINVAL; - tpnt = match->data; - /* Sometimes Antares cards come up not completely * setup, and we get a report of a zero IRQ. */ if (op->archdata.irqs[0] == 0) return -ENODEV; - host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); + host = scsi_host_alloc(&qpti_template, sizeof(struct qlogicpti)); if (!host) return -ENOMEM; @@ -1445,19 +1438,15 @@ static int __devexit qpti_sbus_remove(struct platform_device *op) static const struct of_device_id qpti_match[] = { { .name = "ptisp", - .data = &qpti_template, }, { .name = "PTI,ptisp", - .data = &qpti_template, }, { .name = "QLGC,isp", - .data = &qpti_template, }, { .name = "SUNW,isp", - .data = &qpti_template, }, {}, }; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 2936b447cae..2c0d0ec8150 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -55,6 +55,7 @@ #include <linux/cpu.h> #include <linux/mutex.h> #include <linux/async.h> +#include <asm/unaligned.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -1062,6 +1063,50 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, EXPORT_SYMBOL_GPL(scsi_get_vpd_page); /** + * scsi_report_opcode - Find out if a given command opcode is supported + * @sdev: scsi device to query + * @buffer: scratch buffer (must be at least 20 bytes long) + * @len: length of buffer + * @opcode: opcode for command to look up + * + * Uses the REPORT SUPPORTED OPERATION CODES to look up the given + * opcode. Returns 0 if RSOC fails or if the command opcode is + * unsupported. Returns 1 if the device claims to support the command. + */ +int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, + unsigned int len, unsigned char opcode) +{ + unsigned char cmd[16]; + struct scsi_sense_hdr sshdr; + int result; + + if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3) + return 0; + + memset(cmd, 0, 16); + cmd[0] = MAINTENANCE_IN; + cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES; + cmd[2] = 1; /* One command format */ + cmd[3] = opcode; + put_unaligned_be32(len, &cmd[6]); + memset(buffer, 0, len); + + result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, + &sshdr, 30 * HZ, 3, NULL); + + if (result && scsi_sense_valid(&sshdr) && + sshdr.sense_key == ILLEGAL_REQUEST && + (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00) + return 0; + + if ((buffer[1] & 3) == 3) /* Command supported */ + return 1; + + return 0; +} +EXPORT_SYMBOL(scsi_report_opcode); + +/** * scsi_device_get - get an additional reference to a scsi_device * @sdev: device to get a reference to * diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index da36a3a81a9..9032e910bca 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -900,11 +900,23 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) action = ACTION_FAIL; error = -EILSEQ; /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */ - } else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) && - (cmd->cmnd[0] == UNMAP || - cmd->cmnd[0] == WRITE_SAME_16 || - cmd->cmnd[0] == WRITE_SAME)) { - description = "Discard failure"; + } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) { + switch (cmd->cmnd[0]) { + case UNMAP: + description = "Discard failure"; + break; + case WRITE_SAME: + case WRITE_SAME_16: + if (cmd->cmnd[1] & 0x8) + description = "Discard failure"; + else + description = + "Write same failure"; + break; + default: + description = "Invalid command failure"; + break; + } action = ACTION_FAIL; error = -EREMOTEIO; } else diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 12f6fdfc114..352bc77b7c8 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); #endif static void sd_config_discard(struct scsi_disk *, unsigned int); +static void sd_config_write_same(struct scsi_disk *); static int sd_revalidate_disk(struct gendisk *); static void sd_unlock_native_capacity(struct gendisk *disk); static int sd_probe(struct device *); @@ -395,6 +396,45 @@ sd_store_max_medium_access_timeouts(struct device *dev, return err ? err : count; } +static ssize_t +sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + + return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks); +} + +static ssize_t +sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + struct scsi_device *sdp = sdkp->device; + unsigned long max; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (sdp->type != TYPE_DISK) + return -EINVAL; + + err = kstrtoul(buf, 10, &max); + + if (err) + return err; + + if (max == 0) + sdp->no_write_same = 1; + else if (max <= SD_MAX_WS16_BLOCKS) + sdkp->max_ws_blocks = max; + + sd_config_write_same(sdkp); + + return count; +} + static struct device_attribute sd_disk_attrs[] = { __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, sd_store_cache_type), @@ -410,6 +450,8 @@ static struct device_attribute sd_disk_attrs[] = { __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL), __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode, sd_store_provisioning_mode), + __ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR, + sd_show_write_same_blocks, sd_store_write_same_blocks), __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR, sd_show_max_medium_access_timeouts, sd_store_max_medium_access_timeouts), @@ -561,19 +603,23 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) return; case SD_LBP_UNMAP: - max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff); + max_blocks = min_not_zero(sdkp->max_unmap_blocks, + (u32)SD_MAX_WS16_BLOCKS); break; case SD_LBP_WS16: - max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff); + max_blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS16_BLOCKS); break; case SD_LBP_WS10: - max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff); + max_blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS10_BLOCKS); break; case SD_LBP_ZERO: - max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff); + max_blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS10_BLOCKS); q->limits.discard_zeroes_data = 1; break; } @@ -583,29 +629,26 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) } /** - * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device + * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device * @sdp: scsi device to operate one * @rq: Request to prepare * * Will issue either UNMAP or WRITE SAME(16) depending on preference * indicated by target device. **/ -static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) +static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) { struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); - struct bio *bio = rq->bio; - sector_t sector = bio->bi_sector; - unsigned int nr_sectors = bio_sectors(bio); + sector_t sector = blk_rq_pos(rq); + unsigned int nr_sectors = blk_rq_sectors(rq); + unsigned int nr_bytes = blk_rq_bytes(rq); unsigned int len; int ret; char *buf; struct page *page; - if (sdkp->device->sector_size == 4096) { - sector >>= 3; - nr_sectors >>= 3; - } - + sector >>= ilog2(sdp->sector_size) - 9; + nr_sectors >>= ilog2(sdp->sector_size) - 9; rq->timeout = SD_TIMEOUT; memset(rq->cmd, 0, rq->cmd_len); @@ -660,6 +703,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) blk_add_request_payload(rq, page, len); ret = scsi_setup_blk_pc_cmnd(sdp, rq); rq->buffer = page_address(page); + rq->__data_len = nr_bytes; out: if (ret != BLKPREP_OK) { @@ -669,6 +713,83 @@ out: return ret; } +static void sd_config_write_same(struct scsi_disk *sdkp) +{ + struct request_queue *q = sdkp->disk->queue; + unsigned int logical_block_size = sdkp->device->sector_size; + unsigned int blocks = 0; + + if (sdkp->device->no_write_same) { + sdkp->max_ws_blocks = 0; + goto out; + } + + /* Some devices can not handle block counts above 0xffff despite + * supporting WRITE SAME(16). Consequently we default to 64k + * blocks per I/O unless the device explicitly advertises a + * bigger limit. + */ + if (sdkp->max_ws_blocks == 0) + sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS; + + if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS) + blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS16_BLOCKS); + else + blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS10_BLOCKS); + +out: + blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9)); +} + +/** + * sd_setup_write_same_cmnd - write the same data to multiple blocks + * @sdp: scsi device to operate one + * @rq: Request to prepare + * + * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on + * preference indicated by target device. + **/ +static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) +{ + struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); + struct bio *bio = rq->bio; + sector_t sector = blk_rq_pos(rq); + unsigned int nr_sectors = blk_rq_sectors(rq); + unsigned int nr_bytes = blk_rq_bytes(rq); + int ret; + + if (sdkp->device->no_write_same) + return BLKPREP_KILL; + + BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size); + + sector >>= ilog2(sdp->sector_size) - 9; + nr_sectors >>= ilog2(sdp->sector_size) - 9; + + rq->__data_len = sdp->sector_size; + rq->timeout = SD_WRITE_SAME_TIMEOUT; + memset(rq->cmd, 0, rq->cmd_len); + + if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) { + rq->cmd_len = 16; + rq->cmd[0] = WRITE_SAME_16; + put_unaligned_be64(sector, &rq->cmd[2]); + put_unaligned_be32(nr_sectors, &rq->cmd[10]); + } else { + rq->cmd_len = 10; + rq->cmd[0] = WRITE_SAME; + put_unaligned_be32(sector, &rq->cmd[2]); + put_unaligned_be16(nr_sectors, &rq->cmd[7]); + } + + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + rq->__data_len = nr_bytes; + + return ret; +} + static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) { rq->timeout = SD_FLUSH_TIMEOUT; @@ -712,7 +833,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * block PC requests to make life easier. */ if (rq->cmd_flags & REQ_DISCARD) { - ret = scsi_setup_discard_cmnd(sdp, rq); + ret = sd_setup_discard_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_flags & REQ_WRITE_SAME) { + ret = sd_setup_write_same_cmnd(sdp, rq); goto out; } else if (rq->cmd_flags & REQ_FLUSH) { ret = scsi_setup_flush_cmnd(sdp, rq); @@ -1482,12 +1606,21 @@ static int sd_done(struct scsi_cmnd *SCpnt) unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt); struct scsi_sense_hdr sshdr; struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk); + struct request *req = SCpnt->request; int sense_valid = 0; int sense_deferred = 0; unsigned char op = SCpnt->cmnd[0]; + unsigned char unmap = SCpnt->cmnd[1] & 8; - if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result) - scsi_set_resid(SCpnt, 0); + if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) { + if (!result) { + good_bytes = blk_rq_bytes(req); + scsi_set_resid(SCpnt, 0); + } else { + good_bytes = 0; + scsi_set_resid(SCpnt, blk_rq_bytes(req)); + } + } if (result) { sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); @@ -1536,9 +1669,25 @@ static int sd_done(struct scsi_cmnd *SCpnt) if (sshdr.asc == 0x10) /* DIX: Host detected corruption */ good_bytes = sd_completed_bytes(SCpnt); /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */ - if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) && - (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME)) - sd_config_discard(sdkp, SD_LBP_DISABLE); + if (sshdr.asc == 0x20 || sshdr.asc == 0x24) { + switch (op) { + case UNMAP: + sd_config_discard(sdkp, SD_LBP_DISABLE); + break; + case WRITE_SAME_16: + case WRITE_SAME: + if (unmap) + sd_config_discard(sdkp, SD_LBP_DISABLE); + else { + sdkp->device->no_write_same = 1; + sd_config_write_same(sdkp); + + good_bytes = 0; + req->__data_len = blk_rq_bytes(req); + req->cmd_flags |= REQ_QUIET; + } + } + } break; default: break; @@ -2374,9 +2523,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) if (buffer[3] == 0x3c) { unsigned int lba_count, desc_count; - sdkp->max_ws_blocks = - (u32) min_not_zero(get_unaligned_be64(&buffer[36]), - (u64)0xffffffff); + sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]); if (!sdkp->lbpme) goto out; @@ -2469,6 +2616,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp) kfree(buffer); } +static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) +{ + if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE, + WRITE_SAME_16)) + sdkp->ws16 = 1; +} + static int sd_try_extended_inquiry(struct scsi_device *sdp) { /* @@ -2528,6 +2682,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_write_protect_flag(sdkp, buffer); sd_read_cache_type(sdkp, buffer); sd_read_app_tag_own(sdkp, buffer); + sd_read_write_same(sdkp, buffer); } sdkp->first_scan = 0; @@ -2545,6 +2700,7 @@ static int sd_revalidate_disk(struct gendisk *disk) blk_queue_flush(sdkp->disk->queue, flush); set_capacity(disk, sdkp->capacity); + sd_config_write_same(sdkp); kfree(buffer); out: diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 47c52a6d733..74a1e4ca540 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -14,6 +14,7 @@ #define SD_TIMEOUT (30 * HZ) #define SD_MOD_TIMEOUT (75 * HZ) #define SD_FLUSH_TIMEOUT (60 * HZ) +#define SD_WRITE_SAME_TIMEOUT (120 * HZ) /* * Number of allowed retries @@ -39,6 +40,11 @@ enum { }; enum { + SD_MAX_WS10_BLOCKS = 0xffff, + SD_MAX_WS16_BLOCKS = 0x7fffff, +}; + +enum { SD_LBP_FULL = 0, /* Full logical block provisioning */ SD_LBP_UNMAP, /* Use UNMAP command */ SD_LBP_WS16, /* Use WRITE SAME(16) with UNMAP bit */ @@ -77,6 +83,7 @@ struct scsi_disk { unsigned lbpws : 1; unsigned lbpws10 : 1; unsigned lbpvpd : 1; + unsigned ws16 : 1; }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev) diff --git a/drivers/sh/intc/access.c b/drivers/sh/intc/access.c index f892ae1d212..114390f967d 100644 --- a/drivers/sh/intc/access.c +++ b/drivers/sh/intc/access.c @@ -75,54 +75,61 @@ unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle static unsigned long test_8(unsigned long addr, unsigned long h, unsigned long ignore) { - return intc_get_field_from_handle(__raw_readb(addr), h); + void __iomem *ptr = (void __iomem *)addr; + return intc_get_field_from_handle(__raw_readb(ptr), h); } static unsigned long test_16(unsigned long addr, unsigned long h, unsigned long ignore) { - return intc_get_field_from_handle(__raw_readw(addr), h); + void __iomem *ptr = (void __iomem *)addr; + return intc_get_field_from_handle(__raw_readw(ptr), h); } static unsigned long test_32(unsigned long addr, unsigned long h, unsigned long ignore) { - return intc_get_field_from_handle(__raw_readl(addr), h); + void __iomem *ptr = (void __iomem *)addr; + return intc_get_field_from_handle(__raw_readl(ptr), h); } static unsigned long write_8(unsigned long addr, unsigned long h, unsigned long data) { - __raw_writeb(intc_set_field_from_handle(0, data, h), addr); - (void)__raw_readb(addr); /* Defeat write posting */ + void __iomem *ptr = (void __iomem *)addr; + __raw_writeb(intc_set_field_from_handle(0, data, h), ptr); + (void)__raw_readb(ptr); /* Defeat write posting */ return 0; } static unsigned long write_16(unsigned long addr, unsigned long h, unsigned long data) { - __raw_writew(intc_set_field_from_handle(0, data, h), addr); - (void)__raw_readw(addr); /* Defeat write posting */ + void __iomem *ptr = (void __iomem *)addr; + __raw_writew(intc_set_field_from_handle(0, data, h), ptr); + (void)__raw_readw(ptr); /* Defeat write posting */ return 0; } static unsigned long write_32(unsigned long addr, unsigned long h, unsigned long data) { - __raw_writel(intc_set_field_from_handle(0, data, h), addr); - (void)__raw_readl(addr); /* Defeat write posting */ + void __iomem *ptr = (void __iomem *)addr; + __raw_writel(intc_set_field_from_handle(0, data, h), ptr); + (void)__raw_readl(ptr); /* Defeat write posting */ return 0; } static unsigned long modify_8(unsigned long addr, unsigned long h, unsigned long data) { + void __iomem *ptr = (void __iomem *)addr; unsigned long flags; unsigned int value; local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readb(addr), data, h); - __raw_writeb(value, addr); - (void)__raw_readb(addr); /* Defeat write posting */ + value = intc_set_field_from_handle(__raw_readb(ptr), data, h); + __raw_writeb(value, ptr); + (void)__raw_readb(ptr); /* Defeat write posting */ local_irq_restore(flags); return 0; } @@ -130,12 +137,13 @@ static unsigned long modify_8(unsigned long addr, unsigned long h, static unsigned long modify_16(unsigned long addr, unsigned long h, unsigned long data) { + void __iomem *ptr = (void __iomem *)addr; unsigned long flags; unsigned int value; local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readw(addr), data, h); - __raw_writew(value, addr); - (void)__raw_readw(addr); /* Defeat write posting */ + value = intc_set_field_from_handle(__raw_readw(ptr), data, h); + __raw_writew(value, ptr); + (void)__raw_readw(ptr); /* Defeat write posting */ local_irq_restore(flags); return 0; } @@ -143,12 +151,13 @@ static unsigned long modify_16(unsigned long addr, unsigned long h, static unsigned long modify_32(unsigned long addr, unsigned long h, unsigned long data) { + void __iomem *ptr = (void __iomem *)addr; unsigned long flags; unsigned int value; local_irq_save(flags); - value = intc_set_field_from_handle(__raw_readl(addr), data, h); - __raw_writel(value, addr); - (void)__raw_readl(addr); /* Defeat write posting */ + value = intc_set_field_from_handle(__raw_readl(ptr), data, h); + __raw_writel(value, ptr); + (void)__raw_readl(ptr); /* Defeat write posting */ local_irq_restore(flags); return 0; } diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c index 012df2676a2..46427b48e2f 100644 --- a/drivers/sh/intc/chip.c +++ b/drivers/sh/intc/chip.c @@ -83,7 +83,7 @@ static void intc_mask_ack(struct irq_data *data) unsigned int irq = data->irq; struct intc_desc_int *d = get_intc_desc(irq); unsigned long handle = intc_get_ack_handle(irq); - unsigned long addr; + void __iomem *addr; intc_disable(data); @@ -91,7 +91,7 @@ static void intc_mask_ack(struct irq_data *data) if (handle) { unsigned int value; - addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); + addr = (void __iomem *)INTC_REG(d, _INTC_ADDR_D(handle), 0); value = intc_set_field_from_handle(0, 1, handle); switch (_INTC_FN(handle)) { diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index edf1360ab09..86dd04d6bc8 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -323,6 +323,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs, if (!ret) { dev_err(ssp->dev, "DMA transfer timeout\n"); ret = -ETIMEDOUT; + dmaengine_terminate_all(ssp->dmach); goto err_vmalloc; } @@ -480,7 +481,7 @@ static int mxs_spi_transfer_one(struct spi_master *master, first = last = 0; } - m->status = 0; + m->status = status; spi_finalize_current_message(master); return status; diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 919464102d3..a1db91a99b8 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2186,8 +2186,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_resume(dev); - pl022->clk = devm_clk_get(&adev->dev, NULL); if (IS_ERR(pl022->clk)) { status = PTR_ERR(pl022->clk); @@ -2292,7 +2290,6 @@ pl022_remove(struct amba_device *adev) clk_disable(pl022->clk); clk_unprepare(pl022->clk); - pm_runtime_disable(&adev->dev); amba_release_regions(adev); tasklet_disable(&pl022->pump_transfers); spi_unregister_master(pl022->master); diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 4894bde4bbf..30faf6d4ab9 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -147,8 +147,6 @@ struct rspi_data { unsigned char spsr; /* for dmaengine */ - struct sh_dmae_slave dma_tx; - struct sh_dmae_slave dma_rx; struct dma_chan *chan_tx; struct dma_chan *chan_rx; int irq; @@ -663,20 +661,16 @@ static irqreturn_t rspi_irq(int irq, void *_sr) return ret; } -static bool rspi_filter(struct dma_chan *chan, void *filter_param) -{ - chan->private = filter_param; - return true; -} - -static void __devinit rspi_request_dma(struct rspi_data *rspi, - struct platform_device *pdev) +static int __devinit rspi_request_dma(struct rspi_data *rspi, + struct platform_device *pdev) { struct rspi_plat_data *rspi_pd = pdev->dev.platform_data; dma_cap_mask_t mask; + struct dma_slave_config cfg; + int ret; if (!rspi_pd) - return; + return 0; /* The driver assumes no error. */ rspi->dma_width_16bit = rspi_pd->dma_width_16bit; @@ -684,21 +678,35 @@ static void __devinit rspi_request_dma(struct rspi_data *rspi, if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) { dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - rspi->dma_rx.slave_id = rspi_pd->dma_rx_id; - rspi->chan_rx = dma_request_channel(mask, rspi_filter, - &rspi->dma_rx); - if (rspi->chan_rx) - dev_info(&pdev->dev, "Use DMA when rx.\n"); + rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter, + (void *)rspi_pd->dma_rx_id); + if (rspi->chan_rx) { + cfg.slave_id = rspi_pd->dma_rx_id; + cfg.direction = DMA_DEV_TO_MEM; + ret = dmaengine_slave_config(rspi->chan_rx, &cfg); + if (!ret) + dev_info(&pdev->dev, "Use DMA when rx.\n"); + else + return ret; + } } if (rspi_pd->dma_tx_id) { dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - rspi->dma_tx.slave_id = rspi_pd->dma_tx_id; - rspi->chan_tx = dma_request_channel(mask, rspi_filter, - &rspi->dma_tx); - if (rspi->chan_tx) - dev_info(&pdev->dev, "Use DMA when tx\n"); + rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter, + (void *)rspi_pd->dma_tx_id); + if (rspi->chan_tx) { + cfg.slave_id = rspi_pd->dma_tx_id; + cfg.direction = DMA_MEM_TO_DEV; + ret = dmaengine_slave_config(rspi->chan_tx, &cfg); + if (!ret) + dev_info(&pdev->dev, "Use DMA when tx\n"); + else + return ret; + } } + + return 0; } static void __devexit rspi_release_dma(struct rspi_data *rspi) @@ -788,7 +796,11 @@ static int __devinit rspi_probe(struct platform_device *pdev) } rspi->irq = irq; - rspi_request_dma(rspi, pdev); + ret = rspi_request_dma(rspi, pdev); + if (ret < 0) { + dev_err(&pdev->dev, "rspi_request_dma failed.\n"); + goto error4; + } ret = spi_register_master(master); if (ret < 0) { diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 1a81c90a4a7..6e7a805d324 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -132,7 +132,7 @@ struct s3c64xx_spi_dma_data { unsigned ch; - enum dma_data_direction direction; + enum dma_transfer_direction direction; enum dma_ch dmach; struct property *dma_prop; }; @@ -1067,11 +1067,11 @@ static int __devinit s3c64xx_spi_get_dmares( if (tx) { dma_data = &sdd->tx_dma; - dma_data->direction = DMA_TO_DEVICE; + dma_data->direction = DMA_MEM_TO_DEV; chan_str = "tx"; } else { dma_data = &sdd->rx_dma; - dma_data->direction = DMA_FROM_DEVICE; + dma_data->direction = DMA_DEV_TO_MEM; chan_str = "rx"; } diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index f2ffd963f1c..d0cafd63719 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -51,12 +51,10 @@ enum android_alarm_return_flags { #define ANDROID_ALARM_WAIT _IO('a', 1) #define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) -#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size) - /* Set alarm */ #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 7b0ba92e7e4..5d4610babd8 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -567,7 +567,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; BUG_ON(*page); - *page = alloc_page(GFP_KERNEL | __GFP_ZERO); + *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (*page == NULL) { pr_err("binder: %d: binder_alloc_buf failed " "for page at %p\n", proc->pid, page_addr); @@ -2419,14 +2419,38 @@ static void binder_release_work(struct list_head *list) struct binder_transaction *t; t = container_of(w, struct binder_transaction, work); - if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) + if (t->buffer->target_node && + !(t->flags & TF_ONE_WAY)) { binder_send_failed_reply(t, BR_DEAD_REPLY); + } else { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered transaction %d\n", + t->debug_id); + t->buffer->transaction = NULL; + kfree(t); + binder_stats_deleted(BINDER_STAT_TRANSACTION); + } } break; case BINDER_WORK_TRANSACTION_COMPLETE: { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered TRANSACTION_COMPLETE\n"); kfree(w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; + case BINDER_WORK_DEAD_BINDER_AND_CLEAR: + case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { + struct binder_ref_death *death; + + death = container_of(w, struct binder_ref_death, work); + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered death notification, %p\n", + death->cookie); + kfree(death); + binder_stats_deleted(BINDER_STAT_DEATH); + } break; default: + pr_err("binder: unexpected work type, %d, not freed\n", + w->type); break; } } @@ -2899,6 +2923,7 @@ static void binder_deferred_release(struct binder_proc *proc) nodes++; rb_erase(&node->rb_node, &proc->nodes); list_del_init(&node->work.entry); + binder_release_work(&node->async_todo); if (hlist_empty(&node->refs)) { kfree(node); binder_stats_deleted(BINDER_STAT_NODE); @@ -2937,6 +2962,7 @@ static void binder_deferred_release(struct binder_proc *proc) binder_delete_ref(ref); } binder_release_work(&proc->todo); + binder_release_work(&proc->delivered_death); buffers = 0; while ((n = rb_first(&proc->allocated_buffers))) { diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 7dff3c01dc2..d00aff6671d 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -289,6 +289,8 @@ static void pci_8255_detach(struct comedi_device *dev) struct comedi_subdevice *s; int i; + if (!board || !devpriv) + return; if (dev->subdevices) { for (i = 0; i < board->n_8255; i++) { s = &dev->subdevices[i]; diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index 08f305210a6..29eb52d11d2 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -1410,6 +1410,8 @@ static void dio200_detach(struct comedi_device *dev) const struct dio200_layout_struct *layout; unsigned n; + if (!thisboard) + return; if (dev->irq) free_irq(dev->irq, dev); if (dev->subdevices) { diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index eacb5e4735d..4e4f3c15df8 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -573,9 +573,10 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev, static void pc236_detach(struct comedi_device *dev) { const struct pc236_board *thisboard = comedi_board(dev); - struct pc236_private *devpriv = dev->private; - if (devpriv) + if (!thisboard) + return; + if (dev->iobase) pc236_intr_disable(dev); if (dev->irq) free_irq(dev->irq, dev); diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 60830ccfb90..d0a4c441228 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -323,6 +323,8 @@ static void pc263_detach(struct comedi_device *dev) { const struct pc263_board *thisboard = comedi_board(dev); + if (!thisboard) + return; if (is_isa_board(thisboard)) { if (dev->iobase) release_region(dev->iobase, PC263_IO_SIZE); diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 5fd21fa6c1c..c304528cfb1 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -846,6 +846,8 @@ static void __maybe_unused das08_detach(struct comedi_device *dev) { const struct das08_board_struct *thisboard = comedi_board(dev); + if (!thisboard) + return; das08_common_detach(dev); if (is_isa_board(thisboard)) { if (dev->iobase) diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 2ba0ade45c6..68d7c6a5db7 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -95,7 +95,7 @@ static int daq700_dio_insn_bits(struct comedi_device *dev, } data[1] = s->state & 0xff; - data[1] |= inb(dev->iobase + DIO_R); + data[1] |= inb(dev->iobase + DIO_R) << 8; return insn->n; } diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 28b91a6c378..b5a19a0863f 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -772,6 +772,8 @@ void labpc_common_detach(struct comedi_device *dev) { struct comedi_subdevice *s; + if (!thisboard) + return; if (dev->subdevices) { s = &dev->subdevices[2]; subdev_8255_cleanup(dev, s); diff --git a/drivers/staging/dgrp/dgrp_mon_ops.c b/drivers/staging/dgrp/dgrp_mon_ops.c index 268dcb95204..4792d056a36 100644 --- a/drivers/staging/dgrp/dgrp_mon_ops.c +++ b/drivers/staging/dgrp/dgrp_mon_ops.c @@ -38,6 +38,7 @@ #include <linux/sched.h> #include <asm/unaligned.h> #include <linux/proc_fs.h> +#include <linux/uaccess.h> #include "dgrp_common.h" diff --git a/drivers/staging/dgrp/dgrp_specproc.c b/drivers/staging/dgrp/dgrp_specproc.c index 28f5c9ab6b4..24327c3bad8 100644 --- a/drivers/staging/dgrp/dgrp_specproc.c +++ b/drivers/staging/dgrp/dgrp_specproc.c @@ -39,6 +39,7 @@ #include <linux/proc_fs.h> #include <linux/ctype.h> #include <linux/seq_file.h> +#include <linux/uaccess.h> #include <linux/vmalloc.h> #include "dgrp_common.h" @@ -228,6 +229,9 @@ static void register_proc_table(struct dgrp_proc_entry *table, int len; mode_t mode; + if (table == NULL) + return; + for (; table->id; table++) { /* Can't do anything without a proc name. */ if (!table->name) @@ -296,6 +300,9 @@ static void unregister_proc_table(struct dgrp_proc_entry *table, struct proc_dir_entry *de; struct nd_struct *tmp; + if (table == NULL) + return; + list_for_each_entry(tmp, &nd_struct_list, list) { if ((table == dgrp_net_table) && (tmp->nd_net_de)) { unregister_dgrp_device(tmp->nd_net_de); diff --git a/drivers/staging/dgrp/dgrp_tty.c b/drivers/staging/dgrp/dgrp_tty.c index 7d7de873870..e125b03598d 100644 --- a/drivers/staging/dgrp/dgrp_tty.c +++ b/drivers/staging/dgrp/dgrp_tty.c @@ -40,6 +40,7 @@ #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/sched.h> +#include <linux/uaccess.h> #include "dgrp_common.h" @@ -3172,6 +3173,9 @@ dgrp_tty_init(struct nd_struct *nd) */ nd->nd_serial_ttdriver = alloc_tty_driver(CHAN_MAX); + if (!nd->nd_serial_ttdriver) + return -ENOMEM; + sprintf(nd->nd_serial_name, "tty_dgrp_%s_", id); nd->nd_serial_ttdriver->owner = THIS_MODULE; @@ -3231,6 +3235,9 @@ dgrp_tty_init(struct nd_struct *nd) } nd->nd_callout_ttdriver = alloc_tty_driver(CHAN_MAX); + if (!nd->nd_callout_ttdriver) + return -ENOMEM; + sprintf(nd->nd_callout_name, "cu_dgrp_%s_", id); nd->nd_callout_ttdriver->owner = THIS_MODULE; @@ -3268,6 +3275,9 @@ dgrp_tty_init(struct nd_struct *nd) nd->nd_xprint_ttdriver = alloc_tty_driver(CHAN_MAX); + if (!nd->nd_xprint_ttdriver) + return -ENOMEM; + sprintf(nd->nd_xprint_name, "pr_dgrp_%s_", id); nd->nd_xprint_ttdriver->owner = THIS_MODULE; diff --git a/drivers/staging/gdm72xx/gdm_usb.c b/drivers/staging/gdm72xx/gdm_usb.c index 0c9e8958009..39db582ab1a 100644 --- a/drivers/staging/gdm72xx/gdm_usb.c +++ b/drivers/staging/gdm72xx/gdm_usb.c @@ -701,8 +701,6 @@ static int k_mode_thread(void *arg) unsigned long flags, flags2, expire; int ret; - daemonize("k_mode_wimax"); - while (!k_mode_stop) { spin_lock_irqsave(&k_lock, flags2); @@ -764,7 +762,7 @@ static struct usb_driver gdm_usb_driver = { static int __init usb_gdm_wimax_init(void) { #ifdef CONFIG_WIMAX_GDM72XX_K_MODE - kthread_run(k_mode_thread, NULL, "WiMax_thread"); + kthread_run(k_mode_thread, NULL, "k_mode_wimax"); #endif /* CONFIG_WIMAX_GDM72XX_K_MODE */ return usb_register(&gdm_usb_driver); } diff --git a/drivers/staging/iio/accel/adis16201_core.c b/drivers/staging/iio/accel/adis16201_core.c index 8e37d6e0427..b12ca68cd9e 100644 --- a/drivers/staging/iio/accel/adis16201_core.c +++ b/drivers/staging/iio/accel/adis16201_core.c @@ -310,30 +310,32 @@ static int adis16201_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 1220; - else - *val2 = 610; + if (chan->channel == 0) { + *val = 1; + *val2 = 220000; /* 1.22 mV */ + } else { + *val = 0; + *val2 = 610000; /* 0.610 mV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* 0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - *val2 = 462500; - return IIO_VAL_INT_PLUS_MICRO; + *val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */ + return IIO_VAL_INT_PLUS_NANO; case IIO_INCLI: *val = 0; - *val2 = 100000; + *val2 = 100000; /* 0.1 degree */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { diff --git a/drivers/staging/iio/accel/adis16203_core.c b/drivers/staging/iio/accel/adis16203_core.c index 002fa9dfc37..e7b3441115a 100644 --- a/drivers/staging/iio/accel/adis16203_core.c +++ b/drivers/staging/iio/accel/adis16203_core.c @@ -316,25 +316,27 @@ static int adis16203_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 1220; - else - *val2 = 610; + if (chan->channel == 0) { + *val = 1; + *val2 = 220000; /* 1.22 mV */ + } else { + *val = 0; + *val2 = 610000; /* 0.61 mV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* -0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_INCLI: *val = 0; - *val2 = 25000; + *val2 = 25000; /* 0.025 degree */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: bits = 14; diff --git a/drivers/staging/iio/accel/adis16204_core.c b/drivers/staging/iio/accel/adis16204_core.c index 05bdb7c2c8e..c6234c2f46a 100644 --- a/drivers/staging/iio/accel/adis16204_core.c +++ b/drivers/staging/iio/accel/adis16204_core.c @@ -317,26 +317,28 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 1220; - else - *val2 = 610; + if (chan->channel == 0) { + *val = 1; + *val2 = 220000; /* 1.22 mV */ + } else { + *val = 0; + *val2 = 610000; /* 0.61 mV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* 0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; switch (chan->channel2) { case IIO_MOD_X: case IIO_MOD_ROOT_SUM_SQUARED_X_Y: - *val2 = 17125; + *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */ break; case IIO_MOD_Y: case IIO_MOD_Z: - *val2 = 8407; + *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */ break; } return IIO_VAL_INT_PLUS_MICRO; @@ -345,7 +347,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev, } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: case IIO_CHAN_INFO_PEAK: diff --git a/drivers/staging/iio/accel/adis16209_core.c b/drivers/staging/iio/accel/adis16209_core.c index b7333bfe0b2..7ee974b45d7 100644 --- a/drivers/staging/iio/accel/adis16209_core.c +++ b/drivers/staging/iio/accel/adis16209_core.c @@ -343,28 +343,29 @@ static int adis16209_read_raw(struct iio_dev *indio_dev, case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) - *val2 = 305180; + *val2 = 305180; /* 0.30518 mV */ else - *val2 = 610500; + *val2 = 610500; /* 0.6105 mV */ return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = -470000; + *val = -470; /* -0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - *val2 = 2394; - return IIO_VAL_INT_PLUS_MICRO; + *val2 = IIO_G_TO_M_S_2(244140); /* 0.244140 mg */ + return IIO_VAL_INT_PLUS_NANO; case IIO_INCLI: + case IIO_ROT: *val = 0; - *val2 = 436; + *val2 = 25000; /* 0.025 degree */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / -470 - 0x4FE; /* 25 C = 0x4FE */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { @@ -491,6 +492,7 @@ static const struct iio_chan_spec adis16209_channels[] = { .modified = 1, .channel2 = IIO_MOD_X, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, + IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = rot, .scan_index = ADIS16209_SCAN_ROT, .scan_type = { diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index c755089c711..eaadd9df3f7 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -486,7 +486,7 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, break; case IIO_CHAN_INFO_OFFSET: if (chan->type == IIO_TEMP) { - *val = 25; + *val = 25000 / -470 - 1278; /* 25 C = 1278 */ return IIO_VAL_INT; } addrind = 1; @@ -495,19 +495,22 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, addrind = 2; break; case IIO_CHAN_INFO_SCALE: - *val = 0; switch (chan->type) { case IIO_TEMP: - *val2 = -470000; + *val = -470; /* -0.47 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: - *val2 = 1887042; + *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */ return IIO_VAL_INT_PLUS_MICRO; case IIO_VOLTAGE: - if (chan->channel == 0) - *val2 = 0012221; - else /* Should really be dependent on VDD */ - *val2 = 305; + if (chan->channel == 0) { + *val = 1; + *val2 = 220700; /* 1.2207 mV */ + } else { + /* Should really be dependent on VDD */ + *val2 = 305180; /* 305.18 uV */ + } return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; diff --git a/drivers/staging/iio/accel/adis16240_core.c b/drivers/staging/iio/accel/adis16240_core.c index 0fc26a49d68..35e093973d5 100644 --- a/drivers/staging/iio/accel/adis16240_core.c +++ b/drivers/staging/iio/accel/adis16240_core.c @@ -373,30 +373,31 @@ static int adis16240_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 4880; - else + if (chan->channel == 0) { + *val = 4; + *val2 = 880000; /* 4.88 mV */ + return IIO_VAL_INT_PLUS_MICRO; + } else { return -EINVAL; - return IIO_VAL_INT_PLUS_MICRO; + } case IIO_TEMP: - *val = 0; - *val2 = 244000; + *val = 244; /* 0.244 C */ + *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; - *val2 = 504062; + *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_PEAK_SCALE: - *val = 6; - *val2 = 629295; + *val = 0; + *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */ return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 25000 / 244 - 0x133; /* 25 C = 0x133 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: bits = 10; diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c index 9571c03aa4c..aa964a2d829 100644 --- a/drivers/staging/iio/gyro/adis16260_core.c +++ b/drivers/staging/iio/gyro/adis16260_core.c @@ -498,28 +498,33 @@ static int adis16260_read_raw(struct iio_dev *indio_dev, switch (chan->type) { case IIO_ANGL_VEL: *val = 0; - if (spi_get_device_id(st->us)->driver_data) - *val2 = 320; - else - *val2 = 1278; + if (spi_get_device_id(st->us)->driver_data) { + /* 0.01832 degree / sec */ + *val2 = IIO_DEGREE_TO_RAD(18320); + } else { + /* 0.07326 degree / sec */ + *val2 = IIO_DEGREE_TO_RAD(73260); + } return IIO_VAL_INT_PLUS_MICRO; case IIO_VOLTAGE: - *val = 0; - if (chan->channel == 0) - *val2 = 18315; - else - *val2 = 610500; + if (chan->channel == 0) { + *val = 1; + *val2 = 831500; /* 1.8315 mV */ + } else { + *val = 0; + *val2 = 610500; /* 610.5 uV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = 145300; + *val = 145; + *val2 = 300000; /* 0.1453 C */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: - *val = 25; + *val = 250000 / 1453; /* 25 C = 0x00 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h index d59d7ac856a..77c601da184 100644 --- a/drivers/staging/iio/imu/adis16400.h +++ b/drivers/staging/iio/imu/adis16400.h @@ -139,6 +139,8 @@ struct adis16400_chip_info { const long flags; unsigned int gyro_scale_micro; unsigned int accel_scale_micro; + int temp_scale_nano; + int temp_offset; unsigned long default_scan_mask; }; diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c index b302c9ba271..3144a7b1e1c 100644 --- a/drivers/staging/iio/imu/adis16400_core.c +++ b/drivers/staging/iio/imu/adis16400_core.c @@ -553,10 +553,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; case IIO_VOLTAGE: *val = 0; - if (chan->channel == 0) - *val2 = 2418; - else - *val2 = 806; + if (chan->channel == 0) { + *val = 2; + *val2 = 418000; /* 2.418 mV */ + } else { + *val = 0; + *val2 = 805800; /* 805.8 uV */ + } return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; @@ -564,11 +567,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT_PLUS_MICRO; case IIO_MAGN: *val = 0; - *val2 = 500; + *val2 = 500; /* 0.5 mgauss */ return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: - *val = 0; - *val2 = 140000; + *val = st->variant->temp_scale_nano / 1000000; + *val2 = (st->variant->temp_scale_nano % 1000000); return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; @@ -586,9 +589,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: /* currently only temperature */ - *val = 198; - *val2 = 160000; - return IIO_VAL_INT_PLUS_MICRO; + *val = st->variant->temp_offset; + return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: mutex_lock(&indio_dev->mlock); /* Need both the number of taps and the sampling frequency */ @@ -1035,7 +1037,7 @@ static const struct iio_chan_spec adis16334_channels[] = { .indexed = 1, .channel = 0, .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | - IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | + IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | IIO_CHAN_INFO_SCALE_SHARED_BIT, .address = temp0, .scan_index = ADIS16400_SCAN_TEMP, @@ -1058,8 +1060,10 @@ static struct adis16400_chip_info adis16400_chips[] = { [ADIS16300] = { .channels = adis16300_channels, .num_channels = ARRAY_SIZE(adis16300_channels), - .gyro_scale_micro = 873, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ .accel_scale_micro = 5884, + .temp_scale_nano = 140000000, /* 0.14 C */ + .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) | (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) | @@ -1070,8 +1074,10 @@ static struct adis16400_chip_info adis16400_chips[] = { [ADIS16334] = { .channels = adis16334_channels, .num_channels = ARRAY_SIZE(adis16334_channels), - .gyro_scale_micro = 873, - .accel_scale_micro = 981, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ + .temp_scale_nano = 67850000, /* 0.06785 C */ + .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */ .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) | (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | @@ -1080,8 +1086,10 @@ static struct adis16400_chip_info adis16400_chips[] = { [ADIS16350] = { .channels = adis16350_channels, .num_channels = ARRAY_SIZE(adis16350_channels), - .gyro_scale_micro = 872664, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */ + .temp_scale_nano = 145300000, /* 0.1453 C */ + .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, .flags = ADIS16400_NO_BURST, }, @@ -1090,8 +1098,10 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16350_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x3FE8, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, }, [ADIS16362] = { @@ -1099,8 +1109,10 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16350_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x3FEA, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, }, [ADIS16364] = { @@ -1108,8 +1120,10 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16350_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x3FEC, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, }, [ADIS16365] = { @@ -1117,8 +1131,10 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16350_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x3FED, - .gyro_scale_micro = 1279, - .accel_scale_micro = 24732, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .default_scan_mask = 0x7FF, }, [ADIS16400] = { @@ -1126,9 +1142,11 @@ static struct adis16400_chip_info adis16400_chips[] = { .num_channels = ARRAY_SIZE(adis16400_channels), .flags = ADIS16400_HAS_PROD_ID, .product_id = 0x4015, - .gyro_scale_micro = 873, - .accel_scale_micro = 32656, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ .default_scan_mask = 0xFFF, + .temp_scale_nano = 140000000, /* 0.14 C */ + .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ } }; diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index bb8aa70281c..46d6657280b 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -12,6 +12,7 @@ */ #include <linux/module.h> +#include <linux/slab.h> #include "tpci200.h" static u16 tpci200_status_timeout[] = { diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c index 3434e6ec014..66e2c2f8a23 100644 --- a/drivers/staging/omapdrm/omap_gem.c +++ b/drivers/staging/omapdrm/omap_gem.c @@ -246,7 +246,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) * DSS, GPU, etc. are not cache coherent: */ if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { - addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL); + addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL); if (!addrs) { ret = -ENOMEM; goto free_pages; @@ -257,7 +257,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) 0, PAGE_SIZE, DMA_BIDIRECTIONAL); } } else { - addrs = kzalloc(npages * sizeof(addrs), GFP_KERNEL); + addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL); if (!addrs) { ret = -ENOMEM; goto free_pages; diff --git a/drivers/staging/ramster/Kconfig b/drivers/staging/ramster/Kconfig index 843c5410143..3abf6619dac 100644 --- a/drivers/staging/ramster/Kconfig +++ b/drivers/staging/ramster/Kconfig @@ -18,6 +18,7 @@ config ZCACHE2 config RAMSTER bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem" depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE2=y + depends on NET # must ensure struct page is 8-byte aligned select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT default n diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index 066a3ceec65..f619fb3c56d 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -126,7 +126,8 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context, u32 ul_num_bytes, struct hw_mmu_map_attrs_t *hw_attrs); -bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr); +bool wait_for_start(struct bridge_dev_context *dev_context, + void __iomem *sync_addr); /* ----------------------------------- Globals */ @@ -363,10 +364,11 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, { int status = 0; struct bridge_dev_context *dev_context = dev_ctxt; - u32 dw_sync_addr = 0; + void __iomem *sync_addr; u32 ul_shm_base; /* Gpp Phys SM base addr(byte) */ u32 ul_shm_base_virt; /* Dsp Virt SM base addr */ u32 ul_tlb_base_virt; /* Base of MMU TLB entry */ + u32 shm_sync_pa; /* Offset of shm_base_virt from tlb_base_virt */ u32 ul_shm_offset_virt; s32 entry_ndx; @@ -397,15 +399,22 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, /* Kernel logical address */ ul_shm_base = dev_context->atlb_entry[0].gpp_va + ul_shm_offset_virt; + /* SHM physical sync address */ + shm_sync_pa = dev_context->atlb_entry[0].gpp_pa + ul_shm_offset_virt + + SHMSYNCOFFSET; + /* 2nd wd is used as sync field */ - dw_sync_addr = ul_shm_base + SHMSYNCOFFSET; + sync_addr = ioremap(shm_sync_pa, SZ_32); + if (!sync_addr) + return -ENOMEM; + /* Write a signature into the shm base + offset; this will * get cleared when the DSP program starts. */ if ((ul_shm_base_virt == 0) || (ul_shm_base == 0)) { pr_err("%s: Illegal SM base\n", __func__); status = -EPERM; } else - __raw_writel(0xffffffff, dw_sync_addr); + __raw_writel(0xffffffff, sync_addr); if (!status) { resources = dev_context->resources; @@ -419,8 +428,10 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, * function is made available. */ void __iomem *ctrl = ioremap(0x48002000, SZ_4K); - if (!ctrl) + if (!ctrl) { + iounmap(sync_addr); return -ENOMEM; + } (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD, @@ -588,15 +599,15 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL); - dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", dw_sync_addr); + dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", *(u32 *)sync_addr); dev_dbg(bridge, "DSP c_int00 Address = 0x%x\n", dsp_addr); if (dsp_debug) - while (__raw_readw(dw_sync_addr)) + while (__raw_readw(sync_addr)) ; /* Wait for DSP to clear word in shared memory */ /* Read the Location */ - if (!wait_for_start(dev_context, dw_sync_addr)) + if (!wait_for_start(dev_context, sync_addr)) status = -ETIMEDOUT; dev_get_symbol(dev_context->dev_obj, "_WDT_enable", &wdt_en); @@ -612,7 +623,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, /* Write the synchronization bit to indicate the * completion of OPP table update to DSP */ - __raw_writel(0XCAFECAFE, dw_sync_addr); + __raw_writel(0XCAFECAFE, sync_addr); /* update board state */ dev_context->brd_state = BRD_RUNNING; @@ -621,6 +632,9 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, dev_context->brd_state = BRD_UNKNOWN; } } + + iounmap(sync_addr); + return status; } @@ -1796,12 +1810,13 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context, * ======== wait_for_start ======== * Wait for the singal from DSP that it has started, or time out. */ -bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr) +bool wait_for_start(struct bridge_dev_context *dev_context, + void __iomem *sync_addr) { u16 timeout = TIHELEN_ACKTIMEOUT; /* Wait for response from board */ - while (__raw_readw(dw_sync_addr) && --timeout) + while (__raw_readw(sync_addr) && --timeout) udelay(10); /* If timed out: return false */ diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.c b/drivers/staging/tidspbridge/hw/hw_mmu.c index 71cb8229364..50244a47417 100644 --- a/drivers/staging/tidspbridge/hw/hw_mmu.c +++ b/drivers/staging/tidspbridge/hw/hw_mmu.c @@ -48,37 +48,12 @@ enum hw_mmu_page_size_t { }; /* - * FUNCTION : mmu_flush_entry - * - * INPUTS: - * - * Identifier : base_address - * Type : const u32 - * Description : Base Address of instance of MMU module - * - * RETURNS: - * - * Type : hw_status - * Description : 0 -- No errors occurred - * RET_BAD_NULL_PARAM -- A Pointer - * Parameter was set to NULL - * - * PURPOSE: : Flush the TLB entry pointed by the - * lock counter register - * even if this entry is set protected - * - * METHOD: : Check the Input parameter and Flush a - * single entry in the TLB. - */ -static hw_status mmu_flush_entry(const void __iomem *base_address); - -/* * FUNCTION : mmu_set_cam_entry * * INPUTS: * * Identifier : base_address - * TypE : const u32 + * Type : void __iomem * * Description : Base Address of instance of MMU module * * Identifier : page_sz @@ -112,7 +87,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address); * * METHOD: : Check the Input parameters and set the CAM entry. */ -static hw_status mmu_set_cam_entry(const void __iomem *base_address, +static hw_status mmu_set_cam_entry(void __iomem *base_address, const u32 page_sz, const u32 preserved_bit, const u32 valid_bit, @@ -124,7 +99,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address, * INPUTS: * * Identifier : base_address - * Type : const u32 + * Type : void __iomem * * Description : Base Address of instance of MMU module * * Identifier : physical_addr @@ -157,7 +132,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address, * * METHOD: : Check the Input parameters and set the RAM entry. */ -static hw_status mmu_set_ram_entry(const void __iomem *base_address, +static hw_status mmu_set_ram_entry(void __iomem *base_address, const u32 physical_addr, enum hw_endianism_t endianism, enum hw_element_size_t element_size, @@ -165,7 +140,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address, /* HW FUNCTIONS */ -hw_status hw_mmu_enable(const void __iomem *base_address) +hw_status hw_mmu_enable(void __iomem *base_address) { hw_status status = 0; @@ -174,7 +149,7 @@ hw_status hw_mmu_enable(const void __iomem *base_address) return status; } -hw_status hw_mmu_disable(const void __iomem *base_address) +hw_status hw_mmu_disable(void __iomem *base_address) { hw_status status = 0; @@ -183,7 +158,7 @@ hw_status hw_mmu_disable(const void __iomem *base_address) return status; } -hw_status hw_mmu_num_locked_set(const void __iomem *base_address, +hw_status hw_mmu_num_locked_set(void __iomem *base_address, u32 num_locked_entries) { hw_status status = 0; @@ -193,7 +168,7 @@ hw_status hw_mmu_num_locked_set(const void __iomem *base_address, return status; } -hw_status hw_mmu_victim_num_set(const void __iomem *base_address, +hw_status hw_mmu_victim_num_set(void __iomem *base_address, u32 victim_entry_num) { hw_status status = 0; @@ -203,7 +178,7 @@ hw_status hw_mmu_victim_num_set(const void __iomem *base_address, return status; } -hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask) +hw_status hw_mmu_event_ack(void __iomem *base_address, u32 irq_mask) { hw_status status = 0; @@ -212,7 +187,7 @@ hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask) return status; } -hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask) +hw_status hw_mmu_event_disable(void __iomem *base_address, u32 irq_mask) { hw_status status = 0; u32 irq_reg; @@ -224,7 +199,7 @@ hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask) return status; } -hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask) +hw_status hw_mmu_event_enable(void __iomem *base_address, u32 irq_mask) { hw_status status = 0; u32 irq_reg; @@ -236,7 +211,7 @@ hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask) return status; } -hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask) +hw_status hw_mmu_event_status(void __iomem *base_address, u32 *irq_mask) { hw_status status = 0; @@ -245,7 +220,7 @@ hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask) return status; } -hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr) +hw_status hw_mmu_fault_addr_read(void __iomem *base_address, u32 *addr) { hw_status status = 0; @@ -255,7 +230,7 @@ hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr) return status; } -hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr) +hw_status hw_mmu_ttb_set(void __iomem *base_address, u32 ttb_phys_addr) { hw_status status = 0; u32 load_ttb; @@ -267,7 +242,7 @@ hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr) return status; } -hw_status hw_mmu_twl_enable(const void __iomem *base_address) +hw_status hw_mmu_twl_enable(void __iomem *base_address) { hw_status status = 0; @@ -276,7 +251,7 @@ hw_status hw_mmu_twl_enable(const void __iomem *base_address) return status; } -hw_status hw_mmu_twl_disable(const void __iomem *base_address) +hw_status hw_mmu_twl_disable(void __iomem *base_address) { hw_status status = 0; @@ -285,45 +260,7 @@ hw_status hw_mmu_twl_disable(const void __iomem *base_address) return status; } -hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr, - u32 page_sz) -{ - hw_status status = 0; - u32 virtual_addr_tag; - enum hw_mmu_page_size_t pg_size_bits; - - switch (page_sz) { - case HW_PAGE_SIZE4KB: - pg_size_bits = HW_MMU_SMALL_PAGE; - break; - - case HW_PAGE_SIZE64KB: - pg_size_bits = HW_MMU_LARGE_PAGE; - break; - - case HW_PAGE_SIZE1MB: - pg_size_bits = HW_MMU_SECTION; - break; - - case HW_PAGE_SIZE16MB: - pg_size_bits = HW_MMU_SUPERSECTION; - break; - - default: - return -EINVAL; - } - - /* Generate the 20-bit tag from virtual address */ - virtual_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12); - - mmu_set_cam_entry(base_address, pg_size_bits, 0, 0, virtual_addr_tag); - - mmu_flush_entry(base_address); - - return status; -} - -hw_status hw_mmu_tlb_add(const void __iomem *base_address, +hw_status hw_mmu_tlb_add(void __iomem *base_address, u32 physical_addr, u32 virtual_addr, u32 page_sz, @@ -503,20 +440,8 @@ hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size) return status; } -/* mmu_flush_entry */ -static hw_status mmu_flush_entry(const void __iomem *base_address) -{ - hw_status status = 0; - u32 flush_entry_data = 0x1; - - /* write values to register */ - MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, flush_entry_data); - - return status; -} - /* mmu_set_cam_entry */ -static hw_status mmu_set_cam_entry(const void __iomem *base_address, +static hw_status mmu_set_cam_entry(void __iomem *base_address, const u32 page_sz, const u32 preserved_bit, const u32 valid_bit, @@ -536,7 +461,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address, } /* mmu_set_ram_entry */ -static hw_status mmu_set_ram_entry(const void __iomem *base_address, +static hw_status mmu_set_ram_entry(void __iomem *base_address, const u32 physical_addr, enum hw_endianism_t endianism, enum hw_element_size_t element_size, @@ -556,7 +481,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address, } -void hw_mmu_tlb_flush_all(const void __iomem *base) +void hw_mmu_tlb_flush_all(void __iomem *base) { __raw_writel(1, base + MMU_GFLUSH); } diff --git a/drivers/staging/tidspbridge/hw/hw_mmu.h b/drivers/staging/tidspbridge/hw/hw_mmu.h index 1458a2c6027..1c50bb36edf 100644 --- a/drivers/staging/tidspbridge/hw/hw_mmu.h +++ b/drivers/staging/tidspbridge/hw/hw_mmu.h @@ -42,44 +42,41 @@ struct hw_mmu_map_attrs_t { bool donotlockmpupage; }; -extern hw_status hw_mmu_enable(const void __iomem *base_address); +extern hw_status hw_mmu_enable(void __iomem *base_address); -extern hw_status hw_mmu_disable(const void __iomem *base_address); +extern hw_status hw_mmu_disable(void __iomem *base_address); -extern hw_status hw_mmu_num_locked_set(const void __iomem *base_address, +extern hw_status hw_mmu_num_locked_set(void __iomem *base_address, u32 num_locked_entries); -extern hw_status hw_mmu_victim_num_set(const void __iomem *base_address, +extern hw_status hw_mmu_victim_num_set(void __iomem *base_address, u32 victim_entry_num); /* For MMU faults */ -extern hw_status hw_mmu_event_ack(const void __iomem *base_address, +extern hw_status hw_mmu_event_ack(void __iomem *base_address, u32 irq_mask); -extern hw_status hw_mmu_event_disable(const void __iomem *base_address, +extern hw_status hw_mmu_event_disable(void __iomem *base_address, u32 irq_mask); -extern hw_status hw_mmu_event_enable(const void __iomem *base_address, +extern hw_status hw_mmu_event_enable(void __iomem *base_address, u32 irq_mask); -extern hw_status hw_mmu_event_status(const void __iomem *base_address, +extern hw_status hw_mmu_event_status(void __iomem *base_address, u32 *irq_mask); -extern hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, +extern hw_status hw_mmu_fault_addr_read(void __iomem *base_address, u32 *addr); /* Set the TT base address */ -extern hw_status hw_mmu_ttb_set(const void __iomem *base_address, +extern hw_status hw_mmu_ttb_set(void __iomem *base_address, u32 ttb_phys_addr); -extern hw_status hw_mmu_twl_enable(const void __iomem *base_address); +extern hw_status hw_mmu_twl_enable(void __iomem *base_address); -extern hw_status hw_mmu_twl_disable(const void __iomem *base_address); +extern hw_status hw_mmu_twl_disable(void __iomem *base_address); -extern hw_status hw_mmu_tlb_flush(const void __iomem *base_address, - u32 virtual_addr, u32 page_sz); - -extern hw_status hw_mmu_tlb_add(const void __iomem *base_address, +extern hw_status hw_mmu_tlb_add(void __iomem *base_address, u32 physical_addr, u32 virtual_addr, u32 page_sz, @@ -97,7 +94,7 @@ extern hw_status hw_mmu_pte_set(const u32 pg_tbl_va, extern hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size); -void hw_mmu_tlb_flush_all(const void __iomem *base); +void hw_mmu_tlb_flush_all(void __iomem *base); static inline u32 hw_mmu_pte_addr_l1(u32 l1_base, u32 va) { diff --git a/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h b/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h index 60a278136bd..b32c75673ab 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h +++ b/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h @@ -53,8 +53,8 @@ struct cfg_hostres { u32 chnl_buf_size; u32 num_chnls; void __iomem *per_base; - u32 per_pm_base; - u32 core_pm_base; + void __iomem *per_pm_base; + void __iomem *core_pm_base; void __iomem *dmmu_base; }; diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h index ed00d3da320..5e2f4d82d92 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h +++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h @@ -47,8 +47,8 @@ #include <asm/cacheflush.h> #include <linux/dma-mapping.h> -/* TODO -- Remove, once BP defines them */ -#define INT_DSP_MMU_IRQ 28 +/* TODO -- Remove, once omap-iommu is used */ +#define INT_DSP_MMU_IRQ (28 + NR_IRQS) #define PRCM_VDD1 1 diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c index 6795205b015..db1da28cecb 100644 --- a/drivers/staging/tidspbridge/rmgr/drv.c +++ b/drivers/staging/tidspbridge/rmgr/drv.c @@ -667,10 +667,10 @@ int drv_request_bridge_res_dsp(void **phost_resources) OMAP_DSP_MEM3_SIZE); host_res->per_base = ioremap(OMAP_PER_CM_BASE, OMAP_PER_CM_SIZE); - host_res->per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE, - OMAP_PER_PRM_SIZE); - host_res->core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE, - OMAP_CORE_PRM_SIZE); + host_res->per_pm_base = ioremap(OMAP_PER_PRM_BASE, + OMAP_PER_PRM_SIZE); + host_res->core_pm_base = ioremap(OMAP_CORE_PRM_BASE, + OMAP_CORE_PRM_SIZE); host_res->dmmu_base = ioremap(OMAP_DMMU_BASE, OMAP_DMMU_SIZE); diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c index c2fc6137c77..294e9b40f51 100644 --- a/drivers/staging/tidspbridge/rmgr/node.c +++ b/drivers/staging/tidspbridge/rmgr/node.c @@ -304,8 +304,7 @@ int node_allocate(struct proc_object *hprocessor, u32 pul_value; u32 dynext_base; u32 off_set = 0; - u32 ul_stack_seg_addr, ul_stack_seg_val; - u32 ul_gpp_mem_base; + u32 ul_stack_seg_val; struct cfg_hostres *host_res; struct bridge_dev_context *pbridge_context; u32 mapped_addr = 0; @@ -581,6 +580,9 @@ func_cont: if (strcmp((char *) pnode->dcd_props.obj_data.node_obj.ndb_props. stack_seg_name, STACKSEGLABEL) == 0) { + void __iomem *stack_seg; + u32 stack_seg_pa; + status = hnode_mgr->nldr_fxns. get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG", @@ -608,14 +610,21 @@ func_cont: goto func_end; } - ul_gpp_mem_base = (u32) host_res->mem_base[1]; off_set = pul_value - dynext_base; - ul_stack_seg_addr = ul_gpp_mem_base + off_set; - ul_stack_seg_val = readl(ul_stack_seg_addr); + stack_seg_pa = host_res->mem_phys[1] + off_set; + stack_seg = ioremap(stack_seg_pa, SZ_32); + if (!stack_seg) { + status = -ENOMEM; + goto func_end; + } + + ul_stack_seg_val = readl(stack_seg); + + iounmap(stack_seg); dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr =" " 0x%x\n", __func__, ul_stack_seg_val, - ul_stack_seg_addr); + host_res->mem_base[1] + off_set); pnode->create_args.asa.task_arg_obj.stack_seg = ul_stack_seg_val; diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 653b074035f..6edefde2372 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -223,8 +223,13 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, cmem = zs_map_object(zram->mem_pool, zram->table[index].handle, ZS_MM_RO); - ret = lzo1x_decompress_safe(cmem, zram->table[index].size, + if (zram->table[index].size == PAGE_SIZE) { + memcpy(uncmem, cmem, PAGE_SIZE); + ret = LZO_E_OK; + } else { + ret = lzo1x_decompress_safe(cmem, zram->table[index].size, uncmem, &clen); + } if (is_partial_io(bvec)) { memcpy(user_mem + bvec->bv_offset, uncmem + offset, @@ -342,8 +347,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, goto out; } - if (unlikely(clen > max_zpage_size)) + if (unlikely(clen > max_zpage_size)) { zram_stat_inc(&zram->stats.bad_compress); + src = uncmem; + clen = PAGE_SIZE; + } handle = zs_malloc(zram->mem_pool, clen); if (!handle) { diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index d6ce2182e67..035c2c76253 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3719,7 +3719,9 @@ restart: */ iscsit_thread_check_cpumask(conn, current, 1); - schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT); + wait_event_interruptible(conn->queues_wq, + !iscsit_conn_all_queues_empty(conn) || + ts->status == ISCSI_THREAD_SET_RESET); if ((ts->status == ISCSI_THREAD_SET_RESET) || signal_pending(current)) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 2ba9f9b9435..21048dbf7d1 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -486,6 +486,7 @@ struct iscsi_tmr_req { }; struct iscsi_conn { + wait_queue_head_t queues_wq; /* Authentication Successful for this connection */ u8 auth_complete; /* State connection is currently in */ diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index cdc8a10939c..f8dbec05d5e 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -41,6 +41,7 @@ static int iscsi_login_init_conn(struct iscsi_conn *conn) { + init_waitqueue_head(&conn->queues_wq); INIT_LIST_HEAD(&conn->conn_list); INIT_LIST_HEAD(&conn->conn_cmd_list); INIT_LIST_HEAD(&conn->immed_queue_list); diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index afd98ccd40a..1a91195ab61 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue( atomic_set(&conn->check_immediate_queue, 1); spin_unlock_bh(&conn->immed_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn) @@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue( atomic_inc(&cmd->response_queue_count); spin_unlock_bh(&conn->response_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn) @@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue( } } +bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn) +{ + bool empty; + + spin_lock_bh(&conn->immed_queue_lock); + empty = list_empty(&conn->immed_queue_list); + spin_unlock_bh(&conn->immed_queue_lock); + + if (!empty) + return empty; + + spin_lock_bh(&conn->response_queue_lock); + empty = list_empty(&conn->response_queue_list); + spin_unlock_bh(&conn->response_queue_lock); + + return empty; +} + void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn) { struct iscsi_queue_req *qr, *qr_tmp; diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 44054bd3543..894d0f83792 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_ extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8); extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *); extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *); +extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); extern void iscsit_release_cmd(struct iscsi_cmd *); extern void iscsit_free_cmd(struct iscsi_cmd *); diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 015f5be27bf..c123327499a 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; - if (core_dev_setup_virtual_lun0() < 0) + ret = core_dev_setup_virtual_lun0(); + if (ret < 0) goto out; return 0; diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 8d774da1632..9abef9f8eb7 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev) static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) { - u32 tmp, aligned_max_sectors; + u32 aligned_max_sectors; + u32 alignment; /* * Limit max_sectors to a PAGE_SIZE aligned value for modern * transport_allocate_data_tasks() operation. */ - tmp = rounddown((max_sectors * block_size), PAGE_SIZE); - aligned_max_sectors = (tmp / block_size); - if (max_sectors != aligned_max_sectors) { - printk(KERN_INFO "Rounding down aligned max_sectors from %u" - " to %u\n", max_sectors, aligned_max_sectors); - return aligned_max_sectors; - } + alignment = max(1ul, PAGE_SIZE / block_size); + aligned_max_sectors = rounddown(max_sectors, alignment); + + if (max_sectors != aligned_max_sectors) + pr_info("Rounding down aligned max_sectors from %u to %u\n", + max_sectors, aligned_max_sectors); - return max_sectors; + return aligned_max_sectors; } void se_dev_set_default_attribs( diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 868f8aa04f1..a6e27d967c7 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd) return 0; } +static int sbc_emulate_noop(struct se_cmd *cmd) +{ + target_complete_cmd(cmd, GOOD); + return 0; +} + static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors) { return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; @@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops) size = 0; cmd->execute_cmd = sbc_emulate_verify; break; + case REZERO_UNIT: + case SEEK_6: + case SEEK_10: + /* + * There are still clients out there which use these old SCSI-2 + * commands. This mainly happens when running VMs with legacy + * guest systems, connected via SCSI command pass-through to + * iSCSI targets. Make them happy and return status GOOD. + */ + size = 0; + cmd->execute_cmd = sbc_emulate_noop; + break; default: ret = spc_parse_cdb(cmd, &size); if (ret) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 9229bd9ad61..6fd434d3d7e 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd) unsigned char buf[SE_INQUIRY_BUF]; int p, ret; + memset(buf, 0, SE_INQUIRY_BUF); + if (dev == tpg->tpg_virt_lun0.lun_se_dev) buf[0] = 0x3f; /* Not connected */ else diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 1c59a3c23b2..be75c4331a9 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -140,15 +140,15 @@ void core_tmr_abort_task( printk("ABORT_TASK: Found referenced %s task_tag: %u\n", se_cmd->se_tfo->get_fabric_name(), ref_tag); - spin_lock_irq(&se_cmd->t_state_lock); + spin_lock(&se_cmd->t_state_lock); if (se_cmd->transport_state & CMD_T_COMPLETE) { printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); goto out; } se_cmd->transport_state |= CMD_T_ABORTED; - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); list_del_init(&se_cmd->se_cmd_list); kref_get(&se_cmd->cmd_kref); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c33baff86aa..9097155e9eb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work) se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; se_cmd->se_tfo->queue_tm_rsp(se_cmd); - transport_generic_free_cmd(se_cmd, 0); } /** diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index edfd67d2501..e1cb6bd75f6 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -22,6 +22,7 @@ config THERMAL_HWMON config CPU_THERMAL bool "generic cpu cooling support" depends on THERMAL && CPU_FREQ + select CPU_FREQ_TABLE help This implements the generic cpu cooling mechanism through frequency reduction, cpu hotplug and any other ways of reducing temperature. An @@ -50,6 +51,7 @@ config RCAR_THERMAL config EXYNOS_THERMAL tristate "Temperature sensor on Samsung EXYNOS" depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && THERMAL + select CPU_FREQ_TABLE help If you say yes here you get support for TMU (Thermal Managment Unit) on SAMSUNG EXYNOS series of SoC. diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c index fd03e8581af..6dd29e4ce36 100644 --- a/drivers/thermal/exynos_thermal.c +++ b/drivers/thermal/exynos_thermal.c @@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = { }, { }, }; -MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids); +MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids); static inline struct exynos_tmu_platform_data *exynos_get_driver_data( struct platform_device *pdev) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index d4452716aaa..f7a1b574a30 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) goto error_free_priv; } - zone = thermal_zone_device_register("rcar_thermal", 0, priv, + zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv, &rcar_thermal_zone_ops, 0, 0); if (IS_ERR(zone)) { dev_err(&pdev->dev, "thermal zone device is NULL\n"); diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index a5dec1ca1b8..13ee53bd0bf 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -424,7 +424,6 @@ static void hvc_hangup(struct tty_struct *tty) { struct hvc_struct *hp = tty->driver_data; unsigned long flags; - int temp_open_count; if (!hp) return; @@ -444,7 +443,6 @@ static void hvc_hangup(struct tty_struct *tty) return; } - temp_open_count = hp->port.count; hp->port.count = 0; spin_unlock_irqrestore(&hp->port.lock, flags); tty_port_tty_set(&hp->port, NULL); @@ -453,11 +451,6 @@ static void hvc_hangup(struct tty_struct *tty) if (hp->ops->notifier_hangup) hp->ops->notifier_hangup(hp, hp->data); - - while(temp_open_count) { - --temp_open_count; - tty_port_put(&hp->port); - } } /* diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index 8f1dd2cc00a..f3d0edf4664 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -162,7 +162,7 @@ int __init hp300_setup_serial_console(void) static int __devinit hpdca_init_one(struct dio_dev *d, const struct dio_device_id *ent) { - struct uart_port port; + struct uart_8250_port uart; int line; #ifdef CONFIG_SERIAL_8250_CONSOLE @@ -174,19 +174,19 @@ static int __devinit hpdca_init_one(struct dio_dev *d, memset(&uart, 0, sizeof(uart)); /* Memory mapped I/O */ - port.iotype = UPIO_MEM; - port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF; - port.irq = d->ipl; - port.uartclk = HPDCA_BAUD_BASE * 16; - port.mapbase = (d->resource.start + UART_OFFSET); - port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE); - port.regshift = 1; - port.dev = &d->dev; + uart.port.iotype = UPIO_MEM; + uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF; + uart.port.irq = d->ipl; + uart.port.uartclk = HPDCA_BAUD_BASE * 16; + uart.port.mapbase = (d->resource.start + UART_OFFSET); + uart.port.membase = (char *)(uart.port.mapbase + DIO_VIRADDRBASE); + uart.port.regshift = 1; + uart.port.dev = &d->dev; line = serial8250_register_8250_port(&uart); if (line < 0) { printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d" - " irq %d failed\n", d->scode, port.irq); + " irq %d failed\n", d->scode, uart.port.irq); return -ENOMEM; } diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 233fbaaf255..2a53be5f010 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1150,7 +1150,7 @@ config SERIAL_SC26XX_CONSOLE Support for Console on SC2681/SC2692 serial ports. config SERIAL_SCCNXP - bool "SCCNXP serial port support" + tristate "SCCNXP serial port support" depends on !SERIAL_SC26XX select SERIAL_CORE default n @@ -1162,7 +1162,7 @@ config SERIAL_SCCNXP config SERIAL_SCCNXP_CONSOLE bool "Console on SCCNXP serial port" - depends on SERIAL_SCCNXP + depends on SERIAL_SCCNXP=y select SERIAL_CORE_CONSOLE help Support for console on SCCNXP serial ports. diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 2bc28a59d38..1ab1d2c66de 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1239,6 +1239,7 @@ static int __devexit max310x_remove(struct spi_device *spi) static const struct spi_device_id max310x_id_table[] = { { "max3107", MAX310X_TYPE_MAX3107 }, { "max3108", MAX310X_TYPE_MAX3108 }, + { } }; MODULE_DEVICE_TABLE(spi, max310x_id_table); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6ede6fd92b4..6d3d26a607b 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -671,19 +671,19 @@ serial_omap_configure_xonxoff /* * IXON Flag: - * Flow control for OMAP.TX - * OMAP.RX should listen for XON/XOFF + * Enable XON/XOFF flow control on output. + * Transmit XON1, XOFF1 */ if (termios->c_iflag & IXON) - up->efr |= OMAP_UART_SW_RX; + up->efr |= OMAP_UART_SW_TX; /* * IXOFF Flag: - * Flow control for OMAP.RX - * OMAP.TX should send XON/XOFF + * Enable XON/XOFF flow control on input. + * Receiver compares XON1, XOFF1. */ if (termios->c_iflag & IXOFF) - up->efr |= OMAP_UART_SW_TX; + up->efr |= OMAP_UART_SW_RX; serial_out(up, UART_EFR, up->efr | UART_EFR_ECB); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A); diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index b7086d004f5..e821068cd95 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -971,6 +971,7 @@ static const struct platform_device_id sccnxp_id_table[] = { { "sc28202", SCCNXP_TYPE_SC28202 }, { "sc68681", SCCNXP_TYPE_SC68681 }, { "sc68692", SCCNXP_TYPE_SC68692 }, + { }, }; MODULE_DEVICE_TABLE(platform, sccnxp_id_table); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 9be296cf729..6ee59001d61 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -530,7 +530,8 @@ static inline int sci_rxd_in(struct uart_port *port) if (s->cfg->port_reg <= 0) return 1; - return !!__raw_readb(s->cfg->port_reg); + /* Cast for ARM damage */ + return !!__raw_readb((void __iomem *)s->cfg->port_reg); } /* ********************************************************************** * diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 05728894a88..16ee6cee07d 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -452,6 +452,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = { NULL, /* v */ &sysrq_showstate_blocked_op, /* w */ /* x: May be registered on ppc/powerpc for xmon */ + /* x: May be registered on sparc64 for global PMU dump */ NULL, /* x */ /* y: May be registered on sparc64 for global register dump */ NULL, /* y */ diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 981f2132d12..6e49ec6f3ad 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -817,10 +817,6 @@ static const __u32 acm_tty_speed[] = { 2500000, 3000000, 3500000, 4000000 }; -static const __u8 acm_tty_size[] = { - 5, 6, 7, 8 -}; - static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { @@ -834,7 +830,21 @@ static void acm_tty_set_termios(struct tty_struct *tty, newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; - newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; + switch (termios->c_cflag & CSIZE) { + case CS5: + newline.bDataBits = 5; + break; + case CS6: + newline.bDataBits = 6; + break; + case CS7: + newline.bDataBits = 7; + break; + case CS8: + default: + newline.bDataBits = 8; + break; + } /* FIXME: Needs to clear unsupported bits in the termios */ acm->clocal = ((termios->c_cflag & CLOCAL) != 0); @@ -1233,7 +1243,7 @@ made_compressed_probe: if (usb_endpoint_xfer_int(epwrite)) usb_fill_int_urb(snd->urb, usb_dev, - usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), + usb_sndintpipe(usb_dev, epwrite->bEndpointAddress), NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); else usb_fill_bulk_urb(snd->urb, usb_dev, diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e0356cb859b..b78fbe222b7 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1348,6 +1348,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, ret = -EFAULT; goto error; } + uurb->buffer += u; } totlen -= u; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ddd820d2528..6056db7af41 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -367,6 +367,10 @@ static int usb_probe_interface(struct device *dev) intf->condition = USB_INTERFACE_UNBOUND; usb_cancel_queued_reset(intf); + /* If the LPM disable succeeded, balance the ref counts. */ + if (!lpm_disable_error) + usb_unlocked_enable_lpm(udev); + /* Unbound interfaces are always runtime-PM-disabled and -suspended */ if (driver->supports_autosuspend) pm_runtime_disable(dev); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 1e741bca026..f034716190f 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2151,8 +2151,15 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum); irqreturn_t usb_hcd_irq (int irq, void *__hcd) { struct usb_hcd *hcd = __hcd; + unsigned long flags; irqreturn_t rc; + /* IRQF_DISABLED doesn't work correctly with shared IRQs + * when the first handler doesn't use it. So let's just + * assume it's never used. + */ + local_irq_save(flags); + if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) rc = IRQ_NONE; else if (hcd->driver->irq(hcd) == IRQ_NONE) @@ -2160,6 +2167,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd) else rc = IRQ_HANDLED; + local_irq_restore(flags); return rc; } EXPORT_SYMBOL_GPL(usb_hcd_irq); @@ -2347,6 +2355,14 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd, int retval; if (hcd->driver->irq) { + + /* IRQF_DISABLED doesn't work as advertised when used together + * with IRQF_SHARED. As usb_hcd_irq() will always disable + * interrupts we can remove it here. + */ + if (irqflags & IRQF_SHARED) + irqflags &= ~IRQF_DISABLED; + snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); retval = request_irq(irqnum, &usb_hcd_irq, irqflags, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 673ee469626..1af04bdeaf0 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -739,13 +739,16 @@ static void hub_tt_work(struct work_struct *work) int limit = 100; spin_lock_irqsave (&hub->tt.lock, flags); - while (--limit && !list_empty (&hub->tt.clear_list)) { + while (!list_empty(&hub->tt.clear_list)) { struct list_head *next; struct usb_tt_clear *clear; struct usb_device *hdev = hub->hdev; const struct hc_driver *drv; int status; + if (!hub->quiescing && --limit < 0) + break; + next = hub->tt.clear_list.next; clear = list_entry (next, struct usb_tt_clear, clear_list); list_del (&clear->clear_list); @@ -1210,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) if (hub->has_indicators) cancel_delayed_work_sync(&hub->leds); if (hub->tt.hub) - cancel_work_sync(&hub->tt.clear_work); + flush_work(&hub->tt.clear_work); } /* caller has locked the hub device */ @@ -3241,8 +3244,7 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state) (state == USB3_LPM_U2 && (u2_sel > USB3_LPM_MAX_U2_SEL_PEL || u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) { - dev_dbg(&udev->dev, "Device-initiated %s disabled due " - "to long SEL %llu ms or PEL %llu ms\n", + dev_dbg(&udev->dev, "Device-initiated %s disabled due to long SEL %llu us or PEL %llu us\n", usb3_lpm_names[state], u1_sel, u1_pel); return -EINVAL; } @@ -3320,16 +3322,6 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev, if (enable) { /* - * First, let the device know about the exit latencies - * associated with the link state we're about to enable. - */ - ret = usb_req_set_sel(udev, state); - if (ret < 0) { - dev_warn(&udev->dev, "Set SEL for device-initiated " - "%s failed.\n", usb3_lpm_names[state]); - return -EBUSY; - } - /* * Now send the control transfer to enable device-initiated LPM * for either U1 or U2. */ @@ -3414,7 +3406,28 @@ static int usb_set_lpm_timeout(struct usb_device *udev, static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, enum usb3_link_state state) { - int timeout; + int timeout, ret; + __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; + __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; + + /* If the device says it doesn't have *any* exit latency to come out of + * U1 or U2, it's probably lying. Assume it doesn't implement that link + * state. + */ + if ((state == USB3_LPM_U1 && u1_mel == 0) || + (state == USB3_LPM_U2 && u2_mel == 0)) + return; + + /* + * First, let the device know about the exit latencies + * associated with the link state we're about to enable. + */ + ret = usb_req_set_sel(udev, state); + if (ret < 0) { + dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n", + usb3_lpm_names[state]); + return; + } /* We allow the host controller to set the U1/U2 timeout internally * first, so that it can change its schedule to account for the diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index b415c0c859d..c14ebc975ba 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -409,6 +409,10 @@ static void dwc3_core_exit(struct dwc3 *dwc) { dwc3_event_buffers_cleanup(dwc); dwc3_free_event_buffers(dwc); + + usb_phy_shutdown(dwc->usb2_phy); + usb_phy_shutdown(dwc->usb3_phy); + } #define DWC3_ALIGN_MASK (16 - 1) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c9e729a4bf6..7b7deddf6a5 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1904,7 +1904,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); WARN_ON_ONCE(ret); dep->resource_index = 0; - + dep->flags &= ~DWC3_EP_BUSY; udelay(100); } diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index e426ad626d7..4bfa78af379 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -20,6 +20,7 @@ #include <linux/usb/ehci_def.h> #include <linux/delay.h> #include <linux/serial_core.h> +#include <linux/kconfig.h> #include <linux/kgdb.h> #include <linux/kthread.h> #include <asm/io.h> @@ -614,12 +615,6 @@ err: return -ENODEV; } -int dbgp_external_startup(struct usb_hcd *hcd) -{ - return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup(); -} -EXPORT_SYMBOL_GPL(dbgp_external_startup); - static int ehci_reset_port(int port) { u32 portsc; @@ -979,6 +974,7 @@ struct console early_dbgp_console = { .index = -1, }; +#if IS_ENABLED(CONFIG_USB_EHCI_HCD) int dbgp_reset_prep(struct usb_hcd *hcd) { int ret = xen_dbgp_reset_prep(hcd); @@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd) } EXPORT_SYMBOL_GPL(dbgp_reset_prep); +int dbgp_external_startup(struct usb_hcd *hcd) +{ + return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup(); +} +EXPORT_SYMBOL_GPL(dbgp_external_startup); +#endif /* USB_EHCI_HCD */ + #ifdef CONFIG_KGDB static char kgdbdbgp_buf[DBGP_MAX_PACKET]; diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index dfb51a45496..e0ff51b8952 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -952,6 +952,7 @@ endif config USB_G_WEBCAM tristate "USB Webcam Gadget" depends on VIDEO_DEV + select USB_LIBCOMPOSITE help The Webcam Gadget acts as a composite USB Audio and Video Class device. It provides a userspace API to process UVC control requests diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index f696fb9b136..21a9861dabf 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -2930,10 +2930,10 @@ static void vbus_work(struct work_struct *work) /* Get the VBUS status from the transceiver */ value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client, - ISP1301_I2C_OTG_CONTROL_2); + ISP1301_I2C_INTERRUPT_SOURCE); /* VBUS on or off? */ - if (value & OTG_B_SESS_VLD) + if (value & INT_SESS_VLD) udc->vbus = 1; else udc->vbus = 0; diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 43ac7482fa9..c009263a47e 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev) #if defined(PLX_PCI_RDK2) /* see if PCI int for us by checking irqstat */ intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT); - if (!intcsr & (1 << NET2272_PCI_IRQ)) + if (!intcsr & (1 << NET2272_PCI_IRQ)) { + spin_unlock(&dev->lock); return IRQ_NONE; + } /* check dma interrupts */ #endif /* Platform/devcice interrupt handler */ diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 6458764994e..4ec3c0d7a18 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -20,6 +20,7 @@ #include <linux/ctype.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> +#include <linux/if_vlan.h> #include "u_ether.h" @@ -295,7 +296,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req) while (skb2) { if (status < 0 || ETH_HLEN > skb2->len - || skb2->len > ETH_FRAME_LEN) { + || skb2->len > VLAN_ETH_FRAME_LEN) { dev->net->stats.rx_errors++; dev->net->stats.rx_length_errors++; DBG(dev, "rx length %d\n", skb2->len); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 9bfde82078e..0d2f35ca93f 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -222,7 +222,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, if (pdata->controller_ver < 0) { dev_warn(hcd->self.controller, "Could not get controller version\n"); - return; + return -ENODEV; } portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c index ca759652626..aa0f328922d 100644 --- a/drivers/usb/host/ehci-ls1x.c +++ b/drivers/usb/host/ehci-ls1x.c @@ -113,7 +113,7 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev) goto err_put_hcd; } - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (ret) goto err_put_hcd; diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 8e7eca62f16..9c2717d6673 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -160,7 +160,7 @@ static const struct hc_driver ehci_orion_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; -static void __init +static void __devinit ehci_orion_conf_mbus_windows(struct usb_hcd *hcd, const struct mbus_dram_target_info *dram) { diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c index 96722bfebc8..d3c9a3e397b 100644 --- a/drivers/usb/host/ehci-vt8500.c +++ b/drivers/usb/host/ehci-vt8500.c @@ -85,6 +85,8 @@ static const struct hc_driver vt8500_ehci_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; +static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32); + static int vt8500_ehci_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; @@ -95,6 +97,14 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) if (usb_disabled()) return -ENODEV; + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &vt8500_ehci_dma_mask; + if (pdev->resource[1].flags != IORESOURCE_IRQ) { pr_debug("resource[1] is not IORESOURCE_IRQ"); return -ENOMEM; diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c index 84201cd1a47..41e378f17c6 100644 --- a/drivers/usb/host/ohci-xls.c +++ b/drivers/usb/host/ohci-xls.c @@ -56,7 +56,7 @@ static int ohci_xls_probe_internal(const struct hc_driver *driver, goto err3; } - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err4; return retval; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 966d1484ee7..39f9e4a9a2d 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -545,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { /* Pegatron Lucid (Ordissimo AIRIS) */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "M11JB"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), + }, + }, + { + /* Pegatron Lucid (Ordissimo) */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, { } diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c index e4780491df4..68ebf20e151 100644 --- a/drivers/usb/host/uhci-platform.c +++ b/drivers/usb/host/uhci-platform.c @@ -60,6 +60,7 @@ static const struct hc_driver uhci_platform_hc_driver = { .hub_control = uhci_hub_control, }; +static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32); static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev) { @@ -71,6 +72,14 @@ static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev) if (usb_disabled()) return -ENODEV; + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &platform_uhci_dma_mask; + hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev, pdev->name); if (!hcd) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 4b436f5a417..5f3a7c74aa8 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, int i; /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; - struct xhci_slot_ctx *slot_ctx; dma_addr_t dma = ctx->dma; int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); @@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma); } - slot_ctx = xhci_get_slot_ctx(xhci, ctx); xhci_dbg_slot_ctx(xhci, ctx); xhci_dbg_ep_ctx(xhci, ctx, last_ep); } diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index aa90ad4d4fd..a686cf4905b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, if (portsc & PORT_DEV_REMOVE) port_removable |= 1 << (i + 1); } - memset(&desc->u.ss.DeviceRemovable, - (__force __u16) cpu_to_le16(port_removable), - sizeof(__u16)); + + desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable); } static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, @@ -809,11 +808,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, port_array[wIndex]); xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); + spin_unlock_irqrestore(&xhci->lock, flags); temp = usb_acpi_power_manageable(hcd->self.root_hub, wIndex); if (temp) usb_acpi_set_power_state(hcd->self.root_hub, wIndex, true); + spin_lock_irqsave(&xhci->lock, flags); break; case USB_PORT_FEAT_RESET: temp = (temp | PORT_RESET); @@ -917,11 +918,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_writel(xhci, temp & ~PORT_POWER, port_array[wIndex]); + spin_unlock_irqrestore(&xhci->lock, flags); temp = usb_acpi_power_manageable(hcd->self.root_hub, wIndex); if (temp) usb_acpi_set_power_state(hcd->self.root_hub, wIndex, false); + spin_lock_irqsave(&xhci->lock, flags); break; default: goto error; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index c6ebb176dc4..4e1a8946b8d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) cur_seg = find_trb_seg(xhci->cmd_ring->first_seg, xhci->cmd_ring->dequeue, &cycle_state); + if (!cur_seg) { + xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n", + xhci->cmd_ring->dequeue, + (unsigned long long) + xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, + xhci->cmd_ring->dequeue)); + xhci_debug_ring(xhci, xhci->cmd_ring); + xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); + return; + } + /* find the command trb matched by cd from command ring */ for (cmd_trb = xhci->cmd_ring->dequeue; cmd_trb != xhci->cmd_ring->enqueue; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 8d7fcbbe6ad..c9e419f29b7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -479,7 +479,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void) if (strstr(dmi_product_name, "Z420") || strstr(dmi_product_name, "Z620") || - strstr(dmi_product_name, "Z820")) + strstr(dmi_product_name, "Z820") || + strstr(dmi_product_name, "Z1")) return true; return false; @@ -1626,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct xhci_hcd *xhci; struct xhci_container_ctx *in_ctx, *out_ctx; unsigned int ep_index; - struct xhci_ep_ctx *ep_ctx; struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u32 added_ctxs; @@ -1662,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, out_ctx = virt_dev->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); - ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); /* If this endpoint is already in use, and the upper layers are trying * to add it again without dropping it, reject the addition. @@ -1816,6 +1815,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, case COMP_EBADSLT: dev_warn(&udev->dev, "WARN: slot not enabled for" "evaluate context command.\n"); + ret = -EINVAL; + break; case COMP_CTX_STATE: dev_warn(&udev->dev, "WARN: invalid context state for " "evaluate context command.\n"); @@ -4020,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) static unsigned long long xhci_service_interval_to_ns( struct usb_endpoint_descriptor *desc) { - return (1 << (desc->bInterval - 1)) * 125 * 1000; + return (1ULL << (desc->bInterval - 1)) * 125 * 1000; } static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, @@ -4141,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev, (xhci_service_interval_to_ns(desc) > timeout_ns)) timeout_ns = xhci_service_interval_to_ns(desc); - u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000; + u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL; if (u2_del_ns > timeout_ns) timeout_ns = u2_del_ns; diff --git a/drivers/usb/misc/ezusb.c b/drivers/usb/misc/ezusb.c index 4223d761223..6589268a651 100644 --- a/drivers/usb/misc/ezusb.c +++ b/drivers/usb/misc/ezusb.c @@ -158,3 +158,4 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, } EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 457f25e62c5..c964d6af178 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -305,6 +305,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) ret = IRQ_HANDLED; } + /* Drop spurious RX and TX if device is disconnected */ + if (musb->int_usb & MUSB_INTR_DISCONNECT) { + musb->int_tx = 0; + musb->int_rx = 0; + } + if (musb->int_tx || musb->int_rx || musb->int_usb) ret |= musb_interrupt(musb); diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 444346e1e10..ff5f112053d 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) struct platform_device *musb; struct resource *res; struct resource resources[2]; - char res_name[10]; + char res_name[11]; int ret, musbid; /* get memory resource */ - sprintf(res_name, "musb%d", id); + snprintf(res_name, sizeof(res_name), "musb%d", id); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); if (!res) { dev_err(dev, "%s get mem resource failed\n", res_name); @@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) resources[0] = *res; /* get irq resource */ - sprintf(res_name, "musb%d-irq", id); + snprintf(res_name, sizeof(res_name), "musb%d-irq", id); res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); if (!res) { dev_err(dev, "%s get irq resource failed\n", res_name); @@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); - sprintf(res_name, "port%d-mode", id); + snprintf(res_name, sizeof(res_name), "port%d-mode", id); of_property_read_u32(np, res_name, (u32 *)&pdata->mode); of_property_read_u32(np, "power", (u32 *)&pdata->power); config->multipoint = of_property_read_bool(np, "multipoint"); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d0b87e7b4ab..b6b84dacc79 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -707,11 +707,12 @@ static void rxstate(struct musb *musb, struct musb_request *req) fifo_count = musb_readw(epio, MUSB_RXCOUNT); /* - * use mode 1 only if we expect data of at least ep packet_sz - * and have not yet received a short packet + * Enable Mode 1 on RX transfers only when short_not_ok flag + * is set. Currently short_not_ok flag is set only from + * file_storage and f_mass_storage drivers */ - if ((request->length - request->actual >= musb_ep->packet_sz) && - (fifo_count >= musb_ep->packet_sz)) + + if (request->short_not_ok && fifo_count == musb_ep->packet_sz) use_mode_1 = 1; else use_mode_1 = 0; @@ -727,6 +728,27 @@ static void rxstate(struct musb *musb, struct musb_request *req) c = musb->dma_controller; channel = musb_ep->dma; + /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in + * mode 0 only. So we do not get endpoint interrupts due to DMA + * completion. We only get interrupts from DMA controller. + * + * We could operate in DMA mode 1 if we knew the size of the tranfer + * in advance. For mass storage class, request->length = what the host + * sends, so that'd work. But for pretty much everything else, + * request->length is routinely more than what the host sends. For + * most these gadgets, end of is signified either by a short packet, + * or filling the last byte of the buffer. (Sending extra data in + * that last pckate should trigger an overflow fault.) But in mode 1, + * we don't get DMA completion interrupt for short packets. + * + * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1), + * to get endpoint interrupt on every DMA req, but that didn't seem + * to work reliably. + * + * REVISIT an updated g_file_storage can set req->short_not_ok, which + * then becomes usable as a runtime "use mode 1" hint... + */ + /* Experimental: Mode1 works with mass storage use cases */ if (use_mode_1) { csr |= MUSB_RXCSR_AUTOCLEAR; diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index d62a91fedc2..0e62f504410 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -65,7 +65,7 @@ static int __devinit ux500_probe(struct platform_device *pdev) struct platform_device *musb; struct ux500_glue *glue; struct clk *clk; - + int musbid; int ret = -ENOMEM; glue = kzalloc(sizeof(*glue), GFP_KERNEL); diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index d8c8a42bff3..6223062d5d1 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -58,7 +58,7 @@ config USB_ULPI_VIEWPORT config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" - depends on TWL4030_CORE && REGULATOR_TWL4030 + depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL4030 @@ -68,7 +68,7 @@ config TWL4030_USB config TWL6030_USB tristate "TWL6030 USB Transceiver Driver" - depends on TWL4030_CORE && OMAP_USB2 + depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL6030 diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 143c4e9e1be..c021b202c0f 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -795,6 +795,7 @@ static void xfer_work(struct work_struct *work) dev_dbg(dev, " %s %d (%d/ %d)\n", fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); + usbhs_pipe_enable(pipe); usbhsf_dma_start(pipe, fifo); dma_async_issue_pending(chan); } diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 35c5208f324..61933a90e5b 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -273,9 +273,9 @@ static irqreturn_t usbhs_interrupt(int irq, void *data) usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC); usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC); - usbhs_write(priv, BRDYSTS, 0); - usbhs_write(priv, NRDYSTS, 0); - usbhs_write(priv, BEMPSTS, 0); + usbhs_write(priv, BRDYSTS, ~irq_state.brdysts); + usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts); + usbhs_write(priv, BEMPSTS, ~irq_state.bempsts); /* * call irq callback functions diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 9b69a132329..069cd765400 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -334,6 +334,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv, struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; + if (unlikely(!uep)) { + dev_err(dev, "no uep\n"); + return; + } + /******************** spin lock ********************/ usbhs_lock(priv, flags); diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 08786c06dcf..3d80c7b1fd1 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -54,7 +54,7 @@ struct usbhs_pipe_info { * pipe list */ #define __usbhs_for_each_pipe(start, pos, info, i) \ - for (i = start, pos = (info)->pipe; \ + for (i = start, pos = (info)->pipe + i; \ i < (info)->size; \ i++, pos = (info)->pipe + i) diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index cf2522c397d..bd50a8a41a0 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -125,9 +125,6 @@ static inline int calc_divisor(int bps) static int ark3116_attach(struct usb_serial *serial) { - struct usb_serial_port *port = serial->port[0]; - struct ark3116_private *priv; - /* make sure we have our end-points */ if ((serial->num_bulk_in == 0) || (serial->num_bulk_out == 0) || @@ -142,8 +139,15 @@ static int ark3116_attach(struct usb_serial *serial) return -EINVAL; } - priv = kzalloc(sizeof(struct ark3116_private), - GFP_KERNEL); + return 0; +} + +static int ark3116_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct ark3116_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -198,18 +202,15 @@ static int ark3116_attach(struct usb_serial *serial) return 0; } -static void ark3116_release(struct usb_serial *serial) +static int ark3116_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct ark3116_private *priv = usb_get_serial_port_data(port); /* device is closed, so URBs and DMA should be down */ - - usb_set_serial_port_data(port, NULL); - mutex_destroy(&priv->hw_lock); - kfree(priv); + + return 0; } static void ark3116_init_termios(struct tty_struct *tty) @@ -723,7 +724,8 @@ static struct usb_serial_driver ark3116_device = { .id_table = id_table, .num_ports = 1, .attach = ark3116_attach, - .release = ark3116_release, + .port_probe = ark3116_port_probe, + .port_remove = ark3116_port_remove, .set_termios = ark3116_set_termios, .init_termios = ark3116_init_termios, .ioctl = ark3116_ioctl, diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 99449424193..ea29556f0d7 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -45,8 +45,8 @@ #define DRIVER_DESC "USB Belkin Serial converter driver" /* function prototypes for a Belkin USB Serial Adapter F5U103 */ -static int belkin_sa_startup(struct usb_serial *serial); -static void belkin_sa_release(struct usb_serial *serial); +static int belkin_sa_port_probe(struct usb_serial_port *port); +static int belkin_sa_port_remove(struct usb_serial_port *port); static int belkin_sa_open(struct tty_struct *tty, struct usb_serial_port *port); static void belkin_sa_close(struct usb_serial_port *port); @@ -88,8 +88,8 @@ static struct usb_serial_driver belkin_device = { .break_ctl = belkin_sa_break_ctl, .tiocmget = belkin_sa_tiocmget, .tiocmset = belkin_sa_tiocmset, - .attach = belkin_sa_startup, - .release = belkin_sa_release, + .port_probe = belkin_sa_port_probe, + .port_remove = belkin_sa_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -118,17 +118,15 @@ struct belkin_sa_private { (c), BELKIN_SA_SET_REQUEST_TYPE, \ (v), 0, NULL, 0, WDR_TIMEOUT) -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int belkin_sa_startup(struct usb_serial *serial) +static int belkin_sa_port_probe(struct usb_serial_port *port) { - struct usb_device *dev = serial->dev; + struct usb_device *dev = port->serial->dev; struct belkin_sa_private *priv; - /* allocate the private data structure */ priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL); if (!priv) - return -1; /* error */ - /* set initial values for control structures */ + return -ENOMEM; + spin_lock_init(&priv->lock); priv->control_state = 0; priv->last_lsr = 0; @@ -140,18 +138,19 @@ static int belkin_sa_startup(struct usb_serial *serial) le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control); - init_waitqueue_head(&serial->port[0]->write_wait); - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); return 0; } -static void belkin_sa_release(struct usb_serial *serial) +static int belkin_sa_port_remove(struct usb_serial_port *port) { - int i; + struct belkin_sa_private *priv; - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int belkin_sa_open(struct tty_struct *tty, diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index e9c7046ae35..d255f66e708 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -242,13 +242,11 @@ out: kfree(buffer); return r; } -/* allocate private data */ -static int ch341_attach(struct usb_serial *serial) +static int ch341_port_probe(struct usb_serial_port *port) { struct ch341_private *priv; int r; - /* private data */ priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial) priv->baud_rate = DEFAULT_BAUD_RATE; priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; - r = ch341_configure(serial->dev, priv); + r = ch341_configure(port->serial->dev, priv); if (r < 0) goto error; - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); return 0; error: kfree(priv); return r; } +static int ch341_port_remove(struct usb_serial_port *port) +{ + struct ch341_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} + static int ch341_carrier_raised(struct usb_serial_port *port) { struct ch341_private *priv = usb_get_serial_port_data(port); @@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port) static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]); + struct ch341_private *priv = usb_get_serial_port_data(port); int r; priv->baud_rate = DEFAULT_BAUD_RATE; @@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = { .tiocmget = ch341_tiocmget, .tiocmset = ch341_tiocmset, .read_int_callback = ch341_read_int_callback, - .attach = ch341_attach, + .port_probe = ch341_port_probe, + .port_remove = ch341_port_remove, .reset_resume = ch341_reset_resume, }; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 28af5acc336..eb033fc92a1 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -162,7 +162,7 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); -struct cp210x_port_private { +struct cp210x_serial_private { __u8 bInterfaceNumber; }; @@ -276,7 +276,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; @@ -292,7 +292,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, /* Issue the request, attempting to read 'size' bytes */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), request, REQTYPE_INTERFACE_TO_HOST, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_GET_TIMEOUT); /* Convert data into an array of integers */ @@ -323,7 +323,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; - struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); + struct cp210x_serial_private *spriv = usb_get_serial_data(serial); __le32 *buf; int result, i, length; @@ -345,13 +345,13 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, 0x0000, - port_priv->bInterfaceNumber, buf, size, + spriv->bInterfaceNumber, buf, size, USB_CTRL_SET_TIMEOUT); } else { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_INTERFACE, data[0], - port_priv->bInterfaceNumber, NULL, 0, + spriv->bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); } @@ -845,36 +845,30 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state) static int cp210x_startup(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct usb_host_interface *cur_altsetting; + struct cp210x_serial_private *spriv; /* cp210x buffers behave strangely unless device is reset */ usb_reset_device(serial->dev); - for (i = 0; i < serial->num_ports; i++) { - port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); - if (!port_priv) - return -ENOMEM; + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; - port_priv->bInterfaceNumber = - serial->interface->cur_altsetting->desc.bInterfaceNumber; + cur_altsetting = serial->interface->cur_altsetting; + spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber; - usb_set_serial_port_data(serial->port[i], port_priv); - } + usb_set_serial_data(serial, spriv); return 0; } static void cp210x_release(struct usb_serial *serial) { - struct cp210x_port_private *port_priv; - int i; + struct cp210x_serial_private *spriv; - for (i = 0; i < serial->num_ports; i++) { - port_priv = usb_get_serial_port_data(serial->port[i]); - kfree(port_priv); - usb_set_serial_port_data(serial->port[i], NULL); - } + spriv = usb_get_serial_data(serial); + kfree(spriv); } module_usb_serial_driver(serial_drivers, id_table); diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 2a7aecc7223..4ee77dcbe69 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -55,9 +55,9 @@ #define CYBERJACK_PRODUCT_ID 0x0100 /* Function prototypes */ -static int cyberjack_startup(struct usb_serial *serial); static void cyberjack_disconnect(struct usb_serial *serial); -static void cyberjack_release(struct usb_serial *serial); +static int cyberjack_port_probe(struct usb_serial_port *port); +static int cyberjack_port_remove(struct usb_serial_port *port); static int cyberjack_open(struct tty_struct *tty, struct usb_serial_port *port); static void cyberjack_close(struct usb_serial_port *port); @@ -83,9 +83,9 @@ static struct usb_serial_driver cyberjack_device = { .description = "Reiner SCT Cyberjack USB card reader", .id_table = id_table, .num_ports = 1, - .attach = cyberjack_startup, .disconnect = cyberjack_disconnect, - .release = cyberjack_release, + .port_probe = cyberjack_port_probe, + .port_remove = cyberjack_port_remove, .open = cyberjack_open, .close = cyberjack_close, .write = cyberjack_write, @@ -107,56 +107,45 @@ struct cyberjack_private { short wrsent; /* Data already sent */ }; -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int cyberjack_startup(struct usb_serial *serial) +static int cyberjack_port_probe(struct usb_serial_port *port) { struct cyberjack_private *priv; - int i; + int result; - /* allocate the private data structure */ priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL); if (!priv) return -ENOMEM; - /* set initial values */ spin_lock_init(&priv->lock); priv->rdtodo = 0; priv->wrfilled = 0; priv->wrsent = 0; - usb_set_serial_port_data(serial->port[0], priv); - init_waitqueue_head(&serial->port[0]->write_wait); + usb_set_serial_port_data(port, priv); - for (i = 0; i < serial->num_ports; ++i) { - int result; - result = usb_submit_urb(serial->port[i]->interrupt_in_urb, - GFP_KERNEL); - if (result) - dev_err(&serial->dev->dev, - "usb_submit_urb(read int) failed\n"); - dev_dbg(&serial->dev->dev, "%s - usb_submit_urb(int urb)\n", - __func__); - } + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); return 0; } -static void cyberjack_disconnect(struct usb_serial *serial) +static int cyberjack_port_remove(struct usb_serial_port *port) { - int i; + struct cyberjack_private *priv; - for (i = 0; i < serial->num_ports; ++i) - usb_kill_urb(serial->port[i]->interrupt_in_urb); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } -static void cyberjack_release(struct usb_serial *serial) +static void cyberjack_disconnect(struct usb_serial *serial) { int i; - for (i = 0; i < serial->num_ports; ++i) { - /* My special items, the standard routines free my urbs */ - kfree(usb_get_serial_port_data(serial->port[i])); - } + for (i = 0; i < serial->num_ports; ++i) + usb_kill_urb(serial->port[i]->interrupt_in_urb); } static int cyberjack_open(struct tty_struct *tty, diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 1befce21e17..f0da1279c11 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -123,10 +123,10 @@ struct cypress_private { }; /* function prototypes for the Cypress USB to serial device */ -static int cypress_earthmate_startup(struct usb_serial *serial); -static int cypress_hidcom_startup(struct usb_serial *serial); -static int cypress_ca42v2_startup(struct usb_serial *serial); -static void cypress_release(struct usb_serial *serial); +static int cypress_earthmate_port_probe(struct usb_serial_port *port); +static int cypress_hidcom_port_probe(struct usb_serial_port *port); +static int cypress_ca42v2_port_probe(struct usb_serial_port *port); +static int cypress_port_remove(struct usb_serial_port *port); static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port); static void cypress_close(struct usb_serial_port *port); static void cypress_dtr_rts(struct usb_serial_port *port, int on); @@ -156,8 +156,8 @@ static struct usb_serial_driver cypress_earthmate_device = { .description = "DeLorme Earthmate USB", .id_table = id_table_earthmate, .num_ports = 1, - .attach = cypress_earthmate_startup, - .release = cypress_release, + .port_probe = cypress_earthmate_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -182,8 +182,8 @@ static struct usb_serial_driver cypress_hidcom_device = { .description = "HID->COM RS232 Adapter", .id_table = id_table_cyphidcomrs232, .num_ports = 1, - .attach = cypress_hidcom_startup, - .release = cypress_release, + .port_probe = cypress_hidcom_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -208,8 +208,8 @@ static struct usb_serial_driver cypress_ca42v2_device = { .description = "Nokia CA-42 V2 Adapter", .id_table = id_table_nokiaca42v2, .num_ports = 1, - .attach = cypress_ca42v2_startup, - .release = cypress_release, + .port_probe = cypress_ca42v2_port_probe, + .port_remove = cypress_port_remove, .open = cypress_open, .close = cypress_close, .dtr_rts = cypress_dtr_rts, @@ -438,10 +438,10 @@ static void cypress_set_dead(struct usb_serial_port *port) *****************************************************************************/ -static int generic_startup(struct usb_serial *serial) +static int cypress_generic_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); if (!priv) @@ -490,14 +490,16 @@ static int generic_startup(struct usb_serial *serial) } -static int cypress_earthmate_startup(struct usb_serial *serial) +static int cypress_earthmate_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); - return 1; + return ret; } priv = usb_get_serial_port_data(port); @@ -518,56 +520,53 @@ static int cypress_earthmate_startup(struct usb_serial *serial) } return 0; -} /* cypress_earthmate_startup */ - +} -static int cypress_hidcom_startup(struct usb_serial *serial) +static int cypress_hidcom_port_probe(struct usb_serial_port *port) { struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); - return 1; + return ret; } priv = usb_get_serial_port_data(port); priv->chiptype = CT_CYPHIDCOM; return 0; -} /* cypress_hidcom_startup */ - +} -static int cypress_ca42v2_startup(struct usb_serial *serial) +static int cypress_ca42v2_port_probe(struct usb_serial_port *port) { struct cypress_private *priv; - struct usb_serial_port *port = serial->port[0]; + int ret; - if (generic_startup(serial)) { + ret = cypress_generic_port_probe(port); + if (ret) { dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); - return 1; + return ret; } priv = usb_get_serial_port_data(port); priv->chiptype = CT_CA42V2; return 0; -} /* cypress_ca42v2_startup */ - +} -static void cypress_release(struct usb_serial *serial) +static int cypress_port_remove(struct usb_serial_port *port) { struct cypress_private *priv; - /* all open ports are closed at this point */ - priv = usb_get_serial_port_data(serial->port[0]); + priv = usb_get_serial_port_data(port); - if (priv) { - kfifo_free(&priv->write_fifo); - kfree(priv); - } -} + kfifo_free(&priv->write_fifo); + kfree(priv); + return 0; +} static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) { diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index c86f68c6b07..b50fa1c6d88 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); static void digi_disconnect(struct usb_serial *serial); static void digi_release(struct usb_serial *serial); +static int digi_port_probe(struct usb_serial_port *port); +static int digi_port_remove(struct usb_serial_port *port); static void digi_read_bulk_callback(struct urb *urb); static int digi_read_inb_callback(struct urb *urb); static int digi_read_oob_callback(struct urb *urb); @@ -294,6 +296,8 @@ static struct usb_serial_driver digi_acceleport_2_device = { .attach = digi_startup, .disconnect = digi_disconnect, .release = digi_release, + .port_probe = digi_port_probe, + .port_remove = digi_port_remove, }; static struct usb_serial_driver digi_acceleport_4_device = { @@ -320,6 +324,8 @@ static struct usb_serial_driver digi_acceleport_4_device = { .attach = digi_startup, .disconnect = digi_disconnect, .release = digi_release, + .port_probe = digi_port_probe, + .port_remove = digi_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -1240,59 +1246,50 @@ static int digi_startup_device(struct usb_serial *serial) return ret; } - -static int digi_startup(struct usb_serial *serial) +static int digi_port_init(struct usb_serial_port *port, unsigned port_num) { - - int i; struct digi_port *priv; - struct digi_serial *serial_priv; - /* allocate the private data structures for all ports */ - /* number of regular ports + 1 for the out-of-band port */ - for (i = 0; i < serial->type->num_ports + 1; i++) { - /* allocate port private structure */ - priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL); - if (priv == NULL) { - while (--i >= 0) - kfree(usb_get_serial_port_data(serial->port[i])); - return 1; /* error */ - } + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - /* initialize port private structure */ - spin_lock_init(&priv->dp_port_lock); - priv->dp_port_num = i; - priv->dp_out_buf_len = 0; - priv->dp_write_urb_in_use = 0; - priv->dp_modem_signals = 0; - init_waitqueue_head(&priv->dp_modem_change_wait); - priv->dp_transmit_idle = 0; - init_waitqueue_head(&priv->dp_transmit_idle_wait); - priv->dp_throttled = 0; - priv->dp_throttle_restart = 0; - init_waitqueue_head(&priv->dp_flush_wait); - init_waitqueue_head(&priv->dp_close_wait); - INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); - priv->dp_port = serial->port[i]; - /* initialize write wait queue for this port */ - init_waitqueue_head(&serial->port[i]->write_wait); - - usb_set_serial_port_data(serial->port[i], priv); - } + spin_lock_init(&priv->dp_port_lock); + priv->dp_port_num = port_num; + init_waitqueue_head(&priv->dp_modem_change_wait); + init_waitqueue_head(&priv->dp_transmit_idle_wait); + init_waitqueue_head(&priv->dp_flush_wait); + init_waitqueue_head(&priv->dp_close_wait); + INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); + priv->dp_port = port; - /* allocate serial private structure */ - serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL); - if (serial_priv == NULL) { - for (i = 0; i < serial->type->num_ports + 1; i++) - kfree(usb_get_serial_port_data(serial->port[i])); - return 1; /* error */ - } + init_waitqueue_head(&port->write_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int digi_startup(struct usb_serial *serial) +{ + struct digi_serial *serial_priv; + int ret; + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) + return -ENOMEM; - /* initialize serial private structure */ spin_lock_init(&serial_priv->ds_serial_lock); serial_priv->ds_oob_port_num = serial->type->num_ports; serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; - serial_priv->ds_device_started = 0; + + ret = digi_port_init(serial_priv->ds_oob_port, + serial_priv->ds_oob_port_num); + if (ret) { + kfree(serial_priv); + return ret; + } + usb_set_serial_data(serial, serial_priv); return 0; @@ -1313,15 +1310,35 @@ static void digi_disconnect(struct usb_serial *serial) static void digi_release(struct usb_serial *serial) { - int i; + struct digi_serial *serial_priv; + struct digi_port *priv; + + serial_priv = usb_get_serial_data(serial); + + priv = usb_get_serial_port_data(serial_priv->ds_oob_port); + kfree(priv); - /* free the private data structures for all ports */ - /* number of regular ports + 1 for the out-of-band port */ - for (i = 0; i < serial->type->num_ports + 1; i++) - kfree(usb_get_serial_port_data(serial->port[i])); - kfree(usb_get_serial_data(serial)); + kfree(serial_priv); } +static int digi_port_probe(struct usb_serial_port *port) +{ + unsigned port_num; + + port_num = port->number - port->serial->minor; + + return digi_port_init(port, port_num); +} + +static int digi_port_remove(struct usb_serial_port *port) +{ + struct digi_port *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} static void digi_read_bulk_callback(struct urb *urb) { diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 244477107e2..6e4eb57d017 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -318,39 +318,30 @@ static int f81232_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } -static int f81232_startup(struct usb_serial *serial) +static int f81232_port_probe(struct usb_serial_port *port) { struct f81232_private *priv; - int i; - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL); - if (!priv) - goto cleanup; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[i], priv); - } - return 0; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; -cleanup: - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; } -static void f81232_release(struct usb_serial *serial) +static int f81232_port_remove(struct usb_serial_port *port) { - int i; struct f81232_private *priv; - for (i = 0; i < serial->num_ports; ++i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static struct usb_serial_driver f81232_device = { @@ -373,8 +364,8 @@ static struct usb_serial_driver f81232_device = { .tiocmset = f81232_tiocmset, .process_read_urb = f81232_process_read_urb, .read_int_callback = f81232_read_int_callback, - .attach = f81232_startup, - .release = f81232_release, + .port_probe = f81232_port_probe, + .port_remove = f81232_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 3ee92648c02..203358d7e7b 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1405,11 +1405,10 @@ static void timeout_handler(unsigned long data) -static int garmin_attach(struct usb_serial *serial) +static int garmin_port_probe(struct usb_serial_port *port) { - int status = 0; - struct usb_serial_port *port = serial->port[0]; - struct garmin_data *garmin_data_p = NULL; + int status; + struct garmin_data *garmin_data_p; garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); if (garmin_data_p == NULL) { @@ -1434,22 +1433,14 @@ static int garmin_attach(struct usb_serial *serial) } -static void garmin_disconnect(struct usb_serial *serial) +static int garmin_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); usb_kill_urb(port->interrupt_in_urb); del_timer_sync(&garmin_data_p->timer); -} - - -static void garmin_release(struct usb_serial *serial) -{ - struct usb_serial_port *port = serial->port[0]; - struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - kfree(garmin_data_p); + return 0; } @@ -1466,9 +1457,8 @@ static struct usb_serial_driver garmin_device = { .close = garmin_close, .throttle = garmin_throttle, .unthrottle = garmin_unthrottle, - .attach = garmin_attach, - .disconnect = garmin_disconnect, - .release = garmin_release, + .port_probe = garmin_port_probe, + .port_remove = garmin_port_remove, .write = garmin_write, .write_room = garmin_write_room, .write_bulk_callback = garmin_write_bulk_callback, diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 8e6faaf3580..5acc0d13864 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -225,6 +225,8 @@ static int edge_get_icount(struct tty_struct *tty, static int edge_startup(struct usb_serial *serial); static void edge_disconnect(struct usb_serial *serial); static void edge_release(struct usb_serial *serial); +static int edge_port_probe(struct usb_serial_port *port); +static int edge_port_remove(struct usb_serial_port *port); #include "io_tables.h" /* all of the devices that this driver supports */ @@ -2875,10 +2877,9 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; - struct edgeport_port *edge_port; struct usb_device *dev; struct device *ddev = &serial->dev->dev; - int i, j; + int i; int response; bool interrupt_in_found; bool bulk_in_found; @@ -2961,25 +2962,6 @@ static int edge_startup(struct usb_serial *serial) /* we set up the pointers to the endpoints in the edge_open function, * as the structures aren't created yet. */ - /* set up our port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); - if (edge_port == NULL) { - dev_err(ddev, "%s - Out of memory\n", __func__); - for (j = 0; j < i; ++j) { - kfree(usb_get_serial_port_data(serial->port[j])); - usb_set_serial_port_data(serial->port[j], - NULL); - } - usb_set_serial_data(serial, NULL); - kfree(edge_serial); - return -ENOMEM; - } - spin_lock_init(&edge_port->ep_lock); - edge_port->port = serial->port[i]; - usb_set_serial_port_data(serial->port[i], edge_port); - } - response = 0; if (edge_serial->is_epic) { @@ -3120,14 +3102,36 @@ static void edge_disconnect(struct usb_serial *serial) static void edge_release(struct usb_serial *serial) { struct edgeport_serial *edge_serial = usb_get_serial_data(serial); - int i; - - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); kfree(edge_serial); } +static int edge_port_probe(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL); + if (!edge_port) + return -ENOMEM; + + spin_lock_init(&edge_port->ep_lock); + edge_port->port = port; + + usb_set_serial_port_data(port, edge_port); + + return 0; +} + +static int edge_port_remove(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = usb_get_serial_port_data(port); + kfree(edge_port); + + return 0; +} + module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 350afddb55b..1511dd0ad32 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -110,6 +110,8 @@ static struct usb_serial_driver edgeport_2port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -139,6 +141,8 @@ static struct usb_serial_driver edgeport_4port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -168,6 +172,8 @@ static struct usb_serial_driver edgeport_8port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -197,6 +203,8 @@ static struct usb_serial_driver epic_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index a2209cd4509..60023c2d2a3 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -2532,12 +2532,7 @@ static void edge_break(struct tty_struct *tty, int break_state) static int edge_startup(struct usb_serial *serial) { struct edgeport_serial *edge_serial; - struct edgeport_port *edge_port; - struct usb_device *dev; int status; - int i; - - dev = serial->dev; /* create our private serial structure */ edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); @@ -2555,40 +2550,7 @@ static int edge_startup(struct usb_serial *serial) return status; } - /* set up our port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); - if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); - goto cleanup; - } - spin_lock_init(&edge_port->ep_lock); - if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, - GFP_KERNEL)) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); - kfree(edge_port); - goto cleanup; - } - edge_port->port = serial->port[i]; - edge_port->edge_serial = edge_serial; - usb_set_serial_port_data(serial->port[i], edge_port); - edge_port->bUartMode = default_uart_mode; - } - return 0; - -cleanup: - for (--i; i >= 0; --i) { - edge_port = usb_get_serial_port_data(serial->port[i]); - kfifo_free(&edge_port->write_fifo); - kfree(edge_port); - usb_set_serial_port_data(serial->port[i], NULL); - } - kfree(edge_serial); - usb_set_serial_data(serial, NULL); - return -ENOMEM; } static void edge_disconnect(struct usb_serial *serial) @@ -2597,17 +2559,54 @@ static void edge_disconnect(struct usb_serial *serial) static void edge_release(struct usb_serial *serial) { - int i; + kfree(usb_get_serial_data(serial)); +} + +static int edge_port_probe(struct usb_serial_port *port) +{ struct edgeport_port *edge_port; + int ret; - for (i = 0; i < serial->num_ports; ++i) { - edge_port = usb_get_serial_port_data(serial->port[i]); + edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL); + if (!edge_port) + return -ENOMEM; + + ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, + GFP_KERNEL); + if (ret) { + kfree(edge_port); + return -ENOMEM; + } + + spin_lock_init(&edge_port->ep_lock); + edge_port->port = port; + edge_port->edge_serial = usb_get_serial_data(port->serial); + edge_port->bUartMode = default_uart_mode; + + usb_set_serial_port_data(port, edge_port); + + ret = edge_create_sysfs_attrs(port); + if (ret) { kfifo_free(&edge_port->write_fifo); kfree(edge_port); + return ret; } - kfree(usb_get_serial_data(serial)); + + return 0; } +static int edge_port_remove(struct usb_serial_port *port) +{ + struct edgeport_port *edge_port; + + edge_port = usb_get_serial_port_data(port); + + edge_remove_sysfs_attrs(port); + kfifo_free(&edge_port->write_fifo); + kfree(edge_port); + + return 0; +} /* Sysfs Attributes */ @@ -2667,8 +2666,8 @@ static struct usb_serial_driver edgeport_1port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, - .port_probe = edge_create_sysfs_attrs, - .port_remove = edge_remove_sysfs_attrs, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, @@ -2698,8 +2697,8 @@ static struct usb_serial_driver edgeport_2port_device = { .attach = edge_startup, .disconnect = edge_disconnect, .release = edge_release, - .port_probe = edge_create_sysfs_attrs, - .port_remove = edge_remove_sysfs_attrs, + .port_probe = edge_port_probe, + .port_remove = edge_port_remove, .ioctl = edge_ioctl, .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 20a132ec39e..4264821a3b3 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) return 0; } -/* fake probe - only to allocate data structures */ -static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id) +static int ipw_attach(struct usb_serial *serial) { struct usb_wwan_intf_private *data; @@ -303,9 +302,9 @@ static struct usb_serial_driver ipw_device = { .num_ports = 1, .open = ipw_open, .close = ipw_close, - .probe = ipw_probe, - .attach = usb_wwan_startup, + .attach = ipw_attach, .release = ipw_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, .dtr_rts = ipw_dtr_rts, .write = usb_wwan_write, diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 01da3ea36e8..cd5533e81de 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -53,6 +53,8 @@ static int iuu_cardout; static bool xmas; static int vcc_default = 5; +static int iuu_create_sysfs_attrs(struct usb_serial_port *port); +static int iuu_remove_sysfs_attrs(struct usb_serial_port *port); static void read_rxcmd_callback(struct urb *urb); struct iuu_private { @@ -72,63 +74,55 @@ struct iuu_private { u32 clk; }; - -static void iuu_free_buf(struct iuu_private *priv) -{ - kfree(priv->buf); - kfree(priv->writebuf); -} - -static int iuu_alloc_buf(struct usb_serial *serial, struct iuu_private *priv) -{ - priv->buf = kzalloc(256, GFP_KERNEL); - priv->writebuf = kzalloc(256, GFP_KERNEL); - if (!priv->buf || !priv->writebuf) { - iuu_free_buf(priv); - dev_dbg(&serial->dev->dev, "%s problem allocation buffer\n", __func__); - return -ENOMEM; - } - dev_dbg(&serial->dev->dev, "%s - Privates buffers allocation success\n", __func__); - return 0; -} - -static int iuu_startup(struct usb_serial *serial) +static int iuu_port_probe(struct usb_serial_port *port) { struct iuu_private *priv; + int ret; priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); - dev_dbg(&serial->dev->dev, "%s- priv allocation success\n", __func__); if (!priv) return -ENOMEM; - if (iuu_alloc_buf(serial, priv)) { + + priv->buf = kzalloc(256, GFP_KERNEL); + if (!priv->buf) { + kfree(priv); + return -ENOMEM; + } + + priv->writebuf = kzalloc(256, GFP_KERNEL); + if (!priv->writebuf) { + kfree(priv->buf); kfree(priv); return -ENOMEM; } + priv->vcc = vcc_default; spin_lock_init(&priv->lock); init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[0], priv); + + usb_set_serial_port_data(port, priv); + + ret = iuu_create_sysfs_attrs(port); + if (ret) { + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); + return ret; + } + return 0; } -/* Release function */ -static void iuu_release(struct usb_serial *serial) +static int iuu_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct iuu_private *priv = usb_get_serial_port_data(port); - if (!port) - return; - if (priv) { - iuu_free_buf(priv); - dev_dbg(&port->dev, "%s - I will free all\n", __func__); - usb_set_serial_port_data(port, NULL); - - dev_dbg(&port->dev, "%s - priv is not anymore in port structure\n", __func__); - kfree(priv); + iuu_remove_sysfs_attrs(port); + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); - dev_dbg(&port->dev, "%s priv is now kfree\n", __func__); - } + return 0; } static int iuu_tiocmset(struct tty_struct *tty, @@ -1215,8 +1209,6 @@ static struct usb_serial_driver iuu_device = { .num_ports = 1, .bulk_in_size = 512, .bulk_out_size = 512, - .port_probe = iuu_create_sysfs_attrs, - .port_remove = iuu_remove_sysfs_attrs, .open = iuu_open, .close = iuu_close, .write = iuu_uart_write, @@ -1225,8 +1217,8 @@ static struct usb_serial_driver iuu_device = { .tiocmset = iuu_tiocmset, .set_termios = iuu_set_termios, .init_termios = iuu_init_termios, - .attach = iuu_startup, - .release = iuu_release, + .port_probe = iuu_port_probe, + .port_remove = iuu_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 29c943d737d..cff8dd5b462 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1374,13 +1374,9 @@ static struct callbacks { data in device_details */ static void keyspan_setup_urbs(struct usb_serial *serial) { - int i, j; struct keyspan_serial_private *s_priv; const struct keyspan_device_details *d_details; - struct usb_serial_port *port; - struct keyspan_port_private *p_priv; struct callbacks *cback; - int endp; s_priv = usb_get_serial_data(serial); d_details = s_priv->device_details; @@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial) (serial, d_details->glocont_endpoint, USB_DIR_OUT, serial, s_priv->glocont_buf, GLOCONT_BUFLEN, cback->glocont_callback); - - /* Setup endpoints for each port specific thing */ - for (i = 0; i < d_details->num_ports; i++) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - - /* Do indat endpoints first, once for each flip */ - endp = d_details->indat_endpoints[i]; - for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { - p_priv->in_urbs[j] = keyspan_setup_urb - (serial, endp, USB_DIR_IN, port, - p_priv->in_buffer[j], 64, - cback->indat_callback); - } - for (; j < 2; ++j) - p_priv->in_urbs[j] = NULL; - - /* outdat endpoints also have flip */ - endp = d_details->outdat_endpoints[i]; - for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { - p_priv->out_urbs[j] = keyspan_setup_urb - (serial, endp, USB_DIR_OUT, port, - p_priv->out_buffer[j], 64, - cback->outdat_callback); - } - for (; j < 2; ++j) - p_priv->out_urbs[j] = NULL; - - /* inack endpoint */ - p_priv->inack_urb = keyspan_setup_urb - (serial, d_details->inack_endpoints[i], USB_DIR_IN, - port, p_priv->inack_buffer, 1, cback->inack_callback); - - /* outcont endpoint */ - p_priv->outcont_urb = keyspan_setup_urb - (serial, d_details->outcont_endpoints[i], USB_DIR_OUT, - port, p_priv->outcont_buffer, 64, - cback->outcont_callback); - } } /* usa19 function doesn't require prescaler */ @@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) static int keyspan_startup(struct usb_serial *serial) { int i, err; - struct usb_serial_port *port; struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) @@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial) s_priv->device_details = d_details; usb_set_serial_data(serial, s_priv); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - p_priv = kzalloc(sizeof(struct keyspan_port_private), - GFP_KERNEL); - if (!p_priv) { - dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i); - return 1; - } - p_priv->device_details = d_details; - usb_set_serial_port_data(port, p_priv); - } - keyspan_setup_urbs(serial); if (s_priv->instat_urb != NULL) { @@ -2463,59 +2405,111 @@ static int keyspan_startup(struct usb_serial *serial) static void keyspan_disconnect(struct usb_serial *serial) { - int i, j; - struct usb_serial_port *port; - struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; + struct keyspan_serial_private *s_priv; s_priv = usb_get_serial_data(serial); - /* Stop reading/writing urbs */ stop_urb(s_priv->instat_urb); stop_urb(s_priv->glocont_urb); stop_urb(s_priv->indat_urb); - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - stop_urb(p_priv->inack_urb); - stop_urb(p_priv->outcont_urb); - for (j = 0; j < 2; j++) { - stop_urb(p_priv->in_urbs[j]); - stop_urb(p_priv->out_urbs[j]); - } - } +} + +static void keyspan_release(struct usb_serial *serial) +{ + struct keyspan_serial_private *s_priv; + + s_priv = usb_get_serial_data(serial); - /* Now free them */ usb_free_urb(s_priv->instat_urb); usb_free_urb(s_priv->indat_urb); usb_free_urb(s_priv->glocont_urb); - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - p_priv = usb_get_serial_port_data(port); - usb_free_urb(p_priv->inack_urb); - usb_free_urb(p_priv->outcont_urb); - for (j = 0; j < 2; j++) { - usb_free_urb(p_priv->in_urbs[j]); - usb_free_urb(p_priv->out_urbs[j]); - } - } + + kfree(s_priv); } -static void keyspan_release(struct usb_serial *serial) +static int keyspan_port_probe(struct usb_serial_port *port) { - int i; - struct usb_serial_port *port; - struct keyspan_serial_private *s_priv; + struct usb_serial *serial = port->serial; + struct keyspan_serial_private *s_priv; + struct keyspan_port_private *p_priv; + const struct keyspan_device_details *d_details; + struct callbacks *cback; + int endp; + int port_num; + int i; s_priv = usb_get_serial_data(serial); + d_details = s_priv->device_details; - kfree(s_priv); + p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL); + if (!p_priv) + return -ENOMEM; - /* 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)); + p_priv->device_details = d_details; + + /* Setup values for the various callback routines */ + cback = &keyspan_callbacks[d_details->msg_format]; + + port_num = port->number - port->serial->minor; + + /* Do indat endpoints first, once for each flip */ + endp = d_details->indat_endpoints[port_num]; + for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) { + p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp, + USB_DIR_IN, port, + p_priv->in_buffer[i], 64, + cback->indat_callback); + } + /* outdat endpoints also have flip */ + endp = d_details->outdat_endpoints[port_num]; + for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) { + p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp, + USB_DIR_OUT, port, + p_priv->out_buffer[i], 64, + cback->outdat_callback); + } + /* inack endpoint */ + p_priv->inack_urb = keyspan_setup_urb(serial, + d_details->inack_endpoints[port_num], + USB_DIR_IN, port, + p_priv->inack_buffer, 1, + cback->inack_callback); + /* outcont endpoint */ + p_priv->outcont_urb = keyspan_setup_urb(serial, + d_details->outcont_endpoints[port_num], + USB_DIR_OUT, port, + p_priv->outcont_buffer, 64, + cback->outcont_callback); + + usb_set_serial_port_data(port, p_priv); + + return 0; +} + +static int keyspan_port_remove(struct usb_serial_port *port) +{ + struct keyspan_port_private *p_priv; + int i; + + p_priv = usb_get_serial_port_data(port); + + stop_urb(p_priv->inack_urb); + stop_urb(p_priv->outcont_urb); + for (i = 0; i < 2; i++) { + stop_urb(p_priv->in_urbs[i]); + stop_urb(p_priv->out_urbs[i]); + } + + usb_free_urb(p_priv->inack_urb); + usb_free_urb(p_priv->outcont_urb); + for (i = 0; i < 2; i++) { + usb_free_urb(p_priv->in_urbs[i]); + usb_free_urb(p_priv->out_urbs[i]); } + + kfree(p_priv); + + return 0; } MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 0a8a40b5711..0273dda303a 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -42,6 +42,8 @@ static void keyspan_dtr_rts (struct usb_serial_port *port, int on); static int keyspan_startup (struct usb_serial *serial); static void keyspan_disconnect (struct usb_serial *serial); static void keyspan_release (struct usb_serial *serial); +static int keyspan_port_probe(struct usb_serial_port *port); +static int keyspan_port_remove(struct usb_serial_port *port); static int keyspan_write_room (struct tty_struct *tty); static int keyspan_write (struct tty_struct *tty, @@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver keyspan_2port_device = { @@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver keyspan_4port_device = { @@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = { .attach = keyspan_startup, .disconnect = keyspan_disconnect, .release = keyspan_release, + .port_probe = keyspan_port_probe, + .port_remove = keyspan_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index ca43ecb4a2b..bb87e29c4ac 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -713,29 +713,33 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); #endif -static int keyspan_pda_startup(struct usb_serial *serial) +static int keyspan_pda_port_probe(struct usb_serial_port *port) { struct keyspan_pda_private *priv; - /* allocate the private data structures for all ports. Well, for all - one ports. */ - priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL); if (!priv) - return 1; /* error */ - usb_set_serial_port_data(serial->port[0], priv); - init_waitqueue_head(&serial->port[0]->write_wait); + return -ENOMEM; + INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); - priv->serial = serial; - priv->port = serial->port[0]; + priv->serial = port->serial; + priv->port = port; + + usb_set_serial_port_data(port, priv); + return 0; } -static void keyspan_pda_release(struct usb_serial *serial) +static int keyspan_pda_port_remove(struct usb_serial_port *port) { - kfree(usb_get_serial_port_data(serial->port[0])); + struct keyspan_pda_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } #ifdef KEYSPAN @@ -786,8 +790,8 @@ static struct usb_serial_driver keyspan_pda_device = { .break_ctl = keyspan_pda_break_ctl, .tiocmget = keyspan_pda_tiocmget, .tiocmset = keyspan_pda_tiocmset, - .attach = keyspan_pda_startup, - .release = keyspan_pda_release, + .port_probe = keyspan_pda_port_probe, + .port_remove = keyspan_pda_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 3f6d7376c02..1f4517864cd 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -60,8 +60,8 @@ /* * Function prototypes */ -static int klsi_105_startup(struct usb_serial *serial); -static void klsi_105_release(struct usb_serial *serial); +static int klsi_105_port_probe(struct usb_serial_port *port); +static int klsi_105_port_remove(struct usb_serial_port *port); static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port); static void klsi_105_close(struct usb_serial_port *port); static void klsi_105_set_termios(struct tty_struct *tty, @@ -99,8 +99,8 @@ static struct usb_serial_driver kl5kusb105d_device = { /*.break_ctl = klsi_105_break_ctl,*/ .tiocmget = klsi_105_tiocmget, .tiocmset = klsi_105_tiocmset, - .attach = klsi_105_startup, - .release = klsi_105_release, + .port_probe = klsi_105_port_probe, + .port_remove = klsi_105_port_remove, .throttle = usb_serial_generic_throttle, .unthrottle = usb_serial_generic_unthrottle, .process_read_urb = klsi_105_process_read_urb, @@ -223,60 +223,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, * Driver's tty interface functions */ -static int klsi_105_startup(struct usb_serial *serial) +static int klsi_105_port_probe(struct usb_serial_port *port) { struct klsi_105_private *priv; - int i; - /* check if we support the product id (see keyspan.c) - * FIXME - */ + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - /* allocate the private data structure */ - for (i = 0; i < serial->num_ports; i++) { - priv = kmalloc(sizeof(struct klsi_105_private), - GFP_KERNEL); - if (!priv) { - dev_dbg(&serial->interface->dev, - "%s - kmalloc for klsi_105_private failed.\n", - __func__); - i--; - goto err_cleanup; - } - /* set initial values for control structures */ - priv->cfg.pktlen = 5; - priv->cfg.baudrate = kl5kusb105a_sio_b9600; - priv->cfg.databits = kl5kusb105a_dtb_8; - priv->cfg.unknown1 = 0; - priv->cfg.unknown2 = 1; + /* set initial values for control structures */ + priv->cfg.pktlen = 5; + priv->cfg.baudrate = kl5kusb105a_sio_b9600; + priv->cfg.databits = kl5kusb105a_dtb_8; + priv->cfg.unknown1 = 0; + priv->cfg.unknown2 = 1; - priv->line_state = 0; + priv->line_state = 0; - usb_set_serial_port_data(serial->port[i], priv); + spin_lock_init(&priv->lock); - spin_lock_init(&priv->lock); + /* priv->termios is left uninitialized until port opening */ - /* priv->termios is left uninitialized until port opening */ - init_waitqueue_head(&serial->port[i]->write_wait); - } + usb_set_serial_port_data(port, priv); return 0; - -err_cleanup: - for (; i >= 0; i--) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; } -static void klsi_105_release(struct usb_serial *serial) +static int klsi_105_port_remove(struct usb_serial_port *port) { - int i; + struct klsi_105_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + return 0; } static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 5c4d2fbd4e1..c9ca7a5b12e 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -54,8 +54,8 @@ /* Function prototypes */ -static int kobil_startup(struct usb_serial *serial); -static void kobil_release(struct usb_serial *serial); +static int kobil_port_probe(struct usb_serial_port *probe); +static int kobil_port_remove(struct usb_serial_port *probe); static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); static void kobil_close(struct usb_serial_port *port); static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -89,8 +89,8 @@ static struct usb_serial_driver kobil_device = { .description = "KOBIL USB smart card terminal", .id_table = id_table, .num_ports = 1, - .attach = kobil_startup, - .release = kobil_release, + .port_probe = kobil_port_probe, + .port_remove = kobil_port_remove, .ioctl = kobil_ioctl, .set_termios = kobil_set_termios, .init_termios = kobil_init_termios, @@ -117,9 +117,10 @@ struct kobil_private { }; -static int kobil_startup(struct usb_serial *serial) +static int kobil_port_probe(struct usb_serial_port *port) { int i; + struct usb_serial *serial = port->serial; struct kobil_private *priv; struct usb_device *pdev; struct usb_host_config *actconfig; @@ -149,7 +150,7 @@ static int kobil_startup(struct usb_serial *serial) dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n"); break; } - usb_set_serial_port_data(serial->port[0], priv); + usb_set_serial_port_data(port, priv); /* search for the necessary endpoints */ pdev = serial->dev; @@ -179,12 +180,14 @@ static int kobil_startup(struct usb_serial *serial) } -static void kobil_release(struct usb_serial *serial) +static int kobil_port_remove(struct usb_serial_port *port) { - int i; + struct kobil_private *priv; - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static void kobil_init_termios(struct tty_struct *tty) diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index f3947712e13..8a208100410 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -49,7 +49,8 @@ * Function prototypes */ static int mct_u232_startup(struct usb_serial *serial); -static void mct_u232_release(struct usb_serial *serial); +static int mct_u232_port_probe(struct usb_serial_port *port); +static int mct_u232_port_remove(struct usb_serial_port *remove); static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port); static void mct_u232_close(struct usb_serial_port *port); static void mct_u232_dtr_rts(struct usb_serial_port *port, int on); @@ -99,7 +100,8 @@ static struct usb_serial_driver mct_u232_device = { .tiocmget = mct_u232_tiocmget, .tiocmset = mct_u232_tiocmset, .attach = mct_u232_startup, - .release = mct_u232_release, + .port_probe = mct_u232_port_probe, + .port_remove = mct_u232_port_remove, .ioctl = mct_u232_ioctl, .get_icount = mct_u232_get_icount, }; @@ -388,18 +390,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port, static int mct_u232_startup(struct usb_serial *serial) { - struct mct_u232_private *priv; struct usb_serial_port *port, *rport; - priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL); - if (!priv) - return -ENOMEM; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->msr_wait); - usb_set_serial_port_data(serial->port[0], priv); - - init_waitqueue_head(&serial->port[0]->write_wait); - /* Puh, that's dirty */ port = serial->port[0]; rport = serial->port[1]; @@ -412,18 +404,31 @@ static int mct_u232_startup(struct usb_serial *serial) return 0; } /* mct_u232_startup */ +static int mct_u232_port_probe(struct usb_serial_port *port) +{ + struct mct_u232_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->msr_wait); + + usb_set_serial_port_data(port, priv); -static void mct_u232_release(struct usb_serial *serial) + return 0; +} + +static int mct_u232_port_remove(struct usb_serial_port *port) { struct mct_u232_private *priv; - int i; - for (i = 0; i < serial->num_ports; ++i) { - /* My special items, the standard routines free my urbs */ - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } -} /* mct_u232_release */ + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; +} static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) { @@ -515,12 +520,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) static void mct_u232_close(struct usb_serial_port *port) { - if (port->serial->dev) { - /* shutdown our urbs */ - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - usb_kill_urb(port->interrupt_in_urb); - } + /* + * Must kill the read urb as it is actually an interrupt urb, which + * generic close thus fails to kill. + */ + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); + + usb_serial_generic_close(port); } /* mct_u232_close */ diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 0b257ddffbd..6f29c74eb76 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -179,16 +179,13 @@ static void metrousb_cleanup(struct usb_serial_port *port) { dev_dbg(&port->dev, "%s\n", __func__); - if (port->serial->dev) { - /* Shutdown any interrupt in urbs. */ - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_kill_urb(port->interrupt_in_urb); - } - - /* Send deactivate cmd to device */ + usb_unlink_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); + + mutex_lock(&port->serial->disc_mutex); + if (!port->serial->disconnected) metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); - } + mutex_unlock(&port->serial->disc_mutex); } static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -271,51 +268,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr return retval; } -static void metrousb_shutdown(struct usb_serial *serial) +static int metrousb_port_probe(struct usb_serial_port *port) { - int i = 0; + struct metrousb_private *metro_priv; - dev_dbg(&serial->dev->dev, "%s\n", __func__); + metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL); + if (!metro_priv) + return -ENOMEM; - /* Stop reading and writing on all ports. */ - for (i = 0; i < serial->num_ports; ++i) { - /* Close any open urbs. */ - metrousb_cleanup(serial->port[i]); + spin_lock_init(&metro_priv->lock); - /* Free memory. */ - kfree(usb_get_serial_port_data(serial->port[i])); - usb_set_serial_port_data(serial->port[i], NULL); + usb_set_serial_port_data(port, metro_priv); - dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n", - __func__, serial->port[i]->number); - } + return 0; } -static int metrousb_startup(struct usb_serial *serial) +static int metrousb_port_remove(struct usb_serial_port *port) { struct metrousb_private *metro_priv; - struct usb_serial_port *port; - int i = 0; - dev_dbg(&serial->dev->dev, "%s\n", __func__); - - /* Loop through the serial ports setting up the private structures. - * Currently we only use one port. */ - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - - /* Declare memory. */ - metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL); - if (!metro_priv) - return -ENOMEM; - - /* Initialize memory. */ - spin_lock_init(&metro_priv->lock); - usb_set_serial_port_data(port, metro_priv); - - dev_dbg(&serial->dev->dev, "%s - port number=%d\n ", - __func__, port->number); - } + metro_priv = usb_get_serial_port_data(port); + kfree(metro_priv); return 0; } @@ -414,8 +387,8 @@ static struct usb_serial_driver metrousb_device = { .close = metrousb_cleanup, .read_int_callback = metrousb_read_int_callback, .write_int_callback = metrousb_write_int_callback, - .attach = metrousb_startup, - .release = metrousb_shutdown, + .port_probe = metrousb_port_probe, + .port_remove = metrousb_port_remove, .throttle = metrousb_throttle, .unthrottle = metrousb_unthrottle, .tiocmget = metrousb_tiocmget, diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 1bf1ad06666..75267421aad 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1966,9 +1966,7 @@ static int mos7720_ioctl(struct tty_struct *tty, static int mos7720_startup(struct usb_serial *serial) { - struct moschip_port *mos7720_port; struct usb_device *dev; - int i; char data; u16 product; int ret_val; @@ -1999,29 +1997,6 @@ static int mos7720_startup(struct usb_serial *serial) serial->port[1]->interrupt_in_buffer = NULL; } - - /* set up serial port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); - if (mos7720_port == NULL) { - dev_err(&dev->dev, "%s - Out of memory\n", __func__); - return -ENOMEM; - } - - /* Initialize all port interrupt end point to port 0 int - * endpoint. Our device has only one interrupt endpoint - * common to all ports */ - serial->port[i]->interrupt_in_endpointAddress = - serial->port[0]->interrupt_in_endpointAddress; - - mos7720_port->port = serial->port[i]; - usb_set_serial_port_data(serial->port[i], mos7720_port); - - dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number); - dev_dbg(&dev->dev, "serial number is %d\n", serial->minor); - } - - /* setting configuration feature to one */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); @@ -2049,8 +2024,6 @@ static int mos7720_startup(struct usb_serial *serial) static void mos7720_release(struct usb_serial *serial) { - int i; - #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT /* close the parallel port */ @@ -2089,9 +2062,36 @@ static void mos7720_release(struct usb_serial *serial) kref_put(&mos_parport->ref_count, destroy_mos_parport); } #endif - /* free private structure allocated for serial port */ - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); +} + +static int mos7720_port_probe(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + + mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL); + if (!mos7720_port) + return -ENOMEM; + + /* Initialize all port interrupt end point to port 0 int endpoint. + * Our device has only one interrupt endpoint common to all ports. + */ + port->interrupt_in_endpointAddress = + port->serial->port[0]->interrupt_in_endpointAddress; + mos7720_port->port = port; + + usb_set_serial_port_data(port, mos7720_port); + + return 0; +} + +static int mos7720_port_remove(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + + mos7720_port = usb_get_serial_port_data(port); + kfree(mos7720_port); + + return 0; } static struct usb_serial_driver moschip7720_2port_driver = { @@ -2109,6 +2109,8 @@ static struct usb_serial_driver moschip7720_2port_driver = { .probe = mos77xx_probe, .attach = mos7720_startup, .release = mos7720_release, + .port_probe = mos7720_port_probe, + .port_remove = mos7720_port_remove, .ioctl = mos7720_ioctl, .tiocmget = mos7720_tiocmget, .tiocmset = mos7720_tiocmset, diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d6d4eeca8c6..1cf3375ec1a 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -218,12 +218,10 @@ struct moschip_port { int port_num; /*Actual port number in the device(1,2,etc) */ struct urb *write_urb; /* write URB for this port */ struct urb *read_urb; /* read URB for this port */ - struct urb *int_urb; __u8 shadowLCR; /* last LCR value received */ __u8 shadowMCR; /* last MCR value received */ char open; char open_ports; - char zombie; wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ int delta_msr_cond; @@ -478,7 +476,6 @@ static void mos7840_control_callback(struct urb *urb) struct moschip_port *mos7840_port; struct device *dev = &urb->dev->dev; __u8 regval = 0x0; - int result = 0; int status = urb->status; mos7840_port = urb->context; @@ -495,7 +492,7 @@ static void mos7840_control_callback(struct urb *urb) return; default: dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); - goto exit; + return; } dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); @@ -508,16 +505,6 @@ static void mos7840_control_callback(struct urb *urb) mos7840_handle_new_msr(mos7840_port, regval); else if (mos7840_port->MsrLsr == 1) mos7840_handle_new_lsr(mos7840_port, regval); - -exit: - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) - result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); - spin_unlock(&mos7840_port->pool_lock); - if (result) { - dev_err(dev, "%s - Error %d submitting interrupt urb\n", - __func__, result); - } } static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, @@ -686,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb) wreg = MODEM_STATUS_REGISTER; break; } - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) { - rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); - } else { - spin_unlock(&mos7840_port->pool_lock); - return; - } - spin_unlock(&mos7840_port->pool_lock); + rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); } } } @@ -2347,309 +2327,249 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) return mos7840_num_ports; } -/**************************************************************************** - * mos7840_startup - ****************************************************************************/ - -static int mos7840_startup(struct usb_serial *serial) +static int mos7840_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct moschip_port *mos7840_port; - struct usb_device *dev; - int i, status; + int status; + int pnum; __u16 Data; - dev = serial->dev; - /* we set up the pointers to the endpoints in the mos7840_open * * function, as the structures aren't created yet. */ - /* set up port private structures */ - for (i = 0; i < serial->num_ports; ++i) { - dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i); - mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); - if (mos7840_port == NULL) { - dev_err(&dev->dev, "%s - Out of memory\n", __func__); - status = -ENOMEM; - i--; /* don't follow NULL pointer cleaning up */ - goto error; - } - - /* Initialize all port interrupt end point to port 0 int - * endpoint. Our device has only one interrupt end point - * common to all port */ - - mos7840_port->port = serial->port[i]; - mos7840_set_port_private(serial->port[i], mos7840_port); - spin_lock_init(&mos7840_port->pool_lock); - - /* minor is not initialised until later by - * usb-serial.c:get_free_serial() and cannot therefore be used - * to index device instances */ - mos7840_port->port_num = i + 1; - dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number); - dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor); - dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); - dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor); - - if (mos7840_port->port_num == 1) { - mos7840_port->SpRegOffset = 0x0; - mos7840_port->ControlRegOffset = 0x1; - mos7840_port->DcrRegOffset = 0x4; - } else if ((mos7840_port->port_num == 2) - && (serial->num_ports == 4)) { - mos7840_port->SpRegOffset = 0x8; - mos7840_port->ControlRegOffset = 0x9; - mos7840_port->DcrRegOffset = 0x16; - } else if ((mos7840_port->port_num == 2) - && (serial->num_ports == 2)) { - mos7840_port->SpRegOffset = 0xa; - mos7840_port->ControlRegOffset = 0xb; - mos7840_port->DcrRegOffset = 0x19; - } else if ((mos7840_port->port_num == 3) - && (serial->num_ports == 4)) { - mos7840_port->SpRegOffset = 0xa; - mos7840_port->ControlRegOffset = 0xb; - mos7840_port->DcrRegOffset = 0x19; - } else if ((mos7840_port->port_num == 4) - && (serial->num_ports == 4)) { - mos7840_port->SpRegOffset = 0xc; - mos7840_port->ControlRegOffset = 0xd; - mos7840_port->DcrRegOffset = 0x1c; - } - mos7840_dump_serial_port(serial->port[i], mos7840_port); - mos7840_set_port_private(serial->port[i], mos7840_port); + pnum = port->number - serial->minor; - /* enable rx_disable bit in control register */ - status = mos7840_get_reg_sync(serial->port[i], - mos7840_port->ControlRegOffset, &Data); - if (status < 0) { - dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); - Data |= 0x08; /* setting driver done bit */ - Data |= 0x04; /* sp1_bit to have cts change reflect in - modem status reg */ - - /* Data |= 0x20; //rx_disable bit */ - status = mos7840_set_reg_sync(serial->port[i], - mos7840_port->ControlRegOffset, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status); + dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum); + mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); + if (mos7840_port == NULL) { + dev_err(&port->dev, "%s - Out of memory\n", __func__); + return -ENOMEM; + } - /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 - and 0x24 in DCR3 */ - Data = 0x01; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (mos7840_port->DcrRegOffset + 0), Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status); + /* Initialize all port interrupt end point to port 0 int + * endpoint. Our device has only one interrupt end point + * common to all port */ + + mos7840_port->port = port; + mos7840_set_port_private(port, mos7840_port); + spin_lock_init(&mos7840_port->pool_lock); + + /* minor is not initialised until later by + * usb-serial.c:get_free_serial() and cannot therefore be used + * to index device instances */ + mos7840_port->port_num = pnum + 1; + dev_dbg(&port->dev, "port->number = %d\n", port->number); + dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); + dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); + dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); + + if (mos7840_port->port_num == 1) { + mos7840_port->SpRegOffset = 0x0; + mos7840_port->ControlRegOffset = 0x1; + mos7840_port->DcrRegOffset = 0x4; + } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) { + mos7840_port->SpRegOffset = 0x8; + mos7840_port->ControlRegOffset = 0x9; + mos7840_port->DcrRegOffset = 0x16; + } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) { + mos7840_port->SpRegOffset = 0xa; + mos7840_port->ControlRegOffset = 0xb; + mos7840_port->DcrRegOffset = 0x19; + } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) { + mos7840_port->SpRegOffset = 0xa; + mos7840_port->ControlRegOffset = 0xb; + mos7840_port->DcrRegOffset = 0x19; + } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) { + mos7840_port->SpRegOffset = 0xc; + mos7840_port->ControlRegOffset = 0xd; + mos7840_port->DcrRegOffset = 0x1c; + } + mos7840_dump_serial_port(port, mos7840_port); + mos7840_set_port_private(port, mos7840_port); + + /* enable rx_disable bit in control register */ + status = mos7840_get_reg_sync(port, + mos7840_port->ControlRegOffset, &Data); + if (status < 0) { + dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); + Data |= 0x08; /* setting driver done bit */ + Data |= 0x04; /* sp1_bit to have cts change reflect in + modem status reg */ - Data = 0x05; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (mos7840_port->DcrRegOffset + 1), Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status); + /* Data |= 0x20; //rx_disable bit */ + status = mos7840_set_reg_sync(port, + mos7840_port->ControlRegOffset, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status); - Data = 0x24; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (mos7840_port->DcrRegOffset + 2), Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status); + /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 + and 0x24 in DCR3 */ + Data = 0x01; + status = mos7840_set_reg_sync(port, + (__u16) (mos7840_port->DcrRegOffset + 0), Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status); - /* write values in clkstart0x0 and clkmulti 0x20 */ - Data = 0x0; - status = mos7840_set_reg_sync(serial->port[i], - CLK_START_VALUE_REGISTER, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); + Data = 0x05; + status = mos7840_set_reg_sync(port, + (__u16) (mos7840_port->DcrRegOffset + 1), Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status); - Data = 0x20; - status = mos7840_set_reg_sync(serial->port[i], - CLK_MULTI_REGISTER, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); - goto error; - } else - dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); + Data = 0x24; + status = mos7840_set_reg_sync(port, + (__u16) (mos7840_port->DcrRegOffset + 2), Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status); - /* write value 0x0 to scratchpad register */ - Data = 0x00; - status = mos7840_set_uart_reg(serial->port[i], - SCRATCH_PAD_REGISTER, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); - break; - } else - dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); + /* write values in clkstart0x0 and clkmulti 0x20 */ + Data = 0x0; + status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); - /* Zero Length flag register */ - if ((mos7840_port->port_num != 1) - && (serial->num_ports == 2)) { + Data = 0x20; + status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); + goto error; + } else + dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); - Data = 0xff; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (ZLP_REG1 + - ((__u16)mos7840_port->port_num)), Data); - dev_dbg(&dev->dev, "ZLIP offset %x\n", + /* write value 0x0 to scratchpad register */ + Data = 0x00; + status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); + goto out; + } else + dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); + + /* Zero Length flag register */ + if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) { + Data = 0xff; + status = mos7840_set_reg_sync(port, + (__u16) (ZLP_REG1 + + ((__u16)mos7840_port->port_num)), Data); + dev_dbg(&port->dev, "ZLIP offset %x\n", (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); - if (status < 0) { - dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status); - break; - } else - dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status); - } else { - Data = 0xff; - status = mos7840_set_reg_sync(serial->port[i], - (__u16) (ZLP_REG1 + - ((__u16)mos7840_port->port_num) - 0x1), Data); - dev_dbg(&dev->dev, "ZLIP offset %x\n", + if (status < 0) { + dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status); + goto out; + } else + dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status); + } else { + Data = 0xff; + status = mos7840_set_reg_sync(port, + (__u16) (ZLP_REG1 + + ((__u16)mos7840_port->port_num) - 0x1), Data); + dev_dbg(&port->dev, "ZLIP offset %x\n", (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); - if (status < 0) { - dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status); - break; - } else - dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status); + if (status < 0) { + dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status); + goto out; + } else + dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status); - } - mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); - mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); - mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), - GFP_KERNEL); - if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || - !mos7840_port->dr) { - status = -ENOMEM; - goto error; - } + } + mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); + mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL); + mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest), + GFP_KERNEL); + if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf || + !mos7840_port->dr) { + status = -ENOMEM; + goto error; + } - mos7840_port->has_led = false; + mos7840_port->has_led = false; - /* Initialize LED timers */ - if (device_type == MOSCHIP_DEVICE_ID_7810) { - mos7840_port->has_led = true; + /* Initialize LED timers */ + if (device_type == MOSCHIP_DEVICE_ID_7810) { + mos7840_port->has_led = true; - init_timer(&mos7840_port->led_timer1); - mos7840_port->led_timer1.function = mos7840_led_off; - mos7840_port->led_timer1.expires = - jiffies + msecs_to_jiffies(LED_ON_MS); - mos7840_port->led_timer1.data = - (unsigned long)mos7840_port; + init_timer(&mos7840_port->led_timer1); + mos7840_port->led_timer1.function = mos7840_led_off; + mos7840_port->led_timer1.expires = + jiffies + msecs_to_jiffies(LED_ON_MS); + mos7840_port->led_timer1.data = (unsigned long)mos7840_port; - init_timer(&mos7840_port->led_timer2); - mos7840_port->led_timer2.function = - mos7840_led_flag_off; - mos7840_port->led_timer2.expires = - jiffies + msecs_to_jiffies(LED_OFF_MS); - mos7840_port->led_timer2.data = - (unsigned long)mos7840_port; + init_timer(&mos7840_port->led_timer2); + mos7840_port->led_timer2.function = mos7840_led_flag_off; + mos7840_port->led_timer2.expires = + jiffies + msecs_to_jiffies(LED_OFF_MS); + mos7840_port->led_timer2.data = (unsigned long)mos7840_port; - mos7840_port->led_flag = false; + mos7840_port->led_flag = false; - /* Turn off LED */ - mos7840_set_led_sync(serial->port[i], - MODEM_CONTROL_REGISTER, 0x0300); - } + /* Turn off LED */ + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); } +out: + if (pnum == serial->num_ports - 1) { + /* Zero Length flag enable */ + Data = 0x0f; + status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); + if (status < 0) { + dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); + goto error; + } else + dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status); - /* Zero Length flag enable */ - Data = 0x0f; - status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); - if (status < 0) { - dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); - goto error; - } else - dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status); - - /* setting configuration feature to one */ - usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT); + /* setting configuration feature to one */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + 0x03, 0x00, 0x01, 0x00, NULL, 0x00, + MOS_WDR_TIMEOUT); + } return 0; error: - for (/* nothing */; i >= 0; i--) { - mos7840_port = mos7840_get_port_private(serial->port[i]); + kfree(mos7840_port->dr); + kfree(mos7840_port->ctrl_buf); + usb_free_urb(mos7840_port->control_urb); + kfree(mos7840_port); - kfree(mos7840_port->dr); - kfree(mos7840_port->ctrl_buf); - usb_free_urb(mos7840_port->control_urb); - kfree(mos7840_port); - serial->port[i] = NULL; - } return status; } -/**************************************************************************** - * mos7840_disconnect - * This function is called whenever the device is removed from the usb bus. - ****************************************************************************/ - -static void mos7840_disconnect(struct usb_serial *serial) +static int mos7840_port_remove(struct usb_serial_port *port) { - int i; - unsigned long flags; struct moschip_port *mos7840_port; - /* check for the ports to be closed,close the ports and disconnect */ + mos7840_port = mos7840_get_port_private(port); - /* free private structure allocated for serial port * - * stop reads and writes on all ports */ + if (mos7840_port->has_led) { + /* Turn off LED */ + mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300); - for (i = 0; i < serial->num_ports; ++i) { - mos7840_port = mos7840_get_port_private(serial->port[i]); - if (mos7840_port) { - spin_lock_irqsave(&mos7840_port->pool_lock, flags); - mos7840_port->zombie = 1; - spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); - usb_kill_urb(mos7840_port->control_urb); - } + del_timer_sync(&mos7840_port->led_timer1); + del_timer_sync(&mos7840_port->led_timer2); } -} - -/**************************************************************************** - * mos7840_release - * This function is called when the usb_serial structure is freed. - ****************************************************************************/ - -static void mos7840_release(struct usb_serial *serial) -{ - int i; - struct moschip_port *mos7840_port; - - /* check for the ports to be closed,close the ports and disconnect */ + usb_kill_urb(mos7840_port->control_urb); + usb_free_urb(mos7840_port->control_urb); + kfree(mos7840_port->ctrl_buf); + kfree(mos7840_port->dr); + kfree(mos7840_port); - /* free private structure allocated for serial port * - * stop reads and writes on all ports */ - - for (i = 0; i < serial->num_ports; ++i) { - mos7840_port = mos7840_get_port_private(serial->port[i]); - if (mos7840_port) { - if (mos7840_port->has_led) { - /* Turn off LED */ - mos7840_set_led_sync(mos7840_port->port, - MODEM_CONTROL_REGISTER, 0x0300); - - del_timer_sync(&mos7840_port->led_timer1); - del_timer_sync(&mos7840_port->led_timer2); - } - kfree(mos7840_port->ctrl_buf); - kfree(mos7840_port->dr); - kfree(mos7840_port); - } - } + return 0; } static struct usb_serial_driver moschip7840_4port_device = { @@ -2677,9 +2597,8 @@ static struct usb_serial_driver moschip7840_4port_device = { .tiocmget = mos7840_tiocmget, .tiocmset = mos7840_tiocmset, .get_icount = mos7840_get_icount, - .attach = mos7840_startup, - .disconnect = mos7840_disconnect, - .release = mos7840_release, + .port_probe = mos7840_port_probe, + .port_remove = mos7840_port_remove, .read_bulk_callback = mos7840_bulk_in_callback, .read_int_callback = mos7840_interrupt_callback, }; diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 6def58b7938..9ab73d29577 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -44,8 +44,8 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); static int omninet_write_room(struct tty_struct *tty); static void omninet_disconnect(struct usb_serial *serial); -static void omninet_release(struct usb_serial *serial); -static int omninet_attach(struct usb_serial *serial); +static int omninet_port_probe(struct usb_serial_port *port); +static int omninet_port_remove(struct usb_serial_port *port); static const struct usb_device_id id_table[] = { { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) }, @@ -62,7 +62,8 @@ static struct usb_serial_driver zyxel_omninet_device = { .description = "ZyXEL - omni.net lcd plus usb", .id_table = id_table, .num_ports = 1, - .attach = omninet_attach, + .port_probe = omninet_port_probe, + .port_remove = omninet_port_remove, .open = omninet_open, .close = omninet_close, .write = omninet_write, @@ -70,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = { .read_bulk_callback = omninet_read_bulk_callback, .write_bulk_callback = omninet_write_bulk_callback, .disconnect = omninet_disconnect, - .release = omninet_release, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -112,18 +112,26 @@ struct omninet_data { __u8 od_outseq; /* Sequence number for bulk_out URBs */ }; -static int omninet_attach(struct usb_serial *serial) +static int omninet_port_probe(struct usb_serial_port *port) { struct omninet_data *od; - struct usb_serial_port *port = serial->port[0]; od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL); - if (!od) { - dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", - __func__, sizeof(struct omninet_data)); + if (!od) return -ENOMEM; - } + usb_set_serial_port_data(port, od); + + return 0; +} + +static int omninet_port_remove(struct usb_serial_port *port) +{ + struct omninet_data *od; + + od = usb_get_serial_port_data(port); + kfree(od); + return 0; } @@ -279,14 +287,6 @@ static void omninet_disconnect(struct usb_serial *serial) usb_kill_urb(wport->write_urb); } - -static void omninet_release(struct usb_serial *serial) -{ - struct usb_serial_port *port = serial->port[0]; - - kfree(usb_get_serial_port_data(port)); -} - module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 41b1647306e..6aba731d486 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, { struct usb_serial *serial = port->serial; int retval; - u8 buffer[2]; + u8 *buffer; + + buffer = kzalloc(1, GFP_KERNEL); + if (!buffer) + return -ENOMEM; buffer[0] = val; /* Send the message to the vendor control endpoint @@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, requesttype, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 0, 0, buffer, 1, 0); + kfree(buffer); return retval; } @@ -281,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, if (!dr) { dev_err(&port->dev, "out of memory\n"); count = -ENOMEM; - goto error; + goto error_no_dr; } dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; @@ -311,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, return count; error: + kfree(dr); +error_no_dr: usb_free_urb(urb); error_no_urb: kfree(buffer); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 30cff03e9f0..edc64bb6f45 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -47,6 +47,7 @@ /* Function prototypes */ static int option_probe(struct usb_serial *serial, const struct usb_device_id *id); +static int option_attach(struct usb_serial *serial); static void option_release(struct usb_serial *serial); static int option_send_setup(struct usb_serial_port *port); static void option_instat_callback(struct urb *urb); @@ -157,6 +158,7 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 +#define NOVATELWIRELESS_PRODUCT_E362 0x9010 #define NOVATELWIRELESS_PRODUCT_G1 0xA001 #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 #define NOVATELWIRELESS_PRODUCT_G2 0xA010 @@ -192,6 +194,9 @@ static void option_instat_callback(struct urb *urb); #define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181 #define DELL_PRODUCT_5730_MINICARD_VZW 0x8182 +#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */ +#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */ + #define KYOCERA_VENDOR_ID 0x0c88 #define KYOCERA_PRODUCT_KPC650 0x17da #define KYOCERA_PRODUCT_KPC680 0x180a @@ -282,6 +287,7 @@ static void option_instat_callback(struct urb *urb); /* ALCATEL PRODUCTS */ #define ALCATEL_VENDOR_ID 0x1bbb #define ALCATEL_PRODUCT_X060S_X200 0x0000 +#define ALCATEL_PRODUCT_X220_X500D 0x0017 #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -503,11 +509,19 @@ static const struct option_blacklist_info net_intf5_blacklist = { .reserved = BIT(5), }; +static const struct option_blacklist_info net_intf6_blacklist = { + .reserved = BIT(6), +}; + static const struct option_blacklist_info zte_mf626_blacklist = { .sendsetup = BIT(0) | BIT(1), .reserved = BIT(4), }; +static const struct option_blacklist_info zte_1255_blacklist = { + .reserved = BIT(3) | BIT(4), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -697,6 +711,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, @@ -719,6 +734,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, @@ -853,13 +870,19 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, @@ -872,7 +895,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, @@ -880,13 +904,22 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */ + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { 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, 0x1012, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_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) }, @@ -1002,18 +1035,24 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_1255_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) }, @@ -1058,8 +1097,16 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */ + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, @@ -1071,15 +1118,21 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, @@ -1112,6 +1165,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), @@ -1244,8 +1298,9 @@ static struct usb_serial_driver option_1port_device = { .tiocmget = usb_wwan_tiocmget, .tiocmset = usb_wwan_tiocmset, .ioctl = usb_wwan_ioctl, - .attach = usb_wwan_startup, + .attach = option_attach, .release = option_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, .read_int_callback = option_instat_callback, #ifdef CONFIG_PM @@ -1291,8 +1346,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { - struct usb_wwan_intf_private *data; - struct option_private *priv; struct usb_interface_descriptor *iface_desc = &serial->interface->cur_altsetting->desc; struct usb_device_descriptor *dev_desc = &serial->dev->descriptor; @@ -1330,6 +1383,19 @@ static int option_probe(struct usb_serial *serial, iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA) return -ENODEV; + /* Store device id so we can use it during attach. */ + usb_set_serial_data(serial, (void *)id); + + return 0; +} + +static int option_attach(struct usb_serial *serial) +{ + struct usb_interface_descriptor *iface_desc; + const struct usb_device_id *id; + struct usb_wwan_intf_private *data; + struct option_private *priv; + data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL); if (!data) return -ENOMEM; @@ -1340,6 +1406,10 @@ static int option_probe(struct usb_serial *serial, return -ENOMEM; } + /* Retrieve device id stored at probe. */ + id = usb_get_serial_data(serial); + iface_desc = &serial->interface->cur_altsetting->desc; + priv->bInterfaceNumber = iface_desc->bInterfaceNumber; data->private = priv; diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 933241f03fd..cee9a52ca89 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -137,8 +137,8 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); static int oti6858_tiocmget(struct tty_struct *tty); static int oti6858_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int oti6858_startup(struct usb_serial *serial); -static void oti6858_release(struct usb_serial *serial); +static int oti6858_port_probe(struct usb_serial_port *port); +static int oti6858_port_remove(struct usb_serial_port *port); /* device info */ static struct usb_serial_driver oti6858_device = { @@ -161,8 +161,8 @@ static struct usb_serial_driver oti6858_device = { .write_bulk_callback = oti6858_write_bulk_callback, .write_room = oti6858_write_room, .chars_in_buffer = oti6858_chars_in_buffer, - .attach = oti6858_startup, - .release = oti6858_release, + .port_probe = oti6858_port_probe, + .port_remove = oti6858_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -331,36 +331,33 @@ static void send_data(struct work_struct *work) usb_serial_port_softint(port); } -static int oti6858_startup(struct usb_serial *serial) +static int oti6858_port_probe(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct oti6858_private *priv; - int i; - - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL); - if (!priv) - break; - - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->intr_wait); -/* INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */ -/* INIT_WORK(&priv->write_work, send_data, serial->port[i]); */ - priv->port = port; - INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); - INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); - - usb_set_serial_port_data(serial->port[i], priv); - } - if (i == serial->num_ports) - return 0; - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->intr_wait); + priv->port = port; + INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); + INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int oti6858_port_remove(struct usb_serial_port *port) +{ + struct oti6858_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -709,15 +706,6 @@ static int oti6858_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } - -static void oti6858_release(struct usb_serial *serial) -{ - int i; - - for (i = 0; i < serial->num_ports; ++i) - kfree(usb_get_serial_port_data(serial->port[i])); -} - static void oti6858_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 892ebdc7a36..60024190136 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -133,12 +133,15 @@ enum pl2303_type { HX, /* HX version of the pl2303 chip */ }; +struct pl2303_serial_private { + enum pl2303_type type; +}; + struct pl2303_private { spinlock_t lock; wait_queue_head_t delta_msr_wait; u8 line_control; u8 line_status; - enum pl2303_type type; }; static int pl2303_vendor_read(__u16 value, __u16 index, @@ -167,14 +170,19 @@ static int pl2303_vendor_write(__u16 value, __u16 index, static int pl2303_startup(struct usb_serial *serial) { - struct pl2303_private *priv; + struct pl2303_serial_private *spriv; enum pl2303_type type = type_0; unsigned char *buf; - int i; + + spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); + if (!spriv) + return -ENOMEM; buf = kmalloc(10, GFP_KERNEL); - if (buf == NULL) + if (!buf) { + kfree(spriv); return -ENOMEM; + } if (serial->dev->descriptor.bDeviceClass == 0x02) type = type_0; @@ -186,15 +194,8 @@ static int pl2303_startup(struct usb_serial *serial) type = type_1; dev_dbg(&serial->interface->dev, "device type: %d\n", type); - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL); - if (!priv) - goto cleanup; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - priv->type = type; - usb_set_serial_port_data(serial->port[i], priv); - } + spriv->type = type; + usb_set_serial_data(serial, spriv); pl2303_vendor_read(0x8484, 0, serial, buf); pl2303_vendor_write(0x0404, 0, serial); @@ -213,15 +214,40 @@ static int pl2303_startup(struct usb_serial *serial) kfree(buf); return 0; +} -cleanup: - kfree(buf); - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i], NULL); - } - return -ENOMEM; +static void pl2303_release(struct usb_serial *serial) +{ + struct pl2303_serial_private *spriv; + + spriv = usb_get_serial_data(serial); + kfree(spriv); +} + +static int pl2303_port_probe(struct usb_serial_port *port) +{ + struct pl2303_private *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + + usb_set_serial_port_data(port, priv); + + return 0; +} + +static int pl2303_port_remove(struct usb_serial_port *port) +{ + struct pl2303_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int set_control_lines(struct usb_device *dev, u8 value) @@ -240,6 +266,7 @@ static void pl2303_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_serial *serial = port->serial; + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; unsigned int cflag; @@ -323,7 +350,7 @@ static void pl2303_set_termios(struct tty_struct *tty, } if (baud > 1228800) { /* type_0, type_1 only support up to 1228800 baud */ - if (priv->type != HX) + if (spriv->type != HX) baud = 1228800; else if (baud > 6000000) baud = 6000000; @@ -426,7 +453,7 @@ static void pl2303_set_termios(struct tty_struct *tty, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); if (cflag & CRTSCTS) { - if (priv->type == HX) + if (spriv->type == HX) pl2303_vendor_write(0x0, 0x61, serial); else pl2303_vendor_write(0x0, 0x41, serial); @@ -468,10 +495,10 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) { struct ktermios tmp_termios; struct usb_serial *serial = port->serial; - struct pl2303_private *priv = usb_get_serial_port_data(port); + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); int result; - if (priv->type != HX) { + if (spriv->type != HX) { usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); } else { @@ -655,17 +682,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state) dev_err(&port->dev, "error sending break = %d\n", result); } -static void pl2303_release(struct usb_serial *serial) -{ - int i; - struct pl2303_private *priv; - - for (i = 0; i < serial->num_ports; ++i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - } -} - static void pl2303_update_line_status(struct usb_serial_port *port, unsigned char *data, unsigned int actual_length) @@ -827,6 +843,8 @@ static struct usb_serial_driver pl2303_device = { .read_int_callback = pl2303_read_int_callback, .attach = pl2303_startup, .release = pl2303_release, + .port_probe = pl2303_port_probe, + .port_remove = pl2303_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index c3ddb65c05f..aa148c21ea4 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table); static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) { - struct usb_wwan_intf_private *data; struct usb_host_interface *intf = serial->interface->cur_altsetting; struct device *dev = &serial->dev->dev; int retval = -ENODEV; @@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) ifnum = intf->desc.bInterfaceNumber; dev_dbg(dev, "This Interface = %d\n", ifnum); - data = kzalloc(sizeof(struct usb_wwan_intf_private), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - spin_lock_init(&data->susp_lock); - if (nintf == 1) { /* QDL mode */ /* Gobi 2000 has a single altsetting, older ones have two */ @@ -253,20 +245,28 @@ done: } } - /* Set serial->private if not returning error */ - if (retval == 0) - usb_set_serial_data(serial, data); - else - kfree(data); - return retval; } +static int qc_attach(struct usb_serial *serial) +{ + struct usb_wwan_intf_private *data; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&data->susp_lock); + + usb_set_serial_data(serial, data); + + return 0; +} + static void qc_release(struct usb_serial *serial) { struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); - /* Free the private data allocated in qcprobe */ usb_set_serial_data(serial, NULL); kfree(priv); } @@ -285,8 +285,9 @@ static struct usb_serial_driver qcdevice = { .write = usb_wwan_write, .write_room = usb_wwan_write_room, .chars_in_buffer = usb_wwan_chars_in_buffer, - .attach = usb_wwan_startup, + .attach = qc_attach, .release = qc_release, + .port_probe = usb_wwan_port_probe, .port_remove = usb_wwan_port_remove, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 2cdfdcc90b3..ffcfc962ab1 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb); static void qt2_release(struct usb_serial *serial) { - int i; + struct qt2_serial_private *serial_priv; - kfree(usb_get_serial_data(serial)); + serial_priv = usb_get_serial_data(serial); - for (i = 0; i < serial->num_ports; i++) - kfree(usb_get_serial_port_data(serial->port[i])); + usb_free_urb(serial_priv->read_urb); + kfree(serial_priv); } static inline int calc_baud_divisor(int baudrate) @@ -423,11 +423,16 @@ static void qt2_close(struct usb_serial_port *port) port_priv->is_open = false; spin_lock_irqsave(&port_priv->urb_lock, flags); - if (port_priv->write_urb->status == -EINPROGRESS) - usb_kill_urb(port_priv->write_urb); + usb_kill_urb(port_priv->write_urb); port_priv->urb_in_use = false; spin_unlock_irqrestore(&port_priv->urb_lock, flags); + mutex_lock(&port->serial->disc_mutex); + if (port->serial->disconnected) { + mutex_unlock(&port->serial->disc_mutex); + return; + } + /* flush the port transmit buffer */ i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -459,26 +464,14 @@ static void qt2_close(struct usb_serial_port *port) dev_err(&port->dev, "%s - close port failed %i\n", __func__, i); + mutex_unlock(&port->serial->disc_mutex); } static void qt2_disconnect(struct usb_serial *serial) { struct qt2_serial_private *serial_priv = usb_get_serial_data(serial); - struct qt2_port_private *port_priv; - int i; - - if (serial_priv->read_urb->status == -EINPROGRESS) - usb_kill_urb(serial_priv->read_urb); - - usb_free_urb(serial_priv->read_urb); - for (i = 0; i < serial->num_ports; i++) { - port_priv = usb_get_serial_port_data(serial->port[i]); - - if (port_priv->write_urb->status == -EINPROGRESS) - usb_kill_urb(port_priv->write_urb); - usb_free_urb(port_priv->write_urb); - } + usb_kill_urb(serial_priv->read_urb); } static int get_serial_info(struct usb_serial_port *port, @@ -773,11 +766,9 @@ static void qt2_read_bulk_callback(struct urb *urb) static int qt2_setup_urbs(struct usb_serial *serial) { - struct usb_serial_port *port; struct usb_serial_port *port0; struct qt2_serial_private *serial_priv; - struct qt2_port_private *port_priv; - int pcount, status; + int status; port0 = serial->port[0]; @@ -795,46 +786,21 @@ static int qt2_setup_urbs(struct usb_serial *serial) sizeof(serial_priv->read_buffer), qt2_read_bulk_callback, serial); - /* setup write_urb for each port */ - for (pcount = 0; pcount < serial->num_ports; pcount++) { - - port = serial->port[pcount]; - port_priv = usb_get_serial_port_data(port); - - port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!port_priv->write_urb) { - dev_err(&serial->dev->dev, - "failed to alloc write_urb for port %i\n", - pcount); - return -ENOMEM; - } - - usb_fill_bulk_urb(port_priv->write_urb, - serial->dev, - usb_sndbulkpipe(serial->dev, - port0-> - bulk_out_endpointAddress), - port_priv->write_buffer, - sizeof(port_priv->write_buffer), - qt2_write_bulk_callback, port); - } - status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL); if (status != 0) { dev_err(&serial->dev->dev, "%s - submit read urb failed %i\n", __func__, status); + usb_free_urb(serial_priv->read_urb); return status; } return 0; - } static int qt2_attach(struct usb_serial *serial) { struct qt2_serial_private *serial_priv; - struct qt2_port_private *port_priv; - int status, pcount; + int status; /* power on unit */ status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -854,26 +820,6 @@ static int qt2_attach(struct usb_serial *serial) usb_set_serial_data(serial, serial_priv); - for (pcount = 0; pcount < serial->num_ports; pcount++) { - port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); - if (!port_priv) { - dev_err(&serial->dev->dev, - "%s- kmalloc(%Zd) failed.\n", __func__, - sizeof(*port_priv)); - pcount--; - status = -ENOMEM; - goto attach_failed; - } - - spin_lock_init(&port_priv->lock); - spin_lock_init(&port_priv->urb_lock); - init_waitqueue_head(&port_priv->delta_msr_wait); - - port_priv->port = serial->port[pcount]; - - usb_set_serial_port_data(serial->port[pcount], port_priv); - } - status = qt2_setup_urbs(serial); if (status != 0) goto attach_failed; @@ -881,14 +827,53 @@ static int qt2_attach(struct usb_serial *serial) return 0; attach_failed: - for (/* empty */; pcount >= 0; pcount--) { - port_priv = usb_get_serial_port_data(serial->port[pcount]); - kfree(port_priv); - } kfree(serial_priv); return status; } +static int qt2_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct qt2_port_private *port_priv; + u8 bEndpointAddress; + + port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); + if (!port_priv) + return -ENOMEM; + + spin_lock_init(&port_priv->lock); + spin_lock_init(&port_priv->urb_lock); + init_waitqueue_head(&port_priv->delta_msr_wait); + port_priv->port = port; + + port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!port_priv->write_urb) { + kfree(port_priv); + return -ENOMEM; + } + bEndpointAddress = serial->port[0]->bulk_out_endpointAddress; + usb_fill_bulk_urb(port_priv->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, bEndpointAddress), + port_priv->write_buffer, + sizeof(port_priv->write_buffer), + qt2_write_bulk_callback, port); + + usb_set_serial_port_data(port, port_priv); + + return 0; +} + +static int qt2_port_remove(struct usb_serial_port *port) +{ + struct qt2_port_private *port_priv; + + port_priv = usb_get_serial_port_data(port); + usb_free_urb(port_priv->write_urb); + kfree(port_priv); + + return 0; +} + static int qt2_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -1127,6 +1112,8 @@ static struct usb_serial_driver qt2_device = { .attach = qt2_attach, .release = qt2_release, .disconnect = qt2_disconnect, + .port_probe = qt2_port_probe, + .port_remove = qt2_port_remove, .dtr_rts = qt2_dtr_rts, .break_ctl = qt2_break_ctl, .tiocmget = qt2_tiocmget, diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 01d882cf377..270860f6bb2 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial, { int result = 0; struct usb_device *udev; - struct sierra_intf_private *data; u8 ifnum; udev = serial->dev; @@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial, return -ENODEV; } - data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); - if (!data) - return -ENOMEM; - spin_lock_init(&data->susp_lock); - return result; } @@ -884,11 +878,15 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on) static int sierra_startup(struct usb_serial *serial) { - struct usb_serial_port *port; - struct sierra_port_private *portdata; - struct sierra_iface_info *himemoryp = NULL; - int i; - u8 ifnum; + struct sierra_intf_private *intfdata; + + intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); + if (!intfdata) + return -ENOMEM; + + spin_lock_init(&intfdata->susp_lock); + + usb_set_serial_data(serial, intfdata); /* Set Device mode to D0 */ sierra_set_power_state(serial->dev, 0x0000); @@ -897,68 +895,71 @@ static int sierra_startup(struct usb_serial *serial) if (nmea) sierra_vsc_set_nmea(serial->dev, 1); - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dev_dbg(&port->dev, "%s: kmalloc for " - "sierra_port_private (%d) failed!\n", - __func__, i); - return -ENOMEM; - } - spin_lock_init(&portdata->lock); - init_usb_anchor(&portdata->active); - init_usb_anchor(&portdata->delayed); - ifnum = i; - /* Assume low memory requirements */ - portdata->num_out_urbs = N_OUT_URB; - portdata->num_in_urbs = N_IN_URB; - - /* Determine actual memory requirements */ - if (serial->num_ports == 1) { - /* Get interface number for composite device */ - ifnum = sierra_calc_interface(serial); - himemoryp = - (struct sierra_iface_info *)&typeB_interface_list; - if (is_himemory(ifnum, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - else { - himemoryp = - (struct sierra_iface_info *)&typeA_interface_list; - if (is_himemory(i, himemoryp)) { - portdata->num_out_urbs = N_OUT_URB_HM; - portdata->num_in_urbs = N_IN_URB_HM; - } - } - dev_dbg(&serial->dev->dev, - "Memory usage (urbs) interface #%d, in=%d, out=%d\n", - ifnum,portdata->num_in_urbs, portdata->num_out_urbs ); - /* Set the port private data pointer */ - usb_set_serial_port_data(port, portdata); - } - return 0; } static void sierra_release(struct usb_serial *serial) { - int i; - struct usb_serial_port *port; + struct sierra_intf_private *intfdata; + + intfdata = usb_get_serial_data(serial); + kfree(intfdata); +} + +static int sierra_port_probe(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; + const struct sierra_iface_info *himemoryp; + u8 ifnum; - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (!port) - continue; - portdata = usb_get_serial_port_data(port); - if (!portdata) - continue; - kfree(portdata); + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) + return -ENOMEM; + + spin_lock_init(&portdata->lock); + init_usb_anchor(&portdata->active); + init_usb_anchor(&portdata->delayed); + + /* Assume low memory requirements */ + portdata->num_out_urbs = N_OUT_URB; + portdata->num_in_urbs = N_IN_URB; + + /* Determine actual memory requirements */ + if (serial->num_ports == 1) { + /* Get interface number for composite device */ + ifnum = sierra_calc_interface(serial); + himemoryp = &typeB_interface_list; + } else { + /* This is really the usb-serial port number of the interface + * rather than the interface number. + */ + ifnum = port->number - serial->minor; + himemoryp = &typeA_interface_list; } + + if (is_himemory(ifnum, himemoryp)) { + portdata->num_out_urbs = N_OUT_URB_HM; + portdata->num_in_urbs = N_IN_URB_HM; + } + + dev_dbg(&port->dev, + "Memory usage (urbs) interface #%d, in=%d, out=%d\n", + ifnum, portdata->num_in_urbs, portdata->num_out_urbs); + + usb_set_serial_port_data(port, portdata); + + return 0; +} + +static int sierra_port_remove(struct usb_serial_port *port) +{ + struct sierra_port_private *portdata; + + portdata = usb_get_serial_port_data(port); + kfree(portdata); + + return 0; } #ifdef CONFIG_PM @@ -1062,6 +1063,8 @@ static struct usb_serial_driver sierra_device = { .tiocmset = sierra_tiocmset, .attach = sierra_startup, .release = sierra_release, + .port_probe = sierra_port_probe, + .port_remove = sierra_port_remove, .suspend = sierra_suspend, .resume = sierra_resume, .read_int_callback = sierra_instat_callback, diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 9716efe9295..769c137f897 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -157,13 +157,10 @@ struct spcp8x5_private { u8 line_status; }; -/* desc : when device plug in,this function would be called. - * thanks to usb_serial subsystem,then do almost every things for us. And what - * we should do just alloc the buffer */ -static int spcp8x5_startup(struct usb_serial *serial) +static int spcp8x5_port_probe(struct usb_serial_port *port) { + struct usb_serial *serial = port->serial; struct spcp8x5_private *priv; - int i; enum spcp8x5_type type = SPCP825_007_TYPE; u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); @@ -180,34 +177,27 @@ static int spcp8x5_startup(struct usb_serial *serial) type = SPCP825_PHILIP_TYPE; dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type); - for (i = 0; i < serial->num_ports; ++i) { - priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL); - if (!priv) - goto cleanup; + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; - spin_lock_init(&priv->lock); - init_waitqueue_head(&priv->delta_msr_wait); - priv->type = type; - usb_set_serial_port_data(serial->port[i] , priv); - } + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); + priv->type = type; + + usb_set_serial_port_data(port , priv); return 0; -cleanup: - for (--i; i >= 0; --i) { - priv = usb_get_serial_port_data(serial->port[i]); - kfree(priv); - usb_set_serial_port_data(serial->port[i] , NULL); - } - return -ENOMEM; } -/* call when the device plug out. free all the memory alloced by probe */ -static void spcp8x5_release(struct usb_serial *serial) +static int spcp8x5_port_remove(struct usb_serial_port *port) { - int i; + struct spcp8x5_private *priv; - for (i = 0; i < serial->num_ports; i++) - kfree(usb_get_serial_port_data(serial->port[i])); + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } /* set the modem control line of the device. @@ -649,8 +639,8 @@ static struct usb_serial_driver spcp8x5_device = { .ioctl = spcp8x5_ioctl, .tiocmget = spcp8x5_tiocmget, .tiocmset = spcp8x5_tiocmset, - .attach = spcp8x5_startup, - .release = spcp8x5_release, + .port_probe = spcp8x5_port_probe, + .port_remove = spcp8x5_port_remove, .process_read_urb = spcp8x5_process_read_urb, }; diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 015810b3785..868d1e6852e 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -67,13 +67,6 @@ struct ssu100_port_private { struct async_icount icount; }; -static void ssu100_release(struct usb_serial *serial) -{ - struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port); - - kfree(priv); -} - static inline int ssu100_control_msg(struct usb_device *dev, u8 request, u16 data, u16 index) { @@ -442,21 +435,33 @@ static int ssu100_ioctl(struct tty_struct *tty, static int ssu100_attach(struct usb_serial *serial) { + return ssu100_initdevice(serial->dev); +} + +static int ssu100_port_probe(struct usb_serial_port *port) +{ struct ssu100_port_private *priv; - struct usb_serial_port *port = *serial->port; priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__, - sizeof(*priv)); + if (!priv) return -ENOMEM; - } spin_lock_init(&priv->status_lock); init_waitqueue_head(&priv->delta_msr_wait); + usb_set_serial_port_data(port, priv); - return ssu100_initdevice(serial->dev); + return 0; +} + +static int ssu100_port_remove(struct usb_serial_port *port) +{ + struct ssu100_port_private *priv; + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } static int ssu100_tiocmget(struct tty_struct *tty) @@ -647,7 +652,8 @@ static struct usb_serial_driver ssu100_device = { .open = ssu100_open, .close = ssu100_close, .attach = ssu100_attach, - .release = ssu100_release, + .port_probe = ssu100_port_probe, + .port_remove = ssu100_port_remove, .dtr_rts = ssu100_dtr_rts, .process_read_urb = ssu100_process_read_urb, .tiocmget = ssu100_tiocmget, diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 6f49392cda5..f2530d2ef3c 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -97,6 +97,8 @@ struct ti_device { static int ti_startup(struct usb_serial *serial); static void ti_release(struct usb_serial *serial); +static int ti_port_probe(struct usb_serial_port *port); +static int ti_port_remove(struct usb_serial_port *port); static int ti_open(struct tty_struct *tty, struct usb_serial_port *port); static void ti_close(struct usb_serial_port *port); static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -221,6 +223,8 @@ static struct usb_serial_driver ti_1port_device = { .num_ports = 1, .attach = ti_startup, .release = ti_release, + .port_probe = ti_port_probe, + .port_remove = ti_port_remove, .open = ti_open, .close = ti_close, .write = ti_write, @@ -249,6 +253,8 @@ static struct usb_serial_driver ti_2port_device = { .num_ports = 2, .attach = ti_startup, .release = ti_release, + .port_probe = ti_port_probe, + .port_remove = ti_port_remove, .open = ti_open, .close = ti_close, .write = ti_write, @@ -347,11 +353,8 @@ module_exit(ti_exit); static int ti_startup(struct usb_serial *serial) { struct ti_device *tdev; - struct ti_port *tport; struct usb_device *dev = serial->dev; int status; - int i; - dev_dbg(&dev->dev, "%s - product 0x%4X, num configurations %d, configuration value %d", @@ -399,42 +402,8 @@ static int ti_startup(struct usb_serial *serial) goto free_tdev; } - /* set up port structures */ - for (i = 0; i < serial->num_ports; ++i) { - tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL); - if (tport == NULL) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); - status = -ENOMEM; - goto free_tports; - } - spin_lock_init(&tport->tp_lock); - tport->tp_uart_base_addr = (i == 0 ? - TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); - tport->tp_closing_wait = closing_wait; - init_waitqueue_head(&tport->tp_msr_wait); - init_waitqueue_head(&tport->tp_write_wait); - if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, - GFP_KERNEL)) { - dev_err(&dev->dev, "%s - out of memory\n", __func__); - kfree(tport); - status = -ENOMEM; - goto free_tports; - } - tport->tp_port = serial->port[i]; - tport->tp_tdev = tdev; - usb_set_serial_port_data(serial->port[i], tport); - tport->tp_uart_mode = 0; /* default is RS232 */ - } - return 0; -free_tports: - for (--i; i >= 0; --i) { - tport = usb_get_serial_port_data(serial->port[i]); - kfifo_free(&tport->write_fifo); - kfree(tport); - usb_set_serial_port_data(serial->port[i], NULL); - } free_tdev: kfree(tdev); usb_set_serial_data(serial, NULL); @@ -444,21 +413,50 @@ free_tdev: static void ti_release(struct usb_serial *serial) { - int i; struct ti_device *tdev = usb_get_serial_data(serial); + + kfree(tdev); +} + +static int ti_port_probe(struct usb_serial_port *port) +{ struct ti_port *tport; - for (i = 0; i < serial->num_ports; ++i) { - tport = usb_get_serial_port_data(serial->port[i]); - if (tport) { - kfifo_free(&tport->write_fifo); - kfree(tport); - } + tport = kzalloc(sizeof(*tport), GFP_KERNEL); + if (!tport) + return -ENOMEM; + + spin_lock_init(&tport->tp_lock); + if (port == port->serial->port[0]) + tport->tp_uart_base_addr = TI_UART1_BASE_ADDR; + else + tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; + tport->tp_closing_wait = closing_wait; + init_waitqueue_head(&tport->tp_msr_wait); + init_waitqueue_head(&tport->tp_write_wait); + if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) { + kfree(tport); + return -ENOMEM; } + tport->tp_port = port; + tport->tp_tdev = usb_get_serial_data(port->serial); + tport->tp_uart_mode = 0; /* default is RS232 */ - kfree(tdev); + usb_set_serial_port_data(port, tport); + + return 0; } +static int ti_port_remove(struct usb_serial_port *port) +{ + struct ti_port *tport; + + tport = usb_get_serial_port_data(port); + kfifo_free(&tport->write_fifo); + kfree(tport); + + return 0; +} static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) { diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 1f034d2397c..684739b8efd 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -8,7 +8,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 int usb_wwan_port_probe(struct usb_serial_port *port); 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, diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index e42aa398ed3..a3e9c095f0d 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -447,15 +447,14 @@ void usb_wwan_close(struct usb_serial_port *port) EXPORT_SYMBOL(usb_wwan_close); /* Helper functions used by usb_wwan_setup_urbs */ -static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, +static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, + int endpoint, int dir, void *ctx, char *buf, int len, void (*callback) (struct urb *)) { + struct usb_serial *serial = port->serial; struct urb *urb; - if (endpoint == -1) - return NULL; /* endpoint not needed */ - urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ if (urb == NULL) { dev_dbg(&serial->interface->dev, @@ -472,101 +471,78 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, return urb; } -/* Setup urbs */ -static void usb_wwan_setup_urbs(struct usb_serial *serial) +int usb_wwan_port_probe(struct usb_serial_port *port) { - int i, j; - struct usb_serial_port *port; struct usb_wwan_port_private *portdata; + struct urb *urb; + u8 *buffer; + int err; + int i; - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = usb_get_serial_port_data(port); + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) + return -ENOMEM; - /* Do indat endpoints first */ - for (j = 0; j < N_IN_URB; ++j) { - portdata->in_urbs[j] = usb_wwan_setup_urb(serial, - port-> - bulk_in_endpointAddress, - USB_DIR_IN, - port, - portdata-> - in_buffer[j], - IN_BUFLEN, - usb_wwan_indat_callback); - } + init_usb_anchor(&portdata->delayed); - /* outdat endpoints */ - for (j = 0; j < N_OUT_URB; ++j) { - portdata->out_urbs[j] = usb_wwan_setup_urb(serial, - port-> - bulk_out_endpointAddress, - USB_DIR_OUT, - port, - portdata-> - out_buffer - [j], - OUT_BUFLEN, - usb_wwan_outdat_callback); - } - } -} + for (i = 0; i < N_IN_URB; i++) { + if (!port->bulk_in_size) + break; -int usb_wwan_startup(struct usb_serial *serial) -{ - int i, j, err; - struct usb_serial_port *port; - struct usb_wwan_port_private *portdata; - u8 *buffer; + buffer = (u8 *)__get_free_page(GFP_KERNEL); + if (!buffer) + goto bail_out_error; + portdata->in_buffer[i] = buffer; - /* Now setup per port private data */ - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n", - __func__, i); - return 1; - } - init_usb_anchor(&portdata->delayed); + urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress, + USB_DIR_IN, port, + buffer, IN_BUFLEN, + usb_wwan_indat_callback); + portdata->in_urbs[i] = urb; + } - for (j = 0; j < N_IN_URB; j++) { - buffer = (u8 *) __get_free_page(GFP_KERNEL); - if (!buffer) - goto bail_out_error; - portdata->in_buffer[j] = buffer; - } + for (i = 0; i < N_OUT_URB; i++) { + if (!port->bulk_out_size) + break; - for (j = 0; j < N_OUT_URB; j++) { - buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); - if (!buffer) - goto bail_out_error2; - portdata->out_buffer[j] = buffer; - } + buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); + if (!buffer) + goto bail_out_error2; + portdata->out_buffer[i] = buffer; - usb_set_serial_port_data(port, portdata); + urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress, + USB_DIR_OUT, port, + buffer, OUT_BUFLEN, + usb_wwan_outdat_callback); + portdata->out_urbs[i] = urb; + } - if (!port->interrupt_in_urb) - continue; + usb_set_serial_port_data(port, portdata); + + if (port->interrupt_in_urb) { err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (err) dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n", __func__, err); } - usb_wwan_setup_urbs(serial); + return 0; bail_out_error2: - for (j = 0; j < N_OUT_URB; j++) - kfree(portdata->out_buffer[j]); + for (i = 0; i < N_OUT_URB; i++) { + usb_free_urb(portdata->out_urbs[i]); + kfree(portdata->out_buffer[i]); + } bail_out_error: - for (j = 0; j < N_IN_URB; j++) - if (portdata->in_buffer[j]) - free_page((unsigned long)portdata->in_buffer[j]); + for (i = 0; i < N_IN_URB; i++) { + usb_free_urb(portdata->in_urbs[i]); + free_page((unsigned long)portdata->in_buffer[i]); + } kfree(portdata); - return 1; + + return -ENOMEM; } -EXPORT_SYMBOL(usb_wwan_startup); +EXPORT_SYMBOL_GPL(usb_wwan_port_probe); int usb_wwan_port_remove(struct usb_serial_port *port) { diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 346c7efc20b..b9fca3586d7 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -83,6 +83,8 @@ static int whiteheat_firmware_attach(struct usb_serial *serial); /* function prototypes for the Connect Tech WhiteHEAT serial converter */ static int whiteheat_attach(struct usb_serial *serial); static void whiteheat_release(struct usb_serial *serial); +static int whiteheat_port_probe(struct usb_serial_port *port); +static int whiteheat_port_remove(struct usb_serial_port *port); static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port); static void whiteheat_close(struct usb_serial_port *port); @@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = { .num_ports = 4, .attach = whiteheat_attach, .release = whiteheat_release, + .port_probe = whiteheat_port_probe, + .port_remove = whiteheat_port_remove, .open = whiteheat_open, .close = whiteheat_close, .ioctl = whiteheat_ioctl, @@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial) { struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; - struct usb_serial_port *port; - struct whiteheat_private *info; struct whiteheat_hw_info *hw_info; int pipe; int ret; int alen; __u8 *command; __u8 *result; - int i; command_port = serial->port[COMMAND_PORT]; @@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial) serial->type->description, hw_info->sw_major_rev, hw_info->sw_minor_rev); - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - - info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL); - if (info == NULL) { - dev_err(&port->dev, - "%s: Out of memory for port structures\n", - serial->type->description); - goto no_private; - } - - info->mcr = 0; - - usb_set_serial_port_data(port, info); - } - command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL); if (command_info == NULL) { @@ -333,16 +318,10 @@ no_firmware: "%s: please contact support@connecttech.com\n", serial->type->description); kfree(result); + kfree(command); return -ENODEV; no_command_private: - for (i = serial->num_ports - 1; i >= 0; i--) { - port = serial->port[i]; - info = usb_get_serial_port_data(port); - kfree(info); -no_private: - ; - } kfree(result); no_result_buffer: kfree(command); @@ -350,21 +329,36 @@ no_command_buffer: return -ENOMEM; } - static void whiteheat_release(struct usb_serial *serial) { struct usb_serial_port *command_port; - struct whiteheat_private *info; - int i; /* free up our private data for our command port */ command_port = serial->port[COMMAND_PORT]; kfree(usb_get_serial_port_data(command_port)); +} - for (i = 0; i < serial->num_ports; i++) { - info = usb_get_serial_port_data(serial->port[i]); - kfree(info); - } +static int whiteheat_port_probe(struct usb_serial_port *port) +{ + struct whiteheat_private *info; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + usb_set_serial_port_data(port, info); + + return 0; +} + +static int whiteheat_port_remove(struct usb_serial_port *port) +{ + struct whiteheat_private *info; + + info = usb_get_serial_port_data(port); + kfree(info); + + return 0; } static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index a3d54366afc..92f35abee92 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -186,6 +186,12 @@ static int slave_configure(struct scsi_device *sdev) /* Some devices don't handle VPD pages correctly */ sdev->skip_vpd_pages = 1; + /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */ + sdev->no_report_opcodes = 1; + + /* Do not attempt to use WRITE SAME */ + sdev->no_write_same = 1; + /* Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. * If this device makes that mistake, tell the sd driver. */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 779cd954abc..d305a5aa3a5 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999, USB_SC_8070, USB_PR_CB, NULL, US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), +/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */ +UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100, + "Casio", + "EX-N1 DigitalCamera", + USB_SC_8070, USB_PR_DEVICE, NULL, 0), + /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, "Samsung", diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 072cbbadbc3..7f93f34b7f9 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -379,7 +379,8 @@ static void handle_rx(struct vhost_net *net) .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE }; size_t total_len = 0; - int err, headcount, mergeable; + int err, mergeable; + s16 headcount; size_t vhost_hlen, sock_hlen; size_t vhost_len, sock_len; /* TODO: check that we are running from vhost_worker? */ diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index c101697a4ba..765a945f8ea 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -60,7 +60,8 @@ config LCD_LTV350QV The LTV350QV panel is present on all ATSTK1000 boards. config LCD_ILI9320 - tristate + tristate "ILI Technology ILI9320 controller support" + depends on SPI help If you have a panel based on the ILI9320 controller chip then say y to include a power driver for it. diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c index c6915c6c3cd..585949b5705 100644 --- a/drivers/video/backlight/lm3639_bl.c +++ b/drivers/video/backlight/lm3639_bl.c @@ -206,11 +206,11 @@ static ssize_t lm3639_bled_mode_store(struct device *dev, out: dev_err(pchip->dev, "%s:i2c access fail to register\n", __func__); - return size; + return ret; out_input: dev_err(pchip->dev, "%s:input conversion fail\n", __func__); - return size; + return ret; } diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index d64ac384288..bee92846cfa 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -365,11 +365,20 @@ struct platform_device *dsi_get_dsidev_from_id(int module) struct omap_dss_output *out; enum omap_dss_output_id id; - id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + switch (module) { + case 0: + id = OMAP_DSS_OUTPUT_DSI1; + break; + case 1: + id = OMAP_DSS_OUTPUT_DSI2; + break; + default: + return NULL; + } out = omap_dss_get_output(id); - return out->pdev; + return out ? out->pdev : NULL; } static inline void dsi_write_reg(struct platform_device *dsidev, diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 2ab1c3e9655..5f6eea801b0 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -697,11 +697,15 @@ static int dss_get_clocks(void) dss.dss_clk = clk; - clk = clk_get(NULL, dss.feat->clk_name); - if (IS_ERR(clk)) { - DSSERR("Failed to get %s\n", dss.feat->clk_name); - r = PTR_ERR(clk); - goto err; + if (dss.feat->clk_name) { + clk = clk_get(NULL, dss.feat->clk_name); + if (IS_ERR(clk)) { + DSSERR("Failed to get %s\n", dss.feat->clk_name); + r = PTR_ERR(clk); + goto err; + } + } else { + clk = NULL; } dss.dpll4_m4_ck = clk; @@ -805,10 +809,10 @@ static int __init dss_init_features(struct device *dev) if (cpu_is_omap24xx()) src = &omap24xx_dss_feats; - else if (cpu_is_omap34xx()) - src = &omap34xx_dss_feats; else if (cpu_is_omap3630()) src = &omap3630_dss_feats; + else if (cpu_is_omap34xx()) + src = &omap34xx_dss_feats; else if (cpu_is_omap44xx()) src = &omap44xx_dss_feats; else if (soc_is_omap54xx()) diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index a48a7dd75b3..8c9b8b3b7f7 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -644,8 +644,10 @@ static void hdmi_dump_regs(struct seq_file *s) { mutex_lock(&hdmi.lock); - if (hdmi_runtime_get()) + if (hdmi_runtime_get()) { + mutex_unlock(&hdmi.lock); return; + } hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s); hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 606b89f1235..d630b26a005 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -787,7 +787,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) case OMAPFB_WAITFORVSYNC: DBG("ioctl WAITFORVSYNC\n"); - if (!display && !display->output && !display->output->manager) { + if (!display || !display->output || !display->output->manager) { r = -EINVAL; break; } diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index b7f5173ff9e..917bb568168 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev, case XenbusStateReconfiguring: case XenbusStateReconfigured: case XenbusStateUnknown: - case XenbusStateClosed: break; case XenbusStateInitWait: @@ -670,6 +669,10 @@ InitWait: info->feature_resize = val; break; + case XenbusStateClosed: + if (dev->state == XenbusStateClosed) + break; + /* Missed the backend's CLOSING state -- fallthrough */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 1e8659ca27e..809b0de59c0 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device); void unregister_virtio_device(struct virtio_device *dev) { + int index = dev->index; /* save for after device release */ + device_unregister(&dev->dev); - ida_simple_remove(&virtio_index_ida, dev->index); + ida_simple_remove(&virtio_index_ida, index); } EXPORT_SYMBOL_GPL(unregister_virtio_device); diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index d4dffcd5287..126d8ce591c 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -3,6 +3,7 @@ menu "Xen driver support" config XEN_BALLOON bool "Xen memory balloon driver" + depends on !ARM default y help The balloon driver allows the Xen domain to request more memory from @@ -145,6 +146,7 @@ config SWIOTLB_XEN config XEN_TMEM bool + depends on !ARM default y if (CLEANCACHE || FRONTSWAP) help Shim to interface in-kernel Transcendent Memory hooks diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 0e863703545..74354708c6c 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -2,6 +2,7 @@ ifneq ($(CONFIG_ARM),y) obj-y += manage.o balloon.o obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o endif +obj-$(CONFIG_X86) += fallback.o obj-y += grant-table.o features.o events.o obj-y += xenbus/ diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 31ab82fda38..d6886d90ccf 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -55,7 +55,6 @@ #include <asm/pgalloc.h> #include <asm/pgtable.h> #include <asm/tlb.h> -#include <asm/e820.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> @@ -88,7 +87,7 @@ struct balloon_stats balloon_stats; EXPORT_SYMBOL_GPL(balloon_stats); /* We increase/decrease in batches which fit in a page */ -static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)]; +static xen_pfn_t frame_list[PAGE_SIZE / sizeof(unsigned long)]; #ifdef CONFIG_HIGHMEM #define inc_totalhigh_pages() (totalhigh_pages++) diff --git a/drivers/xen/dbgp.c b/drivers/xen/dbgp.c index 42569c77ccc..f3ccc80a455 100644 --- a/drivers/xen/dbgp.c +++ b/drivers/xen/dbgp.c @@ -8,7 +8,9 @@ static int xen_dbgp_op(struct usb_hcd *hcd, int op) { +#ifdef CONFIG_PCI const struct device *ctrlr = hcd_to_bus(hcd)->controller; +#endif struct physdev_dbgp_op dbgp; if (!xen_initial_domain()) diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 59e10a1286d..0be4df39e95 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -115,7 +115,9 @@ struct irq_info { #define PIRQ_SHAREABLE (1 << 1) static int *evtchn_to_irq; +#ifdef CONFIG_X86 static unsigned long *pirq_eoi_map; +#endif static bool (*pirq_needs_eoi)(unsigned irq); static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG], @@ -277,10 +279,12 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn) return ret; } +#ifdef CONFIG_X86 static bool pirq_check_eoi_map(unsigned irq) { return test_bit(pirq_from_irq(irq), pirq_eoi_map); } +#endif static bool pirq_needs_eoi_flag(unsigned irq) { @@ -1391,10 +1395,10 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); + irq_enter(); #ifdef CONFIG_X86 exit_idle(); #endif - irq_enter(); __xen_evtchn_do_upcall(); diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c new file mode 100644 index 00000000000..0ef7c4d40f8 --- /dev/null +++ b/drivers/xen/fallback.c @@ -0,0 +1,80 @@ +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/bug.h> +#include <linux/export.h> +#include <asm/hypervisor.h> +#include <asm/xen/hypercall.h> + +int xen_event_channel_op_compat(int cmd, void *arg) +{ + struct evtchn_op op; + int rc; + + op.cmd = cmd; + memcpy(&op.u, arg, sizeof(op.u)); + rc = _hypercall1(int, event_channel_op_compat, &op); + + switch (cmd) { + case EVTCHNOP_close: + case EVTCHNOP_send: + case EVTCHNOP_bind_vcpu: + case EVTCHNOP_unmask: + /* no output */ + break; + +#define COPY_BACK(eop) \ + case EVTCHNOP_##eop: \ + memcpy(arg, &op.u.eop, sizeof(op.u.eop)); \ + break + + COPY_BACK(bind_interdomain); + COPY_BACK(bind_virq); + COPY_BACK(bind_pirq); + COPY_BACK(status); + COPY_BACK(alloc_unbound); + COPY_BACK(bind_ipi); +#undef COPY_BACK + + default: + WARN_ON(rc != -ENOSYS); + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); + +int HYPERVISOR_physdev_op_compat(int cmd, void *arg) +{ + struct physdev_op op; + int rc; + + op.cmd = cmd; + memcpy(&op.u, arg, sizeof(op.u)); + rc = _hypercall1(int, physdev_op_compat, &op); + + switch (cmd) { + case PHYSDEVOP_IRQ_UNMASK_NOTIFY: + case PHYSDEVOP_set_iopl: + case PHYSDEVOP_set_iobitmap: + case PHYSDEVOP_apic_write: + /* no output */ + break; + +#define COPY_BACK(pop, fld) \ + case PHYSDEVOP_##pop: \ + memcpy(arg, &op.u.fld, sizeof(op.u.fld)); \ + break + + COPY_BACK(irq_status_query, irq_status_query); + COPY_BACK(apic_read, apic_op); + COPY_BACK(ASSIGN_VECTOR, irq_op); +#undef COPY_BACK + + default: + WARN_ON(rc != -ENOSYS); + break; + } + + return rc; +} diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 610bfc6be17..2e22df2f7a3 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv, #endif } +static void gntdev_free_map(struct grant_map *map) +{ + if (map == NULL) + return; + + if (map->pages) + free_xenballooned_pages(map->count, map->pages); + kfree(map->pages); + kfree(map->grants); + kfree(map->map_ops); + kfree(map->unmap_ops); + kfree(map->kmap_ops); + kfree(map); +} + static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) { struct grant_map *add; @@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) return add; err: - kfree(add->pages); - kfree(add->grants); - kfree(add->map_ops); - kfree(add->unmap_ops); - kfree(add->kmap_ops); - kfree(add); + gntdev_free_map(add); return NULL; } @@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map) evtchn_put(map->notify.event); } - if (map->pages) { - if (!use_ptemod) - unmap_grant_pages(map, 0, map->count); - - free_xenballooned_pages(map->count, map->pages); - } - kfree(map->pages); - kfree(map->grants); - kfree(map->map_ops); - kfree(map->unmap_ops); - kfree(map); + if (map->pages && !use_ptemod) + unmap_grant_pages(map, 0, map->count); + gntdev_free_map(map); } /* ------------------------------------------------------------------ */ diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index b2b0a375b34..b91f14e8316 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -84,7 +84,7 @@ struct gnttab_ops { * nr_gframes is the number of frames to map grant table. Returning * GNTST_okay means success and negative value means failure. */ - int (*map_frames)(unsigned long *frames, unsigned int nr_gframes); + int (*map_frames)(xen_pfn_t *frames, unsigned int nr_gframes); /* * Release a list of frames which are mapped in map_frames for grant * entry status. @@ -960,7 +960,7 @@ static unsigned nr_status_frames(unsigned nr_grant_frames) return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; } -static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes) +static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) { int rc; @@ -977,7 +977,7 @@ static void gnttab_unmap_frames_v1(void) arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames); } -static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes) +static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes) { uint64_t *sframes; unsigned int nr_sframes; @@ -1029,7 +1029,7 @@ static void gnttab_unmap_frames_v2(void) static int gnttab_map(unsigned int start_idx, unsigned int end_idx) { struct gnttab_setup_table setup; - unsigned long *frames; + xen_pfn_t *frames; unsigned int nr_gframes = end_idx + 1; int rc; diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 8adb9cc267f..71f5c459b08 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -361,13 +361,13 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) down_write(&mm->mmap_sem); vma = find_vma(mm, m.addr); - ret = -EINVAL; if (!vma || vma->vm_ops != &privcmd_vm_ops || (m.addr != vma->vm_start) || ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) || !privcmd_enforce_singleshot_mapping(vma)) { up_write(&mm->mmap_sem); + ret = -EINVAL; goto out; } @@ -383,12 +383,16 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) up_write(&mm->mmap_sem); - if (state.global_error && (version == 1)) { - /* Write back errors in second pass. */ - state.user_mfn = (xen_pfn_t *)m.arr; - state.err = err_array; - ret = traverse_pages(m.num, sizeof(xen_pfn_t), - &pagelist, mmap_return_errors_v1, &state); + if (version == 1) { + if (state.global_error) { + /* Write back errors in second pass. */ + state.user_mfn = (xen_pfn_t *)m.arr; + state.err = err_array; + ret = traverse_pages(m.num, sizeof(xen_pfn_t), + &pagelist, mmap_return_errors_v1, &state); + } else + ret = 0; + } else if (version == 2) { ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); if (ret) diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index 5e5ad7e2885..96453f8a85c 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/kobject.h> +#include <linux/err.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> @@ -284,7 +285,8 @@ static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer) ret = HYPERVISOR_xen_version(XENVER_platform_parameters, parms); if (!ret) - ret = sprintf(buffer, "%lx\n", parms->virt_start); + ret = sprintf(buffer, "%"PRI_xen_ulong"\n", + parms->virt_start); kfree(parms); } diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c index 46d140baebd..0f478ac483c 100644 --- a/drivers/xen/xen-pciback/vpci.c +++ b/drivers/xen/xen-pciback/vpci.c @@ -89,9 +89,15 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, mutex_lock(&vpci_dev->lock); - /* Keep multi-function devices together on the virtual PCI bus */ - for (slot = 0; slot < PCI_SLOT_MAX; slot++) { - if (!list_empty(&vpci_dev->dev_list[slot])) { + /* + * Keep multi-function devices together on the virtual PCI bus, except + * virtual functions. + */ + if (!dev->is_virtfn) { + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { + if (list_empty(&vpci_dev->dev_list[slot])) + continue; + t = list_entry(list_first(&vpci_dev->dev_list[slot]), struct pci_dev_entry, list); @@ -116,7 +122,7 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, pci_name(dev), slot); list_add_tail(&dev_entry->list, &vpci_dev->dev_list[slot]); - func = PCI_FUNC(dev->devfn); + func = dev->is_virtfn ? 0 : PCI_FUNC(dev->devfn); goto unlock; } } diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index 89f76252a16..ac727028e65 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp, goto out; /* Can't write a xenbus message larger we can buffer */ - if ((len + u->len) > sizeof(u->u.buffer)) { + if (len > sizeof(u->u.buffer) - u->len) { /* On error, dump existing buffer */ u->len = 0; rc = -EINVAL; diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 48220e129f8..acedeabe589 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -625,8 +625,9 @@ static struct xenbus_watch *find_watch(const char *token) * so if we are running on anything older than 4 do not attempt to read * control/platform-feature-xs_reset_watches. */ -static bool xen_strict_xenbus_quirk() +static bool xen_strict_xenbus_quirk(void) { +#ifdef CONFIG_X86 uint32_t eax, ebx, ecx, edx, base; base = xen_cpuid_base(); @@ -634,6 +635,7 @@ static bool xen_strict_xenbus_quirk() if ((eax >> 16) < 4) return true; +#endif return false; } @@ -75,6 +75,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) unsigned int sz = sizeof(struct bio) + extra_size; struct kmem_cache *slab = NULL; struct bio_slab *bslab, *new_bio_slabs; + unsigned int new_bio_slab_max; unsigned int i, entry = -1; mutex_lock(&bio_slab_lock); @@ -97,12 +98,13 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) goto out_unlock; if (bio_slab_nr == bio_slab_max && entry == -1) { - bio_slab_max <<= 1; + new_bio_slab_max = bio_slab_max << 1; new_bio_slabs = krealloc(bio_slabs, - bio_slab_max * sizeof(struct bio_slab), + new_bio_slab_max * sizeof(struct bio_slab), GFP_KERNEL); if (!new_bio_slabs) goto out_unlock; + bio_slab_max = new_bio_slab_max; bio_slabs = new_bio_slabs; } if (entry == -1) diff --git a/fs/block_dev.c b/fs/block_dev.c index b3c1d3dae77..1a1e5e3b1ea 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1661,6 +1661,39 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma) return ret; } +static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) +{ + ssize_t ret; + struct block_device *bdev = I_BDEV(file->f_mapping->host); + + percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_splice_read(file, ppos, pipe, len, flags); + + percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; +} + +static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe, + struct file *file, loff_t *ppos, size_t len, + unsigned int flags) +{ + ssize_t ret; + struct block_device *bdev = I_BDEV(file->f_mapping->host); + + percpu_down_read(&bdev->bd_block_size_semaphore); + + ret = generic_file_splice_write(pipe, file, ppos, len, flags); + + percpu_up_read(&bdev->bd_block_size_semaphore); + + return ret; +} + + /* * Try to release a page associated with block device when the system * is under memory pressure. @@ -1699,8 +1732,8 @@ const struct file_operations def_blk_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = compat_blkdev_ioctl, #endif - .splice_read = generic_file_splice_read, - .splice_write = generic_file_splice_write, + .splice_read = blkdev_splice_read, + .splice_write = blkdev_splice_write, }; int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index f3187938e08..208d8aa5b07 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, goto out; } - rcu_read_lock(); - root_level = btrfs_header_level(root->node); - rcu_read_unlock(); + root_level = btrfs_old_root_level(root, time_seq); if (root_level + 1 == level) goto out; @@ -1177,16 +1175,15 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, return ret; } -static char *ref_to_path(struct btrfs_root *fs_root, - struct btrfs_path *path, - u32 name_len, unsigned long name_off, - struct extent_buffer *eb_in, u64 parent, - char *dest, u32 size) +char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, + u32 name_len, unsigned long name_off, + struct extent_buffer *eb_in, u64 parent, + char *dest, u32 size) { int slot; u64 next_inum; int ret; - s64 bytes_left = size - 1; + s64 bytes_left = ((s64)size) - 1; struct extent_buffer *eb = eb_in; struct btrfs_key found_key; int leave_spinning = path->leave_spinning; @@ -1266,10 +1263,10 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct extent_buffer *eb_in, u64 parent, char *dest, u32 size) { - return ref_to_path(fs_root, path, - btrfs_inode_ref_name_len(eb_in, iref), - (unsigned long)(iref + 1), - eb_in, parent, dest, size); + return btrfs_ref_to_path(fs_root, path, + btrfs_inode_ref_name_len(eb_in, iref), + (unsigned long)(iref + 1), + eb_in, parent, dest, size); } /* @@ -1715,9 +1712,8 @@ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off, ipath->fspath->bytes_left - s_ptr : 0; fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; - fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, - name_off, eb, inum, fspath_min, - bytes_left); + fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, + name_off, eb, inum, fspath_min, bytes_left); if (IS_ERR(fspath)) return PTR_ERR(fspath); diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index e75533043a5..d61feca7945 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h @@ -62,6 +62,10 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, struct btrfs_inode_ref *iref, struct extent_buffer *eb, u64 parent, char *dest, u32 size); +char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, + u32 name_len, unsigned long name_off, + struct extent_buffer *eb_in, u64 parent, + char *dest, u32 size); struct btrfs_data_container *init_data_container(u32 total_bytes); struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b3343621100..cdfb4c49a80 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, if (tree_mod_dont_log(fs_info, eb)) return 0; + /* + * When we override something during the move, we log these removals. + * This can only happen when we move towards the beginning of the + * buffer, i.e. dst_slot < src_slot. + */ for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot, MOD_LOG_KEY_REMOVE_WHILE_MOVING); @@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, if (tree_mod_dont_log(fs_info, NULL)) return 0; - __tree_mod_log_free_eb(fs_info, old_root); - ret = tree_mod_alloc(fs_info, flags, &tm); if (ret < 0) goto out; @@ -926,12 +929,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, ret = btrfs_dec_ref(trans, root, buf, 1, 1); BUG_ON(ret); /* -ENOMEM */ } - /* - * don't log freeing in case we're freeing the root node, this - * is done by tree_mod_log_set_root_pointer later - */ - if (buf != root->node && btrfs_header_level(buf) != 0) - tree_mod_log_free_eb(root->fs_info, buf); + tree_mod_log_free_eb(root->fs_info, buf); clean_tree_block(trans, root, buf); *last_ref = 1; } @@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, free_extent_buffer(eb); __tree_mod_log_rewind(eb_rewin, time_seq, tm); + WARN_ON(btrfs_header_nritems(eb_rewin) > + BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root)); return eb_rewin; } @@ -1241,9 +1241,11 @@ get_old_root(struct btrfs_root *root, u64 time_seq) { struct tree_mod_elem *tm; struct extent_buffer *eb; + struct extent_buffer *old; struct tree_mod_root *old_root = NULL; u64 old_generation = 0; u64 logical; + u32 blocksize; eb = btrfs_read_lock_root_node(root); tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); @@ -1259,14 +1261,32 @@ get_old_root(struct btrfs_root *root, u64 time_seq) } tm = tree_mod_log_search(root->fs_info, logical, time_seq); - if (old_root) + if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) { + btrfs_tree_read_unlock(root->node); + free_extent_buffer(root->node); + blocksize = btrfs_level_size(root, old_root->level); + old = read_tree_block(root, logical, blocksize, 0); + if (!old) { + pr_warn("btrfs: failed to read tree block %llu from get_old_root\n", + logical); + WARN_ON(1); + } else { + eb = btrfs_clone_extent_buffer(old); + free_extent_buffer(old); + } + } else if (old_root) { + btrfs_tree_read_unlock(root->node); + free_extent_buffer(root->node); eb = alloc_dummy_extent_buffer(logical, root->nodesize); - else + } else { eb = btrfs_clone_extent_buffer(root->node); - btrfs_tree_read_unlock(root->node); - free_extent_buffer(root->node); + btrfs_tree_read_unlock(root->node); + free_extent_buffer(root->node); + } + if (!eb) return NULL; + extent_buffer_get(eb); btrfs_tree_read_lock(eb); if (old_root) { btrfs_set_header_bytenr(eb, eb->start); @@ -1279,11 +1299,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq) __tree_mod_log_rewind(eb, time_seq, tm); else WARN_ON(btrfs_header_level(eb) != 0); - extent_buffer_get(eb); + WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); return eb; } +int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq) +{ + struct tree_mod_elem *tm; + int level; + + tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); + if (tm && tm->op == MOD_LOG_ROOT_REPLACE) { + level = tm->old_root.level; + } else { + rcu_read_lock(); + level = btrfs_header_level(root->node); + rcu_read_unlock(); + } + + return level; +} + static inline int should_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf) @@ -1725,6 +1762,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, goto enospc; } + tree_mod_log_free_eb(root->fs_info, root->node); tree_mod_log_set_root_pointer(root, child); rcu_assign_pointer(root->node, child); @@ -2970,8 +3008,10 @@ static int push_node_left(struct btrfs_trans_handle *trans, push_items * sizeof(struct btrfs_key_ptr)); if (push_items < src_nritems) { - tree_mod_log_eb_move(root->fs_info, src, 0, push_items, - src_nritems - push_items); + /* + * don't call tree_mod_log_eb_move here, key removal was already + * fully logged by tree_mod_log_eb_copy above. + */ memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), btrfs_node_key_ptr_offset(push_items), (src_nritems - push_items) * diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 926c9ffc66d..c72ead86950 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info) { return atomic_inc_return(&fs_info->tree_mod_seq); } +int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq); /* root-item.c */ int btrfs_find_root_ref(struct btrfs_root *tree_root, @@ -3338,6 +3339,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, int btrfs_update_inode(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct inode *inode); +int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, + struct btrfs_root *root, struct inode *inode); int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); int btrfs_orphan_cleanup(struct btrfs_root *root); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8036d3a8485..472873a94d9 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4110,8 +4110,8 @@ struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len) return eb; err: - for (i--; i >= 0; i--) - __free_page(eb->pages[i]); + for (; i > 0; i--) + __free_page(eb->pages[i - 1]); __free_extent_buffer(eb); return NULL; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 85a1e5053fe..95542a1b3df 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -94,8 +94,6 @@ static noinline int cow_file_range(struct inode *inode, struct page *locked_page, u64 start, u64 end, int *page_started, unsigned long *nr_written, int unlock); -static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode); static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, struct inode *inode, struct inode *dir, @@ -2746,8 +2744,9 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, return btrfs_update_inode_item(trans, root, inode); } -static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct inode *inode) +noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct inode *inode) { int ret; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 61168805f17..8fcf9a59c28 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -343,7 +343,8 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) return -EOPNOTSUPP; if (copy_from_user(&range, arg, sizeof(range))) return -EFAULT; - if (range.start > total_bytes) + if (range.start > total_bytes || + range.len < fs_info->sb->s_blocksize) return -EINVAL; range.len = min(range.len, total_bytes - range.start); @@ -570,7 +571,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, ret = btrfs_commit_transaction(trans, root->fs_info->extent_root); } - BUG_ON(ret); + if (ret) + goto fail; ret = pending_snapshot->error; if (ret) diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 5039686df6a..fe9d02c45f8 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -790,8 +790,10 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, } path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; + if (!path) { + ret = -ENOMEM; + goto out_free_root; + } key.objectid = 0; key.type = BTRFS_QGROUP_STATUS_KEY; @@ -800,7 +802,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, ret = btrfs_insert_empty_item(trans, quota_root, path, &key, sizeof(*ptr)); if (ret) - goto out; + goto out_free_path; leaf = path->nodes[0]; ptr = btrfs_item_ptr(leaf, path->slots[0], @@ -818,8 +820,15 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, fs_info->quota_root = quota_root; fs_info->pending_quota_state = 1; spin_unlock(&fs_info->qgroup_lock); -out: +out_free_path: btrfs_free_path(path); +out_free_root: + if (ret) { + free_extent_buffer(quota_root->node); + free_extent_buffer(quota_root->commit_root); + kfree(quota_root); + } +out: return ret; } diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index c7beb543a4a..e78b297b0b0 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -745,31 +745,36 @@ typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index, void *ctx); /* - * Helper function to iterate the entries in ONE btrfs_inode_ref. + * Helper function to iterate the entries in ONE btrfs_inode_ref or + * btrfs_inode_extref. * The iterate callback may return a non zero value to stop iteration. This can * be a negative value for error codes or 1 to simply stop it. * - * path must point to the INODE_REF when called. + * path must point to the INODE_REF or INODE_EXTREF when called. */ static int iterate_inode_ref(struct send_ctx *sctx, struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *found_key, int resolve, iterate_inode_ref_t iterate, void *ctx) { - struct extent_buffer *eb; + struct extent_buffer *eb = path->nodes[0]; struct btrfs_item *item; struct btrfs_inode_ref *iref; + struct btrfs_inode_extref *extref; struct btrfs_path *tmp_path; struct fs_path *p; - u32 cur; - u32 len; + u32 cur = 0; u32 total; - int slot; + int slot = path->slots[0]; u32 name_len; char *start; int ret = 0; - int num; + int num = 0; int index; + u64 dir; + unsigned long name_off; + unsigned long elem_size; + unsigned long ptr; p = fs_path_alloc_reversed(sctx); if (!p) @@ -781,24 +786,40 @@ static int iterate_inode_ref(struct send_ctx *sctx, return -ENOMEM; } - eb = path->nodes[0]; - slot = path->slots[0]; - item = btrfs_item_nr(eb, slot); - iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref); - cur = 0; - len = 0; - total = btrfs_item_size(eb, item); - num = 0; + if (found_key->type == BTRFS_INODE_REF_KEY) { + ptr = (unsigned long)btrfs_item_ptr(eb, slot, + struct btrfs_inode_ref); + item = btrfs_item_nr(eb, slot); + total = btrfs_item_size(eb, item); + elem_size = sizeof(*iref); + } else { + ptr = btrfs_item_ptr_offset(eb, slot); + total = btrfs_item_size_nr(eb, slot); + elem_size = sizeof(*extref); + } + while (cur < total) { fs_path_reset(p); - name_len = btrfs_inode_ref_name_len(eb, iref); - index = btrfs_inode_ref_index(eb, iref); + if (found_key->type == BTRFS_INODE_REF_KEY) { + iref = (struct btrfs_inode_ref *)(ptr + cur); + name_len = btrfs_inode_ref_name_len(eb, iref); + name_off = (unsigned long)(iref + 1); + index = btrfs_inode_ref_index(eb, iref); + dir = found_key->offset; + } else { + extref = (struct btrfs_inode_extref *)(ptr + cur); + name_len = btrfs_inode_extref_name_len(eb, extref); + name_off = (unsigned long)&extref->name; + index = btrfs_inode_extref_index(eb, extref); + dir = btrfs_inode_extref_parent(eb, extref); + } + if (resolve) { - start = btrfs_iref_to_path(root, tmp_path, iref, eb, - found_key->offset, p->buf, - p->buf_len); + start = btrfs_ref_to_path(root, tmp_path, name_len, + name_off, eb, dir, + p->buf, p->buf_len); if (IS_ERR(start)) { ret = PTR_ERR(start); goto out; @@ -809,9 +830,10 @@ static int iterate_inode_ref(struct send_ctx *sctx, p->buf_len + p->buf - start); if (ret < 0) goto out; - start = btrfs_iref_to_path(root, tmp_path, iref, - eb, found_key->offset, p->buf, - p->buf_len); + start = btrfs_ref_to_path(root, tmp_path, + name_len, name_off, + eb, dir, + p->buf, p->buf_len); if (IS_ERR(start)) { ret = PTR_ERR(start); goto out; @@ -820,21 +842,16 @@ static int iterate_inode_ref(struct send_ctx *sctx, } p->start = start; } else { - ret = fs_path_add_from_extent_buffer(p, eb, - (unsigned long)(iref + 1), name_len); + ret = fs_path_add_from_extent_buffer(p, eb, name_off, + name_len); if (ret < 0) goto out; } - - len = sizeof(*iref) + name_len; - iref = (struct btrfs_inode_ref *)((char *)iref + len); - cur += len; - - ret = iterate(num, found_key->offset, index, p, ctx); + cur += elem_size + name_len; + ret = iterate(num, dir, index, p, ctx); if (ret) goto out; - num++; } @@ -998,7 +1015,8 @@ static int get_inode_path(struct send_ctx *sctx, struct btrfs_root *root, } btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); if (found_key.objectid != ino || - found_key.type != BTRFS_INODE_REF_KEY) { + (found_key.type != BTRFS_INODE_REF_KEY && + found_key.type != BTRFS_INODE_EXTREF_KEY)) { ret = -ENOENT; goto out; } @@ -1551,8 +1569,8 @@ static int get_first_ref(struct send_ctx *sctx, struct btrfs_key key; struct btrfs_key found_key; struct btrfs_path *path; - struct btrfs_inode_ref *iref; int len; + u64 parent_dir; path = alloc_path_for_send(); if (!path) @@ -1568,27 +1586,41 @@ static int get_first_ref(struct send_ctx *sctx, if (!ret) btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]); - if (ret || found_key.objectid != key.objectid || - found_key.type != key.type) { + if (ret || found_key.objectid != ino || + (found_key.type != BTRFS_INODE_REF_KEY && + found_key.type != BTRFS_INODE_EXTREF_KEY)) { ret = -ENOENT; goto out; } - iref = btrfs_item_ptr(path->nodes[0], path->slots[0], - struct btrfs_inode_ref); - len = btrfs_inode_ref_name_len(path->nodes[0], iref); - ret = fs_path_add_from_extent_buffer(name, path->nodes[0], - (unsigned long)(iref + 1), len); + if (key.type == BTRFS_INODE_REF_KEY) { + struct btrfs_inode_ref *iref; + iref = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_inode_ref); + len = btrfs_inode_ref_name_len(path->nodes[0], iref); + ret = fs_path_add_from_extent_buffer(name, path->nodes[0], + (unsigned long)(iref + 1), + len); + parent_dir = found_key.offset; + } else { + struct btrfs_inode_extref *extref; + extref = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_inode_extref); + len = btrfs_inode_extref_name_len(path->nodes[0], extref); + ret = fs_path_add_from_extent_buffer(name, path->nodes[0], + (unsigned long)&extref->name, len); + parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref); + } if (ret < 0) goto out; btrfs_release_path(path); - ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL, + ret = get_inode_info(root, parent_dir, NULL, dir_gen, NULL, NULL, NULL, NULL); if (ret < 0) goto out; - *dir = found_key.offset; + *dir = parent_dir; out: btrfs_free_path(path); @@ -2430,7 +2462,8 @@ verbose_printk("btrfs: send_create_inode %llu\n", ino); TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p); } else if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { - TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev); + TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, new_encode_dev(rdev)); + TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode); } ret = send_cmd(sctx); @@ -3226,7 +3259,8 @@ static int process_all_refs(struct send_ctx *sctx, btrfs_item_key_to_cpu(eb, &found_key, slot); if (found_key.objectid != key.objectid || - found_key.type != key.type) + (found_key.type != BTRFS_INODE_REF_KEY && + found_key.type != BTRFS_INODE_EXTREF_KEY)) break; ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, @@ -3987,7 +4021,7 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end) if (sctx->cur_ino == 0) goto out; if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && - sctx->cmp_key->type <= BTRFS_INODE_REF_KEY) + sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY) goto out; if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) goto out; @@ -4033,22 +4067,21 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end) if (ret < 0) goto out; - if (!S_ISLNK(sctx->cur_inode_mode)) { - if (!sctx->parent_root || sctx->cur_inode_new) { + if (!sctx->parent_root || sctx->cur_inode_new) { + need_chown = 1; + if (!S_ISLNK(sctx->cur_inode_mode)) need_chmod = 1; - need_chown = 1; - } else { - ret = get_inode_info(sctx->parent_root, sctx->cur_ino, - NULL, NULL, &right_mode, &right_uid, - &right_gid, NULL); - if (ret < 0) - goto out; + } else { + ret = get_inode_info(sctx->parent_root, sctx->cur_ino, + NULL, NULL, &right_mode, &right_uid, + &right_gid, NULL); + if (ret < 0) + goto out; - if (left_uid != right_uid || left_gid != right_gid) - need_chown = 1; - if (left_mode != right_mode) - need_chmod = 1; - } + if (left_uid != right_uid || left_gid != right_gid) + need_chown = 1; + if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode) + need_chmod = 1; } if (S_ISREG(sctx->cur_inode_mode)) { @@ -4335,7 +4368,8 @@ static int changed_cb(struct btrfs_root *left_root, if (key->type == BTRFS_INODE_ITEM_KEY) ret = changed_inode(sctx, result); - else if (key->type == BTRFS_INODE_REF_KEY) + else if (key->type == BTRFS_INODE_REF_KEY || + key->type == BTRFS_INODE_EXTREF_KEY) ret = changed_ref(sctx, result); else if (key->type == BTRFS_XATTR_ITEM_KEY) ret = changed_xattr(sctx, result); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 77db875b511..04bbfb1052e 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1200,7 +1200,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, btrfs_i_size_write(parent_inode, parent_inode->i_size + dentry->d_name.len * 2); parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; - ret = btrfs_update_inode(trans, parent_root, parent_inode); + ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode); if (ret) btrfs_abort_transaction(trans, root, ret); fail: diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 029b903a4ae..0f5ebb72a5e 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1819,6 +1819,13 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) "Failed to relocate sys chunks after " "device initialization. This can be fixed " "using the \"btrfs balance\" command."); + trans = btrfs_attach_transaction(root); + if (IS_ERR(trans)) { + if (PTR_ERR(trans) == -ENOENT) + return 0; + return PTR_ERR(trans); + } + ret = btrfs_commit_transaction(trans, root); } return ret; diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 02ce90972d8..9349bb37a2f 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len, *max_len = handle_length; type = 255; } + if (dentry) + dput(dentry); return type; } diff --git a/fs/char_dev.c b/fs/char_dev.c index 3f152b92a94..afc2bb69178 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -471,9 +471,19 @@ static int exact_lock(dev_t dev, void *data) */ int cdev_add(struct cdev *p, dev_t dev, unsigned count) { + int error; + p->dev = dev; p->count = count; - return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p); + + error = kobj_map(cdev_map, dev, count, NULL, + exact_match, exact_lock, p); + if (error) + return error; + + kobject_get(p->kobj.parent); + + return 0; } static void cdev_unmap(dev_t dev, unsigned count) @@ -498,14 +508,20 @@ void cdev_del(struct cdev *p) static void cdev_default_release(struct kobject *kobj) { struct cdev *p = container_of(kobj, struct cdev, kobj); + struct kobject *parent = kobj->parent; + cdev_purge(p); + kobject_put(parent); } static void cdev_dynamic_release(struct kobject *kobj) { struct cdev *p = container_of(kobj, struct cdev, kobj); + struct kobject *parent = kobj->parent; + cdev_purge(p); kfree(p); + kobject_put(parent); } static struct kobj_type ktype_cdev_default = { diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index fc783e26442..0fb15bbbe43 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -225,6 +225,13 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr) } static void +cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) +{ + memcpy(dst, src, sizeof(*dst)); + dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS); +} + +static void id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, struct cifs_sid_id **psidid, char *typestr) { @@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, } } - memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); + cifs_copy_sid(&(*psidid)->sid, sidptr); (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); (*psidid)->refcount = 0; @@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) * any fields of the node after a reference is put . */ if (test_bit(SID_ID_MAPPED, &psidid->state)) { - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); + cifs_copy_sid(ssid, &psidid->sid); psidid->time = jiffies; /* update ts for accessing */ goto id_sid_out; } @@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) if (IS_ERR(sidkey)) { rc = -EINVAL; cFYI(1, "%s: Can't map and id to a SID", __func__); + } else if (sidkey->datalen < sizeof(struct cifs_sid)) { + rc = -EIO; + cFYI(1, "%s: Downcall contained malformed key " + "(datalen=%hu)", __func__, sidkey->datalen); } else { lsid = (struct cifs_sid *)sidkey->payload.data; - memcpy(&psidid->sid, lsid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); - memcpy(ssid, &psidid->sid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); + cifs_copy_sid(&psidid->sid, lsid); + cifs_copy_sid(ssid, &psidid->sid); set_bit(SID_ID_MAPPED, &psidid->state); key_put(sidkey); kfree(psidid->sidstr); @@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) return rc; } if (test_bit(SID_ID_MAPPED, &psidid->state)) - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); + cifs_copy_sid(ssid, &psidid->sid); else rc = -EINVAL; } @@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) static void copy_sec_desc(const struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, __u32 sidsoffset) { - int i; - struct cifs_sid *owner_sid_ptr, *group_sid_ptr; struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; @@ -692,26 +697,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd, owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->osidoffset)); nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); - - nowner_sid_ptr->revision = owner_sid_ptr->revision; - nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i]; + cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr); /* copy group sid */ group_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->gsidoffset)); ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset + sizeof(struct cifs_sid)); - - ngroup_sid_ptr->revision = group_sid_ptr->revision; - ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i]; + cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr); return; } @@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, kfree(nowner_sid_ptr); return rc; } - memcpy(owner_sid_ptr, nowner_sid_ptr, - sizeof(struct cifs_sid)); + cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr); kfree(nowner_sid_ptr); *aclflag = CIFS_ACL_OWNER; } @@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, kfree(ngroup_sid_ptr); return rc; } - memcpy(group_sid_ptr, ngroup_sid_ptr, - sizeof(struct cifs_sid)); + cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr); kfree(ngroup_sid_ptr); *aclflag = CIFS_ACL_GROUP; } diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 7c0a8128364..d3671f2acb2 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -398,7 +398,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry, * in network traffic in the other paths. */ if (!(oflags & O_CREAT)) { - struct dentry *res = cifs_lookup(inode, direntry, 0); + struct dentry *res; + + /* + * Check for hashed negative dentry. We have already revalidated + * the dentry and it is fine. No need to perform another lookup. + */ + if (!d_unhashed(direntry)) + return -ENOENT; + + res = cifs_lookup(inode, direntry, 0); if (IS_ERR(res)) return PTR_ERR(res); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index f5054025f9d..4c6285fff59 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, err = get_user(palp, &up->palette); err |= get_user(length, &up->length); + if (err) + return -EFAULT; up_native = compat_alloc_user_space(sizeof(struct video_spu_palette)); err = put_user(compat_ptr(palp), &up_native->palette); diff --git a/fs/coredump.c b/fs/coredump.c index fd37facac8d..ce47379bfa6 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -450,11 +450,12 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) cp->file = files[1]; - replace_fd(0, files[0], 0); + err = replace_fd(0, files[0], 0); + fput(files[0]); /* and disallow core files too */ current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; - return 0; + return err; } void do_coredump(siginfo_t *siginfo, struct pt_regs *regs) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index da72250ddc1..cd96649bfe6 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -346,7 +346,7 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p) /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */ static inline int ep_op_has_event(int op) { - return op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD; + return op != EPOLL_CTL_DEL; } /* Initialize the poll safe wake up structure */ @@ -676,34 +676,6 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi) return 0; } -/* - * Disables a "struct epitem" in the eventpoll set. Returns -EBUSY if the item - * had no event flags set, indicating that another thread may be currently - * handling that item's events (in the case that EPOLLONESHOT was being - * used). Otherwise a zero result indicates that the item has been disabled - * from receiving events. A disabled item may be re-enabled via - * EPOLL_CTL_MOD. Must be called with "mtx" held. - */ -static int ep_disable(struct eventpoll *ep, struct epitem *epi) -{ - int result = 0; - unsigned long flags; - - spin_lock_irqsave(&ep->lock, flags); - if (epi->event.events & ~EP_PRIVATE_BITS) { - if (ep_is_linked(&epi->rdllink)) - list_del_init(&epi->rdllink); - /* Ensure ep_poll_callback will not add epi back onto ready - list: */ - epi->event.events &= EP_PRIVATE_BITS; - } - else - result = -EBUSY; - spin_unlock_irqrestore(&ep->lock, flags); - - return result; -} - static void ep_free(struct eventpoll *ep) { struct rb_node *rbp; @@ -1048,6 +1020,8 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) rb_insert_color(&epi->rbn, &ep->rbr); } + + #define PATH_ARR_SIZE 5 /* * These are the number paths of length 1 to 5, that we are allowing to emanate @@ -1813,12 +1787,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, } else error = -ENOENT; break; - case EPOLL_CTL_DISABLE: - if (epi) - error = ep_disable(ep, epi); - else - error = -ENOENT; - break; } mutex_unlock(&ep->mtx); diff --git a/fs/exec.c b/fs/exec.c index 8b9011b6704..0039055b1fc 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1083,7 +1083,8 @@ int flush_old_exec(struct linux_binprm * bprm) bprm->mm = NULL; /* We're using it now */ set_fs(USER_DS); - current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD); + current->flags &= + ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE); flush_thread(); current->personality &= ~bprm->per_clear; diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 6c205d0c565..fa04d023177 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -469,7 +469,7 @@ static int parse_options(char *options, struct super_block *sb) uid = make_kuid(current_user_ns(), option); if (!uid_valid(uid)) { ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option); - return -1; + return 0; } sbi->s_resuid = uid; @@ -480,7 +480,7 @@ static int parse_options(char *options, struct super_block *sb) gid = make_kgid(current_user_ns(), option); if (!gid_valid(gid)) { ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option); - return -1; + return 0; } sbi->s_resgid = gid; break; diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 7320a66e958..22548f56197 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -2101,8 +2101,9 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range) end = start + (range->len >> sb->s_blocksize_bits) - 1; minlen = range->minlen >> sb->s_blocksize_bits; - if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) || - unlikely(start >= max_blks)) + if (minlen > EXT3_BLOCKS_PER_GROUP(sb) || + start >= max_blks || + range->len < sb->s_blocksize) return -EINVAL; if (end >= max_blks) end = max_blks - 1; diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 8f4fddac01a..890b8947c54 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -46,8 +46,7 @@ static struct buffer_head *ext3_append(handle_t *handle, *block = inode->i_size >> inode->i_sb->s_blocksize_bits; - bh = ext3_bread(handle, inode, *block, 1, err); - if (bh) { + if ((bh = ext3_dir_bread(handle, inode, *block, 1, err))) { inode->i_size += inode->i_sb->s_blocksize; EXT3_I(inode)->i_disksize = inode->i_size; *err = ext3_journal_get_write_access(handle, bh); @@ -339,8 +338,10 @@ dx_probe(struct qstr *entry, struct inode *dir, u32 hash; frame->bh = NULL; - if (!(bh = ext3_bread (NULL,dir, 0, 0, err))) + if (!(bh = ext3_dir_bread(NULL, dir, 0, 0, err))) { + *err = ERR_BAD_DX_DIR; goto fail; + } root = (struct dx_root *) bh->b_data; if (root->info.hash_version != DX_HASH_TEA && root->info.hash_version != DX_HASH_HALF_MD4 && @@ -436,8 +437,10 @@ dx_probe(struct qstr *entry, struct inode *dir, frame->entries = entries; frame->at = at; if (!indirect--) return frame; - if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) + if (!(bh = ext3_dir_bread(NULL, dir, dx_get_block(at), 0, err))) { + *err = ERR_BAD_DX_DIR; goto fail2; + } at = entries = ((struct dx_node *) bh->b_data)->entries; if (dx_get_limit(entries) != dx_node_limit (dir)) { ext3_warning(dir->i_sb, __func__, @@ -535,8 +538,8 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash, * block so no check is necessary */ while (num_frames--) { - if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), - 0, &err))) + if (!(bh = ext3_dir_bread(NULL, dir, dx_get_block(p->at), + 0, &err))) return err; /* Failure */ p++; brelse (p->bh); @@ -559,10 +562,11 @@ static int htree_dirblock_to_tree(struct file *dir_file, { struct buffer_head *bh; struct ext3_dir_entry_2 *de, *top; - int err, count = 0; + int err = 0, count = 0; dxtrace(printk("In htree dirblock_to_tree: block %d\n", block)); - if (!(bh = ext3_bread (NULL, dir, block, 0, &err))) + + if (!(bh = ext3_dir_bread(NULL, dir, block, 0, &err))) return err; de = (struct ext3_dir_entry_2 *) bh->b_data; @@ -976,7 +980,7 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir, return NULL; do { block = dx_get_block(frame->at); - if (!(bh = ext3_bread (NULL,dir, block, 0, err))) + if (!(bh = ext3_dir_bread (NULL, dir, block, 0, err))) goto errout; retval = search_dirblock(bh, dir, entry, @@ -1458,9 +1462,9 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry, } blocks = dir->i_size >> sb->s_blocksize_bits; for (block = 0; block < blocks; block++) { - bh = ext3_bread(handle, dir, block, 0, &retval); - if(!bh) + if (!(bh = ext3_dir_bread(handle, dir, block, 0, &retval))) return retval; + retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh); if (retval != -ENOSPC) return retval; @@ -1500,7 +1504,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, entries = frame->entries; at = frame->at; - if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err))) + if (!(bh = ext3_dir_bread(handle, dir, dx_get_block(frame->at), 0, &err))) goto cleanup; BUFFER_TRACE(bh, "get_write_access"); @@ -1790,8 +1794,7 @@ retry: inode->i_op = &ext3_dir_inode_operations; inode->i_fop = &ext3_dir_operations; inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; - dir_block = ext3_bread (handle, inode, 0, 1, &err); - if (!dir_block) + if (!(dir_block = ext3_dir_bread(handle, inode, 0, 1, &err))) goto out_clear_inode; BUFFER_TRACE(dir_block, "get_write_access"); @@ -1859,7 +1862,7 @@ static int empty_dir (struct inode * inode) sb = inode->i_sb; if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) || - !(bh = ext3_bread (NULL, inode, 0, 0, &err))) { + !(bh = ext3_dir_bread(NULL, inode, 0, 0, &err))) { if (err) ext3_error(inode->i_sb, __func__, "error %d reading directory #%lu offset 0", @@ -1890,9 +1893,8 @@ static int empty_dir (struct inode * inode) (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { err = 0; brelse (bh); - bh = ext3_bread (NULL, inode, - offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err); - if (!bh) { + if (!(bh = ext3_dir_bread (NULL, inode, + offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err))) { if (err) ext3_error(sb, __func__, "error %d reading directory" @@ -2388,7 +2390,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, goto end_rename; } retval = -EIO; - dir_bh = ext3_bread (handle, old_inode, 0, 0, &retval); + dir_bh = ext3_dir_bread(handle, old_inode, 0, 0, &retval); if (!dir_bh) goto end_rename; if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) diff --git a/fs/ext3/namei.h b/fs/ext3/namei.h index f2ce2b0065c..46304d8c9f0 100644 --- a/fs/ext3/namei.h +++ b/fs/ext3/namei.h @@ -6,3 +6,22 @@ */ extern struct dentry *ext3_get_parent(struct dentry *child); + +static inline struct buffer_head *ext3_dir_bread(handle_t *handle, + struct inode *inode, + int block, int create, + int *err) +{ + struct buffer_head *bh; + + bh = ext3_bread(handle, inode, block, create, err); + + if (!bh && !(*err)) { + *err = -EIO; + ext3_error(inode->i_sb, __func__, + "Directory hole detected on inode %lu\n", + inode->i_ino); + return NULL; + } + return bh; +} diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 29e79713c7e..5366393528d 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1001,7 +1001,7 @@ static int parse_options (char *options, struct super_block *sb, uid = make_kuid(current_user_ns(), option); if (!uid_valid(uid)) { ext3_msg(sb, KERN_ERR, "Invalid uid value %d", option); - return -1; + return 0; } sbi->s_resuid = uid; @@ -1012,7 +1012,7 @@ static int parse_options (char *options, struct super_block *sb, gid = make_kgid(current_user_ns(), option); if (!gid_valid(gid)) { ext3_msg(sb, KERN_ERR, "Invalid gid value %d", option); - return -1; + return 0; } sbi->s_resgid = gid; break; diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 1b5089067d0..cf1821784a1 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -174,8 +174,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, ext4_free_inodes_set(sb, gdp, 0); ext4_itable_unused_set(sb, gdp, 0); memset(bh->b_data, 0xff, sb->s_blocksize); - ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, block_group, gdp, bh); return; } memset(bh->b_data, 0, sb->s_blocksize); @@ -212,8 +211,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, */ ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group), sb->s_blocksize * 8, bh->b_data); - ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, block_group, gdp, bh); ext4_group_desc_csum_set(sb, block_group, gdp); } @@ -350,7 +348,7 @@ void ext4_validate_block_bitmap(struct super_block *sb, return; } if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, - desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) { + desc, bh))) { ext4_unlock_group(sb, block_group); ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); return; diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index 5c2d1813ebe..3285aa5a706 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -58,11 +58,12 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group, int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, - struct buffer_head *bh, int sz) + struct buffer_head *bh) { __u32 hi; __u32 provided, calculated; struct ext4_sb_info *sbi = EXT4_SB(sb); + int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8; if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) @@ -84,8 +85,9 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, - struct buffer_head *bh, int sz) + struct buffer_head *bh) { + int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8; __u32 csum; struct ext4_sb_info *sbi = EXT4_SB(sb); diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 3ab2539b7b2..3c20de1d59d 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1882,10 +1882,10 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, struct buffer_head *bh, int sz); void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, - struct buffer_head *bh, int sz); + struct buffer_head *bh); int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, - struct buffer_head *bh, int sz); + struct buffer_head *bh); /* balloc.c */ extern void ext4_validate_block_bitmap(struct super_block *sb, @@ -2063,8 +2063,7 @@ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); extern int ext4_calculate_overhead(struct super_block *sb); extern int ext4_superblock_csum_verify(struct super_block *sb, struct ext4_super_block *es); -extern void ext4_superblock_csum_set(struct super_block *sb, - struct ext4_super_block *es); +extern void ext4_superblock_csum_set(struct super_block *sb); extern void *ext4_kvmalloc(size_t size, gfp_t flags); extern void *ext4_kvzalloc(size_t size, gfp_t flags); extern void ext4_kvfree(void *ptr); diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index bfa65b49d42..b4323ba846b 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c @@ -143,17 +143,13 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line, struct buffer_head *bh = EXT4_SB(sb)->s_sbh; int err = 0; + ext4_superblock_csum_set(sb); if (ext4_handle_valid(handle)) { - ext4_superblock_csum_set(sb, - (struct ext4_super_block *)bh->b_data); err = jbd2_journal_dirty_metadata(handle, bh); if (err) ext4_journal_abort_handle(where, line, __func__, bh, handle, err); - } else { - ext4_superblock_csum_set(sb, - (struct ext4_super_block *)bh->b_data); + } else mark_buffer_dirty(bh); - } return err; } diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 1c94cca35ed..7011ac96720 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -52,6 +52,9 @@ #define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ #define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ +#define EXT4_EXT_DATA_VALID1 0x8 /* first half contains valid data */ +#define EXT4_EXT_DATA_VALID2 0x10 /* second half contains valid data */ + static __le32 ext4_extent_block_csum(struct inode *inode, struct ext4_extent_header *eh) { @@ -2914,6 +2917,9 @@ static int ext4_split_extent_at(handle_t *handle, unsigned int ee_len, depth; int err = 0; + BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == + (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); + ext_debug("ext4_split_extents_at: inode %lu, logical" "block %llu\n", inode->i_ino, (unsigned long long)split); @@ -2972,7 +2978,14 @@ static int ext4_split_extent_at(handle_t *handle, err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { - err = ext4_ext_zeroout(inode, &orig_ex); + if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { + if (split_flag & EXT4_EXT_DATA_VALID1) + err = ext4_ext_zeroout(inode, ex2); + else + err = ext4_ext_zeroout(inode, ex); + } else + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) goto fix_extent_len; /* update the extent length and mark as initialized */ @@ -3025,12 +3038,13 @@ static int ext4_split_extent(handle_t *handle, uninitialized = ext4_ext_is_uninitialized(ex); if (map->m_lblk + map->m_len < ee_block + ee_len) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; + split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; if (uninitialized) split_flag1 |= EXT4_EXT_MARK_UNINIT1 | EXT4_EXT_MARK_UNINIT2; + if (split_flag & EXT4_EXT_DATA_VALID2) + split_flag1 |= EXT4_EXT_DATA_VALID1; err = ext4_split_extent_at(handle, inode, path, map->m_lblk + map->m_len, split_flag1, flags1); if (err) @@ -3043,8 +3057,8 @@ static int ext4_split_extent(handle_t *handle, return PTR_ERR(path); if (map->m_lblk >= ee_block) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; + split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT | + EXT4_EXT_DATA_VALID2); if (uninitialized) split_flag1 |= EXT4_EXT_MARK_UNINIT1; if (split_flag & EXT4_EXT_MARK_UNINIT2) @@ -3323,26 +3337,47 @@ static int ext4_split_unwritten_extents(handle_t *handle, split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; split_flag |= EXT4_EXT_MARK_UNINIT2; - + if (flags & EXT4_GET_BLOCKS_CONVERT) + split_flag |= EXT4_EXT_DATA_VALID2; flags |= EXT4_GET_BLOCKS_PRE_IO; return ext4_split_extent(handle, inode, path, map, split_flag, flags); } static int ext4_convert_unwritten_extents_endio(handle_t *handle, - struct inode *inode, - struct ext4_ext_path *path) + struct inode *inode, + struct ext4_map_blocks *map, + struct ext4_ext_path *path) { struct ext4_extent *ex; + ext4_lblk_t ee_block; + unsigned int ee_len; int depth; int err = 0; depth = ext_depth(inode); ex = path[depth].p_ext; + ee_block = le32_to_cpu(ex->ee_block); + ee_len = ext4_ext_get_actual_len(ex); ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" "block %llu, max_blocks %u\n", inode->i_ino, - (unsigned long long)le32_to_cpu(ex->ee_block), - ext4_ext_get_actual_len(ex)); + (unsigned long long)ee_block, ee_len); + + /* If extent is larger than requested then split is required */ + if (ee_block != map->m_lblk || ee_len > map->m_len) { + err = ext4_split_unwritten_extents(handle, inode, map, path, + EXT4_GET_BLOCKS_CONVERT); + if (err < 0) + goto out; + ext4_ext_drop_refs(path); + path = ext4_ext_find_extent(inode, map->m_lblk, path); + if (IS_ERR(path)) { + err = PTR_ERR(path); + goto out; + } + depth = ext_depth(inode); + ex = path[depth].p_ext; + } err = ext4_ext_get_access(handle, inode, path + depth); if (err) @@ -3652,7 +3687,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, } /* IO end_io complete, convert the filled extent to written */ if ((flags & EXT4_GET_BLOCKS_CONVERT)) { - ret = ext4_convert_unwritten_extents_endio(handle, inode, + ret = ext4_convert_unwritten_extents_endio(handle, inode, map, path); if (ret >= 0) { ext4_update_inode_fsync_trans(handle, inode, 1); @@ -4428,6 +4463,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) */ if (len <= EXT_UNINIT_MAX_LEN << blkbits) flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; + + /* Prevent race condition between unwritten */ + ext4_flush_unwritten_io(inode); retry: while (ret >= 0 && ret < max_blocks) { map.m_lblk = map.m_lblk + ret; diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index fa36372f3fd..3a100e7a62a 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -725,6 +725,10 @@ repeat_in_this_group: "inode=%lu", ino + 1); continue; } + BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, inode_bitmap_bh); + if (err) + goto fail; ext4_lock_group(sb, group); ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); ext4_unlock_group(sb, group); @@ -738,6 +742,11 @@ repeat_in_this_group: goto out; got: + BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); + err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); + if (err) + goto fail; + /* We may have to initialize the block bitmap if it isn't already */ if (ext4_has_group_desc_csum(sb) && gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { @@ -762,9 +771,7 @@ got: ext4_free_group_clusters_set(sb, gdp, ext4_free_clusters_after_init(sb, group, gdp)); ext4_block_bitmap_csum_set(sb, group, gdp, - block_bitmap_bh, - EXT4_BLOCKS_PER_GROUP(sb) / - 8); + block_bitmap_bh); ext4_group_desc_csum_set(sb, group, gdp); } ext4_unlock_group(sb, group); @@ -773,11 +780,6 @@ got: goto fail; } - BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); - err = ext4_journal_get_write_access(handle, inode_bitmap_bh); - if (err) - goto fail; - BUFFER_TRACE(group_desc_bh, "get_write_access"); err = ext4_journal_get_write_access(handle, group_desc_bh); if (err) @@ -825,11 +827,6 @@ got: } ext4_unlock_group(sb, group); - BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); - err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); - if (err) - goto fail; - BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); if (err) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index f8b27bf80ac..526e5535860 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2805,8 +2805,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, } len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len; ext4_free_group_clusters_set(sb, gdp, len); - ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh); ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp); ext4_unlock_group(sb, ac->ac_b_ex.fe_group); @@ -4666,8 +4665,7 @@ do_more: ret = ext4_free_group_clusters(sb, gdp) + count_clusters; ext4_free_group_clusters_set(sb, gdp, ret); - ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh); ext4_group_desc_csum_set(sb, block_group, gdp); ext4_unlock_group(sb, block_group); percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters); @@ -4811,8 +4809,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, mb_free_blocks(NULL, &e4b, bit, count); blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc); ext4_free_group_clusters_set(sb, desc, blk_free_count); - ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh); ext4_group_desc_csum_set(sb, block_group, desc); ext4_unlock_group(sb, block_group); percpu_counter_add(&sbi->s_freeclusters_counter, @@ -4993,8 +4990,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) minlen = EXT4_NUM_B2C(EXT4_SB(sb), range->minlen >> sb->s_blocksize_bits); - if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) || - unlikely(start >= max_blks)) + if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) || + start >= max_blks || + range->len < sb->s_blocksize) return -EINVAL; if (end >= max_blks) end = max_blks - 1; diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 7a75e108696..47bf06a2765 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1212,8 +1212,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb, bh = ext4_get_bitmap(sb, group_data->block_bitmap); if (!bh) return -EIO; - ext4_block_bitmap_csum_set(sb, group, gdp, bh, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + ext4_block_bitmap_csum_set(sb, group, gdp, bh); brelse(bh); return 0; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 7265a036747..80928f71685 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -143,9 +143,10 @@ int ext4_superblock_csum_verify(struct super_block *sb, return es->s_checksum == ext4_superblock_csum(sb, es); } -void ext4_superblock_csum_set(struct super_block *sb, - struct ext4_super_block *es) +void ext4_superblock_csum_set(struct super_block *sb) { + struct ext4_super_block *es = EXT4_SB(sb)->s_es; + if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) return; @@ -1963,7 +1964,7 @@ static int ext4_fill_flex_info(struct super_block *sb) sbi->s_log_groups_per_flex = 0; return 1; } - groups_per_flex = 1 << sbi->s_log_groups_per_flex; + groups_per_flex = 1U << sbi->s_log_groups_per_flex; err = ext4_alloc_flex_bg_array(sb, sbi->s_groups_count); if (err) @@ -4381,7 +4382,7 @@ static int ext4_commit_super(struct super_block *sb, int sync) cpu_to_le32(percpu_counter_sum_positive( &EXT4_SB(sb)->s_freeinodes_counter)); BUFFER_TRACE(sbh, "marking dirty"); - ext4_superblock_csum_set(sb, es); + ext4_superblock_csum_set(sb); mark_buffer_dirty(sbh); if (sync) { error = sync_dirty_buffer(sbh); diff --git a/fs/file.c b/fs/file.c index d3b5fa80b71..7272a1c5831 100644 --- a/fs/file.c +++ b/fs/file.c @@ -519,12 +519,6 @@ struct files_struct init_files = { .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), }; -void daemonize_descriptors(void) -{ - atomic_inc(&init_files.count); - reset_files_struct(&init_files); -} - /* * allocate a file descriptor, mark it busy. */ @@ -685,7 +679,6 @@ void do_close_on_exec(struct files_struct *files) struct fdtable *fdt; /* exec unshares first */ - BUG_ON(atomic_read(&files->count) != 1); spin_lock(&files->file_lock); for (i = 0; ; i++) { unsigned long set; @@ -900,7 +893,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags) return __close_fd(files, fd); if (fd >= rlimit(RLIMIT_NOFILE)) - return -EMFILE; + return -EBADF; spin_lock(&files->file_lock); err = expand_files(files, fd); @@ -926,7 +919,7 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags) return -EINVAL; if (newfd >= rlimit(RLIMIT_NOFILE)) - return -EMFILE; + return -EBADF; spin_lock(&files->file_lock); err = expand_files(files, newfd); diff --git a/fs/fs_struct.c b/fs/fs_struct.c index 5df4775fea0..fe6ca583bbc 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c @@ -164,27 +164,3 @@ struct fs_struct init_fs = { .seq = SEQCNT_ZERO, .umask = 0022, }; - -void daemonize_fs_struct(void) -{ - struct fs_struct *fs = current->fs; - - if (fs) { - int kill; - - task_lock(current); - - spin_lock(&init_fs.lock); - init_fs.users++; - spin_unlock(&init_fs.lock); - - spin_lock(&fs->lock); - current->fs = &init_fs; - kill = !--fs->users; - spin_unlock(&fs->lock); - - task_unlock(current); - if (kill) - free_fs_struct(fs); - } -} diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 0def0504afc..e056b4ce487 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -516,15 +516,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) struct gfs2_holder i_gh; int error; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); - error = gfs2_glock_nq(&i_gh); - if (error == 0) { - file_accessed(file); - gfs2_glock_dq(&i_gh); - } - gfs2_holder_uninit(&i_gh); + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, + &i_gh); if (error) return error; + /* grab lock to update inode */ + gfs2_glock_dq_uninit(&i_gh); + file_accessed(file); } vma->vm_ops = &gfs2_vm_ops; @@ -677,10 +675,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, size_t writesize = iov_length(iov, nr_segs); struct dentry *dentry = file->f_dentry; struct gfs2_inode *ip = GFS2_I(dentry->d_inode); - struct gfs2_sbd *sdp; int ret; - sdp = GFS2_SB(file->f_mapping->host); ret = gfs2_rs_alloc(ip); if (ret) return ret; diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 8ff95a2d54e..9ceccb1595a 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) struct gfs2_meta_header *mh; struct gfs2_trans *tr; - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); tr = current->journal_info; tr->tr_touched = 1; if (!list_empty(&bd->bd_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; @@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) sdp->sd_log_num_buf++; list_add(&bd->bd_list, &sdp->sd_log_le_buf); tr->tr_num_buf_new++; -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } static void gfs2_check_magic(struct buffer_head *bh) @@ -621,7 +616,6 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) static void revoke_lo_before_commit(struct gfs2_sbd *sdp) { - struct gfs2_log_descriptor *ld; struct gfs2_meta_header *mh; unsigned int offset; struct list_head *head = &sdp->sd_log_le_revoke; @@ -634,7 +628,6 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) length = gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, sizeof(u64)); page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE, length, sdp->sd_log_num_revoke); - ld = page_address(page); offset = sizeof(struct gfs2_log_descriptor); list_for_each_entry(bd, head, bd_list) { @@ -777,12 +770,10 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) struct address_space *mapping = bd->bd_bh->b_page->mapping; struct gfs2_inode *ip = GFS2_I(mapping->host); - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); if (tr) tr->tr_touched = 1; if (!list_empty(&bd->bd_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); if (gfs2_is_jdata(ip)) { @@ -793,9 +784,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) } else { list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered); } -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } /** diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 40c4b0d42fa..c5af8e18f27 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -497,8 +497,11 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) struct gfs2_quota_data **qd; int error; - if (ip->i_res == NULL) - gfs2_rs_alloc(ip); + if (ip->i_res == NULL) { + error = gfs2_rs_alloc(ip); + if (error) + return error; + } qd = ip->i_res->rs_qa_qd; diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 3cc402ce6fe..38fe18f2f05 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -553,7 +553,6 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd) */ int gfs2_rs_alloc(struct gfs2_inode *ip) { - int error = 0; struct gfs2_blkreserv *res; if (ip->i_res) @@ -561,7 +560,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip) res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS); if (!res) - error = -ENOMEM; + return -ENOMEM; RB_CLEAR_NODE(&res->rs_node); @@ -571,7 +570,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip) else ip->i_res = res; up_write(&ip->i_rw_mutex); - return error; + return 0; } static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs) @@ -1263,7 +1262,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp) int ret = 0; u64 amt; u64 trimmed = 0; + u64 start, end, minlen; unsigned int x; + unsigned bs_shift = sdp->sd_sb.sb_bsize_shift; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1271,19 +1272,25 @@ int gfs2_fitrim(struct file *filp, void __user *argp) if (!blk_queue_discard(q)) return -EOPNOTSUPP; - if (argp == NULL) { - r.start = 0; - r.len = ULLONG_MAX; - r.minlen = 0; - } else if (copy_from_user(&r, argp, sizeof(r))) + if (copy_from_user(&r, argp, sizeof(r))) return -EFAULT; ret = gfs2_rindex_update(sdp); if (ret) return ret; - rgd = gfs2_blk2rgrpd(sdp, r.start, 0); - rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0); + start = r.start >> bs_shift; + end = start + (r.len >> bs_shift); + minlen = max_t(u64, r.minlen, + q->limits.discard_granularity) >> bs_shift; + + rgd = gfs2_blk2rgrpd(sdp, start, 0); + rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0); + + if (end <= start || + minlen > sdp->sd_max_rg_data || + start > rgd_end->rd_data0 + rgd_end->rd_data) + return -EINVAL; while (1) { @@ -1295,7 +1302,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp) /* Trim each bitmap in the rgrp */ for (x = 0; x < rgd->rd_length; x++) { struct gfs2_bitmap *bi = rgd->rd_bits + x; - ret = gfs2_rgrp_send_discards(sdp, rgd->rd_data0, NULL, bi, r.minlen, &amt); + ret = gfs2_rgrp_send_discards(sdp, + rgd->rd_data0, NULL, bi, minlen, + &amt); if (ret) { gfs2_glock_dq_uninit(&gh); goto out; @@ -1324,7 +1333,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp) out: r.len = trimmed << 9; - if (argp && copy_to_user(argp, &r, sizeof(r))) + if (copy_to_user(argp, &r, sizeof(r))) return -EFAULT; return ret; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index bc737261f23..d6488674d91 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags) return; } need_unlock = 1; - } + } else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE)) + return; if (current->journal_info == NULL) { ret = gfs2_trans_begin(sdp, RES_DINODE, 0); diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index adbd27875ef..413627072f3 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta) struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_bufdata *bd; + lock_buffer(bh); + gfs2_log_lock(sdp); bd = bh->b_private; if (bd) gfs2_assert(sdp, bd->bd_gl == gl); else { + gfs2_log_unlock(sdp); + unlock_buffer(bh); gfs2_attach_bufdata(gl, bh, meta); bd = bh->b_private; + lock_buffer(bh); + gfs2_log_lock(sdp); } lops_add(sdp, bd); + gfs2_log_unlock(sdp); + unlock_buffer(bh); } void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 60ef3fb707f..1506673c087 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, struct page *pg; struct inode *inode = mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_raw_inode ri; + uint32_t alloc_len = 0; pgoff_t index = pos >> PAGE_CACHE_SHIFT; uint32_t pageofs = index << PAGE_CACHE_SHIFT; int ret = 0; + jffs2_dbg(1, "%s()\n", __func__); + + if (pageofs > inode->i_size) { + ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + if (ret) + return ret; + } + + mutex_lock(&f->sem); pg = grab_cache_page_write_begin(mapping, index, flags); - if (!pg) + if (!pg) { + if (alloc_len) + jffs2_complete_reservation(c); + mutex_unlock(&f->sem); return -ENOMEM; + } *pagep = pg; - jffs2_dbg(1, "%s()\n", __func__); - - if (pageofs > inode->i_size) { + if (alloc_len) { /* Make new hole frag from old EOF to new page */ - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; - uint32_t alloc_len; jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs); - ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, - ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); - if (ret) - goto out_page; - - mutex_lock(&f->sem); memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, if (IS_ERR(fn)) { ret = PTR_ERR(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } ret = jffs2_add_full_dnode_to_inode(c, f, fn); @@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } jffs2_complete_reservation(c); inode->i_size = pageofs; - mutex_unlock(&f->sem); } /* @@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, * case of a short-copy. */ if (!PageUptodate(pg)) { - mutex_lock(&f->sem); ret = jffs2_do_readpage_nolock(inode, pg); - mutex_unlock(&f->sem); if (ret) goto out_page; } + mutex_unlock(&f->sem); jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); return ret; out_page: unlock_page(pg); page_cache_release(pg); + mutex_unlock(&f->sem); return ret; } diff --git a/fs/jfs/jfs_discard.c b/fs/jfs/jfs_discard.c index 9947563e417..dfcd5030455 100644 --- a/fs/jfs/jfs_discard.c +++ b/fs/jfs/jfs_discard.c @@ -83,7 +83,7 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range) struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; struct super_block *sb = ipbmap->i_sb; int agno, agno_end; - s64 start, end, minlen; + u64 start, end, minlen; u64 trimmed = 0; /** @@ -93,15 +93,19 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range) * minlen: minimum extent length in Bytes */ start = range->start >> sb->s_blocksize_bits; - if (start < 0) - start = 0; end = start + (range->len >> sb->s_blocksize_bits) - 1; - if (end >= bmp->db_mapsize) - end = bmp->db_mapsize - 1; minlen = range->minlen >> sb->s_blocksize_bits; - if (minlen <= 0) + if (minlen == 0) minlen = 1; + if (minlen > bmp->db_agsize || + start >= bmp->db_mapsize || + range->len < sb->s_blocksize) + return -EINVAL; + + if (end >= bmp->db_mapsize) + end = bmp->db_mapsize - 1; + /** * we trim all ag's within the range */ diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c index d269ada7670..982d2676e1f 100644 --- a/fs/lockd/clntxdr.c +++ b/fs/lockd/clntxdr.c @@ -223,7 +223,7 @@ static void encode_nlm_stat(struct xdr_stream *xdr, { __be32 *p; - BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); + WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); p = xdr_reserve_space(xdr, 4); *p = stat; } diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index e4fb3ba5a58..3d7e09bcc0e 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net) return rpc_create(&args); } +static struct rpc_clnt *nsm_client_set(struct lockd_net *ln, + struct rpc_clnt *clnt) +{ + spin_lock(&ln->nsm_clnt_lock); + if (ln->nsm_users == 0) { + if (clnt == NULL) + goto out; + ln->nsm_clnt = clnt; + } + clnt = ln->nsm_clnt; + ln->nsm_users++; +out: + spin_unlock(&ln->nsm_clnt_lock); + return clnt; +} + static struct rpc_clnt *nsm_client_get(struct net *net) { - static DEFINE_MUTEX(nsm_create_mutex); - struct rpc_clnt *clnt; + struct rpc_clnt *clnt, *new; struct lockd_net *ln = net_generic(net, lockd_net_id); - spin_lock(&ln->nsm_clnt_lock); - if (ln->nsm_users) { - ln->nsm_users++; - clnt = ln->nsm_clnt; - spin_unlock(&ln->nsm_clnt_lock); + clnt = nsm_client_set(ln, NULL); + if (clnt != NULL) goto out; - } - spin_unlock(&ln->nsm_clnt_lock); - mutex_lock(&nsm_create_mutex); - clnt = nsm_create(net); - if (!IS_ERR(clnt)) { - ln->nsm_clnt = clnt; - smp_wmb(); - ln->nsm_users = 1; - } - mutex_unlock(&nsm_create_mutex); + clnt = new = nsm_create(net); + if (IS_ERR(clnt)) + goto out; + + clnt = nsm_client_set(ln, new); + if (clnt != new) + rpc_shutdown_client(new); out: return clnt; } @@ -115,18 +124,16 @@ out: static void nsm_client_put(struct net *net) { struct lockd_net *ln = net_generic(net, lockd_net_id); - struct rpc_clnt *clnt = ln->nsm_clnt; - int shutdown = 0; + struct rpc_clnt *clnt = NULL; spin_lock(&ln->nsm_clnt_lock); - if (ln->nsm_users) { - if (--ln->nsm_users) - ln->nsm_clnt = NULL; - shutdown = !ln->nsm_users; + ln->nsm_users--; + if (ln->nsm_users == 0) { + clnt = ln->nsm_clnt; + ln->nsm_clnt = NULL; } spin_unlock(&ln->nsm_clnt_lock); - - if (shutdown) + if (clnt != NULL) rpc_shutdown_client(clnt); } diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 3009a365e08..21171f0c647 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -68,7 +68,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain file pointer. Not used by FREE_ALL call. */ if (filp != NULL) { - if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) + error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh)); + if (error != 0) goto no_locks; *filp = file; diff --git a/fs/namei.c b/fs/namei.c index d1895f30815..937f9d50c84 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -705,8 +705,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki path_put(link); } -int sysctl_protected_symlinks __read_mostly = 1; -int sysctl_protected_hardlinks __read_mostly = 1; +int sysctl_protected_symlinks __read_mostly = 0; +int sysctl_protected_hardlinks __read_mostly = 0; /** * may_follow_link - Check symlink following for unsafe situations diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 9a521fb3986..5088b57b078 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -241,7 +241,7 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, svc_exit_thread(cb_info->rqst); cb_info->rqst = NULL; cb_info->task = NULL; - return PTR_ERR(cb_info->task); + return ret; } dprintk("nfs_callback_up: service started\n"); return 0; diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index 31c26c4dcc2..ca4b11ec87a 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) { char buf1[NFS_DNS_HOSTNAME_MAXLEN+1]; struct nfs_dns_ent key, *item; - unsigned long ttl; + unsigned int ttl; ssize_t len; int ret = -EINVAL; @@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) key.namelen = len; memset(&key.h, 0, sizeof(key.h)); - ttl = get_expiry(&buf); + if (get_uint(&buf, &ttl) < 0) + goto out; if (ttl == 0) goto out; key.h.expiry_time = ttl + seconds_since_boot(); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 5c7325c5c5e..6fa01aea248 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) if (ctx->cred != NULL) put_rpccred(ctx->cred); dput(ctx->dentry); - nfs_sb_deactive(sb); + if (is_sync) + nfs_sb_deactive(sb); + else + nfs_sb_deactive_async(sb); kfree(ctx->mdsthreshold); kfree(ctx); } diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 59b133c5d65..05521cadac2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -351,10 +351,12 @@ extern int __init register_nfs_fs(void); extern void __exit unregister_nfs_fs(void); extern void nfs_sb_active(struct super_block *sb); extern void nfs_sb_deactive(struct super_block *sb); +extern void nfs_sb_deactive_async(struct super_block *sb); /* namespace.c */ +#define NFS_PATH_CANONICAL 1 extern char *nfs_path(char **p, struct dentry *dentry, - char *buffer, ssize_t buflen); + char *buffer, ssize_t buflen, unsigned flags); extern struct vfsmount *nfs_d_automount(struct path *path); struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *, struct nfs_fh *, struct nfs_fattr *); @@ -498,7 +500,7 @@ static inline char *nfs_devname(struct dentry *dentry, char *buffer, ssize_t buflen) { char *dummy; - return nfs_path(&dummy, dentry, buffer, buflen); + return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL); } /* diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 8e65c7f1f87..015f71f8f62 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info) else msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; - status = rpc_call_sync(mnt_clnt, &msg, 0); + status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT); rpc_shutdown_client(mnt_clnt); if (status < 0) diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 655925373b9..dd057bc6b65 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; * @dentry - pointer to dentry * @buffer - result buffer * @buflen - length of buffer + * @flags - options (see below) * * Helper function for constructing the server pathname * by arbitrary hashed dentry. @@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; * This is mainly for use in figuring out the path on the * server side when automounting on top of an existing partition * and in generating /proc/mounts and friends. + * + * Supported flags: + * NFS_PATH_CANONICAL: ensure there is exactly one slash after + * the original device (export) name + * (if unset, the original name is returned verbatim) */ -char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) +char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen, + unsigned flags) { char *end; int namelen; @@ -74,7 +81,7 @@ rename_retry: rcu_read_unlock(); goto rename_retry; } - if (*end != '/') { + if ((flags & NFS_PATH_CANONICAL) && *end != '/') { if (--buflen < 0) { spin_unlock(&dentry->d_lock); rcu_read_unlock(); @@ -91,9 +98,11 @@ rename_retry: return end; } namelen = strlen(base); - /* Strip off excess slashes in base string */ - while (namelen > 0 && base[namelen - 1] == '/') - namelen--; + if (flags & NFS_PATH_CANONICAL) { + /* Strip off excess slashes in base string */ + while (namelen > 0 && base[namelen - 1] == '/') + namelen--; + } buflen -= namelen; if (buflen < 0) { spin_unlock(&dentry->d_lock); diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 52d84721206..2e45fd9c02a 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -122,12 +122,21 @@ static void filelayout_reset_read(struct nfs_read_data *data) } } +static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo) +{ + if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) + return; + clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags); + pnfs_return_layout(inode); +} + static int filelayout_async_handle_error(struct rpc_task *task, struct nfs4_state *state, struct nfs_client *clp, struct pnfs_layout_segment *lseg) { - struct inode *inode = lseg->pls_layout->plh_inode; + struct pnfs_layout_hdr *lo = lseg->pls_layout; + struct inode *inode = lo->plh_inode; struct nfs_server *mds_server = NFS_SERVER(inode); struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); struct nfs_client *mds_client = mds_server->nfs_client; @@ -204,10 +213,8 @@ static int filelayout_async_handle_error(struct rpc_task *task, dprintk("%s DS connection error %d\n", __func__, task->tk_status); nfs4_mark_deviceid_unavailable(devid); - clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags); - _pnfs_return_layout(inode); + set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags); rpc_wake_up(&tbl->slot_tbl_waitq); - nfs4_ds_disconnect(clp); /* fall through */ default: reset: @@ -331,7 +338,9 @@ static void filelayout_read_count_stats(struct rpc_task *task, void *data) static void filelayout_read_release(void *data) { struct nfs_read_data *rdata = data; + struct pnfs_layout_hdr *lo = rdata->header->lseg->pls_layout; + filelayout_fenceme(lo->plh_inode, lo); nfs_put_client(rdata->ds_clp); rdata->header->mds_ops->rpc_release(data); } @@ -429,7 +438,9 @@ static void filelayout_write_count_stats(struct rpc_task *task, void *data) static void filelayout_write_release(void *data) { struct nfs_write_data *wdata = data; + struct pnfs_layout_hdr *lo = wdata->header->lseg->pls_layout; + filelayout_fenceme(lo->plh_inode, lo); nfs_put_client(wdata->ds_clp); wdata->header->mds_ops->rpc_release(data); } @@ -739,7 +750,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, goto out_err; if (fl->num_fh > 0) { - fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), + fl->fh_array = kcalloc(fl->num_fh, sizeof(fl->fh_array[0]), gfp_flags); if (!fl->fh_array) goto out_err; diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index dca47d78671..8c07241fe52 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h @@ -149,6 +149,5 @@ extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); struct nfs4_file_layout_dsaddr * filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); -void nfs4_ds_disconnect(struct nfs_client *clp); #endif /* FS_NFS_NFS4FILELAYOUT_H */ diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 3336d5eaf87..a8eaa9b7bb0 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c @@ -149,28 +149,6 @@ _data_server_lookup_locked(const struct list_head *dsaddrs) } /* - * Lookup DS by nfs_client pointer. Zero data server client pointer - */ -void nfs4_ds_disconnect(struct nfs_client *clp) -{ - struct nfs4_pnfs_ds *ds; - struct nfs_client *found = NULL; - - dprintk("%s clp %p\n", __func__, clp); - spin_lock(&nfs4_ds_cache_lock); - list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) - if (ds->ds_clp && ds->ds_clp == clp) { - found = ds->ds_clp; - ds->ds_clp = NULL; - } - spin_unlock(&nfs4_ds_cache_lock); - if (found) { - set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state); - nfs_put_client(clp); - } -} - -/* * Create an rpc connection to the nfs4_pnfs_ds data server * Currently only supports IPv4 and IPv6 addresses */ diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c index 6a83780e0ce..549462e5b9b 100644 --- a/fs/nfs/nfs4getroot.c +++ b/fs/nfs/nfs4getroot.c @@ -5,6 +5,7 @@ #include <linux/nfs_fs.h> #include "nfs4_fs.h" +#include "internal.h" #define NFSDBG_FACILITY NFSDBG_CLIENT diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 79fbb61ce20..1e09eb78543 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end) static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) { char *limit; - char *path = nfs_path(&limit, dentry, buffer, buflen); + char *path = nfs_path(&limit, dentry, buffer, buflen, + NFS_PATH_CANONICAL); if (!IS_ERR(path)) { char *path_component = nfs_path_component(path, limit); if (path_component) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 68b21d81b7a..5eec4429970 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -339,8 +339,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc dprintk("%s ERROR: %d Reset session\n", __func__, errorcode); nfs4_schedule_session_recovery(clp->cl_session, errorcode); - exception->retry = 1; - break; + goto wait_on_recovery; #endif /* defined(CONFIG_NFS_V4_1) */ case -NFS4ERR_FILE_OPEN: if (exception->timeout > HZ) { @@ -1572,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) data->timestamp = jiffies; if (nfs4_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, - &data->o_res.seq_res, task)) - return; - rpc_call_start(task); + &data->o_res.seq_res, + task) != 0) + nfs_release_seqid(data->o_arg.seqid); + else + rpc_call_start(task); return; unlock_no_action: rcu_read_unlock(); @@ -1748,7 +1749,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred, /* even though OPEN succeeded, access is denied. Close the file */ nfs4_close_state(state, fmode); - return -NFS4ERR_ACCESS; + return -EACCES; } /* @@ -2196,7 +2197,7 @@ static void nfs4_free_closedata(void *data) nfs4_put_open_state(calldata->state); nfs_free_seqid(calldata->arg.seqid); nfs4_put_state_owner(sp); - nfs_sb_deactive(sb); + nfs_sb_deactive_async(sb); kfree(calldata); } @@ -2296,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) if (nfs4_setup_sequence(NFS_SERVER(inode), &calldata->arg.seq_args, &calldata->res.seq_res, - task)) - goto out; - rpc_call_start(task); + task) != 0) + nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); out: dprintk("%s: done!\n", __func__); } @@ -4529,6 +4531,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) rpc_restart_call_prepare(task); } + nfs_release_seqid(calldata->arg.seqid); } static void nfs4_locku_prepare(struct rpc_task *task, void *data) @@ -4545,9 +4548,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) calldata->timestamp = jiffies; if (nfs4_setup_sequence(calldata->server, &calldata->arg.seq_args, - &calldata->res.seq_res, task)) - return; - rpc_call_start(task); + &calldata->res.seq_res, + task) != 0) + nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); } static const struct rpc_call_ops nfs4_locku_ops = { @@ -4692,7 +4697,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) /* Do we need to do an open_to_lock_owner? */ if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) - return; + goto out_release_lock_seqid; data->arg.open_stateid = &state->stateid; data->arg.new_lock_owner = 1; data->res.open_seqid = data->arg.open_seqid; @@ -4701,10 +4706,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) data->timestamp = jiffies; if (nfs4_setup_sequence(data->server, &data->arg.seq_args, - &data->res.seq_res, task)) + &data->res.seq_res, + task) == 0) { + rpc_call_start(task); return; - rpc_call_start(task); - dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); + } + nfs_release_seqid(data->arg.open_seqid); +out_release_lock_seqid: + nfs_release_seqid(data->arg.lock_seqid); + dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); } static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) @@ -5667,7 +5677,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl, tbl->slots = new; tbl->max_slots = max_slots; } - tbl->highest_used_slotid = -1; /* no slot is currently used */ + tbl->highest_used_slotid = NFS4_NO_SLOT; for (i = 0; i < tbl->max_slots; i++) tbl->slots[i].seq_nr = ivalue; spin_unlock(&tbl->slot_tbl_lock); diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index be731e6b7b9..c6f990656f8 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -369,7 +369,7 @@ void objio_free_result(struct objlayout_io_res *oir) kfree(objios); } -enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep) +static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep) { switch (oep) { case OSD_ERR_PRI_NO_ERROR: @@ -574,7 +574,7 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, (unsigned long)pgio->pg_layout_private; } -void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +static 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)) @@ -604,7 +604,7 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, return false; } -void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) +static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) { unsigned long stripe_end = 0; u64 wb_size; diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index fe624c91bd0..2878f97bd78 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -925,8 +925,8 @@ pnfs_find_alloc_layout(struct inode *ino, if (likely(nfsi->layout == NULL)) { /* Won the race? */ nfsi->layout = new; return new; - } - pnfs_free_layout_hdr(new); + } else if (new != NULL) + pnfs_free_layout_hdr(new); out_existing: pnfs_get_layout_hdr(nfsi->layout); return nfsi->layout; diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 2d722dba111..dbf7bba52da 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -62,6 +62,7 @@ enum { NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */ NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */ NFS_LAYOUT_ROC, /* some lseg had roc bit set */ + NFS_LAYOUT_RETURN, /* Return this layout ASAP */ }; enum layoutdriver_policy_flags { diff --git a/fs/nfs/super.c b/fs/nfs/super.c index e831bce4976..652d3f7176a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -54,6 +54,7 @@ #include <linux/parser.h> #include <linux/nsproxy.h> #include <linux/rcupdate.h> +#include <linux/kthread.h> #include <asm/uaccess.h> @@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb) } EXPORT_SYMBOL_GPL(nfs_sb_deactive); +static int nfs_deactivate_super_async_work(void *ptr) +{ + struct super_block *sb = ptr; + + deactivate_super(sb); + module_put_and_exit(0); + return 0; +} + +/* + * same effect as deactivate_super, but will do final unmount in kthread + * context + */ +static void nfs_deactivate_super_async(struct super_block *sb) +{ + struct task_struct *task; + char buf[INET6_ADDRSTRLEN + 1]; + struct nfs_server *server = NFS_SB(sb); + struct nfs_client *clp = server->nfs_client; + + if (!atomic_add_unless(&sb->s_active, -1, 1)) { + rcu_read_lock(); + snprintf(buf, sizeof(buf), + rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); + rcu_read_unlock(); + + __module_get(THIS_MODULE); + task = kthread_run(nfs_deactivate_super_async_work, sb, + "%s-deactivate-super", buf); + if (IS_ERR(task)) { + pr_err("%s: kthread_run: %ld\n", + __func__, PTR_ERR(task)); + /* make synchronous call and hope for the best */ + deactivate_super(sb); + module_put(THIS_MODULE); + } + } +} + +void nfs_sb_deactive_async(struct super_block *sb) +{ + struct nfs_server *server = NFS_SB(sb); + + if (atomic_dec_and_test(&server->active)) + nfs_deactivate_super_async(sb); +} +EXPORT_SYMBOL_GPL(nfs_sb_deactive_async); + /* * Deliver file system statistics to userspace */ @@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root) int err = 0; if (!page) return -ENOMEM; - devname = nfs_path(&dummy, root, page, PAGE_SIZE); + devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0); if (IS_ERR(devname)) err = PTR_ERR(devname); else diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 13cea637eff..3f79c77153b 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata) nfs_dec_sillycount(data->dir); nfs_free_unlinkdata(data); - nfs_sb_deactive(sb); + nfs_sb_deactive_async(sb); } static void nfs_unlink_prepare(struct rpc_task *task, void *calldata) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index f35794b97e8..a5063602536 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) if ((old->path.mnt == new->path.mnt) && (old->path.dentry == new->path.dentry)) return true; + break; case (FSNOTIFY_EVENT_NONE): return true; default: diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 721d692fa8d..6fcaeb8c902 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -258,7 +258,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, if (ret) goto out_close_fd; - fd_install(fd, f); + if (fd != FAN_NOFD) + fd_install(fd, f); return fanotify_event_metadata.event_len; out_close_fd: diff --git a/fs/proc/base.c b/fs/proc/base.c index 144a96732dd..3c231adf845 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -873,6 +873,113 @@ static const struct file_operations proc_environ_operations = { .release = mem_release, }; +static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); + char buffer[PROC_NUMBUF]; + int oom_adj = OOM_ADJUST_MIN; + size_t len; + unsigned long flags; + + if (!task) + return -ESRCH; + if (lock_task_sighand(task, &flags)) { + if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX) + oom_adj = OOM_ADJUST_MAX; + else + oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) / + OOM_SCORE_ADJ_MAX; + unlock_task_sighand(task, &flags); + } + put_task_struct(task); + len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj); + return simple_read_from_buffer(buf, count, ppos, buffer, len); +} + +static ssize_t oom_adj_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct task_struct *task; + char buffer[PROC_NUMBUF]; + int oom_adj; + unsigned long flags; + int err; + + memset(buffer, 0, sizeof(buffer)); + if (count > sizeof(buffer) - 1) + count = sizeof(buffer) - 1; + if (copy_from_user(buffer, buf, count)) { + err = -EFAULT; + goto out; + } + + err = kstrtoint(strstrip(buffer), 0, &oom_adj); + if (err) + goto out; + if ((oom_adj < OOM_ADJUST_MIN || oom_adj > OOM_ADJUST_MAX) && + oom_adj != OOM_DISABLE) { + err = -EINVAL; + goto out; + } + + task = get_proc_task(file->f_path.dentry->d_inode); + if (!task) { + err = -ESRCH; + goto out; + } + + task_lock(task); + if (!task->mm) { + err = -EINVAL; + goto err_task_lock; + } + + if (!lock_task_sighand(task, &flags)) { + err = -ESRCH; + goto err_task_lock; + } + + /* + * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum + * value is always attainable. + */ + if (oom_adj == OOM_ADJUST_MAX) + oom_adj = OOM_SCORE_ADJ_MAX; + else + oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; + + if (oom_adj < task->signal->oom_score_adj && + !capable(CAP_SYS_RESOURCE)) { + err = -EACCES; + goto err_sighand; + } + + /* + * /proc/pid/oom_adj is provided for legacy purposes, ask users to use + * /proc/pid/oom_score_adj instead. + */ + printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n", + current->comm, task_pid_nr(current), task_pid_nr(task), + task_pid_nr(task)); + + task->signal->oom_score_adj = oom_adj; + trace_oom_score_adj_update(task); +err_sighand: + unlock_task_sighand(task, &flags); +err_task_lock: + task_unlock(task); + put_task_struct(task); +out: + return err < 0 ? err : count; +} + +static const struct file_operations proc_oom_adj_operations = { + .read = oom_adj_read, + .write = oom_adj_write, + .llseek = generic_file_llseek, +}; + static ssize_t oom_score_adj_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -2598,6 +2705,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("cgroup", S_IRUGO, proc_cgroup_operations), #endif INF("oom_score", S_IRUGO, proc_oom_score), + REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), @@ -2964,6 +3072,7 @@ static const struct pid_entry tid_base_stuff[] = { REG("cgroup", S_IRUGO, proc_cgroup_operations), #endif INF("oom_score", S_IRUGO, proc_oom_score), + REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), diff --git a/fs/proc/internal.h b/fs/proc/internal.h index cceaab07ad5..43973b084ab 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -12,6 +12,7 @@ #include <linux/sched.h> #include <linux/proc_fs.h> struct ctl_table_header; +struct mempolicy; extern struct proc_dir_entry proc_root; #ifdef CONFIG_PROC_SYSCTL @@ -74,6 +75,9 @@ struct proc_maps_private { #ifdef CONFIG_MMU struct vm_area_struct *tail_vma; #endif +#ifdef CONFIG_NUMA + struct mempolicy *task_mempolicy; +#endif }; void proc_init_inodecache(void); diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 64c3b317236..e296572c73e 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c @@ -45,10 +45,13 @@ static cputime64_t get_iowait_time(int cpu) static u64 get_idle_time(int cpu) { - u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL); + u64 idle, idle_time = -1ULL; + + if (cpu_online(cpu)) + idle_time = get_cpu_idle_time_us(cpu, NULL); if (idle_time == -1ULL) - /* !NO_HZ so we can rely on cpustat.idle */ + /* !NO_HZ or cpu offline so we can rely on cpustat.idle */ idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE]; else idle = usecs_to_cputime64(idle_time); @@ -58,10 +61,13 @@ static u64 get_idle_time(int cpu) static u64 get_iowait_time(int cpu) { - u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL); + u64 iowait, iowait_time = -1ULL; + + if (cpu_online(cpu)) + iowait_time = get_cpu_iowait_time_us(cpu, NULL); if (iowait_time == -1ULL) - /* !NO_HZ so we can rely on cpustat.iowait */ + /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */ iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT]; else iowait = usecs_to_cputime64(iowait_time); diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 79827ce03e3..90c63f9392a 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -90,10 +90,55 @@ static void pad_len_spaces(struct seq_file *m, int len) seq_printf(m, "%*c", len, ' '); } +#ifdef CONFIG_NUMA +/* + * These functions are for numa_maps but called in generic **maps seq_file + * ->start(), ->stop() ops. + * + * numa_maps scans all vmas under mmap_sem and checks their mempolicy. + * Each mempolicy object is controlled by reference counting. The problem here + * is how to avoid accessing dead mempolicy object. + * + * Because we're holding mmap_sem while reading seq_file, it's safe to access + * each vma's mempolicy, no vma objects will never drop refs to mempolicy. + * + * A task's mempolicy (task->mempolicy) has different behavior. task->mempolicy + * is set and replaced under mmap_sem but unrefed and cleared under task_lock(). + * So, without task_lock(), we cannot trust get_vma_policy() because we cannot + * gurantee the task never exits under us. But taking task_lock() around + * get_vma_plicy() causes lock order problem. + * + * To access task->mempolicy without lock, we hold a reference count of an + * object pointed by task->mempolicy and remember it. This will guarantee + * that task->mempolicy points to an alive object or NULL in numa_maps accesses. + */ +static void hold_task_mempolicy(struct proc_maps_private *priv) +{ + struct task_struct *task = priv->task; + + task_lock(task); + priv->task_mempolicy = task->mempolicy; + mpol_get(priv->task_mempolicy); + task_unlock(task); +} +static void release_task_mempolicy(struct proc_maps_private *priv) +{ + mpol_put(priv->task_mempolicy); +} +#else +static void hold_task_mempolicy(struct proc_maps_private *priv) +{ +} +static void release_task_mempolicy(struct proc_maps_private *priv) +{ +} +#endif + static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma) { if (vma && vma != priv->tail_vma) { struct mm_struct *mm = vma->vm_mm; + release_task_mempolicy(priv); up_read(&mm->mmap_sem); mmput(mm); } @@ -132,7 +177,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) tail_vma = get_gate_vma(priv->task->mm); priv->tail_vma = tail_vma; - + hold_task_mempolicy(priv); /* Start with last addr hint */ vma = find_vma(mm, last_addr); if (last_addr && vma) { @@ -159,6 +204,7 @@ out: if (vma) return vma; + release_task_mempolicy(priv); /* End of vmas has been reached */ m->version = (tail_vma != NULL)? 0: -1UL; up_read(&mm->mmap_sem); @@ -1158,6 +1204,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) struct vm_area_struct *vma = v; struct numa_maps *md = &numa_priv->md; struct file *file = vma->vm_file; + struct task_struct *task = proc_priv->task; struct mm_struct *mm = vma->vm_mm; struct mm_walk walk = {}; struct mempolicy *pol; @@ -1177,7 +1224,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) walk.private = md; walk.mm = mm; - pol = get_vma_policy(proc_priv->task, vma, vma->vm_start); + pol = get_vma_policy(task, vma, vma->vm_start); mpol_to_str(buffer, sizeof(buffer), pol, 0); mpol_cond_put(pol); @@ -1189,7 +1236,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { seq_printf(m, " heap"); } else { - pid_t tid = vm_is_stack(proc_priv->task, vma, is_pid); + pid_t tid = vm_is_stack(task, vma, is_pid); if (tid != 0) { /* * Thread stack in /proc/PID/task/TID/maps or diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index a40da07e93d..947fbe06c3b 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -161,6 +161,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) while (s < e) { unsigned long flags; + u64 id; if (c > psinfo->bufsize) c = psinfo->bufsize; @@ -172,7 +173,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) spin_lock_irqsave(&psinfo->buf_lock, flags); } memcpy(psinfo->buf, s, c); - psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo); + psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, c, psinfo); spin_unlock_irqrestore(&psinfo->buf_lock, flags); s += c; c = e - s; diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 557a9c20a21..05ae3c97f7a 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -1160,6 +1160,8 @@ static int need_print_warning(struct dquot_warn *warn) return uid_eq(current_fsuid(), warn->w_dq_id.uid); case GRPQUOTA: return in_group_p(warn->w_dq_id.gid); + case PRJQUOTA: /* Never taken... Just make gcc happy */ + return 0; } return 0; } diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index f27f01a98aa..d83736fbc26 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, BUG_ON(!th->t_trans_id); - dquot_initialize(inode); + reiserfs_write_unlock(inode->i_sb); err = dquot_alloc_inode(inode); + reiserfs_write_lock(inode->i_sb); if (err) goto out_end_trans; if (!dir->i_nlink) { @@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, out_end_trans: journal_end(th, th->t_super, th->t_blocks_allocated); + reiserfs_write_unlock(inode->i_sb); /* Drop can be outside and it needs more credits so it's better to have it outside */ dquot_drop(inode); + reiserfs_write_lock(inode->i_sb); inode->i_flags |= S_NOQUOTA; make_bad_inode(inode); @@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) /* must be turned off for recursive notify_change calls */ ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); - depth = reiserfs_write_lock_once(inode->i_sb); if (is_quota_modification(inode, attr)) dquot_initialize(inode); - + depth = reiserfs_write_lock_once(inode->i_sb); if (attr->ia_valid & ATTR_SIZE) { /* version 2 items will be caught by the s_maxbytes check ** done for us in vmtruncate @@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) error = journal_begin(&th, inode->i_sb, jbegin_count); if (error) goto out; + reiserfs_write_unlock_once(inode->i_sb, depth); error = dquot_transfer(inode, attr); + depth = reiserfs_write_lock_once(inode->i_sb); if (error) { journal_end(&th, inode->i_sb, jbegin_count); goto out; diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index f8afa4b162b..2f40a4c70a4 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree key2type(&(key->on_disk_key))); #endif + reiserfs_write_unlock(inode->i_sb); retval = dquot_alloc_space_nodirty(inode, pasted_size); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(search_path); return retval; @@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, "reiserquota insert_item(): allocating %u id=%u type=%c", quota_bytes, inode->i_uid, head2type(ih)); #endif + reiserfs_write_unlock(inode->i_sb); /* We can't dirty inode here. It would be immediately written but * appropriate stat item isn't inserted yet... */ retval = dquot_alloc_space_nodirty(inode, quota_bytes); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(path); return retval; diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 1078ae17999..418bdc3a57d 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s) retval = remove_save_link_only(s, &save_link_key, 0); continue; } + reiserfs_write_unlock(s); dquot_initialize(inode); + reiserfs_write_lock(s); if (truncate && S_ISDIR(inode->i_mode)) { /* We got a truncate request for a dir which is impossible. @@ -1335,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) kfree(qf_names[i]); #endif err = -EINVAL; - goto out_err; + goto out_unlock; } #ifdef CONFIG_QUOTA handle_quota_files(s, qf_names, &qfmt); @@ -1379,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (blocks) { err = reiserfs_resize(s, blocks); if (err != 0) - goto out_err; + goto out_unlock; } if (*mount_flags & MS_RDONLY) { @@ -1389,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) /* it is read-only already */ goto out_ok; + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_suspend() without it. + */ + reiserfs_write_unlock(s); err = dquot_suspend(s, -1); if (err < 0) goto out_err; + reiserfs_write_lock(s); /* try to remount file system with read-only permissions */ if (sb_umount_state(rs) == REISERFS_VALID_FS @@ -1401,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mounting a rw partition read-only. */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1416,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (reiserfs_is_journal_aborted(journal)) { err = journal->j_errno; - goto out_err; + goto out_unlock; } handle_data_mode(s, mount_options); @@ -1425,7 +1433,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mount a partition which is read-only, read-write */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1442,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) SB_JOURNAL(s)->j_must_wait = 1; err = journal_end(&th, s, 10); if (err) - goto out_err; + goto out_unlock; if (!(*mount_flags & MS_RDONLY)) { + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_resume() without it. + */ + reiserfs_write_unlock(s); dquot_resume(s, -1); + reiserfs_write_lock(s); finish_unfinished(s); reiserfs_xattr_init(s, *mount_flags); } @@ -1455,9 +1469,10 @@ out_ok: reiserfs_write_unlock(s); return 0; +out_unlock: + reiserfs_write_unlock(s); out_err: kfree(new_opts); - reiserfs_write_unlock(s); return err; } @@ -2095,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot) REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_commit(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2117,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_acquire(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2137,19 +2156,21 @@ static int reiserfs_release_dquot(struct dquot *dquot) ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); + reiserfs_write_unlock(dquot->dq_sb); if (ret) { /* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release(dquot); goto out; } ret = dquot_release(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: reiserfs_write_unlock(dquot->dq_sb); +out: return ret; } @@ -2174,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type) ret = journal_begin(&th, sb, 2); if (ret) goto out; + reiserfs_write_unlock(sb); ret = dquot_commit_info(sb, type); + reiserfs_write_lock(sb); err = journal_end(&th, sb, 2); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(sb); return ret; } @@ -2203,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, struct reiserfs_transaction_handle th; int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA; - if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) - return -EINVAL; + reiserfs_write_lock(sb); + if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) { + err = -EINVAL; + goto out; + } /* Quotafile not on the same filesystem? */ if (path->dentry->d_sb != sb) { @@ -2246,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, if (err) goto out; } - err = dquot_quota_on(sb, type, format_id, path); + reiserfs_write_unlock(sb); + return dquot_quota_on(sb, type, format_id, path); out: + reiserfs_write_unlock(sb); return err; } @@ -2320,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; tmp_bh.b_state = 0; + reiserfs_write_lock(sb); err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE); + reiserfs_write_unlock(sb); if (err) goto out; if (offset || tocopy != sb->s_blocksize) @@ -2336,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, flush_dcache_page(bh->b_page); set_buffer_uptodate(bh); unlock_buffer(bh); + reiserfs_write_lock(sb); reiserfs_prepare_for_journal(sb, bh, 1); journal_mark_dirty(current->journal_info, sb, bh); if (!journal_quota) reiserfs_add_ordered_list(inode, bh); + reiserfs_write_unlock(sb); brelse(bh); offset = 0; towrite -= tocopy; diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 6b0bb00d4d2..2fbdff6be25 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -485,20 +485,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) /** * sysfs_pathname - return full path to sysfs dirent * @sd: sysfs_dirent whose path we want - * @path: caller allocated buffer + * @path: caller allocated buffer of size PATH_MAX * * Gives the name "/" to the sysfs_root entry; any path returned * is relative to wherever sysfs is mounted. - * - * XXX: does no error checking on @path size */ static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) { if (sd->s_parent) { sysfs_pathname(sd->s_parent, path); - strcat(path, "/"); + strlcat(path, "/", PATH_MAX); } - strcat(path, sd->s_name); + strlcat(path, sd->s_name, PATH_MAX); return path; } @@ -531,9 +529,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) char *path = kzalloc(PATH_MAX, GFP_KERNEL); WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s'\n", - (path == NULL) ? sd->s_name : - strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"), - sd->s_name)); + (path == NULL) ? sd->s_name + : (sysfs_pathname(acxt->parent_sd, path), + strlcat(path, "/", PATH_MAX), + strlcat(path, sd->s_name, PATH_MAX), + path)); kfree(path); } diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index 28ec13af28d..2dcf3d473fe 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -681,8 +681,16 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c) if (!lprops) { lprops = ubifs_fast_find_freeable(c); if (!lprops) { - ubifs_assert(c->freeable_cnt == 0); - if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { + /* + * The first condition means the following: go scan the + * LPT if there are uncategorized lprops, which means + * there may be freeable LEBs there (UBIFS does not + * store the information about freeable LEBs in the + * master node). + */ + if (c->in_a_category_cnt != c->main_lebs || + c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { + ubifs_assert(c->freeable_cnt == 0); lprops = scan_for_leb_for_idx(c); if (IS_ERR(lprops)) { err = PTR_ERR(lprops); diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index e5a2a35a46d..46190a7c42a 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, default: ubifs_assert(0); } + lprops->flags &= ~LPROPS_CAT_MASK; lprops->flags |= cat; + c->in_a_category_cnt += 1; + ubifs_assert(c->in_a_category_cnt <= c->main_lebs); } /** @@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct ubifs_info *c, default: ubifs_assert(0); } + + c->in_a_category_cnt -= 1; + ubifs_assert(c->in_a_category_cnt >= 0); } /** diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 5486346d0a3..d133c276fe0 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1183,6 +1183,8 @@ struct ubifs_debug_info; * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size) * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size) * @freeable_cnt: number of freeable LEBs in @freeable_list + * @in_a_category_cnt: count of lprops which are in a certain category, which + * basically meants that they were loaded from the flash * * @ltab_lnum: LEB number of LPT's own lprops table * @ltab_offs: offset of LPT's own lprops table @@ -1412,6 +1414,7 @@ struct ubifs_info { struct list_head freeable_list; struct list_head frdi_idx_list; int freeable_cnt; + int in_a_category_cnt; int ltab_lnum; int ltab_offs; diff --git a/fs/xattr.c b/fs/xattr.c index e164dddb8e9..e21c119f4f9 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -846,7 +846,7 @@ static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name, const void *value, size_t size, int flags) { struct simple_xattr *xattr; - struct simple_xattr *uninitialized_var(new_xattr); + struct simple_xattr *new_xattr = NULL; int err = 0; /* value == NULL means remove */ diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 4f33c32affe..335206a9c69 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -1866,6 +1866,7 @@ xfs_alloc_fix_freelist( /* * Initialize the args structure. */ + memset(&targs, 0, sizeof(targs)); targs.tp = tp; targs.mp = mp; targs.agbp = agbp; @@ -2207,7 +2208,7 @@ xfs_alloc_read_agf( * group or loop over the allocation groups to find the result. */ int /* error */ -__xfs_alloc_vextent( +xfs_alloc_vextent( xfs_alloc_arg_t *args) /* allocation argument structure */ { xfs_agblock_t agsize; /* allocation group size */ @@ -2417,46 +2418,6 @@ error0: return error; } -static void -xfs_alloc_vextent_worker( - struct work_struct *work) -{ - struct xfs_alloc_arg *args = container_of(work, - struct xfs_alloc_arg, work); - unsigned long pflags; - - /* we are in a transaction context here */ - current_set_flags_nested(&pflags, PF_FSTRANS); - - args->result = __xfs_alloc_vextent(args); - complete(args->done); - - current_restore_flags_nested(&pflags, PF_FSTRANS); -} - -/* - * Data allocation requests often come in with little stack to work on. Push - * them off to a worker thread so there is lots of stack to use. Metadata - * requests, OTOH, are generally from low stack usage paths, so avoid the - * context switch overhead here. - */ -int -xfs_alloc_vextent( - struct xfs_alloc_arg *args) -{ - DECLARE_COMPLETION_ONSTACK(done); - - if (!args->userdata) - return __xfs_alloc_vextent(args); - - - args->done = &done; - INIT_WORK_ONSTACK(&args->work, xfs_alloc_vextent_worker); - queue_work(xfs_alloc_wq, &args->work); - wait_for_completion(&done); - return args->result; -} - /* * Free an extent. * Just break up the extent address and hand off to xfs_free_ag_extent diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 93be4a667ca..feacb061bab 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h @@ -120,9 +120,6 @@ typedef struct xfs_alloc_arg { char isfl; /* set if is freelist blocks - !acctg */ char userdata; /* set if this is user data */ xfs_fsblock_t firstblock; /* io first block allocated */ - struct completion *done; - struct work_struct work; - int result; } xfs_alloc_arg_t; /* diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index f1647caace8..f7876c6d616 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c @@ -121,6 +121,8 @@ xfs_allocbt_free_block( xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1, XFS_EXTENT_BUSY_SKIP_DISCARD); xfs_trans_agbtree_delta(cur->bc_tp, -1); + + xfs_trans_binval(cur->bc_tp, bp); return 0; } diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index e562dd43f41..e57e2daa357 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -481,11 +481,17 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh) * * The fix is two passes across the ioend list - one to start writeback on the * buffer_heads, and then submit them for I/O on the second pass. + * + * If @fail is non-zero, it means that we have a situation where some part of + * the submission process has failed after we have marked paged for writeback + * and unlocked them. In this situation, we need to fail the ioend chain rather + * than submit it to IO. This typically only happens on a filesystem shutdown. */ STATIC void xfs_submit_ioend( struct writeback_control *wbc, - xfs_ioend_t *ioend) + xfs_ioend_t *ioend, + int fail) { xfs_ioend_t *head = ioend; xfs_ioend_t *next; @@ -506,6 +512,18 @@ xfs_submit_ioend( next = ioend->io_list; bio = NULL; + /* + * If we are failing the IO now, just mark the ioend with an + * error and finish it. This will run IO completion immediately + * as there is only one reference to the ioend at this point in + * time. + */ + if (fail) { + ioend->io_error = -fail; + xfs_finish_ioend(ioend); + continue; + } + for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) { if (!bio) { @@ -1060,7 +1078,18 @@ xfs_vm_writepage( xfs_start_page_writeback(page, 1, count); - if (ioend && imap_valid) { + /* if there is no IO to be submitted for this page, we are done */ + if (!ioend) + return 0; + + ASSERT(iohead); + + /* + * Any errors from this point onwards need tobe reported through the IO + * completion path as we have marked the initial page as under writeback + * and unlocked it. + */ + if (imap_valid) { xfs_off_t end_index; end_index = imap.br_startoff + imap.br_blockcount; @@ -1079,20 +1108,15 @@ xfs_vm_writepage( wbc, end_index); } - if (iohead) { - /* - * Reserve log space if we might write beyond the on-disk - * inode size. - */ - if (ioend->io_type != XFS_IO_UNWRITTEN && - xfs_ioend_is_append(ioend)) { - err = xfs_setfilesize_trans_alloc(ioend); - if (err) - goto error; - } - xfs_submit_ioend(wbc, iohead); - } + /* + * Reserve log space if we might write beyond the on-disk inode size. + */ + err = 0; + if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend)) + err = xfs_setfilesize_trans_alloc(ioend); + + xfs_submit_ioend(wbc, iohead, err); return 0; diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index d330111ca73..70eec182977 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c @@ -1291,6 +1291,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, leaf2 = blk2->bp->b_addr; ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); + ASSERT(leaf2->hdr.count == 0); args = state->args; trace_xfs_attr_leaf_rebalance(args); @@ -1361,6 +1362,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, * I assert that since all callers pass in an empty * second buffer, this code should never execute. */ + ASSERT(0); /* * Figure the total bytes to be added to the destination leaf. @@ -1422,10 +1424,24 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, args->index2 = 0; args->blkno2 = blk2->blkno; } else { + /* + * On a double leaf split, the original attr location + * is already stored in blkno2/index2, so don't + * overwrite it overwise we corrupt the tree. + */ blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); - args->index = args->index2 = blk2->index; - args->blkno = args->blkno2 = blk2->blkno; + args->index = blk2->index; + args->blkno = blk2->blkno; + if (!state->extravalid) { + /* + * set the new attr location to match the old + * one and let the higher level split code + * decide where in the leaf to place it. + */ + args->index2 = blk2->index; + args->blkno2 = blk2->blkno; + } } } else { ASSERT(state->inleaf == 1); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 848ffa77707..83d0cf3df93 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2437,6 +2437,7 @@ xfs_bmap_btalloc( * Normal allocation, done through xfs_alloc_vextent. */ tryagain = isaligned = 0; + memset(&args, 0, sizeof(args)); args.tp = ap->tp; args.mp = mp; args.fsbno = ap->blkno; @@ -3082,6 +3083,7 @@ xfs_bmap_extents_to_btree( * Convert to a btree with two levels, one record in root. */ XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE); + memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = mp; args.firstblock = *firstblock; @@ -3237,6 +3239,7 @@ xfs_bmap_local_to_extents( xfs_buf_t *bp; /* buffer for extent block */ xfs_bmbt_rec_host_t *ep;/* extent record pointer */ + memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = ip->i_mount; args.firstblock = *firstblock; @@ -4616,12 +4619,11 @@ xfs_bmapi_delay( STATIC int -xfs_bmapi_allocate( - struct xfs_bmalloca *bma, - int flags) +__xfs_bmapi_allocate( + struct xfs_bmalloca *bma) { struct xfs_mount *mp = bma->ip->i_mount; - int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? + int whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ? XFS_ATTR_FORK : XFS_DATA_FORK; struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); int tmp_logflags = 0; @@ -4654,24 +4656,27 @@ xfs_bmapi_allocate( * Indicate if this is the first user data in the file, or just any * user data. */ - if (!(flags & XFS_BMAPI_METADATA)) { + if (!(bma->flags & XFS_BMAPI_METADATA)) { bma->userdata = (bma->offset == 0) ? XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA; } - bma->minlen = (flags & XFS_BMAPI_CONTIG) ? bma->length : 1; + bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1; /* * Only want to do the alignment at the eof if it is userdata and * allocation length is larger than a stripe unit. */ if (mp->m_dalign && bma->length >= mp->m_dalign && - !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) { + !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) { error = xfs_bmap_isaeof(bma, whichfork); if (error) return error; } + if (bma->flags & XFS_BMAPI_STACK_SWITCH) + bma->stack_switch = 1; + error = xfs_bmap_alloc(bma); if (error) return error; @@ -4706,7 +4711,7 @@ xfs_bmapi_allocate( * A wasdelay extent has been initialized, so shouldn't be flagged * as unwritten. */ - if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) && + if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) && xfs_sb_version_hasextflgbit(&mp->m_sb)) bma->got.br_state = XFS_EXT_UNWRITTEN; @@ -4734,6 +4739,45 @@ xfs_bmapi_allocate( return 0; } +static void +xfs_bmapi_allocate_worker( + struct work_struct *work) +{ + struct xfs_bmalloca *args = container_of(work, + struct xfs_bmalloca, work); + unsigned long pflags; + + /* we are in a transaction context here */ + current_set_flags_nested(&pflags, PF_FSTRANS); + + args->result = __xfs_bmapi_allocate(args); + complete(args->done); + + current_restore_flags_nested(&pflags, PF_FSTRANS); +} + +/* + * Some allocation requests often come in with little stack to work on. Push + * them off to a worker thread so there is lots of stack to use. Otherwise just + * call directly to avoid the context switch overhead here. + */ +int +xfs_bmapi_allocate( + struct xfs_bmalloca *args) +{ + DECLARE_COMPLETION_ONSTACK(done); + + if (!args->stack_switch) + return __xfs_bmapi_allocate(args); + + + args->done = &done; + INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker); + queue_work(xfs_alloc_wq, &args->work); + wait_for_completion(&done); + return args->result; +} + STATIC int xfs_bmapi_convert_unwritten( struct xfs_bmalloca *bma, @@ -4919,6 +4963,7 @@ xfs_bmapi_write( bma.conv = !!(flags & XFS_BMAPI_CONVERT); bma.wasdel = wasdelay; bma.offset = bno; + bma.flags = flags; /* * There's a 32/64 bit type mismatch between the @@ -4934,7 +4979,7 @@ xfs_bmapi_write( ASSERT(len > 0); ASSERT(bma.length > 0); - error = xfs_bmapi_allocate(&bma, flags); + error = xfs_bmapi_allocate(&bma); if (error) goto error0; if (bma.blkno == NULLFSBLOCK) diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 803b56d7ce1..5f469c3516e 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h @@ -77,6 +77,7 @@ typedef struct xfs_bmap_free * from written to unwritten, otherwise convert from unwritten to written. */ #define XFS_BMAPI_CONVERT 0x040 +#define XFS_BMAPI_STACK_SWITCH 0x080 #define XFS_BMAPI_FLAGS \ { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ @@ -85,7 +86,8 @@ typedef struct xfs_bmap_free { XFS_BMAPI_PREALLOC, "PREALLOC" }, \ { XFS_BMAPI_IGSTATE, "IGSTATE" }, \ { XFS_BMAPI_CONTIG, "CONTIG" }, \ - { XFS_BMAPI_CONVERT, "CONVERT" } + { XFS_BMAPI_CONVERT, "CONVERT" }, \ + { XFS_BMAPI_STACK_SWITCH, "STACK_SWITCH" } static inline int xfs_bmapi_aflag(int w) @@ -133,6 +135,11 @@ typedef struct xfs_bmalloca { char userdata;/* set if is user data */ char aeof; /* allocated space at eof */ char conv; /* overwriting unwritten extents */ + char stack_switch; + int flags; + struct completion *done; + struct work_struct work; + int result; } xfs_bmalloca_t; /* diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 933b7930b86..4b0b8dd1b7b 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io( { xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; - xfs_buf_ioerror(bp, -error); + /* + * don't overwrite existing errors - otherwise we can lose errors on + * buffers that require multiple bios to complete. + */ + if (!bp->b_error) + xfs_buf_ioerror(bp, -error); - if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) + if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); _xfs_buf_ioend(bp, 1); @@ -1279,6 +1284,11 @@ next_chunk: if (size) goto next_chunk; } else { + /* + * This is guaranteed not to be the last io reference count + * because the caller (xfs_buf_iorequest) holds a count itself. + */ + atomic_dec(&bp->b_io_remaining); xfs_buf_ioerror(bp, EIO); bio_put(bio); } diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index a8d0ed91119..becf4a97efc 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -526,7 +526,25 @@ xfs_buf_item_unpin( } xfs_buf_relse(bp); } else if (freed && remove) { + /* + * There are currently two references to the buffer - the active + * LRU reference and the buf log item. What we are about to do + * here - simulate a failed IO completion - requires 3 + * references. + * + * The LRU reference is removed by the xfs_buf_stale() call. The + * buf item reference is removed by the xfs_buf_iodone() + * callback that is run by xfs_buf_do_callbacks() during ioend + * processing (via the bp->b_iodone callback), and then finally + * the ioend processing will drop the IO reference if the buffer + * is marked XBF_ASYNC. + * + * Hence we need to take an additional reference here so that IO + * completion processing doesn't free the buffer prematurely. + */ xfs_buf_lock(bp); + xfs_buf_hold(bp); + bp->b_flags |= XBF_ASYNC; xfs_buf_ioerror(bp, EIO); XFS_BUF_UNDONE(bp); xfs_buf_stale(bp); diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index c25b094efbf..4beaede4327 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -399,9 +399,26 @@ xfs_growfs_data_private( /* update secondary superblocks. */ for (agno = 1; agno < nagcount; agno++) { - error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, + error = 0; + /* + * new secondary superblocks need to be zeroed, not read from + * disk as the contents of the new area we are growing into is + * completely unknown. + */ + if (agno < oagcount) { + error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), XFS_FSS_TO_BB(mp, 1), 0, &bp); + } else { + bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), + XFS_FSS_TO_BB(mp, 1), 0); + if (bp) + xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); + else + error = ENOMEM; + } + if (error) { xfs_warn(mp, "error %d reading secondary superblock for ag %d", @@ -423,7 +440,7 @@ xfs_growfs_data_private( break; /* no point in continuing */ } } - return 0; + return error; error0: xfs_trans_cancel(tp, XFS_TRANS_ABORT); diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 445bf1aef31..c5c4ef4f2bd 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -250,6 +250,7 @@ xfs_ialloc_ag_alloc( /* boundary */ struct xfs_perag *pag; + memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = tp->t_mountp; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 2778258fcfa..1938b41ee9f 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1509,7 +1509,8 @@ xfs_ifree_cluster( * to mark all the active inodes on the buffer stale. */ bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno, - mp->m_bsize * blks_per_cluster, 0); + mp->m_bsize * blks_per_cluster, + XBF_UNMAPPED); if (!bp) return ENOMEM; diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 8305f2ac677..c1df3c623de 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -70,7 +70,7 @@ xfs_find_handle( int hsize; xfs_handle_t handle; struct inode *inode; - struct fd f; + struct fd f = {0}; struct path path; int error; struct xfs_inode *ip; diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 973dff6ad93..7f537663365 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -584,7 +584,9 @@ xfs_iomap_write_allocate( * pointer that the caller gave to us. */ error = xfs_bmapi_write(tp, ip, map_start_fsb, - count_fsb, 0, &first_block, 1, + count_fsb, + XFS_BMAPI_STACK_SWITCH, + &first_block, 1, imap, &nimaps, &free_list); if (error) goto trans_cancel; diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 7f4f9370d0e..4dad756962d 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -2387,14 +2387,27 @@ xlog_state_do_callback( /* - * update the last_sync_lsn before we drop the + * Completion of a iclog IO does not imply that + * a transaction has completed, as transactions + * can be large enough to span many iclogs. We + * cannot change the tail of the log half way + * through a transaction as this may be the only + * transaction in the log and moving th etail to + * point to the middle of it will prevent + * recovery from finding the start of the + * transaction. Hence we should only update the + * last_sync_lsn if this iclog contains + * transaction completion callbacks on it. + * + * We have to do this before we drop the * icloglock to ensure we are the only one that * can update it. */ ASSERT(XFS_LSN_CMP(atomic64_read(&log->l_last_sync_lsn), be64_to_cpu(iclog->ic_header.h_lsn)) <= 0); - atomic64_set(&log->l_last_sync_lsn, - be64_to_cpu(iclog->ic_header.h_lsn)); + if (iclog->ic_callback) + atomic64_set(&log->l_last_sync_lsn, + be64_to_cpu(iclog->ic_header.h_lsn)); } else ioerrors++; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 5da3ace352b..d308749fabf 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3541,7 +3541,7 @@ xlog_do_recovery_pass( * - order is important. */ error = xlog_bread_offset(log, 0, - bblks - split_bblks, hbp, + bblks - split_bblks, dbp, offset + BBTOB(split_bblks)); if (error) goto bread_err2; diff --git a/include/Kbuild b/include/Kbuild index 8d226bfa269..83256b64166 100644 --- a/include/Kbuild +++ b/include/Kbuild @@ -1,12 +1,8 @@ # Top-level Makefile calls into asm-$(ARCH) # List only non-arch directories below -header-y += asm-generic/ header-y += linux/ header-y += sound/ -header-y += mtd/ header-y += rdma/ header-y += video/ -header-y += drm/ -header-y += xen/ header-y += scsi/ diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/asm-generic/Kbuild +++ /dev/null diff --git a/include/asm-generic/syscalls.h b/include/asm-generic/syscalls.h index d89dec864d4..7e4fdb64995 100644 --- a/include/asm-generic/syscalls.h +++ b/include/asm-generic/syscalls.h @@ -10,16 +10,15 @@ */ #ifndef sys_clone asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, - void __user *parent_tid, void __user *child_tid, - struct pt_regs *regs); + void __user *parent_tid, void __user *child_tid); #endif #ifndef sys_fork -asmlinkage long sys_fork(struct pt_regs *regs); +asmlinkage long sys_fork(void); #endif #ifndef sys_vfork -asmlinkage long sys_vfork(struct pt_regs *regs); +asmlinkage long sys_vfork(void); #endif #ifndef sys_execve diff --git a/include/drm/Kbuild b/include/drm/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/drm/Kbuild +++ /dev/null diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index c78bb997e2c..c5c35e62942 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -205,9 +205,12 @@ {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -217,6 +220,7 @@ {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, 0x6811, 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}, \ diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 5b57367e28d..7fe2dae251e 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -1,31 +1,5 @@ -header-y += byteorder/ -header-y += can/ -header-y += caif/ header-y += dvb/ header-y += hdlc/ header-y += hsi/ -header-y += isdn/ -header-y += mmc/ -header-y += nfsd/ header-y += raid/ -header-y += spi/ -header-y += sunrpc/ -header-y += tc_act/ -header-y += tc_ematch/ -header-y += netfilter/ -header-y += netfilter_arp/ -header-y += netfilter_bridge/ -header-y += netfilter_ipv4/ -header-y += netfilter_ipv6/ header-y += usb/ -header-y += wimax/ - -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \ - $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h),) -endif -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \ - $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h),) -endif -ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h \ - $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h),) -endif diff --git a/include/linux/byteorder/Kbuild b/include/linux/byteorder/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/byteorder/Kbuild +++ /dev/null diff --git a/include/linux/caif/Kbuild b/include/linux/caif/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/caif/Kbuild +++ /dev/null diff --git a/include/linux/can/Kbuild b/include/linux/can/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/can/Kbuild +++ /dev/null diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index c1273158292..f9f5e9eeb9d 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -335,8 +335,8 @@ const char *__clk_get_name(struct clk *clk); struct clk_hw *__clk_get_hw(struct clk *clk); u8 __clk_get_num_parents(struct clk *clk); struct clk *__clk_get_parent(struct clk *clk); -inline int __clk_get_enable_count(struct clk *clk); -inline int __clk_get_prepare_count(struct clk *clk); +int __clk_get_enable_count(struct clk *clk); +int __clk_get_prepare_count(struct clk *clk); unsigned long __clk_get_rate(struct clk *clk); unsigned long __clk_get_flags(struct clk *clk); int __clk_is_enabled(struct clk *clk); diff --git a/include/linux/compat.h b/include/linux/compat.h index d0ced1011f2..d2db71077d9 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -286,10 +286,8 @@ asmlinkage ssize_t compat_sys_pwritev(unsigned long fd, int compat_do_execve(const char *filename, const compat_uptr_t __user *argv, const compat_uptr_t __user *envp, struct pt_regs *regs); -#ifdef __ARCH_WANT_SYS_EXECVE asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv, const compat_uptr_t __user *envp); -#endif asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, diff --git a/include/linux/coredump.h b/include/linux/coredump.h index 1775eb8acc0..1d7399314a8 100644 --- a/include/linux/coredump.h +++ b/include/linux/coredump.h @@ -4,6 +4,7 @@ #include <linux/types.h> #include <linux/mm.h> #include <linux/fs.h> +#include <asm/siginfo.h> /* * These are the only things you should do on a core-file: use only these diff --git a/include/linux/dvb/Kbuild b/include/linux/dvb/Kbuild index f4dba8637f9..e69de29bb2d 100644 --- a/include/linux/dvb/Kbuild +++ b/include/linux/dvb/Kbuild @@ -1,8 +0,0 @@ -header-y += audio.h -header-y += ca.h -header-y += dmx.h -header-y += frontend.h -header-y += net.h -header-y += osd.h -header-y += version.h -header-y += video.h diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h index f078f3ac82d..0be6d8f2b52 100644 --- a/include/linux/dvb/dmx.h +++ b/include/linux/dvb/dmx.h @@ -20,138 +20,10 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ - #ifndef _DVBDMX_H_ #define _DVBDMX_H_ -#include <linux/types.h> -#ifdef __KERNEL__ #include <linux/time.h> -#else -#include <time.h> -#endif - - -#define DMX_FILTER_SIZE 16 - -typedef enum -{ - DMX_OUT_DECODER, /* Streaming directly to decoder. */ - DMX_OUT_TAP, /* Output going to a memory buffer */ - /* (to be retrieved via the read command).*/ - DMX_OUT_TS_TAP, /* Output multiplexed into a new TS */ - /* (to be retrieved by reading from the */ - /* logical DVR device). */ - DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */ -} dmx_output_t; - - -typedef enum -{ - DMX_IN_FRONTEND, /* Input from a front-end device. */ - DMX_IN_DVR /* Input from the logical DVR device. */ -} dmx_input_t; - - -typedef enum -{ - DMX_PES_AUDIO0, - DMX_PES_VIDEO0, - DMX_PES_TELETEXT0, - DMX_PES_SUBTITLE0, - DMX_PES_PCR0, - - DMX_PES_AUDIO1, - DMX_PES_VIDEO1, - DMX_PES_TELETEXT1, - DMX_PES_SUBTITLE1, - DMX_PES_PCR1, - - DMX_PES_AUDIO2, - DMX_PES_VIDEO2, - DMX_PES_TELETEXT2, - DMX_PES_SUBTITLE2, - DMX_PES_PCR2, - - DMX_PES_AUDIO3, - DMX_PES_VIDEO3, - DMX_PES_TELETEXT3, - DMX_PES_SUBTITLE3, - DMX_PES_PCR3, - - DMX_PES_OTHER -} dmx_pes_type_t; - -#define DMX_PES_AUDIO DMX_PES_AUDIO0 -#define DMX_PES_VIDEO DMX_PES_VIDEO0 -#define DMX_PES_TELETEXT DMX_PES_TELETEXT0 -#define DMX_PES_SUBTITLE DMX_PES_SUBTITLE0 -#define DMX_PES_PCR DMX_PES_PCR0 - - -typedef struct dmx_filter -{ - __u8 filter[DMX_FILTER_SIZE]; - __u8 mask[DMX_FILTER_SIZE]; - __u8 mode[DMX_FILTER_SIZE]; -} dmx_filter_t; - - -struct dmx_sct_filter_params -{ - __u16 pid; - dmx_filter_t filter; - __u32 timeout; - __u32 flags; -#define DMX_CHECK_CRC 1 -#define DMX_ONESHOT 2 -#define DMX_IMMEDIATE_START 4 -#define DMX_KERNEL_CLIENT 0x8000 -}; - - -struct dmx_pes_filter_params -{ - __u16 pid; - dmx_input_t input; - dmx_output_t output; - dmx_pes_type_t pes_type; - __u32 flags; -}; - -typedef struct dmx_caps { - __u32 caps; - int num_decoders; -} dmx_caps_t; - -typedef enum { - DMX_SOURCE_FRONT0 = 0, - DMX_SOURCE_FRONT1, - DMX_SOURCE_FRONT2, - DMX_SOURCE_FRONT3, - DMX_SOURCE_DVR0 = 16, - DMX_SOURCE_DVR1, - DMX_SOURCE_DVR2, - DMX_SOURCE_DVR3 -} dmx_source_t; - -struct dmx_stc { - unsigned int num; /* input : which STC? 0..N */ - unsigned int base; /* output: divisor for stc to get 90 kHz clock */ - __u64 stc; /* output: stc in 'base'*90 kHz units */ -}; - - -#define DMX_START _IO('o', 41) -#define DMX_STOP _IO('o', 42) -#define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params) -#define DMX_SET_PES_FILTER _IOW('o', 44, struct dmx_pes_filter_params) -#define DMX_SET_BUFFER_SIZE _IO('o', 45) -#define DMX_GET_PES_PIDS _IOR('o', 47, __u16[5]) -#define DMX_GET_CAPS _IOR('o', 48, dmx_caps_t) -#define DMX_SET_SOURCE _IOW('o', 49, dmx_source_t) -#define DMX_GET_STC _IOWR('o', 50, struct dmx_stc) -#define DMX_ADD_PID _IOW('o', 51, __u16) -#define DMX_REMOVE_PID _IOW('o', 52, __u16) +#include <uapi/linux/dvb/dmx.h> #endif /*_DVBDMX_H_*/ diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h index 1d750c0fd86..85c20d92569 100644 --- a/include/linux/dvb/video.h +++ b/include/linux/dvb/video.h @@ -20,257 +20,10 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ - #ifndef _DVBVIDEO_H_ #define _DVBVIDEO_H_ -#include <linux/types.h> -#ifdef __KERNEL__ #include <linux/compiler.h> -#else -#include <stdint.h> -#include <time.h> -#endif - -typedef enum { - VIDEO_FORMAT_4_3, /* Select 4:3 format */ - VIDEO_FORMAT_16_9, /* Select 16:9 format. */ - VIDEO_FORMAT_221_1 /* 2.21:1 */ -} video_format_t; - - -typedef enum { - VIDEO_SYSTEM_PAL, - VIDEO_SYSTEM_NTSC, - VIDEO_SYSTEM_PALN, - VIDEO_SYSTEM_PALNc, - VIDEO_SYSTEM_PALM, - VIDEO_SYSTEM_NTSC60, - VIDEO_SYSTEM_PAL60, - VIDEO_SYSTEM_PALM60 -} video_system_t; - - -typedef enum { - VIDEO_PAN_SCAN, /* use pan and scan format */ - VIDEO_LETTER_BOX, /* use letterbox format */ - VIDEO_CENTER_CUT_OUT /* use center cut out format */ -} video_displayformat_t; - -typedef struct { - int w; - int h; - video_format_t aspect_ratio; -} video_size_t; - -typedef enum { - VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */ - VIDEO_SOURCE_MEMORY /* If this source is selected, the stream - comes from the user through the write - system call */ -} video_stream_source_t; - - -typedef enum { - VIDEO_STOPPED, /* Video is stopped */ - VIDEO_PLAYING, /* Video is currently playing */ - VIDEO_FREEZED /* Video is freezed */ -} video_play_state_t; - - -/* Decoder commands */ -#define VIDEO_CMD_PLAY (0) -#define VIDEO_CMD_STOP (1) -#define VIDEO_CMD_FREEZE (2) -#define VIDEO_CMD_CONTINUE (3) - -/* Flags for VIDEO_CMD_FREEZE */ -#define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0) - -/* Flags for VIDEO_CMD_STOP */ -#define VIDEO_CMD_STOP_TO_BLACK (1 << 0) -#define VIDEO_CMD_STOP_IMMEDIATELY (1 << 1) - -/* Play input formats: */ -/* The decoder has no special format requirements */ -#define VIDEO_PLAY_FMT_NONE (0) -/* The decoder requires full GOPs */ -#define VIDEO_PLAY_FMT_GOP (1) - -/* The structure must be zeroed before use by the application - This ensures it can be extended safely in the future. */ -struct video_command { - __u32 cmd; - __u32 flags; - union { - struct { - __u64 pts; - } stop; - - struct { - /* 0 or 1000 specifies normal speed, - 1 specifies forward single stepping, - -1 specifies backward single stepping, - >1: playback at speed/1000 of the normal speed, - <-1: reverse playback at (-speed/1000) of the normal speed. */ - __s32 speed; - __u32 format; - } play; - - struct { - __u32 data[16]; - } raw; - }; -}; - -/* FIELD_UNKNOWN can be used if the hardware does not know whether - the Vsync is for an odd, even or progressive (i.e. non-interlaced) - field. */ -#define VIDEO_VSYNC_FIELD_UNKNOWN (0) -#define VIDEO_VSYNC_FIELD_ODD (1) -#define VIDEO_VSYNC_FIELD_EVEN (2) -#define VIDEO_VSYNC_FIELD_PROGRESSIVE (3) - -struct video_event { - __s32 type; -#define VIDEO_EVENT_SIZE_CHANGED 1 -#define VIDEO_EVENT_FRAME_RATE_CHANGED 2 -#define VIDEO_EVENT_DECODER_STOPPED 3 -#define VIDEO_EVENT_VSYNC 4 - __kernel_time_t timestamp; - union { - video_size_t size; - unsigned int frame_rate; /* in frames per 1000sec */ - unsigned char vsync_field; /* unknown/odd/even/progressive */ - } u; -}; - - -struct video_status { - int video_blank; /* blank video on freeze? */ - video_play_state_t play_state; /* current state of playback */ - video_stream_source_t stream_source; /* current source (demux/memory) */ - video_format_t video_format; /* current aspect ratio of stream*/ - video_displayformat_t display_format;/* selected cropping mode */ -}; - - -struct video_still_picture { - char __user *iFrame; /* pointer to a single iframe in memory */ - __s32 size; -}; - - -typedef -struct video_highlight { - int active; /* 1=show highlight, 0=hide highlight */ - __u8 contrast1; /* 7- 4 Pattern pixel contrast */ - /* 3- 0 Background pixel contrast */ - __u8 contrast2; /* 7- 4 Emphasis pixel-2 contrast */ - /* 3- 0 Emphasis pixel-1 contrast */ - __u8 color1; /* 7- 4 Pattern pixel color */ - /* 3- 0 Background pixel color */ - __u8 color2; /* 7- 4 Emphasis pixel-2 color */ - /* 3- 0 Emphasis pixel-1 color */ - __u32 ypos; /* 23-22 auto action mode */ - /* 21-12 start y */ - /* 9- 0 end y */ - __u32 xpos; /* 23-22 button color number */ - /* 21-12 start x */ - /* 9- 0 end x */ -} video_highlight_t; - - -typedef struct video_spu { - int active; - int stream_id; -} video_spu_t; - - -typedef struct video_spu_palette { /* SPU Palette information */ - int length; - __u8 __user *palette; -} video_spu_palette_t; - - -typedef struct video_navi_pack { - int length; /* 0 ... 1024 */ - __u8 data[1024]; -} video_navi_pack_t; - - -typedef __u16 video_attributes_t; -/* bits: descr. */ -/* 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */ -/* 13-12 TV system (0=525/60, 1=625/50) */ -/* 11-10 Aspect ratio (0=4:3, 3=16:9) */ -/* 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */ -/* 7 line 21-1 data present in GOP (1=yes, 0=no) */ -/* 6 line 21-2 data present in GOP (1=yes, 0=no) */ -/* 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */ -/* 2 source letterboxed (1=yes, 0=no) */ -/* 0 film/camera mode (0=camera, 1=film (625/50 only)) */ - - -/* bit definitions for capabilities: */ -/* can the hardware decode MPEG1 and/or MPEG2? */ -#define VIDEO_CAP_MPEG1 1 -#define VIDEO_CAP_MPEG2 2 -/* can you send a system and/or program stream to video device? - (you still have to open the video and the audio device but only - send the stream to the video device) */ -#define VIDEO_CAP_SYS 4 -#define VIDEO_CAP_PROG 8 -/* can the driver also handle SPU, NAVI and CSS encoded data? - (CSS API is not present yet) */ -#define VIDEO_CAP_SPU 16 -#define VIDEO_CAP_NAVI 32 -#define VIDEO_CAP_CSS 64 - - -#define VIDEO_STOP _IO('o', 21) -#define VIDEO_PLAY _IO('o', 22) -#define VIDEO_FREEZE _IO('o', 23) -#define VIDEO_CONTINUE _IO('o', 24) -#define VIDEO_SELECT_SOURCE _IO('o', 25) -#define VIDEO_SET_BLANK _IO('o', 26) -#define VIDEO_GET_STATUS _IOR('o', 27, struct video_status) -#define VIDEO_GET_EVENT _IOR('o', 28, struct video_event) -#define VIDEO_SET_DISPLAY_FORMAT _IO('o', 29) -#define VIDEO_STILLPICTURE _IOW('o', 30, struct video_still_picture) -#define VIDEO_FAST_FORWARD _IO('o', 31) -#define VIDEO_SLOWMOTION _IO('o', 32) -#define VIDEO_GET_CAPABILITIES _IOR('o', 33, unsigned int) -#define VIDEO_CLEAR_BUFFER _IO('o', 34) -#define VIDEO_SET_ID _IO('o', 35) -#define VIDEO_SET_STREAMTYPE _IO('o', 36) -#define VIDEO_SET_FORMAT _IO('o', 37) -#define VIDEO_SET_SYSTEM _IO('o', 38) -#define VIDEO_SET_HIGHLIGHT _IOW('o', 39, video_highlight_t) -#define VIDEO_SET_SPU _IOW('o', 50, video_spu_t) -#define VIDEO_SET_SPU_PALETTE _IOW('o', 51, video_spu_palette_t) -#define VIDEO_GET_NAVI _IOR('o', 52, video_navi_pack_t) -#define VIDEO_SET_ATTRIBUTES _IO('o', 53) -#define VIDEO_GET_SIZE _IOR('o', 55, video_size_t) -#define VIDEO_GET_FRAME_RATE _IOR('o', 56, unsigned int) - -/** - * VIDEO_GET_PTS - * - * Read the 33 bit presentation time stamp as defined - * in ITU T-REC-H.222.0 / ISO/IEC 13818-1. - * - * The PTS should belong to the currently played - * frame if possible, but may also be a value close to it - * like the PTS of the last decoded frame or the last PTS - * extracted by the PES parser. - */ -#define VIDEO_GET_PTS _IOR('o', 57, __u64) - -/* Read the number of displayed frames since the decoder was started */ -#define VIDEO_GET_FRAME_COUNT _IOR('o', 58, __u64) - -#define VIDEO_COMMAND _IOWR('o', 59, struct video_command) -#define VIDEO_TRY_COMMAND _IOWR('o', 60, struct video_command) +#include <uapi/linux/dvb/video.h> #endif /*_DVBVIDEO_H_*/ diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index c18257b0fa7..6dd4787a798 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -61,7 +61,7 @@ int __dynamic_netdev_dbg(struct _ddebug *descriptor, const char *fmt, ...); #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \ - static struct _ddebug __used __aligned(8) \ + static struct _ddebug __aligned(8) \ __attribute__((section("__verbose"))) name = { \ .modname = KBUILD_MODNAME, \ .function = __func__, \ diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h new file mode 100644 index 00000000000..386440317b0 --- /dev/null +++ b/include/linux/elf-fdpic.h @@ -0,0 +1,51 @@ +/* FDPIC ELF load map + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.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. + */ + +#ifndef _LINUX_ELF_FDPIC_H +#define _LINUX_ELF_FDPIC_H + +#include <uapi/linux/elf-fdpic.h> + +/* + * binfmt binary parameters structure + */ +struct elf_fdpic_params { + struct elfhdr hdr; /* ref copy of ELF header */ + struct elf_phdr *phdrs; /* ref copy of PT_PHDR table */ + struct elf32_fdpic_loadmap *loadmap; /* loadmap to be passed to userspace */ + unsigned long elfhdr_addr; /* mapped ELF header user address */ + unsigned long ph_addr; /* mapped PT_PHDR user address */ + unsigned long map_addr; /* mapped loadmap user address */ + unsigned long entry_addr; /* mapped entry user address */ + unsigned long stack_size; /* stack size requested (PT_GNU_STACK) */ + unsigned long dynamic_addr; /* mapped PT_DYNAMIC user address */ + unsigned long load_addr; /* user address at which to map binary */ + unsigned long flags; +#define ELF_FDPIC_FLAG_ARRANGEMENT 0x0000000f /* PT_LOAD arrangement flags */ +#define ELF_FDPIC_FLAG_INDEPENDENT 0x00000000 /* PT_LOADs can be put anywhere */ +#define ELF_FDPIC_FLAG_HONOURVADDR 0x00000001 /* PT_LOAD.vaddr must be honoured */ +#define ELF_FDPIC_FLAG_CONSTDISP 0x00000002 /* PT_LOADs require constant + * displacement */ +#define ELF_FDPIC_FLAG_CONTIGUOUS 0x00000003 /* PT_LOADs should be contiguous */ +#define ELF_FDPIC_FLAG_EXEC_STACK 0x00000010 /* T if stack to be executable */ +#define ELF_FDPIC_FLAG_NOEXEC_STACK 0x00000020 /* T if stack not to be executable */ +#define ELF_FDPIC_FLAG_EXECUTABLE 0x00000040 /* T if this object is the executable */ +#define ELF_FDPIC_FLAG_PRESENT 0x80000000 /* T if this object is present */ +}; + +#ifdef CONFIG_MMU +extern void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params, + struct elf_fdpic_params *interp_params, + unsigned long *start_stack, + unsigned long *start_brk); +#endif + +#endif /* _LINUX_ELF_FDPIC_H */ diff --git a/include/linux/extcon.h b/include/linux/extcon.h index 7443a560c9d..2c26c14cd71 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -68,7 +68,7 @@ enum extcon_cable_name { EXTCON_VIDEO_OUT, EXTCON_MECHANICAL, }; -extern const char *extcon_cable_name[]; +extern const char extcon_cable_name[][CABLE_NAME_MAX + 1]; struct extcon_cable; diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 45052aa814c..fb7dacae052 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h @@ -95,7 +95,6 @@ struct task_struct; struct files_struct *get_files_struct(struct task_struct *); void put_files_struct(struct files_struct *fs); void reset_files_struct(struct files_struct *); -void daemonize_descriptors(void); int unshare_files(struct files_struct **); struct files_struct *dup_fd(struct files_struct *, int *); void do_close_on_exec(struct files_struct *); diff --git a/include/linux/fs.h b/include/linux/fs.h index 001c7cff2d4..b33cfc97b9c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -64,6 +64,73 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, ssize_t bytes, void *private, int ret, bool is_async); +#define MAY_EXEC 0x00000001 +#define MAY_WRITE 0x00000002 +#define MAY_READ 0x00000004 +#define MAY_APPEND 0x00000008 +#define MAY_ACCESS 0x00000010 +#define MAY_OPEN 0x00000020 +#define MAY_CHDIR 0x00000040 +/* called from RCU mode, don't block */ +#define MAY_NOT_BLOCK 0x00000080 + +/* + * flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond + * to O_WRONLY and O_RDWR via the strange trick in __dentry_open() + */ + +/* file is open for reading */ +#define FMODE_READ ((__force fmode_t)0x1) +/* file is open for writing */ +#define FMODE_WRITE ((__force fmode_t)0x2) +/* file is seekable */ +#define FMODE_LSEEK ((__force fmode_t)0x4) +/* file can be accessed using pread */ +#define FMODE_PREAD ((__force fmode_t)0x8) +/* file can be accessed using pwrite */ +#define FMODE_PWRITE ((__force fmode_t)0x10) +/* File is opened for execution with sys_execve / sys_uselib */ +#define FMODE_EXEC ((__force fmode_t)0x20) +/* File is opened with O_NDELAY (only set for block devices) */ +#define FMODE_NDELAY ((__force fmode_t)0x40) +/* File is opened with O_EXCL (only set for block devices) */ +#define FMODE_EXCL ((__force fmode_t)0x80) +/* File is opened using open(.., 3, ..) and is writeable only for ioctls + (specialy hack for floppy.c) */ +#define FMODE_WRITE_IOCTL ((__force fmode_t)0x100) +/* 32bit hashes as llseek() offset (for directories) */ +#define FMODE_32BITHASH ((__force fmode_t)0x200) +/* 64bit hashes as llseek() offset (for directories) */ +#define FMODE_64BITHASH ((__force fmode_t)0x400) + +/* + * Don't update ctime and mtime. + * + * Currently a special hack for the XFS open_by_handle ioctl, but we'll + * hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon. + */ +#define FMODE_NOCMTIME ((__force fmode_t)0x800) + +/* Expect random access pattern */ +#define FMODE_RANDOM ((__force fmode_t)0x1000) + +/* File is huge (eg. /dev/kmem): treat loff_t as unsigned */ +#define FMODE_UNSIGNED_OFFSET ((__force fmode_t)0x2000) + +/* File is opened with O_PATH; almost nothing can be done with it */ +#define FMODE_PATH ((__force fmode_t)0x4000) + +/* File was opened by fanotify and shouldn't generate fanotify events */ +#define FMODE_NONOTIFY ((__force fmode_t)0x1000000) + +/* + * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector + * that indicates that they should check the contents of the iovec are + * valid, but not check the memory that the iovec elements + * points too. + */ +#define CHECK_IOVEC_ONLY -1 + /* * The below are the various read and write types that we support. Some of * them include behavioral modifiers that send information down to the @@ -1557,6 +1624,60 @@ struct super_operations { }; /* + * Inode flags - they have no relation to superblock flags now + */ +#define S_SYNC 1 /* Writes are synced at once */ +#define S_NOATIME 2 /* Do not update access times */ +#define S_APPEND 4 /* Append-only file */ +#define S_IMMUTABLE 8 /* Immutable file */ +#define S_DEAD 16 /* removed, but still open directory */ +#define S_NOQUOTA 32 /* Inode is not counted to quota */ +#define S_DIRSYNC 64 /* Directory modifications are synchronous */ +#define S_NOCMTIME 128 /* Do not update file c/mtime */ +#define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */ +#define S_PRIVATE 512 /* Inode is fs-internal */ +#define S_IMA 1024 /* Inode has an associated IMA struct */ +#define S_AUTOMOUNT 2048 /* Automount/referral quasi-directory */ +#define S_NOSEC 4096 /* no suid or xattr security attributes */ + +/* + * Note that nosuid etc flags are inode-specific: setting some file-system + * flags just means all the inodes inherit those flags by default. It might be + * possible to override it selectively if you really wanted to with some + * ioctl() that is not currently implemented. + * + * Exception: MS_RDONLY is always applied to the entire file system. + * + * Unfortunately, it is possible to change a filesystems flags with it mounted + * with files in use. This means that all of the inodes will not have their + * i_flags updated. Hence, i_flags no longer inherit the superblock mount + * flags, so these have to be checked separately. -- rmk@arm.uk.linux.org + */ +#define __IS_FLG(inode, flg) ((inode)->i_sb->s_flags & (flg)) + +#define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY) +#define IS_SYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS) || \ + ((inode)->i_flags & S_SYNC)) +#define IS_DIRSYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \ + ((inode)->i_flags & (S_SYNC|S_DIRSYNC))) +#define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK) +#define IS_NOATIME(inode) __IS_FLG(inode, MS_RDONLY|MS_NOATIME) +#define IS_I_VERSION(inode) __IS_FLG(inode, MS_I_VERSION) + +#define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) +#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) +#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) +#define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL) + +#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD) +#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME) +#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE) +#define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE) +#define IS_IMA(inode) ((inode)->i_flags & S_IMA) +#define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT) +#define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC) + +/* * Inode state bits. Protected by inode->i_lock * * Three bits determine the dirty state of the inode, I_DIRTY_SYNC, @@ -1688,6 +1809,11 @@ int sync_inode_metadata(struct inode *inode, int wait); struct file_system_type { const char *name; int fs_flags; +#define FS_REQUIRES_DEV 1 +#define FS_BINARY_MOUNTDATA 2 +#define FS_HAS_SUBTYPE 4 +#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */ +#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */ struct dentry *(*mount) (struct file_system_type *, int, const char *, void *); void (*kill_sb) (struct super_block *); diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h index 003dc0fd734..d0ae3a84bcf 100644 --- a/include/linux/fs_struct.h +++ b/include/linux/fs_struct.h @@ -21,7 +21,6 @@ extern void set_fs_root(struct fs_struct *, struct path *); extern void set_fs_pwd(struct fs_struct *, struct path *); extern struct fs_struct *copy_fs_struct(struct fs_struct *); extern void free_fs_struct(struct fs_struct *); -extern void daemonize_fs_struct(void); extern int unshare_fs_struct(void); static inline void get_fs_root(struct fs_struct *fs, struct path *root) diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h new file mode 100644 index 00000000000..227c62424f3 --- /dev/null +++ b/include/linux/hashtable.h @@ -0,0 +1,192 @@ +/* + * Statically sized hash table implementation + * (C) 2012 Sasha Levin <levinsasha928@gmail.com> + */ + +#ifndef _LINUX_HASHTABLE_H +#define _LINUX_HASHTABLE_H + +#include <linux/list.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/hash.h> +#include <linux/rculist.h> + +#define DEFINE_HASHTABLE(name, bits) \ + struct hlist_head name[1 << (bits)] = \ + { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT } + +#define DECLARE_HASHTABLE(name, bits) \ + struct hlist_head name[1 << (bits)] + +#define HASH_SIZE(name) (ARRAY_SIZE(name)) +#define HASH_BITS(name) ilog2(HASH_SIZE(name)) + +/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */ +#define hash_min(val, bits) \ + (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits)) + +static inline void __hash_init(struct hlist_head *ht, unsigned int sz) +{ + unsigned int i; + + for (i = 0; i < sz; i++) + INIT_HLIST_HEAD(&ht[i]); +} + +/** + * hash_init - initialize a hash table + * @hashtable: hashtable to be initialized + * + * Calculates the size of the hashtable from the given parameter, otherwise + * same as hash_init_size. + * + * This has to be a macro since HASH_BITS() will not work on pointers since + * it calculates the size during preprocessing. + */ +#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable)) + +/** + * hash_add - add an object to a hashtable + * @hashtable: hashtable to add to + * @node: the &struct hlist_node of the object to be added + * @key: the key of the object to be added + */ +#define hash_add(hashtable, node, key) \ + hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) + +/** + * hash_add_rcu - add an object to a rcu enabled hashtable + * @hashtable: hashtable to add to + * @node: the &struct hlist_node of the object to be added + * @key: the key of the object to be added + */ +#define hash_add_rcu(hashtable, node, key) \ + hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) + +/** + * hash_hashed - check whether an object is in any hashtable + * @node: the &struct hlist_node of the object to be checked + */ +static inline bool hash_hashed(struct hlist_node *node) +{ + return !hlist_unhashed(node); +} + +static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz) +{ + unsigned int i; + + for (i = 0; i < sz; i++) + if (!hlist_empty(&ht[i])) + return false; + + return true; +} + +/** + * hash_empty - check whether a hashtable is empty + * @hashtable: hashtable to check + * + * This has to be a macro since HASH_BITS() will not work on pointers since + * it calculates the size during preprocessing. + */ +#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable)) + +/** + * hash_del - remove an object from a hashtable + * @node: &struct hlist_node of the object to remove + */ +static inline void hash_del(struct hlist_node *node) +{ + hlist_del_init(node); +} + +/** + * hash_del_rcu - remove an object from a rcu enabled hashtable + * @node: &struct hlist_node of the object to remove + */ +static inline void hash_del_rcu(struct hlist_node *node) +{ + hlist_del_init_rcu(node); +} + +/** + * hash_for_each - iterate over a hashtable + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @node: the &struct list_head to use as a loop cursor for each entry + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each(name, bkt, node, obj, member) \ + for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ + hlist_for_each_entry(obj, node, &name[bkt], member) + +/** + * hash_for_each_rcu - iterate over a rcu enabled hashtable + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @node: the &struct list_head to use as a loop cursor for each entry + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each_rcu(name, bkt, node, obj, member) \ + for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ + hlist_for_each_entry_rcu(obj, node, &name[bkt], member) + +/** + * hash_for_each_safe - iterate over a hashtable safe against removal of + * hash entry + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @node: the &struct list_head to use as a loop cursor for each entry + * @tmp: a &struct used for temporary storage + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each_safe(name, bkt, node, tmp, obj, member) \ + for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ + hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member) + +/** + * hash_for_each_possible - iterate over all possible objects hashing to the + * same bucket + * @name: hashtable to iterate + * @obj: the type * to use as a loop cursor for each entry + * @node: the &struct list_head to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + * @key: the key of the objects to iterate over + */ +#define hash_for_each_possible(name, obj, node, member, key) \ + hlist_for_each_entry(obj, node, &name[hash_min(key, HASH_BITS(name))], member) + +/** + * hash_for_each_possible_rcu - iterate over all possible objects hashing to the + * same bucket in an rcu enabled hashtable + * in a rcu enabled hashtable + * @name: hashtable to iterate + * @obj: the type * to use as a loop cursor for each entry + * @node: the &struct list_head to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + * @key: the key of the objects to iterate over + */ +#define hash_for_each_possible_rcu(name, obj, node, member, key) \ + hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member) + +/** + * hash_for_each_possible_safe - iterate over all possible objects hashing to the + * same bucket safe against removals + * @name: hashtable to iterate + * @obj: the type * to use as a loop cursor for each entry + * @node: the &struct list_head to use as a loop cursor for each entry + * @tmp: a &struct used for temporary storage + * @member: the name of the hlist_node within the struct + * @key: the key of the objects to iterate over + */ +#define hash_for_each_possible_safe(name, obj, node, tmp, member, key) \ + hlist_for_each_entry_safe(obj, node, tmp, \ + &name[hash_min(key, HASH_BITS(name))], member) + + +#endif diff --git a/include/linux/hsi/Kbuild b/include/linux/hsi/Kbuild index 271a770b478..e69de29bb2d 100644 --- a/include/linux/hsi/Kbuild +++ b/include/linux/hsi/Kbuild @@ -1 +0,0 @@ -header-y += hsi_char.h diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h index df804ba73e0..92a0dc75bc7 100644 --- a/include/linux/i2c-omap.h +++ b/include/linux/i2c-omap.h @@ -34,6 +34,7 @@ struct omap_i2c_bus_platform_data { u32 clkrate; u32 rev; u32 flags; + void (*set_mpu_wkup_lat)(struct device *dev, long set); }; #endif diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index c0ae76ac4e0..7806c24e5bc 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -618,4 +618,20 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev) }; #endif +/** + * IIO_DEGREE_TO_RAD() - Convert degree to rad + * @deg: A value in degree + * + * Returns the given value converted from degree to rad + */ +#define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL) + +/** + * IIO_G_TO_M_S_2() - Convert g to meter / second**2 + * @g: A value in g + * + * Returns the given value converted from g to meter / second**2 + */ +#define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL) + #endif /* _INDUSTRIAL_IO_H_ */ diff --git a/include/linux/isdn/Kbuild b/include/linux/isdn/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/isdn/Kbuild +++ /dev/null diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 93bfc9f9815..ecc554374e4 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -42,19 +42,8 @@ */ #define KVM_MEMSLOT_INVALID (1UL << 16) -/* - * If we support unaligned MMIO, at most one fragment will be split into two: - */ -#ifdef KVM_UNALIGNED_MMIO -# define KVM_EXTRA_MMIO_FRAGMENTS 1 -#else -# define KVM_EXTRA_MMIO_FRAGMENTS 0 -#endif - -#define KVM_USER_MMIO_SIZE 8 - -#define KVM_MAX_MMIO_FRAGMENTS \ - (KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS) +/* Two fragments for cross MMIO pages. */ +#define KVM_MAX_MMIO_FRAGMENTS 2 /* * For the normal pfn, the highest 12 bits should be zero, diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 569d67d4243..d452ee19106 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +void memblock_trim_memory(phys_addr_t align); #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, diff --git a/include/linux/mfd/max77693.h b/include/linux/mfd/max77693.h index 1d28ae90384..fe03b2d35d4 100644 --- a/include/linux/mfd/max77693.h +++ b/include/linux/mfd/max77693.h @@ -30,7 +30,20 @@ #ifndef __LINUX_MFD_MAX77693_H #define __LINUX_MFD_MAX77693_H +struct max77693_reg_data { + u8 addr; + u8 data; +}; + +struct max77693_muic_platform_data { + struct max77693_reg_data *init_data; + int num_init_data; +}; + struct max77693_platform_data { int wakeup; + + /* muic data */ + struct max77693_muic_platform_data *muic_data; }; #endif /* __LINUX_MFD_MAX77693_H */ diff --git a/include/linux/mm.h b/include/linux/mm.h index fa068040273..bcaab4e6fe9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1684,9 +1684,5 @@ static inline unsigned int debug_guardpage_minorder(void) { return 0; } static inline bool page_is_guard(struct page *page) { return false; } #endif /* CONFIG_DEBUG_PAGEALLOC */ -extern void reset_zone_present_pages(void); -extern void fixup_zone_present_pages(int nid, unsigned long start_pfn, - unsigned long end_pfn); - #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/include/linux/mmc/Kbuild b/include/linux/mmc/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/mmc/Kbuild +++ /dev/null diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 7c6a1139d8f..96531664a06 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -137,7 +137,7 @@ struct dw_mci { dma_addr_t sg_dma; void *sg_cpu; - struct dw_mci_dma_ops *dma_ops; + const struct dw_mci_dma_ops *dma_ops; #ifdef CONFIG_MMC_DW_IDMAC unsigned int ring_size; #else @@ -162,7 +162,7 @@ struct dw_mci { u16 data_offset; struct device *dev; struct dw_mci_board *pdata; - struct dw_mci_drv_data *drv_data; + const struct dw_mci_drv_data *drv_data; void *priv; struct clk *biu_clk; struct clk *ciu_clk; @@ -186,7 +186,7 @@ struct dw_mci { struct regulator *vmmc; /* Power regulator */ unsigned long irq_flags; /* IRQ flags */ - unsigned int irq; + int irq; }; /* DMA ops for Internal/External DMAC interface */ diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index fa8529a859b..1edcb4dad8c 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -91,6 +91,7 @@ struct sdhci_host { unsigned int quirks2; /* More deviations from spec. */ #define SDHCI_QUIRK2_HOST_OFF_CARD_ON (1<<0) +#define SDHCI_QUIRK2_HOST_NO_CMD23 (1<<1) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 50aaca81f63..a23923ba826 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -752,7 +752,7 @@ extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn, unsigned long size, enum memmap_context context); -extern void lruvec_init(struct lruvec *lruvec, struct zone *zone); +extern void lruvec_init(struct lruvec *lruvec); static inline struct zone *lruvec_zone(struct lruvec *lruvec) { diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild deleted file mode 100644 index b3322023e9a..00000000000 --- a/include/linux/netfilter/Kbuild +++ /dev/null @@ -1 +0,0 @@ -header-y += ipset/ diff --git a/include/linux/netfilter/ipset/Kbuild b/include/linux/netfilter/ipset/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/netfilter/ipset/Kbuild +++ /dev/null diff --git a/include/linux/netfilter_arp/Kbuild b/include/linux/netfilter_arp/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/netfilter_arp/Kbuild +++ /dev/null diff --git a/include/linux/netfilter_bridge/Kbuild b/include/linux/netfilter_bridge/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/netfilter_bridge/Kbuild +++ /dev/null diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/netfilter_ipv4/Kbuild +++ /dev/null diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/netfilter_ipv6/Kbuild +++ /dev/null diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/nfsd/Kbuild +++ /dev/null diff --git a/include/linux/of.h b/include/linux/of.h index 72843b72a2b..b4e50d56fc7 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -331,6 +331,13 @@ static inline bool of_have_populated_dt(void) #define for_each_child_of_node(parent, child) \ while (0) +static inline struct device_node *of_get_child_by_name( + const struct device_node *node, + const char *name) +{ + return NULL; +} + static inline int of_get_child_count(const struct device_node *np) { return 0; diff --git a/include/linux/of_address.h b/include/linux/of_address.h index c3cdc1025c3..0506eb53519 100644 --- a/include/linux/of_address.h +++ b/include/linux/of_address.h @@ -19,7 +19,7 @@ extern void __iomem *of_iomap(struct device_node *device, int index); * the address space flags too. The PCI version uses a BAR number * instead of an absolute index */ -extern const u32 *of_get_address(struct device_node *dev, int index, +extern const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags); #ifndef pci_address_to_pio @@ -28,11 +28,13 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; } #endif #else /* CONFIG_OF_ADDRESS */ +#ifndef of_address_to_resource static inline int of_address_to_resource(struct device_node *dev, int index, struct resource *r) { return -EINVAL; } +#endif static inline struct device_node *of_find_matching_node_by_address( struct device_node *from, const struct of_device_id *matches, @@ -40,11 +42,13 @@ static inline struct device_node *of_find_matching_node_by_address( { return NULL; } +#ifndef of_iomap static inline void __iomem *of_iomap(struct device_node *device, int index) { return NULL; } -static inline const u32 *of_get_address(struct device_node *dev, int index, +#endif +static inline const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags) { return NULL; diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h index b8e24112520..535cecf1e02 100644 --- a/include/linux/of_irq.h +++ b/include/linux/of_irq.h @@ -58,8 +58,8 @@ static inline int of_irq_map_oldworld(struct device_node *device, int index, #endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */ -extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec, - u32 ointsize, const u32 *addr, +extern int of_irq_map_raw(struct device_node *parent, const __be32 *intspec, + u32 ointsize, const __be32 *addr, struct of_irq *out_irq); extern int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq); diff --git a/include/linux/percpu-rwsem.h b/include/linux/percpu-rwsem.h index cf80f7e5277..250a4acddb2 100644 --- a/include/linux/percpu-rwsem.h +++ b/include/linux/percpu-rwsem.h @@ -12,34 +12,27 @@ struct percpu_rw_semaphore { struct mutex mtx; }; +#define light_mb() barrier() +#define heavy_mb() synchronize_sched() + static inline void percpu_down_read(struct percpu_rw_semaphore *p) { - rcu_read_lock(); + rcu_read_lock_sched(); if (unlikely(p->locked)) { - rcu_read_unlock(); + rcu_read_unlock_sched(); mutex_lock(&p->mtx); this_cpu_inc(*p->counters); mutex_unlock(&p->mtx); return; } this_cpu_inc(*p->counters); - rcu_read_unlock(); + rcu_read_unlock_sched(); + light_mb(); /* A, between read of p->locked and read of data, paired with D */ } static inline void percpu_up_read(struct percpu_rw_semaphore *p) { - /* - * On X86, write operation in this_cpu_dec serves as a memory unlock - * barrier (i.e. memory accesses may be moved before the write, but - * no memory accesses are moved past the write). - * On other architectures this may not be the case, so we need smp_mb() - * there. - */ -#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE)) - barrier(); -#else - smp_mb(); -#endif + light_mb(); /* B, between read of the data and write to p->counter, paired with C */ this_cpu_dec(*p->counters); } @@ -58,14 +51,15 @@ static inline void percpu_down_write(struct percpu_rw_semaphore *p) { mutex_lock(&p->mtx); p->locked = true; - synchronize_rcu(); + synchronize_sched(); /* make sure that all readers exit the rcu_read_lock_sched region */ while (__percpu_count(p->counters)) msleep(1); - smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */ + heavy_mb(); /* C, between read of p->counter and write to data, paired with B */ } static inline void percpu_up_write(struct percpu_rw_semaphore *p) { + heavy_mb(); /* D, between write to data and write to p->locked, paired with A */ p->locked = false; mutex_unlock(&p->mtx); } diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 2e902359aee..6bfb2faa0b1 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -803,12 +803,16 @@ static inline void perf_event_task_tick(void) { } do { \ static struct notifier_block fn##_nb __cpuinitdata = \ { .notifier_call = fn, .priority = CPU_PRI_PERF }; \ + unsigned long cpu = smp_processor_id(); \ + unsigned long flags; \ fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE, \ - (void *)(unsigned long)smp_processor_id()); \ + (void *)(unsigned long)cpu); \ + local_irq_save(flags); \ fn(&fn##_nb, (unsigned long)CPU_STARTING, \ - (void *)(unsigned long)smp_processor_id()); \ + (void *)(unsigned long)cpu); \ + local_irq_restore(flags); \ fn(&fn##_nb, (unsigned long)CPU_ONLINE, \ - (void *)(unsigned long)smp_processor_id()); \ + (void *)(unsigned long)cpu); \ register_cpu_notifier(&fn##_nb); \ } while (0) diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index 00474b04714..65e3e87eacc 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -47,15 +47,9 @@ static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns) } extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns); -extern void free_pid_ns(struct kref *kref); extern void zap_pid_ns_processes(struct pid_namespace *pid_ns); extern int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd); - -static inline void put_pid_ns(struct pid_namespace *ns) -{ - if (ns != &init_pid_ns) - kref_put(&ns->kref, free_pid_ns); -} +extern void put_pid_ns(struct pid_namespace *ns); #else /* !CONFIG_PID_NS */ #include <linux/err.h> diff --git a/include/linux/platform_data/omap_ocp2scp.h b/include/linux/platform_data/omap_ocp2scp.h new file mode 100644 index 00000000000..5c6c3939355 --- /dev/null +++ b/include/linux/platform_data/omap_ocp2scp.h @@ -0,0 +1,31 @@ +/* + * omap_ocp2scp.h -- ocp2scp header file + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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. + * + * Author: Kishon Vijay Abraham I <kishon@ti.com> + * + * 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. + * + */ + +#ifndef __DRIVERS_OMAP_OCP2SCP_H +#define __DRIVERS_OMAP_OCP2SCP_H + +struct omap_ocp2scp_dev { + const char *drv_name; + struct resource *res; +}; + +struct omap_ocp2scp_platform_data { + int dev_cnt; + struct omap_ocp2scp_dev **devices; +}; +#endif /* __DRIVERS_OMAP_OCP2SCP_H */ diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h index f2dc6d8fc68..38a99350832 100644 --- a/include/linux/ptp_clock_kernel.h +++ b/include/linux/ptp_clock_kernel.h @@ -54,7 +54,8 @@ struct ptp_clock_request { * clock operations * * @adjfreq: Adjusts the frequency of the hardware clock. - * parameter delta: Desired period change in parts per billion. + * parameter delta: Desired frequency offset from nominal frequency + * in parts per billion * * @adjtime: Shifts the time of the hardware clock. * parameter delta: Desired change in nanoseconds. diff --git a/include/linux/raid/Kbuild b/include/linux/raid/Kbuild index 2415a64c5e5..e69de29bb2d 100644 --- a/include/linux/raid/Kbuild +++ b/include/linux/raid/Kbuild @@ -1,2 +0,0 @@ -header-y += md_p.h -header-y += md_u.h diff --git a/include/linux/raid/md_u.h b/include/linux/raid/md_u.h index fb1abb3367e..358c04bfbe2 100644 --- a/include/linux/raid/md_u.h +++ b/include/linux/raid/md_u.h @@ -11,149 +11,10 @@ (for example /usr/src/linux/COPYING); if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - #ifndef _MD_U_H #define _MD_U_H -/* - * Different major versions are not compatible. - * Different minor versions are only downward compatible. - * Different patchlevel versions are downward and upward compatible. - */ -#define MD_MAJOR_VERSION 0 -#define MD_MINOR_VERSION 90 -/* - * MD_PATCHLEVEL_VERSION indicates kernel functionality. - * >=1 means different superblock formats are selectable using SET_ARRAY_INFO - * and major_version/minor_version accordingly - * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT - * in the super status byte - * >=3 means that bitmap superblock version 4 is supported, which uses - * little-ending representation rather than host-endian - */ -#define MD_PATCHLEVEL_VERSION 3 - -/* ioctls */ - -/* status */ -#define RAID_VERSION _IOR (MD_MAJOR, 0x10, mdu_version_t) -#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, mdu_array_info_t) -#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t) -#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13) -#define RAID_AUTORUN _IO (MD_MAJOR, 0x14) -#define GET_BITMAP_FILE _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) - -/* configuration */ -#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20) -#define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, mdu_disk_info_t) -#define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22) -#define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, mdu_array_info_t) -#define SET_DISK_INFO _IO (MD_MAJOR, 0x24) -#define WRITE_RAID_INFO _IO (MD_MAJOR, 0x25) -#define UNPROTECT_ARRAY _IO (MD_MAJOR, 0x26) -#define PROTECT_ARRAY _IO (MD_MAJOR, 0x27) -#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28) -#define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29) -#define HOT_GENERATE_ERROR _IO (MD_MAJOR, 0x2a) -#define SET_BITMAP_FILE _IOW (MD_MAJOR, 0x2b, int) +#include <uapi/linux/raid/md_u.h> -/* usage */ -#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, mdu_param_t) -/* 0x31 was START_ARRAY */ -#define STOP_ARRAY _IO (MD_MAJOR, 0x32) -#define STOP_ARRAY_RO _IO (MD_MAJOR, 0x33) -#define RESTART_ARRAY_RW _IO (MD_MAJOR, 0x34) - -/* 63 partitions with the alternate major number (mdp) */ -#define MdpMinorShift 6 -#ifdef __KERNEL__ extern int mdp_major; -#endif - -typedef struct mdu_version_s { - int major; - int minor; - int patchlevel; -} mdu_version_t; - -typedef struct mdu_array_info_s { - /* - * Generic constant information - */ - int major_version; - int minor_version; - int patch_version; - int ctime; - int level; - int size; - int nr_disks; - int raid_disks; - int md_minor; - int not_persistent; - - /* - * Generic state information - */ - int utime; /* 0 Superblock update time */ - int state; /* 1 State bits (clean, ...) */ - int active_disks; /* 2 Number of currently active disks */ - int working_disks; /* 3 Number of working disks */ - int failed_disks; /* 4 Number of failed disks */ - int spare_disks; /* 5 Number of spare disks */ - - /* - * Personality information - */ - int layout; /* 0 the array's physical layout */ - int chunk_size; /* 1 chunk size in bytes */ - -} mdu_array_info_t; - -/* non-obvious values for 'level' */ -#define LEVEL_MULTIPATH (-4) -#define LEVEL_LINEAR (-1) -#define LEVEL_FAULTY (-5) - -/* we need a value for 'no level specified' and 0 - * means 'raid0', so we need something else. This is - * for internal use only - */ -#define LEVEL_NONE (-1000000) - -typedef struct mdu_disk_info_s { - /* - * configuration/status of one particular disk - */ - int number; - int major; - int minor; - int raid_disk; - int state; - -} mdu_disk_info_t; - -typedef struct mdu_start_info_s { - /* - * configuration/status of one particular disk - */ - int major; - int minor; - int raid_disk; - int state; - -} mdu_start_info_t; - -typedef struct mdu_bitmap_file_s -{ - char pathname[4096]; -} mdu_bitmap_file_t; - -typedef struct mdu_param_s -{ - int personality; /* 1,2,3,4 */ - int chunk_size; /* in bytes */ - int max_fault; /* unused for now */ -} mdu_param_t; - #endif - diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h index e11ccb4cf48..0a260d8a18b 100644 --- a/include/linux/ratelimit.h +++ b/include/linux/ratelimit.h @@ -46,20 +46,17 @@ extern int ___ratelimit(struct ratelimit_state *rs, const char *func); #define WARN_ON_RATELIMIT(condition, state) \ WARN_ON((condition) && __ratelimit(state)) -#define __WARN_RATELIMIT(condition, state, format...) \ -({ \ - int rtn = 0; \ - if (unlikely(__ratelimit(state))) \ - rtn = WARN(condition, format); \ - rtn; \ -}) - -#define WARN_RATELIMIT(condition, format...) \ +#define WARN_RATELIMIT(condition, format, ...) \ ({ \ static DEFINE_RATELIMIT_STATE(_rs, \ DEFAULT_RATELIMIT_INTERVAL, \ DEFAULT_RATELIMIT_BURST); \ - __WARN_RATELIMIT(condition, &_rs, format); \ + int rtn = !!(condition); \ + \ + if (unlikely(rtn && __ratelimit(&_rs))) \ + WARN(rtn, format, ##__VA_ARGS__); \ + \ + rtn; \ }) #else @@ -67,15 +64,9 @@ extern int ___ratelimit(struct ratelimit_state *rs, const char *func); #define WARN_ON_RATELIMIT(condition, state) \ WARN_ON(condition) -#define __WARN_RATELIMIT(condition, state, format...) \ -({ \ - int rtn = WARN(condition, format); \ - rtn; \ -}) - -#define WARN_RATELIMIT(condition, format...) \ +#define WARN_RATELIMIT(condition, format, ...) \ ({ \ - int rtn = WARN(condition, format); \ + int rtn = WARN(condition, format, ##__VA_ARGS__); \ rtn; \ }) diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h index 214caa33433..2ac60c9cf64 100644 --- a/include/linux/rbtree_augmented.h +++ b/include/linux/rbtree_augmented.h @@ -24,6 +24,7 @@ #ifndef _LINUX_RBTREE_AUGMENTED_H #define _LINUX_RBTREE_AUGMENTED_H +#include <linux/compiler.h> #include <linux/rbtree.h> /* diff --git a/include/linux/rio.h b/include/linux/rio.h index 4187da51100..a3e78427866 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -275,9 +275,11 @@ struct rio_id_table { * struct rio_net - RIO network info * @node: Node in global list of RIO networks * @devices: List of devices in this network + * @switches: List of switches in this netowrk * @mports: List of master ports accessing this network * @hport: Default port for accessing this network * @id: RIO network ID + * @destid_table: destID allocation table */ struct rio_net { struct list_head node; /* node in list of networks */ diff --git a/include/linux/sched.h b/include/linux/sched.h index 0dd42a02df2..a0166481eb2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2283,7 +2283,6 @@ extern void flush_itimer_signals(void); extern void do_group_exit(int); -extern void daemonize(const char *, ...); extern int allow_signal(int); extern int disallow_signal(int); diff --git a/include/linux/spi/Kbuild b/include/linux/spi/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/spi/Kbuild +++ /dev/null diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h index c64de9dd763..2f694f3846a 100644 --- a/include/linux/spi/ads7846.h +++ b/include/linux/spi/ads7846.h @@ -46,8 +46,9 @@ struct ads7846_platform_data { u16 debounce_rep; /* additional consecutive good readings * required after the first two */ int gpio_pendown; /* the GPIO used to decide the pendown - * state if get_pendown_state == NULL - */ + * state if get_pendown_state == NULL */ + int gpio_pendown_debounce; /* platform specific debounce time for + * the gpio_pendown */ int (*get_pendown_state)(void); int (*filter_init) (const struct ads7846_platform_data *pdata, void **filter_data); diff --git a/include/linux/spi/tsc2005.h b/include/linux/spi/tsc2005.h index d9b0c84220c..8f721e465e0 100644 --- a/include/linux/spi/tsc2005.h +++ b/include/linux/spi/tsc2005.h @@ -3,8 +3,6 @@ * * Copyright (C) 2009-2010 Nokia Corporation * - * Contact: Aaro Koskinen <aaro.koskinen@nokia.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 diff --git a/include/linux/sunrpc/Kbuild b/include/linux/sunrpc/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/sunrpc/Kbuild +++ /dev/null diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/tc_act/Kbuild +++ /dev/null diff --git a/include/linux/tc_ematch/Kbuild b/include/linux/tc_ematch/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/tc_ematch/Kbuild +++ /dev/null diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 8a7fc4be2d7..60b7aac15e0 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -191,7 +191,8 @@ struct tcp_sock { u8 do_early_retrans:1,/* Enable RFC5827 early-retransmit */ early_retrans_delayed:1, /* Delayed ER timer installed */ syn_data:1, /* SYN includes data */ - syn_fastopen:1; /* SYN includes Fast Open option */ + syn_fastopen:1, /* SYN includes Fast Open option */ + syn_data_acked:1;/* data in SYN is acked by SYN-ACK */ /* RTT measurement */ u32 srtt; /* smoothed round trip time << 3 */ diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h index e6f0331e3d4..24594571c5a 100644 --- a/include/linux/uprobes.h +++ b/include/linux/uprobes.h @@ -35,16 +35,6 @@ struct inode; # include <asm/uprobes.h> #endif -/* flags that denote/change uprobes behaviour */ - -/* Have a copy of original instruction */ -#define UPROBE_COPY_INSN 0x1 - -/* Dont run handlers when first register/ last unregister in progress*/ -#define UPROBE_RUN_HANDLER 0x2 -/* Can skip singlestep */ -#define UPROBE_SKIP_SSTEP 0x4 - struct uprobe_consumer { int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs); /* @@ -59,7 +49,6 @@ struct uprobe_consumer { #ifdef CONFIG_UPROBES enum uprobe_task_state { UTASK_RUNNING, - UTASK_BP_HIT, UTASK_SSTEP, UTASK_SSTEP_ACK, UTASK_SSTEP_TRAPPED, diff --git a/include/linux/usb.h b/include/linux/usb.h index 07915a32fb9..10278d18709 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1778,17 +1778,6 @@ static inline int usb_translate_errors(int error_code) extern void usb_register_notify(struct notifier_block *nb); extern void usb_unregister_notify(struct notifier_block *nb); -#ifdef DEBUG -#define dbg(format, arg...) \ - printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg) -#else -#define dbg(format, arg...) \ -do { \ - if (0) \ - printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ -} while (0) -#endif - /* debugfs stuff */ extern struct dentry *usb_debug_root; diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild index b607f3532e8..e69de29bb2d 100644 --- a/include/linux/usb/Kbuild +++ b/include/linux/usb/Kbuild @@ -1,10 +0,0 @@ -header-y += audio.h -header-y += cdc.h -header-y += ch9.h -header-y += ch11.h -header-y += functionfs.h -header-y += gadgetfs.h -header-y += midi.h -header-y += g_printer.h -header-y += tmc.h -header-y += video.h diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h index a54b8255d75..3d84619110a 100644 --- a/include/linux/usb/audio.h +++ b/include/linux/usb/audio.h @@ -17,531 +17,11 @@ * Types and defines in this file are either specific to version 1.0 of * this standard or common for newer versions. */ - #ifndef __LINUX_USB_AUDIO_H #define __LINUX_USB_AUDIO_H -#include <linux/types.h> - -/* bInterfaceProtocol values to denote the version of the standard used */ -#define UAC_VERSION_1 0x00 -#define UAC_VERSION_2 0x20 - -/* A.2 Audio Interface Subclass Codes */ -#define USB_SUBCLASS_AUDIOCONTROL 0x01 -#define USB_SUBCLASS_AUDIOSTREAMING 0x02 -#define USB_SUBCLASS_MIDISTREAMING 0x03 - -/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */ -#define UAC_HEADER 0x01 -#define UAC_INPUT_TERMINAL 0x02 -#define UAC_OUTPUT_TERMINAL 0x03 -#define UAC_MIXER_UNIT 0x04 -#define UAC_SELECTOR_UNIT 0x05 -#define UAC_FEATURE_UNIT 0x06 -#define UAC1_PROCESSING_UNIT 0x07 -#define UAC1_EXTENSION_UNIT 0x08 - -/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */ -#define UAC_AS_GENERAL 0x01 -#define UAC_FORMAT_TYPE 0x02 -#define UAC_FORMAT_SPECIFIC 0x03 - -/* A.7 Processing Unit Process Types */ -#define UAC_PROCESS_UNDEFINED 0x00 -#define UAC_PROCESS_UP_DOWNMIX 0x01 -#define UAC_PROCESS_DOLBY_PROLOGIC 0x02 -#define UAC_PROCESS_STEREO_EXTENDER 0x03 -#define UAC_PROCESS_REVERB 0x04 -#define UAC_PROCESS_CHORUS 0x05 -#define UAC_PROCESS_DYN_RANGE_COMP 0x06 - -/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */ -#define UAC_EP_GENERAL 0x01 - -/* A.9 Audio Class-Specific Request Codes */ -#define UAC_SET_ 0x00 -#define UAC_GET_ 0x80 - -#define UAC__CUR 0x1 -#define UAC__MIN 0x2 -#define UAC__MAX 0x3 -#define UAC__RES 0x4 -#define UAC__MEM 0x5 - -#define UAC_SET_CUR (UAC_SET_ | UAC__CUR) -#define UAC_GET_CUR (UAC_GET_ | UAC__CUR) -#define UAC_SET_MIN (UAC_SET_ | UAC__MIN) -#define UAC_GET_MIN (UAC_GET_ | UAC__MIN) -#define UAC_SET_MAX (UAC_SET_ | UAC__MAX) -#define UAC_GET_MAX (UAC_GET_ | UAC__MAX) -#define UAC_SET_RES (UAC_SET_ | UAC__RES) -#define UAC_GET_RES (UAC_GET_ | UAC__RES) -#define UAC_SET_MEM (UAC_SET_ | UAC__MEM) -#define UAC_GET_MEM (UAC_GET_ | UAC__MEM) - -#define UAC_GET_STAT 0xff - -/* A.10 Control Selector Codes */ - -/* A.10.1 Terminal Control Selectors */ -#define UAC_TERM_COPY_PROTECT 0x01 - -/* A.10.2 Feature Unit Control Selectors */ -#define UAC_FU_MUTE 0x01 -#define UAC_FU_VOLUME 0x02 -#define UAC_FU_BASS 0x03 -#define UAC_FU_MID 0x04 -#define UAC_FU_TREBLE 0x05 -#define UAC_FU_GRAPHIC_EQUALIZER 0x06 -#define UAC_FU_AUTOMATIC_GAIN 0x07 -#define UAC_FU_DELAY 0x08 -#define UAC_FU_BASS_BOOST 0x09 -#define UAC_FU_LOUDNESS 0x0a - -#define UAC_CONTROL_BIT(CS) (1 << ((CS) - 1)) - -/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */ -#define UAC_UD_ENABLE 0x01 -#define UAC_UD_MODE_SELECT 0x02 - -/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */ -#define UAC_DP_ENABLE 0x01 -#define UAC_DP_MODE_SELECT 0x02 - -/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */ -#define UAC_3D_ENABLE 0x01 -#define UAC_3D_SPACE 0x02 - -/* A.10.3.4 Reverberation Processing Unit Control Selectors */ -#define UAC_REVERB_ENABLE 0x01 -#define UAC_REVERB_LEVEL 0x02 -#define UAC_REVERB_TIME 0x03 -#define UAC_REVERB_FEEDBACK 0x04 - -/* A.10.3.5 Chorus Processing Unit Control Selectors */ -#define UAC_CHORUS_ENABLE 0x01 -#define UAC_CHORUS_LEVEL 0x02 -#define UAC_CHORUS_RATE 0x03 -#define UAC_CHORUS_DEPTH 0x04 - -/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */ -#define UAC_DCR_ENABLE 0x01 -#define UAC_DCR_RATE 0x02 -#define UAC_DCR_MAXAMPL 0x03 -#define UAC_DCR_THRESHOLD 0x04 -#define UAC_DCR_ATTACK_TIME 0x05 -#define UAC_DCR_RELEASE_TIME 0x06 - -/* A.10.4 Extension Unit Control Selectors */ -#define UAC_XU_ENABLE 0x01 - -/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */ -#define UAC_MS_HEADER 0x01 -#define UAC_MIDI_IN_JACK 0x02 -#define UAC_MIDI_OUT_JACK 0x03 - -/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */ -#define UAC_MS_GENERAL 0x01 - -/* Terminals - 2.1 USB Terminal Types */ -#define UAC_TERMINAL_UNDEFINED 0x100 -#define UAC_TERMINAL_STREAMING 0x101 -#define UAC_TERMINAL_VENDOR_SPEC 0x1FF - -/* Terminal Control Selectors */ -/* 4.3.2 Class-Specific AC Interface Descriptor */ -struct uac1_ac_header_descriptor { - __u8 bLength; /* 8 + n */ - __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ - __u8 bDescriptorSubtype; /* UAC_MS_HEADER */ - __le16 bcdADC; /* 0x0100 */ - __le16 wTotalLength; /* includes Unit and Terminal desc. */ - __u8 bInCollection; /* n */ - __u8 baInterfaceNr[]; /* [n] */ -} __attribute__ ((packed)); - -#define UAC_DT_AC_HEADER_SIZE(n) (8 + (n)) - -/* As above, but more useful for defining your own descriptors: */ -#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n) \ -struct uac1_ac_header_descriptor_##n { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubtype; \ - __le16 bcdADC; \ - __le16 wTotalLength; \ - __u8 bInCollection; \ - __u8 baInterfaceNr[n]; \ -} __attribute__ ((packed)) - -/* 4.3.2.1 Input Terminal Descriptor */ -struct uac_input_terminal_descriptor { - __u8 bLength; /* in bytes: 12 */ - __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ - __u8 bDescriptorSubtype; /* INPUT_TERMINAL descriptor subtype */ - __u8 bTerminalID; /* Constant uniquely terminal ID */ - __le16 wTerminalType; /* USB Audio Terminal Types */ - __u8 bAssocTerminal; /* ID of the Output Terminal associated */ - __u8 bNrChannels; /* Number of logical output channels */ - __le16 wChannelConfig; - __u8 iChannelNames; - __u8 iTerminal; -} __attribute__ ((packed)); - -#define UAC_DT_INPUT_TERMINAL_SIZE 12 - -/* Terminals - 2.2 Input Terminal Types */ -#define UAC_INPUT_TERMINAL_UNDEFINED 0x200 -#define UAC_INPUT_TERMINAL_MICROPHONE 0x201 -#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE 0x202 -#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE 0x203 -#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE 0x204 -#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY 0x205 -#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY 0x206 - -/* Terminals - control selectors */ - -#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL 0x01 - -/* 4.3.2.2 Output Terminal Descriptor */ -struct uac1_output_terminal_descriptor { - __u8 bLength; /* in bytes: 9 */ - __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ - __u8 bDescriptorSubtype; /* OUTPUT_TERMINAL descriptor subtype */ - __u8 bTerminalID; /* Constant uniquely terminal ID */ - __le16 wTerminalType; /* USB Audio Terminal Types */ - __u8 bAssocTerminal; /* ID of the Input Terminal associated */ - __u8 bSourceID; /* ID of the connected Unit or Terminal*/ - __u8 iTerminal; -} __attribute__ ((packed)); - -#define UAC_DT_OUTPUT_TERMINAL_SIZE 9 - -/* Terminals - 2.3 Output Terminal Types */ -#define UAC_OUTPUT_TERMINAL_UNDEFINED 0x300 -#define UAC_OUTPUT_TERMINAL_SPEAKER 0x301 -#define UAC_OUTPUT_TERMINAL_HEADPHONES 0x302 -#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303 -#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER 0x304 -#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER 0x305 -#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306 -#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307 - -/* Set bControlSize = 2 as default setting */ -#define UAC_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 2) - -/* As above, but more useful for defining your own descriptors: */ -#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch) \ -struct uac_feature_unit_descriptor_##ch { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubtype; \ - __u8 bUnitID; \ - __u8 bSourceID; \ - __u8 bControlSize; \ - __le16 bmaControls[ch + 1]; \ - __u8 iFeature; \ -} __attribute__ ((packed)) - -/* 4.3.2.3 Mixer Unit Descriptor */ -struct uac_mixer_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bUnitID; - __u8 bNrInPins; - __u8 baSourceID[]; -} __attribute__ ((packed)); +#include <uapi/linux/usb/audio.h> -static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *desc) -{ - return desc->baSourceID[desc->bNrInPins]; -} - -static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc, - int protocol) -{ - if (protocol == UAC_VERSION_1) - return (desc->baSourceID[desc->bNrInPins + 2] << 8) | - desc->baSourceID[desc->bNrInPins + 1]; - else - return (desc->baSourceID[desc->bNrInPins + 4] << 24) | - (desc->baSourceID[desc->bNrInPins + 3] << 16) | - (desc->baSourceID[desc->bNrInPins + 2] << 8) | - (desc->baSourceID[desc->bNrInPins + 1]); -} - -static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc, - int protocol) -{ - return (protocol == UAC_VERSION_1) ? - desc->baSourceID[desc->bNrInPins + 3] : - desc->baSourceID[desc->bNrInPins + 5]; -} - -static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc, - int protocol) -{ - return (protocol == UAC_VERSION_1) ? - &desc->baSourceID[desc->bNrInPins + 4] : - &desc->baSourceID[desc->bNrInPins + 6]; -} - -static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc) -{ - __u8 *raw = (__u8 *) desc; - return raw[desc->bLength - 1]; -} - -/* 4.3.2.4 Selector Unit Descriptor */ -struct uac_selector_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bUintID; - __u8 bNrInPins; - __u8 baSourceID[]; -} __attribute__ ((packed)); - -static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc) -{ - __u8 *raw = (__u8 *) desc; - return raw[desc->bLength - 1]; -} - -/* 4.3.2.5 Feature Unit Descriptor */ -struct uac_feature_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bUnitID; - __u8 bSourceID; - __u8 bControlSize; - __u8 bmaControls[0]; /* variable length */ -} __attribute__((packed)); - -static inline __u8 uac_feature_unit_iFeature(struct uac_feature_unit_descriptor *desc) -{ - __u8 *raw = (__u8 *) desc; - return raw[desc->bLength - 1]; -} - -/* 4.3.2.6 Processing Unit Descriptors */ -struct uac_processing_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bUnitID; - __u16 wProcessType; - __u8 bNrInPins; - __u8 baSourceID[]; -} __attribute__ ((packed)); - -static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_descriptor *desc) -{ - return desc->baSourceID[desc->bNrInPins]; -} - -static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - if (protocol == UAC_VERSION_1) - return (desc->baSourceID[desc->bNrInPins + 2] << 8) | - desc->baSourceID[desc->bNrInPins + 1]; - else - return (desc->baSourceID[desc->bNrInPins + 4] << 24) | - (desc->baSourceID[desc->bNrInPins + 3] << 16) | - (desc->baSourceID[desc->bNrInPins + 2] << 8) | - (desc->baSourceID[desc->bNrInPins + 1]); -} - -static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - return (protocol == UAC_VERSION_1) ? - desc->baSourceID[desc->bNrInPins + 3] : - desc->baSourceID[desc->bNrInPins + 5]; -} - -static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - return (protocol == UAC_VERSION_1) ? - desc->baSourceID[desc->bNrInPins + 4] : - desc->baSourceID[desc->bNrInPins + 6]; -} - -static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - return (protocol == UAC_VERSION_1) ? - &desc->baSourceID[desc->bNrInPins + 5] : - &desc->baSourceID[desc->bNrInPins + 7]; -} - -static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - return desc->baSourceID[desc->bNrInPins + control_size]; -} - -static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc, - int protocol) -{ - __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - return &desc->baSourceID[desc->bNrInPins + control_size + 1]; -} - -/* 4.5.2 Class-Specific AS Interface Descriptor */ -struct uac1_as_header_descriptor { - __u8 bLength; /* in bytes: 7 */ - __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ - __u8 bDescriptorSubtype; /* AS_GENERAL */ - __u8 bTerminalLink; /* Terminal ID of connected Terminal */ - __u8 bDelay; /* Delay introduced by the data path */ - __le16 wFormatTag; /* The Audio Data Format */ -} __attribute__ ((packed)); - -#define UAC_DT_AS_HEADER_SIZE 7 - -/* Formats - A.1.1 Audio Data Format Type I Codes */ -#define UAC_FORMAT_TYPE_I_UNDEFINED 0x0 -#define UAC_FORMAT_TYPE_I_PCM 0x1 -#define UAC_FORMAT_TYPE_I_PCM8 0x2 -#define UAC_FORMAT_TYPE_I_IEEE_FLOAT 0x3 -#define UAC_FORMAT_TYPE_I_ALAW 0x4 -#define UAC_FORMAT_TYPE_I_MULAW 0x5 - -struct uac_format_type_i_continuous_descriptor { - __u8 bLength; /* in bytes: 8 + (ns * 3) */ - __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ - __u8 bDescriptorSubtype; /* FORMAT_TYPE */ - __u8 bFormatType; /* FORMAT_TYPE_1 */ - __u8 bNrChannels; /* physical channels in the stream */ - __u8 bSubframeSize; /* */ - __u8 bBitResolution; - __u8 bSamFreqType; - __u8 tLowerSamFreq[3]; - __u8 tUpperSamFreq[3]; -} __attribute__ ((packed)); - -#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14 - -struct uac_format_type_i_discrete_descriptor { - __u8 bLength; /* in bytes: 8 + (ns * 3) */ - __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ - __u8 bDescriptorSubtype; /* FORMAT_TYPE */ - __u8 bFormatType; /* FORMAT_TYPE_1 */ - __u8 bNrChannels; /* physical channels in the stream */ - __u8 bSubframeSize; /* */ - __u8 bBitResolution; - __u8 bSamFreqType; - __u8 tSamFreq[][3]; -} __attribute__ ((packed)); - -#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n) \ -struct uac_format_type_i_discrete_descriptor_##n { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubtype; \ - __u8 bFormatType; \ - __u8 bNrChannels; \ - __u8 bSubframeSize; \ - __u8 bBitResolution; \ - __u8 bSamFreqType; \ - __u8 tSamFreq[n][3]; \ -} __attribute__ ((packed)) - -#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n) (8 + (n * 3)) - -struct uac_format_type_i_ext_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bFormatType; - __u8 bSubslotSize; - __u8 bBitResolution; - __u8 bHeaderLength; - __u8 bControlSize; - __u8 bSideBandProtocol; -} __attribute__((packed)); - -/* Formats - Audio Data Format Type I Codes */ - -#define UAC_FORMAT_TYPE_II_MPEG 0x1001 -#define UAC_FORMAT_TYPE_II_AC3 0x1002 - -struct uac_format_type_ii_discrete_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bFormatType; - __le16 wMaxBitRate; - __le16 wSamplesPerFrame; - __u8 bSamFreqType; - __u8 tSamFreq[][3]; -} __attribute__((packed)); - -struct uac_format_type_ii_ext_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubtype; - __u8 bFormatType; - __u16 wMaxBitRate; - __u16 wSamplesPerFrame; - __u8 bHeaderLength; - __u8 bSideBandProtocol; -} __attribute__((packed)); - -/* type III */ -#define UAC_FORMAT_TYPE_III_IEC1937_AC3 0x2001 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1 0x2002 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT 0x2003 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT 0x2004 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS 0x2005 -#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS 0x2006 - -/* Formats - A.2 Format Type Codes */ -#define UAC_FORMAT_TYPE_UNDEFINED 0x0 -#define UAC_FORMAT_TYPE_I 0x1 -#define UAC_FORMAT_TYPE_II 0x2 -#define UAC_FORMAT_TYPE_III 0x3 -#define UAC_EXT_FORMAT_TYPE_I 0x81 -#define UAC_EXT_FORMAT_TYPE_II 0x82 -#define UAC_EXT_FORMAT_TYPE_III 0x83 - -struct uac_iso_endpoint_descriptor { - __u8 bLength; /* in bytes: 7 */ - __u8 bDescriptorType; /* USB_DT_CS_ENDPOINT */ - __u8 bDescriptorSubtype; /* EP_GENERAL */ - __u8 bmAttributes; - __u8 bLockDelayUnits; - __le16 wLockDelay; -} __attribute__((packed)); -#define UAC_ISO_ENDPOINT_DESC_SIZE 7 - -#define UAC_EP_CS_ATTR_SAMPLE_RATE 0x01 -#define UAC_EP_CS_ATTR_PITCH_CONTROL 0x02 -#define UAC_EP_CS_ATTR_FILL_MAX 0x80 - -/* status word format (3.7.1.1) */ - -#define UAC1_STATUS_TYPE_ORIG_MASK 0x0f -#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0 -#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF 0x1 -#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP 0x2 - -#define UAC1_STATUS_TYPE_IRQ_PENDING (1 << 7) -#define UAC1_STATUS_TYPE_MEM_CHANGED (1 << 6) - -struct uac1_status_word { - __u8 bStatusType; - __u8 bOriginator; -} __attribute__((packed)); - -#ifdef __KERNEL__ struct usb_audio_control { struct list_head list; @@ -561,6 +41,4 @@ struct usb_audio_control_selector { struct usb_descriptor_header *desc; }; -#endif /* __KERNEL__ */ - #endif /* __LINUX_USB_AUDIO_H */ diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index d1d732c2838..9c210f2283d 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -29,887 +29,11 @@ * someone that the two other points are non-issues for that * particular descriptor type. */ - #ifndef __LINUX_USB_CH9_H #define __LINUX_USB_CH9_H -#include <linux/types.h> /* __u8 etc */ -#include <asm/byteorder.h> /* le16_to_cpu */ - -/*-------------------------------------------------------------------------*/ - -/* CONTROL REQUEST SUPPORT */ - -/* - * USB directions - * - * This bit flag is used in endpoint descriptors' bEndpointAddress field. - * It's also one of three fields in control requests bRequestType. - */ -#define USB_DIR_OUT 0 /* to device */ -#define USB_DIR_IN 0x80 /* to host */ - -/* - * USB types, the second of three bRequestType fields - */ -#define USB_TYPE_MASK (0x03 << 5) -#define USB_TYPE_STANDARD (0x00 << 5) -#define USB_TYPE_CLASS (0x01 << 5) -#define USB_TYPE_VENDOR (0x02 << 5) -#define USB_TYPE_RESERVED (0x03 << 5) - -/* - * USB recipients, the third of three bRequestType fields - */ -#define USB_RECIP_MASK 0x1f -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 -/* From Wireless USB 1.0 */ -#define USB_RECIP_PORT 0x04 -#define USB_RECIP_RPIPE 0x05 - -/* - * Standard requests, for the bRequest field of a SETUP packet. - * - * These are qualified by the bRequestType field, so that for example - * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved - * by a GET_STATUS request. - */ -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C -#define USB_REQ_SET_SEL 0x30 -#define USB_REQ_SET_ISOCH_DELAY 0x31 - -#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ -#define USB_REQ_GET_ENCRYPTION 0x0E -#define USB_REQ_RPIPE_ABORT 0x0E -#define USB_REQ_SET_HANDSHAKE 0x0F -#define USB_REQ_RPIPE_RESET 0x0F -#define USB_REQ_GET_HANDSHAKE 0x10 -#define USB_REQ_SET_CONNECTION 0x11 -#define USB_REQ_SET_SECURITY_DATA 0x12 -#define USB_REQ_GET_SECURITY_DATA 0x13 -#define USB_REQ_SET_WUSB_DATA 0x14 -#define USB_REQ_LOOPBACK_DATA_WRITE 0x15 -#define USB_REQ_LOOPBACK_DATA_READ 0x16 -#define USB_REQ_SET_INTERFACE_DS 0x17 - -/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command, - * used by hubs to put ports into a new L1 suspend state, except that it - * forgot to define its number ... - */ - -/* - * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and - * are read as a bit array returned by USB_REQ_GET_STATUS. (So there - * are at most sixteen features of each type.) Hubs may also support a - * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend. - */ -#define USB_DEVICE_SELF_POWERED 0 /* (read only) */ -#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ -#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ -#define USB_DEVICE_BATTERY 2 /* (wireless) */ -#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ -#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ -#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ -#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ -#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ - -/* - * Test Mode Selectors - * See USB 2.0 spec Table 9-7 - */ -#define TEST_J 1 -#define TEST_K 2 -#define TEST_SE0_NAK 3 -#define TEST_PACKET 4 -#define TEST_FORCE_EN 5 - -/* - * New Feature Selectors as added by USB 3.0 - * See USB 3.0 spec Table 9-6 - */ -#define USB_DEVICE_U1_ENABLE 48 /* dev may initiate U1 transition */ -#define USB_DEVICE_U2_ENABLE 49 /* dev may initiate U2 transition */ -#define USB_DEVICE_LTM_ENABLE 50 /* dev may send LTM */ -#define USB_INTRF_FUNC_SUSPEND 0 /* function suspend */ - -#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00 -/* - * Suspend Options, Table 9-7 USB 3.0 spec - */ -#define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0)) -#define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1)) - -#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ - -/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */ -#define USB_DEV_STAT_U1_ENABLED 2 /* transition into U1 state */ -#define USB_DEV_STAT_U2_ENABLED 3 /* transition into U2 state */ -#define USB_DEV_STAT_LTM_ENABLED 4 /* Latency tolerance messages */ - -/** - * struct usb_ctrlrequest - SETUP data for a USB device control request - * @bRequestType: matches the USB bmRequestType field - * @bRequest: matches the USB bRequest field - * @wValue: matches the USB wValue field (le16 byte order) - * @wIndex: matches the USB wIndex field (le16 byte order) - * @wLength: matches the USB wLength field (le16 byte order) - * - * This structure is used to send control requests to a USB device. It matches - * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the - * USB spec for a fuller description of the different fields, and what they are - * used for. - * - * Note that the driver for any interface can issue control requests. - * For most devices, interfaces don't coordinate with each other, so - * such requests may be made at any time. - */ -struct usb_ctrlrequest { - __u8 bRequestType; - __u8 bRequest; - __le16 wValue; - __le16 wIndex; - __le16 wLength; -} __attribute__ ((packed)); - -/*-------------------------------------------------------------------------*/ - -/* - * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or - * (rarely) accepted by SET_DESCRIPTOR. - * - * Note that all multi-byte values here are encoded in little endian - * byte order "on the wire". Within the kernel and when exposed - * through the Linux-USB APIs, they are not converted to cpu byte - * order; it is the responsibility of the client code to do this. - * The single exception is when device and configuration descriptors (but - * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD); - * in this case the fields are converted to host endianness by the kernel. - */ - -/* - * Descriptor types ... USB 2.0 spec table 9.5 - */ -#define USB_DT_DEVICE 0x01 -#define USB_DT_CONFIG 0x02 -#define USB_DT_STRING 0x03 -#define USB_DT_INTERFACE 0x04 -#define USB_DT_ENDPOINT 0x05 -#define USB_DT_DEVICE_QUALIFIER 0x06 -#define USB_DT_OTHER_SPEED_CONFIG 0x07 -#define USB_DT_INTERFACE_POWER 0x08 -/* these are from a minor usb 2.0 revision (ECN) */ -#define USB_DT_OTG 0x09 -#define USB_DT_DEBUG 0x0a -#define USB_DT_INTERFACE_ASSOCIATION 0x0b -/* these are from the Wireless USB spec */ -#define USB_DT_SECURITY 0x0c -#define USB_DT_KEY 0x0d -#define USB_DT_ENCRYPTION_TYPE 0x0e -#define USB_DT_BOS 0x0f -#define USB_DT_DEVICE_CAPABILITY 0x10 -#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 -#define USB_DT_WIRE_ADAPTER 0x21 -#define USB_DT_RPIPE 0x22 -#define USB_DT_CS_RADIO_CONTROL 0x23 -/* From the T10 UAS specification */ -#define USB_DT_PIPE_USAGE 0x24 -/* From the USB 3.0 spec */ -#define USB_DT_SS_ENDPOINT_COMP 0x30 - -/* Conventional codes for class-specific descriptors. The convention is - * defined in the USB "Common Class" Spec (3.11). Individual class specs - * are authoritative for their usage, not the "common class" writeup. - */ -#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE) -#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG) -#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING) -#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE) -#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT) - -/* All standard descriptors have these 2 fields at the beginning */ -struct usb_descriptor_header { - __u8 bLength; - __u8 bDescriptorType; -} __attribute__ ((packed)); - - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_DEVICE: Device descriptor */ -struct usb_device_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __le16 bcdUSB; - __u8 bDeviceClass; - __u8 bDeviceSubClass; - __u8 bDeviceProtocol; - __u8 bMaxPacketSize0; - __le16 idVendor; - __le16 idProduct; - __le16 bcdDevice; - __u8 iManufacturer; - __u8 iProduct; - __u8 iSerialNumber; - __u8 bNumConfigurations; -} __attribute__ ((packed)); - -#define USB_DT_DEVICE_SIZE 18 - - -/* - * Device and/or Interface Class codes - * as found in bDeviceClass or bInterfaceClass - * and defined by www.usb.org documents - */ -#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ -#define USB_CLASS_AUDIO 1 -#define USB_CLASS_COMM 2 -#define USB_CLASS_HID 3 -#define USB_CLASS_PHYSICAL 5 -#define USB_CLASS_STILL_IMAGE 6 -#define USB_CLASS_PRINTER 7 -#define USB_CLASS_MASS_STORAGE 8 -#define USB_CLASS_HUB 9 -#define USB_CLASS_CDC_DATA 0x0a -#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ -#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ -#define USB_CLASS_VIDEO 0x0e -#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 -#define USB_CLASS_MISC 0xef -#define USB_CLASS_APP_SPEC 0xfe -#define USB_CLASS_VENDOR_SPEC 0xff - -#define USB_SUBCLASS_VENDOR_SPEC 0xff - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_CONFIG: Configuration descriptor information. - * - * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the - * descriptor type is different. Highspeed-capable devices can look - * different depending on what speed they're currently running. Only - * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG - * descriptors. - */ -struct usb_config_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __le16 wTotalLength; - __u8 bNumInterfaces; - __u8 bConfigurationValue; - __u8 iConfiguration; - __u8 bmAttributes; - __u8 bMaxPower; -} __attribute__ ((packed)); - -#define USB_DT_CONFIG_SIZE 9 - -/* from config descriptor bmAttributes */ -#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ -#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ -#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ -#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_STRING: String descriptor */ -struct usb_string_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __le16 wData[1]; /* UTF-16LE encoded */ -} __attribute__ ((packed)); - -/* note that "string" zero is special, it holds language codes that - * the device supports, not Unicode characters. - */ - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_INTERFACE: Interface descriptor */ -struct usb_interface_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bInterfaceNumber; - __u8 bAlternateSetting; - __u8 bNumEndpoints; - __u8 bInterfaceClass; - __u8 bInterfaceSubClass; - __u8 bInterfaceProtocol; - __u8 iInterface; -} __attribute__ ((packed)); - -#define USB_DT_INTERFACE_SIZE 9 - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_ENDPOINT: Endpoint descriptor */ -struct usb_endpoint_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bEndpointAddress; - __u8 bmAttributes; - __le16 wMaxPacketSize; - __u8 bInterval; - - /* NOTE: these two are _only_ in audio endpoints. */ - /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ - __u8 bRefresh; - __u8 bSynchAddress; -} __attribute__ ((packed)); - -#define USB_DT_ENDPOINT_SIZE 7 -#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ - - -/* - * Endpoints - */ -#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ -#define USB_ENDPOINT_DIR_MASK 0x80 - -#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ -#define USB_ENDPOINT_XFER_CONTROL 0 -#define USB_ENDPOINT_XFER_ISOC 1 -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_XFER_INT 3 -#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 - -/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */ -#define USB_ENDPOINT_INTRTYPE 0x30 -#define USB_ENDPOINT_INTR_PERIODIC (0 << 4) -#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4) - -#define USB_ENDPOINT_SYNCTYPE 0x0c -#define USB_ENDPOINT_SYNC_NONE (0 << 2) -#define USB_ENDPOINT_SYNC_ASYNC (1 << 2) -#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << 2) -#define USB_ENDPOINT_SYNC_SYNC (3 << 2) - -#define USB_ENDPOINT_USAGE_MASK 0x30 -#define USB_ENDPOINT_USAGE_DATA 0x00 -#define USB_ENDPOINT_USAGE_FEEDBACK 0x10 -#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20 /* Implicit feedback Data endpoint */ - -/*-------------------------------------------------------------------------*/ - -/** - * usb_endpoint_num - get the endpoint's number - * @epd: endpoint to be checked - * - * Returns @epd's number: 0 to 15. - */ -static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) -{ - return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; -} - -/** - * usb_endpoint_type - get the endpoint's transfer type - * @epd: endpoint to be checked - * - * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according - * to @epd's transfer type. - */ -static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) -{ - return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; -} - -/** - * usb_endpoint_dir_in - check if the endpoint has IN direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type IN, otherwise it returns false. - */ -static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); -} - -/** - * usb_endpoint_dir_out - check if the endpoint has OUT direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type OUT, otherwise it returns false. - */ -static inline int usb_endpoint_dir_out( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); -} - -/** - * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type bulk, otherwise it returns false. - */ -static inline int usb_endpoint_xfer_bulk( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_BULK); -} - -/** - * usb_endpoint_xfer_control - check if the endpoint has control transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type control, otherwise it returns false. - */ -static inline int usb_endpoint_xfer_control( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL); -} - -/** - * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type interrupt, otherwise it returns - * false. - */ -static inline int usb_endpoint_xfer_int( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT); -} - -/** - * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type isochronous, otherwise it returns - * false. - */ -static inline int usb_endpoint_xfer_isoc( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_ISOC); -} - -/** - * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has bulk transfer type and IN direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_bulk_in( - const struct usb_endpoint_descriptor *epd) -{ - return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd); -} - -/** - * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has bulk transfer type and OUT direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_bulk_out( - const struct usb_endpoint_descriptor *epd) -{ - return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd); -} - -/** - * usb_endpoint_is_int_in - check if the endpoint is interrupt IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and IN direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_int_in( - const struct usb_endpoint_descriptor *epd) -{ - return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd); -} - -/** - * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and OUT direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_int_out( - const struct usb_endpoint_descriptor *epd) -{ - return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd); -} - -/** - * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has isochronous transfer type and IN direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_isoc_in( - const struct usb_endpoint_descriptor *epd) -{ - return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd); -} - -/** - * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has isochronous transfer type and OUT direction, - * otherwise it returns false. - */ -static inline int usb_endpoint_is_isoc_out( - const struct usb_endpoint_descriptor *epd) -{ - return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd); -} - -/** - * usb_endpoint_maxp - get endpoint's max packet size - * @epd: endpoint to be checked - * - * Returns @epd's max packet - */ -static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd) -{ - return __le16_to_cpu(epd->wMaxPacketSize); -} - -static inline int usb_endpoint_interrupt_type( - const struct usb_endpoint_descriptor *epd) -{ - return epd->bmAttributes & USB_ENDPOINT_INTRTYPE; -} - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ -struct usb_ss_ep_comp_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bMaxBurst; - __u8 bmAttributes; - __le16 wBytesPerInterval; -} __attribute__ ((packed)); - -#define USB_DT_SS_EP_COMP_SIZE 6 - -/* Bits 4:0 of bmAttributes if this is a bulk endpoint */ -static inline int -usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp) -{ - int max_streams; - - if (!comp) - return 0; - - max_streams = comp->bmAttributes & 0x1f; - - if (!max_streams) - return 0; - - max_streams = 1 << max_streams; - - return max_streams; -} - -/* Bits 1:0 of bmAttributes if this is an isoc endpoint */ -#define USB_SS_MULT(p) (1 + ((p) & 0x3)) - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ -struct usb_qualifier_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __le16 bcdUSB; - __u8 bDeviceClass; - __u8 bDeviceSubClass; - __u8 bDeviceProtocol; - __u8 bMaxPacketSize0; - __u8 bNumConfigurations; - __u8 bRESERVED; -} __attribute__ ((packed)); - - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_OTG (from OTG 1.0a supplement) */ -struct usb_otg_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bmAttributes; /* support for HNP, SRP, etc */ -} __attribute__ ((packed)); - -/* from usb_otg_descriptor.bmAttributes */ -#define USB_OTG_SRP (1 << 0) -#define USB_OTG_HNP (1 << 1) /* swap host/device roles */ - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */ -struct usb_debug_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - /* bulk endpoints with 8 byte maxpacket */ - __u8 bDebugInEndpoint; - __u8 bDebugOutEndpoint; -} __attribute__((packed)); - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */ -struct usb_interface_assoc_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bFirstInterface; - __u8 bInterfaceCount; - __u8 bFunctionClass; - __u8 bFunctionSubClass; - __u8 bFunctionProtocol; - __u8 iFunction; -} __attribute__ ((packed)); - - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_SECURITY: group of wireless security descriptors, including - * encryption types available for setting up a CC/association. - */ -struct usb_security_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __le16 wTotalLength; - __u8 bNumEncryptionTypes; -} __attribute__((packed)); - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys - * may be retrieved. - */ -struct usb_key_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 tTKID[3]; - __u8 bReserved; - __u8 bKeyData[0]; -} __attribute__((packed)); - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */ -struct usb_encryption_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bEncryptionType; -#define USB_ENC_TYPE_UNSECURE 0 -#define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */ -#define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */ -#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */ - __u8 bEncryptionValue; /* use in SET_ENCRYPTION */ - __u8 bAuthKeyIndex; -} __attribute__((packed)); - - -/*-------------------------------------------------------------------------*/ - -/* USB_DT_BOS: group of device-level capabilities */ -struct usb_bos_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __le16 wTotalLength; - __u8 bNumDeviceCaps; -} __attribute__((packed)); - -#define USB_DT_BOS_SIZE 5 -/*-------------------------------------------------------------------------*/ - -/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */ -struct usb_dev_cap_header { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDevCapabilityType; -} __attribute__((packed)); - -#define USB_CAP_TYPE_WIRELESS_USB 1 - -struct usb_wireless_cap_descriptor { /* Ultra Wide Band */ - __u8 bLength; - __u8 bDescriptorType; - __u8 bDevCapabilityType; - - __u8 bmAttributes; -#define USB_WIRELESS_P2P_DRD (1 << 1) -#define USB_WIRELESS_BEACON_MASK (3 << 2) -#define USB_WIRELESS_BEACON_SELF (1 << 2) -#define USB_WIRELESS_BEACON_DIRECTED (2 << 2) -#define USB_WIRELESS_BEACON_NONE (3 << 2) - __le16 wPHYRates; /* bit rates, Mbps */ -#define USB_WIRELESS_PHY_53 (1 << 0) /* always set */ -#define USB_WIRELESS_PHY_80 (1 << 1) -#define USB_WIRELESS_PHY_107 (1 << 2) /* always set */ -#define USB_WIRELESS_PHY_160 (1 << 3) -#define USB_WIRELESS_PHY_200 (1 << 4) /* always set */ -#define USB_WIRELESS_PHY_320 (1 << 5) -#define USB_WIRELESS_PHY_400 (1 << 6) -#define USB_WIRELESS_PHY_480 (1 << 7) - __u8 bmTFITXPowerInfo; /* TFI power levels */ - __u8 bmFFITXPowerInfo; /* FFI power levels */ - __le16 bmBandGroup; - __u8 bReserved; -} __attribute__((packed)); - -/* USB 2.0 Extension descriptor */ -#define USB_CAP_TYPE_EXT 2 - -struct usb_ext_cap_descriptor { /* Link Power Management */ - __u8 bLength; - __u8 bDescriptorType; - __u8 bDevCapabilityType; - __le32 bmAttributes; -#define USB_LPM_SUPPORT (1 << 1) /* supports LPM */ -#define USB_BESL_SUPPORT (1 << 2) /* supports BESL */ -#define USB_BESL_BASELINE_VALID (1 << 3) /* Baseline BESL valid*/ -#define USB_BESL_DEEP_VALID (1 << 4) /* Deep BESL valid */ -#define USB_GET_BESL_BASELINE(p) (((p) & (0xf << 8)) >> 8) -#define USB_GET_BESL_DEEP(p) (((p) & (0xf << 12)) >> 12) -} __attribute__((packed)); - -#define USB_DT_USB_EXT_CAP_SIZE 7 - -/* - * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB - * specific device level capabilities - */ -#define USB_SS_CAP_TYPE 3 -struct usb_ss_cap_descriptor { /* Link Power Management */ - __u8 bLength; - __u8 bDescriptorType; - __u8 bDevCapabilityType; - __u8 bmAttributes; -#define USB_LTM_SUPPORT (1 << 1) /* supports LTM */ - __le16 wSpeedSupported; -#define USB_LOW_SPEED_OPERATION (1) /* Low speed operation */ -#define USB_FULL_SPEED_OPERATION (1 << 1) /* Full speed operation */ -#define USB_HIGH_SPEED_OPERATION (1 << 2) /* High speed operation */ -#define USB_5GBPS_OPERATION (1 << 3) /* Operation at 5Gbps */ - __u8 bFunctionalitySupport; - __u8 bU1devExitLat; - __le16 bU2DevExitLat; -} __attribute__((packed)); - -#define USB_DT_USB_SS_CAP_SIZE 10 - -/* - * Container ID Capability descriptor: Defines the instance unique ID used to - * identify the instance across all operating modes - */ -#define CONTAINER_ID_TYPE 4 -struct usb_ss_container_id_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDevCapabilityType; - __u8 bReserved; - __u8 ContainerID[16]; /* 128-bit number */ -} __attribute__((packed)); - -#define USB_DT_USB_SS_CONTN_ID_SIZE 20 -/*-------------------------------------------------------------------------*/ - -/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with - * each endpoint descriptor for a wireless device - */ -struct usb_wireless_ep_comp_descriptor { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bMaxBurst; - __u8 bMaxSequence; - __le16 wMaxStreamDelay; - __le16 wOverTheAirPacketSize; - __u8 bOverTheAirInterval; - __u8 bmCompAttributes; -#define USB_ENDPOINT_SWITCH_MASK 0x03 /* in bmCompAttributes */ -#define USB_ENDPOINT_SWITCH_NO 0 -#define USB_ENDPOINT_SWITCH_SWITCH 1 -#define USB_ENDPOINT_SWITCH_SCALE 2 -} __attribute__((packed)); - -/*-------------------------------------------------------------------------*/ - -/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless - * host and a device for connection set up, mutual authentication, and - * exchanging short lived session keys. The handshake depends on a CC. - */ -struct usb_handshake { - __u8 bMessageNumber; - __u8 bStatus; - __u8 tTKID[3]; - __u8 bReserved; - __u8 CDID[16]; - __u8 nonce[16]; - __u8 MIC[8]; -} __attribute__((packed)); - -/*-------------------------------------------------------------------------*/ - -/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC). - * A CC may also be set up using non-wireless secure channels (including - * wired USB!), and some devices may support CCs with multiple hosts. - */ -struct usb_connection_context { - __u8 CHID[16]; /* persistent host id */ - __u8 CDID[16]; /* device id (unique w/in host context) */ - __u8 CK[16]; /* connection key */ -} __attribute__((packed)); - -/*-------------------------------------------------------------------------*/ +#include <uapi/linux/usb/ch9.h> -/* USB 2.0 defines three speeds, here's how Linux identifies them */ - -enum usb_device_speed { - USB_SPEED_UNKNOWN = 0, /* enumerating */ - USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ - USB_SPEED_HIGH, /* usb 2.0 */ - USB_SPEED_WIRELESS, /* wireless (usb 2.5) */ - USB_SPEED_SUPER, /* usb 3.0 */ -}; - -#ifdef __KERNEL__ /** * usb_speed_string() - Returns human readable-name of the speed. @@ -919,86 +43,4 @@ enum usb_device_speed { */ extern const char *usb_speed_string(enum usb_device_speed speed); -#endif - -enum usb_device_state { - /* NOTATTACHED isn't in the USB spec, and this state acts - * the same as ATTACHED ... but it's clearer this way. - */ - USB_STATE_NOTATTACHED = 0, - - /* chapter 9 and authentication (wireless) device states */ - USB_STATE_ATTACHED, - USB_STATE_POWERED, /* wired */ - USB_STATE_RECONNECTING, /* auth */ - USB_STATE_UNAUTHENTICATED, /* auth */ - USB_STATE_DEFAULT, /* limited function */ - USB_STATE_ADDRESS, - USB_STATE_CONFIGURED, /* most functions */ - - USB_STATE_SUSPENDED - - /* NOTE: there are actually four different SUSPENDED - * states, returning to POWERED, DEFAULT, ADDRESS, or - * CONFIGURED respectively when SOF tokens flow again. - * At this level there's no difference between L1 and L2 - * suspend states. (L2 being original USB 1.1 suspend.) - */ -}; - -enum usb3_link_state { - USB3_LPM_U0 = 0, - USB3_LPM_U1, - USB3_LPM_U2, - USB3_LPM_U3 -}; - -/* - * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1. - * 0xff means the parent hub will accept transitions to U1, but will not - * initiate a transition. - * - * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to - * U1 after that many microseconds. Timeouts of 0x80 to 0xFE are reserved - * values. - * - * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2. - * 0xff means the parent hub will accept transitions to U2, but will not - * initiate a transition. - * - * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to - * U2 after N*256 microseconds. Therefore a U2 timeout value of 0x1 means a U2 - * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means - * 65.024ms. - */ -#define USB3_LPM_DISABLED 0x0 -#define USB3_LPM_U1_MAX_TIMEOUT 0x7F -#define USB3_LPM_U2_MAX_TIMEOUT 0xFE -#define USB3_LPM_DEVICE_INITIATED 0xFF - -struct usb_set_sel_req { - __u8 u1_sel; - __u8 u1_pel; - __le16 u2_sel; - __le16 u2_pel; -} __attribute__ ((packed)); - -/* - * The Set System Exit Latency control transfer provides one byte each for - * U1 SEL and U1 PEL, so the max exit latency is 0xFF. U2 SEL and U2 PEL each - * are two bytes long. - */ -#define USB3_LPM_MAX_U1_SEL_PEL 0xFF -#define USB3_LPM_MAX_U2_SEL_PEL 0xFFFF - -/*-------------------------------------------------------------------------*/ - -/* - * As per USB compliance update, a device that is actively drawing - * more than 100mA from USB must report itself as bus-powered in - * the GetStatus(DEVICE) call. - * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34 - */ -#define USB_SELF_POWER_VBUS_MAX_DRAW 100 - #endif /* __LINUX_USB_CH9_H */ diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h index a843d085136..65d0a88dbc6 100644 --- a/include/linux/usb/functionfs.h +++ b/include/linux/usb/functionfs.h @@ -1,171 +1,8 @@ #ifndef __LINUX_FUNCTIONFS_H__ #define __LINUX_FUNCTIONFS_H__ 1 +#include <uapi/linux/usb/functionfs.h> -#include <linux/types.h> -#include <linux/ioctl.h> - -#include <linux/usb/ch9.h> - - -enum { - FUNCTIONFS_DESCRIPTORS_MAGIC = 1, - FUNCTIONFS_STRINGS_MAGIC = 2 -}; - - -#ifndef __KERNEL__ - -/* Descriptor of an non-audio endpoint */ -struct usb_endpoint_descriptor_no_audio { - __u8 bLength; - __u8 bDescriptorType; - - __u8 bEndpointAddress; - __u8 bmAttributes; - __le16 wMaxPacketSize; - __u8 bInterval; -} __attribute__((packed)); - - -/* - * All numbers must be in little endian order. - */ - -struct usb_functionfs_descs_head { - __le32 magic; - __le32 length; - __le32 fs_count; - __le32 hs_count; -} __attribute__((packed)); - -/* - * Descriptors format: - * - * | off | name | type | description | - * |-----+-----------+--------------+--------------------------------------| - * | 0 | magic | LE32 | FUNCTIONFS_{FS,HS}_DESCRIPTORS_MAGIC | - * | 4 | length | LE32 | length of the whole data chunk | - * | 8 | fs_count | LE32 | number of full-speed descriptors | - * | 12 | hs_count | LE32 | number of high-speed descriptors | - * | 16 | fs_descrs | Descriptor[] | list of full-speed descriptors | - * | | hs_descrs | Descriptor[] | list of high-speed descriptors | - * - * descs are just valid USB descriptors and have the following format: - * - * | off | name | type | description | - * |-----+-----------------+------+--------------------------| - * | 0 | bLength | U8 | length of the descriptor | - * | 1 | bDescriptorType | U8 | descriptor type | - * | 2 | payload | | descriptor's payload | - */ - -struct usb_functionfs_strings_head { - __le32 magic; - __le32 length; - __le32 str_count; - __le32 lang_count; -} __attribute__((packed)); - -/* - * Strings format: - * - * | off | name | type | description | - * |-----+------------+-----------------------+----------------------------| - * | 0 | magic | LE32 | FUNCTIONFS_STRINGS_MAGIC | - * | 4 | length | LE32 | length of the data chunk | - * | 8 | str_count | LE32 | number of strings | - * | 12 | lang_count | LE32 | number of languages | - * | 16 | stringtab | StringTab[lang_count] | table of strings per lang | - * - * For each language there is one stringtab entry (ie. there are lang_count - * stringtab entires). Each StringTab has following format: - * - * | off | name | type | description | - * |-----+---------+-------------------+------------------------------------| - * | 0 | lang | LE16 | language code | - * | 2 | strings | String[str_count] | array of strings in given language | - * - * For each string there is one strings entry (ie. there are str_count - * string entries). Each String is a NUL terminated string encoded in - * UTF-8. - */ - -#endif - - -/* - * Events are delivered on the ep0 file descriptor, when the user mode driver - * reads from this file descriptor after writing the descriptors. Don't - * stop polling this descriptor. - */ - -enum usb_functionfs_event_type { - FUNCTIONFS_BIND, - FUNCTIONFS_UNBIND, - - FUNCTIONFS_ENABLE, - FUNCTIONFS_DISABLE, - - FUNCTIONFS_SETUP, - - FUNCTIONFS_SUSPEND, - FUNCTIONFS_RESUME -}; - -/* NOTE: this structure must stay the same size and layout on - * both 32-bit and 64-bit kernels. - */ -struct usb_functionfs_event { - union { - /* SETUP: packet; DATA phase i/o precedes next event - *(setup.bmRequestType & USB_DIR_IN) flags direction */ - struct usb_ctrlrequest setup; - } __attribute__((packed)) u; - - /* enum usb_functionfs_event_type */ - __u8 type; - __u8 _pad[3]; -} __attribute__((packed)); - - -/* Endpoint ioctls */ -/* The same as in gadgetfs */ - -/* IN transfers may be reported to the gadget driver as complete - * when the fifo is loaded, before the host reads the data; - * OUT transfers may be reported to the host's "client" driver as - * complete when they're sitting in the FIFO unread. - * THIS returns how many bytes are "unclaimed" in the endpoint fifo - * (needed for precise fault handling, when the hardware allows it) - */ -#define FUNCTIONFS_FIFO_STATUS _IO('g', 1) - -/* discards any unclaimed data in the fifo. */ -#define FUNCTIONFS_FIFO_FLUSH _IO('g', 2) - -/* resets endpoint halt+toggle; used to implement set_interface. - * some hardware (like pxa2xx) can't support this. - */ -#define FUNCTIONFS_CLEAR_HALT _IO('g', 3) - -/* Specific for functionfs */ - -/* - * Returns reverse mapping of an interface. Called on EP0. If there - * is no such interface returns -EDOM. If function is not active - * returns -ENODEV. - */ -#define FUNCTIONFS_INTERFACE_REVMAP _IO('g', 128) - -/* - * Returns real bEndpointAddress of an endpoint. If function is not - * active returns -ENODEV. - */ -#define FUNCTIONFS_ENDPOINT_REVMAP _IO('g', 129) - - -#ifdef __KERNEL__ struct ffs_data; struct usb_composite_dev; @@ -197,5 +34,3 @@ static void functionfs_release_dev_callback(struct ffs_data *ffs_data) #endif - -#endif diff --git a/include/linux/wimax/Kbuild b/include/linux/wimax/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/linux/wimax/Kbuild +++ /dev/null diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/mtd/Kbuild +++ /dev/null diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1b498908224..7d5b6000378 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request { const u8 *ie; size_t ie_len; u16 reason_code; + bool local_state_change; }; /** @@ -2651,6 +2652,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); /** + * ieee80211_get_mesh_hdrlen - get mesh extension header length + * @meshhdr: the mesh extension header, only the flags field + * (first byte) will be accessed + * Returns the length of the extension header, which is always at + * least 6 bytes and at most 18 if address 5 and 6 are present. + */ +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); + +/** * DOC: Data path helpers * * In addition to generic utilities, cfg80211 also offers diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 6f0ba01afe7..63445ede48b 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1351,7 +1351,7 @@ struct xfrm6_tunnel { }; extern void xfrm_init(void); -extern void xfrm4_init(int rt_hash_size); +extern void xfrm4_init(void); extern int xfrm_state_init(struct net *net); extern void xfrm_state_fini(struct net *net); extern void xfrm4_state_init(void); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 88fae8d2015..55367b04dc9 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -135,6 +135,8 @@ struct scsi_device { * because we did a bus reset. */ unsigned use_10_for_rw:1; /* first try 10-byte read / write */ unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */ + unsigned no_report_opcodes:1; /* no REPORT SUPPORTED OPERATION CODES */ + unsigned no_write_same:1; /* no WRITE SAME command */ unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */ unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */ unsigned skip_vpd_pages:1; /* do not read VPD pages */ @@ -362,6 +364,8 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries, struct scsi_sense_hdr *sshdr); extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf, int buf_len); +extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, + unsigned int len, unsigned char opcode); extern int scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state); extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type, diff --git a/include/sound/core.h b/include/sound/core.h index bc056687f64..93896ad1fcd 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -132,6 +132,7 @@ struct snd_card { int shutdown; /* this card is going down */ int free_on_last_close; /* free in context of file_release */ wait_queue_head_t shutdown_sleep; + atomic_t refcount; /* refcount for disconnection */ struct device *dev; /* device assigned to this card */ struct device *card_dev; /* cardX object for sysfs */ @@ -189,6 +190,7 @@ struct snd_minor { const struct file_operations *f_ops; /* file operations */ void *private_data; /* private data for f_ops->open */ struct device *dev; /* device for sysfs */ + struct snd_card *card_ptr; /* assigned card instance */ }; /* return a device pointer linked to each sound device as a parent */ @@ -295,6 +297,7 @@ int snd_card_info_done(void); int snd_component_add(struct snd_card *card, const char *component); int snd_card_file_add(struct snd_card *card, struct file *file); int snd_card_file_remove(struct snd_card *card, struct file *file); +void snd_card_unref(struct snd_card *card); #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index 15ba03bdd7c..d06b6da5c1e 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h @@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd, DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); +TRACE_EVENT(xen_mmu_flush_tlb_all, + TP_PROTO(int x), + TP_ARGS(x), + TP_STRUCT__entry(__array(char, x, 0)), + TP_fast_assign((void)x), + TP_printk("%s", "") + ); + TRACE_EVENT(xen_mmu_flush_tlb, TP_PROTO(int x), TP_ARGS(x), diff --git a/include/uapi/asm-generic/kvm_para.h b/include/uapi/asm-generic/kvm_para.h index e69de29bb2d..486f0af73c3 100644 --- a/include/uapi/asm-generic/kvm_para.h +++ b/include/uapi/asm-generic/kvm_para.h @@ -0,0 +1,4 @@ +/* + * There isn't anything here, but the file must not be empty or patch + * will delete it. + */ diff --git a/include/uapi/linux/dvb/Kbuild b/include/uapi/linux/dvb/Kbuild index aafaa5aa54d..d40942cfc62 100644 --- a/include/uapi/linux/dvb/Kbuild +++ b/include/uapi/linux/dvb/Kbuild @@ -1 +1,9 @@ # UAPI Header export list +header-y += audio.h +header-y += ca.h +header-y += dmx.h +header-y += frontend.h +header-y += net.h +header-y += osd.h +header-y += version.h +header-y += video.h diff --git a/include/linux/dvb/audio.h b/include/uapi/linux/dvb/audio.h index d47bccd604e..d47bccd604e 100644 --- a/include/linux/dvb/audio.h +++ b/include/uapi/linux/dvb/audio.h diff --git a/include/linux/dvb/ca.h b/include/uapi/linux/dvb/ca.h index c18537f3e44..c18537f3e44 100644 --- a/include/linux/dvb/ca.h +++ b/include/uapi/linux/dvb/ca.h diff --git a/include/uapi/linux/dvb/dmx.h b/include/uapi/linux/dvb/dmx.h new file mode 100644 index 00000000000..b2a9ad8cafd --- /dev/null +++ b/include/uapi/linux/dvb/dmx.h @@ -0,0 +1,155 @@ +/* + * dmx.h + * + * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de> + * & Ralph Metzler <ralph@convergence.de> + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _UAPI_DVBDMX_H_ +#define _UAPI_DVBDMX_H_ + +#include <linux/types.h> +#ifndef __KERNEL__ +#include <time.h> +#endif + + +#define DMX_FILTER_SIZE 16 + +typedef enum +{ + DMX_OUT_DECODER, /* Streaming directly to decoder. */ + DMX_OUT_TAP, /* Output going to a memory buffer */ + /* (to be retrieved via the read command).*/ + DMX_OUT_TS_TAP, /* Output multiplexed into a new TS */ + /* (to be retrieved by reading from the */ + /* logical DVR device). */ + DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */ +} dmx_output_t; + + +typedef enum +{ + DMX_IN_FRONTEND, /* Input from a front-end device. */ + DMX_IN_DVR /* Input from the logical DVR device. */ +} dmx_input_t; + + +typedef enum +{ + DMX_PES_AUDIO0, + DMX_PES_VIDEO0, + DMX_PES_TELETEXT0, + DMX_PES_SUBTITLE0, + DMX_PES_PCR0, + + DMX_PES_AUDIO1, + DMX_PES_VIDEO1, + DMX_PES_TELETEXT1, + DMX_PES_SUBTITLE1, + DMX_PES_PCR1, + + DMX_PES_AUDIO2, + DMX_PES_VIDEO2, + DMX_PES_TELETEXT2, + DMX_PES_SUBTITLE2, + DMX_PES_PCR2, + + DMX_PES_AUDIO3, + DMX_PES_VIDEO3, + DMX_PES_TELETEXT3, + DMX_PES_SUBTITLE3, + DMX_PES_PCR3, + + DMX_PES_OTHER +} dmx_pes_type_t; + +#define DMX_PES_AUDIO DMX_PES_AUDIO0 +#define DMX_PES_VIDEO DMX_PES_VIDEO0 +#define DMX_PES_TELETEXT DMX_PES_TELETEXT0 +#define DMX_PES_SUBTITLE DMX_PES_SUBTITLE0 +#define DMX_PES_PCR DMX_PES_PCR0 + + +typedef struct dmx_filter +{ + __u8 filter[DMX_FILTER_SIZE]; + __u8 mask[DMX_FILTER_SIZE]; + __u8 mode[DMX_FILTER_SIZE]; +} dmx_filter_t; + + +struct dmx_sct_filter_params +{ + __u16 pid; + dmx_filter_t filter; + __u32 timeout; + __u32 flags; +#define DMX_CHECK_CRC 1 +#define DMX_ONESHOT 2 +#define DMX_IMMEDIATE_START 4 +#define DMX_KERNEL_CLIENT 0x8000 +}; + + +struct dmx_pes_filter_params +{ + __u16 pid; + dmx_input_t input; + dmx_output_t output; + dmx_pes_type_t pes_type; + __u32 flags; +}; + +typedef struct dmx_caps { + __u32 caps; + int num_decoders; +} dmx_caps_t; + +typedef enum { + DMX_SOURCE_FRONT0 = 0, + DMX_SOURCE_FRONT1, + DMX_SOURCE_FRONT2, + DMX_SOURCE_FRONT3, + DMX_SOURCE_DVR0 = 16, + DMX_SOURCE_DVR1, + DMX_SOURCE_DVR2, + DMX_SOURCE_DVR3 +} dmx_source_t; + +struct dmx_stc { + unsigned int num; /* input : which STC? 0..N */ + unsigned int base; /* output: divisor for stc to get 90 kHz clock */ + __u64 stc; /* output: stc in 'base'*90 kHz units */ +}; + + +#define DMX_START _IO('o', 41) +#define DMX_STOP _IO('o', 42) +#define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params) +#define DMX_SET_PES_FILTER _IOW('o', 44, struct dmx_pes_filter_params) +#define DMX_SET_BUFFER_SIZE _IO('o', 45) +#define DMX_GET_PES_PIDS _IOR('o', 47, __u16[5]) +#define DMX_GET_CAPS _IOR('o', 48, dmx_caps_t) +#define DMX_SET_SOURCE _IOW('o', 49, dmx_source_t) +#define DMX_GET_STC _IOWR('o', 50, struct dmx_stc) +#define DMX_ADD_PID _IOW('o', 51, __u16) +#define DMX_REMOVE_PID _IOW('o', 52, __u16) + +#endif /* _UAPI_DVBDMX_H_ */ diff --git a/include/linux/dvb/frontend.h b/include/uapi/linux/dvb/frontend.h index c12d452cb40..c12d452cb40 100644 --- a/include/linux/dvb/frontend.h +++ b/include/uapi/linux/dvb/frontend.h diff --git a/include/linux/dvb/net.h b/include/uapi/linux/dvb/net.h index f451e7eb0b0..f451e7eb0b0 100644 --- a/include/linux/dvb/net.h +++ b/include/uapi/linux/dvb/net.h diff --git a/include/linux/dvb/osd.h b/include/uapi/linux/dvb/osd.h index 880e6843583..880e6843583 100644 --- a/include/linux/dvb/osd.h +++ b/include/uapi/linux/dvb/osd.h diff --git a/include/linux/dvb/version.h b/include/uapi/linux/dvb/version.h index 827cce7e33e..827cce7e33e 100644 --- a/include/linux/dvb/version.h +++ b/include/uapi/linux/dvb/version.h diff --git a/include/uapi/linux/dvb/video.h b/include/uapi/linux/dvb/video.h new file mode 100644 index 00000000000..d3d14a59d2d --- /dev/null +++ b/include/uapi/linux/dvb/video.h @@ -0,0 +1,274 @@ +/* + * video.h + * + * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de> + * & Ralph Metzler <ralph@convergence.de> + * for convergence integrated media GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef _UAPI_DVBVIDEO_H_ +#define _UAPI_DVBVIDEO_H_ + +#include <linux/types.h> +#ifndef __KERNEL__ +#include <stdint.h> +#include <time.h> +#endif + +typedef enum { + VIDEO_FORMAT_4_3, /* Select 4:3 format */ + VIDEO_FORMAT_16_9, /* Select 16:9 format. */ + VIDEO_FORMAT_221_1 /* 2.21:1 */ +} video_format_t; + + +typedef enum { + VIDEO_SYSTEM_PAL, + VIDEO_SYSTEM_NTSC, + VIDEO_SYSTEM_PALN, + VIDEO_SYSTEM_PALNc, + VIDEO_SYSTEM_PALM, + VIDEO_SYSTEM_NTSC60, + VIDEO_SYSTEM_PAL60, + VIDEO_SYSTEM_PALM60 +} video_system_t; + + +typedef enum { + VIDEO_PAN_SCAN, /* use pan and scan format */ + VIDEO_LETTER_BOX, /* use letterbox format */ + VIDEO_CENTER_CUT_OUT /* use center cut out format */ +} video_displayformat_t; + +typedef struct { + int w; + int h; + video_format_t aspect_ratio; +} video_size_t; + +typedef enum { + VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */ + VIDEO_SOURCE_MEMORY /* If this source is selected, the stream + comes from the user through the write + system call */ +} video_stream_source_t; + + +typedef enum { + VIDEO_STOPPED, /* Video is stopped */ + VIDEO_PLAYING, /* Video is currently playing */ + VIDEO_FREEZED /* Video is freezed */ +} video_play_state_t; + + +/* Decoder commands */ +#define VIDEO_CMD_PLAY (0) +#define VIDEO_CMD_STOP (1) +#define VIDEO_CMD_FREEZE (2) +#define VIDEO_CMD_CONTINUE (3) + +/* Flags for VIDEO_CMD_FREEZE */ +#define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0) + +/* Flags for VIDEO_CMD_STOP */ +#define VIDEO_CMD_STOP_TO_BLACK (1 << 0) +#define VIDEO_CMD_STOP_IMMEDIATELY (1 << 1) + +/* Play input formats: */ +/* The decoder has no special format requirements */ +#define VIDEO_PLAY_FMT_NONE (0) +/* The decoder requires full GOPs */ +#define VIDEO_PLAY_FMT_GOP (1) + +/* The structure must be zeroed before use by the application + This ensures it can be extended safely in the future. */ +struct video_command { + __u32 cmd; + __u32 flags; + union { + struct { + __u64 pts; + } stop; + + struct { + /* 0 or 1000 specifies normal speed, + 1 specifies forward single stepping, + -1 specifies backward single stepping, + >1: playback at speed/1000 of the normal speed, + <-1: reverse playback at (-speed/1000) of the normal speed. */ + __s32 speed; + __u32 format; + } play; + + struct { + __u32 data[16]; + } raw; + }; +}; + +/* FIELD_UNKNOWN can be used if the hardware does not know whether + the Vsync is for an odd, even or progressive (i.e. non-interlaced) + field. */ +#define VIDEO_VSYNC_FIELD_UNKNOWN (0) +#define VIDEO_VSYNC_FIELD_ODD (1) +#define VIDEO_VSYNC_FIELD_EVEN (2) +#define VIDEO_VSYNC_FIELD_PROGRESSIVE (3) + +struct video_event { + __s32 type; +#define VIDEO_EVENT_SIZE_CHANGED 1 +#define VIDEO_EVENT_FRAME_RATE_CHANGED 2 +#define VIDEO_EVENT_DECODER_STOPPED 3 +#define VIDEO_EVENT_VSYNC 4 + __kernel_time_t timestamp; + union { + video_size_t size; + unsigned int frame_rate; /* in frames per 1000sec */ + unsigned char vsync_field; /* unknown/odd/even/progressive */ + } u; +}; + + +struct video_status { + int video_blank; /* blank video on freeze? */ + video_play_state_t play_state; /* current state of playback */ + video_stream_source_t stream_source; /* current source (demux/memory) */ + video_format_t video_format; /* current aspect ratio of stream*/ + video_displayformat_t display_format;/* selected cropping mode */ +}; + + +struct video_still_picture { + char __user *iFrame; /* pointer to a single iframe in memory */ + __s32 size; +}; + + +typedef +struct video_highlight { + int active; /* 1=show highlight, 0=hide highlight */ + __u8 contrast1; /* 7- 4 Pattern pixel contrast */ + /* 3- 0 Background pixel contrast */ + __u8 contrast2; /* 7- 4 Emphasis pixel-2 contrast */ + /* 3- 0 Emphasis pixel-1 contrast */ + __u8 color1; /* 7- 4 Pattern pixel color */ + /* 3- 0 Background pixel color */ + __u8 color2; /* 7- 4 Emphasis pixel-2 color */ + /* 3- 0 Emphasis pixel-1 color */ + __u32 ypos; /* 23-22 auto action mode */ + /* 21-12 start y */ + /* 9- 0 end y */ + __u32 xpos; /* 23-22 button color number */ + /* 21-12 start x */ + /* 9- 0 end x */ +} video_highlight_t; + + +typedef struct video_spu { + int active; + int stream_id; +} video_spu_t; + + +typedef struct video_spu_palette { /* SPU Palette information */ + int length; + __u8 __user *palette; +} video_spu_palette_t; + + +typedef struct video_navi_pack { + int length; /* 0 ... 1024 */ + __u8 data[1024]; +} video_navi_pack_t; + + +typedef __u16 video_attributes_t; +/* bits: descr. */ +/* 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */ +/* 13-12 TV system (0=525/60, 1=625/50) */ +/* 11-10 Aspect ratio (0=4:3, 3=16:9) */ +/* 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */ +/* 7 line 21-1 data present in GOP (1=yes, 0=no) */ +/* 6 line 21-2 data present in GOP (1=yes, 0=no) */ +/* 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */ +/* 2 source letterboxed (1=yes, 0=no) */ +/* 0 film/camera mode (0=camera, 1=film (625/50 only)) */ + + +/* bit definitions for capabilities: */ +/* can the hardware decode MPEG1 and/or MPEG2? */ +#define VIDEO_CAP_MPEG1 1 +#define VIDEO_CAP_MPEG2 2 +/* can you send a system and/or program stream to video device? + (you still have to open the video and the audio device but only + send the stream to the video device) */ +#define VIDEO_CAP_SYS 4 +#define VIDEO_CAP_PROG 8 +/* can the driver also handle SPU, NAVI and CSS encoded data? + (CSS API is not present yet) */ +#define VIDEO_CAP_SPU 16 +#define VIDEO_CAP_NAVI 32 +#define VIDEO_CAP_CSS 64 + + +#define VIDEO_STOP _IO('o', 21) +#define VIDEO_PLAY _IO('o', 22) +#define VIDEO_FREEZE _IO('o', 23) +#define VIDEO_CONTINUE _IO('o', 24) +#define VIDEO_SELECT_SOURCE _IO('o', 25) +#define VIDEO_SET_BLANK _IO('o', 26) +#define VIDEO_GET_STATUS _IOR('o', 27, struct video_status) +#define VIDEO_GET_EVENT _IOR('o', 28, struct video_event) +#define VIDEO_SET_DISPLAY_FORMAT _IO('o', 29) +#define VIDEO_STILLPICTURE _IOW('o', 30, struct video_still_picture) +#define VIDEO_FAST_FORWARD _IO('o', 31) +#define VIDEO_SLOWMOTION _IO('o', 32) +#define VIDEO_GET_CAPABILITIES _IOR('o', 33, unsigned int) +#define VIDEO_CLEAR_BUFFER _IO('o', 34) +#define VIDEO_SET_ID _IO('o', 35) +#define VIDEO_SET_STREAMTYPE _IO('o', 36) +#define VIDEO_SET_FORMAT _IO('o', 37) +#define VIDEO_SET_SYSTEM _IO('o', 38) +#define VIDEO_SET_HIGHLIGHT _IOW('o', 39, video_highlight_t) +#define VIDEO_SET_SPU _IOW('o', 50, video_spu_t) +#define VIDEO_SET_SPU_PALETTE _IOW('o', 51, video_spu_palette_t) +#define VIDEO_GET_NAVI _IOR('o', 52, video_navi_pack_t) +#define VIDEO_SET_ATTRIBUTES _IO('o', 53) +#define VIDEO_GET_SIZE _IOR('o', 55, video_size_t) +#define VIDEO_GET_FRAME_RATE _IOR('o', 56, unsigned int) + +/** + * VIDEO_GET_PTS + * + * Read the 33 bit presentation time stamp as defined + * in ITU T-REC-H.222.0 / ISO/IEC 13818-1. + * + * The PTS should belong to the currently played + * frame if possible, but may also be a value close to it + * like the PTS of the last decoded frame or the last PTS + * extracted by the PES parser. + */ +#define VIDEO_GET_PTS _IOR('o', 57, __u64) + +/* Read the number of displayed frames since the decoder was started */ +#define VIDEO_GET_FRAME_COUNT _IOR('o', 58, __u64) + +#define VIDEO_COMMAND _IOWR('o', 59, struct video_command) +#define VIDEO_TRY_COMMAND _IOWR('o', 60, struct video_command) + +#endif /* _UAPI_DVBVIDEO_H_ */ diff --git a/include/uapi/linux/elf-fdpic.h b/include/uapi/linux/elf-fdpic.h index 1065078938f..3921e33aec8 100644 --- a/include/uapi/linux/elf-fdpic.h +++ b/include/uapi/linux/elf-fdpic.h @@ -9,8 +9,8 @@ * 2 of the License, or (at your option) any later version. */ -#ifndef _LINUX_ELF_FDPIC_H -#define _LINUX_ELF_FDPIC_H +#ifndef _UAPI_LINUX_ELF_FDPIC_H +#define _UAPI_LINUX_ELF_FDPIC_H #include <linux/elf.h> @@ -31,40 +31,4 @@ struct elf32_fdpic_loadmap { #define ELF32_FDPIC_LOADMAP_VERSION 0x0000 -#ifndef __KERNEL__ -/* - * binfmt binary parameters structure - */ -struct elf_fdpic_params { - struct elfhdr hdr; /* ref copy of ELF header */ - struct elf_phdr *phdrs; /* ref copy of PT_PHDR table */ - struct elf32_fdpic_loadmap *loadmap; /* loadmap to be passed to userspace */ - unsigned long elfhdr_addr; /* mapped ELF header user address */ - unsigned long ph_addr; /* mapped PT_PHDR user address */ - unsigned long map_addr; /* mapped loadmap user address */ - unsigned long entry_addr; /* mapped entry user address */ - unsigned long stack_size; /* stack size requested (PT_GNU_STACK) */ - unsigned long dynamic_addr; /* mapped PT_DYNAMIC user address */ - unsigned long load_addr; /* user address at which to map binary */ - unsigned long flags; -#define ELF_FDPIC_FLAG_ARRANGEMENT 0x0000000f /* PT_LOAD arrangement flags */ -#define ELF_FDPIC_FLAG_INDEPENDENT 0x00000000 /* PT_LOADs can be put anywhere */ -#define ELF_FDPIC_FLAG_HONOURVADDR 0x00000001 /* PT_LOAD.vaddr must be honoured */ -#define ELF_FDPIC_FLAG_CONSTDISP 0x00000002 /* PT_LOADs require constant - * displacement */ -#define ELF_FDPIC_FLAG_CONTIGUOUS 0x00000003 /* PT_LOADs should be contiguous */ -#define ELF_FDPIC_FLAG_EXEC_STACK 0x00000010 /* T if stack to be executable */ -#define ELF_FDPIC_FLAG_NOEXEC_STACK 0x00000020 /* T if stack not to be executable */ -#define ELF_FDPIC_FLAG_EXECUTABLE 0x00000040 /* T if this object is the executable */ -#define ELF_FDPIC_FLAG_PRESENT 0x80000000 /* T if this object is present */ -}; - -#ifdef CONFIG_MMU -extern void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params, - struct elf_fdpic_params *interp_params, - unsigned long *start_stack, - unsigned long *start_brk); -#endif -#endif /* __KERNEL__ */ - -#endif /* _LINUX_ELF_FDPIC_H */ +#endif /* _UAPI_LINUX_ELF_FDPIC_H */ diff --git a/include/uapi/linux/eventpoll.h b/include/uapi/linux/eventpoll.h index 8c99ce7202c..2c267bcbb85 100644 --- a/include/uapi/linux/eventpoll.h +++ b/include/uapi/linux/eventpoll.h @@ -25,7 +25,6 @@ #define EPOLL_CTL_ADD 1 #define EPOLL_CTL_DEL 2 #define EPOLL_CTL_MOD 3 -#define EPOLL_CTL_DISABLE 4 /* * Request the handling of system wakeup events so as to prevent system suspends diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 9fcc880d4be..780d4c6093e 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -57,85 +57,6 @@ struct inodes_stat_t { #define NR_FILE 8192 /* this can well be larger on a larger system */ -#define MAY_EXEC 0x00000001 -#define MAY_WRITE 0x00000002 -#define MAY_READ 0x00000004 -#define MAY_APPEND 0x00000008 -#define MAY_ACCESS 0x00000010 -#define MAY_OPEN 0x00000020 -#define MAY_CHDIR 0x00000040 -/* called from RCU mode, don't block */ -#define MAY_NOT_BLOCK 0x00000080 - -/* - * flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond - * to O_WRONLY and O_RDWR via the strange trick in __dentry_open() - */ - -/* file is open for reading */ -#define FMODE_READ ((__force fmode_t)0x1) -/* file is open for writing */ -#define FMODE_WRITE ((__force fmode_t)0x2) -/* file is seekable */ -#define FMODE_LSEEK ((__force fmode_t)0x4) -/* file can be accessed using pread */ -#define FMODE_PREAD ((__force fmode_t)0x8) -/* file can be accessed using pwrite */ -#define FMODE_PWRITE ((__force fmode_t)0x10) -/* File is opened for execution with sys_execve / sys_uselib */ -#define FMODE_EXEC ((__force fmode_t)0x20) -/* File is opened with O_NDELAY (only set for block devices) */ -#define FMODE_NDELAY ((__force fmode_t)0x40) -/* File is opened with O_EXCL (only set for block devices) */ -#define FMODE_EXCL ((__force fmode_t)0x80) -/* File is opened using open(.., 3, ..) and is writeable only for ioctls - (specialy hack for floppy.c) */ -#define FMODE_WRITE_IOCTL ((__force fmode_t)0x100) -/* 32bit hashes as llseek() offset (for directories) */ -#define FMODE_32BITHASH ((__force fmode_t)0x200) -/* 64bit hashes as llseek() offset (for directories) */ -#define FMODE_64BITHASH ((__force fmode_t)0x400) - -/* - * Don't update ctime and mtime. - * - * Currently a special hack for the XFS open_by_handle ioctl, but we'll - * hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon. - */ -#define FMODE_NOCMTIME ((__force fmode_t)0x800) - -/* Expect random access pattern */ -#define FMODE_RANDOM ((__force fmode_t)0x1000) - -/* File is huge (eg. /dev/kmem): treat loff_t as unsigned */ -#define FMODE_UNSIGNED_OFFSET ((__force fmode_t)0x2000) - -/* File is opened with O_PATH; almost nothing can be done with it */ -#define FMODE_PATH ((__force fmode_t)0x4000) - -/* File was opened by fanotify and shouldn't generate fanotify events */ -#define FMODE_NONOTIFY ((__force fmode_t)0x1000000) - -/* - * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector - * that indicates that they should check the contents of the iovec are - * valid, but not check the memory that the iovec elements - * points too. - */ -#define CHECK_IOVEC_ONLY -1 - -#define SEL_IN 1 -#define SEL_OUT 2 -#define SEL_EX 4 - -/* public flags for file_system_type */ -#define FS_REQUIRES_DEV 1 -#define FS_BINARY_MOUNTDATA 2 -#define FS_HAS_SUBTYPE 4 -#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */ -#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() - * during rename() internally. - */ /* * These are the fs-independent mount-flags: up to 32 flags are supported @@ -181,59 +102,6 @@ struct inodes_stat_t { #define MS_MGC_VAL 0xC0ED0000 #define MS_MGC_MSK 0xffff0000 -/* Inode flags - they have nothing to superblock flags now */ - -#define S_SYNC 1 /* Writes are synced at once */ -#define S_NOATIME 2 /* Do not update access times */ -#define S_APPEND 4 /* Append-only file */ -#define S_IMMUTABLE 8 /* Immutable file */ -#define S_DEAD 16 /* removed, but still open directory */ -#define S_NOQUOTA 32 /* Inode is not counted to quota */ -#define S_DIRSYNC 64 /* Directory modifications are synchronous */ -#define S_NOCMTIME 128 /* Do not update file c/mtime */ -#define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */ -#define S_PRIVATE 512 /* Inode is fs-internal */ -#define S_IMA 1024 /* Inode has an associated IMA struct */ -#define S_AUTOMOUNT 2048 /* Automount/referral quasi-directory */ -#define S_NOSEC 4096 /* no suid or xattr security attributes */ - -/* - * Note that nosuid etc flags are inode-specific: setting some file-system - * flags just means all the inodes inherit those flags by default. It might be - * possible to override it selectively if you really wanted to with some - * ioctl() that is not currently implemented. - * - * Exception: MS_RDONLY is always applied to the entire file system. - * - * Unfortunately, it is possible to change a filesystems flags with it mounted - * with files in use. This means that all of the inodes will not have their - * i_flags updated. Hence, i_flags no longer inherit the superblock mount - * flags, so these have to be checked separately. -- rmk@arm.uk.linux.org - */ -#define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg)) - -#define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY) -#define IS_SYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS) || \ - ((inode)->i_flags & S_SYNC)) -#define IS_DIRSYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \ - ((inode)->i_flags & (S_SYNC|S_DIRSYNC))) -#define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK) -#define IS_NOATIME(inode) __IS_FLG(inode, MS_RDONLY|MS_NOATIME) -#define IS_I_VERSION(inode) __IS_FLG(inode, MS_I_VERSION) - -#define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) -#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) -#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) -#define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL) - -#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD) -#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME) -#define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE) -#define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE) -#define IS_IMA(inode) ((inode)->i_flags & S_IMA) -#define IS_AUTOMOUNT(inode) ((inode)->i_flags & S_AUTOMOUNT) -#define IS_NOSEC(inode) ((inode)->i_flags & S_NOSEC) - /* the read-only stuff doesn't really belong here, but any other place is probably as bad and I don't want to create yet another include file. */ diff --git a/include/uapi/linux/hsi/Kbuild b/include/uapi/linux/hsi/Kbuild index aafaa5aa54d..30ab3cd3b8a 100644 --- a/include/uapi/linux/hsi/Kbuild +++ b/include/uapi/linux/hsi/Kbuild @@ -1 +1,2 @@ # UAPI Header export list +header-y += hsi_char.h diff --git a/include/linux/hsi/hsi_char.h b/include/uapi/linux/hsi/hsi_char.h index 76160b4f455..76160b4f455 100644 --- a/include/linux/hsi/hsi_char.h +++ b/include/uapi/linux/hsi/hsi_char.h diff --git a/include/uapi/linux/irqnr.h b/include/uapi/linux/irqnr.h index e69de29bb2d..ae5704fa77a 100644 --- a/include/uapi/linux/irqnr.h +++ b/include/uapi/linux/irqnr.h @@ -0,0 +1,4 @@ +/* + * There isn't anything here anymore, but the file must not be empty or patch + * will delete it. + */ diff --git a/include/uapi/linux/oom.h b/include/uapi/linux/oom.h index a49c4afc706..b29272d621c 100644 --- a/include/uapi/linux/oom.h +++ b/include/uapi/linux/oom.h @@ -8,4 +8,13 @@ #define OOM_SCORE_ADJ_MIN (-1000) #define OOM_SCORE_ADJ_MAX 1000 +/* + * /proc/<pid>/oom_adj set to -17 protects from the oom killer for legacy + * purposes. + */ +#define OOM_DISABLE (-17) +/* inclusive */ +#define OOM_ADJUST_MIN (-16) +#define OOM_ADJUST_MAX 15 + #endif /* _UAPI__INCLUDE_LINUX_OOM_H */ diff --git a/include/uapi/linux/raid/Kbuild b/include/uapi/linux/raid/Kbuild index aafaa5aa54d..e2c3d25405d 100644 --- a/include/uapi/linux/raid/Kbuild +++ b/include/uapi/linux/raid/Kbuild @@ -1 +1,3 @@ # UAPI Header export list +header-y += md_p.h +header-y += md_u.h diff --git a/include/linux/raid/md_p.h b/include/uapi/linux/raid/md_p.h index ee753536ab7..ee753536ab7 100644 --- a/include/linux/raid/md_p.h +++ b/include/uapi/linux/raid/md_p.h diff --git a/include/uapi/linux/raid/md_u.h b/include/uapi/linux/raid/md_u.h new file mode 100644 index 00000000000..4133e744e4e --- /dev/null +++ b/include/uapi/linux/raid/md_u.h @@ -0,0 +1,155 @@ +/* + md_u.h : user <=> kernel API between Linux raidtools and RAID drivers + Copyright (C) 1998 Ingo Molnar + + 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, or (at your option) + any later version. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _UAPI_MD_U_H +#define _UAPI_MD_U_H + +/* + * Different major versions are not compatible. + * Different minor versions are only downward compatible. + * Different patchlevel versions are downward and upward compatible. + */ +#define MD_MAJOR_VERSION 0 +#define MD_MINOR_VERSION 90 +/* + * MD_PATCHLEVEL_VERSION indicates kernel functionality. + * >=1 means different superblock formats are selectable using SET_ARRAY_INFO + * and major_version/minor_version accordingly + * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT + * in the super status byte + * >=3 means that bitmap superblock version 4 is supported, which uses + * little-ending representation rather than host-endian + */ +#define MD_PATCHLEVEL_VERSION 3 + +/* ioctls */ + +/* status */ +#define RAID_VERSION _IOR (MD_MAJOR, 0x10, mdu_version_t) +#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, mdu_array_info_t) +#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t) +#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13) +#define RAID_AUTORUN _IO (MD_MAJOR, 0x14) +#define GET_BITMAP_FILE _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) + +/* configuration */ +#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20) +#define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, mdu_disk_info_t) +#define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22) +#define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, mdu_array_info_t) +#define SET_DISK_INFO _IO (MD_MAJOR, 0x24) +#define WRITE_RAID_INFO _IO (MD_MAJOR, 0x25) +#define UNPROTECT_ARRAY _IO (MD_MAJOR, 0x26) +#define PROTECT_ARRAY _IO (MD_MAJOR, 0x27) +#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28) +#define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29) +#define HOT_GENERATE_ERROR _IO (MD_MAJOR, 0x2a) +#define SET_BITMAP_FILE _IOW (MD_MAJOR, 0x2b, int) + +/* usage */ +#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, mdu_param_t) +/* 0x31 was START_ARRAY */ +#define STOP_ARRAY _IO (MD_MAJOR, 0x32) +#define STOP_ARRAY_RO _IO (MD_MAJOR, 0x33) +#define RESTART_ARRAY_RW _IO (MD_MAJOR, 0x34) + +/* 63 partitions with the alternate major number (mdp) */ +#define MdpMinorShift 6 + +typedef struct mdu_version_s { + int major; + int minor; + int patchlevel; +} mdu_version_t; + +typedef struct mdu_array_info_s { + /* + * Generic constant information + */ + int major_version; + int minor_version; + int patch_version; + int ctime; + int level; + int size; + int nr_disks; + int raid_disks; + int md_minor; + int not_persistent; + + /* + * Generic state information + */ + int utime; /* 0 Superblock update time */ + int state; /* 1 State bits (clean, ...) */ + int active_disks; /* 2 Number of currently active disks */ + int working_disks; /* 3 Number of working disks */ + int failed_disks; /* 4 Number of failed disks */ + int spare_disks; /* 5 Number of spare disks */ + + /* + * Personality information + */ + int layout; /* 0 the array's physical layout */ + int chunk_size; /* 1 chunk size in bytes */ + +} mdu_array_info_t; + +/* non-obvious values for 'level' */ +#define LEVEL_MULTIPATH (-4) +#define LEVEL_LINEAR (-1) +#define LEVEL_FAULTY (-5) + +/* we need a value for 'no level specified' and 0 + * means 'raid0', so we need something else. This is + * for internal use only + */ +#define LEVEL_NONE (-1000000) + +typedef struct mdu_disk_info_s { + /* + * configuration/status of one particular disk + */ + int number; + int major; + int minor; + int raid_disk; + int state; + +} mdu_disk_info_t; + +typedef struct mdu_start_info_s { + /* + * configuration/status of one particular disk + */ + int major; + int minor; + int raid_disk; + int state; + +} mdu_start_info_t; + +typedef struct mdu_bitmap_file_s +{ + char pathname[4096]; +} mdu_bitmap_file_t; + +typedef struct mdu_param_s +{ + int personality; /* 1,2,3,4 */ + int chunk_size; /* in bytes */ + int max_fault; /* unused for now */ +} mdu_param_t; + +#endif /* _UAPI_MD_U_H */ diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index c4b89a5cb7d..e962faa5ab0 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h @@ -130,6 +130,7 @@ enum { #define TCPI_OPT_WSCALE 4 #define TCPI_OPT_ECN 8 /* ECN was negociated at TCP session init */ #define TCPI_OPT_ECN_SEEN 16 /* we received at least one packet with ECT */ +#define TCPI_OPT_SYN_DATA 32 /* SYN-ACK acked data in SYN sent or rcvd */ enum tcp_ca_state { TCP_CA_Open = 0, diff --git a/include/uapi/linux/usb/Kbuild b/include/uapi/linux/usb/Kbuild index aafaa5aa54d..6cb4ea82683 100644 --- a/include/uapi/linux/usb/Kbuild +++ b/include/uapi/linux/usb/Kbuild @@ -1 +1,11 @@ # UAPI Header export list +header-y += audio.h +header-y += cdc.h +header-y += ch11.h +header-y += ch9.h +header-y += functionfs.h +header-y += g_printer.h +header-y += gadgetfs.h +header-y += midi.h +header-y += tmc.h +header-y += video.h diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h new file mode 100644 index 00000000000..ac90037894d --- /dev/null +++ b/include/uapi/linux/usb/audio.h @@ -0,0 +1,545 @@ +/* + * <linux/usb/audio.h> -- USB Audio definitions. + * + * Copyright (C) 2006 Thumtronics Pty Ltd. + * Developed for Thumtronics by Grey Innovation + * Ben Williamson <ben.williamson@greyinnovation.com> + * + * This software is distributed under the terms of the GNU General Public + * License ("GPL") version 2, as published by the Free Software Foundation. + * + * This file holds USB constants and structures defined + * by the USB Device Class Definition for Audio Devices. + * Comments below reference relevant sections of that document: + * + * http://www.usb.org/developers/devclass_docs/audio10.pdf + * + * Types and defines in this file are either specific to version 1.0 of + * this standard or common for newer versions. + */ + +#ifndef _UAPI__LINUX_USB_AUDIO_H +#define _UAPI__LINUX_USB_AUDIO_H + +#include <linux/types.h> + +/* bInterfaceProtocol values to denote the version of the standard used */ +#define UAC_VERSION_1 0x00 +#define UAC_VERSION_2 0x20 + +/* A.2 Audio Interface Subclass Codes */ +#define USB_SUBCLASS_AUDIOCONTROL 0x01 +#define USB_SUBCLASS_AUDIOSTREAMING 0x02 +#define USB_SUBCLASS_MIDISTREAMING 0x03 + +/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */ +#define UAC_HEADER 0x01 +#define UAC_INPUT_TERMINAL 0x02 +#define UAC_OUTPUT_TERMINAL 0x03 +#define UAC_MIXER_UNIT 0x04 +#define UAC_SELECTOR_UNIT 0x05 +#define UAC_FEATURE_UNIT 0x06 +#define UAC1_PROCESSING_UNIT 0x07 +#define UAC1_EXTENSION_UNIT 0x08 + +/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */ +#define UAC_AS_GENERAL 0x01 +#define UAC_FORMAT_TYPE 0x02 +#define UAC_FORMAT_SPECIFIC 0x03 + +/* A.7 Processing Unit Process Types */ +#define UAC_PROCESS_UNDEFINED 0x00 +#define UAC_PROCESS_UP_DOWNMIX 0x01 +#define UAC_PROCESS_DOLBY_PROLOGIC 0x02 +#define UAC_PROCESS_STEREO_EXTENDER 0x03 +#define UAC_PROCESS_REVERB 0x04 +#define UAC_PROCESS_CHORUS 0x05 +#define UAC_PROCESS_DYN_RANGE_COMP 0x06 + +/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */ +#define UAC_EP_GENERAL 0x01 + +/* A.9 Audio Class-Specific Request Codes */ +#define UAC_SET_ 0x00 +#define UAC_GET_ 0x80 + +#define UAC__CUR 0x1 +#define UAC__MIN 0x2 +#define UAC__MAX 0x3 +#define UAC__RES 0x4 +#define UAC__MEM 0x5 + +#define UAC_SET_CUR (UAC_SET_ | UAC__CUR) +#define UAC_GET_CUR (UAC_GET_ | UAC__CUR) +#define UAC_SET_MIN (UAC_SET_ | UAC__MIN) +#define UAC_GET_MIN (UAC_GET_ | UAC__MIN) +#define UAC_SET_MAX (UAC_SET_ | UAC__MAX) +#define UAC_GET_MAX (UAC_GET_ | UAC__MAX) +#define UAC_SET_RES (UAC_SET_ | UAC__RES) +#define UAC_GET_RES (UAC_GET_ | UAC__RES) +#define UAC_SET_MEM (UAC_SET_ | UAC__MEM) +#define UAC_GET_MEM (UAC_GET_ | UAC__MEM) + +#define UAC_GET_STAT 0xff + +/* A.10 Control Selector Codes */ + +/* A.10.1 Terminal Control Selectors */ +#define UAC_TERM_COPY_PROTECT 0x01 + +/* A.10.2 Feature Unit Control Selectors */ +#define UAC_FU_MUTE 0x01 +#define UAC_FU_VOLUME 0x02 +#define UAC_FU_BASS 0x03 +#define UAC_FU_MID 0x04 +#define UAC_FU_TREBLE 0x05 +#define UAC_FU_GRAPHIC_EQUALIZER 0x06 +#define UAC_FU_AUTOMATIC_GAIN 0x07 +#define UAC_FU_DELAY 0x08 +#define UAC_FU_BASS_BOOST 0x09 +#define UAC_FU_LOUDNESS 0x0a + +#define UAC_CONTROL_BIT(CS) (1 << ((CS) - 1)) + +/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */ +#define UAC_UD_ENABLE 0x01 +#define UAC_UD_MODE_SELECT 0x02 + +/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */ +#define UAC_DP_ENABLE 0x01 +#define UAC_DP_MODE_SELECT 0x02 + +/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */ +#define UAC_3D_ENABLE 0x01 +#define UAC_3D_SPACE 0x02 + +/* A.10.3.4 Reverberation Processing Unit Control Selectors */ +#define UAC_REVERB_ENABLE 0x01 +#define UAC_REVERB_LEVEL 0x02 +#define UAC_REVERB_TIME 0x03 +#define UAC_REVERB_FEEDBACK 0x04 + +/* A.10.3.5 Chorus Processing Unit Control Selectors */ +#define UAC_CHORUS_ENABLE 0x01 +#define UAC_CHORUS_LEVEL 0x02 +#define UAC_CHORUS_RATE 0x03 +#define UAC_CHORUS_DEPTH 0x04 + +/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */ +#define UAC_DCR_ENABLE 0x01 +#define UAC_DCR_RATE 0x02 +#define UAC_DCR_MAXAMPL 0x03 +#define UAC_DCR_THRESHOLD 0x04 +#define UAC_DCR_ATTACK_TIME 0x05 +#define UAC_DCR_RELEASE_TIME 0x06 + +/* A.10.4 Extension Unit Control Selectors */ +#define UAC_XU_ENABLE 0x01 + +/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */ +#define UAC_MS_HEADER 0x01 +#define UAC_MIDI_IN_JACK 0x02 +#define UAC_MIDI_OUT_JACK 0x03 + +/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */ +#define UAC_MS_GENERAL 0x01 + +/* Terminals - 2.1 USB Terminal Types */ +#define UAC_TERMINAL_UNDEFINED 0x100 +#define UAC_TERMINAL_STREAMING 0x101 +#define UAC_TERMINAL_VENDOR_SPEC 0x1FF + +/* Terminal Control Selectors */ +/* 4.3.2 Class-Specific AC Interface Descriptor */ +struct uac1_ac_header_descriptor { + __u8 bLength; /* 8 + n */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* UAC_MS_HEADER */ + __le16 bcdADC; /* 0x0100 */ + __le16 wTotalLength; /* includes Unit and Terminal desc. */ + __u8 bInCollection; /* n */ + __u8 baInterfaceNr[]; /* [n] */ +} __attribute__ ((packed)); + +#define UAC_DT_AC_HEADER_SIZE(n) (8 + (n)) + +/* As above, but more useful for defining your own descriptors: */ +#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n) \ +struct uac1_ac_header_descriptor_##n { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubtype; \ + __le16 bcdADC; \ + __le16 wTotalLength; \ + __u8 bInCollection; \ + __u8 baInterfaceNr[n]; \ +} __attribute__ ((packed)) + +/* 4.3.2.1 Input Terminal Descriptor */ +struct uac_input_terminal_descriptor { + __u8 bLength; /* in bytes: 12 */ + __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ + __u8 bDescriptorSubtype; /* INPUT_TERMINAL descriptor subtype */ + __u8 bTerminalID; /* Constant uniquely terminal ID */ + __le16 wTerminalType; /* USB Audio Terminal Types */ + __u8 bAssocTerminal; /* ID of the Output Terminal associated */ + __u8 bNrChannels; /* Number of logical output channels */ + __le16 wChannelConfig; + __u8 iChannelNames; + __u8 iTerminal; +} __attribute__ ((packed)); + +#define UAC_DT_INPUT_TERMINAL_SIZE 12 + +/* Terminals - 2.2 Input Terminal Types */ +#define UAC_INPUT_TERMINAL_UNDEFINED 0x200 +#define UAC_INPUT_TERMINAL_MICROPHONE 0x201 +#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE 0x202 +#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE 0x203 +#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE 0x204 +#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY 0x205 +#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY 0x206 + +/* Terminals - control selectors */ + +#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL 0x01 + +/* 4.3.2.2 Output Terminal Descriptor */ +struct uac1_output_terminal_descriptor { + __u8 bLength; /* in bytes: 9 */ + __u8 bDescriptorType; /* CS_INTERFACE descriptor type */ + __u8 bDescriptorSubtype; /* OUTPUT_TERMINAL descriptor subtype */ + __u8 bTerminalID; /* Constant uniquely terminal ID */ + __le16 wTerminalType; /* USB Audio Terminal Types */ + __u8 bAssocTerminal; /* ID of the Input Terminal associated */ + __u8 bSourceID; /* ID of the connected Unit or Terminal*/ + __u8 iTerminal; +} __attribute__ ((packed)); + +#define UAC_DT_OUTPUT_TERMINAL_SIZE 9 + +/* Terminals - 2.3 Output Terminal Types */ +#define UAC_OUTPUT_TERMINAL_UNDEFINED 0x300 +#define UAC_OUTPUT_TERMINAL_SPEAKER 0x301 +#define UAC_OUTPUT_TERMINAL_HEADPHONES 0x302 +#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303 +#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER 0x304 +#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER 0x305 +#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306 +#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307 + +/* Set bControlSize = 2 as default setting */ +#define UAC_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 2) + +/* As above, but more useful for defining your own descriptors: */ +#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch) \ +struct uac_feature_unit_descriptor_##ch { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubtype; \ + __u8 bUnitID; \ + __u8 bSourceID; \ + __u8 bControlSize; \ + __le16 bmaControls[ch + 1]; \ + __u8 iFeature; \ +} __attribute__ ((packed)) + +/* 4.3.2.3 Mixer Unit Descriptor */ +struct uac_mixer_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __u8 bNrInPins; + __u8 baSourceID[]; +} __attribute__ ((packed)); + +static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *desc) +{ + return desc->baSourceID[desc->bNrInPins]; +} + +static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc, + int protocol) +{ + if (protocol == UAC_VERSION_1) + return (desc->baSourceID[desc->bNrInPins + 2] << 8) | + desc->baSourceID[desc->bNrInPins + 1]; + else + return (desc->baSourceID[desc->bNrInPins + 4] << 24) | + (desc->baSourceID[desc->bNrInPins + 3] << 16) | + (desc->baSourceID[desc->bNrInPins + 2] << 8) | + (desc->baSourceID[desc->bNrInPins + 1]); +} + +static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc, + int protocol) +{ + return (protocol == UAC_VERSION_1) ? + desc->baSourceID[desc->bNrInPins + 3] : + desc->baSourceID[desc->bNrInPins + 5]; +} + +static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc, + int protocol) +{ + return (protocol == UAC_VERSION_1) ? + &desc->baSourceID[desc->bNrInPins + 4] : + &desc->baSourceID[desc->bNrInPins + 6]; +} + +static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc) +{ + __u8 *raw = (__u8 *) desc; + return raw[desc->bLength - 1]; +} + +/* 4.3.2.4 Selector Unit Descriptor */ +struct uac_selector_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUintID; + __u8 bNrInPins; + __u8 baSourceID[]; +} __attribute__ ((packed)); + +static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc) +{ + __u8 *raw = (__u8 *) desc; + return raw[desc->bLength - 1]; +} + +/* 4.3.2.5 Feature Unit Descriptor */ +struct uac_feature_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __u8 bSourceID; + __u8 bControlSize; + __u8 bmaControls[0]; /* variable length */ +} __attribute__((packed)); + +static inline __u8 uac_feature_unit_iFeature(struct uac_feature_unit_descriptor *desc) +{ + __u8 *raw = (__u8 *) desc; + return raw[desc->bLength - 1]; +} + +/* 4.3.2.6 Processing Unit Descriptors */ +struct uac_processing_unit_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bUnitID; + __u16 wProcessType; + __u8 bNrInPins; + __u8 baSourceID[]; +} __attribute__ ((packed)); + +static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_descriptor *desc) +{ + return desc->baSourceID[desc->bNrInPins]; +} + +static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + if (protocol == UAC_VERSION_1) + return (desc->baSourceID[desc->bNrInPins + 2] << 8) | + desc->baSourceID[desc->bNrInPins + 1]; + else + return (desc->baSourceID[desc->bNrInPins + 4] << 24) | + (desc->baSourceID[desc->bNrInPins + 3] << 16) | + (desc->baSourceID[desc->bNrInPins + 2] << 8) | + (desc->baSourceID[desc->bNrInPins + 1]); +} + +static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + return (protocol == UAC_VERSION_1) ? + desc->baSourceID[desc->bNrInPins + 3] : + desc->baSourceID[desc->bNrInPins + 5]; +} + +static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + return (protocol == UAC_VERSION_1) ? + desc->baSourceID[desc->bNrInPins + 4] : + desc->baSourceID[desc->bNrInPins + 6]; +} + +static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + return (protocol == UAC_VERSION_1) ? + &desc->baSourceID[desc->bNrInPins + 5] : + &desc->baSourceID[desc->bNrInPins + 7]; +} + +static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); + return desc->baSourceID[desc->bNrInPins + control_size]; +} + +static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc, + int protocol) +{ + __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); + return &desc->baSourceID[desc->bNrInPins + control_size + 1]; +} + +/* 4.5.2 Class-Specific AS Interface Descriptor */ +struct uac1_as_header_descriptor { + __u8 bLength; /* in bytes: 7 */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* AS_GENERAL */ + __u8 bTerminalLink; /* Terminal ID of connected Terminal */ + __u8 bDelay; /* Delay introduced by the data path */ + __le16 wFormatTag; /* The Audio Data Format */ +} __attribute__ ((packed)); + +#define UAC_DT_AS_HEADER_SIZE 7 + +/* Formats - A.1.1 Audio Data Format Type I Codes */ +#define UAC_FORMAT_TYPE_I_UNDEFINED 0x0 +#define UAC_FORMAT_TYPE_I_PCM 0x1 +#define UAC_FORMAT_TYPE_I_PCM8 0x2 +#define UAC_FORMAT_TYPE_I_IEEE_FLOAT 0x3 +#define UAC_FORMAT_TYPE_I_ALAW 0x4 +#define UAC_FORMAT_TYPE_I_MULAW 0x5 + +struct uac_format_type_i_continuous_descriptor { + __u8 bLength; /* in bytes: 8 + (ns * 3) */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* FORMAT_TYPE */ + __u8 bFormatType; /* FORMAT_TYPE_1 */ + __u8 bNrChannels; /* physical channels in the stream */ + __u8 bSubframeSize; /* */ + __u8 bBitResolution; + __u8 bSamFreqType; + __u8 tLowerSamFreq[3]; + __u8 tUpperSamFreq[3]; +} __attribute__ ((packed)); + +#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14 + +struct uac_format_type_i_discrete_descriptor { + __u8 bLength; /* in bytes: 8 + (ns * 3) */ + __u8 bDescriptorType; /* USB_DT_CS_INTERFACE */ + __u8 bDescriptorSubtype; /* FORMAT_TYPE */ + __u8 bFormatType; /* FORMAT_TYPE_1 */ + __u8 bNrChannels; /* physical channels in the stream */ + __u8 bSubframeSize; /* */ + __u8 bBitResolution; + __u8 bSamFreqType; + __u8 tSamFreq[][3]; +} __attribute__ ((packed)); + +#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n) \ +struct uac_format_type_i_discrete_descriptor_##n { \ + __u8 bLength; \ + __u8 bDescriptorType; \ + __u8 bDescriptorSubtype; \ + __u8 bFormatType; \ + __u8 bNrChannels; \ + __u8 bSubframeSize; \ + __u8 bBitResolution; \ + __u8 bSamFreqType; \ + __u8 tSamFreq[n][3]; \ +} __attribute__ ((packed)) + +#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n) (8 + (n * 3)) + +struct uac_format_type_i_ext_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bFormatType; + __u8 bSubslotSize; + __u8 bBitResolution; + __u8 bHeaderLength; + __u8 bControlSize; + __u8 bSideBandProtocol; +} __attribute__((packed)); + +/* Formats - Audio Data Format Type I Codes */ + +#define UAC_FORMAT_TYPE_II_MPEG 0x1001 +#define UAC_FORMAT_TYPE_II_AC3 0x1002 + +struct uac_format_type_ii_discrete_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bFormatType; + __le16 wMaxBitRate; + __le16 wSamplesPerFrame; + __u8 bSamFreqType; + __u8 tSamFreq[][3]; +} __attribute__((packed)); + +struct uac_format_type_ii_ext_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u8 bFormatType; + __u16 wMaxBitRate; + __u16 wSamplesPerFrame; + __u8 bHeaderLength; + __u8 bSideBandProtocol; +} __attribute__((packed)); + +/* type III */ +#define UAC_FORMAT_TYPE_III_IEC1937_AC3 0x2001 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1 0x2002 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT 0x2003 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT 0x2004 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS 0x2005 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS 0x2006 + +/* Formats - A.2 Format Type Codes */ +#define UAC_FORMAT_TYPE_UNDEFINED 0x0 +#define UAC_FORMAT_TYPE_I 0x1 +#define UAC_FORMAT_TYPE_II 0x2 +#define UAC_FORMAT_TYPE_III 0x3 +#define UAC_EXT_FORMAT_TYPE_I 0x81 +#define UAC_EXT_FORMAT_TYPE_II 0x82 +#define UAC_EXT_FORMAT_TYPE_III 0x83 + +struct uac_iso_endpoint_descriptor { + __u8 bLength; /* in bytes: 7 */ + __u8 bDescriptorType; /* USB_DT_CS_ENDPOINT */ + __u8 bDescriptorSubtype; /* EP_GENERAL */ + __u8 bmAttributes; + __u8 bLockDelayUnits; + __le16 wLockDelay; +} __attribute__((packed)); +#define UAC_ISO_ENDPOINT_DESC_SIZE 7 + +#define UAC_EP_CS_ATTR_SAMPLE_RATE 0x01 +#define UAC_EP_CS_ATTR_PITCH_CONTROL 0x02 +#define UAC_EP_CS_ATTR_FILL_MAX 0x80 + +/* status word format (3.7.1.1) */ + +#define UAC1_STATUS_TYPE_ORIG_MASK 0x0f +#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0 +#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF 0x1 +#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP 0x2 + +#define UAC1_STATUS_TYPE_IRQ_PENDING (1 << 7) +#define UAC1_STATUS_TYPE_MEM_CHANGED (1 << 6) + +struct uac1_status_word { + __u8 bStatusType; + __u8 bOriginator; +} __attribute__((packed)); + + +#endif /* _UAPI__LINUX_USB_AUDIO_H */ diff --git a/include/linux/usb/cdc.h b/include/uapi/linux/usb/cdc.h index 81a927930bf..81a927930bf 100644 --- a/include/linux/usb/cdc.h +++ b/include/uapi/linux/usb/cdc.h diff --git a/include/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h index 7692dc69ccf..7692dc69ccf 100644 --- a/include/linux/usb/ch11.h +++ b/include/uapi/linux/usb/ch11.h diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h new file mode 100644 index 00000000000..50598472dc4 --- /dev/null +++ b/include/uapi/linux/usb/ch9.h @@ -0,0 +1,993 @@ +/* + * This file holds USB constants and structures that are needed for + * USB device APIs. These are used by the USB device model, which is + * defined in chapter 9 of the USB 2.0 specification and in the + * Wireless USB 1.0 (spread around). Linux has several APIs in C that + * need these: + * + * - the master/host side Linux-USB kernel driver API; + * - the "usbfs" user space API; and + * - the Linux "gadget" slave/device/peripheral side driver API. + * + * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems + * act either as a USB master/host or as a USB slave/device. That means + * the master and slave side APIs benefit from working well together. + * + * There's also "Wireless USB", using low power short range radios for + * peripheral interconnection but otherwise building on the USB framework. + * + * Note all descriptors are declared '__attribute__((packed))' so that: + * + * [a] they never get padded, either internally (USB spec writers + * probably handled that) or externally; + * + * [b] so that accessing bigger-than-a-bytes fields will never + * generate bus errors on any platform, even when the location of + * its descriptor inside a bundle isn't "naturally aligned", and + * + * [c] for consistency, removing all doubt even when it appears to + * someone that the two other points are non-issues for that + * particular descriptor type. + */ + +#ifndef _UAPI__LINUX_USB_CH9_H +#define _UAPI__LINUX_USB_CH9_H + +#include <linux/types.h> /* __u8 etc */ +#include <asm/byteorder.h> /* le16_to_cpu */ + +/*-------------------------------------------------------------------------*/ + +/* CONTROL REQUEST SUPPORT */ + +/* + * USB directions + * + * This bit flag is used in endpoint descriptors' bEndpointAddress field. + * It's also one of three fields in control requests bRequestType. + */ +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ + +/* + * USB types, the second of three bRequestType fields + */ +#define USB_TYPE_MASK (0x03 << 5) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +/* + * USB recipients, the third of three bRequestType fields + */ +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 +/* From Wireless USB 1.0 */ +#define USB_RECIP_PORT 0x04 +#define USB_RECIP_RPIPE 0x05 + +/* + * Standard requests, for the bRequest field of a SETUP packet. + * + * These are qualified by the bRequestType field, so that for example + * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved + * by a GET_STATUS request. + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C +#define USB_REQ_SET_SEL 0x30 +#define USB_REQ_SET_ISOCH_DELAY 0x31 + +#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ +#define USB_REQ_GET_ENCRYPTION 0x0E +#define USB_REQ_RPIPE_ABORT 0x0E +#define USB_REQ_SET_HANDSHAKE 0x0F +#define USB_REQ_RPIPE_RESET 0x0F +#define USB_REQ_GET_HANDSHAKE 0x10 +#define USB_REQ_SET_CONNECTION 0x11 +#define USB_REQ_SET_SECURITY_DATA 0x12 +#define USB_REQ_GET_SECURITY_DATA 0x13 +#define USB_REQ_SET_WUSB_DATA 0x14 +#define USB_REQ_LOOPBACK_DATA_WRITE 0x15 +#define USB_REQ_LOOPBACK_DATA_READ 0x16 +#define USB_REQ_SET_INTERFACE_DS 0x17 + +/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command, + * used by hubs to put ports into a new L1 suspend state, except that it + * forgot to define its number ... + */ + +/* + * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and + * are read as a bit array returned by USB_REQ_GET_STATUS. (So there + * are at most sixteen features of each type.) Hubs may also support a + * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend. + */ +#define USB_DEVICE_SELF_POWERED 0 /* (read only) */ +#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ +#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ +#define USB_DEVICE_BATTERY 2 /* (wireless) */ +#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ +#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ +#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ +#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ +#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ + +/* + * Test Mode Selectors + * See USB 2.0 spec Table 9-7 + */ +#define TEST_J 1 +#define TEST_K 2 +#define TEST_SE0_NAK 3 +#define TEST_PACKET 4 +#define TEST_FORCE_EN 5 + +/* + * New Feature Selectors as added by USB 3.0 + * See USB 3.0 spec Table 9-6 + */ +#define USB_DEVICE_U1_ENABLE 48 /* dev may initiate U1 transition */ +#define USB_DEVICE_U2_ENABLE 49 /* dev may initiate U2 transition */ +#define USB_DEVICE_LTM_ENABLE 50 /* dev may send LTM */ +#define USB_INTRF_FUNC_SUSPEND 0 /* function suspend */ + +#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00 +/* + * Suspend Options, Table 9-7 USB 3.0 spec + */ +#define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0)) +#define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1)) + +#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ + +/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */ +#define USB_DEV_STAT_U1_ENABLED 2 /* transition into U1 state */ +#define USB_DEV_STAT_U2_ENABLED 3 /* transition into U2 state */ +#define USB_DEV_STAT_LTM_ENABLED 4 /* Latency tolerance messages */ + +/** + * struct usb_ctrlrequest - SETUP data for a USB device control request + * @bRequestType: matches the USB bmRequestType field + * @bRequest: matches the USB bRequest field + * @wValue: matches the USB wValue field (le16 byte order) + * @wIndex: matches the USB wIndex field (le16 byte order) + * @wLength: matches the USB wLength field (le16 byte order) + * + * This structure is used to send control requests to a USB device. It matches + * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the + * USB spec for a fuller description of the different fields, and what they are + * used for. + * + * Note that the driver for any interface can issue control requests. + * For most devices, interfaces don't coordinate with each other, so + * such requests may be made at any time. + */ +struct usb_ctrlrequest { + __u8 bRequestType; + __u8 bRequest; + __le16 wValue; + __le16 wIndex; + __le16 wLength; +} __attribute__ ((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or + * (rarely) accepted by SET_DESCRIPTOR. + * + * Note that all multi-byte values here are encoded in little endian + * byte order "on the wire". Within the kernel and when exposed + * through the Linux-USB APIs, they are not converted to cpu byte + * order; it is the responsibility of the client code to do this. + * The single exception is when device and configuration descriptors (but + * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD); + * in this case the fields are converted to host endianness by the kernel. + */ + +/* + * Descriptor types ... USB 2.0 spec table 9.5 + */ +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_DEVICE_QUALIFIER 0x06 +#define USB_DT_OTHER_SPEED_CONFIG 0x07 +#define USB_DT_INTERFACE_POWER 0x08 +/* these are from a minor usb 2.0 revision (ECN) */ +#define USB_DT_OTG 0x09 +#define USB_DT_DEBUG 0x0a +#define USB_DT_INTERFACE_ASSOCIATION 0x0b +/* these are from the Wireless USB spec */ +#define USB_DT_SECURITY 0x0c +#define USB_DT_KEY 0x0d +#define USB_DT_ENCRYPTION_TYPE 0x0e +#define USB_DT_BOS 0x0f +#define USB_DT_DEVICE_CAPABILITY 0x10 +#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 +#define USB_DT_WIRE_ADAPTER 0x21 +#define USB_DT_RPIPE 0x22 +#define USB_DT_CS_RADIO_CONTROL 0x23 +/* From the T10 UAS specification */ +#define USB_DT_PIPE_USAGE 0x24 +/* From the USB 3.0 spec */ +#define USB_DT_SS_ENDPOINT_COMP 0x30 + +/* Conventional codes for class-specific descriptors. The convention is + * defined in the USB "Common Class" Spec (3.11). Individual class specs + * are authoritative for their usage, not the "common class" writeup. + */ +#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE) +#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG) +#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING) +#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE) +#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT) + +/* All standard descriptors have these 2 fields at the beginning */ +struct usb_descriptor_header { + __u8 bLength; + __u8 bDescriptorType; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE: Device descriptor */ +struct usb_device_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 bcdUSB; + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + __u8 bMaxPacketSize0; + __le16 idVendor; + __le16 idProduct; + __le16 bcdDevice; + __u8 iManufacturer; + __u8 iProduct; + __u8 iSerialNumber; + __u8 bNumConfigurations; +} __attribute__ ((packed)); + +#define USB_DT_DEVICE_SIZE 18 + + +/* + * Device and/or Interface Class codes + * as found in bDeviceClass or bInterfaceClass + * and defined by www.usb.org documents + */ +#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PHYSICAL 5 +#define USB_CLASS_STILL_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ +#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ +#define USB_CLASS_VIDEO 0x0e +#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_APP_SPEC 0xfe +#define USB_CLASS_VENDOR_SPEC 0xff + +#define USB_SUBCLASS_VENDOR_SPEC 0xff + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_CONFIG: Configuration descriptor information. + * + * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the + * descriptor type is different. Highspeed-capable devices can look + * different depending on what speed they're currently running. Only + * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG + * descriptors. + */ +struct usb_config_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 wTotalLength; + __u8 bNumInterfaces; + __u8 bConfigurationValue; + __u8 iConfiguration; + __u8 bmAttributes; + __u8 bMaxPower; +} __attribute__ ((packed)); + +#define USB_DT_CONFIG_SIZE 9 + +/* from config descriptor bmAttributes */ +#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ +#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ +#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ +#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_STRING: String descriptor */ +struct usb_string_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 wData[1]; /* UTF-16LE encoded */ +} __attribute__ ((packed)); + +/* note that "string" zero is special, it holds language codes that + * the device supports, not Unicode characters. + */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_INTERFACE: Interface descriptor */ +struct usb_interface_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bInterfaceNumber; + __u8 bAlternateSetting; + __u8 bNumEndpoints; + __u8 bInterfaceClass; + __u8 bInterfaceSubClass; + __u8 bInterfaceProtocol; + __u8 iInterface; +} __attribute__ ((packed)); + +#define USB_DT_INTERFACE_SIZE 9 + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_ENDPOINT: Endpoint descriptor */ +struct usb_endpoint_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bEndpointAddress; + __u8 bmAttributes; + __le16 wMaxPacketSize; + __u8 bInterval; + + /* NOTE: these two are _only_ in audio endpoints. */ + /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ + __u8 bRefresh; + __u8 bSynchAddress; +} __attribute__ ((packed)); + +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ + + +/* + * Endpoints + */ +#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ +#define USB_ENDPOINT_DIR_MASK 0x80 + +#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_XFER_CONTROL 0 +#define USB_ENDPOINT_XFER_ISOC 1 +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_XFER_INT 3 +#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 + +/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */ +#define USB_ENDPOINT_INTRTYPE 0x30 +#define USB_ENDPOINT_INTR_PERIODIC (0 << 4) +#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4) + +#define USB_ENDPOINT_SYNCTYPE 0x0c +#define USB_ENDPOINT_SYNC_NONE (0 << 2) +#define USB_ENDPOINT_SYNC_ASYNC (1 << 2) +#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << 2) +#define USB_ENDPOINT_SYNC_SYNC (3 << 2) + +#define USB_ENDPOINT_USAGE_MASK 0x30 +#define USB_ENDPOINT_USAGE_DATA 0x00 +#define USB_ENDPOINT_USAGE_FEEDBACK 0x10 +#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20 /* Implicit feedback Data endpoint */ + +/*-------------------------------------------------------------------------*/ + +/** + * usb_endpoint_num - get the endpoint's number + * @epd: endpoint to be checked + * + * Returns @epd's number: 0 to 15. + */ +static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) +{ + return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; +} + +/** + * usb_endpoint_type - get the endpoint's transfer type + * @epd: endpoint to be checked + * + * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according + * to @epd's transfer type. + */ +static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) +{ + return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; +} + +/** + * usb_endpoint_dir_in - check if the endpoint has IN direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type IN, otherwise it returns false. + */ +static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); +} + +/** + * usb_endpoint_dir_out - check if the endpoint has OUT direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type OUT, otherwise it returns false. + */ +static inline int usb_endpoint_dir_out( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); +} + +/** + * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type bulk, otherwise it returns false. + */ +static inline int usb_endpoint_xfer_bulk( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK); +} + +/** + * usb_endpoint_xfer_control - check if the endpoint has control transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type control, otherwise it returns false. + */ +static inline int usb_endpoint_xfer_control( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL); +} + +/** + * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type interrupt, otherwise it returns + * false. + */ +static inline int usb_endpoint_xfer_int( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT); +} + +/** + * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type isochronous, otherwise it returns + * false. + */ +static inline int usb_endpoint_xfer_isoc( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC); +} + +/** + * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_bulk_in( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd); +} + +/** + * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_bulk_out( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd); +} + +/** + * usb_endpoint_is_int_in - check if the endpoint is interrupt IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_int_in( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd); +} + +/** + * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_int_out( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd); +} + +/** + * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_isoc_in( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd); +} + +/** + * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_isoc_out( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd); +} + +/** + * usb_endpoint_maxp - get endpoint's max packet size + * @epd: endpoint to be checked + * + * Returns @epd's max packet + */ +static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd) +{ + return __le16_to_cpu(epd->wMaxPacketSize); +} + +static inline int usb_endpoint_interrupt_type( + const struct usb_endpoint_descriptor *epd) +{ + return epd->bmAttributes & USB_ENDPOINT_INTRTYPE; +} + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ +struct usb_ss_ep_comp_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bMaxBurst; + __u8 bmAttributes; + __le16 wBytesPerInterval; +} __attribute__ ((packed)); + +#define USB_DT_SS_EP_COMP_SIZE 6 + +/* Bits 4:0 of bmAttributes if this is a bulk endpoint */ +static inline int +usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp) +{ + int max_streams; + + if (!comp) + return 0; + + max_streams = comp->bmAttributes & 0x1f; + + if (!max_streams) + return 0; + + max_streams = 1 << max_streams; + + return max_streams; +} + +/* Bits 1:0 of bmAttributes if this is an isoc endpoint */ +#define USB_SS_MULT(p) (1 + ((p) & 0x3)) + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ +struct usb_qualifier_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 bcdUSB; + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + __u8 bMaxPacketSize0; + __u8 bNumConfigurations; + __u8 bRESERVED; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_OTG (from OTG 1.0a supplement) */ +struct usb_otg_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bmAttributes; /* support for HNP, SRP, etc */ +} __attribute__ ((packed)); + +/* from usb_otg_descriptor.bmAttributes */ +#define USB_OTG_SRP (1 << 0) +#define USB_OTG_HNP (1 << 1) /* swap host/device roles */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */ +struct usb_debug_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + /* bulk endpoints with 8 byte maxpacket */ + __u8 bDebugInEndpoint; + __u8 bDebugOutEndpoint; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */ +struct usb_interface_assoc_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bFirstInterface; + __u8 bInterfaceCount; + __u8 bFunctionClass; + __u8 bFunctionSubClass; + __u8 bFunctionProtocol; + __u8 iFunction; +} __attribute__ ((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_SECURITY: group of wireless security descriptors, including + * encryption types available for setting up a CC/association. + */ +struct usb_security_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 wTotalLength; + __u8 bNumEncryptionTypes; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys + * may be retrieved. + */ +struct usb_key_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 tTKID[3]; + __u8 bReserved; + __u8 bKeyData[0]; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */ +struct usb_encryption_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bEncryptionType; +#define USB_ENC_TYPE_UNSECURE 0 +#define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */ +#define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */ +#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */ + __u8 bEncryptionValue; /* use in SET_ENCRYPTION */ + __u8 bAuthKeyIndex; +} __attribute__((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_BOS: group of device-level capabilities */ +struct usb_bos_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __le16 wTotalLength; + __u8 bNumDeviceCaps; +} __attribute__((packed)); + +#define USB_DT_BOS_SIZE 5 +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */ +struct usb_dev_cap_header { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; +} __attribute__((packed)); + +#define USB_CAP_TYPE_WIRELESS_USB 1 + +struct usb_wireless_cap_descriptor { /* Ultra Wide Band */ + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + + __u8 bmAttributes; +#define USB_WIRELESS_P2P_DRD (1 << 1) +#define USB_WIRELESS_BEACON_MASK (3 << 2) +#define USB_WIRELESS_BEACON_SELF (1 << 2) +#define USB_WIRELESS_BEACON_DIRECTED (2 << 2) +#define USB_WIRELESS_BEACON_NONE (3 << 2) + __le16 wPHYRates; /* bit rates, Mbps */ +#define USB_WIRELESS_PHY_53 (1 << 0) /* always set */ +#define USB_WIRELESS_PHY_80 (1 << 1) +#define USB_WIRELESS_PHY_107 (1 << 2) /* always set */ +#define USB_WIRELESS_PHY_160 (1 << 3) +#define USB_WIRELESS_PHY_200 (1 << 4) /* always set */ +#define USB_WIRELESS_PHY_320 (1 << 5) +#define USB_WIRELESS_PHY_400 (1 << 6) +#define USB_WIRELESS_PHY_480 (1 << 7) + __u8 bmTFITXPowerInfo; /* TFI power levels */ + __u8 bmFFITXPowerInfo; /* FFI power levels */ + __le16 bmBandGroup; + __u8 bReserved; +} __attribute__((packed)); + +/* USB 2.0 Extension descriptor */ +#define USB_CAP_TYPE_EXT 2 + +struct usb_ext_cap_descriptor { /* Link Power Management */ + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + __le32 bmAttributes; +#define USB_LPM_SUPPORT (1 << 1) /* supports LPM */ +#define USB_BESL_SUPPORT (1 << 2) /* supports BESL */ +#define USB_BESL_BASELINE_VALID (1 << 3) /* Baseline BESL valid*/ +#define USB_BESL_DEEP_VALID (1 << 4) /* Deep BESL valid */ +#define USB_GET_BESL_BASELINE(p) (((p) & (0xf << 8)) >> 8) +#define USB_GET_BESL_DEEP(p) (((p) & (0xf << 12)) >> 12) +} __attribute__((packed)); + +#define USB_DT_USB_EXT_CAP_SIZE 7 + +/* + * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB + * specific device level capabilities + */ +#define USB_SS_CAP_TYPE 3 +struct usb_ss_cap_descriptor { /* Link Power Management */ + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + __u8 bmAttributes; +#define USB_LTM_SUPPORT (1 << 1) /* supports LTM */ + __le16 wSpeedSupported; +#define USB_LOW_SPEED_OPERATION (1) /* Low speed operation */ +#define USB_FULL_SPEED_OPERATION (1 << 1) /* Full speed operation */ +#define USB_HIGH_SPEED_OPERATION (1 << 2) /* High speed operation */ +#define USB_5GBPS_OPERATION (1 << 3) /* Operation at 5Gbps */ + __u8 bFunctionalitySupport; + __u8 bU1devExitLat; + __le16 bU2DevExitLat; +} __attribute__((packed)); + +#define USB_DT_USB_SS_CAP_SIZE 10 + +/* + * Container ID Capability descriptor: Defines the instance unique ID used to + * identify the instance across all operating modes + */ +#define CONTAINER_ID_TYPE 4 +struct usb_ss_container_id_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; + __u8 bReserved; + __u8 ContainerID[16]; /* 128-bit number */ +} __attribute__((packed)); + +#define USB_DT_USB_SS_CONTN_ID_SIZE 20 +/*-------------------------------------------------------------------------*/ + +/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with + * each endpoint descriptor for a wireless device + */ +struct usb_wireless_ep_comp_descriptor { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bMaxBurst; + __u8 bMaxSequence; + __le16 wMaxStreamDelay; + __le16 wOverTheAirPacketSize; + __u8 bOverTheAirInterval; + __u8 bmCompAttributes; +#define USB_ENDPOINT_SWITCH_MASK 0x03 /* in bmCompAttributes */ +#define USB_ENDPOINT_SWITCH_NO 0 +#define USB_ENDPOINT_SWITCH_SWITCH 1 +#define USB_ENDPOINT_SWITCH_SCALE 2 +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless + * host and a device for connection set up, mutual authentication, and + * exchanging short lived session keys. The handshake depends on a CC. + */ +struct usb_handshake { + __u8 bMessageNumber; + __u8 bStatus; + __u8 tTKID[3]; + __u8 bReserved; + __u8 CDID[16]; + __u8 nonce[16]; + __u8 MIC[8]; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC). + * A CC may also be set up using non-wireless secure channels (including + * wired USB!), and some devices may support CCs with multiple hosts. + */ +struct usb_connection_context { + __u8 CHID[16]; /* persistent host id */ + __u8 CDID[16]; /* device id (unique w/in host context) */ + __u8 CK[16]; /* connection key */ +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB 2.0 defines three speeds, here's how Linux identifies them */ + +enum usb_device_speed { + USB_SPEED_UNKNOWN = 0, /* enumerating */ + USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ + USB_SPEED_HIGH, /* usb 2.0 */ + USB_SPEED_WIRELESS, /* wireless (usb 2.5) */ + USB_SPEED_SUPER, /* usb 3.0 */ +}; + + +enum usb_device_state { + /* NOTATTACHED isn't in the USB spec, and this state acts + * the same as ATTACHED ... but it's clearer this way. + */ + USB_STATE_NOTATTACHED = 0, + + /* chapter 9 and authentication (wireless) device states */ + USB_STATE_ATTACHED, + USB_STATE_POWERED, /* wired */ + USB_STATE_RECONNECTING, /* auth */ + USB_STATE_UNAUTHENTICATED, /* auth */ + USB_STATE_DEFAULT, /* limited function */ + USB_STATE_ADDRESS, + USB_STATE_CONFIGURED, /* most functions */ + + USB_STATE_SUSPENDED + + /* NOTE: there are actually four different SUSPENDED + * states, returning to POWERED, DEFAULT, ADDRESS, or + * CONFIGURED respectively when SOF tokens flow again. + * At this level there's no difference between L1 and L2 + * suspend states. (L2 being original USB 1.1 suspend.) + */ +}; + +enum usb3_link_state { + USB3_LPM_U0 = 0, + USB3_LPM_U1, + USB3_LPM_U2, + USB3_LPM_U3 +}; + +/* + * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1. + * 0xff means the parent hub will accept transitions to U1, but will not + * initiate a transition. + * + * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to + * U1 after that many microseconds. Timeouts of 0x80 to 0xFE are reserved + * values. + * + * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2. + * 0xff means the parent hub will accept transitions to U2, but will not + * initiate a transition. + * + * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to + * U2 after N*256 microseconds. Therefore a U2 timeout value of 0x1 means a U2 + * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means + * 65.024ms. + */ +#define USB3_LPM_DISABLED 0x0 +#define USB3_LPM_U1_MAX_TIMEOUT 0x7F +#define USB3_LPM_U2_MAX_TIMEOUT 0xFE +#define USB3_LPM_DEVICE_INITIATED 0xFF + +struct usb_set_sel_req { + __u8 u1_sel; + __u8 u1_pel; + __le16 u2_sel; + __le16 u2_pel; +} __attribute__ ((packed)); + +/* + * The Set System Exit Latency control transfer provides one byte each for + * U1 SEL and U1 PEL, so the max exit latency is 0xFF. U2 SEL and U2 PEL each + * are two bytes long. + */ +#define USB3_LPM_MAX_U1_SEL_PEL 0xFF +#define USB3_LPM_MAX_U2_SEL_PEL 0xFFFF + +/*-------------------------------------------------------------------------*/ + +/* + * As per USB compliance update, a device that is actively drawing + * more than 100mA from USB must report itself as bus-powered in + * the GetStatus(DEVICE) call. + * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34 + */ +#define USB_SELF_POWER_VBUS_MAX_DRAW 100 + +#endif /* _UAPI__LINUX_USB_CH9_H */ diff --git a/include/uapi/linux/usb/functionfs.h b/include/uapi/linux/usb/functionfs.h new file mode 100644 index 00000000000..d6b01283f85 --- /dev/null +++ b/include/uapi/linux/usb/functionfs.h @@ -0,0 +1,169 @@ +#ifndef _UAPI__LINUX_FUNCTIONFS_H__ +#define _UAPI__LINUX_FUNCTIONFS_H__ + + +#include <linux/types.h> +#include <linux/ioctl.h> + +#include <linux/usb/ch9.h> + + +enum { + FUNCTIONFS_DESCRIPTORS_MAGIC = 1, + FUNCTIONFS_STRINGS_MAGIC = 2 +}; + + +#ifndef __KERNEL__ + +/* Descriptor of an non-audio endpoint */ +struct usb_endpoint_descriptor_no_audio { + __u8 bLength; + __u8 bDescriptorType; + + __u8 bEndpointAddress; + __u8 bmAttributes; + __le16 wMaxPacketSize; + __u8 bInterval; +} __attribute__((packed)); + + +/* + * All numbers must be in little endian order. + */ + +struct usb_functionfs_descs_head { + __le32 magic; + __le32 length; + __le32 fs_count; + __le32 hs_count; +} __attribute__((packed)); + +/* + * Descriptors format: + * + * | off | name | type | description | + * |-----+-----------+--------------+--------------------------------------| + * | 0 | magic | LE32 | FUNCTIONFS_{FS,HS}_DESCRIPTORS_MAGIC | + * | 4 | length | LE32 | length of the whole data chunk | + * | 8 | fs_count | LE32 | number of full-speed descriptors | + * | 12 | hs_count | LE32 | number of high-speed descriptors | + * | 16 | fs_descrs | Descriptor[] | list of full-speed descriptors | + * | | hs_descrs | Descriptor[] | list of high-speed descriptors | + * + * descs are just valid USB descriptors and have the following format: + * + * | off | name | type | description | + * |-----+-----------------+------+--------------------------| + * | 0 | bLength | U8 | length of the descriptor | + * | 1 | bDescriptorType | U8 | descriptor type | + * | 2 | payload | | descriptor's payload | + */ + +struct usb_functionfs_strings_head { + __le32 magic; + __le32 length; + __le32 str_count; + __le32 lang_count; +} __attribute__((packed)); + +/* + * Strings format: + * + * | off | name | type | description | + * |-----+------------+-----------------------+----------------------------| + * | 0 | magic | LE32 | FUNCTIONFS_STRINGS_MAGIC | + * | 4 | length | LE32 | length of the data chunk | + * | 8 | str_count | LE32 | number of strings | + * | 12 | lang_count | LE32 | number of languages | + * | 16 | stringtab | StringTab[lang_count] | table of strings per lang | + * + * For each language there is one stringtab entry (ie. there are lang_count + * stringtab entires). Each StringTab has following format: + * + * | off | name | type | description | + * |-----+---------+-------------------+------------------------------------| + * | 0 | lang | LE16 | language code | + * | 2 | strings | String[str_count] | array of strings in given language | + * + * For each string there is one strings entry (ie. there are str_count + * string entries). Each String is a NUL terminated string encoded in + * UTF-8. + */ + +#endif + + +/* + * Events are delivered on the ep0 file descriptor, when the user mode driver + * reads from this file descriptor after writing the descriptors. Don't + * stop polling this descriptor. + */ + +enum usb_functionfs_event_type { + FUNCTIONFS_BIND, + FUNCTIONFS_UNBIND, + + FUNCTIONFS_ENABLE, + FUNCTIONFS_DISABLE, + + FUNCTIONFS_SETUP, + + FUNCTIONFS_SUSPEND, + FUNCTIONFS_RESUME +}; + +/* NOTE: this structure must stay the same size and layout on + * both 32-bit and 64-bit kernels. + */ +struct usb_functionfs_event { + union { + /* SETUP: packet; DATA phase i/o precedes next event + *(setup.bmRequestType & USB_DIR_IN) flags direction */ + struct usb_ctrlrequest setup; + } __attribute__((packed)) u; + + /* enum usb_functionfs_event_type */ + __u8 type; + __u8 _pad[3]; +} __attribute__((packed)); + + +/* Endpoint ioctls */ +/* The same as in gadgetfs */ + +/* IN transfers may be reported to the gadget driver as complete + * when the fifo is loaded, before the host reads the data; + * OUT transfers may be reported to the host's "client" driver as + * complete when they're sitting in the FIFO unread. + * THIS returns how many bytes are "unclaimed" in the endpoint fifo + * (needed for precise fault handling, when the hardware allows it) + */ +#define FUNCTIONFS_FIFO_STATUS _IO('g', 1) + +/* discards any unclaimed data in the fifo. */ +#define FUNCTIONFS_FIFO_FLUSH _IO('g', 2) + +/* resets endpoint halt+toggle; used to implement set_interface. + * some hardware (like pxa2xx) can't support this. + */ +#define FUNCTIONFS_CLEAR_HALT _IO('g', 3) + +/* Specific for functionfs */ + +/* + * Returns reverse mapping of an interface. Called on EP0. If there + * is no such interface returns -EDOM. If function is not active + * returns -ENODEV. + */ +#define FUNCTIONFS_INTERFACE_REVMAP _IO('g', 128) + +/* + * Returns real bEndpointAddress of an endpoint. If function is not + * active returns -ENODEV. + */ +#define FUNCTIONFS_ENDPOINT_REVMAP _IO('g', 129) + + + +#endif /* _UAPI__LINUX_FUNCTIONFS_H__ */ diff --git a/include/linux/usb/g_printer.h b/include/uapi/linux/usb/g_printer.h index 6178fde50f7..6178fde50f7 100644 --- a/include/linux/usb/g_printer.h +++ b/include/uapi/linux/usb/g_printer.h diff --git a/include/linux/usb/gadgetfs.h b/include/uapi/linux/usb/gadgetfs.h index 0bb12e0d4f8..0bb12e0d4f8 100644 --- a/include/linux/usb/gadgetfs.h +++ b/include/uapi/linux/usb/gadgetfs.h diff --git a/include/linux/usb/midi.h b/include/uapi/linux/usb/midi.h index c8c52e3c91d..c8c52e3c91d 100644 --- a/include/linux/usb/midi.h +++ b/include/uapi/linux/usb/midi.h diff --git a/include/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index c045ae12556..c045ae12556 100644 --- a/include/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h diff --git a/include/linux/usb/video.h b/include/uapi/linux/usb/video.h index 3b3b95e01f7..3b3b95e01f7 100644 --- a/include/linux/usb/video.h +++ b/include/uapi/linux/usb/video.h diff --git a/include/xen/Kbuild b/include/xen/Kbuild deleted file mode 100644 index e69de29bb2d..00000000000 --- a/include/xen/Kbuild +++ /dev/null diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index aecee9d112c..694dcaf266e 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -170,7 +170,7 @@ gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr, unmap->dev_bus_addr = 0; } -int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, +int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes, unsigned long max_nr_gframes, void **__shared); int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes, diff --git a/include/xen/hvm.h b/include/xen/hvm.h index b193fa2f9fd..13e43e41637 100644 --- a/include/xen/hvm.h +++ b/include/xen/hvm.h @@ -5,6 +5,36 @@ #include <xen/interface/hvm/params.h> #include <asm/xen/hypercall.h> +static const char *param_name(int op) +{ +#define PARAM(x) [HVM_PARAM_##x] = #x + static const char *const names[] = { + PARAM(CALLBACK_IRQ), + PARAM(STORE_PFN), + PARAM(STORE_EVTCHN), + PARAM(PAE_ENABLED), + PARAM(IOREQ_PFN), + PARAM(BUFIOREQ_PFN), + PARAM(TIMER_MODE), + PARAM(HPET_ENABLED), + PARAM(IDENT_PT), + PARAM(DM_DOMAIN), + PARAM(ACPI_S_STATE), + PARAM(VM86_TSS), + PARAM(VPT_ALIGN), + PARAM(CONSOLE_PFN), + PARAM(CONSOLE_EVTCHN), + }; +#undef PARAM + + if (op >= ARRAY_SIZE(names)) + return "unknown"; + + if (!names[op]) + return "reserved"; + + return names[op]; +} static inline int hvm_get_parameter(int idx, uint64_t *value) { struct xen_hvm_param xhv; @@ -14,8 +44,8 @@ static inline int hvm_get_parameter(int idx, uint64_t *value) xhv.index = idx; r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv); if (r < 0) { - printk(KERN_ERR "Cannot get hvm parameter %d: %d!\n", - idx, r); + printk(KERN_ERR "Cannot get hvm parameter %s (%d): %d!\n", + param_name(idx), idx, r); return r; } *value = xhv.value; diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h index f9f8b975ae7..e40fae9bf11 100644 --- a/include/xen/interface/grant_table.h +++ b/include/xen/interface/grant_table.h @@ -310,7 +310,7 @@ struct gnttab_setup_table { uint32_t nr_frames; /* OUT parameters. */ int16_t status; /* GNTST_* */ - GUEST_HANDLE(ulong) frame_list; + GUEST_HANDLE(xen_pfn_t) frame_list; }; DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table); diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index b66d04ce695..90712e2072d 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h @@ -179,28 +179,8 @@ struct xen_add_to_physmap { }; DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap); -/* - * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error - * code on failure. This call only works for auto-translated guests. - */ -#define XENMEM_translate_gpfn_list 8 -struct xen_translate_gpfn_list { - /* Which domain to translate for? */ - domid_t domid; - - /* Length of list. */ - xen_ulong_t nr_gpfns; - - /* List of GPFNs to translate. */ - GUEST_HANDLE(ulong) gpfn_list; - - /* - * Output list to contain MFN translations. May be the same as the input - * list (in which case each input GPFN is overwritten with the output MFN). - */ - GUEST_HANDLE(ulong) mfn_list; -}; -DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list); +/*** REMOVED ***/ +/*#define XENMEM_translate_gpfn_list 8*/ /* * Returns the pseudo-physical memory map as it was when the domain diff --git a/init/main.c b/init/main.c index 9cf77ab138a..e33e09df3cb 100644 --- a/init/main.c +++ b/init/main.c @@ -442,9 +442,11 @@ void __init __weak smp_setup_processor_id(void) { } +# if THREAD_SIZE >= PAGE_SIZE void __init __weak thread_info_cache_init(void) { } +#endif /* * Set up kernel memory allocators diff --git a/kernel/Makefile b/kernel/Makefile index 0dfeca4324e..86e3285ae7e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -174,10 +174,8 @@ signing_key.priv signing_key.x509: x509.genkey @echo "###" @echo "### If this takes a long time, you might wish to run rngd in the" @echo "### background to keep the supply of entropy topped up. It" - @echo "### needs to be run as root, and should use a hardware random" - @echo "### number generator if one is available, eg:" - @echo "###" - @echo "### rngd -r /dev/hwrandom" + @echo "### needs to be run as root, and uses a hardware random" + @echo "### number generator if one is available." @echo "###" openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \ -x509 -config x509.genkey \ diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 13774b3b39a..f24f724620d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1962,9 +1962,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp, * trading it for newcg is protected by cgroup_mutex, we're safe to drop * it here; it will be freed under RCU. */ - put_css_set(oldcg); - set_bit(CGRP_RELEASABLE, &oldcgrp->flags); + put_css_set(oldcg); } /** @@ -4815,31 +4814,20 @@ static const struct file_operations proc_cgroupstats_operations = { * * A pointer to the shared css_set was automatically copied in * fork.c by dup_task_struct(). However, we ignore that copy, since - * it was not made under the protection of RCU, cgroup_mutex or - * threadgroup_change_begin(), so it might no longer be a valid - * cgroup pointer. cgroup_attach_task() might have already changed - * current->cgroups, allowing the previously referenced cgroup - * group to be removed and freed. - * - * Outside the pointer validity we also need to process the css_set - * inheritance between threadgoup_change_begin() and - * threadgoup_change_end(), this way there is no leak in any process - * wide migration performed by cgroup_attach_proc() that could otherwise - * miss a thread because it is too early or too late in the fork stage. + * it was not made under the protection of RCU or cgroup_mutex, so + * might no longer be a valid cgroup pointer. cgroup_attach_task() might + * have already changed current->cgroups, allowing the previously + * referenced cgroup group to be removed and freed. * * At the point that cgroup_fork() is called, 'current' is the parent * task, and the passed argument 'child' points to the child task. */ void cgroup_fork(struct task_struct *child) { - /* - * We don't need to task_lock() current because current->cgroups - * can't be changed concurrently here. The parent obviously hasn't - * exited and called cgroup_exit(), and we are synchronized against - * cgroup migration through threadgroup_change_begin(). - */ + task_lock(current); child->cgroups = current->cgroups; get_css_set(child->cgroups); + task_unlock(current); INIT_LIST_HEAD(&child->cg_list); } @@ -4895,19 +4883,10 @@ void cgroup_post_fork(struct task_struct *child) */ if (use_task_css_set_links) { write_lock(&css_set_lock); - if (list_empty(&child->cg_list)) { - /* - * It's safe to use child->cgroups without task_lock() - * here because we are protected through - * threadgroup_change_begin() against concurrent - * css_set change in cgroup_task_migrate(). Also - * the task can't exit at that point until - * wake_up_new_task() is called, so we are protected - * against cgroup_exit() setting child->cgroup to - * init_css_set. - */ + task_lock(child); + if (list_empty(&child->cg_list)) list_add(&child->cg_list, &child->cgroups->tasks); - } + task_unlock(child); write_unlock(&css_set_lock); } } diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 98256bc71ee..5cc4e7e42e6 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -78,15 +78,23 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; */ static atomic_t uprobe_events = ATOMIC_INIT(0); +/* Have a copy of original instruction */ +#define UPROBE_COPY_INSN 0 +/* Dont run handlers when first register/ last unregister in progress*/ +#define UPROBE_RUN_HANDLER 1 +/* Can skip singlestep */ +#define UPROBE_SKIP_SSTEP 2 + struct uprobe { struct rb_node rb_node; /* node in the rb tree */ atomic_t ref; struct rw_semaphore consumer_rwsem; + struct mutex copy_mutex; /* TODO: kill me and UPROBE_COPY_INSN */ struct list_head pending_list; struct uprobe_consumer *consumers; struct inode *inode; /* Also hold a ref to inode */ loff_t offset; - int flags; + unsigned long flags; struct arch_uprobe arch; }; @@ -100,17 +108,12 @@ struct uprobe { */ static bool valid_vma(struct vm_area_struct *vma, bool is_register) { - if (!vma->vm_file) - return false; - - if (!is_register) - return true; + vm_flags_t flags = VM_HUGETLB | VM_MAYEXEC | VM_SHARED; - if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) - == (VM_READ|VM_EXEC)) - return true; + if (is_register) + flags |= VM_WRITE; - return false; + return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC; } static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset) @@ -193,19 +196,44 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn) return *insn == UPROBE_SWBP_INSN; } +static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode) +{ + void *kaddr = kmap_atomic(page); + memcpy(opcode, kaddr + (vaddr & ~PAGE_MASK), UPROBE_SWBP_INSN_SIZE); + kunmap_atomic(kaddr); +} + +static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode) +{ + uprobe_opcode_t old_opcode; + bool is_swbp; + + copy_opcode(page, vaddr, &old_opcode); + is_swbp = is_swbp_insn(&old_opcode); + + if (is_swbp_insn(new_opcode)) { + if (is_swbp) /* register: already installed? */ + return 0; + } else { + if (!is_swbp) /* unregister: was it changed by us? */ + return 0; + } + + return 1; +} + /* * NOTE: * Expect the breakpoint instruction to be the smallest size instruction for * the architecture. If an arch has variable length instruction and the * breakpoint instruction is not of the smallest length instruction - * supported by that architecture then we need to modify read_opcode / + * supported by that architecture then we need to modify is_swbp_at_addr and * write_opcode accordingly. This would never be a problem for archs that * have fixed length instructions. */ /* * write_opcode - write the opcode at a given virtual address. - * @auprobe: arch breakpointing information. * @mm: the probed process address space. * @vaddr: the virtual address to store the opcode. * @opcode: opcode to be written at @vaddr. @@ -216,8 +244,8 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn) * For mm @mm, write the opcode at @vaddr. * Return 0 (success) or a negative errno. */ -static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, - unsigned long vaddr, uprobe_opcode_t opcode) +static int write_opcode(struct mm_struct *mm, unsigned long vaddr, + uprobe_opcode_t opcode) { struct page *old_page, *new_page; void *vaddr_old, *vaddr_new; @@ -226,10 +254,14 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, retry: /* Read the page with vaddr into memory */ - ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma); + ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma); if (ret <= 0) return ret; + ret = verify_opcode(old_page, vaddr, &opcode); + if (ret <= 0) + goto put_old; + ret = -ENOMEM; new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr); if (!new_page) @@ -264,63 +296,6 @@ put_old: } /** - * read_opcode - read the opcode at a given virtual address. - * @mm: the probed process address space. - * @vaddr: the virtual address to read the opcode. - * @opcode: location to store the read opcode. - * - * Called with mm->mmap_sem held (for read and with a reference to - * mm. - * - * For mm @mm, read the opcode at @vaddr and store it in @opcode. - * Return 0 (success) or a negative errno. - */ -static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode) -{ - struct page *page; - void *vaddr_new; - int ret; - - ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); - if (ret <= 0) - return ret; - - vaddr_new = kmap_atomic(page); - vaddr &= ~PAGE_MASK; - memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE); - kunmap_atomic(vaddr_new); - - put_page(page); - - return 0; -} - -static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) -{ - uprobe_opcode_t opcode; - int result; - - if (current->mm == mm) { - pagefault_disable(); - result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, - sizeof(opcode)); - pagefault_enable(); - - if (likely(result == 0)) - goto out; - } - - result = read_opcode(mm, vaddr, &opcode); - if (result) - return result; -out: - if (is_swbp_insn(&opcode)) - return 1; - - return 0; -} - -/** * set_swbp - store breakpoint at a given address. * @auprobe: arch specific probepoint information. * @mm: the probed process address space. @@ -331,18 +306,7 @@ out: */ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) { - int result; - /* - * See the comment near uprobes_hash(). - */ - result = is_swbp_at_addr(mm, vaddr); - if (result == 1) - return 0; - - if (result) - return result; - - return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN); + return write_opcode(mm, vaddr, UPROBE_SWBP_INSN); } /** @@ -357,16 +321,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned int __weak set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) { - int result; - - result = is_swbp_at_addr(mm, vaddr); - if (!result) - return -EINVAL; - - if (result != 1) - return result; - - return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); + return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); } static int match_uprobe(struct uprobe *l, struct uprobe *r) @@ -473,7 +428,7 @@ static struct uprobe *insert_uprobe(struct uprobe *uprobe) spin_unlock(&uprobes_treelock); /* For now assume that the instruction need not be single-stepped */ - uprobe->flags |= UPROBE_SKIP_SSTEP; + __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags); return u; } @@ -495,6 +450,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset) uprobe->inode = igrab(inode); uprobe->offset = offset; init_rwsem(&uprobe->consumer_rwsem); + mutex_init(&uprobe->copy_mutex); /* add to uprobes_tree, sorted on inode:offset */ cur_uprobe = insert_uprobe(uprobe); @@ -515,7 +471,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs) { struct uprobe_consumer *uc; - if (!(uprobe->flags & UPROBE_RUN_HANDLER)) + if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags)) return; down_read(&uprobe->consumer_rwsem); @@ -621,29 +577,43 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp) return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); } -/* - * How mm->uprobes_state.count gets updated - * uprobe_mmap() increments the count if - * - it successfully adds a breakpoint. - * - it cannot add a breakpoint, but sees that there is a underlying - * breakpoint (via a is_swbp_at_addr()). - * - * uprobe_munmap() decrements the count if - * - it sees a underlying breakpoint, (via is_swbp_at_addr) - * (Subsequent uprobe_unregister wouldnt find the breakpoint - * unless a uprobe_mmap kicks in, since the old vma would be - * dropped just after uprobe_munmap.) - * - * uprobe_register increments the count if: - * - it successfully adds a breakpoint. - * - * uprobe_unregister decrements the count if: - * - it sees a underlying breakpoint and removes successfully. - * (via is_swbp_at_addr) - * (Subsequent uprobe_munmap wouldnt find the breakpoint - * since there is no underlying breakpoint after the - * breakpoint removal.) - */ +static int prepare_uprobe(struct uprobe *uprobe, struct file *file, + struct mm_struct *mm, unsigned long vaddr) +{ + int ret = 0; + + if (test_bit(UPROBE_COPY_INSN, &uprobe->flags)) + return ret; + + mutex_lock(&uprobe->copy_mutex); + if (test_bit(UPROBE_COPY_INSN, &uprobe->flags)) + goto out; + + ret = copy_insn(uprobe, file); + if (ret) + goto out; + + ret = -ENOTSUPP; + if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) + goto out; + + ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); + if (ret) + goto out; + + /* write_opcode() assumes we don't cross page boundary */ + BUG_ON((uprobe->offset & ~PAGE_MASK) + + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); + + smp_wmb(); /* pairs with rmb() in find_active_uprobe() */ + set_bit(UPROBE_COPY_INSN, &uprobe->flags); + + out: + mutex_unlock(&uprobe->copy_mutex); + + return ret; +} + static int install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, struct vm_area_struct *vma, unsigned long vaddr) @@ -661,24 +631,9 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, if (!uprobe->consumers) return 0; - if (!(uprobe->flags & UPROBE_COPY_INSN)) { - ret = copy_insn(uprobe, vma->vm_file); - if (ret) - return ret; - - if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) - return -ENOTSUPP; - - ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); - if (ret) - return ret; - - /* write_opcode() assumes we don't cross page boundary */ - BUG_ON((uprobe->offset & ~PAGE_MASK) + - UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); - - uprobe->flags |= UPROBE_COPY_INSN; - } + ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr); + if (ret) + return ret; /* * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(), @@ -697,15 +652,15 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, return ret; } -static void +static int remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr) { /* can happen if uprobe_register() fails */ if (!test_bit(MMF_HAS_UPROBES, &mm->flags)) - return; + return 0; set_bit(MMF_RECALC_UPROBES, &mm->flags); - set_orig_insn(&uprobe->arch, mm, vaddr); + return set_orig_insn(&uprobe->arch, mm, vaddr); } /* @@ -820,7 +775,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register) struct mm_struct *mm = info->mm; struct vm_area_struct *vma; - if (err) + if (err && is_register) goto free; down_write(&mm->mmap_sem); @@ -836,7 +791,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register) if (is_register) err = install_breakpoint(uprobe, mm, vma, info->vaddr); else - remove_breakpoint(uprobe, mm, info->vaddr); + err |= remove_breakpoint(uprobe, mm, info->vaddr); unlock: up_write(&mm->mmap_sem); @@ -893,13 +848,15 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer * mutex_lock(uprobes_hash(inode)); uprobe = alloc_uprobe(inode, offset); - if (uprobe && !consumer_add(uprobe, uc)) { + if (!uprobe) { + ret = -ENOMEM; + } else if (!consumer_add(uprobe, uc)) { ret = __uprobe_register(uprobe); if (ret) { uprobe->consumers = NULL; __uprobe_unregister(uprobe); } else { - uprobe->flags |= UPROBE_RUN_HANDLER; + set_bit(UPROBE_RUN_HANDLER, &uprobe->flags); } } @@ -932,7 +889,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume if (consumer_del(uprobe, uc)) { if (!uprobe->consumers) { __uprobe_unregister(uprobe); - uprobe->flags &= ~UPROBE_RUN_HANDLER; + clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags); } } @@ -1393,10 +1350,11 @@ bool uprobe_deny_signal(void) */ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs) { - if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) - return true; - - uprobe->flags &= ~UPROBE_SKIP_SSTEP; + if (test_bit(UPROBE_SKIP_SSTEP, &uprobe->flags)) { + if (arch_uprobe_skip_sstep(&uprobe->arch, regs)) + return true; + clear_bit(UPROBE_SKIP_SSTEP, &uprobe->flags); + } return false; } @@ -1419,6 +1377,30 @@ static void mmf_recalc_uprobes(struct mm_struct *mm) clear_bit(MMF_HAS_UPROBES, &mm->flags); } +static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr) +{ + struct page *page; + uprobe_opcode_t opcode; + int result; + + pagefault_disable(); + result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, + sizeof(opcode)); + pagefault_enable(); + + if (likely(result == 0)) + goto out; + + result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL); + if (result < 0) + return result; + + copy_opcode(page, vaddr, &opcode); + put_page(page); + out: + return is_swbp_insn(&opcode); +} + static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp) { struct mm_struct *mm = current->mm; @@ -1489,38 +1471,41 @@ static void handle_swbp(struct pt_regs *regs) } return; } + /* + * TODO: move copy_insn/etc into _register and remove this hack. + * After we hit the bp, _unregister + _register can install the + * new and not-yet-analyzed uprobe at the same address, restart. + */ + smp_rmb(); /* pairs with wmb() in install_breakpoint() */ + if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) + goto restart; utask = current->utask; if (!utask) { utask = add_utask(); /* Cannot allocate; re-execute the instruction. */ if (!utask) - goto cleanup_ret; + goto restart; } - utask->active_uprobe = uprobe; + handler_chain(uprobe, regs); - if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs)) - goto cleanup_ret; + if (can_skip_sstep(uprobe, regs)) + goto out; - utask->state = UTASK_SSTEP; if (!pre_ssout(uprobe, regs, bp_vaddr)) { arch_uprobe_enable_step(&uprobe->arch); + utask->active_uprobe = uprobe; + utask->state = UTASK_SSTEP; return; } -cleanup_ret: - if (utask) { - utask->active_uprobe = NULL; - utask->state = UTASK_RUNNING; - } - if (!(uprobe->flags & UPROBE_SKIP_SSTEP)) - - /* - * cannot singlestep; cannot skip instruction; - * re-execute the instruction. - */ - instruction_pointer_set(regs, bp_vaddr); - +restart: + /* + * cannot singlestep; cannot skip instruction; + * re-execute the instruction. + */ + instruction_pointer_set(regs, bp_vaddr); +out: put_uprobe(uprobe); } @@ -1552,13 +1537,12 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs) } /* - * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag. (and on - * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and - * allows the thread to return from interrupt. + * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag and + * allows the thread to return from interrupt. After that handle_swbp() + * sets utask->active_uprobe. * - * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and - * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from - * interrupt. + * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag + * and allows the thread to return from interrupt. * * While returning to userspace, thread notices the TIF_UPROBE flag and calls * uprobe_notify_resume(). @@ -1567,11 +1551,13 @@ void uprobe_notify_resume(struct pt_regs *regs) { struct uprobe_task *utask; + clear_thread_flag(TIF_UPROBE); + utask = current->utask; - if (!utask || utask->state == UTASK_BP_HIT) - handle_swbp(regs); - else + if (utask && utask->active_uprobe) handle_singlestep(utask, regs); + else + handle_swbp(regs); } /* @@ -1580,17 +1566,10 @@ void uprobe_notify_resume(struct pt_regs *regs) */ int uprobe_pre_sstep_notifier(struct pt_regs *regs) { - struct uprobe_task *utask; - if (!current->mm || !test_bit(MMF_HAS_UPROBES, ¤t->mm->flags)) return 0; - utask = current->utask; - if (utask) - utask->state = UTASK_BP_HIT; - set_thread_flag(TIF_UPROBE); - return 1; } diff --git a/kernel/exit.c b/kernel/exit.c index 346616c0092..f9275e2c7c2 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -322,43 +322,6 @@ kill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent) } } -/** - * reparent_to_kthreadd - Reparent the calling kernel thread to kthreadd - * - * If a kernel thread is launched as a result of a system call, or if - * it ever exits, it should generally reparent itself to kthreadd so it - * isn't in the way of other processes and is correctly cleaned up on exit. - * - * The various task state such as scheduling policy and priority may have - * been inherited from a user process, so we reset them to sane values here. - * - * NOTE that reparent_to_kthreadd() gives the caller full capabilities. - */ -static void reparent_to_kthreadd(void) -{ - write_lock_irq(&tasklist_lock); - - ptrace_unlink(current); - /* Reparent to init */ - current->real_parent = current->parent = kthreadd_task; - list_move_tail(¤t->sibling, ¤t->real_parent->children); - - /* Set the exit signal to SIGCHLD so we signal init on exit */ - current->exit_signal = SIGCHLD; - - if (task_nice(current) < 0) - set_user_nice(current, 0); - /* cpus_allowed? */ - /* rt_priority? */ - /* signals? */ - memcpy(current->signal->rlim, init_task.signal->rlim, - sizeof(current->signal->rlim)); - - atomic_inc(&init_cred.usage); - commit_creds(&init_cred); - write_unlock_irq(&tasklist_lock); -} - void __set_special_pids(struct pid *pid) { struct task_struct *curr = current->group_leader; @@ -370,13 +333,6 @@ void __set_special_pids(struct pid *pid) change_pid(curr, PIDTYPE_PGID, pid); } -static void set_special_pids(struct pid *pid) -{ - write_lock_irq(&tasklist_lock); - __set_special_pids(pid); - write_unlock_irq(&tasklist_lock); -} - /* * Let kernel threads use this to say that they allow a certain signal. * Must not be used if kthread was cloned with CLONE_SIGHAND. @@ -416,54 +372,6 @@ int disallow_signal(int sig) EXPORT_SYMBOL(disallow_signal); -/* - * Put all the gunge required to become a kernel thread without - * attached user resources in one place where it belongs. - */ - -void daemonize(const char *name, ...) -{ - va_list args; - sigset_t blocked; - - va_start(args, name); - vsnprintf(current->comm, sizeof(current->comm), name, args); - va_end(args); - - /* - * If we were started as result of loading a module, close all of the - * user space pages. We don't need them, and if we didn't close them - * they would be locked into memory. - */ - exit_mm(current); - /* - * We don't want to get frozen, in case system-wide hibernation - * or suspend transition begins right now. - */ - current->flags |= (PF_NOFREEZE | PF_KTHREAD); - - if (current->nsproxy != &init_nsproxy) { - get_nsproxy(&init_nsproxy); - switch_task_namespaces(current, &init_nsproxy); - } - set_special_pids(&init_struct_pid); - proc_clear_tty(current); - - /* Block and flush all signals */ - sigfillset(&blocked); - sigprocmask(SIG_BLOCK, &blocked, NULL); - flush_signals(current); - - /* Become as one with the init task */ - - daemonize_fs_struct(); - daemonize_descriptors(); - - reparent_to_kthreadd(); -} - -EXPORT_SYMBOL(daemonize); - #ifdef CONFIG_MM_OWNER /* * A task is exiting. If it owned this mm, find a new owner for the mm. diff --git a/kernel/fork.c b/kernel/fork.c index 8b20ab7d3aa..27a337549da 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1645,6 +1645,49 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) } #endif +#ifdef __ARCH_WANT_SYS_FORK +SYSCALL_DEFINE0(fork) +{ +#ifdef CONFIG_MMU + return do_fork(SIGCHLD, 0, current_pt_regs(), 0, NULL, NULL); +#else + /* can not support in nommu mode */ + return(-EINVAL); +#endif +} +#endif + +#ifdef __ARCH_WANT_SYS_VFORK +SYSCALL_DEFINE0(vfork) +{ + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, current_pt_regs(), + 0, NULL, NULL); +} +#endif + +#ifdef __ARCH_WANT_SYS_CLONE +#ifdef CONFIG_CLONE_BACKWARDS +SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, + int __user *, parent_tidptr, + int, tls_val, + int __user *, child_tidptr) +#elif defined(CONFIG_CLONE_BACKWARDS2) +SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags, + int __user *, parent_tidptr, + int __user *, child_tidptr, + int, tls_val) +#else +SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, + int __user *, parent_tidptr, + int __user *, child_tidptr, + int, tls_val) +#endif +{ + return do_fork(clone_flags, newsp, current_pt_regs(), 0, + parent_tidptr, child_tidptr); +} +#endif + #ifndef ARCH_MIN_MMSTRUCT_ALIGN #define ARCH_MIN_MMSTRUCT_ALIGN 0 #endif diff --git a/kernel/futex.c b/kernel/futex.c index 3717e7b306e..20ef219bbe9 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, struct futex_pi_state **ps, struct task_struct *task, int set_waiters) { - int lock_taken, ret, ownerdied = 0; + int lock_taken, ret, force_take = 0; u32 uval, newval, curval, vpid = task_pid_vnr(task); retry: @@ -755,17 +755,15 @@ retry: newval = curval | FUTEX_WAITERS; /* - * There are two cases, where a futex might have no owner (the - * owner TID is 0): OWNER_DIED. We take over the futex in this - * case. We also do an unconditional take over, when the owner - * of the futex died. - * - * This is safe as we are protected by the hash bucket lock ! + * Should we force take the futex? See below. */ - if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { - /* Keep the OWNER_DIED bit */ + if (unlikely(force_take)) { + /* + * Keep the OWNER_DIED and the WAITERS bit and set the + * new TID value. + */ newval = (curval & ~FUTEX_TID_MASK) | vpid; - ownerdied = 0; + force_take = 0; lock_taken = 1; } @@ -775,7 +773,7 @@ retry: goto retry; /* - * We took the lock due to owner died take over. + * We took the lock due to forced take over. */ if (unlikely(lock_taken)) return 1; @@ -790,20 +788,25 @@ retry: switch (ret) { case -ESRCH: /* - * No owner found for this futex. Check if the - * OWNER_DIED bit is set to figure out whether - * this is a robust futex or not. + * We failed to find an owner for this + * futex. So we have no pi_state to block + * on. This can happen in two cases: + * + * 1) The owner died + * 2) A stale FUTEX_WAITERS bit + * + * Re-read the futex value. */ if (get_futex_value_locked(&curval, uaddr)) return -EFAULT; /* - * We simply start over in case of a robust - * futex. The code above will take the futex - * and return happy. + * If the owner died or we have a stale + * WAITERS bit the owner TID in the user space + * futex is 0. */ - if (curval & FUTEX_OWNER_DIED) { - ownerdied = 1; + if (!(curval & FUTEX_TID_MASK)) { + force_take = 1; goto retry; } default: diff --git a/kernel/module-internal.h b/kernel/module-internal.h index 6114a13419b..24f9247b7d0 100644 --- a/kernel/module-internal.h +++ b/kernel/module-internal.h @@ -11,5 +11,4 @@ extern struct key *modsign_keyring; -extern int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen); +extern int mod_verify_sig(const void *mod, unsigned long *_modlen); diff --git a/kernel/module.c b/kernel/module.c index 0e2da8695f8..6e48c3a4359 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2293,12 +2293,17 @@ static void layout_symtab(struct module *mod, struct load_info *info) src = (void *)info->hdr + symsect->sh_offset; nsrc = symsect->sh_size / sizeof(*src); + /* strtab always starts with a nul, so offset 0 is the empty string. */ + strtab_size = 1; + /* Compute total space required for the core symbols' strtab. */ - for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src) - if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { - strtab_size += strlen(&info->strtab[src->st_name]) + 1; + for (ndst = i = 0; i < nsrc; i++) { + if (i == 0 || + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { + strtab_size += strlen(&info->strtab[src[i].st_name])+1; ndst++; } + } /* Append room for core symbols at end of core part. */ info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); @@ -2332,15 +2337,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) mod->core_symtab = dst = mod->module_core + info->symoffs; mod->core_strtab = s = mod->module_core + info->stroffs; src = mod->symtab; - *dst = *src; *s++ = 0; - for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { - if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) - continue; - - dst[ndst] = *src; - dst[ndst++].st_name = s - mod->core_strtab; - s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1; + for (ndst = i = 0; i < mod->num_symtab; i++) { + if (i == 0 || + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { + dst[ndst] = src[i]; + dst[ndst++].st_name = s - mod->core_strtab; + s += strlcpy(s, &mod->strtab[src[i].st_name], + KSYM_NAME_LEN) + 1; + } } mod->core_num_syms = ndst; } @@ -2421,25 +2426,17 @@ static inline void kmemleak_load_module(const struct module *mod, #ifdef CONFIG_MODULE_SIG static int module_sig_check(struct load_info *info, - const void *mod, unsigned long *len) + const void *mod, unsigned long *_len) { int err = -ENOKEY; - const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; - const void *p = mod, *end = mod + *len; - - /* Poor man's memmem. */ - while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { - if (p + markerlen > end) - break; - - if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { - const void *sig = p + markerlen; - /* Truncate module up to signature. */ - *len = p - mod; - err = mod_verify_sig(mod, *len, sig, end - sig); - break; - } - p++; + unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; + unsigned long len = *_len; + + if (len > markerlen && + memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { + /* We truncate the module to discard the signature */ + *_len -= markerlen; + err = mod_verify_sig(mod, _len); } if (!err) { diff --git a/kernel/module_signing.c b/kernel/module_signing.c index 6b09f6983ac..ea1b1df5dbb 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -183,27 +183,33 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len, /* * Verify the signature on a module. */ -int mod_verify_sig(const void *mod, unsigned long modlen, - const void *sig, unsigned long siglen) +int mod_verify_sig(const void *mod, unsigned long *_modlen) { struct public_key_signature *pks; struct module_signature ms; struct key *key; - size_t sig_len; + const void *sig; + size_t modlen = *_modlen, sig_len; int ret; - pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); + pr_devel("==>%s(,%zu)\n", __func__, modlen); - if (siglen <= sizeof(ms)) + if (modlen <= sizeof(ms)) return -EBADMSG; - memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); - siglen -= sizeof(ms); + memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); + modlen -= sizeof(ms); sig_len = be32_to_cpu(ms.sig_len); - if (sig_len >= siglen || - siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) + if (sig_len >= modlen) return -EBADMSG; + modlen -= sig_len; + if ((size_t)ms.signer_len + ms.key_id_len >= modlen) + return -EBADMSG; + modlen -= (size_t)ms.signer_len + ms.key_id_len; + + *_modlen = modlen; + sig = mod + modlen; /* For the moment, only support RSA and X.509 identifiers */ if (ms.algo != PKEY_ALGO_RSA || diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 478bad2745e..7b07cc0dfb7 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -71,12 +71,22 @@ err_alloc: return NULL; } +/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */ +#define MAX_PID_NS_LEVEL 32 + static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns) { struct pid_namespace *ns; unsigned int level = parent_pid_ns->level + 1; - int i, err = -ENOMEM; + int i; + int err; + + if (level > MAX_PID_NS_LEVEL) { + err = -EINVAL; + goto out; + } + err = -ENOMEM; ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL); if (ns == NULL) goto out; @@ -133,19 +143,26 @@ struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old return create_pid_namespace(old_ns); } -void free_pid_ns(struct kref *kref) +static void free_pid_ns(struct kref *kref) { - struct pid_namespace *ns, *parent; + struct pid_namespace *ns; ns = container_of(kref, struct pid_namespace, kref); - - parent = ns->parent; destroy_pid_namespace(ns); +} + +void put_pid_ns(struct pid_namespace *ns) +{ + struct pid_namespace *parent; - if (parent != NULL) - put_pid_ns(parent); + while (ns != &init_pid_ns) { + parent = ns->parent; + if (!kref_put(&ns->kref, free_pid_ns)) + break; + ns = parent; + } } -EXPORT_SYMBOL_GPL(free_pid_ns); +EXPORT_SYMBOL_GPL(put_pid_ns); void zap_pid_ns_processes(struct pid_namespace *pid_ns) { diff --git a/kernel/printk.c b/kernel/printk.c index 66a2ea37b57..2d607f4d179 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1890,7 +1890,6 @@ static int __cpuinit console_cpu_notify(struct notifier_block *self, switch (action) { case CPU_ONLINE: case CPU_DEAD: - case CPU_DYING: case CPU_DOWN_FAILED: case CPU_UP_CANCELED: console_lock(); diff --git a/kernel/sys.c b/kernel/sys.c index c5cb5b99cb8..e6e0ece5f6a 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1265,15 +1265,16 @@ DECLARE_RWSEM(uts_sem); * Work around broken programs that cannot handle "Linux 3.0". * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40 */ -static int override_release(char __user *release, int len) +static int override_release(char __user *release, size_t len) { int ret = 0; - char buf[65]; if (current->personality & UNAME26) { - char *rest = UTS_RELEASE; + const char *rest = UTS_RELEASE; + char buf[65] = { 0 }; int ndots = 0; unsigned v; + size_t copy; while (*rest) { if (*rest == '.' && ++ndots >= 3) @@ -1283,8 +1284,9 @@ static int override_release(char __user *release, int len) rest++; } v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40; - snprintf(buf, len, "2.6.%u%s", v, rest); - ret = copy_to_user(release, buf, len); + copy = clamp_t(size_t, len, 1, sizeof(buf)); + copy = scnprintf(buf, copy, "2.6.%u%s", v, rest); + ret = copy_to_user(release, buf, copy + 1); } return ret; } diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index b32ed0e385a..b979426d16c 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1567,6 +1567,10 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size, put_online_cpus(); } else { + /* Make sure this CPU has been intitialized */ + if (!cpumask_test_cpu(cpu_id, buffer->cpumask)) + goto out; + cpu_buffer = buffer->buffers[cpu_id]; if (nr_pages == cpu_buffer->nr_pages) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index d951daa0ca9..042d221d33c 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -2982,7 +2982,7 @@ bool cancel_delayed_work(struct delayed_work *dwork) set_work_cpu_and_clear_pending(&dwork->work, work_cpu(&dwork->work)); local_irq_restore(flags); - return true; + return ret; } EXPORT_SYMBOL(cancel_delayed_work); diff --git a/lib/dma-debug.c b/lib/dma-debug.c index b9087bff008..d84beb994f3 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c @@ -264,7 +264,7 @@ static struct dma_debug_entry *__hash_bucket_find(struct hash_bucket *bucket, match_fn match) { struct dma_debug_entry *entry, *ret = NULL; - int matches = 0, match_lvl, last_lvl = 0; + int matches = 0, match_lvl, last_lvl = -1; list_for_each_entry(entry, &bucket->list, list) { if (!match(ref, entry)) @@ -293,7 +293,7 @@ static struct dma_debug_entry *__hash_bucket_find(struct hash_bucket *bucket, } else if (match_lvl > last_lvl) { /* * We found an entry that fits better then the - * previous one + * previous one or it is the 1st match. */ last_lvl = match_lvl; ret = entry; diff --git a/lib/genalloc.c b/lib/genalloc.c index ca208a92628..54920433705 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -178,7 +178,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy struct gen_pool_chunk *chunk; int nbits = size >> pool->min_alloc_order; int nbytes = sizeof(struct gen_pool_chunk) + - (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; + BITS_TO_LONGS(nbits) * sizeof(long); chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid); if (unlikely(chunk == NULL)) diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index 678ce4f1e12..095ab157a52 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h @@ -641,7 +641,14 @@ do { \ ************** MIPS ***************** ***************************************/ #if defined(__mips__) && W_TYPE_SIZE == 32 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + UDItype __ll = (UDItype)(u) * (v); \ + w1 = __ll >> 32; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("multu %2,%3" \ : "=l" ((USItype)(w0)), \ @@ -666,7 +673,15 @@ do { \ ************** MIPS/64 ************** ***************************************/ #if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ + __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ + w1 = __ll >> 64; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("dmultu %2,%3" \ : "=l" ((UDItype)(w0)), \ diff --git a/mm/bootmem.c b/mm/bootmem.c index 434be4ae7a0..f468185b3b2 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -198,8 +198,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) int order = ilog2(BITS_PER_LONG); __free_pages_bootmem(pfn_to_page(start), order); - fixup_zone_present_pages(page_to_nid(pfn_to_page(start)), - start, start + BITS_PER_LONG); count += BITS_PER_LONG; start += BITS_PER_LONG; } else { @@ -210,9 +208,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) if (vec & 1) { page = pfn_to_page(start + off); __free_pages_bootmem(page, 0); - fixup_zone_present_pages( - page_to_nid(page), - start + off, start + off + 1); count++; } vec >>= 1; @@ -226,11 +221,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) pages = bdata->node_low_pfn - bdata->node_min_pfn; pages = bootmem_bootmap_pages(pages); count += pages; - while (pages--) { - fixup_zone_present_pages(page_to_nid(page), - page_to_pfn(page), page_to_pfn(page) + 1); + while (pages--) __free_pages_bootmem(page++, 0); - } bdebug("nid=%td released=%lx\n", bdata - bootmem_node_data, count); diff --git a/mm/compaction.c b/mm/compaction.c index 2c4ce17651d..9eef55838fc 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -346,7 +346,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc, * pages requested were isolated. If there were any failures, 0 is * returned and CMA will fail. */ - if (strict && nr_strict_required != total_isolated) + if (strict && nr_strict_required > total_isolated) total_isolated = 0; if (locked) diff --git a/mm/fremap.c b/mm/fremap.c index 3899a86851c..a0aaf0e5680 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -169,7 +169,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR)) goto out; - if (!vma->vm_ops->remap_pages) + if (!vma->vm_ops || !vma->vm_ops->remap_pages) goto out; if (start < vma->vm_start || start + size > vma->vm_end) diff --git a/mm/highmem.c b/mm/highmem.c index d517cd16a6e..2da13a5c50e 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -98,7 +98,7 @@ struct page *kmap_to_page(void *vaddr) { unsigned long addr = (unsigned long)vaddr; - if (addr >= PKMAP_ADDR(0) && addr <= PKMAP_ADDR(LAST_PKMAP)) { + if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) { int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT; return pte_page(pkmap_page_table[i]); } diff --git a/mm/huge_memory.c b/mm/huge_memory.c index a863af26c79..40f17c34b41 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -17,6 +17,7 @@ #include <linux/khugepaged.h> #include <linux/freezer.h> #include <linux/mman.h> +#include <linux/pagemap.h> #include <asm/tlb.h> #include <asm/pgalloc.h> #include "internal.h" diff --git a/mm/memblock.c b/mm/memblock.c index 931eef145af..625905523c2 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -930,6 +930,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si return memblock_overlaps_region(&memblock.reserved, base, size) >= 0; } +void __init_memblock memblock_trim_memory(phys_addr_t align) +{ + int i; + phys_addr_t start, end, orig_start, orig_end; + struct memblock_type *mem = &memblock.memory; + + for (i = 0; i < mem->cnt; i++) { + orig_start = mem->regions[i].base; + orig_end = mem->regions[i].base + mem->regions[i].size; + start = round_up(orig_start, align); + end = round_down(orig_end, align); + + if (start == orig_start && end == orig_end) + continue; + + if (start < end) { + mem->regions[i].base = start; + mem->regions[i].size = end - start; + } else { + memblock_remove_region(mem, i); + i--; + } + } +} void __init_memblock memblock_set_current_limit(phys_addr_t limit) { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 7acf43bf04a..dd39ba000b3 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1055,12 +1055,24 @@ struct lruvec *mem_cgroup_zone_lruvec(struct zone *zone, struct mem_cgroup *memcg) { struct mem_cgroup_per_zone *mz; + struct lruvec *lruvec; - if (mem_cgroup_disabled()) - return &zone->lruvec; + if (mem_cgroup_disabled()) { + lruvec = &zone->lruvec; + goto out; + } mz = mem_cgroup_zoneinfo(memcg, zone_to_nid(zone), zone_idx(zone)); - return &mz->lruvec; + lruvec = &mz->lruvec; +out: + /* + * Since a node can be onlined after the mem_cgroup was created, + * we have to be prepared to initialize lruvec->zone here; + * and if offlined then reonlined, we need to reinitialize it. + */ + if (unlikely(lruvec->zone != zone)) + lruvec->zone = zone; + return lruvec; } /* @@ -1087,9 +1099,12 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone) struct mem_cgroup_per_zone *mz; struct mem_cgroup *memcg; struct page_cgroup *pc; + struct lruvec *lruvec; - if (mem_cgroup_disabled()) - return &zone->lruvec; + if (mem_cgroup_disabled()) { + lruvec = &zone->lruvec; + goto out; + } pc = lookup_page_cgroup(page); memcg = pc->mem_cgroup; @@ -1107,7 +1122,16 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone) pc->mem_cgroup = memcg = root_mem_cgroup; mz = page_cgroup_zoneinfo(memcg, page); - return &mz->lruvec; + lruvec = &mz->lruvec; +out: + /* + * Since a node can be onlined after the mem_cgroup was created, + * we have to be prepared to initialize lruvec->zone here; + * and if offlined then reonlined, we need to reinitialize it. + */ + if (unlikely(lruvec->zone != zone)) + lruvec->zone = zone; + return lruvec; } /** @@ -1452,17 +1476,26 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg) static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) { u64 limit; - u64 memsw; limit = res_counter_read_u64(&memcg->res, RES_LIMIT); - limit += total_swap_pages << PAGE_SHIFT; - memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); /* - * If memsw is finite and limits the amount of swap space available - * to this memcg, return that limit. + * Do not consider swap space if we cannot swap due to swappiness */ - return min(limit, memsw); + if (mem_cgroup_swappiness(memcg)) { + u64 memsw; + + limit += total_swap_pages << PAGE_SHIFT; + memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); + + /* + * If memsw is finite and limits the amount of swap space + * available to this memcg, return that limit. + */ + limit = min(limit, memsw); + } + + return limit; } void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, @@ -3688,17 +3721,17 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order, static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg, int node, int zid, enum lru_list lru) { - struct mem_cgroup_per_zone *mz; + struct lruvec *lruvec; unsigned long flags, loop; struct list_head *list; struct page *busy; struct zone *zone; zone = &NODE_DATA(node)->node_zones[zid]; - mz = mem_cgroup_zoneinfo(memcg, node, zid); - list = &mz->lruvec.lists[lru]; + lruvec = mem_cgroup_zone_lruvec(zone, memcg); + list = &lruvec->lists[lru]; - loop = mz->lru_size[lru]; + loop = mem_cgroup_get_lru_size(lruvec, lru); /* give some margin against EBUSY etc...*/ loop += 256; busy = NULL; @@ -4736,7 +4769,7 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node) for (zone = 0; zone < MAX_NR_ZONES; zone++) { mz = &pn->zoneinfo[zone]; - lruvec_init(&mz->lruvec, &NODE_DATA(node)->node_zones[zone]); + lruvec_init(&mz->lruvec); mz->usage_in_excess = 0; mz->on_tree = false; mz->memcg = memcg; diff --git a/mm/memory.c b/mm/memory.c index fb135ba4aba..221fc9ffcab 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2527,9 +2527,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, int ret = 0; int page_mkwrite = 0; struct page *dirty_page = NULL; - unsigned long mmun_start; /* For mmu_notifiers */ - unsigned long mmun_end; /* For mmu_notifiers */ - bool mmun_called = false; /* For mmu_notifiers */ + unsigned long mmun_start = 0; /* For mmu_notifiers */ + unsigned long mmun_end = 0; /* For mmu_notifiers */ old_page = vm_normal_page(vma, address, orig_pte); if (!old_page) { @@ -2708,8 +2707,7 @@ gotten: goto oom_free_new; mmun_start = address & PAGE_MASK; - mmun_end = (address & PAGE_MASK) + PAGE_SIZE; - mmun_called = true; + mmun_end = mmun_start + PAGE_SIZE; mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); /* @@ -2778,7 +2776,7 @@ gotten: page_cache_release(new_page); unlock: pte_unmap_unlock(page_table, ptl); - if (mmun_called) + if (mmun_end > mmun_start) mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); if (old_page) { /* diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 56b758ae57d..e4eeacae2b9 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -106,7 +106,6 @@ static void get_page_bootmem(unsigned long info, struct page *page, void __ref put_page_bootmem(struct page *page) { unsigned long type; - struct zone *zone; type = (unsigned long) page->lru.next; BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE || @@ -117,12 +116,6 @@ void __ref put_page_bootmem(struct page *page) set_page_private(page, 0); INIT_LIST_HEAD(&page->lru); __free_pages_bootmem(page, 0); - - zone = page_zone(page); - zone_span_writelock(zone); - zone->present_pages++; - zone_span_writeunlock(zone); - totalram_pages++; } } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 0b78fb9ea65..d04a8a54c29 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1536,9 +1536,8 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len, * * Returns effective policy for a VMA at specified address. * Falls back to @task or system default policy, as necessary. - * Current or other task's task mempolicy and non-shared vma policies - * are protected by the task's mmap_sem, which must be held for read by - * the caller. + * Current or other task's task mempolicy and non-shared vma policies must be + * protected by task_lock(task) by the caller. * Shared policies [those marked as MPOL_F_SHARED] require an extra reference * count--added by the get_policy() vm_op, as appropriate--to protect against * freeing by another task. It is the caller's responsibility to free the diff --git a/mm/mmap.c b/mm/mmap.c index 2d942353d68..9a796c41e7d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -334,8 +334,10 @@ void validate_mm(struct mm_struct *mm) struct vm_area_struct *vma = mm->mmap; while (vma) { struct anon_vma_chain *avc; + vma_lock_anon_vma(vma); list_for_each_entry(avc, &vma->anon_vma_chain, same_vma) anon_vma_interval_tree_verify(avc); + vma_unlock_anon_vma(vma); vma = vma->vm_next; i++; } diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 479a1e751a7..8a5ac8c686b 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -196,28 +196,28 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn, BUG_ON(atomic_read(&mm->mm_users) <= 0); /* - * Verify that mmu_notifier_init() already run and the global srcu is - * initialized. - */ + * Verify that mmu_notifier_init() already run and the global srcu is + * initialized. + */ BUG_ON(!srcu.per_cpu_ref); + ret = -ENOMEM; + mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL); + if (unlikely(!mmu_notifier_mm)) + goto out; + if (take_mmap_sem) down_write(&mm->mmap_sem); ret = mm_take_all_locks(mm); if (unlikely(ret)) - goto out; + goto out_clean; if (!mm_has_notifiers(mm)) { - mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), - GFP_KERNEL); - if (unlikely(!mmu_notifier_mm)) { - ret = -ENOMEM; - goto out_of_mem; - } INIT_HLIST_HEAD(&mmu_notifier_mm->list); spin_lock_init(&mmu_notifier_mm->lock); mm->mmu_notifier_mm = mmu_notifier_mm; + mmu_notifier_mm = NULL; } atomic_inc(&mm->mm_count); @@ -233,12 +233,12 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn, hlist_add_head(&mn->hlist, &mm->mmu_notifier_mm->list); spin_unlock(&mm->mmu_notifier_mm->lock); -out_of_mem: mm_drop_all_locks(mm); -out: +out_clean: if (take_mmap_sem) up_write(&mm->mmap_sem); - + kfree(mmu_notifier_mm); +out: BUG_ON(atomic_read(&mm->mm_users) <= 0); return ret; } diff --git a/mm/mmzone.c b/mm/mmzone.c index 3cef80f6ac7..4596d81b89b 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -87,7 +87,7 @@ int memmap_valid_within(unsigned long pfn, } #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */ -void lruvec_init(struct lruvec *lruvec, struct zone *zone) +void lruvec_init(struct lruvec *lruvec) { enum lru_list lru; @@ -95,8 +95,4 @@ void lruvec_init(struct lruvec *lruvec, struct zone *zone) for_each_lru(lru) INIT_LIST_HEAD(&lruvec->lists[lru]); - -#ifdef CONFIG_MEMCG - lruvec->zone = zone; -#endif } diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 714d5d65047..bd82f6b3141 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -116,8 +116,6 @@ static unsigned long __init __free_memory_core(phys_addr_t start, return 0; __free_pages_memory(start_pfn, end_pfn); - fixup_zone_present_pages(pfn_to_nid(start >> PAGE_SHIFT), - start_pfn, end_pfn); return end_pfn - start_pfn; } @@ -128,7 +126,6 @@ unsigned long __init free_low_memory_core_early(int nodeid) phys_addr_t start, end, size; u64 i; - reset_zone_present_pages(); for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) count += __free_memory_core(start, end); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bb90971182b..bcb72c6e2b2 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1405,7 +1405,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) mt = get_pageblock_migratetype(page); if (unlikely(mt != MIGRATE_ISOLATE)) - __mod_zone_freepage_state(zone, -(1UL << order), mt); + __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt); if (alloc_order != order) expand(zone, page, alloc_order, order, @@ -1809,10 +1809,10 @@ static void __paginginit init_zone_allows_reclaim(int nid) int i; for_each_online_node(i) - if (node_distance(nid, i) <= RECLAIM_DISTANCE) { + if (node_distance(nid, i) <= RECLAIM_DISTANCE) node_set(i, NODE_DATA(nid)->reclaim_nodes); + else zone_reclaim_mode = 1; - } } #else /* CONFIG_NUMA */ @@ -4505,7 +4505,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, zone->zone_pgdat = pgdat; zone_pcp_init(zone); - lruvec_init(&zone->lruvec, zone); + lruvec_init(&zone->lruvec); if (!size) continue; @@ -5825,7 +5825,7 @@ int alloc_contig_range(unsigned long start, unsigned long end, ret = start_isolate_page_range(pfn_max_align_down(start), pfn_max_align_up(end), migratetype); if (ret) - goto done; + return ret; ret = __alloc_contig_migrate_range(&cc, start, end); if (ret) @@ -6098,37 +6098,3 @@ void dump_page(struct page *page) dump_page_flags(page->flags); mem_cgroup_print_bad_page(page); } - -/* reset zone->present_pages */ -void reset_zone_present_pages(void) -{ - struct zone *z; - int i, nid; - - for_each_node_state(nid, N_HIGH_MEMORY) { - for (i = 0; i < MAX_NR_ZONES; i++) { - z = NODE_DATA(nid)->node_zones + i; - z->present_pages = 0; - } - } -} - -/* calculate zone's present pages in buddy system */ -void fixup_zone_present_pages(int nid, unsigned long start_pfn, - unsigned long end_pfn) -{ - struct zone *z; - unsigned long zone_start_pfn, zone_end_pfn; - int i; - - for (i = 0; i < MAX_NR_ZONES; i++) { - z = NODE_DATA(nid)->node_zones + i; - zone_start_pfn = z->zone_start_pfn; - zone_end_pfn = zone_start_pfn + z->spanned_pages; - - /* if the two regions intersect */ - if (!(zone_start_pfn >= end_pfn || zone_end_pfn <= start_pfn)) - z->present_pages += min(end_pfn, zone_end_pfn) - - max(start_pfn, zone_start_pfn); - } -} diff --git a/mm/rmap.c b/mm/rmap.c index 7df7984d476..2ee1ef0f317 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -56,6 +56,7 @@ #include <linux/mmu_notifier.h> #include <linux/migrate.h> #include <linux/hugetlb.h> +#include <linux/backing-dev.h> #include <asm/tlbflush.h> @@ -926,11 +927,8 @@ int page_mkclean(struct page *page) if (page_mapped(page)) { struct address_space *mapping = page_mapping(page); - if (mapping) { + if (mapping) ret = page_mkclean_file(mapping, page); - if (page_test_and_clear_dirty(page_to_pfn(page), 1)) - ret = 1; - } } return ret; @@ -1116,6 +1114,7 @@ void page_add_file_rmap(struct page *page) */ void page_remove_rmap(struct page *page) { + struct address_space *mapping = page_mapping(page); bool anon = PageAnon(page); bool locked; unsigned long flags; @@ -1138,8 +1137,19 @@ void page_remove_rmap(struct page *page) * this if the page is anon, so about to be freed; but perhaps * not if it's in swapcache - there might be another pte slot * containing the swap entry, but page not yet written to swap. + * + * And we can skip it on file pages, so long as the filesystem + * participates in dirty tracking; but need to catch shm and tmpfs + * and ramfs pages which have been modified since creation by read + * fault. + * + * Note that mapping must be decided above, before decrementing + * mapcount (which luckily provides a barrier): once page is unmapped, + * it could be truncated and page->mapping reset to NULL at any moment. + * Note also that we are relying on page_mapping(page) to set mapping + * to &swapper_space when PageSwapCache(page). */ - if ((!anon || PageSwapCache(page)) && + if (mapping && !mapping_cap_account_dirty(mapping) && page_test_and_clear_dirty(page_to_pfn(page), 1)) set_page_dirty(page); /* diff --git a/mm/shmem.c b/mm/shmem.c index 67afba5117f..89341b658bd 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -643,7 +643,7 @@ static void shmem_evict_inode(struct inode *inode) kfree(info->symlink); simple_xattrs_free(&info->xattrs); - BUG_ON(inode->i_blocks); + WARN_ON(inode->i_blocks); shmem_free_inode(inode->i_sb); clear_inode(inode); } @@ -1145,8 +1145,20 @@ repeat: if (!error) { error = shmem_add_to_page_cache(page, mapping, index, gfp, swp_to_radix_entry(swap)); - /* We already confirmed swap, and make no allocation */ - VM_BUG_ON(error); + /* + * We already confirmed swap under page lock, and make + * no memory allocation here, so usually no possibility + * of error; but free_swap_and_cache() only trylocks a + * page, so it is just possible that the entry has been + * truncated or holepunched since swap was confirmed. + * shmem_undo_range() will have done some of the + * unaccounting, now delete_from_swap_cache() will do + * the rest (including mem_cgroup_uncharge_swapcache). + * Reset swap.val? No, leave it so "failed" goes back to + * "repeat": reading a hole and writing should succeed. + */ + if (error) + delete_from_swap_cache(page); } if (error) goto failed; diff --git a/mm/slob.c b/mm/slob.c index a08e4681fd0..1e921c5e957 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -429,7 +429,7 @@ static __always_inline void * __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller) { unsigned int *m; - int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); + int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); void *ret; gfp &= gfp_allowed_mask; @@ -502,7 +502,7 @@ void kfree(const void *block) sp = virt_to_page(block); if (PageSlab(sp)) { - int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); + int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); slob_free(m, *m + align); } else @@ -521,7 +521,7 @@ size_t ksize(const void *block) sp = virt_to_page(block); if (PageSlab(sp)) { - int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); + int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); return SLOB_UNITS(*m) * SLOB_UNIT; } else diff --git a/mm/swapfile.c b/mm/swapfile.c index 71cd288b200..f91a25547ff 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1494,9 +1494,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) BUG_ON(!current->mm); pathname = getname(specialfile); - err = PTR_ERR(pathname); if (IS_ERR(pathname)) - goto out; + return PTR_ERR(pathname); victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0); err = PTR_ERR(victim); @@ -1608,6 +1607,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) out_dput: filp_close(victim, NULL); out: + putname(pathname); return err; } diff --git a/mm/vmscan.c b/mm/vmscan.c index 2624edcfb42..48550c66f1f 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1760,28 +1760,6 @@ static bool in_reclaim_compaction(struct scan_control *sc) return false; } -#ifdef CONFIG_COMPACTION -/* - * If compaction is deferred for sc->order then scale the number of pages - * reclaimed based on the number of consecutive allocation failures - */ -static unsigned long scale_for_compaction(unsigned long pages_for_compaction, - struct lruvec *lruvec, struct scan_control *sc) -{ - struct zone *zone = lruvec_zone(lruvec); - - if (zone->compact_order_failed <= sc->order) - pages_for_compaction <<= zone->compact_defer_shift; - return pages_for_compaction; -} -#else -static unsigned long scale_for_compaction(unsigned long pages_for_compaction, - struct lruvec *lruvec, struct scan_control *sc) -{ - return pages_for_compaction; -} -#endif - /* * Reclaim/compaction is used for high-order allocation requests. It reclaims * order-0 pages before compacting the zone. should_continue_reclaim() returns @@ -1829,9 +1807,6 @@ static inline bool should_continue_reclaim(struct lruvec *lruvec, * inactive lists are large enough, continue reclaiming */ pages_for_compaction = (2UL << sc->order); - - pages_for_compaction = scale_for_compaction(pages_for_compaction, - lruvec, sc); inactive_lru_pages = get_lru_size(lruvec, LRU_INACTIVE_FILE); if (nr_swap_pages > 0) inactive_lru_pages += get_lru_size(lruvec, LRU_INACTIVE_ANON); @@ -3017,6 +2992,8 @@ static int kswapd(void *p) &balanced_classzone_idx); } } + + current->reclaim_state = NULL; return 0; } diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 9096bcb0813..ee070722a3a 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -463,7 +463,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ - return NOTIFY_BAD; + if (vlan_uses_dev(dev)) + return NOTIFY_BAD; + break; case NETDEV_NOTIFY_PEERS: case NETDEV_BONDING_FAILOVER: diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index fbbf1fa0094..65e06abe023 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -366,6 +366,13 @@ EXPORT_SYMBOL(vlan_vids_del_by_dev); bool vlan_uses_dev(const struct net_device *dev) { - return rtnl_dereference(dev->vlan_info) ? true : false; + struct vlan_info *vlan_info; + + ASSERT_RTNL(); + + vlan_info = rtnl_dereference(dev->vlan_info); + if (!vlan_info) + return false; + return vlan_info->grp.nr_vlan_devs ? true : false; } EXPORT_SYMBOL(vlan_uses_dev); diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 0a9084ad19a..fd8d5afec0d 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1167,6 +1167,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) uint16_t crc; unsigned long entrytime; + spin_lock_init(&bat_priv->bla.bcast_duplist_lock); + batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n"); /* setting claim destination address */ @@ -1210,8 +1212,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) /** * batadv_bla_check_bcast_duplist * @bat_priv: the bat priv with all the soft interface information - * @bcast_packet: originator mac address - * @hdr_size: maximum length of the frame + * @bcast_packet: encapsulated broadcast frame plus batman header + * @bcast_packet_len: length of encapsulated broadcast frame plus batman header * * check if it is on our broadcast list. Another gateway might * have sent the same packet because it is connected to the same backbone, @@ -1224,20 +1226,22 @@ int batadv_bla_init(struct batadv_priv *bat_priv) */ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, struct batadv_bcast_packet *bcast_packet, - int hdr_size) + int bcast_packet_len) { - int i, length, curr; + int i, length, curr, ret = 0; uint8_t *content; uint16_t crc; struct batadv_bcast_duplist_entry *entry; - length = hdr_size - sizeof(*bcast_packet); + length = bcast_packet_len - sizeof(*bcast_packet); content = (uint8_t *)bcast_packet; content += sizeof(*bcast_packet); /* calculate the crc ... */ crc = crc16(0, content, length); + spin_lock_bh(&bat_priv->bla.bcast_duplist_lock); + for (i = 0; i < BATADV_DUPLIST_SIZE; i++) { curr = (bat_priv->bla.bcast_duplist_curr + i); curr %= BATADV_DUPLIST_SIZE; @@ -1259,9 +1263,12 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, /* this entry seems to match: same crc, not too old, * and from another gw. therefore return 1 to forbid it. */ - return 1; + ret = 1; + goto out; } - /* not found, add a new entry (overwrite the oldest entry) */ + /* not found, add a new entry (overwrite the oldest entry) + * and allow it, its the first occurence. + */ curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1); curr %= BATADV_DUPLIST_SIZE; entry = &bat_priv->bla.bcast_duplist[curr]; @@ -1270,8 +1277,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); bat_priv->bla.bcast_duplist_curr = curr; - /* allow it, its the first occurence. */ - return 0; +out: + spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock); + + return ret; } diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 939fc01371d..376b4cc6ca8 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1124,8 +1124,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, spin_unlock_bh(&orig_node->bcast_seqno_lock); + /* keep skb linear for crc calculation */ + if (skb_linearize(skb) < 0) + goto out; + + bcast_packet = (struct batadv_bcast_packet *)skb->data; + /* check whether this has been sent by another originator before */ - if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) + if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len)) goto out; /* rebroadcast packet */ diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index b9a28d2dd3e..ce0684a1fc8 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -325,6 +325,12 @@ void batadv_interface_rx(struct net_device *soft_iface, soft_iface->last_rx = jiffies; + /* Let the bridge loop avoidance check the packet. If will + * not handle it, we can safely push it up. + */ + if (batadv_bla_rx(bat_priv, skb, vid, is_bcast)) + goto out; + if (orig_node) batadv_tt_add_temporary_global_entry(bat_priv, orig_node, ethhdr->h_source); @@ -332,12 +338,6 @@ void batadv_interface_rx(struct net_device *soft_iface, if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest)) goto dropped; - /* Let the bridge loop avoidance check the packet. If will - * not handle it, we can safely push it up. - */ - if (batadv_bla_rx(bat_priv, skb, vid, is_bcast)) - goto out; - netif_rx(skb); goto out; diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 112edd371b2..baae7158580 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -769,6 +769,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, */ tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP; + /* the change can carry possible "attribute" flags like the + * TT_CLIENT_WIFI, therefore they have to be copied in the + * client entry + */ + tt_global_entry->common.flags |= flags; + /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only * one originator left in the list and we previously received a * delete + roaming change for this originator. @@ -1496,7 +1502,7 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, memcpy(tt_change->addr, tt_common_entry->addr, ETH_ALEN); - tt_change->flags = BATADV_NO_FLAGS; + tt_change->flags = tt_common_entry->flags; tt_count++; tt_change++; @@ -2450,6 +2456,13 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, { bool ret = false; + /* if the originator is a backbone node (meaning it belongs to the same + * LAN of this node) the temporary client must not be added because to + * reach such destination the node must use the LAN instead of the mesh + */ + if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig)) + goto out; + if (!batadv_tt_global_add(bat_priv, orig_node, addr, BATADV_TT_CLIENT_TEMP, atomic_read(&orig_node->last_ttvn))) diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 2ed82caacdc..ac1e07a8045 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -205,6 +205,8 @@ struct batadv_priv_bla { struct batadv_hashtable *backbone_hash; struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; int bcast_duplist_curr; + /* protects bcast_duplist and bcast_duplist_curr */ + spinlock_t bcast_duplist_lock; struct batadv_bla_claim_dst claim_dest; struct delayed_work work; }; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 8a0ce706aeb..a0a2f97b9c6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1754,11 +1754,11 @@ int hci_register_dev(struct hci_dev *hdev) if (hdev->dev_type != HCI_AMP) set_bit(HCI_AUTO_OFF, &hdev->dev_flags); - schedule_work(&hdev->power_on); - hci_notify(hdev, HCI_DEV_REG); hci_dev_hold(hdev); + schedule_work(&hdev->power_on); + return id; err_wqueue: diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index aa2ea0a8142..91de4239da6 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -326,7 +326,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, struct hci_dev *d; size_t rp_len; u16 count; - int i, err; + int err; BT_DBG("sock %p", sk); @@ -347,9 +347,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, return -ENOMEM; } - rp->num_controllers = cpu_to_le16(count); - - i = 0; + count = 0; list_for_each_entry(d, &hci_dev_list, list) { if (test_bit(HCI_SETUP, &d->dev_flags)) continue; @@ -357,10 +355,13 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, if (!mgmt_valid_hdev(d)) continue; - rp->index[i++] = cpu_to_le16(d->id); + rp->index[count++] = cpu_to_le16(d->id); BT_DBG("Added hci%u", d->id); } + rp->num_controllers = cpu_to_le16(count); + rp_len = sizeof(*rp) + (2 * count); + read_unlock(&hci_dev_list_lock); err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp, @@ -1366,6 +1367,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, continue; list_del(&match->list); + kfree(match); found++; } diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8c225ef349c..a5923378bdf 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -32,6 +32,8 @@ #define SMP_TIMEOUT msecs_to_jiffies(30000) +#define AUTH_REQ_MASK 0x07 + static inline void swap128(u8 src[16], u8 dst[16]) { int i; @@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, req->max_key_size = SMP_MAX_ENC_KEY_SIZE; req->init_key_dist = 0; req->resp_key_dist = dist_keys; - req->auth_req = authreq; + req->auth_req = (authreq & AUTH_REQ_MASK); return; } @@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; rsp->init_key_dist = 0; rsp->resp_key_dist = req->resp_key_dist & dist_keys; - rsp->auth_req = authreq; + rsp->auth_req = (authreq & AUTH_REQ_MASK); } static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) @@ -265,7 +267,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags); mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, - hcon->dst_type, reason); + hcon->dst_type, HCI_ERROR_AUTH_FAILURE); cancel_delayed_work_sync(&conn->security_timer); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 159aa8bef9e..3ef1759403b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2300,10 +2300,11 @@ restart: mutex_unlock(&con->mutex); return; } else { - con->ops->put(con); dout("con_work %p FAILED to back off %lu\n", con, con->delay); + set_bit(CON_FLAG_BACKOFF, &con->flags); } + goto done; } if (con->state == CON_STATE_STANDBY) { @@ -2749,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) msg = con->ops->alloc_msg(con, hdr, skip); mutex_lock(&con->mutex); if (con->state != CON_STATE_OPEN) { - ceph_msg_put(msg); + if (msg) + ceph_msg_put(msg); return -EAGAIN; } con->in_msg = msg; diff --git a/net/core/dev.c b/net/core/dev.c index 09cb3f6dc40..c0946cb2b35 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1666,7 +1666,7 @@ static inline int deliver_skb(struct sk_buff *skb, static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) { - if (ptype->af_packet_priv == NULL) + if (!ptype->af_packet_priv || !skb->sk) return false; if (ptype->id_match) @@ -2818,8 +2818,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, if (unlikely(tcpu != next_cpu) && (tcpu == RPS_NO_CPU || !cpu_online(tcpu) || ((int)(per_cpu(softnet_data, tcpu).input_queue_head - - rflow->last_qtail)) >= 0)) + rflow->last_qtail)) >= 0)) { + tcpu = next_cpu; rflow = set_rps_cpu(dev, skb, rflow, next_cpu); + } if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) { *rflowp = rflow; diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 87cc17db2d5..b079c7bbc15 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -319,7 +319,8 @@ int dev_addr_del(struct net_device *dev, const unsigned char *addr, */ ha = list_first_entry(&dev->dev_addrs.list, struct netdev_hw_addr, list); - if (ha->addr == dev->dev_addr && ha->refcount == 1) + if (!memcmp(ha->addr, addr, dev->addr_len) && + ha->type == addr_type && ha->refcount == 1) return -ENOENT; err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index bcf02f608cb..017a8bacfb2 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -429,6 +429,17 @@ static struct attribute_group netstat_group = { .name = "statistics", .attrs = netstat_attrs, }; + +#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) +static struct attribute *wireless_attrs[] = { + NULL +}; + +static struct attribute_group wireless_group = { + .name = "wireless", + .attrs = wireless_attrs, +}; +#endif #endif /* CONFIG_SYSFS */ #ifdef CONFIG_RPS @@ -1409,6 +1420,15 @@ int netdev_register_kobject(struct net_device *net) groups++; *groups++ = &netstat_group; + +#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) + if (net->ieee80211_ptr) + *groups++ = &wireless_group; +#if IS_ENABLED(CONFIG_WIRELESS_EXT) + else if (net->wireless_handlers) + *groups++ = &wireless_group; +#endif +#endif #endif /* CONFIG_SYSFS */ error = device_add(dev); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 76d4c2c3c89..fad649ae4de 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2192,7 +2192,8 @@ static int nlmsg_populate_fdb(struct sk_buff *skb, goto skip; err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, - portid, seq, 0, NTF_SELF); + portid, seq, + RTM_NEWNEIGH, NTF_SELF); if (err < 0) return err; skip: diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6e04b1fa11f..4007c1437fd 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3379,10 +3379,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding); void kfree_skb_partial(struct sk_buff *skb, bool head_stolen) { - if (head_stolen) + if (head_stolen) { + skb_release_head_state(skb); kmem_cache_free(skbuff_head_cache, skb); - else + } else { __kfree_skb(skb); + } } EXPORT_SYMBOL(kfree_skb_partial); diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 535584c00f9..0c34bfabc11 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -892,13 +892,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, struct inet_diag_req_v2 *r, struct nlattr *bc) { const struct inet_diag_handler *handler; + int err = 0; handler = inet_diag_lock_handler(r->sdiag_protocol); if (!IS_ERR(handler)) handler->dump(skb, cb, r, bc); + else + err = PTR_ERR(handler); inet_diag_unlock_handler(handler); - return skb->len; + return err ? : skb->len; } static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 5eea4a81104..14bbfcf717a 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock *sk, int level, struct inet_sock *inet = inet_sk(sk); int val = 0, err; - if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | - (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | - (1<<IP_RETOPTS) | (1<<IP_TOS) | - (1<<IP_TTL) | (1<<IP_HDRINCL) | - (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | - (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) | - (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) | - (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) || - optname == IP_UNICAST_IF || - optname == IP_MULTICAST_TTL || - optname == IP_MULTICAST_ALL || - optname == IP_MULTICAST_LOOP || - optname == IP_RECVORIGDSTADDR) { + switch (optname) { + case IP_PKTINFO: + case IP_RECVTTL: + case IP_RECVOPTS: + case IP_RECVTOS: + case IP_RETOPTS: + case IP_TOS: + case IP_TTL: + case IP_HDRINCL: + case IP_MTU_DISCOVER: + case IP_RECVERR: + case IP_ROUTER_ALERT: + case IP_FREEBIND: + case IP_PASSSEC: + case IP_TRANSPARENT: + case IP_MINTTL: + case IP_NODEFRAG: + case IP_UNICAST_IF: + case IP_MULTICAST_TTL: + case IP_MULTICAST_ALL: + case IP_MULTICAST_LOOP: + case IP_RECVORIGDSTADDR: if (optlen >= sizeof(int)) { if (get_user(val, (int __user *) optval)) return -EFAULT; diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 1831092f999..858fddf6482 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -338,12 +338,17 @@ static int vti_rcv(struct sk_buff *skb) if (tunnel != NULL) { struct pcpu_tstats *tstats; + if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) + return -1; + tstats = this_cpu_ptr(tunnel->dev->tstats); u64_stats_update_begin(&tstats->syncp); tstats->rx_packets++; tstats->rx_bytes += skb->len; u64_stats_update_end(&tstats->syncp); + skb->mark = 0; + secpath_reset(skb); skb->dev = tunnel->dev; return 1; } diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index 9e0ffaf1d94..a82047282db 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c @@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum, if ((ct->tuplehash[dir].tuple.src.u3.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) || - (ct->tuplehash[dir].tuple.src.u.all != + (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && + ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all)) if (nf_xfrm_me_harder(skb, AF_INET) < 0) ret = NF_DROP; @@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum, } #ifdef CONFIG_XFRM else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && + ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && ct->tuplehash[dir].tuple.dst.u.all != ct->tuplehash[!dir].tuple.src.u.all) if (nf_xfrm_me_harder(skb, AF_INET) < 0) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 432f4bb7723..df251424d81 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1163,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, spin_lock_bh(&fnhe_lock); if (daddr == fnhe->fnhe_daddr) { - struct rtable *orig; - + struct rtable *orig = rcu_dereference(fnhe->fnhe_rth); + if (orig && rt_is_expired(orig)) { + fnhe->fnhe_gw = 0; + fnhe->fnhe_pmtu = 0; + fnhe->fnhe_expires = 0; + } if (fnhe->fnhe_pmtu) { unsigned long expires = fnhe->fnhe_expires; unsigned long diff = expires - jiffies; @@ -1181,7 +1185,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, } else if (!rt->rt_gateway) rt->rt_gateway = daddr; - orig = rcu_dereference(fnhe->fnhe_rth); rcu_assign_pointer(fnhe->fnhe_rth, rt); if (orig) rt_free(orig); @@ -1782,6 +1785,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, if (dev_out->flags & IFF_LOOPBACK) flags |= RTCF_LOCAL; + do_cache = true; if (type == RTN_BROADCAST) { flags |= RTCF_BROADCAST | RTCF_LOCAL; fi = NULL; @@ -1790,6 +1794,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr, fl4->flowi4_proto)) flags &= ~RTCF_LOCAL; + else + do_cache = false; /* If multicast route do not exist use * default one, but do not gateway in this case. * Yes, it is hack. @@ -1799,8 +1805,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, } fnhe = NULL; - do_cache = fi != NULL; - if (fi) { + do_cache &= fi != NULL; + if (do_cache) { struct rtable __rcu **prth; struct fib_nh *nh = &FIB_RES_NH(*res); @@ -2594,7 +2600,7 @@ int __init ip_rt_init(void) pr_err("Unable to create route proc files\n"); #ifdef CONFIG_XFRM xfrm_init(); - xfrm4_init(ip_rt_max_size); + xfrm4_init(); #endif rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f32c02e2a54..083092e3aed 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -549,14 +549,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) !tp->urg_data || before(tp->urg_seq, tp->copied_seq) || !before(tp->urg_seq, tp->rcv_nxt)) { - struct sk_buff *skb; answ = tp->rcv_nxt - tp->copied_seq; - /* Subtract 1, if FIN is in queue. */ - skb = skb_peek_tail(&sk->sk_receive_queue); - if (answ && skb) - answ -= tcp_hdr(skb)->fin; + /* Subtract 1, if FIN was received */ + if (answ && sock_flag(sk, SOCK_DONE)) + answ--; } else answ = tp->urg_seq - tp->copied_seq; release_sock(sk); @@ -1214,7 +1212,7 @@ new_segment: wait_for_sndbuf: set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); wait_for_memory: - if (copied && likely(!tp->repair)) + if (copied) tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH); if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) @@ -1225,7 +1223,7 @@ wait_for_memory: } out: - if (copied && likely(!tp->repair)) + if (copied) tcp_push(sk, flags, mss_now, tp->nonagle); release_sock(sk); return copied + copied_syn; @@ -2766,6 +2764,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) info->tcpi_options |= TCPI_OPT_ECN; if (tp->ecn_flags & TCP_ECN_SEEN) info->tcpi_options |= TCPI_OPT_ECN_SEEN; + if (tp->syn_data_acked) + info->tcpi_options |= TCPI_OPT_SYN_DATA; info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto); info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato); diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 813b43a76fe..834857f3c87 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c @@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, .tcpv_rttcnt = ca->cnt_rtt, .tcpv_minrtt = ca->base_rtt, }; - u64 t = ca->sum_rtt; - do_div(t, ca->cnt_rtt); - info.tcpv_rtt = t; + if (info.tcpv_rttcnt > 0) { + u64 t = ca->sum_rtt; + do_div(t, info.tcpv_rttcnt); + info.tcpv_rtt = t; + } nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); } } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 432c36649db..609ff98aeb4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size) struct tcphdr *th; bool fragstolen; + if (size == 0) + return 0; + skb = alloc_skb(size + sizeof(*th), sk->sk_allocation); if (!skb) goto err; @@ -5310,11 +5313,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, goto discard; } - /* ts_recent update must be made after we are sure that the packet - * is in window. - */ - tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); - /* step 3: check security and precedence [ignored] */ /* step 4: Check for a SYN @@ -5549,6 +5547,11 @@ step5: if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) goto discard; + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + tcp_rcv_rtt_measure_ts(sk, skb); /* Process urgent data. */ @@ -5646,6 +5649,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, tcp_rearm_rto(sk); return true; } + tp->syn_data_acked = tp->syn_data; return false; } @@ -5963,7 +5967,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, req = tp->fastopen_rsk; if (req != NULL) { - BUG_ON(sk->sk_state != TCP_SYN_RECV && + WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && sk->sk_state != TCP_FIN_WAIT1); if (tcp_check_req(sk, skb, req, NULL, true) == NULL) @@ -6052,7 +6056,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, * ACK we have received, this would have acknowledged * our SYNACK so stop the SYNACK timer. */ - if (acceptable && req != NULL) { + if (req != NULL) { + /* Return RST if ack_seq is invalid. + * Note that RFC793 only says to generate a + * DUPACK for it but for TCP Fast Open it seems + * better to treat this case like TCP_SYN_RECV + * above. + */ + if (!acceptable) + return 1; /* We no longer need the request sock. */ reqsk_fastopen_remove(sk, req, false); tcp_rearm_rto(sk); @@ -6118,6 +6130,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } else goto discard; + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + /* step 6: check the URG bit */ tcp_urg(sk, skb, th); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ef998b008a5..0c4a6435560 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1461,6 +1461,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, skb_set_owner_r(skb, child); __skb_queue_tail(&child->sk_receive_queue, skb); tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; + tp->syn_data_acked = 1; } sk->sk_data_ready(sk, 0); bh_unlock_sock(child); diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 4c752a6e0bc..f696d7c2e9f 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -1,7 +1,6 @@ #include <linux/rcupdate.h> #include <linux/spinlock.h> #include <linux/jiffies.h> -#include <linux/bootmem.h> #include <linux/module.h> #include <linux/cache.h> #include <linux/slab.h> @@ -9,6 +8,7 @@ #include <linux/tcp.h> #include <linux/hash.h> #include <linux/tcp_metrics.h> +#include <linux/vmalloc.h> #include <net/inet_connection_sock.h> #include <net/net_namespace.h> @@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr, } a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6]; if (a) { - if (nla_len(a) != sizeof(sizeof(struct in6_addr))) + if (nla_len(a) != sizeof(struct in6_addr)) return -EINVAL; addr->family = AF_INET6; memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6)); @@ -1034,7 +1034,10 @@ static int __net_init tcp_net_metrics_init(struct net *net) net->ipv4.tcp_metrics_hash_log = order_base_2(slots); size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log; - net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL); + net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); + if (!net->ipv4.tcp_metrics_hash) + net->ipv4.tcp_metrics_hash = vzalloc(size); + if (!net->ipv4.tcp_metrics_hash) return -ENOMEM; @@ -1055,7 +1058,10 @@ static void __net_exit tcp_net_metrics_exit(struct net *net) tm = next; } } - kfree(net->ipv4.tcp_metrics_hash); + if (is_vmalloc_addr(net->ipv4.tcp_metrics_hash)) + vfree(net->ipv4.tcp_metrics_hash); + else + kfree(net->ipv4.tcp_metrics_hash); } static __net_initdata struct pernet_operations tcp_net_metrics_ops = { diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 27536ba16c9..a7302d974f3 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -510,6 +510,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, newtp->rx_opt.mss_clamp = req->mss; TCP_ECN_openreq_child(newtp, req); newtp->fastopen_rsk = NULL; + newtp->syn_data_acked = 0; TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS); } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index cfe6ffe1c17..2798706cb06 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1986,6 +1986,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, tso_segs = tcp_init_tso_segs(sk, skb, mss_now); BUG_ON(!tso_segs); + if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) + goto repair; /* Skip network transmission */ + cwnd_quota = tcp_cwnd_test(tp, skb); if (!cwnd_quota) break; @@ -2026,6 +2029,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp))) break; +repair: /* Advance the send_head. This one is sent out. * This call will increment packets_out. */ diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index fc04711e80c..d47c1b4421a 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk) return; } if (tp->fastopen_rsk) { - BUG_ON(sk->sk_state != TCP_SYN_RECV && - sk->sk_state != TCP_FIN_WAIT1); + WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV && + sk->sk_state != TCP_FIN_WAIT1); tcp_fastopen_synack_timer(sk); /* Before we receive ACK to our SYN-ACK don't retransmit * anything else (e.g., data or FIN segments). diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 05c5ab8d983..3be0ac2c192 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -279,19 +279,8 @@ static void __exit xfrm4_policy_fini(void) xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo); } -void __init xfrm4_init(int rt_max_size) +void __init xfrm4_init(void) { - /* - * Select a default value for the gc_thresh based on the main route - * table hash size. It seems to me the worst case scenario is when - * we have ipsec operating in transport mode, in which we create a - * dst_entry per socket. The xfrm gc algorithm starts trying to remove - * entries at gc_thresh, and prevents new allocations as 2*gc_thresh - * so lets set an initial xfrm gc_thresh value at the rt_max_size/2. - * That will let us store an ipsec connection per route table entry, - * and start cleaning when were 1/2 full - */ - xfrm4_dst_ops.gc_thresh = rt_max_size/2; dst_entries_init(&xfrm4_dst_ops); xfrm4_state_init(); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d7c56f8a5b4..0424e4e2741 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3064,14 +3064,15 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos) struct hlist_node *n; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; /* sync with offset */ if (p < state->offset) { p++; continue; } state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } /* prepare for next bucket */ @@ -3089,18 +3090,20 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct hlist_node *n = &ifa->addr_lst; hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } while (++state->bucket < IN6_ADDR_HSIZE) { state->offset = 0; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } } diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index c4f934176ca..30647857a37 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -252,6 +252,7 @@ struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu) return NULL; dst->ops->update_pmtu(dst, sk, NULL, mtu); - return inet6_csk_route_socket(sk, &fl6); + dst = inet6_csk_route_socket(sk, &fl6); + return IS_ERR(dst) ? NULL : dst; } EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu); diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 0185679c5f5..d5cb3c4e66f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1633,9 +1633,9 @@ static size_t ip6gre_get_size(const struct net_device *dev) /* IFLA_GRE_OKEY */ nla_total_size(4) + /* IFLA_GRE_LOCAL */ - nla_total_size(4) + + nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GRE_REMOTE */ - nla_total_size(4) + + nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GRE_TTL */ nla_total_size(1) + /* IFLA_GRE_TOS */ @@ -1659,8 +1659,8 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev) nla_put_be16(skb, IFLA_GRE_OFLAGS, p->o_flags) || nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || - nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->raddr) || - nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->laddr) || + nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->laddr) || + nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->raddr) || nla_put_u8(skb, IFLA_GRE_TTL, p->hop_limit) || /*nla_put_u8(skb, IFLA_GRE_TOS, t->priority) ||*/ nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) || diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index ba6d13d1f1e..e02faed6d17 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -827,6 +827,7 @@ pref_skip_coa: if (val < 0 || val > 255) goto e_inval; np->min_hopcount = val; + retv = 0; break; case IPV6_DONTFRAG: np->dontfrag = valbool; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index ff36194a71a..2edce30ef73 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -535,7 +535,7 @@ static void ndisc_send_unsol_na(struct net_device *dev) { struct inet6_dev *idev; struct inet6_ifaddr *ifa; - struct in6_addr mcaddr; + struct in6_addr mcaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT; idev = in6_dev_get(dev); if (!idev) @@ -543,7 +543,6 @@ static void ndisc_send_unsol_na(struct net_device *dev) read_lock_bh(&idev->lock); list_for_each_entry(ifa, &idev->addr_list, if_list) { - addrconf_addr_solict_mult(&ifa->addr, &mcaddr); ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr, /*router=*/ !!idev->cnf.forwarding, /*solicited=*/ false, /*override=*/ true, diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index e418bd6350a..d57dab17a18 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c @@ -186,7 +186,8 @@ nf_nat_ipv6_out(unsigned int hooknum, if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3) || - (ct->tuplehash[dir].tuple.src.u.all != + (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && + ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all)) if (nf_xfrm_me_harder(skb, AF_INET6) < 0) ret = NF_DROP; @@ -222,6 +223,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum, } #ifdef CONFIG_XFRM else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && + ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && ct->tuplehash[dir].tuple.dst.u.all != ct->tuplehash[!dir].tuple.src.u.all) if (nf_xfrm_me_harder(skb, AF_INET6)) diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 18bd9bbbd1c..22c8ea95118 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = { { } }; -static int __net_init nf_ct_frag6_sysctl_register(struct net *net) +static int nf_ct_frag6_sysctl_register(struct net *net) { struct ctl_table *table; struct ctl_table_header *hdr; @@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) } #else -static int __net_init nf_ct_frag6_sysctl_register(struct net *net) +static int nf_ct_frag6_sysctl_register(struct net *net) { return 0; } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7c7e963260e..b1e6cf0b95f 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { }; static const u32 ip6_template_metrics[RTAX_MAX] = { - [RTAX_HOPLIMIT - 1] = 255, + [RTAX_HOPLIMIT - 1] = 0, }; static const struct rt6_info ip6_null_entry_template = { @@ -1232,7 +1232,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, rt->rt6i_dst.addr = fl6->daddr; rt->rt6i_dst.plen = 128; rt->rt6i_idev = idev; - dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); spin_lock_bh(&icmp6_dst_lock); rt->dst.next = icmp6_dst_gc_list; diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 95a3a7a336b..496ce2cebcd 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -421,6 +421,8 @@ static int ircomm_tty_install(struct tty_driver *driver, struct tty_struct *tty) hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL); } + tty->driver_data = self; + return tty_port_install(&self->port, driver, tty); } diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 37b8b8ba31f..76125c57ee6 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p out_del_dev: free_netdev(dev); + spriv->dev = NULL; out_del_session: l2tp_session_delete(session); out: diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 05f3a313db8..7371f676cf4 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2594,6 +2594,9 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, else local->probe_req_reg--; + if (!local->open_count) + break; + ieee80211_queue_work(&local->hw, &local->reconfig_filter); break; default: diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5f3620f0bc0..c21e33d1abd 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; sdata->u.ibss.ibss_join_req = jiffies; - memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); + memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); sdata->u.ibss.ssid_len = params->ssid_len; mutex_unlock(&sdata->u.ibss.mtx); @@ -1151,10 +1151,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->u.ibss.mtx); - sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; - memset(sdata->u.ibss.bssid, 0, ETH_ALEN); - sdata->u.ibss.ssid_len = 0; - active_ibss = ieee80211_sta_active_ibss(sdata); if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { @@ -1175,6 +1171,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) } } + ifibss->state = IEEE80211_IBSS_MLME_SEARCH; + memset(ifibss->bssid, 0, ETH_ALEN); + ifibss->ssid_len = 0; + sta_info_flush(sdata->local, sdata); spin_lock_bh(&ifibss->incomplete_lock); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8c804550465..156e5835e37 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1314,6 +1314,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + struct sk_buff_head *skbs); /* HT */ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6f8a73c64fb..7de7717ad67 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -853,7 +853,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (info->control.vif == &sdata->vif) { __skb_unlink(skb, &local->pending[i]); - dev_kfree_skb_irq(skb); + ieee80211_free_txskb(&local->hw, skb); } } } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c80c4490351..f57f597972f 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -871,8 +871,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) local->hw.wiphy->cipher_suites, sizeof(u32) * local->hw.wiphy->n_cipher_suites, GFP_KERNEL); - if (!suites) - return -ENOMEM; + if (!suites) { + result = -ENOMEM; + goto fail_wiphy_register; + } for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { u32 suite = local->hw.wiphy->cipher_suites[r]; if (suite == WLAN_CIPHER_SUITE_WEP40 || diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e714ed8bb19..1b7eed252fe 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ht_cfreq, ht_oper->primary_chan, cbss->channel->band); ht_oper = NULL; + } else { + channel_type = NL80211_CHAN_HT20; } } - if (ht_oper) { - channel_type = NL80211_CHAN_HT20; + if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { + /* + * cfg80211 already verified that the channel itself can + * be used, but it didn't check that we can do the right + * HT type, so do that here as well. If HT40 isn't allowed + * on this channel, disable 40 MHz operation. + */ - if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - switch (ht_oper->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) + ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; + else channel_type = NL80211_CHAN_HT40PLUS; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + break; + case IEEE80211_HT_PARAM_CHA_SEC_BELOW: + if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) + ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; + else channel_type = NL80211_CHAN_HT40MINUS; - break; - } + break; } } @@ -3549,6 +3559,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; + bool tx = !req->local_state_change; mutex_lock(&ifmgd->mtx); @@ -3565,12 +3576,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, if (ifmgd->associated && ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, - req->reason_code, true, frame_buf); + req->reason_code, tx, frame_buf); } else { drv_mgd_prepare_tx(sdata->local, sdata); ieee80211_send_deauth_disassoc(sdata, req->bssid, IEEE80211_STYPE_DEAUTH, - req->reason_code, true, + req->reason_code, tx, frame_buf); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 61c621e9273..00ade7feb2e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) if (ieee80211_is_action(hdr->frame_control)) { u8 category; + + /* make sure category field is present */ + if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) + return RX_DROP_MONITOR; + mgmt = (struct ieee80211_mgmt *)hdr; category = mgmt->u.action.category; if (category != WLAN_CATEGORY_MESH_ACTION && @@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) */ if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && ieee80211_is_data_present(hdr->frame_control)) { - u16 ethertype; - u8 *payload; - - payload = rx->skb->data + - ieee80211_hdrlen(hdr->frame_control); - ethertype = (payload[6] << 8) | payload[7]; - if (cpu_to_be16(ethertype) == - rx->sdata->control_port_protocol) + unsigned int hdrlen; + __be16 ethertype; + + hdrlen = ieee80211_hdrlen(hdr->frame_control); + + if (rx->skb->len < hdrlen + 8) + return RX_DROP_MONITOR; + + skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); + if (ethertype == rx->sdata->control_port_protocol) return RX_CONTINUE; } @@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) hdr = (struct ieee80211_hdr *)rx->skb->data; fc = hdr->frame_control; + + if (ieee80211_is_ctl(fc)) + return RX_CONTINUE; + sc = le16_to_cpu(hdr->seq_ctrl); frag = sc & IEEE80211_SCTL_FRAG; if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || - (rx->skb)->len < 24 || is_multicast_ether_addr(hdr->addr1))) { /* not fragmented */ goto out; @@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) hdr = (struct ieee80211_hdr *) skb->data; hdrlen = ieee80211_hdrlen(hdr->frame_control); + + /* make sure fixed part of mesh header is there, also checks skb len */ + if (!pskb_may_pull(rx->skb, hdrlen + 6)) + return RX_DROP_MONITOR; + + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + + /* make sure full mesh header is there, also checks skb len */ + if (!pskb_may_pull(rx->skb, + hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) + return RX_DROP_MONITOR; + + /* reload pointers */ + hdr = (struct ieee80211_hdr *) skb->data; mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); /* frame is in RMC, don't forward */ @@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) return RX_DROP_MONITOR; - if (!ieee80211_is_data(hdr->frame_control)) + if (!ieee80211_is_data(hdr->frame_control) || + !(status->rx_flags & IEEE80211_RX_RA_MATCH)) return RX_CONTINUE; if (!mesh_hdr->ttl) @@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(hdr->addr1)) { mpp_addr = hdr->addr3; proxied_addr = mesh_hdr->eaddr1; - } else { + } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { + /* has_a4 already checked in ieee80211_rx_mesh_check */ mpp_addr = hdr->addr4; proxied_addr = mesh_hdr->eaddr2; + } else { + return RX_DROP_MONITOR; } rcu_read_lock(); @@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) } skb_set_queue_mapping(skb, q); - if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) - goto out; - if (!--mesh_hdr->ttl) { IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); - return RX_DROP_MONITOR; + goto out; } if (!ifmsh->mshcfg.dot11MeshForwarding) @@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; case WLAN_CATEGORY_SELF_PROTECTED: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.self_prot.action_code))) + break; + switch (mgmt->u.action.u.self_prot.action_code) { case WLAN_SP_MESH_PEERING_OPEN: case WLAN_SP_MESH_PEERING_CLOSE: @@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; case WLAN_CATEGORY_MESH_ACTION: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.mesh_action.action_code))) + break; + if (!ieee80211_vif_is_mesh(&sdata->vif)) break; if (mesh_action_is_path_sel(mgmt) && @@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) local->dot11ReceivedFragmentCount++; - if (ieee80211_is_mgmt(fc)) - err = skb_linearize(skb); - else + if (ieee80211_is_mgmt(fc)) { + /* drop frame if too short for header */ + if (skb->len < ieee80211_hdrlen(fc)) + err = -ENOBUFS; + else + err = skb_linearize(skb); + } else { err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); + } if (err) { dev_kfree_skb(skb); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index c4cdbde24fd..43e60b5a754 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -917,7 +917,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, struct cfg80211_sched_scan_request *req) { struct ieee80211_local *local = sdata->local; - struct ieee80211_sched_scan_ies sched_scan_ies; + struct ieee80211_sched_scan_ies sched_scan_ies = {}; int ret, i; mutex_lock(&local->mtx); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 797dd36a220..d2eb64e1235 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -117,8 +117,8 @@ static void free_sta_work(struct work_struct *wk) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->tx_filtered[ac]); + ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); + ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); } #ifdef CONFIG_MAC80211_MESH @@ -141,7 +141,7 @@ static void free_sta_work(struct work_struct *wk) tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); if (!tid_tx) continue; - __skb_queue_purge(&tid_tx->pending); + ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); kfree(tid_tx); } @@ -650,7 +650,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, */ if (!skb) break; - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); } /* @@ -679,7 +679,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, local->total_ps_buffered--; ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n", sta->sta.addr); - dev_kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); } /* @@ -961,6 +961,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) struct ieee80211_local *local = sdata->local; struct sk_buff_head pending; int filtered = 0, buffered = 0, ac; + unsigned long flags; clear_sta_flag(sta, WLAN_STA_SP); @@ -976,12 +977,16 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { int count = skb_queue_len(&pending), tmp; + spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); + spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); tmp = skb_queue_len(&pending); filtered += tmp - count; count = tmp; + spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); + spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); tmp = skb_queue_len(&pending); buffered += tmp - count; } diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 3af0cc4130f..101eb88a2b7 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -668,3 +668,12 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb_any(skb); } EXPORT_SYMBOL(ieee80211_free_txskb); + +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + struct sk_buff_head *skbs) +{ + struct sk_buff *skb; + + while ((skb = __skb_dequeue(skbs))) + ieee80211_free_txskb(hw, skb); +} diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c9bf83f3665..b858ebe41fd 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1358,7 +1358,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) if (tx->skb) ieee80211_free_txskb(&tx->local->hw, tx->skb); else - __skb_queue_purge(&tx->skbs); + ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs); return -1; } else if (unlikely(res == TX_QUEUED)) { I802_DEBUG_INC(tx->local->tx_handlers_queued); @@ -2120,10 +2120,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, */ void ieee80211_clear_tx_pending(struct ieee80211_local *local) { + struct sk_buff *skb; int i; - for (i = 0; i < local->hw.queues; i++) - skb_queue_purge(&local->pending[i]); + for (i = 0; i < local->hw.queues; i++) { + while ((skb = skb_dequeue(&local->pending[i])) != NULL) + ieee80211_free_txskb(&local->hw, skb); + } } /* diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 22ca35054dd..0151ae33c4c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, int queue = info->hw_queue; if (WARN_ON(!info->control.vif)) { - kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); return; } @@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); if (WARN_ON(!info->control.vif)) { - kfree_skb(skb); + ieee80211_free_txskb(&local->hw, skb); continue; } @@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, break; } - if (id != WLAN_EID_VENDOR_SPECIFIC && - id != WLAN_EID_QUIET && - test_bit(id, seen_elems)) { - elems->parse_error = true; - left -= elen; - pos += elen; - continue; + switch (id) { + case WLAN_EID_SSID: + case WLAN_EID_SUPP_RATES: + case WLAN_EID_FH_PARAMS: + case WLAN_EID_DS_PARAMS: + case WLAN_EID_CF_PARAMS: + case WLAN_EID_TIM: + case WLAN_EID_IBSS_PARAMS: + case WLAN_EID_CHALLENGE: + case WLAN_EID_RSN: + case WLAN_EID_ERP_INFO: + case WLAN_EID_EXT_SUPP_RATES: + case WLAN_EID_HT_CAPABILITY: + case WLAN_EID_HT_OPERATION: + case WLAN_EID_VHT_CAPABILITY: + case WLAN_EID_VHT_OPERATION: + case WLAN_EID_MESH_ID: + case WLAN_EID_MESH_CONFIG: + case WLAN_EID_PEER_MGMT: + case WLAN_EID_PREQ: + case WLAN_EID_PREP: + case WLAN_EID_PERR: + case WLAN_EID_RANN: + case WLAN_EID_CHANNEL_SWITCH: + case WLAN_EID_EXT_CHANSWITCH_ANN: + case WLAN_EID_COUNTRY: + case WLAN_EID_PWR_CONSTRAINT: + case WLAN_EID_TIMEOUT_INTERVAL: + if (test_bit(id, seen_elems)) { + elems->parse_error = true; + left -= elen; + pos += elen; + continue; + } + break; } if (calc_crc && id < 64 && (filter & (1ULL << id))) @@ -1463,6 +1491,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_STATION) continue; + if (!sdata->u.mgd.associated) + continue; ieee80211_send_nullfunc(local, sdata, 0); } diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index bdb53aba888..8bd2f5c6a56 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; - if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) + if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key && + rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) goto update_iv; return RX_CONTINUE; @@ -545,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) static void bip_aad(struct sk_buff *skb, u8 *aad) { + __le16 mask_fc; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + /* BIP AAD: FC(masked) || A1 || A2 || A3 */ /* FC type/subtype */ - aad[0] = skb->data[0]; /* Mask FC Retry, PwrMgt, MoreData flags to zero */ - aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); + mask_fc = hdr->frame_control; + mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM | + IEEE80211_FCTL_MOREDATA); + put_unaligned(mask_fc, (__le16 *) &aad[0]); /* A1 || A2 || A3 */ - memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); + memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN); } diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c index ec3dba5dcd6..5c0b78528e5 100644 --- a/net/netfilter/ipset/ip_set_hash_ip.c +++ b/net/netfilter/ipset/ip_set_hash_ip.c @@ -173,6 +173,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], return adtfn(set, &nip, timeout, flags); } + ip_to = ip; if (tb[IPSET_ATTR_IP_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) @@ -185,8 +186,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], if (!cidr || cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); - } else - ip_to = ip; + } hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index 0171f7502fa..6283351f4ee 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c @@ -162,7 +162,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport4_elem data = { }; - u32 ip, ip_to = 0, p = 0, port, port_to; + u32 ip, ip_to, p = 0, port, port_to; u32 timeout = h->timeout; bool with_ports = false; int ret; @@ -210,7 +210,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], return ip_set_eexist(ret, flags) ? 0 : ret; } - ip = ntohl(data.ip); + ip_to = ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) @@ -223,8 +223,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], if (!cidr || cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); - } else - ip_to = ip; + } port_to = port = ntohs(data.port); if (with_ports && tb[IPSET_ATTR_PORT_TO]) { diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 6344ef551ec..6a21271c8d5 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c @@ -166,7 +166,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip4_elem data = { }; - u32 ip, ip_to = 0, p = 0, port, port_to; + u32 ip, ip_to, p = 0, port, port_to; u32 timeout = h->timeout; bool with_ports = false; int ret; @@ -218,7 +218,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], return ip_set_eexist(ret, flags) ? 0 : ret; } - ip = ntohl(data.ip); + ip_to = ip = ntohl(data.ip); if (tb[IPSET_ATTR_IP_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) @@ -231,8 +231,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], if (!cidr || cidr > 32) return -IPSET_ERR_INVALID_CIDR; ip_set_mask_from_to(ip, ip_to, cidr); - } else - ip_to = ip; + } port_to = port = ntohs(data.port); if (with_ports && tb[IPSET_ATTR_PORT_TO]) { diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index cb71f9a774e..2d5cd4ee30e 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c @@ -215,8 +215,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], const struct ip_set_hash *h = set->data; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 }; - u32 ip, ip_to = 0, p = 0, port, port_to; - u32 ip2_from = 0, ip2_to, ip2_last, ip2; + u32 ip, ip_to, p = 0, port, port_to; + u32 ip2_from, ip2_to, ip2_last, ip2; u32 timeout = h->timeout; bool with_ports = false; u8 cidr; @@ -286,6 +286,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], return ip_set_eexist(ret, flags) ? 0 : ret; } + ip_to = ip; if (tb[IPSET_ATTR_IP_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); if (ret) @@ -306,6 +307,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], if (port > port_to) swap(port, port_to); } + + ip2_to = ip2_from; if (tb[IPSET_ATTR_IP2_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to); if (ret) diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 7e7198b51c0..c4ee43710aa 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -2589,6 +2589,8 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u) struct ip_vs_proto_data *pd; #endif + memset(u, 0, sizeof (*u)); + #ifdef CONFIG_IP_VS_PROTO_TCP pd = ip_vs_proto_data_get(net, IPPROTO_TCP); u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ; @@ -2766,7 +2768,6 @@ 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_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 1b30b0dee70..962795e839a 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -753,7 +753,8 @@ static int callforward_do_filter(const union nf_inet_addr *src, flowi4_to_flowi(&fl1), false)) { if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, flowi4_to_flowi(&fl2), false)) { - if (rt1->rt_gateway == rt2->rt_gateway && + if (rt_nexthop(rt1, fl1.daddr) == + rt_nexthop(rt2, fl2.daddr) && rt1->dst.dev == rt2->dst.dev) ret = 1; dst_release(&rt2->dst); diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 8847b4d8be0..701c88a20fe 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -41,7 +41,8 @@ MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tu static LIST_HEAD(cttimeout_list); static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = { - [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING }, + [CTA_TIMEOUT_NAME] = { .type = NLA_NUL_STRING, + .len = CTNL_TIMEOUT_NAME_MAX - 1}, [CTA_TIMEOUT_L3PROTO] = { .type = NLA_U16 }, [CTA_TIMEOUT_L4PROTO] = { .type = NLA_U8 }, [CTA_TIMEOUT_DATA] = { .type = NLA_NESTED }, diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 16c71256386..ae7f5daeee4 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c @@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, typeof(nf_ct_timeout_find_get_hook) timeout_find_get; struct ctnl_timeout *timeout; struct nf_conn_timeout *timeout_ext; - const struct ipt_entry *e = par->entryinfo; struct nf_conntrack_l4proto *l4proto; int ret = 0; + u8 proto; rcu_read_lock(); timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); @@ -192,9 +192,11 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, goto out; } - if (e->ip.invflags & IPT_INV_PROTO) { + proto = xt_ct_find_proto(par); + if (!proto) { ret = -EINVAL; - pr_info("You cannot use inversion on L4 protocol\n"); + pr_info("You must specify a L4 protocol, and not use " + "inversions on it.\n"); goto out; } @@ -214,7 +216,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, /* Make sure the timeout policy matches any existing protocol tracker, * otherwise default to generic. */ - l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto); + l4proto = __nf_ct_l4proto_find(par->family, proto); if (timeout->l4proto->l4proto != l4proto->l4proto) { ret = -EINVAL; pr_info("Timeout policy `%s' can only be used by L4 protocol " diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c index ee2e5bc5a8c..bd93e51d30a 100644 --- a/net/netfilter/xt_TEE.c +++ b/net/netfilter/xt_TEE.c @@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info) fl4.daddr = info->gw.ip; fl4.flowi4_tos = RT_TOS(iph->tos); fl4.flowi4_scope = RT_SCOPE_UNIVERSE; + fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH; rt = ip_route_output_key(net, &fl4); if (IS_ERR(rt)) return false; diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c index 81aafa8e4fe..bea7464cc43 100644 --- a/net/netfilter/xt_nat.c +++ b/net/netfilter/xt_nat.c @@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .family = NFPROTO_IPV4, .table = "nat", .hooks = (1 << NF_INET_POST_ROUTING) | - (1 << NF_INET_LOCAL_OUT), + (1 << NF_INET_LOCAL_IN), .me = THIS_MODULE, }, { @@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .family = NFPROTO_IPV4, .table = "nat", .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_LOCAL_IN), + (1 << NF_INET_LOCAL_OUT), .me = THIS_MODULE, }, { @@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .targetsize = sizeof(struct nf_nat_range), .table = "nat", .hooks = (1 << NF_INET_POST_ROUTING) | - (1 << NF_INET_LOCAL_OUT), + (1 << NF_INET_LOCAL_IN), .me = THIS_MODULE, }, { @@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { .targetsize = sizeof(struct nf_nat_range), .table = "nat", .hooks = (1 << NF_INET_PRE_ROUTING) | - (1 << NF_INET_LOCAL_IN), + (1 << NF_INET_LOCAL_OUT), .me = THIS_MODULE, }, }; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 01e944a017a..4da797fa5ec 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk); static DEFINE_RWLOCK(nl_table_lock); static atomic_t nl_table_users = ATOMIC_INIT(0); +#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); + static ATOMIC_NOTIFIER_HEAD(netlink_chain); static inline u32 netlink_group_mask(u32 group) @@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk) struct hlist_node *node; unsigned long mask; unsigned int i; + struct listeners *listeners; + + listeners = nl_deref_protected(tbl->listeners); + if (!listeners) + return; for (i = 0; i < NLGRPLONGS(tbl->groups); i++) { mask = 0; @@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk) if (i < NLGRPLONGS(nlk_sk(sk)->ngroups)) mask |= nlk_sk(sk)->groups[i]; } - tbl->listeners->masks[i] = mask; + listeners->masks[i] = mask; } /* this function is only called with the netlink table "grabbed", which * makes sure updates are visible before bind or setsockopt return. */ @@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock) if (netlink_is_kernel(sk)) { BUG_ON(nl_table[sk->sk_protocol].registered == 0); if (--nl_table[sk->sk_protocol].registered == 0) { - kfree(nl_table[sk->sk_protocol].listeners); + struct listeners *old; + + old = nl_deref_protected(nl_table[sk->sk_protocol].listeners); + RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL); + kfree_rcu(old, rcu); nl_table[sk->sk_protocol].module = NULL; nl_table[sk->sk_protocol].bind = NULL; nl_table[sk->sk_protocol].flags = 0; @@ -982,7 +993,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group) rcu_read_lock(); listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners); - if (group - 1 < nl_table[sk->sk_protocol].groups) + if (listeners && group - 1 < nl_table[sk->sk_protocol].groups) res = test_bit(group - 1, listeners->masks); rcu_read_unlock(); @@ -1625,7 +1636,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups) new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC); if (!new) return -ENOMEM; - old = rcu_dereference_protected(tbl->listeners, 1); + old = nl_deref_protected(tbl->listeners); memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups)); rcu_assign_pointer(tbl->listeners, new); diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index cc10d073c33..9e8f4b2801f 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -1210,7 +1210,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) local->remote_miu = LLCP_DEFAULT_MIU; local->remote_lto = LLCP_DEFAULT_LTO; - list_add(&llcp_devices, &local->list); + list_add(&local->list, &llcp_devices); return 0; } diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index f0dd83cff90..9687fa1c227 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -84,18 +84,19 @@ * grp->index is the index of the group; and grp->slot_shift * is the shift for the corresponding (scaled) sigma_i. */ -#define QFQ_MAX_INDEX 19 -#define QFQ_MAX_WSHIFT 16 +#define QFQ_MAX_INDEX 24 +#define QFQ_MAX_WSHIFT 12 #define QFQ_MAX_WEIGHT (1<<QFQ_MAX_WSHIFT) -#define QFQ_MAX_WSUM (2*QFQ_MAX_WEIGHT) +#define QFQ_MAX_WSUM (16*QFQ_MAX_WEIGHT) #define FRAC_BITS 30 /* fixed point arithmetic */ #define ONE_FP (1UL << FRAC_BITS) #define IWSUM (ONE_FP/QFQ_MAX_WSUM) -#define QFQ_MTU_SHIFT 11 +#define QFQ_MTU_SHIFT 16 /* to support TSO/GSO */ #define QFQ_MIN_SLOT_SHIFT (FRAC_BITS + QFQ_MTU_SHIFT - QFQ_MAX_INDEX) +#define QFQ_MIN_LMAX 256 /* min possible lmax for a class */ /* * Possible group states. These values are used as indexes for the bitmaps @@ -231,6 +232,32 @@ static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl, q->wsum += delta_w; } +static void qfq_update_reactivate_class(struct qfq_sched *q, + struct qfq_class *cl, + u32 inv_w, u32 lmax, int delta_w) +{ + bool need_reactivation = false; + int i = qfq_calc_index(inv_w, lmax); + + 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)); +} + + static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **tca, unsigned long *arg) { @@ -238,7 +265,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct qfq_class *cl = (struct qfq_class *)*arg; struct nlattr *tb[TCA_QFQ_MAX + 1]; u32 weight, lmax, inv_w; - int i, err; + int err; int delta_w; if (tca[TCA_OPTIONS] == NULL) { @@ -270,16 +297,14 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, if (tb[TCA_QFQ_LMAX]) { lmax = nla_get_u32(tb[TCA_QFQ_LMAX]); - if (!lmax || lmax > (1UL << QFQ_MTU_SHIFT)) { + if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) { pr_notice("qfq: invalid max length %u\n", lmax); return -EINVAL; } } else - lmax = 1UL << QFQ_MTU_SHIFT; + lmax = psched_mtu(qdisc_dev(sch)); 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), @@ -291,24 +316,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, 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)); + qfq_update_reactivate_class(q, cl, inv_w, lmax, delta_w); sch_tree_unlock(sch); return 0; @@ -663,15 +672,48 @@ static void qfq_make_eligible(struct qfq_sched *q, u64 old_V) /* - * XXX we should make sure that slot becomes less than 32. - * This is guaranteed by the input values. - * roundedS is always cl->S rounded on grp->slot_shift bits. + * If the weight and lmax (max_pkt_size) of the classes do not change, + * then QFQ guarantees that the slot index is never higher than + * 2 + ((1<<QFQ_MTU_SHIFT)/QFQ_MIN_LMAX) * (QFQ_MAX_WEIGHT/QFQ_MAX_WSUM). + * + * With the current values of the above constants, the index is + * then guaranteed to never be higher than 2 + 256 * (1 / 16) = 18. + * + * When the weight of a class is increased or the lmax of the class is + * decreased, a new class with smaller slot size may happen to be + * activated. The activation of this class should be properly delayed + * to when the service of the class has finished in the ideal system + * tracked by QFQ. If the activation of the class is not delayed to + * this reference time instant, then this class may be unjustly served + * before other classes waiting for service. This may cause + * (unfrequently) the above bound to the slot index to be violated for + * some of these unlucky classes. + * + * Instead of delaying the activation of the new class, which is quite + * complex, the following inaccurate but simple solution is used: if + * the slot index is higher than QFQ_MAX_SLOTS-2, then the timestamps + * of the class are shifted backward so as to let the slot index + * become equal to QFQ_MAX_SLOTS-2. This threshold is used because, if + * the slot index is above it, then the data structure implementing + * the bucket list either gets immediately corrupted or may get + * corrupted on a possible next packet arrival that causes the start + * time of the group to be shifted backward. */ static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl, u64 roundedS) { u64 slot = (roundedS - grp->S) >> grp->slot_shift; - unsigned int i = (grp->front + slot) % QFQ_MAX_SLOTS; + unsigned int i; /* slot index in the bucket list */ + + if (unlikely(slot > QFQ_MAX_SLOTS - 2)) { + u64 deltaS = roundedS - grp->S - + ((u64)(QFQ_MAX_SLOTS - 2)<<grp->slot_shift); + cl->S -= deltaS; + cl->F -= deltaS; + slot = QFQ_MAX_SLOTS - 2; + } + + i = (grp->front + slot) % QFQ_MAX_SLOTS; hlist_add_head(&cl->next, &grp->slots[i]); __set_bit(slot, &grp->full_slots); @@ -892,6 +934,13 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) } pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid); + if (unlikely(cl->lmax < qdisc_pkt_len(skb))) { + pr_debug("qfq: increasing maxpkt from %u to %u for class %u", + cl->lmax, qdisc_pkt_len(skb), cl->common.classid); + qfq_update_reactivate_class(q, cl, cl->inv_w, + qdisc_pkt_len(skb), 0); + } + err = qdisc_enqueue(skb, cl->qdisc); if (unlikely(err != NET_XMIT_SUCCESS)) { pr_debug("qfq_enqueue: enqueue failed %d\n", err); diff --git a/net/sctp/proc.c b/net/sctp/proc.c index c3bea269faf..9966e7b1645 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -102,7 +102,7 @@ static const struct file_operations sctp_snmp_seq_fops = { .open = sctp_snmp_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = single_release, + .release = single_release_net, }; /* Set up the proc fs entry for 'snmp' object. */ @@ -251,7 +251,7 @@ static const struct file_operations sctp_eps_seq_fops = { .open = sctp_eps_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = seq_release_net, }; /* Set up the proc fs entry for 'eps' object. */ @@ -372,7 +372,7 @@ static const struct file_operations sctp_assocs_seq_fops = { .open = sctp_assocs_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = seq_release_net, }; /* Set up the proc fs entry for 'assocs' object. */ @@ -517,7 +517,7 @@ static const struct file_operations sctp_remaddr_seq_fops = { .open = sctp_remaddr_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = seq_release_net, }; int __net_init sctp_remaddr_proc_init(struct net *net) diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 57f7de839b0..6773d780362 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1642,8 +1642,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, asoc->outqueue.outstanding_bytes; sackh.num_gap_ack_blocks = 0; sackh.num_dup_tsns = 0; + chunk->subh.sack_hdr = &sackh; sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, - SCTP_SACKH(&sackh)); + SCTP_CHUNK(chunk)); break; case SCTP_CMD_DISCARD_PACKET: diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 59d16ea927f..a60d1f8b41c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -974,7 +974,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, void *addr_buf; struct sctp_af *af; - SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p" + SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p" " addrs_size %d opt %d\n", sk, addrs, addrs_size, op); if (unlikely(addrs_size <= 0)) diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 5a3d675d2f2..a9c0bbccad6 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c @@ -172,7 +172,7 @@ out_free: xprt_free_allocation(req); dprintk("RPC: setup backchannel transport failed\n"); - return -1; + return -ENOMEM; } EXPORT_SYMBOL_GPL(xprt_setup_backchannel); diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 2a68bb3db77..fc2f7aa4dca 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1409,11 +1409,11 @@ static ssize_t read_flush(struct file *file, char __user *buf, size_t count, loff_t *ppos, struct cache_detail *cd) { - char tbuf[20]; + char tbuf[22]; unsigned long p = *ppos; size_t len; - sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time)); + snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time)); len = strlen(tbuf); if (p >= len) return 0; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index aaaadfbe36e..75853cabf4c 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -254,7 +254,6 @@ struct sock_xprt { void (*old_data_ready)(struct sock *, int); void (*old_state_change)(struct sock *); void (*old_write_space)(struct sock *); - void (*old_error_report)(struct sock *); }; /* @@ -737,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task) dprintk("RPC: sendmsg returned unrecognized error %d\n", -status); case -ECONNRESET: - case -EPIPE: xs_tcp_shutdown(xprt); case -ECONNREFUSED: case -ENOTCONN: + case -EPIPE: clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); } @@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) transport->old_data_ready = sk->sk_data_ready; transport->old_state_change = sk->sk_state_change; transport->old_write_space = sk->sk_write_space; - transport->old_error_report = sk->sk_error_report; } static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) @@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s sk->sk_data_ready = transport->old_data_ready; sk->sk_state_change = transport->old_state_change; sk->sk_write_space = transport->old_write_space; - sk->sk_error_report = transport->old_error_report; } static void xs_reset_transport(struct sock_xprt *transport) @@ -1453,7 +1450,7 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) xprt_clear_connecting(xprt); } -static void xs_sock_mark_closed(struct rpc_xprt *xprt) +static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt) { smp_mb__before_clear_bit(); clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); @@ -1461,6 +1458,11 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt) clear_bit(XPRT_CLOSE_WAIT, &xprt->state); clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); +} + +static void xs_sock_mark_closed(struct rpc_xprt *xprt) +{ + xs_sock_reset_connection_flags(xprt); /* Mark transport as closed and wake up all pending tasks */ xprt_disconnect_done(xprt); } @@ -1516,6 +1518,7 @@ static void xs_tcp_state_change(struct sock *sk) case TCP_CLOSE_WAIT: /* The server initiated a shutdown of the socket */ xprt->connect_cookie++; + clear_bit(XPRT_CONNECTED, &xprt->state); xs_tcp_force_close(xprt); case TCP_CLOSING: /* @@ -1540,25 +1543,6 @@ static void xs_tcp_state_change(struct sock *sk) read_unlock_bh(&sk->sk_callback_lock); } -/** - * xs_error_report - callback mainly for catching socket errors - * @sk: socket - */ -static void xs_error_report(struct sock *sk) -{ - struct rpc_xprt *xprt; - - read_lock_bh(&sk->sk_callback_lock); - if (!(xprt = xprt_from_sock(sk))) - goto out; - dprintk("RPC: %s client %p...\n" - "RPC: error %d\n", - __func__, xprt, sk->sk_err); - xprt_wake_pending_tasks(xprt, -EAGAIN); -out: - read_unlock_bh(&sk->sk_callback_lock); -} - static void xs_write_space(struct sock *sk) { struct socket *sock; @@ -1858,7 +1842,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt, sk->sk_user_data = xprt; sk->sk_data_ready = xs_local_data_ready; sk->sk_write_space = xs_udp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_allocation = GFP_ATOMIC; xprt_clear_connected(xprt); @@ -1983,7 +1966,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) sk->sk_user_data = xprt; sk->sk_data_ready = xs_udp_data_ready; sk->sk_write_space = xs_udp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_no_check = UDP_CSUM_NORCV; sk->sk_allocation = GFP_ATOMIC; @@ -2050,10 +2032,8 @@ static void xs_abort_connection(struct sock_xprt *transport) any.sa_family = AF_UNSPEC; result = kernel_connect(transport->sock, &any, sizeof(any), 0); if (!result) - xs_sock_mark_closed(&transport->xprt); - else - dprintk("RPC: AF_UNSPEC connect return code %d\n", - result); + xs_sock_reset_connection_flags(&transport->xprt); + dprintk("RPC: AF_UNSPEC connect return code %d\n", result); } static void xs_tcp_reuse_connection(struct sock_xprt *transport) @@ -2098,7 +2078,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) sk->sk_data_ready = xs_tcp_data_ready; sk->sk_state_change = xs_tcp_state_change; sk->sk_write_space = xs_tcp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_allocation = GFP_ATOMIC; /* socket options */ diff --git a/net/tipc/handler.c b/net/tipc/handler.c index 111ff8300ae..b36f0fcd9bd 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c @@ -116,7 +116,6 @@ void tipc_handler_stop(void) return; handler_enabled = 0; - tasklet_disable(&tipc_tasklet); tasklet_kill(&tipc_tasklet); spin_lock_bh(&qitem_lock); diff --git a/net/wireless/core.c b/net/wireless/core.c index 443d4d7deea..3f725305208 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -526,8 +526,7 @@ int wiphy_register(struct wiphy *wiphy) for (i = 0; i < sband->n_channels; i++) { sband->channels[i].orig_flags = sband->channels[i].flags; - sband->channels[i].orig_mag = - sband->channels[i].max_antenna_gain; + sband->channels[i].orig_mag = INT_MAX; sband->channels[i].orig_mpwr = sband->channels[i].max_power; sband->channels[i].band = band; diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 8016fee0752..904a7f36832 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, .reason_code = reason, .ie = ie, .ie_len = ie_len, + .local_state_change = local_state_change, }; ASSERT_WDEV_LOCK(wdev); - if (local_state_change) { - if (wdev->current_bss && - ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { - cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(&wdev->current_bss->pub); - wdev->current_bss = NULL; - } - + if (local_state_change && (!wdev->current_bss || + !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) return 0; - } return rdev->ops->deauth(&rdev->wiphy, dev, &req); } diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3b8cbbc214d..b75756b05af 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -141,9 +141,8 @@ static const struct ieee80211_regdomain world_regdom = { .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), - /* IEEE 802.11b/g, channels 12..13. No HT40 - * channel fits here. */ - REG_RULE(2467-10, 2472+10, 20, 6, 20, + /* IEEE 802.11b/g, channels 12..13. */ + REG_RULE(2467-10, 2472+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), /* IEEE 802.11 channel 14 - Only JP enables @@ -908,7 +907,7 @@ static void handle_channel(struct wiphy *wiphy, map_regdom_flags(reg_rule->flags) | bw_flags; chan->max_antenna_gain = chan->orig_mag = (int) MBI_TO_DBI(power_rule->max_antenna_gain); - chan->max_power = chan->orig_mpwr = + chan->max_reg_power = chan->max_power = chan->orig_mpwr = (int) MBM_TO_DBM(power_rule->max_eirp); return; } @@ -1331,7 +1330,8 @@ static void handle_channel_custom(struct wiphy *wiphy, chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); - chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); + chan->max_reg_power = chan->max_power = + (int) MBM_TO_DBM(power_rule->max_eirp); } static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, diff --git a/net/wireless/util.c b/net/wireless/util.c index ef35f4ef2aa..2762e832998 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) } EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); -static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) { int ae = meshhdr->flags & MESH_FLAGS_AE; - /* 7.1.3.5a.2 */ + /* 802.11-2012, 8.2.4.7.3 */ switch (ae) { + default: case 0: return 6; case MESH_FLAGS_AE_A4: return 12; case MESH_FLAGS_AE_A5_A6: return 18; - case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): - return 24; - default: - return 6; } } +EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, enum nl80211_iftype iftype) @@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; + if (meshdr->flags & MESH_FLAGS_AE_A4) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), @@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; + if (meshdr->flags & MESH_FLAGS_AE_A5_A6) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A4) skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic index 40caf3c26cd..d17e0ea911e 100644 --- a/scripts/Makefile.asm-generic +++ b/scripts/Makefile.asm-generic @@ -5,7 +5,7 @@ # and for each file listed in this file with generic-y creates # a small wrapper file in $(obj) (arch/$(SRCARCH)/include/generated/asm) -kbuild-file := $(srctree)/arch/$(SRCARCH)/include/asm/Kbuild +kbuild-file := $(srctree)/arch/$(SRCARCH)/include/$(src)/Kbuild -include $(kbuild-file) include scripts/Kbuild.include diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst index c3f69ae275d..4d908d16c03 100644 --- a/scripts/Makefile.fwinst +++ b/scripts/Makefile.fwinst @@ -27,7 +27,7 @@ endif installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw)) installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) -installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/. +installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./ # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work. PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs @@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@) $(installed-fw-dirs): $(call cmd,mkdir) -$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%) +$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %) $(call cmd,install) PHONY += __fw_install __fw_modinst FORCE diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index 3d13d3a3edf..ecbb44797e2 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst @@ -16,8 +16,9 @@ PHONY += $(modules) __modinst: $(modules) @: +# Don't stop modules_install if we can't sign external modules. quiet_cmd_modules_install = INSTALL $@ - cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) + cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD)) # Modules built outside the kernel source tree go into extra by default INSTALL_MOD_DIR ?= extra diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 002089141df..a1cb0222ebe 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -14,8 +14,7 @@ # 3) create one <module>.mod.c file pr. module # 4) create one Module.symvers file with CRC for all exported symbols # 5) compile all <module>.mod.c files -# 6) final link of the module to a <module.ko> (or <module.unsigned>) file -# 7) signs the modules to a <module.ko> file +# 6) final link of the module to a <module.ko> file # Step 3 is used to place certain information in the module's ELF # section, including information such as: @@ -33,8 +32,6 @@ # Step 4 is solely used to allow module versioning in external modules, # where the CRC of each module is retrieved from the Module.symvers file. -# Step 7 is dependent on CONFIG_MODULE_SIG being enabled. - # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined # symbols in the final module linking stage # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. @@ -119,7 +116,6 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE targets += $(modules:.ko=.mod.o) # Step 6), final link of the modules -ifneq ($(CONFIG_MODULE_SIG),y) quiet_cmd_ld_ko_o = LD [M] $@ cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ @@ -129,78 +125,7 @@ $(modules): %.ko :%.o %.mod.o FORCE $(call if_changed,ld_ko_o) targets += $(modules) -else -quiet_cmd_ld_ko_unsigned_o = LD [M] $@ - cmd_ld_ko_unsigned_o = \ - $(LD) -r $(LDFLAGS) \ - $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ - -o $@ $(filter-out FORCE,$^) \ - $(if $(AFTER_LINK),; $(AFTER_LINK)) - -$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE - $(call if_changed,ld_ko_unsigned_o) - -targets += $(modules:.ko=.ko.unsigned) - -# Step 7), sign the modules -MODSECKEY = ./signing_key.priv -MODPUBKEY = ./signing_key.x509 - -ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) -ifeq ($(KBUILD_SRC),) - # no O= is being used - SCRIPTS_DIR := scripts -else - SCRIPTS_DIR := $(KBUILD_SRC)/scripts -endif -SIGN_MODULES := 1 -else -SIGN_MODULES := 0 -endif - -# only sign if it's an in-tree module -ifneq ($(KBUILD_EXTMOD),) -SIGN_MODULES := 0 -endif -# We strip the module as best we can - note that using both strip and eu-strip -# results in a smaller module than using either alone. -EU_STRIP = $(shell which eu-strip || echo true) - -quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@ - cmd_sign_ko_stripped_ko_unsigned = \ - cp $< $@ && \ - strip -x -g $@ && \ - $(EU_STRIP) $@ - -ifeq ($(SIGN_MODULES),1) - -quiet_cmd_genkeyid = GENKEYID $@ - cmd_genkeyid = \ - perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid - -%.signer %.keyid: % - $(call if_changed,genkeyid) - -KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid -quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@ - cmd_sign_ko_ko_stripped = \ - sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@ -else -KEYRING_DEP := -quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ - cmd_sign_ko_ko_unsigned = \ - cp $< $@ -endif - -$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE - $(call if_changed,sign_ko_ko_stripped) - -$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE - $(call if_changed,sign_ko_stripped_ko_unsigned) - -targets += $(modules) -endif # Add FORCE to the prequisites of a target to force it to be always rebuilt. # --------------------------------------------------------------------------- diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 21a9f5de0a2..f18750e3bd6 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1890,8 +1890,10 @@ sub process { } if ($realfile =~ m@^(drivers/net/|net/)@ && - $rawline !~ m@^\+[ \t]*(\/\*|\*\/)@ && - $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { + $rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */ + $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/ + $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/ + $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */ WARN("NETWORKING_BLOCK_COMMENT_STYLE", "networking block comments put the trailing */ on a separate line\n" . $herecurr); } diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index d501c8605f2..3e42a071070 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/dtc.h @@ -161,51 +161,27 @@ struct node { struct label *labels; }; -static inline struct label *for_each_label_next(struct label *l) -{ - do { - l = l->next; - } while (l && l->deleted); - - return l; -} - -#define for_each_label(l0, l) \ - for ((l) = (l0); (l); (l) = for_each_label_next(l)) - #define for_each_label_withdel(l0, l) \ for ((l) = (l0); (l); (l) = (l)->next) -static inline struct property *for_each_property_next(struct property *p) -{ - do { - p = p->next; - } while (p && p->deleted); - - return p; -} - -#define for_each_property(n, p) \ - for ((p) = (n)->proplist; (p); (p) = for_each_property_next(p)) +#define for_each_label(l0, l) \ + for_each_label_withdel(l0, l) \ + if (!(l)->deleted) #define for_each_property_withdel(n, p) \ for ((p) = (n)->proplist; (p); (p) = (p)->next) -static inline struct node *for_each_child_next(struct node *c) -{ - do { - c = c->next_sibling; - } while (c && c->deleted); - - return c; -} - -#define for_each_child(n, c) \ - for ((c) = (n)->children; (c); (c) = for_each_child_next(c)) +#define for_each_property(n, p) \ + for_each_property_withdel(n, p) \ + if (!(p)->deleted) #define for_each_child_withdel(n, c) \ for ((c) = (n)->children; (c); (c) = (c)->next_sibling) +#define for_each_child(n, c) \ + for_each_child_withdel(n, c) \ + if (!(c)->deleted) + void add_label(struct label **labels, char *label); void delete_labels(struct label **labels); diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index bd2e0989555..cdd48600e02 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -12,7 +12,7 @@ extern "C" { #include <assert.h> #include <stdio.h> -#include <sys/queue.h> +#include "list.h" #ifndef __cplusplus #include <stdbool.h> #endif @@ -175,12 +175,11 @@ struct menu { #define MENU_ROOT 0x0002 struct jump_key { - CIRCLEQ_ENTRY(jump_key) entries; + struct list_head entries; size_t offset; struct menu *target; int index; }; -CIRCLEQ_HEAD(jk_head, jump_key); #define JUMP_NB 9 diff --git a/scripts/kconfig/list.h b/scripts/kconfig/list.h new file mode 100644 index 00000000000..0ae730be5f4 --- /dev/null +++ b/scripts/kconfig/list.h @@ -0,0 +1,91 @@ +#ifndef LIST_H +#define LIST_H + +/* + * Copied from include/linux/... + */ + +#undef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + + +struct list_head { + struct list_head *next, *prev; +}; + + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *_new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *_new, struct list_head *head) +{ + __list_add(_new, head->prev, head); +} + +#endif diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 1d1c08537f1..ef1a7381f95 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -21,9 +21,9 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu)); P(menu_get_parent_menu,struct menu *,(struct menu *menu)); P(menu_has_help,bool,(struct menu *menu)); P(menu_get_help,const char *,(struct menu *menu)); -P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head +P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head *head)); -P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head +P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head *head)); P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 48f67448af7..53975cf8760 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -312,7 +312,7 @@ static void set_config_filename(const char *config_filename) struct search_data { - struct jk_head *head; + struct list_head *head; struct menu **targets; int *keys; }; @@ -323,7 +323,7 @@ static void update_text(char *buf, size_t start, size_t end, void *_data) struct jump_key *pos; int k = 0; - CIRCLEQ_FOREACH(pos, data->head, entries) { + list_for_each_entry(pos, data->head, entries) { if (pos->offset >= start && pos->offset < end) { char header[4]; @@ -375,7 +375,7 @@ again: sym_arr = sym_re_search(dialog_input); do { - struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head); + LIST_HEAD(head); struct menu *targets[JUMP_NB]; int keys[JUMP_NB + 1], i; struct search_data data = { diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index a3cade659f8..e98a05c8e50 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -508,7 +508,7 @@ const char *menu_get_help(struct menu *menu) } static void get_prompt_str(struct gstr *r, struct property *prop, - struct jk_head *head) + struct list_head *head) { int i, j; struct menu *submenu[8], *menu, *location = NULL; @@ -544,12 +544,13 @@ static void get_prompt_str(struct gstr *r, struct property *prop, } else jump->target = location; - if (CIRCLEQ_EMPTY(head)) + if (list_empty(head)) jump->index = 0; else - jump->index = CIRCLEQ_LAST(head)->index + 1; + jump->index = list_entry(head->prev, struct jump_key, + entries)->index + 1; - CIRCLEQ_INSERT_TAIL(head, jump, entries); + list_add_tail(&jump->entries, head); } if (i > 0) { @@ -573,7 +574,8 @@ static void get_prompt_str(struct gstr *r, struct property *prop, /* * head is optional and may be NULL */ -void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head) +void get_symbol_str(struct gstr *r, struct symbol *sym, + struct list_head *head) { bool hit; struct property *prop; @@ -612,7 +614,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head) str_append(r, "\n\n"); } -struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head) +struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head) { struct symbol *sym; struct gstr res = str_new(); diff --git a/scripts/sign-file b/scripts/sign-file index e58e34e50ac..974a20b661b 100644..100755 --- a/scripts/sign-file +++ b/scripts/sign-file @@ -1,115 +1,429 @@ -#!/bin/sh +#!/usr/bin/perl -w # # Sign a module file using the given key. # -# Format: sign-file <key> <x509> <src-file> <dst-file> -# - -scripts=`dirname $0` - -CONFIG_MODULE_SIG_SHA512=y -if [ -r .config ] -then - . ./.config -fi - -key="$1" -x509="$2" -src="$3" -dst="$4" - -if [ ! -r "$key" ] -then - echo "Can't read private key" >&2 - exit 2 -fi - -if [ ! -r "$x509" ] -then - echo "Can't read X.509 certificate" >&2 - exit 2 -fi -if [ ! -r "$x509.signer" ] -then - echo "Can't read Signer name" >&2 - exit 2; -fi -if [ ! -r "$x509.keyid" ] -then - echo "Can't read Key identifier" >&2 - exit 2; -fi +# Format: +# +# ./scripts/sign-file [-v] <key> <x509> <module> [<dest>] +# +# +use strict; +use FileHandle; +use IPC::Open2; + +my $verbose = 0; +if ($#ARGV >= 0 && $ARGV[0] eq "-v") { + $verbose = 1; + shift; +} + +die "Format: ./scripts/sign-file [-v] <key> <x509> <module> [<dest>]\n" + if ($#ARGV != 2 && $#ARGV != 3); + +my $private_key = $ARGV[0]; +my $x509 = $ARGV[1]; +my $module = $ARGV[2]; +my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . "~"; + +die "Can't read private key\n" unless (-r $private_key); +die "Can't read X.509 certificate\n" unless (-r $x509); +die "Can't read module\n" unless (-r $module); + +# +# Read the kernel configuration +# +my %config = ( + CONFIG_MODULE_SIG_SHA512 => 1 + ); + +if (-r ".config") { + open(FD, "<.config") || die ".config"; + while (<FD>) { + if ($_ =~ /^(CONFIG_.*)=[ym]/) { + $config{$1} = 1; + } + } + close(FD); +} + +# +# Function to read the contents of a file into a variable. +# +sub read_file($) +{ + my ($file) = @_; + my $contents; + my $len; + + open(FD, "<$file") || die $file; + binmode FD; + my @st = stat(FD); + die $file if (!@st); + $len = read(FD, $contents, $st[7]) || die $file; + close(FD) || die $file; + die "$file: Wanted length ", $st[7], ", got ", $len, "\n" + if ($len != $st[7]); + return $contents; +} + +############################################################################### +# +# First of all, we have to parse the X.509 certificate to find certain details +# about it. +# +# We read the DER-encoded X509 certificate and parse it to extract the Subject +# name and Subject Key Identifier. Theis provides the data we need to build +# the certificate identifier. +# +# The signer's name part of the identifier is fabricated from the commonName, +# the organizationName or the emailAddress components of the X.509 subject +# name. +# +# The subject key ID is used to select which of that signer's certificates +# we're intending to use to sign the module. +# +############################################################################### +my $x509_certificate = read_file($x509); + +my $UNIV = 0 << 6; +my $APPL = 1 << 6; +my $CONT = 2 << 6; +my $PRIV = 3 << 6; + +my $CONS = 0x20; + +my $BOOLEAN = 0x01; +my $INTEGER = 0x02; +my $BIT_STRING = 0x03; +my $OCTET_STRING = 0x04; +my $NULL = 0x05; +my $OBJ_ID = 0x06; +my $UTF8String = 0x0c; +my $SEQUENCE = 0x10; +my $SET = 0x11; +my $UTCTime = 0x17; +my $GeneralizedTime = 0x18; + +my %OIDs = ( + pack("CCC", 85, 4, 3) => "commonName", + pack("CCC", 85, 4, 6) => "countryName", + pack("CCC", 85, 4, 10) => "organizationName", + pack("CCC", 85, 4, 11) => "organizationUnitName", + pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", + pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", + pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", + pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", + pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", + pack("CCC", 85, 29, 19) => "basicConstraints" +); + +############################################################################### +# +# Extract an ASN.1 element from a string and return information about it. +# +############################################################################### +sub asn1_extract($$@) +{ + my ($cursor, $expected_tag, $optional) = @_; + + return [ -1 ] + if ($cursor->[1] == 0 && $optional); + + die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" + if ($cursor->[1] < 2); + + my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); + + if ($expected_tag != -1 && $tag != $expected_tag) { + return [ -1 ] + if ($optional); + die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, + " not ", $expected_tag, ")\n"; + } + + $cursor->[0] += 2; + $cursor->[1] -= 2; + + die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n" + if (($tag & 0x1f) == 0x1f); + die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n" + if ($len == 0x80); + + if ($len > 0x80) { + my $l = $len - 0x80; + die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" + if ($cursor->[1] < $l); + + if ($l == 0x1) { + $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); + } elsif ($l == 0x2) { + $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); + } elsif ($l == 0x3) { + $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; + $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); + } elsif ($l == 0x4) { + $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); + } else { + die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; + } + + $cursor->[0] += $l; + $cursor->[1] -= $l; + } + + die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" + if ($cursor->[1] < $len); + + my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; + $cursor->[0] += $len; + $cursor->[1] -= $len; + + return $ret; +} + +############################################################################### +# +# Retrieve the data referred to by a cursor +# +############################################################################### +sub asn1_retrieve($) +{ + my ($cursor) = @_; + my ($offset, $len, $data) = @$cursor; + return substr($$data, $offset, $len); +} + +############################################################################### +# +# Roughly parse the X.509 certificate +# +############################################################################### +my $cursor = [ 0, length($x509_certificate), \$x509_certificate ]; + +my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); +my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); +my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); +my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); +my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); +my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); +my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); +my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); + +my $subject_key_id = (); +my $authority_key_id = (); + +# +# Parse the extension list +# +if ($extension_list->[0] != -1) { + my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); + + while ($extensions->[1]->[1] > 0) { + my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); + my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); + my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); + my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); + + my $raw_oid = asn1_retrieve($x_oid->[1]); + next if (!exists($OIDs{$raw_oid})); + my $x_type = $OIDs{$raw_oid}; + + my $raw_value = asn1_retrieve($x_val->[1]); + + if ($x_type eq "subjectKeyIdentifier") { + my $vcursor = [ 0, length($raw_value), \$raw_value ]; + + $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); + } + } +} + +############################################################################### +# +# Determine what we're going to use as the signer's name. In order of +# preference, take one of: commonName, organizationName or emailAddress. +# +############################################################################### +my $org = ""; +my $cn = ""; +my $email = ""; + +while ($subject->[1]->[1] > 0) { + my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); + my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); + my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); + my $n_val = asn1_extract($attr->[1], -1); + + my $raw_oid = asn1_retrieve($n_oid->[1]); + next if (!exists($OIDs{$raw_oid})); + my $n_type = $OIDs{$raw_oid}; + + my $raw_value = asn1_retrieve($n_val->[1]); + + if ($n_type eq "organizationName") { + $org = $raw_value; + } elsif ($n_type eq "commonName") { + $cn = $raw_value; + } elsif ($n_type eq "emailAddress") { + $email = $raw_value; + } +} + +my $signers_name = $email; + +if ($org && $cn) { + # Don't use the organizationName if the commonName repeats it + if (length($org) <= length($cn) && + substr($cn, 0, length($org)) eq $org) { + $signers_name = $cn; + goto got_id_name; + } + + # Or a signifcant chunk of it + if (length($org) >= 7 && + length($cn) >= 7 && + substr($cn, 0, 7) eq substr($org, 0, 7)) { + $signers_name = $cn; + goto got_id_name; + } + + $signers_name = $org . ": " . $cn; +} elsif ($org) { + $signers_name = $org; +} elsif ($cn) { + $signers_name = $cn; +} + +got_id_name: + +die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" + if (!$subject_key_id); + +my $key_identifier = asn1_retrieve($subject_key_id->[1]); + +############################################################################### +# +# Create and attach the module signature +# +############################################################################### # # Signature parameters # -algo=1 # Public-key crypto algorithm: RSA -hash= # Digest algorithm -id_type=1 # Identifier type: X.509 +my $algo = 1; # Public-key crypto algorithm: RSA +my $hash = 0; # Digest algorithm +my $id_type = 1; # Identifier type: X.509 # # Digest the data # -dgst= -if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] -then - prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" - dgst=-sha1 - hash=2 -elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] -then - prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" - dgst=-sha224 - hash=7 -elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] -then - prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" - dgst=-sha256 - hash=4 -elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] -then - prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" - dgst=-sha384 - hash=5 -elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] -then - prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" - dgst=-sha512 - hash=6 -else - echo "$0: Can't determine hash algorithm" >&2 - exit 2 -fi - -( -perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? -openssl dgst $dgst -binary $src || exit $? -) >$src.dig || exit $? +my ($dgst, $prologue) = (); +if (exists $config{"CONFIG_MODULE_SIG_SHA1"}) { + $prologue = pack("C*", + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, + 0x2B, 0x0E, 0x03, 0x02, 0x1A, + 0x05, 0x00, 0x04, 0x14); + $dgst = "-sha1"; + $hash = 2; +} elsif (exists $config{"CONFIG_MODULE_SIG_SHA224"}) { + $prologue = pack("C*", + 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, + 0x05, 0x00, 0x04, 0x1C); + $dgst = "-sha224"; + $hash = 7; +} elsif (exists $config{"CONFIG_MODULE_SIG_SHA256"}) { + $prologue = pack("C*", + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + 0x05, 0x00, 0x04, 0x20); + $dgst = "-sha256"; + $hash = 4; +} elsif (exists $config{"CONFIG_MODULE_SIG_SHA384"}) { + $prologue = pack("C*", + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, + 0x05, 0x00, 0x04, 0x30); + $dgst = "-sha384"; + $hash = 5; +} elsif (exists $config{"CONFIG_MODULE_SIG_SHA512"}) { + $prologue = pack("C*", + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, + 0x05, 0x00, 0x04, 0x40); + $dgst = "-sha512"; + $hash = 6; +} else { + die "Can't determine hash algorithm"; +} + +# +# Generate the digest and read from openssl's stdout +# +my $digest; +$digest = readpipe("openssl dgst $dgst -binary $module") || die "openssl dgst"; # # Generate the binary signature, which will be just the integer that comprises # the signature with no metadata attached. # -openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? -signerlen=`stat -c %s $x509.signer` -keyidlen=`stat -c %s $x509.keyid` -siglen=`stat -c %s $src.sig` +my $pid; +$pid = open2(*read_from, *write_to, + "openssl rsautl -sign -inkey $private_key -keyform PEM") || + die "openssl rsautl"; +binmode write_to; +print write_to $prologue . $digest || die "pipe to openssl rsautl"; +close(write_to) || die "pipe to openssl rsautl"; + +binmode read_from; +my $signature; +read(read_from, $signature, 4096) || die "pipe from openssl rsautl"; +close(read_from) || die "pipe from openssl rsautl"; +$signature = pack("n", length($signature)) . $signature, + +waitpid($pid, 0) || die; +die "openssl rsautl died: $?" if ($? >> 8); # # Build the signed binary # -( - cat $src || exit $? - echo '~Module signature appended~' || exit $? - cat $x509.signer $x509.keyid || exit $? +my $unsigned_module = read_file($module); + +my $magic_number = "~Module signature appended~\n"; + +my $info = pack("CCCCCxxxN", + $algo, $hash, $id_type, + length($signers_name), + length($key_identifier), + length($signature)); - # Preface each signature integer with a 2-byte BE length - perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? - cat $src.sig || exit $? +if ($verbose) { + print "Size of unsigned module: ", length($unsigned_module), "\n"; + print "Size of signer's name : ", length($signers_name), "\n"; + print "Size of key identifier : ", length($key_identifier), "\n"; + print "Size of signature : ", length($signature), "\n"; + print "Size of informaton : ", length($info), "\n"; + print "Size of magic number : ", length($magic_number), "\n"; + print "Signer's name : '", $signers_name, "'\n"; + print "Digest : $dgst\n"; +} - # Generate the information block - perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? -) >$dst~ || exit $? +open(FD, ">$dest") || die $dest; +binmode FD; +print FD + $unsigned_module, + $signers_name, + $key_identifier, + $signature, + $info, + $magic_number + ; +close FD || die $dest; -# Permit in-place signing -mv $dst~ $dst || exit $? +if ($#ARGV != 3) { + rename($dest, $module) || die $module; +} diff --git a/scripts/x509keyid b/scripts/x509keyid deleted file mode 100755 index c8e91a4af38..00000000000 --- a/scripts/x509keyid +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/perl -w -# -# Generate an identifier from an X.509 certificate that can be placed in a -# module signature to indentify the key to use. -# -# Format: -# -# ./scripts/x509keyid <x509-cert> <signer's-name> <key-id> -# -# We read the DER-encoded X509 certificate and parse it to extract the Subject -# name and Subject Key Identifier. The provide the data we need to build the -# certificate identifier. -# -# The signer's name part of the identifier is fabricated from the commonName, -# the organizationName or the emailAddress components of the X.509 subject -# name and written to the second named file. -# -# The subject key ID to select which of that signer's certificates we're -# intending to use to sign the module is written to the third named file. -# -use strict; - -my $raw_data; - -die "Need three filenames\n" if ($#ARGV != 2); - -my $src = $ARGV[0]; - -open(FD, "<$src") || die $src; -binmode FD; -my @st = stat(FD); -die $src if (!@st); -read(FD, $raw_data, $st[7]) || die $src; -close(FD); - -my $UNIV = 0 << 6; -my $APPL = 1 << 6; -my $CONT = 2 << 6; -my $PRIV = 3 << 6; - -my $CONS = 0x20; - -my $BOOLEAN = 0x01; -my $INTEGER = 0x02; -my $BIT_STRING = 0x03; -my $OCTET_STRING = 0x04; -my $NULL = 0x05; -my $OBJ_ID = 0x06; -my $UTF8String = 0x0c; -my $SEQUENCE = 0x10; -my $SET = 0x11; -my $UTCTime = 0x17; -my $GeneralizedTime = 0x18; - -my %OIDs = ( - pack("CCC", 85, 4, 3) => "commonName", - pack("CCC", 85, 4, 6) => "countryName", - pack("CCC", 85, 4, 10) => "organizationName", - pack("CCC", 85, 4, 11) => "organizationUnitName", - pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", - pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", - pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", - pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", - pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", - pack("CCC", 85, 29, 19) => "basicConstraints" -); - -############################################################################### -# -# Extract an ASN.1 element from a string and return information about it. -# -############################################################################### -sub asn1_extract($$@) -{ - my ($cursor, $expected_tag, $optional) = @_; - - return [ -1 ] - if ($cursor->[1] == 0 && $optional); - - die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" - if ($cursor->[1] < 2); - - my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); - - if ($expected_tag != -1 && $tag != $expected_tag) { - return [ -1 ] - if ($optional); - die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, - " not ", $expected_tag, ")\n"; - } - - $cursor->[0] += 2; - $cursor->[1] -= 2; - - die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" - if (($tag & 0x1f) == 0x1f); - die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" - if ($len == 0x80); - - if ($len > 0x80) { - my $l = $len - 0x80; - die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" - if ($cursor->[1] < $l); - - if ($l == 0x1) { - $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); - } elsif ($l = 0x2) { - $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); - } elsif ($l = 0x3) { - $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; - $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); - } elsif ($l = 0x4) { - $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); - } else { - die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; - } - - $cursor->[0] += $l; - $cursor->[1] -= $l; - } - - die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" - if ($cursor->[1] < $len); - - my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; - $cursor->[0] += $len; - $cursor->[1] -= $len; - - return $ret; -} - -############################################################################### -# -# Retrieve the data referred to by a cursor -# -############################################################################### -sub asn1_retrieve($) -{ - my ($cursor) = @_; - my ($offset, $len, $data) = @$cursor; - return substr($$data, $offset, $len); -} - -############################################################################### -# -# Roughly parse the X.509 certificate -# -############################################################################### -my $cursor = [ 0, length($raw_data), \$raw_data ]; - -my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); -my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); -my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); -my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); -my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); -my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); -my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); -my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); - -my $subject_key_id = (); -my $authority_key_id = (); - -# -# Parse the extension list -# -if ($extension_list->[0] != -1) { - my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); - - while ($extensions->[1]->[1] > 0) { - my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); - my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); - my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); - my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); - - my $raw_oid = asn1_retrieve($x_oid->[1]); - next if (!exists($OIDs{$raw_oid})); - my $x_type = $OIDs{$raw_oid}; - - my $raw_value = asn1_retrieve($x_val->[1]); - - if ($x_type eq "subjectKeyIdentifier") { - my $vcursor = [ 0, length($raw_value), \$raw_value ]; - - $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); - } - } -} - -############################################################################### -# -# Determine what we're going to use as the signer's name. In order of -# preference, take one of: commonName, organizationName or emailAddress. -# -############################################################################### -my $org = ""; -my $cn = ""; -my $email = ""; - -while ($subject->[1]->[1] > 0) { - my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); - my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); - my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); - my $n_val = asn1_extract($attr->[1], -1); - - my $raw_oid = asn1_retrieve($n_oid->[1]); - next if (!exists($OIDs{$raw_oid})); - my $n_type = $OIDs{$raw_oid}; - - my $raw_value = asn1_retrieve($n_val->[1]); - - if ($n_type eq "organizationName") { - $org = $raw_value; - } elsif ($n_type eq "commonName") { - $cn = $raw_value; - } elsif ($n_type eq "emailAddress") { - $email = $raw_value; - } -} - -my $id_name = $email; - -if ($org && $cn) { - # Don't use the organizationName if the commonName repeats it - if (length($org) <= length($cn) && - substr($cn, 0, length($org)) eq $org) { - $id_name = $cn; - goto got_id_name; - } - - # Or a signifcant chunk of it - if (length($org) >= 7 && - length($cn) >= 7 && - substr($cn, 0, 7) eq substr($org, 0, 7)) { - $id_name = $cn; - goto got_id_name; - } - - $id_name = $org . ": " . $cn; -} elsif ($org) { - $id_name = $org; -} elsif ($cn) { - $id_name = $cn; -} - -got_id_name: - -############################################################################### -# -# Output the signer's name and the key identifier that we're going to include -# in module signatures. -# -############################################################################### -die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" - if (!$subject_key_id); - -my $id_key_id = asn1_retrieve($subject_key_id->[1]); - -open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; -print OUTFD $id_name; -close OUTFD || die $ARGV[1]; - -open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; -print OUTFD $id_key_id; -close OUTFD || die $ARGV[2]; diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile index 7b3021cebbe..5706b74c857 100644 --- a/security/apparmor/Makefile +++ b/security/apparmor/Makefile @@ -57,7 +57,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \ $(obj)/capability.o : $(obj)/capability_names.h $(obj)/resource.o : $(obj)/rlim_names.h -$(obj)/capability_names.h : $(srctree)/include/linux/capability.h \ +$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ $(src)/Makefile $(call cmd,make-caps) $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \ diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index cf5fd220309..813200384d9 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -724,6 +724,8 @@ fail: */ static void free_profile(struct aa_profile *profile) { + struct aa_profile *p; + AA_DEBUG("%s(%p)\n", __func__, profile); if (!profile) @@ -751,7 +753,27 @@ static void free_profile(struct aa_profile *profile) aa_put_dfa(profile->xmatch); aa_put_dfa(profile->policy.dfa); - aa_put_profile(profile->replacedby); + /* put the profile reference for replacedby, but not via + * put_profile(kref_put). + * replacedby can form a long chain that can result in cascading + * frees that blows the stack because kref_put makes a nested fn + * call (it looks like recursion, with free_profile calling + * free_profile) for each profile in the chain lp#1056078. + */ + for (p = profile->replacedby; p; ) { + if (atomic_dec_and_test(&p->base.count.refcount)) { + /* no more refs on p, grab its replacedby */ + struct aa_profile *next = p->replacedby; + /* break the chain */ + p->replacedby = NULL; + /* now free p, chain is broken */ + free_profile(p); + + /* follow up with next profile in the chain */ + p = next; + } else + break; + } kzfree(profile); } diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 44dfc415a37..b08d20c66c2 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -42,7 +42,10 @@ struct dev_exception_item { struct dev_cgroup { struct cgroup_subsys_state css; struct list_head exceptions; - bool deny_all; + enum { + DEVCG_DEFAULT_ALLOW, + DEVCG_DEFAULT_DENY, + } behavior; }; static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) @@ -161,8 +164,8 @@ static void dev_exception_clean(struct dev_cgroup *dev_cgroup) struct dev_exception_item *ex, *tmp; list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) { - list_del(&ex->list); - kfree(ex); + list_del_rcu(&ex->list); + kfree_rcu(ex, rcu); } } @@ -182,13 +185,13 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup *cgroup) parent_cgroup = cgroup->parent; if (parent_cgroup == NULL) - dev_cgroup->deny_all = false; + dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW; else { parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup); mutex_lock(&devcgroup_mutex); ret = dev_exceptions_copy(&dev_cgroup->exceptions, &parent_dev_cgroup->exceptions); - dev_cgroup->deny_all = parent_dev_cgroup->deny_all; + dev_cgroup->behavior = parent_dev_cgroup->behavior; mutex_unlock(&devcgroup_mutex); if (ret) { kfree(dev_cgroup); @@ -260,7 +263,7 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, * - List the exceptions in case the default policy is to deny * This way, the file remains as a "whitelist of devices" */ - if (devcgroup->deny_all == false) { + if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) { set_access(acc, ACC_MASK); set_majmin(maj, ~0); set_majmin(min, ~0); @@ -295,7 +298,7 @@ static int may_access(struct dev_cgroup *dev_cgroup, struct dev_exception_item *ex; bool match = false; - list_for_each_entry(ex, &dev_cgroup->exceptions, list) { + list_for_each_entry_rcu(ex, &dev_cgroup->exceptions, list) { if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK)) continue; if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR)) @@ -314,12 +317,12 @@ static int may_access(struct dev_cgroup *dev_cgroup, * In two cases we'll consider this new exception valid: * - the dev cgroup has its default policy to allow + exception list: * the new exception should *not* match any of the exceptions - * (!deny_all, !match) + * (behavior == DEVCG_DEFAULT_ALLOW, !match) * - the dev cgroup has its default policy to deny + exception list: * the new exception *should* match the exceptions - * (deny_all, match) + * (behavior == DEVCG_DEFAULT_DENY, match) */ - if (dev_cgroup->deny_all == match) + if ((dev_cgroup->behavior == DEVCG_DEFAULT_DENY) == match) return 1; return 0; } @@ -341,6 +344,19 @@ static int parent_has_perm(struct dev_cgroup *childcg, return may_access(parent, ex); } +/** + * may_allow_all - checks if it's possible to change the behavior to + * allow based on parent's rules. + * @parent: device cgroup's parent + * returns: != 0 in case it's allowed, 0 otherwise + */ +static inline int may_allow_all(struct dev_cgroup *parent) +{ + if (!parent) + return 1; + return parent->behavior == DEVCG_DEFAULT_ALLOW; +} + /* * Modify the exception list using allow/deny rules. * CAP_SYS_ADMIN is needed for this. It's at least separate from CAP_MKNOD @@ -358,13 +374,18 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, int filetype, const char *buffer) { const char *b; - char *endp; - int count; + char temp[12]; /* 11 + 1 characters needed for a u32 */ + int count, rc; struct dev_exception_item ex; + struct cgroup *p = devcgroup->css.cgroup; + struct dev_cgroup *parent = NULL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (p->parent) + parent = cgroup_to_devcgroup(p->parent); + memset(&ex, 0, sizeof(ex)); b = buffer; @@ -372,14 +393,21 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, case 'a': switch (filetype) { case DEVCG_ALLOW: - if (!parent_has_perm(devcgroup, &ex)) + if (!may_allow_all(parent)) return -EPERM; dev_exception_clean(devcgroup); - devcgroup->deny_all = false; + devcgroup->behavior = DEVCG_DEFAULT_ALLOW; + if (!parent) + break; + + rc = dev_exceptions_copy(&devcgroup->exceptions, + &parent->exceptions); + if (rc) + return rc; break; case DEVCG_DENY: dev_exception_clean(devcgroup); - devcgroup->deny_all = true; + devcgroup->behavior = DEVCG_DEFAULT_DENY; break; default: return -EINVAL; @@ -402,8 +430,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, ex.major = ~0; b++; } else if (isdigit(*b)) { - ex.major = simple_strtoul(b, &endp, 10); - b = endp; + memset(temp, 0, sizeof(temp)); + for (count = 0; count < sizeof(temp) - 1; count++) { + temp[count] = *b; + b++; + if (!isdigit(*b)) + break; + } + rc = kstrtou32(temp, 10, &ex.major); + if (rc) + return -EINVAL; } else { return -EINVAL; } @@ -416,8 +452,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, ex.minor = ~0; b++; } else if (isdigit(*b)) { - ex.minor = simple_strtoul(b, &endp, 10); - b = endp; + memset(temp, 0, sizeof(temp)); + for (count = 0; count < sizeof(temp) - 1; count++) { + temp[count] = *b; + b++; + if (!isdigit(*b)) + break; + } + rc = kstrtou32(temp, 10, &ex.minor); + if (rc) + return -EINVAL; } else { return -EINVAL; } @@ -452,7 +496,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, * an matching exception instead. And be silent about it: we * don't want to break compatibility */ - if (devcgroup->deny_all == false) { + if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) { dev_exception_rm(devcgroup, &ex); return 0; } @@ -463,7 +507,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, * an matching exception instead. And be silent about it: we * don't want to break compatibility */ - if (devcgroup->deny_all == true) { + if (devcgroup->behavior == DEVCG_DEFAULT_DENY) { dev_exception_rm(devcgroup, &ex); return 0; } @@ -533,10 +577,10 @@ struct cgroup_subsys devices_subsys = { * * returns 0 on success, -EPERM case the operation is not permitted */ -static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup, - short type, u32 major, u32 minor, +static int __devcgroup_check_permission(short type, u32 major, u32 minor, short access) { + struct dev_cgroup *dev_cgroup; struct dev_exception_item ex; int rc; @@ -547,6 +591,7 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup, ex.access = access; rcu_read_lock(); + dev_cgroup = task_devcgroup(current); rc = may_access(dev_cgroup, &ex); rcu_read_unlock(); @@ -558,7 +603,6 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup, int __devcgroup_inode_permission(struct inode *inode, int mask) { - struct dev_cgroup *dev_cgroup = task_devcgroup(current); short type, access = 0; if (S_ISBLK(inode->i_mode)) @@ -570,13 +614,12 @@ int __devcgroup_inode_permission(struct inode *inode, int mask) if (mask & MAY_READ) access |= ACC_READ; - return __devcgroup_check_permission(dev_cgroup, type, imajor(inode), - iminor(inode), access); + return __devcgroup_check_permission(type, imajor(inode), iminor(inode), + access); } int devcgroup_inode_mknod(int mode, dev_t dev) { - struct dev_cgroup *dev_cgroup = task_devcgroup(current); short type; if (!S_ISBLK(mode) && !S_ISCHR(mode)) @@ -587,7 +630,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev) else type = DEV_CHAR; - return __devcgroup_check_permission(dev_cgroup, type, MAJOR(dev), - MINOR(dev), ACC_MKNOD); + return __devcgroup_check_permission(type, MAJOR(dev), MINOR(dev), + ACC_MKNOD); } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 24ab4148547..61a53367d02 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2132,18 +2132,14 @@ static inline void flush_unauthorized_files(const struct cred *cred, return; devnull = dentry_open(&selinux_null, O_RDWR, cred); - if (!IS_ERR(devnull)) { - /* replace all the matching ones with this */ - do { - replace_fd(n - 1, get_file(devnull), 0); - } while ((n = iterate_fd(files, n, match_file, cred)) != 0); + if (IS_ERR(devnull)) + devnull = NULL; + /* replace all the matching ones with this */ + do { + replace_fd(n - 1, devnull, 0); + } while ((n = iterate_fd(files, n, match_file, cred)) != 0); + if (devnull) fput(devnull); - } else { - /* just close all the matching ones */ - do { - replace_fd(n - 1, NULL, 0); - } while ((n = iterate_fd(files, n, match_file, cred)) != 0); - } } /* diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 28f911cdd7c..c5454c0477c 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node) if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) { struct sel_netnode *tail; tail = list_entry( - rcu_dereference(sel_netnode_hash[idx].list.prev), + rcu_dereference_protected(sel_netnode_hash[idx].list.prev, + lockdep_is_held(&sel_netnode_lock)), struct sel_netnode, list); list_del_rcu(&tail->list); kfree_rcu(tail, rcu); diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index c40ae573346..ad11dc99479 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f) if (dirn != compr->direction) { pr_err("this device doesn't support this direction\n"); + snd_card_unref(compr->card); return -EINVAL; } data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) + if (!data) { + snd_card_unref(compr->card); return -ENOMEM; + } data->stream.ops = compr->ops; data->stream.direction = dirn; data->stream.private_data = compr->private_data; @@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f) runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); if (!runtime) { kfree(data); + snd_card_unref(compr->card); return -ENOMEM; } runtime->state = SNDRV_PCM_STATE_OPEN; @@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f) kfree(runtime); kfree(data); } - return ret; + snd_card_unref(compr->card); + return 0; } static int snd_compr_free(struct inode *inode, struct file *f) diff --git a/sound/core/control.c b/sound/core/control.c index 7e86a5b9f3b..8c7c2c9bba6 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) write_lock_irqsave(&card->ctl_files_rwlock, flags); list_add_tail(&ctl->list, &card->ctl_files); write_unlock_irqrestore(&card->ctl_files_rwlock, flags); + snd_card_unref(card); return 0; __error: @@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(card, file); __error1: + if (card) + snd_card_unref(card); return err; } @@ -1434,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, spin_unlock_irq(&ctl->read_lock); schedule(); remove_wait_queue(&ctl->change_sleep, &wait); + if (ctl->card->shutdown) + return -ENODEV; if (signal_pending(current)) return -ERESTARTSYS; spin_lock_irq(&ctl->read_lock); diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 75ea16f35b1..3f7f6628cf7 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) if (hw == NULL) return -ENODEV; - if (!try_module_get(hw->card->module)) + if (!try_module_get(hw->card->module)) { + snd_card_unref(hw->card); return -EFAULT; + } init_waitqueue_entry(&wait, current); add_wait_queue(&hw->open_wait, &wait); @@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); schedule(); mutex_lock(&hw->open_mutex); + if (hw->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); if (err < 0) module_put(hw->card->module); + snd_card_unref(hw->card); return err; } @@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) mutex_unlock(®ister_mutex); return -EINVAL; } + mutex_lock(&hwdep->open_mutex); + wake_up(&hwdep->open_wait); #ifdef CONFIG_SND_OSSEMUL if (hwdep->ossreg) snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); #endif snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); list_del_init(&hwdep->list); + mutex_unlock(&hwdep->open_mutex); mutex_unlock(®ister_mutex); return 0; } diff --git a/sound/core/init.c b/sound/core/init.c index d8ec849af12..7b012d15c2c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid, spin_lock_init(&card->files_lock); INIT_LIST_HEAD(&card->files_list); init_waitqueue_head(&card->shutdown_sleep); + atomic_set(&card->refcount, 0); #ifdef CONFIG_PM mutex_init(&card->power_lock); init_waitqueue_head(&card->power_sleep); @@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card) return 0; } +/** + * snd_card_unref - release the reference counter + * @card: the card instance + * + * Decrements the reference counter. When it reaches to zero, wake up + * the sleeper and call the destructor if needed. + */ +void snd_card_unref(struct snd_card *card) +{ + if (atomic_dec_and_test(&card->refcount)) { + wake_up(&card->shutdown_sleep); + if (card->free_on_last_close) + snd_card_do_free(card); + } +} +EXPORT_SYMBOL(snd_card_unref); + int snd_card_free_when_closed(struct snd_card *card) { - int free_now = 0; - int ret = snd_card_disconnect(card); - if (ret) - return ret; + int ret; - spin_lock(&card->files_lock); - if (list_empty(&card->files_list)) - free_now = 1; - else - card->free_on_last_close = 1; - spin_unlock(&card->files_lock); + atomic_inc(&card->refcount); + ret = snd_card_disconnect(card); + if (ret) { + atomic_dec(&card->refcount); + return ret; + } - if (free_now) + card->free_on_last_close = 1; + if (atomic_dec_and_test(&card->refcount)) snd_card_do_free(card); return 0; } @@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card) return ret; /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, list_empty(&card->files_list)); + wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); snd_card_do_free(card); return 0; } @@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENODEV; } list_add(&mfile->list, &card->files_list); + atomic_inc(&card->refcount); spin_unlock(&card->files_lock); return 0; } @@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add); int snd_card_file_remove(struct snd_card *card, struct file *file) { struct snd_monitor_file *mfile, *found = NULL; - int last_close = 0; spin_lock(&card->files_lock); list_for_each_entry(mfile, &card->files_list, list) { @@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) break; } } - if (list_empty(&card->files_list)) - last_close = 1; spin_unlock(&card->files_lock); - if (last_close) { - wake_up(&card->shutdown_sleep); - if (card->free_on_last_close) - snd_card_do_free(card); - } if (!found) { snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); return -ENOENT; } kfree(found); + snd_card_unref(card); return 0; } diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 29f6ded0255..e8a1d18774b 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) SNDRV_OSS_DEVICE_TYPE_MIXER); if (card == NULL) return -ENODEV; - if (card->mixer_oss == NULL) + if (card->mixer_oss == NULL) { + snd_card_unref(card); return -ENODEV; + } err = snd_card_file_add(card, file); - if (err < 0) + if (err < 0) { + snd_card_unref(card); return err; + } fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL); if (fmixer == NULL) { snd_card_file_remove(card, file); + snd_card_unref(card); return -ENOMEM; } fmixer->card = card; @@ -68,8 +73,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) if (!try_module_get(card->module)) { kfree(fmixer); snd_card_file_remove(card, file); + snd_card_unref(card); return -EFAULT; } + snd_card_unref(card); return 0; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 08fde0060fd..4c1cc51772e 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); + if (pcm->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -2450,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); if (err < 0) goto __error; + snd_card_unref(pcm->card); return err; __error: @@ -2457,6 +2462,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(pcm->card, file); __error1: + if (pcm) + snd_card_unref(pcm->card); return err; } diff --git a/sound/core/pcm.c b/sound/core/pcm.c index f2991940b27..030102caeee 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) if (list_empty(&pcm->list)) goto unlock; + mutex_lock(&pcm->open_mutex); + wake_up(&pcm->open_wait); list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) - if (substream->runtime) + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { + snd_pcm_stream_lock_irq(substream); + if (substream->runtime) { substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; + wake_up(&substream->runtime->sleep); + wake_up(&substream->runtime->tsleep); + } + snd_pcm_stream_unlock_irq(substream); + } list_for_each_entry(notify, &snd_pcm_notify_list, list) { notify->n_disconnect(pcm); } @@ -1110,6 +1118,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) pcm->streams[cidx].chmap_kctl = NULL; } } + mutex_unlock(&pcm->open_mutex); unlock: mutex_unlock(®ister_mutex); return 0; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 5e12e5bacbb..f9ddecf2f4c 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime) return usecs; } +static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) +{ + snd_pcm_stream_lock_irq(substream); + if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) + substream->runtime->status->state = state; + snd_pcm_stream_unlock_irq(substream); +} + static int snd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, runtime->boundary *= 2; snd_pcm_timer_resolution_change(substream); - runtime->status->state = SNDRV_PCM_STATE_SETUP; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); if (pm_qos_request_active(&substream->latency_pm_qos_req)) pm_qos_remove_request(&substream->latency_pm_qos_req); @@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, /* hardware might be unusable from this time, so we force application to retry to set the correct hardware parameter settings */ - runtime->status->state = SNDRV_PCM_STATE_OPEN; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); if (substream->ops->hw_free != NULL) substream->ops->hw_free(substream); return err; @@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) return -EBADFD; if (substream->ops->hw_free) result = substream->ops->hw_free(substream); - runtime->status->state = SNDRV_PCM_STATE_OPEN; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); pm_qos_remove_request(&substream->latency_pm_qos_req); return result; } @@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state) { struct snd_pcm_runtime *runtime = substream->runtime; runtime->control->appl_ptr = runtime->status->hw_ptr; - runtime->status->state = SNDRV_PCM_STATE_PREPARED; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED); } static struct action_ops snd_pcm_action_prepare = { @@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, down_read(&snd_pcm_link_rwsem); snd_pcm_stream_lock_irq(substream); remove_wait_queue(&to_check->sleep, &wait); + if (card->shutdown) { + result = -ENODEV; + break; + } if (tout == 0) { if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) result = -ESTRPIPE; @@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) write_unlock_irq(&snd_pcm_link_rwlock); up_write(&snd_pcm_link_rwsem); _nolock: + snd_card_unref(substream1->pcm->card); fput_light(file, fput_needed); if (res < 0) kfree(group); @@ -2108,7 +2121,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_PLAYBACK); - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); + if (pcm) + snd_card_unref(pcm->card); + return err; } static int snd_pcm_capture_open(struct inode *inode, struct file *file) @@ -2119,7 +2135,10 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_CAPTURE); - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); + if (pcm) + snd_card_unref(pcm->card); + return err; } static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) @@ -2156,6 +2175,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); + if (pcm->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index ebf6e49ad3d..1bb95aeea08 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (rmidi == NULL) return -ENODEV; - if (!try_module_get(rmidi->card->module)) + if (!try_module_get(rmidi->card->module)) { + snd_card_unref(rmidi->card); return -ENXIO; + } mutex_lock(&rmidi->open_mutex); card = rmidi->card; @@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) mutex_unlock(&rmidi->open_mutex); schedule(); mutex_lock(&rmidi->open_mutex); + if (rmidi->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) #endif file->private_data = rawmidi_file; mutex_unlock(&rmidi->open_mutex); + snd_card_unref(rmidi->card); return 0; __error: @@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) __error_card: mutex_unlock(&rmidi->open_mutex); module_put(rmidi->card->module); + snd_card_unref(rmidi->card); return err; } @@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun spin_unlock_irq(&runtime->lock); schedule(); remove_wait_queue(&runtime->sleep, &wait); + if (rfile->rmidi->card->shutdown) + return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail) @@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, spin_unlock_irq(&runtime->lock); timeout = schedule_timeout(30 * HZ); remove_wait_queue(&runtime->sleep, &wait); + if (rfile->rmidi->card->shutdown) + return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail && !timeout) @@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device) static int snd_rawmidi_dev_disconnect(struct snd_device *device) { struct snd_rawmidi *rmidi = device->device_data; + int dir; mutex_lock(®ister_mutex); + mutex_lock(&rmidi->open_mutex); + wake_up(&rmidi->open_wait); list_del_init(&rmidi->list); + for (dir = 0; dir < 2; dir++) { + struct snd_rawmidi_substream *s; + list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { + if (s->runtime) + wake_up(&s->runtime->sleep); + } + } + #ifdef CONFIG_SND_OSSEMUL if (rmidi->ossreg) { if ((int)rmidi->device == midi_map[rmidi->card->number]) { @@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) } #endif /* CONFIG_SND_OSSEMUL */ snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); + mutex_unlock(&rmidi->open_mutex); mutex_unlock(®ister_mutex); return 0; } diff --git a/sound/core/sound.c b/sound/core/sound.c index 643976000ce..70ccdab7415 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -98,6 +98,10 @@ static void snd_request_other(int minor) * * Checks that a minor device with the specified type is registered, and returns * its user data pointer. + * + * This function increments the reference counter of the card instance + * if an associated instance with the given minor number and type is found. + * The caller must call snd_card_unref() appropriately later. */ void *snd_lookup_minor_data(unsigned int minor, int type) { @@ -108,9 +112,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_mutex); mreg = snd_minors[minor]; - if (mreg && mreg->type == type) + if (mreg && mreg->type == type) { private_data = mreg->private_data; - else + if (private_data && mreg->card_ptr) + atomic_inc(&mreg->card_ptr->refcount); + } else private_data = NULL; mutex_unlock(&sound_mutex); return private_data; @@ -275,6 +281,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; + preg->card_ptr = card; mutex_lock(&sound_mutex); #ifdef CONFIG_SND_DYNAMIC_MINORS minor = snd_find_free_minor(type); diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index e9528333e36..726a49ac972 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -40,6 +40,9 @@ static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; static DEFINE_MUTEX(sound_oss_mutex); +/* NOTE: This function increments the refcount of the associated card like + * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately + */ void *snd_lookup_oss_minor_data(unsigned int minor, int type) { struct snd_minor *mreg; @@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_oss_mutex); mreg = snd_oss_minors[minor]; - if (mreg && mreg->type == type) + if (mreg && mreg->type == type) { private_data = mreg->private_data; - else + if (private_data && mreg->card_ptr) + atomic_inc(&mreg->card_ptr->refcount); + } else private_data = NULL; mutex_unlock(&sound_oss_mutex); return private_data; @@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; + preg->card_ptr = card; mutex_lock(&sound_oss_mutex); snd_oss_minors[minor] = preg; minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index ef68d710d08..e04e750a77e 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c @@ -426,7 +426,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Preample Capture Default", + .name = "IEC958 Preamble Capture Default", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4113_spdif_pinfo, diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index 816e7d225fb..5bf4fca19e4 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -401,7 +401,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Preample Capture Default", + .name = "IEC958 Preamble Capture Default", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4114_spdif_pinfo, .get = snd_ak4114_spdif_pget, diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index b4b2a51fc11..40e33c9f2b0 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c @@ -380,7 +380,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = "IEC958 Preample Capture Default", + .name = "IEC958 Preamble Capture Default", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4117_spdif_pinfo, .get = snd_ak4117_spdif_pget, diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index 3d1afb612b3..4a7ff4e8985 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c @@ -1286,7 +1286,6 @@ static int __devinit snd_miro_probe(struct snd_card *card) error = snd_card_miro_aci_detect(card, miro); if (error < 0) { - snd_card_free(card); snd_printk(KERN_ERR "unable to detect aci chip\n"); return -ENODEV; } diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 9473fca9681..8b0f9968830 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1271,6 +1271,8 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne tmp.index = ac97->num; kctl = snd_ctl_new1(&tmp, ac97); } + if (!kctl) + return -ENOMEM; if (reg >= AC97_PHONE && reg <= AC97_PCM) set_tlv_db_scale(kctl, db_scale_5bit_12db_max); else diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 00f157a2cf6..5af3cb6b0c1 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c @@ -394,6 +394,8 @@ static int snd_als300_playback_open(struct snd_pcm_substream *substream) struct snd_als300_substream_data *data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; snd_als300_dbgcallenter(); chip->playback_substream = substream; runtime->hw = snd_als300_playback_hw; @@ -425,6 +427,8 @@ static int snd_als300_capture_open(struct snd_pcm_substream *substream) struct snd_als300_substream_data *data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; snd_als300_dbgcallenter(); chip->capture_substream = substream; runtime->hw = snd_als300_capture_hw; diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index bed4485f34f..c21adb6ef1d 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1416,6 +1416,15 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0108_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ + /* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */ + /* This is MAEM8986, 0202 is MAEM8980 */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102, + .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]", + .id = "EMU1010", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */ /* Tested by James@superbug.co.uk 8th July 2005. */ /* This is MAEM8810, 0202 is MAEM8820 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5d0e568fdea..7266020c16c 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c @@ -2581,9 +2581,14 @@ static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea) struct es1968 *chip = tea->private_data; unsigned long io = chip->io_port + GPIO_DATA; u16 val = inw(io); + u8 ret; - return (val & STR_DATA) ? TEA575X_DATA : 0 | - (val & STR_MOST) ? TEA575X_MOST : 0; + ret = 0; + if (val & STR_DATA) + ret |= TEA575X_DATA; + if (val & STR_MOST) + ret |= TEA575X_MOST; + return ret; } static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output) @@ -2655,6 +2660,8 @@ static struct ess_device_list pm_whitelist[] __devinitdata = { { TYPE_MAESTRO2E, 0x1179 }, { TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */ { TYPE_MAESTRO2E, 0x1558 }, + { TYPE_MAESTRO2E, 0x125d }, /* a PCI card, e.g. Terratec DMX */ + { TYPE_MAESTRO2, 0x125d }, /* a PCI card, e.g. SF64-PCE2 */ }; static struct ess_device_list mpu_blacklist[] __devinitdata = { diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index cc2e91d1553..c5806f89be1 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -767,9 +767,14 @@ static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea) struct fm801 *chip = tea->private_data; unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL)); struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip); - - return (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 | - (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0; + u8 ret; + + ret = 0; + if (reg & FM801_GPIO_GP(gpio.data)) + ret |= TEA575X_DATA; + if (reg & FM801_GPIO_GP(gpio.most)) + ret |= TEA575X_MOST; + return ret; } static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 70d4848b5cd..d010de12335 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -95,6 +95,7 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset) EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); #ifdef CONFIG_PM +#define codec_in_pm(codec) ((codec)->in_pm) static void hda_power_work(struct work_struct *work); static void hda_keep_power_on(struct hda_codec *codec); #define hda_codec_is_power_on(codec) ((codec)->power_on) @@ -104,6 +105,7 @@ static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up) bus->ops.pm_notify(bus, power_up); } #else +#define codec_in_pm(codec) 0 static inline void hda_keep_power_on(struct hda_codec *codec) {} #define hda_codec_is_power_on(codec) 1 #define hda_call_pm_notify(bus, state) {} @@ -228,7 +230,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, } mutex_unlock(&bus->cmd_mutex); snd_hda_power_down(codec); - if (res && *res == -1 && bus->rirb_error) { + if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) { if (bus->response_reset) { snd_printd("hda_codec: resetting BUS due to " "fatal communication error\n"); @@ -238,7 +240,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd, goto again; } /* clear reset-flag when the communication gets recovered */ - if (!err) + if (!err || codec_in_pm(codec)) bus->response_reset = 0; return err; } @@ -3616,6 +3618,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq) { unsigned int state; + codec->in_pm = 1; + if (codec->patch_ops.suspend) codec->patch_ops.suspend(codec); hda_cleanup_all_streams(codec); @@ -3630,6 +3634,7 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq) codec->power_transition = 0; codec->power_jiffies = jiffies; spin_unlock(&codec->power_lock); + codec->in_pm = 0; return state; } @@ -3638,6 +3643,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq) */ static void hda_call_codec_resume(struct hda_codec *codec) { + codec->in_pm = 1; + /* set as if powered on for avoiding re-entering the resume * in the resume / power-save sequence */ @@ -3656,6 +3663,8 @@ static void hda_call_codec_resume(struct hda_codec *codec) snd_hda_codec_resume_cache(codec); } snd_hda_jack_report_sync(codec); + + codec->in_pm = 0; snd_hda_power_down(codec); /* flag down before returning */ } #endif /* CONFIG_PM */ diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 507fe8a917b..4f4e545c0f4 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -869,6 +869,7 @@ struct hda_codec { unsigned int power_on :1; /* current (global) power-state */ unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */ unsigned int pm_down_notified:1; /* PM notified to controller */ + unsigned int in_pm:1; /* suspend/resume being performed */ int power_transition; /* power-state in transition */ int power_count; /* current (global) power refcount */ struct delayed_work power_work; /* delayed task for powerdown */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 6833835a218..f9d870e554d 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -501,6 +501,7 @@ struct azx { /* VGA-switcheroo setup */ unsigned int use_vga_switcheroo:1; + unsigned int vga_switcheroo_registered:1; unsigned int init_failed:1; /* delayed init failed */ unsigned int disabled:1; /* disabled by VGA-switcher */ @@ -555,6 +556,12 @@ enum { #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ #define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ +#define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ + +/* quirks for Intel PCH */ +#define AZX_DCAPS_INTEL_PCH \ + (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \ + AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME) /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ @@ -2157,9 +2164,12 @@ static unsigned int azx_get_position(struct azx *chip, if (delay < 0) delay += azx_dev->bufsize; if (delay >= azx_dev->period_bytes) { - snd_printdd("delay %d > period_bytes %d\n", - delay, azx_dev->period_bytes); - delay = 0; /* something is wrong */ + snd_printk(KERN_WARNING SFX + "Unstable LPIB (%d >= %d); " + "disabling LPIB delay counting\n", + delay, azx_dev->period_bytes); + delay = 0; + chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY; } azx_dev->substream->runtime->delay = bytes_to_frames(azx_dev->substream->runtime, delay); @@ -2429,6 +2439,9 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up) { struct azx *chip = bus->private_data; + if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) + return; + if (power_up) pm_runtime_get_sync(&chip->pci->dev); else @@ -2544,7 +2557,8 @@ static int azx_runtime_suspend(struct device *dev) struct snd_card *card = dev_get_drvdata(dev); struct azx *chip = card->private_data; - if (!power_save_controller) + if (!power_save_controller || + !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) return -EAGAIN; azx_stop_chip(chip); @@ -2640,7 +2654,9 @@ static void azx_vs_set_state(struct pci_dev *pci, if (disabled) { azx_suspend(&pci->dev); chip->disabled = true; - snd_hda_lock_devices(chip->bus); + if (snd_hda_lock_devices(chip->bus)) + snd_printk(KERN_WARNING SFX + "Cannot lock devices!\n"); } else { snd_hda_unlock_devices(chip->bus); chip->disabled = false; @@ -2683,14 +2699,20 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = { static int __devinit register_vga_switcheroo(struct azx *chip) { + int err; + if (!chip->use_vga_switcheroo) return 0; /* FIXME: currently only handling DIS controller * is there any machine with two switchable HDMI audio controllers? */ - return vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, + err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, VGA_SWITCHEROO_DIS, chip->bus != NULL); + if (err < 0) + return err; + chip->vga_switcheroo_registered = 1; + return 0; } #else #define init_vga_switcheroo(chip) /* NOP */ @@ -2712,7 +2734,8 @@ static int azx_free(struct azx *chip) if (use_vga_switcheroo(chip)) { if (chip->disabled && chip->bus) snd_hda_unlock_devices(chip->bus); - vga_switcheroo_unregister_client(chip->pci); + if (chip->vga_switcheroo_registered) + vga_switcheroo_unregister_client(chip->pci); } if (chip->initialized) { @@ -2813,8 +2836,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1043, 0x1ac3, "ASUS X53S", POS_FIX_POSBUF), - SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB), SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), @@ -3062,14 +3083,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } ok: - err = register_vga_switcheroo(chip); - if (err < 0) { - snd_printk(KERN_ERR SFX - "Error registering VGA-switcheroo client\n"); - azx_free(chip); - return err; - } - err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); if (err < 0) { snd_printk(KERN_ERR SFX "Error creating device [card]!\n"); @@ -3340,6 +3353,13 @@ static int __devinit azx_probe(struct pci_dev *pci, if (pci_dev_run_wake(pci)) pm_runtime_put_noidle(&pci->dev); + err = register_vga_switcheroo(chip); + if (err < 0) { + snd_printk(KERN_ERR SFX + "Error registering VGA-switcheroo client\n"); + goto out_free; + } + dev++; return 0; @@ -3419,39 +3439,30 @@ static void __devexit azx_remove(struct pci_dev *pci) static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* CPT */ { PCI_DEVICE(0x8086, 0x1c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, /* PBG */ { PCI_DEVICE(0x8086, 0x1d20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, /* Panther Point */ { PCI_DEVICE(0x8086, 0x1e20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, /* Lynx Point */ { PCI_DEVICE(0x8086, 0x8c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, /* Lynx Point-LP */ { PCI_DEVICE(0x8086, 0x9c20), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, /* Lynx Point-LP */ { PCI_DEVICE(0x8086, 0x9c21), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, /* Haswell */ { PCI_DEVICE(0x8086, 0x0c0c), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH }, { PCI_DEVICE(0x8086, 0x0d0c), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH }, /* 5 Series/3400 */ { PCI_DEVICE(0x8086, 0x3b56), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH }, /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | @@ -3553,6 +3564,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* Teradici */ { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, + { PCI_DEVICE(0x6549, 0x2200), + .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT }, /* Creative X-Fi (CA0110-IBG) */ /* CTHDA chips */ { PCI_DEVICE(0x1102, 0x0010), diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index cdd43eadbc6..1eeba738666 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -545,6 +545,7 @@ static int ad198x_build_pcms(struct hda_codec *codec) if (spec->multiout.dig_out_nid) { info++; codec->num_pcms++; + codec->spdif_status_reset = 1; info->name = "AD198x Digital"; info->pcm_type = HDA_PCM_TYPE_SPDIF; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 61a71131711..3bcb6717235 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -101,8 +101,8 @@ enum { #define CS420X_VENDOR_NID 0x11 #define CS_DIG_OUT1_PIN_NID 0x10 #define CS_DIG_OUT2_PIN_NID 0x15 -#define CS_DMIC1_PIN_NID 0x12 -#define CS_DMIC2_PIN_NID 0x0e +#define CS_DMIC1_PIN_NID 0x0e +#define CS_DMIC2_PIN_NID 0x12 /* coef indices */ #define IDX_SPDIF_STAT 0x0000 @@ -466,6 +466,7 @@ static int parse_output(struct hda_codec *codec) memcpy(cfg->speaker_pins, cfg->line_out_pins, sizeof(cfg->speaker_pins)); cfg->line_outs = 0; + memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins)); } return 0; @@ -1079,14 +1080,18 @@ static void init_input(struct hda_codec *codec) cs_automic(codec, NULL); coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ + cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + + coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG); if (is_active_pin(codec, CS_DMIC2_PIN_NID)) - coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */ + coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */ if (is_active_pin(codec, CS_DMIC1_PIN_NID)) - coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off + coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off * No effect if SPDIF_OUT2 is * selected in IDX_SPDIF_CTL. */ - cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + + cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef); } else { if (spec->mic_detect) cs_automic(codec, NULL); @@ -1107,7 +1112,7 @@ static const struct hda_verb cs_coef_init_verbs[] = { | 0x0400 /* Disable Coefficient Auto increment */ )}, /* Beep */ - {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, + {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG}, {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */ {} /* terminator */ @@ -1728,8 +1733,7 @@ static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol, } -static struct snd_kcontrol_new cs421x_capture_source = { - +static const struct snd_kcontrol_new cs421x_capture_source = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -1946,7 +1950,7 @@ static int cs421x_suspend(struct hda_codec *codec) } #endif -static struct hda_codec_ops cs421x_patch_ops = { +static const struct hda_codec_ops cs421x_patch_ops = { .build_controls = cs421x_build_controls, .build_pcms = cs_build_pcms, .init = cs421x_init, diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8253b4eeb6a..ad68d223f8a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2598,8 +2598,10 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, return "PCM"; break; } - if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name))) + if (ch >= ARRAY_SIZE(channel_name)) { + snd_BUG(); return "PCM"; + } return channel_name[ch]; } @@ -5405,6 +5407,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), + SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), @@ -5675,6 +5678,7 @@ static const struct hda_verb alc268_beep_init_verbs[] = { enum { ALC268_FIXUP_INV_DMIC, + ALC268_FIXUP_HP_EAPD, }; static const struct alc_fixup alc268_fixups[] = { @@ -5682,10 +5686,26 @@ static const struct alc_fixup alc268_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc_fixup_inv_dmic_0x12, }, + [ALC268_FIXUP_HP_EAPD] = { + .type = ALC_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0}, + {} + } + }, }; static const struct alc_model_fixup alc268_fixup_models[] = { {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"}, + {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"}, + {} +}; + +static const struct snd_pci_quirk alc268_fixup_tbl[] = { + /* below is codec SSID since multiple Toshiba laptops have the + * same PCI SSID 1179:ff00 + */ + SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD), {} }; @@ -5720,7 +5740,7 @@ static int patch_alc268(struct hda_codec *codec) spec = codec->spec; - alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups); + alc_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups); alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); /* automatic parse from the BIOS config */ @@ -5821,7 +5841,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) return alc_parse_auto_config(codec, alc269_ignore, ssids); } -static void alc269_toggle_power_output(struct hda_codec *codec, int power_up) +static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up) { int val = alc_read_coef_idx(codec, 0x04); if (power_up) @@ -5838,10 +5858,10 @@ static void alc269_shutup(struct hda_codec *codec) if (spec->codec_variant != ALC269_TYPE_ALC269VB) return; - if ((alc_get_coef0(codec) & 0x00ff) == 0x017) - alc269_toggle_power_output(codec, 0); - if ((alc_get_coef0(codec) & 0x00ff) == 0x018) { - alc269_toggle_power_output(codec, 0); + if (spec->codec_variant == ALC269_TYPE_ALC269VB) + alc269vb_toggle_power_output(codec, 0); + if (spec->codec_variant == ALC269_TYPE_ALC269VB && + (alc_get_coef0(codec) & 0x00ff) == 0x018) { msleep(150); } } @@ -5851,24 +5871,22 @@ static int alc269_resume(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - if (spec->codec_variant == ALC269_TYPE_ALC269VB || + if (spec->codec_variant == ALC269_TYPE_ALC269VB) + alc269vb_toggle_power_output(codec, 0); + if (spec->codec_variant == ALC269_TYPE_ALC269VB && (alc_get_coef0(codec) & 0x00ff) == 0x018) { - alc269_toggle_power_output(codec, 0); msleep(150); } codec->patch_ops.init(codec); - if (spec->codec_variant == ALC269_TYPE_ALC269VB || + if (spec->codec_variant == ALC269_TYPE_ALC269VB) + alc269vb_toggle_power_output(codec, 1); + if (spec->codec_variant == ALC269_TYPE_ALC269VB && (alc_get_coef0(codec) & 0x00ff) == 0x017) { - alc269_toggle_power_output(codec, 1); msleep(200); } - if (spec->codec_variant == ALC269_TYPE_ALC269VB || - (alc_get_coef0(codec) & 0x00ff) == 0x018) - alc269_toggle_power_output(codec, 1); - snd_hda_codec_resume_amp(codec); snd_hda_codec_resume_cache(codec); hda_call_check_power_status(codec, 0x01); @@ -6186,6 +6204,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { 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, 0x21f3, "Thinkpad T430", 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_PCM_44K), @@ -7046,6 +7065,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, + { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, @@ -7059,6 +7079,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { .patch = patch_alc662 }, { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, + { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 }, { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, @@ -7076,6 +7097,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 }, { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 }, + { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 }, {} /* terminator */ }; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 770013ff556..9ba8af05617 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1763,6 +1763,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "HP", STAC_HP_ZEPHYR), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660, "HP Mini", STAC_92HD83XXX_HP_LED), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E, + "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED), {} /* terminator */ }; diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 72a2f60b087..019e1a00414 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1809,11 +1809,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) { struct via_spec *spec = codec->spec; const struct auto_pin_cfg *cfg = &spec->autocfg; - int i, dac_num; + int i; hda_nid_t nid; + spec->multiout.num_dacs = 0; spec->multiout.dac_nids = spec->private_dac_nids; - dac_num = 0; for (i = 0; i < cfg->line_outs; i++) { hda_nid_t dac = 0; nid = cfg->line_out_pins[i]; @@ -1824,16 +1824,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) if (!i && parse_output_path(codec, nid, dac, 1, &spec->out_mix_path)) dac = spec->out_mix_path.path[0]; - if (dac) { - spec->private_dac_nids[i] = dac; - dac_num++; - } + if (dac) + spec->private_dac_nids[spec->multiout.num_dacs++] = dac; } if (!spec->out_path[0].depth && spec->out_mix_path.depth) { spec->out_path[0] = spec->out_mix_path; spec->out_mix_path.depth = 0; } - spec->multiout.num_dacs = dac_num; return 0; } @@ -3628,6 +3625,7 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) */ enum { VIA_FIXUP_INTMIC_BOOST, + VIA_FIXUP_ASUS_G75, }; static void via_fixup_intmic_boost(struct hda_codec *codec, @@ -3642,13 +3640,35 @@ static const struct hda_fixup via_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = via_fixup_intmic_boost, }, + [VIA_FIXUP_ASUS_G75] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + /* set 0x24 and 0x33 as speakers */ + { 0x24, 0x991301f0 }, + { 0x33, 0x991301f1 }, /* subwoofer */ + { } + } + }, }; static const struct snd_pci_quirk vt2002p_fixups[] = { + SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75), SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST), {} }; +/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e + * Replace this with mixer NID 0x1c + */ +static void fix_vt1802_connections(struct hda_codec *codec) +{ + static hda_nid_t conn_24[] = { 0x14, 0x1c }; + static hda_nid_t conn_33[] = { 0x1c }; + + snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24); + snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33); +} + /* patch for vt2002P */ static int patch_vt2002P(struct hda_codec *codec) { @@ -3663,6 +3683,8 @@ static int patch_vt2002P(struct hda_codec *codec) spec->aa_mix_nid = 0x21; override_mic_boost(codec, 0x2b, 0, 3, 40); override_mic_boost(codec, 0x29, 0, 3, 40); + if (spec->codec_type == VT1802) + fix_vt1802_connections(codec); add_secret_dac_path(codec); snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups); diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 3050a527925..245d874891b 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -2859,7 +2859,12 @@ static int snd_vt1724_resume(struct device *dev) ice->set_spdif_clock(ice, 0); } else { /* internal on-card clock */ - snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); + int rate; + if (ice->cur_rate) + rate = ice->cur_rate; + else + rate = ice->pro_rate_default; + snd_vt1724_set_pro_rate(ice, rate, 1); } update_spdif_bits(ice, ice->pm_saved_spdif_ctrl); diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index b12308b5ba2..748e36c6660 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -971,6 +971,7 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); static int hdspm_autosync_ref(struct hdspm *hdspm); static int snd_hdspm_set_defaults(struct hdspm *hdspm); +static int hdspm_system_clock_mode(struct hdspm *hdspm); static void hdspm_set_sgbuf(struct hdspm *hdspm, struct snd_pcm_substream *substream, unsigned int reg, int channels); @@ -1989,10 +1990,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm) rate = hdspm_calc_dds_value(hdspm, period); if (rate > 207000) { - /* Unreasonable high sample rate as seen on PCI MADI cards. - * Use the cached value instead. - */ - rate = hdspm->system_sample_rate; + /* Unreasonable high sample rate as seen on PCI MADI cards. */ + if (0 == hdspm_system_clock_mode(hdspm)) { + /* master mode, return internal sample rate */ + rate = hdspm->system_sample_rate; + } else { + /* slave mode, return external sample rate */ + rate = hdspm_external_sample_rate(hdspm); + } } return rate; @@ -2000,12 +2005,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm) #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdspm_info_system_sample_rate, \ - .get = snd_hdspm_get_system_sample_rate \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ + SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ + .info = snd_hdspm_info_system_sample_rate, \ + .put = snd_hdspm_put_system_sample_rate, \ + .get = snd_hdspm_get_system_sample_rate \ } static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol, @@ -2030,6 +2037,16 @@ static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol, return 0; } +static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value * + ucontrol) +{ + struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); + + hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]); + return 0; +} + /** * Returns the WordClock sample rate class for the given card. @@ -2163,6 +2180,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, hdspm_get_s1_sample_rate(hdspm, kcontrol->private_value-1); } + break; case AIO: switch (kcontrol->private_value) { @@ -2183,6 +2201,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, hdspm_get_s1_sample_rate(hdspm, ucontrol->id.index-1); } + break; case AES32: @@ -2204,8 +2223,23 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, hdspm_get_s1_sample_rate(hdspm, kcontrol->private_value-1); break; + } + break; + case MADI: + case MADIface: + { + int rate = hdspm_external_sample_rate(hdspm); + int i, selected_rate = 0; + for (i = 1; i < 10; i++) + if (HDSPM_bit2freq(i) == rate) { + selected_rate = i; + break; + } + ucontrol->value.enumerated.item[0] = selected_rate; } + break; + default: break; } @@ -2430,7 +2464,7 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol, #define HDSPM_PREF_SYNC_REF(xname, xindex) \ -{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .index = xindex, \ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ @@ -2766,12 +2800,12 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, #define HDSPM_AUTOSYNC_REF(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ, \ - .info = snd_hdspm_info_autosync_ref, \ - .get = snd_hdspm_get_autosync_ref, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .access = SNDRV_CTL_ELEM_ACCESS_READ, \ + .info = snd_hdspm_info_autosync_ref, \ + .get = snd_hdspm_get_autosync_ref, \ } static int hdspm_autosync_ref(struct hdspm *hdspm) @@ -2855,12 +2889,12 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, #define HDSPM_LINE_OUT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_line_out, \ - .get = snd_hdspm_get_line_out, \ - .put = snd_hdspm_put_line_out \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_line_out, \ + .get = snd_hdspm_get_line_out, \ + .put = snd_hdspm_put_line_out \ } static int hdspm_line_out(struct hdspm * hdspm) @@ -2912,12 +2946,12 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol, #define HDSPM_TX_64(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_tx_64, \ - .get = snd_hdspm_get_tx_64, \ - .put = snd_hdspm_put_tx_64 \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_tx_64, \ + .get = snd_hdspm_get_tx_64, \ + .put = snd_hdspm_put_tx_64 \ } static int hdspm_tx_64(struct hdspm * hdspm) @@ -2968,12 +3002,12 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol, #define HDSPM_C_TMS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_c_tms, \ - .get = snd_hdspm_get_c_tms, \ - .put = snd_hdspm_put_c_tms \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_c_tms, \ + .get = snd_hdspm_get_c_tms, \ + .put = snd_hdspm_put_c_tms \ } static int hdspm_c_tms(struct hdspm * hdspm) @@ -3024,12 +3058,12 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol, #define HDSPM_SAFE_MODE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_safe_mode, \ - .get = snd_hdspm_get_safe_mode, \ - .put = snd_hdspm_put_safe_mode \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_safe_mode, \ + .get = snd_hdspm_get_safe_mode, \ + .put = snd_hdspm_put_safe_mode \ } static int hdspm_safe_mode(struct hdspm * hdspm) @@ -3080,12 +3114,12 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol, #define HDSPM_EMPHASIS(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_emphasis, \ - .get = snd_hdspm_get_emphasis, \ - .put = snd_hdspm_put_emphasis \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_emphasis, \ + .get = snd_hdspm_get_emphasis, \ + .put = snd_hdspm_put_emphasis \ } static int hdspm_emphasis(struct hdspm * hdspm) @@ -3136,12 +3170,12 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol, #define HDSPM_DOLBY(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_dolby, \ - .get = snd_hdspm_get_dolby, \ - .put = snd_hdspm_put_dolby \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_dolby, \ + .get = snd_hdspm_get_dolby, \ + .put = snd_hdspm_put_dolby \ } static int hdspm_dolby(struct hdspm * hdspm) @@ -3192,12 +3226,12 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol, #define HDSPM_PROFESSIONAL(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_professional, \ - .get = snd_hdspm_get_professional, \ - .put = snd_hdspm_put_professional \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_professional, \ + .get = snd_hdspm_get_professional, \ + .put = snd_hdspm_put_professional \ } static int hdspm_professional(struct hdspm * hdspm) @@ -3247,12 +3281,12 @@ static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol, } #define HDSPM_INPUT_SELECT(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_input_select, \ - .get = snd_hdspm_get_input_select, \ - .put = snd_hdspm_put_input_select \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_input_select, \ + .get = snd_hdspm_get_input_select, \ + .put = snd_hdspm_put_input_select \ } static int hdspm_input_select(struct hdspm * hdspm) @@ -3319,12 +3353,12 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol, #define HDSPM_DS_WIRE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_ds_wire, \ - .get = snd_hdspm_get_ds_wire, \ - .put = snd_hdspm_put_ds_wire \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_ds_wire, \ + .get = snd_hdspm_get_ds_wire, \ + .put = snd_hdspm_put_ds_wire \ } static int hdspm_ds_wire(struct hdspm * hdspm) @@ -3391,12 +3425,12 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol, #define HDSPM_QS_WIRE(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_hdspm_info_qs_wire, \ - .get = snd_hdspm_get_qs_wire, \ - .put = snd_hdspm_put_qs_wire \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = xname, \ + .index = xindex, \ + .info = snd_hdspm_info_qs_wire, \ + .get = snd_hdspm_get_qs_wire, \ + .put = snd_hdspm_put_qs_wire \ } static int hdspm_qs_wire(struct hdspm * hdspm) @@ -3563,15 +3597,15 @@ static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol, } #define HDSPM_MIXER(xname, xindex) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ - .name = xname, \ - .index = xindex, \ - .device = 0, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_mixer, \ - .get = snd_hdspm_get_mixer, \ - .put = snd_hdspm_put_mixer \ +{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ + .name = xname, \ + .index = xindex, \ + .device = 0, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ + SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ + .info = snd_hdspm_info_mixer, \ + .get = snd_hdspm_get_mixer, \ + .put = snd_hdspm_put_mixer \ } static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol, @@ -3670,12 +3704,12 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol, */ #define HDSPM_PLAYBACK_MIXER \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \ - SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ - .info = snd_hdspm_info_playback_mixer, \ - .get = snd_hdspm_get_playback_mixer, \ - .put = snd_hdspm_put_playback_mixer \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \ + SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ + .info = snd_hdspm_info_playback_mixer, \ + .get = snd_hdspm_get_playback_mixer, \ + .put = snd_hdspm_put_playback_mixer \ } static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol, @@ -3851,12 +3885,17 @@ static int hdspm_sync_in_sync_check(struct hdspm *hdspm) break; case MADI: - case AES32: - status = hdspm_read(hdspm, HDSPM_statusRegister2); + status = hdspm_read(hdspm, HDSPM_statusRegister); lock = (status & HDSPM_syncInLock) ? 1 : 0; sync = (status & HDSPM_syncInSync) ? 1 : 0; break; + case AES32: + status = hdspm_read(hdspm, HDSPM_statusRegister2); + lock = (status & 0x100000) ? 1 : 0; + sync = (status & 0x200000) ? 1 : 0; + break; + case MADIface: break; } @@ -3940,8 +3979,10 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, case 8: /* SYNC IN */ val = hdspm_sync_in_sync_check(hdspm); break; default: - val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); + val = hdspm_s1_sync_check(hdspm, + kcontrol->private_value-1); } + break; case AIO: switch (kcontrol->private_value) { @@ -3954,6 +3995,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, default: val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); } + break; case MADI: switch (kcontrol->private_value) { @@ -3966,6 +4008,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, case 3: /* SYNC_IN */ val = hdspm_sync_in_sync_check(hdspm); break; } + break; case MADIface: val = hdspm_madi_sync_check(hdspm); /* MADI */ @@ -3983,6 +4026,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, val = hdspm_aes_sync_check(hdspm, kcontrol->private_value-1); } + break; } @@ -4427,9 +4471,10 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), + HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), HDSPM_SYNC_CHECK("WC SyncCheck", 0), HDSPM_SYNC_CHECK("MADI SyncCheck", 1), - HDSPM_SYNC_CHECK("TCO SyncCHeck", 2), + HDSPM_SYNC_CHECK("TCO SyncCheck", 2), HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), HDSPM_LINE_OUT("Line Out", 0), HDSPM_TX_64("TX 64 channels mode", 0), @@ -4855,7 +4900,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, insel = "Coaxial"; break; default: - insel = "Unkown"; + insel = "Unknown"; } snd_iprintf(buffer, diff --git a/sound/soc/Makefile b/sound/soc/Makefile index bcbf1d00aa8..99f32f7c069 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,8 +1,9 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o -snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o -obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o +ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),) +snd-soc-core-objs += soc-dmaengine-pcm.o +endif obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index c03b65af305..054967d8bac 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -268,7 +268,7 @@ EXPORT_SYMBOL_GPL(arizona_out_ev); static unsigned int arizona_sysclk_48k_rates[] = { 6144000, 12288000, - 22579200, + 24576000, 49152000, 73728000, 98304000, @@ -278,7 +278,7 @@ static unsigned int arizona_sysclk_48k_rates[] = { static unsigned int arizona_sysclk_44k1_rates[] = { 5644800, 11289600, - 24576000, + 22579200, 45158400, 67737600, 90316800, diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index f994af34f55..e3f0a7f3131 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c @@ -485,7 +485,7 @@ static int cs4271_probe(struct snd_soc_codec *codec) gpio_nreset = cs4271plat->gpio_nreset; if (gpio_nreset >= 0) - if (gpio_request(gpio_nreset, "CS4271 Reset")) + if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset")) gpio_nreset = -EINVAL; if (gpio_nreset >= 0) { /* Reset codec */ @@ -535,15 +535,10 @@ static int cs4271_probe(struct snd_soc_codec *codec) static int cs4271_remove(struct snd_soc_codec *codec) { struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); - int gpio_nreset; - gpio_nreset = cs4271->gpio_nreset; - - if (gpio_is_valid(gpio_nreset)) { + if (gpio_is_valid(cs4271->gpio_nreset)) /* Set codec to the reset state */ - gpio_set_value(gpio_nreset, 0); - gpio_free(gpio_nreset); - } + gpio_set_value(cs4271->gpio_nreset, 0); return 0; }; diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 61599298fb2..97a81051e88 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -763,7 +763,7 @@ static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai, if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) { cs42l52->sysclk = freq; } else { - dev_err(codec->dev, "Invalid freq paramter\n"); + dev_err(codec->dev, "Invalid freq parameter\n"); return -EINVAL; } return 0; @@ -773,7 +773,6 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec); - int ret = 0; u8 iface = 0; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -822,7 +821,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) case SND_SOC_DAIFMT_NB_IF: break; default: - ret = -EINVAL; + return -EINVAL; } cs42l52->config.format = iface; snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format); diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index 185d8dd3639..f379b085c39 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -178,6 +178,12 @@ #define DA9055_AIF_WORD_S24_LE (2 << 2) #define DA9055_AIF_WORD_S32_LE (3 << 2) +/* MIC_L_CTRL bit fields */ +#define DA9055_MIC_L_MUTE_EN (1 << 6) + +/* MIC_R_CTRL bit fields */ +#define DA9055_MIC_R_MUTE_EN (1 << 6) + /* MIXIN_L_CTRL bit fields */ #define DA9055_MIXIN_L_MIX_EN (1 << 3) @@ -476,7 +482,7 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u8 reg_val, adc_left, adc_right; + u8 reg_val, adc_left, adc_right, mic_left, mic_right; int avg_left_data, avg_right_data, offset_l, offset_r; if (ucontrol->value.integer.value[0]) { @@ -485,6 +491,16 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, * offsets must be done first */ + /* Save current values from Mic control registers */ + mic_left = snd_soc_read(codec, DA9055_MIC_L_CTRL); + mic_right = snd_soc_read(codec, DA9055_MIC_R_CTRL); + + /* Mute Mic PGA Left and Right */ + snd_soc_update_bits(codec, DA9055_MIC_L_CTRL, + DA9055_MIC_L_MUTE_EN, DA9055_MIC_L_MUTE_EN); + snd_soc_update_bits(codec, DA9055_MIC_R_CTRL, + DA9055_MIC_R_MUTE_EN, DA9055_MIC_R_MUTE_EN); + /* Save current values from ADC control registers */ adc_left = snd_soc_read(codec, DA9055_ADC_L_CTRL); adc_right = snd_soc_read(codec, DA9055_ADC_R_CTRL); @@ -520,6 +536,10 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, /* Restore original values of ADC control registers */ snd_soc_write(codec, DA9055_ADC_L_CTRL, adc_left); snd_soc_write(codec, DA9055_ADC_R_CTRL, adc_right); + + /* Restore original values of Mic control registers */ + snd_soc_write(codec, DA9055_MIC_L_CTRL, mic_left); + snd_soc_write(codec, DA9055_MIC_R_CTRL, mic_right); } return snd_soc_put_volsw(kcontrol, ucontrol); diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index e8f97af7592..00b85cc1b9a 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -820,10 +820,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"VIBRA DAC", NULL, "Vibra Playback"}, /* ADC -> Stream mapping */ - {"ADC Left", NULL, "Legacy Capture"}, - {"ADC Left", NULL, "Capture"}, - {"ADC Right", NULL, "Legacy Capture"}, - {"ADC Right", NULL, "Capture"}, + {"Legacy Capture" , NULL, "ADC Left"}, + {"Capture", NULL, "ADC Left"}, + {"Legacy Capture", NULL, "ADC Right"}, + {"Capture" , NULL, "ADC Right"}, /* Capture path */ {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index efa93dbb019..eab64a19398 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1028,7 +1028,7 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L, WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0, digital_tlv), SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, - WM2200_SPK1R_MUTE_SHIFT, 1, 0), + WM2200_SPK1R_MUTE_SHIFT, 1, 1), }; WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); @@ -2091,6 +2091,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, switch (wm2200->rev) { case 0: + case 1: ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch, ARRAY_SIZE(wm2200_reva_patch)); if (ret != 0) { diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 1722b586bdb..7394e73fa43 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -42,6 +42,556 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); +static const struct reg_default wm5102_sysclk_reva_patch[] = { + { 0x3000, 0x2225 }, + { 0x3001, 0x3a03 }, + { 0x3002, 0x0225 }, + { 0x3003, 0x0801 }, + { 0x3004, 0x6249 }, + { 0x3005, 0x0c04 }, + { 0x3006, 0x0225 }, + { 0x3007, 0x5901 }, + { 0x3008, 0xe249 }, + { 0x3009, 0x030d }, + { 0x300a, 0x0249 }, + { 0x300b, 0x2c01 }, + { 0x300c, 0xe249 }, + { 0x300d, 0x4342 }, + { 0x300e, 0xe249 }, + { 0x300f, 0x73c0 }, + { 0x3010, 0x4249 }, + { 0x3011, 0x0c00 }, + { 0x3012, 0x0225 }, + { 0x3013, 0x1f01 }, + { 0x3014, 0x0225 }, + { 0x3015, 0x1e01 }, + { 0x3016, 0x0225 }, + { 0x3017, 0xfa00 }, + { 0x3018, 0x0000 }, + { 0x3019, 0xf000 }, + { 0x301a, 0x0000 }, + { 0x301b, 0xf000 }, + { 0x301c, 0x0000 }, + { 0x301d, 0xf000 }, + { 0x301e, 0x0000 }, + { 0x301f, 0xf000 }, + { 0x3020, 0x0000 }, + { 0x3021, 0xf000 }, + { 0x3022, 0x0000 }, + { 0x3023, 0xf000 }, + { 0x3024, 0x0000 }, + { 0x3025, 0xf000 }, + { 0x3026, 0x0000 }, + { 0x3027, 0xf000 }, + { 0x3028, 0x0000 }, + { 0x3029, 0xf000 }, + { 0x302a, 0x0000 }, + { 0x302b, 0xf000 }, + { 0x302c, 0x0000 }, + { 0x302d, 0xf000 }, + { 0x302e, 0x0000 }, + { 0x302f, 0xf000 }, + { 0x3030, 0x0225 }, + { 0x3031, 0x1a01 }, + { 0x3032, 0x0225 }, + { 0x3033, 0x1e00 }, + { 0x3034, 0x0225 }, + { 0x3035, 0x1f00 }, + { 0x3036, 0x6225 }, + { 0x3037, 0xf800 }, + { 0x3038, 0x0000 }, + { 0x3039, 0xf000 }, + { 0x303a, 0x0000 }, + { 0x303b, 0xf000 }, + { 0x303c, 0x0000 }, + { 0x303d, 0xf000 }, + { 0x303e, 0x0000 }, + { 0x303f, 0xf000 }, + { 0x3040, 0x2226 }, + { 0x3041, 0x3a03 }, + { 0x3042, 0x0226 }, + { 0x3043, 0x0801 }, + { 0x3044, 0x6249 }, + { 0x3045, 0x0c06 }, + { 0x3046, 0x0226 }, + { 0x3047, 0x5901 }, + { 0x3048, 0xe249 }, + { 0x3049, 0x030d }, + { 0x304a, 0x0249 }, + { 0x304b, 0x2c01 }, + { 0x304c, 0xe249 }, + { 0x304d, 0x4342 }, + { 0x304e, 0xe249 }, + { 0x304f, 0x73c0 }, + { 0x3050, 0x4249 }, + { 0x3051, 0x0c00 }, + { 0x3052, 0x0226 }, + { 0x3053, 0x1f01 }, + { 0x3054, 0x0226 }, + { 0x3055, 0x1e01 }, + { 0x3056, 0x0226 }, + { 0x3057, 0xfa00 }, + { 0x3058, 0x0000 }, + { 0x3059, 0xf000 }, + { 0x305a, 0x0000 }, + { 0x305b, 0xf000 }, + { 0x305c, 0x0000 }, + { 0x305d, 0xf000 }, + { 0x305e, 0x0000 }, + { 0x305f, 0xf000 }, + { 0x3060, 0x0000 }, + { 0x3061, 0xf000 }, + { 0x3062, 0x0000 }, + { 0x3063, 0xf000 }, + { 0x3064, 0x0000 }, + { 0x3065, 0xf000 }, + { 0x3066, 0x0000 }, + { 0x3067, 0xf000 }, + { 0x3068, 0x0000 }, + { 0x3069, 0xf000 }, + { 0x306a, 0x0000 }, + { 0x306b, 0xf000 }, + { 0x306c, 0x0000 }, + { 0x306d, 0xf000 }, + { 0x306e, 0x0000 }, + { 0x306f, 0xf000 }, + { 0x3070, 0x0226 }, + { 0x3071, 0x1a01 }, + { 0x3072, 0x0226 }, + { 0x3073, 0x1e00 }, + { 0x3074, 0x0226 }, + { 0x3075, 0x1f00 }, + { 0x3076, 0x6226 }, + { 0x3077, 0xf800 }, + { 0x3078, 0x0000 }, + { 0x3079, 0xf000 }, + { 0x307a, 0x0000 }, + { 0x307b, 0xf000 }, + { 0x307c, 0x0000 }, + { 0x307d, 0xf000 }, + { 0x307e, 0x0000 }, + { 0x307f, 0xf000 }, + { 0x3080, 0x2227 }, + { 0x3081, 0x3a03 }, + { 0x3082, 0x0227 }, + { 0x3083, 0x0801 }, + { 0x3084, 0x6255 }, + { 0x3085, 0x0c04 }, + { 0x3086, 0x0227 }, + { 0x3087, 0x5901 }, + { 0x3088, 0xe255 }, + { 0x3089, 0x030d }, + { 0x308a, 0x0255 }, + { 0x308b, 0x2c01 }, + { 0x308c, 0xe255 }, + { 0x308d, 0x4342 }, + { 0x308e, 0xe255 }, + { 0x308f, 0x73c0 }, + { 0x3090, 0x4255 }, + { 0x3091, 0x0c00 }, + { 0x3092, 0x0227 }, + { 0x3093, 0x1f01 }, + { 0x3094, 0x0227 }, + { 0x3095, 0x1e01 }, + { 0x3096, 0x0227 }, + { 0x3097, 0xfa00 }, + { 0x3098, 0x0000 }, + { 0x3099, 0xf000 }, + { 0x309a, 0x0000 }, + { 0x309b, 0xf000 }, + { 0x309c, 0x0000 }, + { 0x309d, 0xf000 }, + { 0x309e, 0x0000 }, + { 0x309f, 0xf000 }, + { 0x30a0, 0x0000 }, + { 0x30a1, 0xf000 }, + { 0x30a2, 0x0000 }, + { 0x30a3, 0xf000 }, + { 0x30a4, 0x0000 }, + { 0x30a5, 0xf000 }, + { 0x30a6, 0x0000 }, + { 0x30a7, 0xf000 }, + { 0x30a8, 0x0000 }, + { 0x30a9, 0xf000 }, + { 0x30aa, 0x0000 }, + { 0x30ab, 0xf000 }, + { 0x30ac, 0x0000 }, + { 0x30ad, 0xf000 }, + { 0x30ae, 0x0000 }, + { 0x30af, 0xf000 }, + { 0x30b0, 0x0227 }, + { 0x30b1, 0x1a01 }, + { 0x30b2, 0x0227 }, + { 0x30b3, 0x1e00 }, + { 0x30b4, 0x0227 }, + { 0x30b5, 0x1f00 }, + { 0x30b6, 0x6227 }, + { 0x30b7, 0xf800 }, + { 0x30b8, 0x0000 }, + { 0x30b9, 0xf000 }, + { 0x30ba, 0x0000 }, + { 0x30bb, 0xf000 }, + { 0x30bc, 0x0000 }, + { 0x30bd, 0xf000 }, + { 0x30be, 0x0000 }, + { 0x30bf, 0xf000 }, + { 0x30c0, 0x2228 }, + { 0x30c1, 0x3a03 }, + { 0x30c2, 0x0228 }, + { 0x30c3, 0x0801 }, + { 0x30c4, 0x6255 }, + { 0x30c5, 0x0c06 }, + { 0x30c6, 0x0228 }, + { 0x30c7, 0x5901 }, + { 0x30c8, 0xe255 }, + { 0x30c9, 0x030d }, + { 0x30ca, 0x0255 }, + { 0x30cb, 0x2c01 }, + { 0x30cc, 0xe255 }, + { 0x30cd, 0x4342 }, + { 0x30ce, 0xe255 }, + { 0x30cf, 0x73c0 }, + { 0x30d0, 0x4255 }, + { 0x30d1, 0x0c00 }, + { 0x30d2, 0x0228 }, + { 0x30d3, 0x1f01 }, + { 0x30d4, 0x0228 }, + { 0x30d5, 0x1e01 }, + { 0x30d6, 0x0228 }, + { 0x30d7, 0xfa00 }, + { 0x30d8, 0x0000 }, + { 0x30d9, 0xf000 }, + { 0x30da, 0x0000 }, + { 0x30db, 0xf000 }, + { 0x30dc, 0x0000 }, + { 0x30dd, 0xf000 }, + { 0x30de, 0x0000 }, + { 0x30df, 0xf000 }, + { 0x30e0, 0x0000 }, + { 0x30e1, 0xf000 }, + { 0x30e2, 0x0000 }, + { 0x30e3, 0xf000 }, + { 0x30e4, 0x0000 }, + { 0x30e5, 0xf000 }, + { 0x30e6, 0x0000 }, + { 0x30e7, 0xf000 }, + { 0x30e8, 0x0000 }, + { 0x30e9, 0xf000 }, + { 0x30ea, 0x0000 }, + { 0x30eb, 0xf000 }, + { 0x30ec, 0x0000 }, + { 0x30ed, 0xf000 }, + { 0x30ee, 0x0000 }, + { 0x30ef, 0xf000 }, + { 0x30f0, 0x0228 }, + { 0x30f1, 0x1a01 }, + { 0x30f2, 0x0228 }, + { 0x30f3, 0x1e00 }, + { 0x30f4, 0x0228 }, + { 0x30f5, 0x1f00 }, + { 0x30f6, 0x6228 }, + { 0x30f7, 0xf800 }, + { 0x30f8, 0x0000 }, + { 0x30f9, 0xf000 }, + { 0x30fa, 0x0000 }, + { 0x30fb, 0xf000 }, + { 0x30fc, 0x0000 }, + { 0x30fd, 0xf000 }, + { 0x30fe, 0x0000 }, + { 0x30ff, 0xf000 }, + { 0x3100, 0x222b }, + { 0x3101, 0x3a03 }, + { 0x3102, 0x222b }, + { 0x3103, 0x5803 }, + { 0x3104, 0xe26f }, + { 0x3105, 0x030d }, + { 0x3106, 0x626f }, + { 0x3107, 0x2c01 }, + { 0x3108, 0xe26f }, + { 0x3109, 0x4342 }, + { 0x310a, 0xe26f }, + { 0x310b, 0x73c0 }, + { 0x310c, 0x026f }, + { 0x310d, 0x0c00 }, + { 0x310e, 0x022b }, + { 0x310f, 0x1f01 }, + { 0x3110, 0x022b }, + { 0x3111, 0x1e01 }, + { 0x3112, 0x022b }, + { 0x3113, 0xfa00 }, + { 0x3114, 0x0000 }, + { 0x3115, 0xf000 }, + { 0x3116, 0x0000 }, + { 0x3117, 0xf000 }, + { 0x3118, 0x0000 }, + { 0x3119, 0xf000 }, + { 0x311a, 0x0000 }, + { 0x311b, 0xf000 }, + { 0x311c, 0x0000 }, + { 0x311d, 0xf000 }, + { 0x311e, 0x0000 }, + { 0x311f, 0xf000 }, + { 0x3120, 0x022b }, + { 0x3121, 0x0a01 }, + { 0x3122, 0x022b }, + { 0x3123, 0x1e00 }, + { 0x3124, 0x022b }, + { 0x3125, 0x1f00 }, + { 0x3126, 0x622b }, + { 0x3127, 0xf800 }, + { 0x3128, 0x0000 }, + { 0x3129, 0xf000 }, + { 0x312a, 0x0000 }, + { 0x312b, 0xf000 }, + { 0x312c, 0x0000 }, + { 0x312d, 0xf000 }, + { 0x312e, 0x0000 }, + { 0x312f, 0xf000 }, + { 0x3130, 0x0000 }, + { 0x3131, 0xf000 }, + { 0x3132, 0x0000 }, + { 0x3133, 0xf000 }, + { 0x3134, 0x0000 }, + { 0x3135, 0xf000 }, + { 0x3136, 0x0000 }, + { 0x3137, 0xf000 }, + { 0x3138, 0x0000 }, + { 0x3139, 0xf000 }, + { 0x313a, 0x0000 }, + { 0x313b, 0xf000 }, + { 0x313c, 0x0000 }, + { 0x313d, 0xf000 }, + { 0x313e, 0x0000 }, + { 0x313f, 0xf000 }, + { 0x3140, 0x0000 }, + { 0x3141, 0xf000 }, + { 0x3142, 0x0000 }, + { 0x3143, 0xf000 }, + { 0x3144, 0x0000 }, + { 0x3145, 0xf000 }, + { 0x3146, 0x0000 }, + { 0x3147, 0xf000 }, + { 0x3148, 0x0000 }, + { 0x3149, 0xf000 }, + { 0x314a, 0x0000 }, + { 0x314b, 0xf000 }, + { 0x314c, 0x0000 }, + { 0x314d, 0xf000 }, + { 0x314e, 0x0000 }, + { 0x314f, 0xf000 }, + { 0x3150, 0x0000 }, + { 0x3151, 0xf000 }, + { 0x3152, 0x0000 }, + { 0x3153, 0xf000 }, + { 0x3154, 0x0000 }, + { 0x3155, 0xf000 }, + { 0x3156, 0x0000 }, + { 0x3157, 0xf000 }, + { 0x3158, 0x0000 }, + { 0x3159, 0xf000 }, + { 0x315a, 0x0000 }, + { 0x315b, 0xf000 }, + { 0x315c, 0x0000 }, + { 0x315d, 0xf000 }, + { 0x315e, 0x0000 }, + { 0x315f, 0xf000 }, + { 0x3160, 0x0000 }, + { 0x3161, 0xf000 }, + { 0x3162, 0x0000 }, + { 0x3163, 0xf000 }, + { 0x3164, 0x0000 }, + { 0x3165, 0xf000 }, + { 0x3166, 0x0000 }, + { 0x3167, 0xf000 }, + { 0x3168, 0x0000 }, + { 0x3169, 0xf000 }, + { 0x316a, 0x0000 }, + { 0x316b, 0xf000 }, + { 0x316c, 0x0000 }, + { 0x316d, 0xf000 }, + { 0x316e, 0x0000 }, + { 0x316f, 0xf000 }, + { 0x3170, 0x0000 }, + { 0x3171, 0xf000 }, + { 0x3172, 0x0000 }, + { 0x3173, 0xf000 }, + { 0x3174, 0x0000 }, + { 0x3175, 0xf000 }, + { 0x3176, 0x0000 }, + { 0x3177, 0xf000 }, + { 0x3178, 0x0000 }, + { 0x3179, 0xf000 }, + { 0x317a, 0x0000 }, + { 0x317b, 0xf000 }, + { 0x317c, 0x0000 }, + { 0x317d, 0xf000 }, + { 0x317e, 0x0000 }, + { 0x317f, 0xf000 }, + { 0x3180, 0x2001 }, + { 0x3181, 0xf101 }, + { 0x3182, 0x0000 }, + { 0x3183, 0xf000 }, + { 0x3184, 0x0000 }, + { 0x3185, 0xf000 }, + { 0x3186, 0x0000 }, + { 0x3187, 0xf000 }, + { 0x3188, 0x0000 }, + { 0x3189, 0xf000 }, + { 0x318a, 0x0000 }, + { 0x318b, 0xf000 }, + { 0x318c, 0x0000 }, + { 0x318d, 0xf000 }, + { 0x318e, 0x0000 }, + { 0x318f, 0xf000 }, + { 0x3190, 0x0000 }, + { 0x3191, 0xf000 }, + { 0x3192, 0x0000 }, + { 0x3193, 0xf000 }, + { 0x3194, 0x0000 }, + { 0x3195, 0xf000 }, + { 0x3196, 0x0000 }, + { 0x3197, 0xf000 }, + { 0x3198, 0x0000 }, + { 0x3199, 0xf000 }, + { 0x319a, 0x0000 }, + { 0x319b, 0xf000 }, + { 0x319c, 0x0000 }, + { 0x319d, 0xf000 }, + { 0x319e, 0x0000 }, + { 0x319f, 0xf000 }, + { 0x31a0, 0x0000 }, + { 0x31a1, 0xf000 }, + { 0x31a2, 0x0000 }, + { 0x31a3, 0xf000 }, + { 0x31a4, 0x0000 }, + { 0x31a5, 0xf000 }, + { 0x31a6, 0x0000 }, + { 0x31a7, 0xf000 }, + { 0x31a8, 0x0000 }, + { 0x31a9, 0xf000 }, + { 0x31aa, 0x0000 }, + { 0x31ab, 0xf000 }, + { 0x31ac, 0x0000 }, + { 0x31ad, 0xf000 }, + { 0x31ae, 0x0000 }, + { 0x31af, 0xf000 }, + { 0x31b0, 0x0000 }, + { 0x31b1, 0xf000 }, + { 0x31b2, 0x0000 }, + { 0x31b3, 0xf000 }, + { 0x31b4, 0x0000 }, + { 0x31b5, 0xf000 }, + { 0x31b6, 0x0000 }, + { 0x31b7, 0xf000 }, + { 0x31b8, 0x0000 }, + { 0x31b9, 0xf000 }, + { 0x31ba, 0x0000 }, + { 0x31bb, 0xf000 }, + { 0x31bc, 0x0000 }, + { 0x31bd, 0xf000 }, + { 0x31be, 0x0000 }, + { 0x31bf, 0xf000 }, + { 0x31c0, 0x0000 }, + { 0x31c1, 0xf000 }, + { 0x31c2, 0x0000 }, + { 0x31c3, 0xf000 }, + { 0x31c4, 0x0000 }, + { 0x31c5, 0xf000 }, + { 0x31c6, 0x0000 }, + { 0x31c7, 0xf000 }, + { 0x31c8, 0x0000 }, + { 0x31c9, 0xf000 }, + { 0x31ca, 0x0000 }, + { 0x31cb, 0xf000 }, + { 0x31cc, 0x0000 }, + { 0x31cd, 0xf000 }, + { 0x31ce, 0x0000 }, + { 0x31cf, 0xf000 }, + { 0x31d0, 0x0000 }, + { 0x31d1, 0xf000 }, + { 0x31d2, 0x0000 }, + { 0x31d3, 0xf000 }, + { 0x31d4, 0x0000 }, + { 0x31d5, 0xf000 }, + { 0x31d6, 0x0000 }, + { 0x31d7, 0xf000 }, + { 0x31d8, 0x0000 }, + { 0x31d9, 0xf000 }, + { 0x31da, 0x0000 }, + { 0x31db, 0xf000 }, + { 0x31dc, 0x0000 }, + { 0x31dd, 0xf000 }, + { 0x31de, 0x0000 }, + { 0x31df, 0xf000 }, + { 0x31e0, 0x0000 }, + { 0x31e1, 0xf000 }, + { 0x31e2, 0x0000 }, + { 0x31e3, 0xf000 }, + { 0x31e4, 0x0000 }, + { 0x31e5, 0xf000 }, + { 0x31e6, 0x0000 }, + { 0x31e7, 0xf000 }, + { 0x31e8, 0x0000 }, + { 0x31e9, 0xf000 }, + { 0x31ea, 0x0000 }, + { 0x31eb, 0xf000 }, + { 0x31ec, 0x0000 }, + { 0x31ed, 0xf000 }, + { 0x31ee, 0x0000 }, + { 0x31ef, 0xf000 }, + { 0x31f0, 0x0000 }, + { 0x31f1, 0xf000 }, + { 0x31f2, 0x0000 }, + { 0x31f3, 0xf000 }, + { 0x31f4, 0x0000 }, + { 0x31f5, 0xf000 }, + { 0x31f6, 0x0000 }, + { 0x31f7, 0xf000 }, + { 0x31f8, 0x0000 }, + { 0x31f9, 0xf000 }, + { 0x31fa, 0x0000 }, + { 0x31fb, 0xf000 }, + { 0x31fc, 0x0000 }, + { 0x31fd, 0xf000 }, + { 0x31fe, 0x0000 }, + { 0x31ff, 0xf000 }, + { 0x024d, 0xff50 }, + { 0x0252, 0xff50 }, + { 0x0259, 0x0112 }, + { 0x025e, 0x0112 }, +}; + +static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = w->codec; + struct arizona *arizona = dev_get_drvdata(codec->dev); + struct regmap *regmap = codec->control_data; + const struct reg_default *patch = NULL; + int i, patch_size; + + switch (arizona->rev) { + case 0: + patch = wm5102_sysclk_reva_patch; + patch_size = ARRAY_SIZE(wm5102_sysclk_reva_patch); + break; + } + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (patch) + for (i = 0; i < patch_size; i++) + regmap_write(regmap, patch[i].reg, + patch[i].def); + break; + + default: + break; + } + + return 0; +} + static const struct snd_kcontrol_new wm5102_snd_controls[] = { SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL, ARIZONA_IN1_OSR_SHIFT, 1, 0), @@ -297,7 +847,7 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux = static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, - 0, NULL, 0), + 0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 5421fd9fbcb..4c0a8e49613 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -782,7 +782,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, wm8978->mclk_idx = -1; f_sel = wm8978->f_mclk; } else { - if (!wm8978->f_pllout) { + if (!wm8978->f_opclk) { /* We only enter here, if OPCLK is not used */ int ret = wm8978_configure_pll(codec); if (ret < 0) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 2b2dadc54da..b2b2b37131b 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -1045,6 +1045,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; + struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); struct wm8994 *control = codec->control_data; int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; int i; @@ -1063,6 +1064,10 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: + /* Don't enable timeslot 2 if not in use */ + if (wm8994->channels[0] <= 2) + mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA); + val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1); if ((val & WM8994_AIF1ADCL_SRC) && (val & WM8994_AIF1ADCR_SRC)) @@ -2687,7 +2692,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - bclk_rate = params_rate(params) * 4; + bclk_rate = params_rate(params); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: bclk_rate *= 16; @@ -2708,6 +2713,17 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } + wm8994->channels[id] = params_channels(params); + switch (params_channels(params)) { + case 1: + case 2: + bclk_rate *= 2; + break; + default: + bclk_rate *= 4; + break; + } + /* Try to find an appropriate sample rate; look for an exact match. */ for (i = 0; i < ARRAY_SIZE(srs); i++) if (srs[i].rate == params_rate(params)) @@ -3706,7 +3722,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) } while (count--); if (count == 0) - dev_warn(codec->dev, "No impedence range reported for jack\n"); + dev_warn(codec->dev, "No impedance range reported for jack\n"); #ifndef CONFIG_SND_SOC_WM8994_MODULE trace_snd_soc_jack_irq(dev_name(codec->dev)); diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index f142ec198db..ccbce5791e9 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -77,6 +77,7 @@ struct wm8994_priv { int sysclk_rate[2]; int mclk[2]; int aifclk[2]; + int channels[2]; struct wm8994_fll_config fll[2], fll_suspend[2]; struct completion fll_locked[2]; bool fll_locked_irq; diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index b9f16598324..2ba08148655 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -71,7 +71,6 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id) printk(KERN_WARNING "%s: got err interrupt 0x%lx\n", __func__, cause); writel(cause, priv->io + KIRKWOOD_ERR_CAUSE); - return IRQ_HANDLED; } /* we've enabled only bytes interrupts ... */ @@ -178,7 +177,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream) } dram = mv_mbus_dram_info(); - addr = virt_to_phys(substream->dma_buffer.area); + addr = substream->dma_buffer.addr; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { prdata->play_stream = substream; kirkwood_dma_conf_mbus_windows(priv->io, diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c index 542538d10ab..1d5db484d2d 100644 --- a/sound/soc/kirkwood/kirkwood-i2s.c +++ b/sound/soc/kirkwood/kirkwood-i2s.c @@ -95,7 +95,7 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate) do { cpu_relax(); value = readl(io + KIRKWOOD_DCO_SPCR_STATUS); - value &= KIRKWOOD_DCO_SPCR_STATUS; + value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK; } while (value == 0); } @@ -180,67 +180,72 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai); - unsigned long value; - - /* - * specs says KIRKWOOD_PLAYCTL must be read 2 times before - * changing it. So read 1 time here and 1 later. - */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); + uint32_t ctl, value; + + ctl = readl(priv->io + KIRKWOOD_PLAYCTL); + if (ctl & KIRKWOOD_PLAYCTL_PAUSE) { + unsigned timeout = 5000; + /* + * The Armada510 spec says that if we enter pause mode, the + * busy bit must be read back as clear _twice_. Make sure + * we respect that otherwise we get DMA underruns. + */ + do { + value = ctl; + ctl = readl(priv->io + KIRKWOOD_PLAYCTL); + if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)) + break; + udelay(1); + } while (timeout--); + + if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY) + dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n", + ctl); + } switch (cmd) { case SNDRV_PCM_TRIGGER_START: - /* stop audio, enable interrupts */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value |= KIRKWOOD_PLAYCTL_PAUSE; - writel(value, priv->io + KIRKWOOD_PLAYCTL); - value = readl(priv->io + KIRKWOOD_INT_MASK); value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES; writel(value, priv->io + KIRKWOOD_INT_MASK); /* configure audio & enable i2s playback */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value &= ~KIRKWOOD_PLAYCTL_BURST_MASK; - value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE + ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK; + ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE | KIRKWOOD_PLAYCTL_SPDIF_EN); if (priv->burst == 32) - value |= KIRKWOOD_PLAYCTL_BURST_32; + ctl |= KIRKWOOD_PLAYCTL_BURST_32; else - value |= KIRKWOOD_PLAYCTL_BURST_128; - value |= KIRKWOOD_PLAYCTL_I2S_EN; - writel(value, priv->io + KIRKWOOD_PLAYCTL); + ctl |= KIRKWOOD_PLAYCTL_BURST_128; + ctl |= KIRKWOOD_PLAYCTL_I2S_EN; + writel(ctl, priv->io + KIRKWOOD_PLAYCTL); break; case SNDRV_PCM_TRIGGER_STOP: /* stop audio, disable interrupts */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; - writel(value, priv->io + KIRKWOOD_PLAYCTL); + ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; + writel(ctl, priv->io + KIRKWOOD_PLAYCTL); value = readl(priv->io + KIRKWOOD_INT_MASK); value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES; writel(value, priv->io + KIRKWOOD_INT_MASK); /* disable all playbacks */ - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN); - writel(value, priv->io + KIRKWOOD_PLAYCTL); + ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN); + writel(ctl, priv->io + KIRKWOOD_PLAYCTL); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; - writel(value, priv->io + KIRKWOOD_PLAYCTL); + ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE; + writel(ctl, priv->io + KIRKWOOD_PLAYCTL); break; case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - value = readl(priv->io + KIRKWOOD_PLAYCTL); - value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE); - writel(value, priv->io + KIRKWOOD_PLAYCTL); + ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE); + writel(ctl, priv->io + KIRKWOOD_PLAYCTL); break; default: @@ -260,11 +265,6 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, switch (cmd) { case SNDRV_PCM_TRIGGER_START: - /* stop audio, enable interrupts */ - value = readl(priv->io + KIRKWOOD_RECCTL); - value |= KIRKWOOD_RECCTL_PAUSE; - writel(value, priv->io + KIRKWOOD_RECCTL); - value = readl(priv->io + KIRKWOOD_INT_MASK); value |= KIRKWOOD_INT_CAUSE_REC_BYTES; writel(value, priv->io + KIRKWOOD_INT_MASK); diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index aa037b292f3..c294fbb523f 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -523,16 +523,24 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* - * write a data to saif data register to trigger - * the transfer + * write data to saif data register to trigger + * the transfer. + * For 24-bit format the 32-bit FIFO register stores + * only one channel, so we need to write twice. + * This is also safe for the other non 24-bit formats. */ __raw_writel(0, saif->base + SAIF_DATA); + __raw_writel(0, saif->base + SAIF_DATA); } else { /* - * read a data from saif data register to trigger - * the receive + * read data from saif data register to trigger + * the receive. + * For 24-bit format the 32-bit FIFO register stores + * only one channel, so we need to read twice. + * This is also safe for the other non 24-bit formats. */ __raw_readl(saif->base + SAIF_DATA); + __raw_readl(saif->base + SAIF_DATA); } master_saif->ongoing = 1; @@ -812,3 +820,4 @@ module_platform_driver(mxs_saif_driver); MODULE_AUTHOR("Freescale Semiconductor, Inc."); MODULE_DESCRIPTION("MXS ASoC SAIF driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mxs-saif"); diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index dc0ee762662..d8e96b2cd03 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -575,56 +575,53 @@ static struct snd_soc_card ams_delta_audio_card = { }; /* Module init/exit */ -static struct platform_device *ams_delta_audio_platform_device; -static struct platform_device *cx20442_platform_device; - -static int __init ams_delta_module_init(void) +static __devinit int ams_delta_probe(struct platform_device *pdev) { + struct snd_soc_card *card = &ams_delta_audio_card; int ret; - if (!(machine_is_ams_delta())) - return -ENODEV; - - ams_delta_audio_platform_device = - platform_device_alloc("soc-audio", -1); - if (!ams_delta_audio_platform_device) - return -ENOMEM; + card->dev = &pdev->dev; - platform_set_drvdata(ams_delta_audio_platform_device, - &ams_delta_audio_card); - - ret = platform_device_add(ams_delta_audio_platform_device); - if (ret) - goto err; - - /* - * Codec platform device could be registered from elsewhere (board?), - * but I do it here as it makes sense only if used with the card. - */ - cx20442_platform_device = - platform_device_register_simple("cx20442-codec", -1, NULL, 0); + ret = snd_soc_register_card(card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + card->dev = NULL; + return ret; + } return 0; -err: - platform_device_put(ams_delta_audio_platform_device); - return ret; } -late_initcall(ams_delta_module_init); -static void __exit ams_delta_module_exit(void) +static int __devexit ams_delta_remove(struct platform_device *pdev) { + struct snd_soc_card *card = platform_get_drvdata(pdev); + if (tty_unregister_ldisc(N_V253) != 0) - dev_warn(&ams_delta_audio_platform_device->dev, + dev_warn(&pdev->dev, "failed to unregister V253 line discipline\n"); snd_soc_jack_free_gpios(&ams_delta_hook_switch, ARRAY_SIZE(ams_delta_hook_switch_gpios), ams_delta_hook_switch_gpios); - platform_device_unregister(cx20442_platform_device); - platform_device_unregister(ams_delta_audio_platform_device); + snd_soc_unregister_card(card); + card->dev = NULL; + return 0; } -module_exit(ams_delta_module_exit); + +#define DRV_NAME "ams-delta-audio" + +static struct platform_driver ams_delta_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = ams_delta_probe, + .remove = __devexit_p(ams_delta_remove), +}; + +module_platform_driver(ams_delta_driver); MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>"); MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 4a73ef3ae12..a57a4e68dcc 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -216,7 +216,7 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); - twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); + twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator"); twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 68f2cd1a920..5a6aeaf552a 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -464,9 +464,9 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev) mutex_init(&dmic->mutex); - dmic->fclk = clk_get(dmic->dev, "dmic_fck"); + dmic->fclk = clk_get(dmic->dev, "fck"); if (IS_ERR(dmic->fclk)) { - dev_err(dmic->dev, "cant get dmic_fck\n"); + dev_err(dmic->dev, "cant get fck\n"); return -ENODEV; } diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index c02b001ee4b..56965bb3275 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -40,7 +40,6 @@ #include <sound/pcm_params.h> #include <sound/soc.h> -#include <plat/omap_hwmod.h> #include "omap-mcpdm.h" #include "omap-pcm.h" @@ -260,13 +259,9 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, mutex_lock(&mcpdm->mutex); if (!dai->active) { - /* Enable watch dog for ES above ES 1.0 to avoid saturation */ - if (omap_rev() != OMAP4430_REV_ES1_0) { - u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); + u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL); - omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, - ctrl | MCPDM_WD_EN); - } + omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN); omap_mcpdm_open_streams(mcpdm); } mutex_unlock(&mcpdm->mutex); diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 677b567935f..1ff6bb9ade5 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c @@ -21,15 +21,14 @@ #include <linux/clk.h> #include <linux/platform_device.h> +#include <linux/gpio.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/soc.h> #include <asm/mach-types.h> -#include <mach/hardware.h> -#include <mach/gpio.h> -#include <mach/board-zoom.h> #include <linux/platform_data/asoc-ti-mcbsp.h> +#include <linux/platform_data/gpio-omap.h> /* Register descriptions for twl4030 codec part */ #include <linux/mfd/twl4030-audio.h> diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 73ac5463c9e..e834faf859f 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c @@ -15,13 +15,13 @@ #include <linux/slab.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> +#include <linux/platform_data/dma-mmp_tdma.h> #include <linux/platform_data/mmp_audio.h> #include <sound/pxa2xx-lib.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> -#include <mach/sram.h> #include <sound/dmaengine_pcm.h> struct mmp_dma_data { diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index e7b83179aca..3c7c3a59ed3 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig @@ -207,6 +207,8 @@ config SND_SOC_BELLS select SND_SOC_WM5102 select SND_SOC_WM5110 select SND_SOC_WM9081 + select SND_SOC_WM0010 + select SND_SOC_WM1250_EV1 config SND_SOC_LOWLAND tristate "Audio support for Wolfson Lowland" diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c index 5dc10dfc0d4..a2ca1567b9e 100644 --- a/sound/soc/samsung/bells.c +++ b/sound/soc/samsung/bells.c @@ -247,7 +247,7 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = { { .name = "Sub", .stream_name = "Sub", - .cpu_dai_name = "wm5102-aif3", + .cpu_dai_name = "wm5110-aif3", .codec_dai_name = "wm9081-hifi", .codec_name = "wm9081.1-006c", .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 5328ae5539f..9d7f30774a4 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -20,6 +20,7 @@ #include <linux/sh_dma.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/workqueue.h> #include <sound/soc.h> #include <sound/sh_fsi.h> @@ -223,7 +224,7 @@ struct fsi_stream { */ struct dma_chan *chan; struct sh_dmae_slave slave; /* see fsi_handler_init() */ - struct tasklet_struct tasklet; + struct work_struct work; dma_addr_t dma; }; @@ -1085,9 +1086,9 @@ static void fsi_dma_complete(void *data) snd_pcm_period_elapsed(io->substream); } -static void fsi_dma_do_tasklet(unsigned long data) +static void fsi_dma_do_work(struct work_struct *work) { - struct fsi_stream *io = (struct fsi_stream *)data; + struct fsi_stream *io = container_of(work, struct fsi_stream, work); struct fsi_priv *fsi = fsi_stream_to_priv(io); struct snd_soc_dai *dai; struct dma_async_tx_descriptor *desc; @@ -1129,7 +1130,7 @@ static void fsi_dma_do_tasklet(unsigned long data) * FIXME * * In DMAEngine case, codec and FSI cannot be started simultaneously - * since FSI is using tasklet. + * since FSI is using the scheduler work queue. * Therefore, in capture case, probably FSI FIFO will have got * overflow error in this point. * in that case, DMA cannot start transfer until error was cleared. @@ -1153,7 +1154,7 @@ static bool fsi_dma_filter(struct dma_chan *chan, void *param) static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) { - tasklet_schedule(&io->tasklet); + schedule_work(&io->work); return 0; } @@ -1195,14 +1196,14 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev return fsi_stream_probe(fsi, dev); } - tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); + INIT_WORK(&io->work, fsi_dma_do_work); return 0; } static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) { - tasklet_kill(&io->tasklet); + cancel_work_sync(&io->work); fsi_stream_stop(fsi, io); diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d1198627fc4..10d21be383f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2786,8 +2786,9 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, val = (ucontrol->value.integer.value[0] + min) & mask; val = val << shift; - if (snd_soc_update_bits_locked(codec, reg, val_mask, val)) - return err; + err = snd_soc_update_bits_locked(codec, reg, val_mask, val); + if (err < 0) + return err; if (snd_soc_volsw_is_stereo(mc)) { val_mask = mask << rshift; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index d0a4be38dc0..6e35bcae02d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3745,7 +3745,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) { struct snd_soc_codec *codec; - list_for_each_entry(codec, &card->codec_dev_list, list) { + list_for_each_entry(codec, &card->codec_dev_list, card_list) { soc_dapm_shutdown_codec(&codec->dapm); if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) snd_soc_dapm_set_bias_level(&codec->dapm, diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index fa0fd8ddae9..1ab5fe04bfc 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -22,7 +22,7 @@ /** * snd_soc_jack_new - Create a new jack - * @card: ASoC card + * @codec: ASoC codec * @id: an identifying string for this jack * @type: a bitmask of enum snd_jack_type values that can be detected by * this jack @@ -133,12 +133,13 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_add_zones); /** * snd_soc_jack_get_type - Based on the mic bias value, this function returns - * the type of jack from the zones delcared in the jack type + * the type of jack from the zones declared in the jack type * + * @jack: ASoC jack * @micbias_voltage: mic bias voltage at adc channel when jack is plugged in * * Based on the mic bias value passed, this function helps identify - * the type of jack from the already delcared jack zones + * the type of jack from the already declared jack zones */ int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage) { diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index 356611d9654..54f7e25b6f7 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -57,6 +57,20 @@ static struct snd_soc_card mop500_card = { .num_links = ARRAY_SIZE(mop500_dai_links), }; +static void mop500_of_node_put(void) +{ + int i; + + for (i = 0; i < 2; i++) { + if (mop500_dai_links[i].cpu_of_node) + of_node_put((struct device_node *) + mop500_dai_links[i].cpu_of_node); + if (mop500_dai_links[i].codec_of_node) + of_node_put((struct device_node *) + mop500_dai_links[i].codec_of_node); + } +} + static int __devinit mop500_of_probe(struct platform_device *pdev, struct device_node *np) { @@ -69,6 +83,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev, if (!(msp_np[0] && msp_np[1] && codec_np)) { dev_err(&pdev->dev, "Phandle missing or invalid\n"); + mop500_of_node_put(); return -EINVAL; } @@ -83,6 +98,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev, return 0; } + static int __devinit mop500_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -128,6 +144,7 @@ static int __devexit mop500_remove(struct platform_device *pdev) snd_soc_unregister_card(mop500_card); mop500_ab8500_remove(mop500_card); + mop500_of_node_put(); return 0; } diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index b7c996e7757..a26c6bf0a29 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c @@ -18,6 +18,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/io.h> #include <linux/of.h> #include <mach/hardware.h> @@ -697,14 +698,11 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, platform_data = devm_kzalloc(&pdev->dev, sizeof(struct msp_i2s_platform_data), GFP_KERNEL); if (!platform_data) - ret = -ENOMEM; + return -ENOMEM; } } else if (!platform_data) - ret = -EINVAL; - - if (ret) - goto err_res; + return -EINVAL; dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__, pdev->name, platform_data->id); diff --git a/sound/usb/card.c b/sound/usb/card.c index 561bb74fd36..dbf7999d18b 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, } mutex_init(&chip->mutex); - mutex_init(&chip->shutdown_mutex); + init_rwsem(&chip->shutdown_rwsem); chip->index = idx; chip->dev = dev; chip->card = card; @@ -559,9 +559,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, return; card = chip->card; - mutex_lock(®ister_mutex); - mutex_lock(&chip->shutdown_mutex); + down_write(&chip->shutdown_rwsem); chip->shutdown = 1; + up_write(&chip->shutdown_rwsem); + + mutex_lock(®ister_mutex); chip->num_interfaces--; if (chip->num_interfaces <= 0) { snd_card_disconnect(card); @@ -582,11 +584,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, snd_usb_mixer_disconnect(p); } usb_chip[chip->index] = NULL; - mutex_unlock(&chip->shutdown_mutex); mutex_unlock(®ister_mutex); snd_card_free_when_closed(card); } else { - mutex_unlock(&chip->shutdown_mutex); mutex_unlock(®ister_mutex); } } @@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) { int err = -ENODEV; + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) err = usb_autopm_get_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); return err; } void snd_usb_autosuspend(struct snd_usb_audio *chip) { + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) usb_autopm_put_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); } static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/sound/usb/card.h b/sound/usb/card.h index afa4f9e9b27..814cb357ff8 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -126,6 +126,7 @@ struct snd_usb_substream { struct snd_usb_endpoint *sync_endpoint; unsigned long flags; bool need_setup_ep; /* (re)configure EP at prepare? */ + unsigned int speed; /* USB_SPEED_XXX */ u64 formats; /* format bitmasks (all or'ed) */ unsigned int num_formats; /* number of supported audio formats (list) */ diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 7f78c6d782b..34de6f2faf6 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -35,6 +35,7 @@ #define EP_FLAG_ACTIVATED 0 #define EP_FLAG_RUNNING 1 +#define EP_FLAG_STOPPING 2 /* * snd_usb_endpoint is a model that abstracts everything related to an @@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep) if (alive) snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n", alive, ep->ep_num); + clear_bit(EP_FLAG_STOPPING, &ep->flags); return 0; } +/* sync the pending stop operation; + * this function itself doesn't trigger the stop operation + */ +void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep) +{ + if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags)) + wait_clear_urbs(ep); +} + /* * unlink active urbs. */ @@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, if (wait) wait_clear_urbs(ep); + else + set_bit(EP_FLAG_STOPPING, &ep->flags); } } diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 6376ccf10fd..3d4c9705041 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, int force, int can_sleep, int wait); +void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep); int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep); void snd_usb_endpoint_free(struct list_head *head); diff --git a/sound/usb/midi.c b/sound/usb/midi.c index c83f6143c0e..eeefbce3873 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint { struct snd_usb_midi_out_endpoint* ep; struct snd_rawmidi_substream *substream; int active; + bool autopm_reference; uint8_t cable; /* cable number << 4 */ uint8_t state; #define STATE_UNKNOWN 0 @@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) return -ENXIO; } err = usb_autopm_get_interface(umidi->iface); - if (err < 0) + port->autopm_reference = err >= 0; + if (err < 0 && err != -EACCES) return -EIO; substream->runtime->private_data = port; port->state = STATE_UNKNOWN; @@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) { struct snd_usb_midi* umidi = substream->rmidi->private_data; + struct usbmidi_out_port *port = substream->runtime->private_data; substream_open(substream, 0); - usb_autopm_put_interface(umidi->iface); + if (port->autopm_reference) + usb_autopm_put_interface(umidi->iface); return 0; } diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index fe56c9da38e..298070e8f2d 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v unsigned char buf[2]; int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; int timeout = 10; - int err; + int idx = 0, err; err = snd_usb_autoresume(cval->mixer->chip); if (err < 0) return -EIO; + down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { + if (chip->shutdown) + break; + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= val_len) { + validx, idx, buf, val_len) >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); - snd_usb_autosuspend(cval->mixer->chip); - return 0; + err = 0; + goto out; } } - snd_usb_autosuspend(cval->mixer->chip); snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); - return -EINVAL; + request, validx, idx, cval->val_type); + err = -EINVAL; + + out: + up_read(&chip->shutdown_rwsem); + snd_usb_autosuspend(cval->mixer->chip); + return err; } static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) @@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ unsigned char *val; - int ret, size; + int idx = 0, ret, size; __u8 bRequest; if (request == UAC_GET_CUR) { @@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v if (ret) goto error; - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, + down_read(&chip->shutdown_rwsem); + if (chip->shutdown) + ret = -ENODEV; + else { + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, size); + validx, idx, buf, size); + } + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(chip); if (ret < 0) { error: snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); + request, validx, idx, cval->val_type); return ret; } @@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, { struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2]; - int val_len, err, timeout = 10; + int idx = 0, val_len, err, timeout = 10; if (cval->mixer->protocol == UAC_VERSION_1) { val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; @@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = snd_usb_autoresume(chip); if (err < 0) return -EIO; - while (timeout-- > 0) + down_read(&chip->shutdown_rwsem); + while (timeout-- > 0) { + if (chip->shutdown) + break; + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); if (snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= 0) { - snd_usb_autosuspend(chip); - return 0; + validx, idx, buf, val_len) >= 0) { + err = 0; + goto out; } - snd_usb_autosuspend(chip); + } snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); - return -EINVAL; + request, validx, idx, cval->val_type, buf[0], buf[1]); + err = -EINVAL; + + out: + up_read(&chip->shutdown_rwsem); + snd_usb_autosuspend(chip); + return err; } static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 690000db0ec..ae2b7143522 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (value > 1) return -EINVAL; changed = value != mixer->audigy2nx_leds[index]; + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) { + err = -ENODEV; + goto out; + } if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, @@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, value, index + 2, NULL, 0); + out: + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->audigy2nx_leds[index] = value; @@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, for (i = 0; jacks[i].name; ++i) { snd_iprintf(buffer, "%s: ", jacks[i].name); - err = snd_usb_ctl_msg(mixer->chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = 0; + else + err = snd_usb_ctl_msg(mixer->chip->dev, usb_rcvctrlpipe(mixer->chip->dev, 0), UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, jacks[i].unitid << 8, buf, 3); + up_read(&mixer->chip->shutdown_rwsem); if (err == 3 && (buf[0] == 3 || buf[0] == 6)) snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); else @@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, else new_status = old_status & ~0x02; changed = new_status != old_status; - err = snd_usb_ctl_msg(mixer->chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, 50, 0, &new_status, 1); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->xonar_u1_status = new_status; @@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u8 tmp; + int ret; - int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + ret = -ENODEV; + else + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0, cpu_to_le16(wIndex), &tmp, sizeof(tmp), 1000); + up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR @@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u16 wValue = ucontrol->value.integer.value[0]; + int ret; - int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + ret = -ENODEV; + else + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, cpu_to_le16(wValue), cpu_to_le16(wIndex), NULL, 0, 1000); + up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR @@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, return -EINVAL; - err = snd_usb_ctl_msg(chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), value, val_len); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; @@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, if (!pval->is_cached) { /* Read current value */ - err = snd_usb_ctl_msg(chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), value, val_len); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; @@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, if (cur_val != new_val) { value[0] = new_val; value[1] = 0; - err = snd_usb_ctl_msg(chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), value, val_len); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 55e19e1b80e..ef6fa24fc47 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream unsigned int hwptr_done; subs = (struct snd_usb_substream *)substream->runtime->private_data; + if (subs->stream->chip->shutdown) + return SNDRV_PCM_POS_XRUN; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; substream->runtime->delay = snd_usb_pcm_delay(subs, @@ -444,7 +446,6 @@ static int configure_endpoint(struct snd_usb_substream *subs) { int ret; - mutex_lock(&subs->stream->chip->shutdown_mutex); /* format changed */ stop_endpoints(subs, 0, 0, 0); ret = snd_usb_endpoint_set_params(subs->data_endpoint, @@ -455,19 +456,16 @@ static int configure_endpoint(struct snd_usb_substream *subs) subs->cur_audiofmt, subs->sync_endpoint); if (ret < 0) - goto unlock; + return ret; if (subs->sync_endpoint) - ret = snd_usb_endpoint_set_params(subs->data_endpoint, + ret = snd_usb_endpoint_set_params(subs->sync_endpoint, subs->pcm_format, subs->channels, subs->period_bytes, subs->cur_rate, subs->cur_audiofmt, NULL); - -unlock: - mutex_unlock(&subs->stream->chip->shutdown_mutex); return ret; } @@ -505,7 +503,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - if ((ret = set_format(subs, fmt)) < 0) + down_read(&subs->stream->chip->shutdown_rwsem); + if (subs->stream->chip->shutdown) + ret = -ENODEV; + else + ret = set_format(subs, fmt); + up_read(&subs->stream->chip->shutdown_rwsem); + if (ret < 0) return ret; subs->interface = fmt->iface; @@ -527,10 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; - mutex_lock(&subs->stream->chip->shutdown_mutex); - stop_endpoints(subs, 0, 1, 1); - deactivate_endpoints(subs); - mutex_unlock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); + if (!subs->stream->chip->shutdown) { + stop_endpoints(subs, 0, 1, 1); + deactivate_endpoints(subs); + } + up_read(&subs->stream->chip->shutdown_rwsem); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -552,12 +558,22 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) return -ENXIO; } - if (snd_BUG_ON(!subs->data_endpoint)) - return -EIO; + down_read(&subs->stream->chip->shutdown_rwsem); + if (subs->stream->chip->shutdown) { + ret = -ENODEV; + goto unlock; + } + if (snd_BUG_ON(!subs->data_endpoint)) { + ret = -EIO; + goto unlock; + } + + snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint); + snd_usb_endpoint_sync_pending_stop(subs->data_endpoint); ret = set_format(subs, subs->cur_audiofmt); if (ret < 0) - return ret; + goto unlock; iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; @@ -567,12 +583,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->cur_audiofmt, subs->cur_rate); if (ret < 0) - return ret; + goto unlock; if (subs->need_setup_ep) { ret = configure_endpoint(subs); if (ret < 0) - return ret; + goto unlock; subs->need_setup_ep = false; } @@ -592,9 +608,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) /* 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) - return start_endpoints(subs, 1); + ret = start_endpoints(subs, 1); - return 0; + unlock: + up_read(&subs->stream->chip->shutdown_rwsem); + return ret; } static struct snd_pcm_hardware snd_usb_hardware = @@ -647,7 +665,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, return 0; } /* check whether the period time is >= the data packet interval */ - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { + if (subs->speed != USB_SPEED_FULL) { ptime = 125 * (1 << fp->datainterval); if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); @@ -925,7 +943,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre return err; param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; - if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) + if (subs->speed == USB_SPEED_FULL) /* full speed devices have fixed data packet interval */ ptmin = 1000; if (ptmin == 1000) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index ebc1a5b5b3f..d218f763501 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s } snd_iprintf(buffer, "\n"); } - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) + if (subs->speed != USB_SPEED_FULL) snd_iprintf(buffer, " Data packet interval: %d us\n", 125 * (1 << fp->datainterval)); // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); @@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs, return; snd_iprintf(buffer, " Packet Size = %d\n", ep->curpacksize); snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", - snd_usb_get_speed(subs->dev) == USB_SPEED_FULL + subs->speed == USB_SPEED_FULL ? get_full_speed_hz(ep->freqm) : get_high_speed_hz(ep->freqm), ep->freqm >> 16, ep->freqm & 0xffff); diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 083ed81160e..1de0c8c002a 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, subs->direction = stream; subs->dev = as->chip->dev; subs->txfr_quirk = as->chip->txfr_quirk; + subs->speed = snd_usb_get_speed(subs->dev); snd_usb_set_pcm_ops(as->pcm, stream); diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index b8233ebe250..ef42797f56f 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -37,7 +37,7 @@ struct snd_usb_audio { struct usb_interface *pm_intf; u32 usb_id; struct mutex mutex; - struct mutex shutdown_mutex; + struct rw_semaphore shutdown_rwsem; unsigned int shutdown:1; unsigned int probing:1; unsigned int autosuspended:1; diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 47264b4652b..f2989c525e4 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -2602,6 +2602,9 @@ find_func_handler(struct pevent *pevent, char *func_name) { struct pevent_function_handler *func; + if (!pevent) + return NULL; + for (func = pevent->func_handlers; func; func = func->next) { if (strcmp(func->name, func_name) == 0) break; @@ -4938,6 +4941,9 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp, goto event_alloc_failed; } + /* Add pevent to event so that it can be referenced */ + event->pevent = pevent; + ret = event_read_format(event); if (ret < 0) { ret = PEVENT_ERRNO__READ_FORMAT_FAILED; @@ -5041,9 +5047,6 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, if (event == NULL) return ret; - /* Add pevent to event so that it can be referenced */ - event->pevent = pevent; - if (add_event(pevent, event)) { ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; goto event_add_failed; diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index ad17855528f..5ea4326ad11 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -209,7 +209,16 @@ static void free_arg(struct filter_arg *arg) switch (arg->type) { case FILTER_ARG_NONE: case FILTER_ARG_BOOLEAN: + break; + case FILTER_ARG_NUM: + free_arg(arg->num.left); + free_arg(arg->num.right); + break; + + case FILTER_ARG_EXP: + free_arg(arg->exp.left); + free_arg(arg->exp.right); break; case FILTER_ARG_STR: @@ -218,6 +227,12 @@ static void free_arg(struct filter_arg *arg) free(arg->str.buffer); break; + case FILTER_ARG_VALUE: + if (arg->value.type == FILTER_STRING || + arg->value.type == FILTER_CHAR) + free(arg->value.str); + break; + case FILTER_ARG_OP: free_arg(arg->op.left); free_arg(arg->op.right); diff --git a/tools/perf/Makefile b/tools/perf/Makefile index f7c968ad517..00deed4d615 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -184,9 +184,22 @@ SCRIPT_SH += perf-archive.sh grep-libs = $(filter -l%,$(1)) strip-libs = $(filter-out -l%,$(1)) +TRACE_EVENT_DIR = ../lib/traceevent/ + +ifneq ($(OUTPUT),) + TE_PATH=$(OUTPUT) +else + TE_PATH=$(TRACE_EVENT_DIR) +endif + +LIBTRACEEVENT = $(TE_PATH)libtraceevent.a +TE_LIB := -L$(TE_PATH) -ltraceevent + PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py +export LIBTRACEEVENT + $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ --quiet build_ext; \ @@ -198,17 +211,6 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) -TRACE_EVENT_DIR = ../lib/traceevent/ - -ifneq ($(OUTPUT),) - TE_PATH=$(OUTPUT) -else - TE_PATH=$(TRACE_EVENT_DIR) -endif - -LIBTRACEEVENT = $(TE_PATH)libtraceevent.a -TE_LIB := -L$(TE_PATH) -ltraceevent - # # Single 'perf' binary right now: # diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 411ee5664e9..178b88ae3d2 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -414,7 +414,7 @@ static int show_html_page(const char *perf_cmd) int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) { bool show_all = false; - enum help_format help_format = HELP_FORMAT_NONE; + enum help_format help_format = HELP_FORMAT_MAN; struct option builtin_help_options[] = { OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index dec8ced61fb..7aaee39f677 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -56,6 +56,10 @@ static int trace__read_syscall_info(struct trace *trace, int id) { char tp_name[128]; struct syscall *sc; + const char *name = audit_syscall_to_name(id, trace->audit_machine); + + if (name == NULL) + return -1; if (id > trace->syscalls.max) { struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); @@ -75,11 +79,8 @@ static int trace__read_syscall_info(struct trace *trace, int id) } sc = trace->syscalls.table + id; - sc->name = audit_syscall_to_name(id, trace->audit_machine); - if (sc->name == NULL) - return -1; - - sc->fmt = syscall_fmt__find(sc->name); + sc->name = name; + sc->fmt = syscall_fmt__find(sc->name); snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); sc->tp_format = event_format__new("syscalls", tp_name); @@ -267,6 +268,13 @@ again: if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1) printf("%d ", sample.tid); + if (sample.raw_data == NULL) { + printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", + perf_evsel__name(evsel), sample.tid, + sample.cpu, sample.raw_size); + continue; + } + handler = evsel->handler.func; handler(trace, evsel, &sample); } diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 276287783a0..c50985eaec4 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -57,7 +57,7 @@ void get_term_dimensions(struct winsize *ws); #endif #ifdef __sparc__ -#include "../../arch/sparc/include/asm/unistd.h" +#include "../../arch/sparc/include/uapi/asm/unistd.h" #define rmb() asm volatile("":::"memory") #define cpu_relax() asm volatile("":::"memory") #define CPUINFO_PROC "cpu" diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 0568536ecf6..ef2f93ca749 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -610,6 +610,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, char folded_sign = ' '; bool current_entry = ui_browser__is_current_entry(&browser->b, row); off_t row_offset = entry->row_offset; + bool first = true; if (current_entry) { browser->he_selection = entry; @@ -633,10 +634,11 @@ static int hist_browser__show_entry(struct hist_browser *browser, if (!perf_hpp__format[i].cond) continue; - if (i) { + if (!first) { slsmg_printf(" "); width -= 2; } + first = false; if (perf_hpp__format[i].color) { hpp.ptr = &percent; @@ -645,7 +647,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, ui_browser__set_percent_color(&browser->b, percent, current_entry); - if (i == 0 && symbol_conf.use_callchain) { + if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) { slsmg_printf("%c ", folded_sign); width -= 2; } diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/util/parse-events-test.c index 28c18d1d52c..516ecd9ddd6 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/util/parse-events-test.c @@ -513,7 +513,8 @@ static int test__group1(struct perf_evlist *evlist) TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); + /* use of precise requires exclude_guest */ + TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); @@ -599,7 +600,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); + /* use of precise requires exclude_guest */ + TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); @@ -662,7 +664,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); + /* use of precise requires exclude_guest */ + TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); TEST_ASSERT_VAL("wrong group name", !evsel->group_name); @@ -676,7 +679,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused) TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); - TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); + /* use of precise requires exclude_guest */ + TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest); TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index aed38e4b9df..75c7b0fca6d 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -690,6 +690,9 @@ static int get_event_modifier(struct event_modifier *mod, char *str, eH = 0; } else if (*str == 'p') { precise++; + /* use of precise requires exclude_guest */ + if (!exclude_GH) + eG = 1; } else break; diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index d0f9f29cf18..73d51026978 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py @@ -23,6 +23,7 @@ cflags += getenv('CFLAGS', '').split() build_lib = getenv('PYTHON_EXTBUILD_LIB') build_tmp = getenv('PYTHON_EXTBUILD_TMP') +libtraceevent = getenv('LIBTRACEEVENT') ext_sources = [f.strip() for f in file('util/python-ext-sources') if len(f.strip()) > 0 and f[0] != '#'] @@ -31,6 +32,7 @@ perf = Extension('perf', sources = ext_sources, include_dirs = ['util/include'], extra_compile_args = cflags, + extra_objects = [libtraceevent], ) setup(name='perf', diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index b5b1b921196..cfd1c0feb32 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -260,6 +260,12 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, if (path != NULL) goto out_path; + if (!self->ms.map) + goto out_ip; + + if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10)) + goto out_ip; + snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64, self->ms.map->dso->long_name, self->ip); fp = popen(cmd, "r"); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index fb4b7ea6752..8b3e5939afb 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm) err = self->comm == NULL ? -ENOMEM : 0; if (!err) { self->comm_set = true; - map_groups__flush(&self->mg); } return err; } diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 2655ae9a3ad..ea095abbe97 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -206,8 +206,10 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) retval = pread(fd, msr, sizeof *msr, offset); close(fd); - if (retval != sizeof *msr) + if (retval != sizeof *msr) { + fprintf(stderr, "%s offset 0x%zx read failed\n", pathname, offset); return -1; + } return 0; } @@ -1101,7 +1103,9 @@ void turbostat_loop() restart: retval = for_all_cpus(get_counters, EVEN_COUNTERS); - if (retval) { + if (retval < -1) { + exit(retval); + } else if (retval == -1) { re_initialize(); goto restart; } @@ -1114,7 +1118,9 @@ restart: } sleep(interval_sec); retval = for_all_cpus(get_counters, ODD_COUNTERS); - if (retval) { + if (retval < -1) { + exit(retval); + } else if (retval == -1) { re_initialize(); goto restart; } @@ -1126,7 +1132,9 @@ restart: flush_stdout(); sleep(interval_sec); retval = for_all_cpus(get_counters, EVEN_COUNTERS); - if (retval) { + if (retval < -1) { + exit(retval); + } else if (retval == -1) { re_initialize(); goto restart; } @@ -1545,8 +1553,11 @@ void turbostat_init() int fork_it(char **argv) { pid_t child_pid; + int status; - for_all_cpus(get_counters, EVEN_COUNTERS); + status = for_all_cpus(get_counters, EVEN_COUNTERS); + if (status) + exit(status); /* clear affinity side-effect of get_counters() */ sched_setaffinity(0, cpu_present_setsize, cpu_present_set); gettimeofday(&tv_even, (struct timezone *)NULL); @@ -1556,7 +1567,6 @@ int fork_it(char **argv) /* child */ execvp(argv[0], argv); } else { - int status; /* parent */ if (child_pid == -1) { @@ -1568,7 +1578,7 @@ int fork_it(char **argv) signal(SIGQUIT, SIG_IGN); if (waitpid(child_pid, &status, 0) == -1) { perror("wait"); - exit(1); + exit(status); } } /* @@ -1585,7 +1595,7 @@ int fork_it(char **argv) fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0); - return 0; + return status; } void cmdline(int argc, char **argv) @@ -1594,7 +1604,7 @@ void cmdline(int argc, char **argv) progname = argv[0]; - while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) { + while ((opt = getopt(argc, argv, "+pPSvi:sc:sC:m:M:")) != -1) { switch (opt) { case 'p': show_core_only++; diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index b51d787176d..c7ba7614061 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1740,8 +1740,10 @@ sub install { open(IN, "$output_config") or dodie("Can't read config file"); while (<IN>) { if (/CONFIG_MODULES(=y)?/) { - $install_mods = 1 if (defined($1)); - last; + if (defined($1)) { + $install_mods = 1; + last; + } } } close(IN); diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 43480149119..85baf11e2ac 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -1,4 +1,4 @@ -TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll +TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug all: for TARGET in $(TARGETS); do \ diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile deleted file mode 100644 index 19806ed62f5..00000000000 --- a/tools/testing/selftests/epoll/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# Makefile for epoll selftests - -all: test_epoll -%: %.c - gcc -pthread -g -o $@ $^ - -run_tests: all - ./test_epoll - -clean: - $(RM) test_epoll diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c deleted file mode 100644 index e0fcff1e833..00000000000 --- a/tools/testing/selftests/epoll/test_epoll.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * tools/testing/selftests/epoll/test_epoll.c - * - * Copyright 2012 Adobe Systems Incorporated - * - * 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. - * - * Paton J. Lewis <palewis@adobe.com> - * - */ - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/epoll.h> -#include <sys/socket.h> - -/* - * A pointer to an epoll_item_private structure will be stored in the epoll - * item's event structure so that we can get access to the epoll_item_private - * data after calling epoll_wait: - */ -struct epoll_item_private { - int index; /* Position of this struct within the epoll_items array. */ - int fd; - uint32_t events; - pthread_mutex_t mutex; /* Guards the following variables... */ - int stop; - int status; /* Stores any error encountered while handling item. */ - /* The following variable allows us to test whether we have encountered - a problem while attempting to cancel and delete the associated - event. When the test program exits, 'deleted' should be exactly - one. If it is greater than one, then the failed test reflects a real - world situation where we would have tried to access the epoll item's - private data after deleting it: */ - int deleted; -}; - -struct epoll_item_private *epoll_items; - -/* - * Delete the specified item from the epoll set. In a real-world secneario this - * is where we would free the associated data structure, but in this testing - * environment we retain the structure so that we can test for double-deletion: - */ -void delete_item(int index) -{ - __sync_fetch_and_add(&epoll_items[index].deleted, 1); -} - -/* - * A pointer to a read_thread_data structure will be passed as the argument to - * each read thread: - */ -struct read_thread_data { - int stop; - int status; /* Indicates any error encountered by the read thread. */ - int epoll_set; -}; - -/* - * The function executed by the read threads: - */ -void *read_thread_function(void *function_data) -{ - struct read_thread_data *thread_data = - (struct read_thread_data *)function_data; - struct epoll_event event_data; - struct epoll_item_private *item_data; - char socket_data; - - /* Handle events until we encounter an error or this thread's 'stop' - condition is set: */ - while (1) { - int result = epoll_wait(thread_data->epoll_set, - &event_data, - 1, /* Number of desired events */ - 1000); /* Timeout in ms */ - if (result < 0) { - /* Breakpoints signal all threads. Ignore that while - debugging: */ - if (errno == EINTR) - continue; - thread_data->status = errno; - return 0; - } else if (thread_data->stop) - return 0; - else if (result == 0) /* Timeout */ - continue; - - /* We need the mutex here because checking for the stop - condition and re-enabling the epoll item need to be done - together as one atomic operation when EPOLL_CTL_DISABLE is - available: */ - item_data = (struct epoll_item_private *)event_data.data.ptr; - pthread_mutex_lock(&item_data->mutex); - - /* Remove the item from the epoll set if we want to stop - handling that event: */ - if (item_data->stop) - delete_item(item_data->index); - else { - /* Clear the data that was written to the other end of - our non-blocking socket: */ - do { - if (read(item_data->fd, &socket_data, 1) < 1) { - if ((errno == EAGAIN) || - (errno == EWOULDBLOCK)) - break; - else - goto error_unlock; - } - } while (item_data->events & EPOLLET); - - /* The item was one-shot, so re-enable it: */ - event_data.events = item_data->events; - if (epoll_ctl(thread_data->epoll_set, - EPOLL_CTL_MOD, - item_data->fd, - &event_data) < 0) - goto error_unlock; - } - - pthread_mutex_unlock(&item_data->mutex); - } - -error_unlock: - thread_data->status = item_data->status = errno; - pthread_mutex_unlock(&item_data->mutex); - return 0; -} - -/* - * A pointer to a write_thread_data structure will be passed as the argument to - * the write thread: - */ -struct write_thread_data { - int stop; - int status; /* Indicates any error encountered by the write thread. */ - int n_fds; - int *fds; -}; - -/* - * The function executed by the write thread. It writes a single byte to each - * socket in turn until the stop condition for this thread is set. If writing to - * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for - * the moment and just move on to the next socket in the list. We don't care - * about the order in which we deliver events to the epoll set. In fact we don't - * care about the data we're writing to the pipes at all; we just want to - * trigger epoll events: - */ -void *write_thread_function(void *function_data) -{ - const char data = 'X'; - int index; - struct write_thread_data *thread_data = - (struct write_thread_data *)function_data; - while (!write_thread_data->stop) - for (index = 0; - !thread_data->stop && (index < thread_data->n_fds); - ++index) - if ((write(thread_data->fds[index], &data, 1) < 1) && - (errno != EAGAIN) && - (errno != EWOULDBLOCK)) { - write_thread_data->status = errno; - return; - } -} - -/* - * Arguments are currently ignored: - */ -int main(int argc, char **argv) -{ - const int n_read_threads = 100; - const int n_epoll_items = 500; - int index; - int epoll_set = epoll_create1(0); - struct write_thread_data write_thread_data = { - 0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int)) - }; - struct read_thread_data *read_thread_data = - malloc(n_read_threads * sizeof(struct read_thread_data)); - pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t)); - pthread_t write_thread; - - printf("-----------------\n"); - printf("Runing test_epoll\n"); - printf("-----------------\n"); - - epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private)); - - if (epoll_set < 0 || epoll_items == 0 || write_thread_data.fds == 0 || - read_thread_data == 0 || read_threads == 0) - goto error; - - if (sysconf(_SC_NPROCESSORS_ONLN) < 2) { - printf("Error: please run this test on a multi-core system.\n"); - goto error; - } - - /* Create the socket pairs and epoll items: */ - for (index = 0; index < n_epoll_items; ++index) { - int socket_pair[2]; - struct epoll_event event_data; - if (socketpair(AF_UNIX, - SOCK_STREAM | SOCK_NONBLOCK, - 0, - socket_pair) < 0) - goto error; - write_thread_data.fds[index] = socket_pair[0]; - epoll_items[index].index = index; - epoll_items[index].fd = socket_pair[1]; - if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0) - goto error; - /* We always use EPOLLONESHOT because this test is currently - structured to demonstrate the need for EPOLL_CTL_DISABLE, - which only produces useful information in the EPOLLONESHOT - case (without EPOLLONESHOT, calling epoll_ctl with - EPOLL_CTL_DISABLE will never return EBUSY). If support for - testing events without EPOLLONESHOT is desired, it should - probably be implemented in a separate unit test. */ - epoll_items[index].events = EPOLLIN | EPOLLONESHOT; - if (index < n_epoll_items / 2) - epoll_items[index].events |= EPOLLET; - epoll_items[index].stop = 0; - epoll_items[index].status = 0; - epoll_items[index].deleted = 0; - event_data.events = epoll_items[index].events; - event_data.data.ptr = &epoll_items[index]; - if (epoll_ctl(epoll_set, - EPOLL_CTL_ADD, - epoll_items[index].fd, - &event_data) < 0) - goto error; - } - - /* Create and start the read threads: */ - for (index = 0; index < n_read_threads; ++index) { - read_thread_data[index].stop = 0; - read_thread_data[index].status = 0; - read_thread_data[index].epoll_set = epoll_set; - if (pthread_create(&read_threads[index], - NULL, - read_thread_function, - &read_thread_data[index]) != 0) - goto error; - } - - if (pthread_create(&write_thread, - NULL, - write_thread_function, - &write_thread_data) != 0) - goto error; - - /* Cancel all event pollers: */ -#ifdef EPOLL_CTL_DISABLE - for (index = 0; index < n_epoll_items; ++index) { - pthread_mutex_lock(&epoll_items[index].mutex); - ++epoll_items[index].stop; - if (epoll_ctl(epoll_set, - EPOLL_CTL_DISABLE, - epoll_items[index].fd, - NULL) == 0) - delete_item(index); - else if (errno != EBUSY) { - pthread_mutex_unlock(&epoll_items[index].mutex); - goto error; - } - /* EBUSY means events were being handled; allow the other thread - to delete the item. */ - pthread_mutex_unlock(&epoll_items[index].mutex); - } -#else - for (index = 0; index < n_epoll_items; ++index) { - pthread_mutex_lock(&epoll_items[index].mutex); - ++epoll_items[index].stop; - pthread_mutex_unlock(&epoll_items[index].mutex); - /* Wait in case a thread running read_thread_function is - currently executing code between epoll_wait and - pthread_mutex_lock with this item. Note that a longer delay - would make double-deletion less likely (at the expense of - performance), but there is no guarantee that any delay would - ever be sufficient. Note also that we delete all event - pollers at once for testing purposes, but in a real-world - environment we are likely to want to be able to cancel event - pollers at arbitrary times. Therefore we can't improve this - situation by just splitting this loop into two loops - (i.e. signal 'stop' for all items, sleep, and then delete all - items). We also can't fix the problem via EPOLL_CTL_DEL - because that command can't prevent the case where some other - thread is executing read_thread_function within the region - mentioned above: */ - usleep(1); - pthread_mutex_lock(&epoll_items[index].mutex); - if (!epoll_items[index].deleted) - delete_item(index); - pthread_mutex_unlock(&epoll_items[index].mutex); - } -#endif - - /* Shut down the read threads: */ - for (index = 0; index < n_read_threads; ++index) - __sync_fetch_and_add(&read_thread_data[index].stop, 1); - for (index = 0; index < n_read_threads; ++index) { - if (pthread_join(read_threads[index], NULL) != 0) - goto error; - if (read_thread_data[index].status) - goto error; - } - - /* Shut down the write thread: */ - __sync_fetch_and_add(&write_thread_data.stop, 1); - if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status) - goto error; - - /* Check for final error conditions: */ - for (index = 0; index < n_epoll_items; ++index) { - if (epoll_items[index].status != 0) - goto error; - if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0) - goto error; - } - for (index = 0; index < n_epoll_items; ++index) - if (epoll_items[index].deleted != 1) { - printf("Error: item data deleted %1d times.\n", - epoll_items[index].deleted); - goto error; - } - - printf("[PASS]\n"); - return 0; - - error: - printf("[FAIL]\n"); - return errno; -} diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c index cd1b03e8089..b76edf2f833 100644 --- a/tools/vm/page-types.c +++ b/tools/vm/page-types.c @@ -35,7 +35,7 @@ #include <sys/mount.h> #include <sys/statfs.h> #include "../../include/uapi/linux/magic.h" -#include "../../include/linux/kernel-page-flags.h" +#include "../../include/uapi/linux/kernel-page-flags.h" #ifndef MAX_PATH diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c index af0f22fb1ef..aca6edcbbc6 100644 --- a/usr/gen_init_cpio.c +++ b/usr/gen_init_cpio.c @@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location, int retval; int rc = -1; int namesize; - int i; + unsigned int i; mode |= S_IFREG; @@ -381,25 +381,28 @@ error: static char *cpio_replace_env(char *new_location) { - char expanded[PATH_MAX + 1]; - char env_var[PATH_MAX + 1]; - char *start; - char *end; - - for (start = NULL; (start = strstr(new_location, "${")); ) { - end = strchr(start, '}'); - if (start < end) { - *env_var = *expanded = '\0'; - strncat(env_var, start + 2, end - start - 2); - strncat(expanded, new_location, start - new_location); - strncat(expanded, getenv(env_var), PATH_MAX); - strncat(expanded, end + 1, PATH_MAX); - strncpy(new_location, expanded, PATH_MAX); - } else - break; - } - - return new_location; + char expanded[PATH_MAX + 1]; + char env_var[PATH_MAX + 1]; + char *start; + char *end; + + for (start = NULL; (start = strstr(new_location, "${")); ) { + end = strchr(start, '}'); + if (start < end) { + *env_var = *expanded = '\0'; + strncat(env_var, start + 2, end - start - 2); + strncat(expanded, new_location, start - new_location); + strncat(expanded, getenv(env_var), + PATH_MAX - strlen(expanded)); + strncat(expanded, end + 1, + PATH_MAX - strlen(expanded)); + strncpy(new_location, expanded, PATH_MAX); + new_location[PATH_MAX] = 0; + } else + break; + } + + return new_location; } diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index e59bb63cb08..be70035fd42 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1322,9 +1322,7 @@ EXPORT_SYMBOL_GPL(kvm_release_page_clean); void kvm_release_pfn_clean(pfn_t pfn) { - WARN_ON(is_error_pfn(pfn)); - - if (!kvm_is_mmio_pfn(pfn)) + if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn)) put_page(pfn_to_page(pfn)); } EXPORT_SYMBOL_GPL(kvm_release_pfn_clean); |