summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2014-04-24 16:15:29 +0200
committerWaldemar Brodkorb <wbx@openadk.org>2014-04-24 16:15:29 +0200
commit94c82fcf15415a015b602a58a26880bb0ad97da4 (patch)
tree828a33bd363bfdbc58edbb45cdb2d8e45150d5d9
parent839ae24b726ab65e1c4cff172f29e24e9f3ee5cd (diff)
update 3.12 kernel
-rw-r--r--Config.in6
-rw-r--r--mk/kernel-ver.mk6
-rw-r--r--target/arm/raspberry-pi/patches/3.12.18/raspberry-pi.patch (renamed from target/linux/patches/3.12.14/raspberry.patch)12640
-rw-r--r--target/linux/config/Config.in.netfilter.ip48
-rw-r--r--target/linux/patches/3.12.18/bsd-compatibility.patch (renamed from target/linux/patches/3.12.14/bsd-compatibility.patch)0
-rw-r--r--target/linux/patches/3.12.18/defaults.patch (renamed from target/linux/patches/3.12.14/defaults.patch)0
-rw-r--r--target/linux/patches/3.12.18/disable-netfilter.patch (renamed from target/linux/patches/3.12.14/disable-netfilter.patch)0
-rw-r--r--target/linux/patches/3.12.18/export-symbol-for-exmap.patch (renamed from target/linux/patches/3.12.14/export-symbol-for-exmap.patch)0
-rw-r--r--target/linux/patches/3.12.18/gemalto.patch (renamed from target/linux/patches/3.12.14/gemalto.patch)0
-rw-r--r--target/linux/patches/3.12.18/lemote-rfkill.patch (renamed from target/linux/patches/3.12.14/lemote-rfkill.patch)0
-rw-r--r--target/linux/patches/3.12.18/microblaze-ethernet.patch (renamed from target/linux/patches/3.12.14/microblaze-ethernet.patch)0
-rw-r--r--target/linux/patches/3.12.18/microblaze-setup.patch (renamed from target/linux/patches/3.12.14/microblaze-setup.patch)0
-rw-r--r--target/linux/patches/3.12.18/mips-lzo-fix.patch (renamed from target/linux/patches/3.12.14/mips-lzo-fix.patch)0
-rw-r--r--target/linux/patches/3.12.18/mtd-rootfs.patch (renamed from target/linux/patches/3.12.14/mtd-rootfs.patch)0
-rw-r--r--target/linux/patches/3.12.18/non-static.patch (renamed from target/linux/patches/3.12.14/non-static.patch)0
-rw-r--r--target/linux/patches/3.12.18/ppc64-missing-zlib.patch (renamed from target/linux/patches/3.12.14/ppc64-missing-zlib.patch)0
-rw-r--r--target/linux/patches/3.12.18/startup.patch (renamed from target/linux/patches/3.12.14/startup.patch)0
-rw-r--r--target/linux/patches/3.12.18/usb-defaults-off.patch (renamed from target/linux/patches/3.12.14/usb-defaults-off.patch)0
-rw-r--r--target/linux/patches/3.12.18/uuid.patch (renamed from target/linux/patches/3.12.14/uuid.patch)0
-rw-r--r--target/linux/patches/3.12.18/vga-cons-default-off.patch (renamed from target/linux/patches/3.12.14/vga-cons-default-off.patch)0
-rw-r--r--target/linux/patches/3.12.18/wlan-cf.patch (renamed from target/linux/patches/3.12.14/wlan-cf.patch)0
-rw-r--r--target/linux/patches/3.12.18/xargs.patch (renamed from target/linux/patches/3.12.14/xargs.patch)0
-rw-r--r--target/linux/patches/3.12.18/zlib-inflate.patch (renamed from target/linux/patches/3.12.14/zlib-inflate.patch)0
-rw-r--r--toolchain/kernel-headers/patches/3.12.18/cleankernel.patch (renamed from toolchain/kernel-headers/patches/3.12.14/cleankernel.patch)0
-rw-r--r--toolchain/kernel-headers/patches/3.12.18/mkpiggy.patch (renamed from toolchain/kernel-headers/patches/3.12.14/mkpiggy.patch)0
-rw-r--r--toolchain/kernel-headers/patches/3.12.18/relocs.patch (renamed from toolchain/kernel-headers/patches/3.12.14/relocs.patch)0
-rw-r--r--toolchain/kernel-headers/patches/3.12.18/sgidefs.patch (renamed from toolchain/kernel-headers/patches/3.12.14/sgidefs.patch)0
-rw-r--r--toolchain/kernel-headers/patches/3.12.18/sortext.patch (renamed from toolchain/kernel-headers/patches/3.12.14/sortext.patch)0
28 files changed, 9167 insertions, 3493 deletions
diff --git a/Config.in b/Config.in
index f4457a8aa..cc8cf243a 100644
--- a/Config.in
+++ b/Config.in
@@ -115,8 +115,8 @@ config ADK_KERNEL_VERSION_3_13_11
prompt "3.13.11"
boolean
-config ADK_KERNEL_VERSION_3_12_14
- prompt "3.12.14"
+config ADK_KERNEL_VERSION_3_12_18
+ prompt "3.12.18"
boolean
config ADK_KERNEL_VERSION_3_11_10
@@ -138,7 +138,7 @@ config ADK_KERNEL_VERSION
string
default "3.14.1" if ADK_KERNEL_VERSION_3_14_1
default "3.13.11" if ADK_KERNEL_VERSION_3_13_11
- default "3.12.14" if ADK_KERNEL_VERSION_3_12_14
+ default "3.12.18" if ADK_KERNEL_VERSION_3_12_18
default "3.11.10" if ADK_KERNEL_VERSION_3_11_10
default "3.10.36" if ADK_KERNEL_VERSION_3_10_36
default "3.4.84" if ADK_KERNEL_VERSION_3_4_84
diff --git a/mk/kernel-ver.mk b/mk/kernel-ver.mk
index 602a3065e..5e9002792 100644
--- a/mk/kernel-ver.mk
+++ b/mk/kernel-ver.mk
@@ -16,11 +16,11 @@ KERNEL_MOD_VERSION:= $(KERNEL_VERSION)
KERNEL_RELEASE:= 1
KERNEL_MD5SUM:= d4e06af8b674ac74ba745d52e4382bd3
endif
-ifeq ($(ADK_KERNEL_VERSION_3_12_14),y)
-KERNEL_VERSION:= 3.12.14
+ifeq ($(ADK_KERNEL_VERSION_3_12_18),y)
+KERNEL_VERSION:= 3.12.18
KERNEL_MOD_VERSION:= $(KERNEL_VERSION)
KERNEL_RELEASE:= 1
-KERNEL_MD5SUM:= 5575e68e287605ad63d3a1444e9b701d
+KERNEL_MD5SUM:= ec32bc59a5feb46c74adb1df7d3e3e98
endif
ifeq ($(ADK_KERNEL_VERSION_3_11_10),y)
KERNEL_VERSION:= 3.11.10
diff --git a/target/linux/patches/3.12.14/raspberry.patch b/target/arm/raspberry-pi/patches/3.12.18/raspberry-pi.patch
index c306f4faf..c5e93d3fb 100644
--- a/target/linux/patches/3.12.14/raspberry.patch
+++ b/target/arm/raspberry-pi/patches/3.12.18/raspberry-pi.patch
@@ -1,6 +1,57 @@
-diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_cutdown_defconfig linux-raspberry-pi/arch/arm/configs/bcmrpi_cutdown_defconfig
---- linux-3.12.13/arch/arm/configs/bcmrpi_cutdown_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/configs/bcmrpi_cutdown_defconfig 2014-03-11 17:51:00.000000000 +0100
+diff -Nur linux-3.12.18/arch/arc/boot/dts/nsimosci.dts linux-rpi/arch/arc/boot/dts/nsimosci.dts
+--- linux-3.12.18/arch/arc/boot/dts/nsimosci.dts 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arc/boot/dts/nsimosci.dts 2014-04-24 16:04:29.363023127 +0200
+@@ -11,16 +11,13 @@
+
+ / {
+ compatible = "snps,nsimosci";
+- clock-frequency = <20000000>; /* 20 MHZ */
++ clock-frequency = <80000000>; /* 80 MHZ */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&intc>;
+
+ chosen {
+- /* this is for console on PGU */
+- /* bootargs = "console=tty0 consoleblank=0"; */
+- /* this is for console on serial */
+- bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug";
++ bootargs = "console=tty0 consoleblank=0";
+ };
+
+ aliases {
+@@ -47,14 +44,15 @@
+ };
+
+ uart0: serial@c0000000 {
+- compatible = "ns8250";
++ compatible = "snps,dw-apb-uart";
+ reg = <0xc0000000 0x2000>;
+ interrupts = <11>;
++ #clock-frequency = <80000000>;
+ clock-frequency = <3686400>;
+ baud = <115200>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+- no-loopback-test = <1>;
++ status = "okay";
+ };
+
+ pgu0: pgu@c9000000 {
+diff -Nur linux-3.12.18/arch/arc/configs/nsimosci_defconfig linux-rpi/arch/arc/configs/nsimosci_defconfig
+--- linux-3.12.18/arch/arc/configs/nsimosci_defconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arc/configs/nsimosci_defconfig 2014-04-24 16:04:29.363023127 +0200
+@@ -54,7 +54,6 @@
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
+ CONFIG_SERIAL_8250_DW=y
+-CONFIG_SERIAL_OF_PLATFORM=y
+ CONFIG_SERIAL_ARC=y
+ CONFIG_SERIAL_ARC_CONSOLE=y
+ # CONFIG_HW_RANDOM is not set
+diff -Nur linux-3.12.18/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi/arch/arm/configs/bcmrpi_cutdown_defconfig
+--- linux-3.12.18/arch/arm/configs/bcmrpi_cutdown_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/configs/bcmrpi_cutdown_defconfig 2014-04-24 16:04:30.011029397 +0200
@@ -0,0 +1,503 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
@@ -505,10 +556,10 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_cutdown_defconfig linux-raspberr
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_BCM2708=m
-diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arch/arm/configs/bcmrpi_defconfig
---- linux-3.12.13/arch/arm/configs/bcmrpi_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/configs/bcmrpi_defconfig 2014-03-11 17:51:00.000000000 +0100
-@@ -0,0 +1,1094 @@
+diff -Nur linux-3.12.18/arch/arm/configs/bcmrpi_defconfig linux-rpi/arch/arm/configs/bcmrpi_defconfig
+--- linux-3.12.18/arch/arm/configs/bcmrpi_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/configs/bcmrpi_defconfig 2014-04-24 16:04:30.011029397 +0200
+@@ -0,0 +1,1097 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
@@ -529,6 +580,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
++CONFIG_MEMCG=y
+CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
+CONFIG_SCHED_AUTOGROUP=y
@@ -553,6 +605,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_AEABI=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
++CONFIG_CMA=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_SECCOMP=y
+CONFIG_CC_STACKPROTECTOR=y
@@ -601,10 +654,10 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
-+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
++CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
@@ -627,7 +680,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
-+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_AUDIT=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -778,6 +830,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_SCTP_COOKIE_HMAC_SHA1=y
+CONFIG_L2TP=m
++CONFIG_L2TP_V3=y
++CONFIG_L2TP_IP=m
++CONFIG_L2TP_ETH=m
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
@@ -888,7 +943,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_NFC_PN533=m
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
-+CONFIG_CMA=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_DRBD=m
@@ -901,6 +955,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
++CONFIG_CHR_DEV_SG=m
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+CONFIG_ISCSI_TCP=m
@@ -912,8 +967,8 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
-+CONFIG_DM_RAID=m
+CONFIG_DM_LOG_USERSPACE=m
++CONFIG_DM_RAID=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_DELAY=m
+CONFIG_NETDEVICES=y
@@ -923,6 +978,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_MACVLAN=m
+CONFIG_NETCONSOLE=m
+CONFIG_TUN=m
++CONFIG_VETH=m
+CONFIG_MDIO_BITBANG=m
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
@@ -944,6 +1000,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=m
++CONFIG_USB_NET_AX88179_178A=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
@@ -985,6 +1042,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_B43=m
+# CONFIG_B43_PHY_N is not set
+CONFIG_B43LEGACY=m
++CONFIG_BRCMFMAC=m
++# CONFIG_BRCMFMAC_SDIO is not set
++CONFIG_BRCMFMAC_USB=y
+CONFIG_HOSTAP=m
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
@@ -995,7 +1055,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
++CONFIG_RT2800USB_RT3573=y
+CONFIG_RT2800USB_RT53XX=y
++CONFIG_RT2800USB_RT55XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_RTL8192CU=m
+CONFIG_ZD1211RW=m
@@ -1011,7 +1073,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
-+CONFIG_JOYSTICK_XPAD=y
++CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
@@ -1029,7 +1091,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
-+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
@@ -1146,8 +1207,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_TLG2300=m
+CONFIG_VIDEO_USBVISION=m
-+CONFIG_VIDEO_STK1160=m
-+CONFIG_VIDEO_STK1160_AC97=y
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_ALSA=m
@@ -1255,6 +1314,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_SND_SOC_I2C_AND_SPI=m
+CONFIG_SND_SOC_PCM5102A=m
+CONFIG_SND_SOC_PCM1794A=m
++CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC=m
+CONFIG_SOUND_PRIME=m
+CONFIG_HIDRAW=y
+CONFIG_HID_A4TECH=m
@@ -1303,6 +1363,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_HID_ZYDACRON=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
++CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=m
+CONFIG_USB_DWCOTG=y
@@ -1335,7 +1396,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
-+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
@@ -1353,16 +1413,13 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
-+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
-+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
-+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
@@ -1371,9 +1428,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
-+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_XSENS_MT=m
-+CONFIG_USB_SERIAL_ZIO=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_ZTE=m
+CONFIG_USB_SERIAL_SSU100=m
@@ -1416,6 +1471,7 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_LEDS_TRIGGER_TRANSIENT=m
+CONFIG_LEDS_TRIGGER_CAMERA=m
+CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
@@ -1451,7 +1507,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_VIRTUAL_CHANNELS=m
+CONFIG_UIO=m
-+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_STAGING=y
+CONFIG_W35UND=m
@@ -1588,7 +1643,6 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+CONFIG_CRYPTO_USER=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
-+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_XCBC=m
@@ -1603,9 +1657,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_defconfig linux-raspberry-pi/arc
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
-diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_emergency_defconfig linux-raspberry-pi/arch/arm/configs/bcmrpi_emergency_defconfig
---- linux-3.12.13/arch/arm/configs/bcmrpi_emergency_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/configs/bcmrpi_emergency_defconfig 2014-03-11 17:31:42.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/configs/bcmrpi_emergency_defconfig linux-rpi/arch/arm/configs/bcmrpi_emergency_defconfig
+--- linux-3.12.18/arch/arm/configs/bcmrpi_emergency_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/configs/bcmrpi_emergency_defconfig 2014-04-24 16:04:30.011029397 +0200
@@ -0,0 +1,532 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
@@ -2139,9 +2193,9 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_emergency_defconfig linux-raspbe
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
-diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_quick_defconfig linux-raspberry-pi/arch/arm/configs/bcmrpi_quick_defconfig
---- linux-3.12.13/arch/arm/configs/bcmrpi_quick_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/configs/bcmrpi_quick_defconfig 2014-03-11 17:31:42.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/configs/bcmrpi_quick_defconfig linux-rpi/arch/arm/configs/bcmrpi_quick_defconfig
+--- linux-3.12.18/arch/arm/configs/bcmrpi_quick_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/configs/bcmrpi_quick_defconfig 2014-04-24 15:35:00.717527267 +0200
@@ -0,0 +1,197 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_LOCALVERSION="-quick"
@@ -2340,20 +2394,38 @@ diff -Nur linux-3.12.13/arch/arm/configs/bcmrpi_quick_defconfig linux-raspberry-
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_LIBCRC32C=y
-diff -Nur linux-3.12.13/arch/arm/include/asm/fiq.h linux-raspberry-pi/arch/arm/include/asm/fiq.h
---- linux-3.12.13/arch/arm/include/asm/fiq.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/include/asm/fiq.h 2014-03-11 17:31:42.000000000 +0100
-@@ -42,6 +42,7 @@
- /* helpers defined in fiqasm.S: */
- extern void __set_fiq_regs(unsigned long const *regs);
- extern void __get_fiq_regs(unsigned long *regs);
-+extern void __FIQ_Branch(unsigned long *regs);
+diff -Nur linux-3.12.18/arch/arm/include/asm/irqflags.h linux-rpi/arch/arm/include/asm/irqflags.h
+--- linux-3.12.18/arch/arm/include/asm/irqflags.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arm/include/asm/irqflags.h 2014-04-24 16:04:30.027029552 +0200
+@@ -145,12 +145,22 @@
+ }
- static inline void set_fiq_regs(struct pt_regs const *regs)
+ /*
+- * restore saved IRQ & FIQ state
++ * restore saved IRQ state
+ */
+ static inline void arch_local_irq_restore(unsigned long flags)
{
-diff -Nur linux-3.12.13/arch/arm/Kconfig linux-raspberry-pi/arch/arm/Kconfig
---- linux-3.12.13/arch/arm/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/Kconfig 2014-03-11 17:51:00.000000000 +0100
+- asm volatile(
+- " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
++ unsigned long temp = 0;
++ flags &= ~(1 << 6);
++ asm volatile (
++ " mrs %0, cpsr"
++ : "=r" (temp)
++ :
++ : "memory", "cc");
++ /* Preserve FIQ bit */
++ temp &= (1 << 6);
++ flags = flags | temp;
++ asm volatile (
++ " msr cpsr_c, %0 @ local_irq_restore"
+ :
+ : "r" (flags)
+ : "memory", "cc");
+diff -Nur linux-3.12.18/arch/arm/Kconfig linux-rpi/arch/arm/Kconfig
+--- linux-3.12.18/arch/arm/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arm/Kconfig 2014-04-24 16:04:29.515024597 +0200
@@ -368,6 +368,24 @@
This enables support for systems based on Atmel
AT91RM9200 and AT91SAM9* processors.
@@ -2387,9 +2459,9 @@ diff -Nur linux-3.12.13/arch/arm/Kconfig linux-raspberry-pi/arch/arm/Kconfig
source "arch/arm/mach-zynq/Kconfig"
-diff -Nur linux-3.12.13/arch/arm/Kconfig.debug linux-raspberry-pi/arch/arm/Kconfig.debug
---- linux-3.12.13/arch/arm/Kconfig.debug 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/Kconfig.debug 2014-03-11 17:51:00.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/Kconfig.debug linux-rpi/arch/arm/Kconfig.debug
+--- linux-3.12.18/arch/arm/Kconfig.debug 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arm/Kconfig.debug 2014-04-24 16:04:29.515024597 +0200
@@ -847,6 +847,14 @@
options; the platform specific options are deprecated
and will be soon removed.
@@ -2405,20 +2477,10 @@ diff -Nur linux-3.12.13/arch/arm/Kconfig.debug linux-raspberry-pi/arch/arm/Kconf
endchoice
config DEBUG_EXYNOS_UART
-diff -Nur linux-3.12.13/arch/arm/kernel/fiqasm.S linux-raspberry-pi/arch/arm/kernel/fiqasm.S
---- linux-3.12.13/arch/arm/kernel/fiqasm.S 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/kernel/fiqasm.S 2014-03-11 17:31:43.000000000 +0100
-@@ -25,6 +25,9 @@
- ENTRY(__set_fiq_regs)
- mov r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE
- mrs r1, cpsr
-+@@@@@@@@@@@@@@@ hack: enable the fiq here to keep usb driver happy
-+ and r1, #~PSR_F_BIT
-+@@@@@@@@@@@@@@@ endhack: (need to find better place for this to happen)
- msr cpsr_c, r2 @ select FIQ mode
- mov r0, r0 @ avoid hazard prior to ARMv4
- ldmia r0!, {r8 - r12}
-@@ -47,3 +50,7 @@
+diff -Nur linux-3.12.18/arch/arm/kernel/fiqasm.S linux-rpi/arch/arm/kernel/fiqasm.S
+--- linux-3.12.18/arch/arm/kernel/fiqasm.S 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arm/kernel/fiqasm.S 2014-04-24 16:04:30.039029668 +0200
+@@ -47,3 +47,7 @@
mov r0, r0 @ avoid hazard prior to ARMv4
mov pc, lr
ENDPROC(__get_fiq_regs)
@@ -2426,20 +2488,9 @@ diff -Nur linux-3.12.13/arch/arm/kernel/fiqasm.S linux-raspberry-pi/arch/arm/ker
+ENTRY(__FIQ_Branch)
+ mov pc, r8
+ENDPROC(__FIQ_Branch)
-diff -Nur linux-3.12.13/arch/arm/kernel/fiq.c linux-raspberry-pi/arch/arm/kernel/fiq.c
---- linux-3.12.13/arch/arm/kernel/fiq.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/kernel/fiq.c 2014-03-11 17:31:43.000000000 +0100
-@@ -142,6 +142,7 @@
- EXPORT_SYMBOL(set_fiq_handler);
- EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */
- EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */
-+EXPORT_SYMBOL(__FIQ_Branch); /* defined in fiqasm.S */
- EXPORT_SYMBOL(claim_fiq);
- EXPORT_SYMBOL(release_fiq);
- EXPORT_SYMBOL(enable_fiq);
-diff -Nur linux-3.12.13/arch/arm/kernel/process.c linux-raspberry-pi/arch/arm/kernel/process.c
---- linux-3.12.13/arch/arm/kernel/process.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/kernel/process.c 2014-03-11 17:51:02.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/kernel/process.c linux-rpi/arch/arm/kernel/process.c
+--- linux-3.12.18/arch/arm/kernel/process.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arm/kernel/process.c 2014-04-24 16:04:30.039029668 +0200
@@ -176,6 +176,16 @@
default_idle();
}
@@ -2457,9 +2508,9 @@ diff -Nur linux-3.12.13/arch/arm/kernel/process.c linux-raspberry-pi/arch/arm/ke
/*
* Called by kexec, immediately prior to machine_kexec().
*
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/armctrl.c linux-raspberry-pi/arch/arm/mach-bcm2708/armctrl.c
---- linux-3.12.13/arch/arm/mach-bcm2708/armctrl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/armctrl.c 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/armctrl.c linux-rpi/arch/arm/mach-bcm2708/armctrl.c
+--- linux-3.12.18/arch/arm/mach-bcm2708/armctrl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/armctrl.c 2014-04-24 15:35:00.773527891 +0200
@@ -0,0 +1,219 @@
+/*
+ * linux/arch/arm/mach-bcm2708/armctrl.c
@@ -2680,9 +2731,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/armctrl.c linux-raspberry-pi/arch/
+ init_FIQ(FIQ_START);
+ return 0;
+}
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/armctrl.h linux-raspberry-pi/arch/arm/mach-bcm2708/armctrl.h
---- linux-3.12.13/arch/arm/mach-bcm2708/armctrl.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/armctrl.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/armctrl.h linux-rpi/arch/arm/mach-bcm2708/armctrl.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/armctrl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/armctrl.h 2014-04-24 15:35:00.773527891 +0200
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/arm/mach-bcm2708/armctrl.h
@@ -2711,10 +2762,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/armctrl.h linux-raspberry-pi/arch/
+ u32 armctrl_sources, u32 resume_sources);
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708.c
---- linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708.c 2014-03-11 17:51:02.000000000 +0100
-@@ -0,0 +1,1011 @@
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/bcm2708.c linux-rpi/arch/arm/mach-bcm2708/bcm2708.c
+--- linux-3.12.18/arch/arm/mach-bcm2708/bcm2708.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/bcm2708.c 2014-04-24 16:04:30.051029784 +0200
+@@ -0,0 +1,1017 @@
+/*
+ * linux/arch/arm/mach-bcm2708/bcm2708.c
+ *
@@ -2758,7 +2809,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/
+#include <asm/irq.h>
+#include <linux/leds.h>
+#include <asm/mach-types.h>
-+#include <asm/sched_clock.h>
++#include <linux/sched_clock.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
@@ -2803,6 +2854,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/
+static unsigned disk_led_gpio = 16;
+static unsigned disk_led_active_low = 1;
+static unsigned reboot_part = 0;
++static unsigned w1_gpio_pin = W1_GPIO;
+
+static void __init bcm2708_init_led(void);
+
@@ -3044,20 +3096,6 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/
+ },
+};
+
-+bool fiq_fix_enable = true;
-+
-+static struct resource bcm2708_usb_resources_no_fiq_fix[] = {
-+ [0] = {
-+ .start = USB_BASE,
-+ .end = USB_BASE + SZ_128K - 1,
-+ .flags = IORESOURCE_MEM,
-+ },
-+ [1] = {
-+ .start = IRQ_USB,
-+ .end = IRQ_USB,
-+ .flags = IORESOURCE_IRQ,
-+ },
-+};
+
+static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
+
@@ -3401,6 +3439,22 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/
+};
+#endif
+
++
++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE)
++static struct platform_device snd_rpi_iqaudio_dac_device = {
++ .name = "snd-rpi-iqaudio-dac",
++ .id = 0,
++ .num_resources = 0,
++};
++
++// Use the actual device name rather than generic driver name
++static struct i2c_board_info __initdata snd_pcm512x_i2c_devices[] = {
++ {
++ I2C_BOARD_INFO("pcm5122", 0x4c)
++ },
++};
++#endif
++
+int __init bcm_register_device(struct platform_device *pdev)
+{
+ int ret;
@@ -3500,15 +3554,11 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/
+ bcm_register_device(&bcm2708_gpio_device);
+#endif
+#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE)
++ w1_gpio_pdata.pin = w1_gpio_pin;
+ platform_device_register(&w1_device);
+#endif
+ bcm_register_device(&bcm2708_systemtimer_device);
+ bcm_register_device(&bcm2708_fb_device);
-+ if (!fiq_fix_enable)
-+ {
-+ bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix;
-+ bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix);
-+ }
+ bcm_register_device(&bcm2708_usb_device);
+ bcm_register_device(&bcm2708_uart1_device);
+ bcm_register_device(&bcm2708_powerman_device);
@@ -3546,6 +3596,12 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/
+ bcm_register_device(&snd_pcm1794a_codec_device);
+#endif
+
++#if defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) || defined(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC_MODULE)
++ bcm_register_device(&snd_rpi_iqaudio_dac_device);
++ i2c_register_board_info(1, snd_pcm512x_i2c_devices, ARRAY_SIZE(snd_pcm512x_i2c_devices));
++#endif
++
++
+ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+ struct amba_device *d = amba_devs[i];
+ amba_device_register(d, &iomem_resource);
@@ -3726,10 +3782,11 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.c linux-raspberry-pi/arch/
+module_param(disk_led_gpio, uint, 0644);
+module_param(disk_led_active_low, uint, 0644);
+module_param(reboot_part, uint, 0644);
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708_gpio.c
---- linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708_gpio.c 2014-03-11 17:51:02.000000000 +0100
-@@ -0,0 +1,339 @@
++module_param(w1_gpio_pin, uint, 0644);
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-rpi/arch/arm/mach-bcm2708/bcm2708_gpio.c
+--- linux-3.12.18/arch/arm/mach-bcm2708/bcm2708_gpio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/bcm2708_gpio.c 2014-04-24 16:04:30.051029784 +0200
+@@ -0,0 +1,361 @@
+/*
+ * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c
+ *
@@ -3790,6 +3847,8 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/
+ struct gpio_chip gc;
+ unsigned long rising;
+ unsigned long falling;
++ unsigned long high;
++ unsigned long low;
+};
+
+static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset,
@@ -3802,7 +3861,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/
+ unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3;
+
+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function);
-+ if (offset >= ARCH_NR_GPIOS)
++ if (offset >= BCM2708_NR_GPIOS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&lock, flags);
@@ -3840,7 +3899,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/
+ unsigned gpio_field_offset = (offset - 32 * gpio_bank);
+ unsigned lev;
+
-+ if (offset >= ARCH_NR_GPIOS)
++ if (offset >= BCM2708_NR_GPIOS)
+ return 0;
+ lev = readl(gpio->base + GPIOLEV(gpio_bank));
+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset));
@@ -3853,7 +3912,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/
+ unsigned gpio_bank = offset / 32;
+ unsigned gpio_field_offset = (offset - 32 * gpio_bank);
+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value);
-+ if (offset >= ARCH_NR_GPIOS)
++ if (offset >= BCM2708_NR_GPIOS)
+ return;
+ if (value)
+ writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank));
@@ -3877,20 +3936,22 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/
+ unsigned irq = d->irq;
+ struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
+
-+ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
++ gpio->rising &= ~(1 << irq_to_gpio(irq));
++ gpio->falling &= ~(1 << irq_to_gpio(irq));
++ gpio->high &= ~(1 << irq_to_gpio(irq));
++ gpio->low &= ~(1 << irq_to_gpio(irq));
++
++ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+ return -EINVAL;
+
-+ if (type & IRQ_TYPE_EDGE_RISING) {
++ if (type & IRQ_TYPE_EDGE_RISING)
+ gpio->rising |= (1 << irq_to_gpio(irq));
-+ } else {
-+ gpio->rising &= ~(1 << irq_to_gpio(irq));
-+ }
-+
-+ if (type & IRQ_TYPE_EDGE_FALLING) {
++ if (type & IRQ_TYPE_EDGE_FALLING)
+ gpio->falling |= (1 << irq_to_gpio(irq));
-+ } else {
-+ gpio->falling &= ~(1 << irq_to_gpio(irq));
-+ }
++ if (type & IRQ_TYPE_LEVEL_HIGH)
++ gpio->high |= (1 << irq_to_gpio(irq));
++ if (type & IRQ_TYPE_LEVEL_LOW)
++ gpio->low |= (1 << irq_to_gpio(irq));
+ return 0;
+}
+
@@ -3900,13 +3961,17 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/
+ struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
+ unsigned gn = irq_to_gpio(irq);
+ unsigned gb = gn / 32;
-+ unsigned long rising = readl(gpio->base + GPIOREN(gb));
++ unsigned long rising = readl(gpio->base + GPIOREN(gb));
+ unsigned long falling = readl(gpio->base + GPIOFEN(gb));
++ unsigned long high = readl(gpio->base + GPIOHEN(gb));
++ unsigned long low = readl(gpio->base + GPIOLEN(gb));
+
+ gn = gn % 32;
+
-+ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
++ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
+ writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
++ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
++ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
+}
+
+static void bcm2708_gpio_irq_unmask(struct irq_data *d)
@@ -3915,24 +3980,38 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/
+ struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
+ unsigned gn = irq_to_gpio(irq);
+ unsigned gb = gn / 32;
-+ unsigned long rising = readl(gpio->base + GPIOREN(gb));
++ unsigned long rising = readl(gpio->base + GPIOREN(gb));
+ unsigned long falling = readl(gpio->base + GPIOFEN(gb));
++ unsigned long high = readl(gpio->base + GPIOHEN(gb));
++ unsigned long low = readl(gpio->base + GPIOLEN(gb));
+
+ gn = gn % 32;
+
+ writel(1 << gn, gpio->base + GPIOEDS(gb));
+
+ if (gpio->rising & (1 << gn)) {
-+ writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
++ writel(rising | (1 << gn), gpio->base + GPIOREN(gb));
+ } else {
+ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
+ }
+
+ if (gpio->falling & (1 << gn)) {
-+ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
++ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb));
+ } else {
+ writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
+ }
++
++ if (gpio->high & (1 << gn)) {
++ writel(high | (1 << gn), gpio->base + GPIOHEN(gb));
++ } else {
++ writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
++ }
++
++ if (gpio->low & (1 << gn)) {
++ writel(low | (1 << gn), gpio->base + GPIOLEN(gb));
++ } else {
++ writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
++ }
+}
+
+static struct irq_chip bcm2708_irqchip = {
@@ -4012,7 +4091,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/
+
+ ucb->gc.label = "bcm2708_gpio";
+ ucb->gc.base = 0;
-+ ucb->gc.ngpio = ARCH_NR_GPIOS;
++ ucb->gc.ngpio = BCM2708_NR_GPIOS;
+ ucb->gc.owner = THIS_MODULE;
+
+ ucb->gc.direction_input = bcm2708_gpio_dir_in;
@@ -4069,10 +4148,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-raspberry-pi/
+
+MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver");
+MODULE_LICENSE("GPL");
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.h linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708.h
---- linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/bcm2708.h 2014-03-11 17:31:43.000000000 +0100
-@@ -0,0 +1,51 @@
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/bcm2708.h linux-rpi/arch/arm/mach-bcm2708/bcm2708.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/bcm2708.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/bcm2708.h 2014-04-24 16:04:30.051029784 +0200
+@@ -0,0 +1,49 @@
+/*
+ * linux/arch/arm/mach-bcm2708/bcm2708.h
+ *
@@ -4118,15 +4197,13 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/bcm2708.h linux-raspberry-pi/arch/
+ .end = (base##_BASE) + SZ_4K - 1,\
+ .flags = IORESOURCE_MEM, \
+ }, \
-+ .dma_mask = ~0, \
+ .irq = base##_IRQ, \
-+ /* .dma = base##_DMA,*/ \
+}
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/clock.c linux-raspberry-pi/arch/arm/mach-bcm2708/clock.c
---- linux-3.12.13/arch/arm/mach-bcm2708/clock.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/clock.c 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/clock.c linux-rpi/arch/arm/mach-bcm2708/clock.c
+--- linux-3.12.18/arch/arm/mach-bcm2708/clock.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/clock.c 2014-04-24 15:35:00.773527891 +0200
@@ -0,0 +1,61 @@
+/*
+ * linux/arch/arm/mach-bcm2708/clock.c
@@ -4189,9 +4266,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/clock.c linux-raspberry-pi/arch/ar
+ return -EIO;
+}
+EXPORT_SYMBOL(clk_set_rate);
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/clock.h linux-raspberry-pi/arch/arm/mach-bcm2708/clock.h
---- linux-3.12.13/arch/arm/mach-bcm2708/clock.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/clock.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/clock.h linux-rpi/arch/arm/mach-bcm2708/clock.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/clock.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/clock.h 2014-04-24 15:35:00.773527891 +0200
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/mach-bcm2708/clock.h
@@ -4217,9 +4294,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/clock.h linux-raspberry-pi/arch/ar
+struct clk {
+ unsigned long rate;
+};
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/dma.c linux-raspberry-pi/arch/arm/mach-bcm2708/dma.c
---- linux-3.12.13/arch/arm/mach-bcm2708/dma.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/dma.c 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/dma.c linux-rpi/arch/arm/mach-bcm2708/dma.c
+--- linux-3.12.18/arch/arm/mach-bcm2708/dma.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/dma.c 2014-04-24 15:35:00.773527891 +0200
@@ -0,0 +1,407 @@
+/*
+ * linux/arch/arm/mach-bcm2708/dma.c
@@ -4628,899 +4705,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/dma.c linux-raspberry-pi/arch/arm/
+MODULE_LICENSE("GPL");
+
+MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM");
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/dmaer.c linux-raspberry-pi/arch/arm/mach-bcm2708/dmaer.c
---- linux-3.12.13/arch/arm/mach-bcm2708/dmaer.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/dmaer.c 2014-03-11 17:51:02.000000000 +0100
-@@ -0,0 +1,886 @@
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/module.h>
-+#include <linux/types.h>
-+#include <linux/kdev_t.h>
-+#include <linux/fs.h>
-+#include <linux/cdev.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/pagemap.h>
-+#include <linux/device.h>
-+#include <linux/jiffies.h>
-+#include <linux/timex.h>
-+#include <linux/dma-mapping.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/atomic.h>
-+#include <asm/cacheflush.h>
-+#include <asm/io.h>
-+
-+#include <mach/dma.h>
-+#include <mach/vc_support.h>
-+
-+#ifdef ECLIPSE_IGNORE
-+
-+#define __user
-+#define __init
-+#define __exit
-+#define __iomem
-+#define KERN_DEBUG
-+#define KERN_ERR
-+#define KERN_WARNING
-+#define KERN_INFO
-+#define _IOWR(a, b, c) b
-+#define _IOW(a, b, c) b
-+#define _IO(a, b) b
-+
-+#endif
-+
-+//#define inline
-+
-+#define PRINTK(args...) printk(args)
-+//#define PRINTK_VERBOSE(args...) printk(args)
-+//#define PRINTK(args...)
-+#define PRINTK_VERBOSE(args...)
-+
-+/***** TYPES ****/
-+#define PAGES_PER_LIST 500
-+struct PageList
-+{
-+ struct page *m_pPages[PAGES_PER_LIST];
-+ unsigned int m_used;
-+ struct PageList *m_pNext;
-+};
-+
-+struct VmaPageList
-+{
-+ //each vma has a linked list of pages associated with it
-+ struct PageList *m_pPageHead;
-+ struct PageList *m_pPageTail;
-+ unsigned int m_refCount;
-+};
-+
-+struct DmaControlBlock
-+{
-+ unsigned int m_transferInfo;
-+ void __user *m_pSourceAddr;
-+ void __user *m_pDestAddr;
-+ unsigned int m_xferLen;
-+ unsigned int m_tdStride;
-+ struct DmaControlBlock *m_pNext;
-+ unsigned int m_blank1, m_blank2;
-+};
-+
-+/***** DEFINES ******/
-+//magic number defining the module
-+#define DMA_MAGIC 0xdd
-+
-+//do user virtual to physical translation of the CB chain
-+#define DMA_PREPARE _IOWR(DMA_MAGIC, 0, struct DmaControlBlock *)
-+
-+//kick the pre-prepared CB chain
-+#define DMA_KICK _IOW(DMA_MAGIC, 1, struct DmaControlBlock *)
-+
-+//prepare it, kick it, wait for it
-+#define DMA_PREPARE_KICK_WAIT _IOWR(DMA_MAGIC, 2, struct DmaControlBlock *)
-+
-+//prepare it, kick it, don't wait for it
-+#define DMA_PREPARE_KICK _IOWR(DMA_MAGIC, 3, struct DmaControlBlock *)
-+
-+//not currently implemented
-+#define DMA_WAIT_ONE _IO(DMA_MAGIC, 4, struct DmaControlBlock *)
-+
-+//wait on all kicked CB chains
-+#define DMA_WAIT_ALL _IO(DMA_MAGIC, 5)
-+
-+//in order to discover the largest AXI burst that should be programmed into the transfer params
-+#define DMA_MAX_BURST _IO(DMA_MAGIC, 6)
-+
-+//set the address range through which the user address is assumed to already by a physical address
-+#define DMA_SET_MIN_PHYS _IOW(DMA_MAGIC, 7, unsigned long)
-+#define DMA_SET_MAX_PHYS _IOW(DMA_MAGIC, 8, unsigned long)
-+#define DMA_SET_PHYS_OFFSET _IOW(DMA_MAGIC, 9, unsigned long)
-+
-+//used to define the size for the CMA-based allocation *in pages*, can only be done once once the file is opened
-+#define DMA_CMA_SET_SIZE _IOW(DMA_MAGIC, 10, unsigned long)
-+
-+//used to get the version of the module, to test for a capability
-+#define DMA_GET_VERSION _IO(DMA_MAGIC, 99)
-+
-+#define VERSION_NUMBER 1
-+
-+#define VIRT_TO_BUS_CACHE_SIZE 8
-+
-+/***** FILE OPS *****/
-+static int Open(struct inode *pInode, struct file *pFile);
-+static int Release(struct inode *pInode, struct file *pFile);
-+static long Ioctl(struct file *pFile, unsigned int cmd, unsigned long arg);
-+static ssize_t Read(struct file *pFile, char __user *pUser, size_t count, loff_t *offp);
-+static int Mmap(struct file *pFile, struct vm_area_struct *pVma);
-+
-+/***** VMA OPS ****/
-+static void VmaOpen4k(struct vm_area_struct *pVma);
-+static void VmaClose4k(struct vm_area_struct *pVma);
-+static int VmaFault4k(struct vm_area_struct *pVma, struct vm_fault *pVmf);
-+
-+/**** DMA PROTOTYPES */
-+static struct DmaControlBlock __user *DmaPrepare(struct DmaControlBlock __user *pUserCB, int *pError);
-+static int DmaKick(struct DmaControlBlock __user *pUserCB);
-+static void DmaWaitAll(void);
-+
-+/**** GENERIC ****/
-+static int __init dmaer_init(void);
-+static void __exit dmaer_exit(void);
-+
-+/*** OPS ***/
-+static struct vm_operations_struct g_vmOps4k = {
-+ .open = VmaOpen4k,
-+ .close = VmaClose4k,
-+ .fault = VmaFault4k,
-+};
-+
-+static struct file_operations g_fOps = {
-+ .owner = THIS_MODULE,
-+ .llseek = 0,
-+ .read = Read,
-+ .write = 0,
-+ .unlocked_ioctl = Ioctl,
-+ .open = Open,
-+ .release = Release,
-+ .mmap = Mmap,
-+};
-+
-+/***** GLOBALS ******/
-+static dev_t g_majorMinor;
-+
-+//tracking usage of the two files
-+static atomic_t g_oneLock4k = ATOMIC_INIT(1);
-+
-+//device operations
-+static struct cdev g_cDev;
-+static int g_trackedPages = 0;
-+
-+//dma control
-+static unsigned int *g_pDmaChanBase;
-+static int g_dmaIrq;
-+static int g_dmaChan;
-+
-+//cma allocation
-+static int g_cmaHandle;
-+
-+//user virtual to bus address translation acceleration
-+static unsigned long g_virtAddr[VIRT_TO_BUS_CACHE_SIZE];
-+static unsigned long g_busAddr[VIRT_TO_BUS_CACHE_SIZE];
-+static unsigned long g_cbVirtAddr;
-+static unsigned long g_cbBusAddr;
-+static int g_cacheInsertAt;
-+static int g_cacheHit, g_cacheMiss;
-+
-+//off by default
-+static void __user *g_pMinPhys;
-+static void __user *g_pMaxPhys;
-+static unsigned long g_physOffset;
-+
-+/****** CACHE OPERATIONS ********/
-+static inline void FlushAddrCache(void)
-+{
-+ int count = 0;
-+ for (count = 0; count < VIRT_TO_BUS_CACHE_SIZE; count++)
-+ g_virtAddr[count] = 0xffffffff; //never going to match as we always chop the bottom bits anyway
-+
-+ g_cbVirtAddr = 0xffffffff;
-+
-+ g_cacheInsertAt = 0;
-+}
-+
-+//translate from a user virtual address to a bus address by mapping the page
-+//NB this won't lock a page in memory, so to avoid potential paging issues using kernel logical addresses
-+static inline void __iomem *UserVirtualToBus(void __user *pUser)
-+{
-+ int mapped;
-+ struct page *pPage;
-+ void *phys;
-+
-+ //map it (requiring that the pointer points to something that does not hang off the page boundary)
-+ mapped = get_user_pages(current, current->mm,
-+ (unsigned long)pUser, 1,
-+ 1, 0,
-+ &pPage,
-+ 0);
-+
-+ if (mapped <= 0) //error
-+ return 0;
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "user virtual %p arm phys %p bus %p\n",
-+ pUser, page_address(pPage), (void __iomem *)__virt_to_bus(page_address(pPage)));
-+
-+ //get the arm physical address
-+ phys = page_address(pPage) + offset_in_page(pUser);
-+ page_cache_release(pPage);
-+
-+ //and now the bus address
-+ return (void __iomem *)__virt_to_bus(phys);
-+}
-+
-+static inline void __iomem *UserVirtualToBusViaCbCache(void __user *pUser)
-+{
-+ unsigned long virtual_page = (unsigned long)pUser & ~4095;
-+ unsigned long page_offset = (unsigned long)pUser & 4095;
-+ unsigned long bus_addr;
-+
-+ if (g_cbVirtAddr == virtual_page)
-+ {
-+ bus_addr = g_cbBusAddr + page_offset;
-+ g_cacheHit++;
-+ return (void __iomem *)bus_addr;
-+ }
-+ else
-+ {
-+ bus_addr = (unsigned long)UserVirtualToBus(pUser);
-+
-+ if (!bus_addr)
-+ return 0;
-+
-+ g_cbVirtAddr = virtual_page;
-+ g_cbBusAddr = bus_addr & ~4095;
-+ g_cacheMiss++;
-+
-+ return (void __iomem *)bus_addr;
-+ }
-+}
-+
-+//do the same as above, by query our virt->bus cache
-+static inline void __iomem *UserVirtualToBusViaCache(void __user *pUser)
-+{
-+ int count;
-+ //get the page and its offset
-+ unsigned long virtual_page = (unsigned long)pUser & ~4095;
-+ unsigned long page_offset = (unsigned long)pUser & 4095;
-+ unsigned long bus_addr;
-+
-+ if (pUser >= g_pMinPhys && pUser < g_pMaxPhys)
-+ {
-+ PRINTK_VERBOSE(KERN_DEBUG "user->phys passthrough on %p\n", pUser);
-+ return (void __iomem *)((unsigned long)pUser + g_physOffset);
-+ }
-+
-+ //check the cache for our entry
-+ for (count = 0; count < VIRT_TO_BUS_CACHE_SIZE; count++)
-+ if (g_virtAddr[count] == virtual_page)
-+ {
-+ bus_addr = g_busAddr[count] + page_offset;
-+ g_cacheHit++;
-+ return (void __iomem *)bus_addr;
-+ }
-+
-+ //not found, look up manually and then insert its page address
-+ bus_addr = (unsigned long)UserVirtualToBus(pUser);
-+
-+ if (!bus_addr)
-+ return 0;
-+
-+ g_virtAddr[g_cacheInsertAt] = virtual_page;
-+ g_busAddr[g_cacheInsertAt] = bus_addr & ~4095;
-+
-+ //round robin
-+ g_cacheInsertAt++;
-+ if (g_cacheInsertAt == VIRT_TO_BUS_CACHE_SIZE)
-+ g_cacheInsertAt = 0;
-+
-+ g_cacheMiss++;
-+
-+ return (void __iomem *)bus_addr;
-+}
-+
-+/***** FILE OPERATIONS ****/
-+static int Open(struct inode *pInode, struct file *pFile)
-+{
-+ PRINTK(KERN_DEBUG "file opening: %d/%d\n", imajor(pInode), iminor(pInode));
-+
-+ //check which device we are
-+ if (iminor(pInode) == 0) //4k
-+ {
-+ //only one at a time
-+ if (!atomic_dec_and_test(&g_oneLock4k))
-+ {
-+ atomic_inc(&g_oneLock4k);
-+ return -EBUSY;
-+ }
-+ }
-+ else
-+ return -EINVAL;
-+
-+ //todo there will be trouble if two different processes open the files
-+
-+ //reset after any file is opened
-+ g_pMinPhys = (void __user *)-1;
-+ g_pMaxPhys = (void __user *)0;
-+ g_physOffset = 0;
-+ g_cmaHandle = 0;
-+
-+ return 0;
-+}
-+
-+static int Release(struct inode *pInode, struct file *pFile)
-+{
-+ PRINTK(KERN_DEBUG "file closing, %d pages tracked\n", g_trackedPages);
-+ if (g_trackedPages)
-+ PRINTK(KERN_ERR "we\'re leaking memory!\n");
-+
-+ //wait for any dmas to finish
-+ DmaWaitAll();
-+
-+ //free this memory on the application closing the file or it crashing (implicitly closing the file)
-+ if (g_cmaHandle)
-+ {
-+ PRINTK(KERN_DEBUG "unlocking vc memory\n");
-+ if (UnlockVcMemory(g_cmaHandle))
-+ PRINTK(KERN_ERR "uh-oh, unable to unlock vc memory!\n");
-+ PRINTK(KERN_DEBUG "releasing vc memory\n");
-+ if (ReleaseVcMemory(g_cmaHandle))
-+ PRINTK(KERN_ERR "uh-oh, unable to release vc memory!\n");
-+ }
-+
-+ if (iminor(pInode) == 0)
-+ atomic_inc(&g_oneLock4k);
-+ else
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static struct DmaControlBlock __user *DmaPrepare(struct DmaControlBlock __user *pUserCB, int *pError)
-+{
-+ struct DmaControlBlock kernCB;
-+ struct DmaControlBlock __user *pUNext;
-+ void __iomem *pSourceBus, __iomem *pDestBus;
-+
-+ //get the control block into kernel memory so we can work on it
-+ if (copy_from_user(&kernCB, pUserCB, sizeof(struct DmaControlBlock)) != 0)
-+ {
-+ PRINTK(KERN_ERR "copy_from_user failed for user cb %p\n", pUserCB);
-+ *pError = 1;
-+ return 0;
-+ }
-+
-+ if (kernCB.m_pSourceAddr == 0 || kernCB.m_pDestAddr == 0)
-+ {
-+ PRINTK(KERN_ERR "faulty source (%p) dest (%p) addresses for user cb %p\n",
-+ kernCB.m_pSourceAddr, kernCB.m_pDestAddr, pUserCB);
-+ *pError = 1;
-+ return 0;
-+ }
-+
-+ pSourceBus = UserVirtualToBusViaCache(kernCB.m_pSourceAddr);
-+ pDestBus = UserVirtualToBusViaCache(kernCB.m_pDestAddr);
-+
-+ if (!pSourceBus || !pDestBus)
-+ {
-+ PRINTK(KERN_ERR "virtual to bus translation failure for source/dest %p/%p->%p/%p\n",
-+ kernCB.m_pSourceAddr, kernCB.m_pDestAddr,
-+ pSourceBus, pDestBus);
-+ *pError = 1;
-+ return 0;
-+ }
-+
-+ //update the user structure with the new bus addresses
-+ kernCB.m_pSourceAddr = pSourceBus;
-+ kernCB.m_pDestAddr = pDestBus;
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "final source %p dest %p\n", kernCB.m_pSourceAddr, kernCB.m_pDestAddr);
-+
-+ //sort out the bus address for the next block
-+ pUNext = kernCB.m_pNext;
-+
-+ if (kernCB.m_pNext)
-+ {
-+ void __iomem *pNextBus;
-+ pNextBus = UserVirtualToBusViaCbCache(kernCB.m_pNext);
-+
-+ if (!pNextBus)
-+ {
-+ PRINTK(KERN_ERR "virtual to bus translation failure for m_pNext\n");
-+ *pError = 1;
-+ return 0;
-+ }
-+
-+ //update the pointer with the bus address
-+ kernCB.m_pNext = pNextBus;
-+ }
-+
-+ //write it back to user space
-+ if (copy_to_user(pUserCB, &kernCB, sizeof(struct DmaControlBlock)) != 0)
-+ {
-+ PRINTK(KERN_ERR "copy_to_user failed for cb %p\n", pUserCB);
-+ *pError = 1;
-+ return 0;
-+ }
-+
-+ __cpuc_flush_dcache_area(pUserCB, 32);
-+
-+ *pError = 0;
-+ return pUNext;
-+}
-+
-+static int DmaKick(struct DmaControlBlock __user *pUserCB)
-+{
-+ void __iomem *pBusCB;
-+
-+ pBusCB = UserVirtualToBusViaCbCache(pUserCB);
-+ if (!pBusCB)
-+ {
-+ PRINTK(KERN_ERR "virtual to bus translation failure for cb\n");
-+ return 1;
-+ }
-+
-+ //flush_cache_all();
-+
-+ bcm_dma_start(g_pDmaChanBase, (dma_addr_t)pBusCB);
-+
-+ return 0;
-+}
-+
-+static void DmaWaitAll(void)
-+{
-+ int counter = 0;
-+ volatile int inner_count;
-+ volatile unsigned int cs;
-+ unsigned long time_before, time_after;
-+
-+ time_before = jiffies;
-+ //bcm_dma_wait_idle(g_pDmaChanBase);
-+ dsb();
-+
-+ cs = readl(g_pDmaChanBase);
-+
-+ while ((cs & 1) == 1)
-+ {
-+ cs = readl(g_pDmaChanBase);
-+ counter++;
-+
-+ for (inner_count = 0; inner_count < 32; inner_count++);
-+
-+ asm volatile ("MCR p15,0,r0,c7,c0,4 \n");
-+ //cpu_do_idle();
-+ if (counter >= 1000000)
-+ {
-+ PRINTK(KERN_WARNING "DMA failed to finish in a timely fashion\n");
-+ break;
-+ }
-+ }
-+ time_after = jiffies;
-+ PRINTK_VERBOSE(KERN_DEBUG "done, counter %d, cs %08x", counter, cs);
-+ PRINTK_VERBOSE(KERN_DEBUG "took %ld jiffies, %d HZ\n", time_after - time_before, HZ);
-+}
-+
-+static long Ioctl(struct file *pFile, unsigned int cmd, unsigned long arg)
-+{
-+ int error = 0;
-+ PRINTK_VERBOSE(KERN_DEBUG "ioctl cmd %x arg %lx\n", cmd, arg);
-+
-+ switch (cmd)
-+ {
-+ case DMA_PREPARE:
-+ case DMA_PREPARE_KICK:
-+ case DMA_PREPARE_KICK_WAIT:
-+ {
-+ struct DmaControlBlock __user *pUCB = (struct DmaControlBlock *)arg;
-+ int steps = 0;
-+ unsigned long start_time = jiffies;
-+ (void)start_time;
-+
-+ //flush our address cache
-+ FlushAddrCache();
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "dma prepare\n");
-+
-+ //do virtual to bus translation for each entry
-+ do
-+ {
-+ pUCB = DmaPrepare(pUCB, &error);
-+ } while (error == 0 && ++steps && pUCB);
-+ PRINTK_VERBOSE(KERN_DEBUG "prepare done in %d steps, %ld\n", steps, jiffies - start_time);
-+
-+ //carry straight on if we want to kick too
-+ if (cmd == DMA_PREPARE || error)
-+ {
-+ PRINTK_VERBOSE(KERN_DEBUG "falling out\n");
-+ return error ? -EINVAL : 0;
-+ }
-+ }
-+ case DMA_KICK:
-+ PRINTK_VERBOSE(KERN_DEBUG "dma begin\n");
-+
-+ if (cmd == DMA_KICK)
-+ FlushAddrCache();
-+
-+ DmaKick((struct DmaControlBlock __user *)arg);
-+
-+ if (cmd != DMA_PREPARE_KICK_WAIT)
-+ break;
-+/* case DMA_WAIT_ONE:
-+ //PRINTK(KERN_DEBUG "dma wait one\n");
-+ break;*/
-+ case DMA_WAIT_ALL:
-+ //PRINTK(KERN_DEBUG "dma wait all\n");
-+ DmaWaitAll();
-+ break;
-+ case DMA_MAX_BURST:
-+ if (g_dmaChan == 0)
-+ return 10;
-+ else
-+ return 5;
-+ case DMA_SET_MIN_PHYS:
-+ g_pMinPhys = (void __user *)arg;
-+ PRINTK(KERN_DEBUG "min/max user/phys bypass set to %p %p\n", g_pMinPhys, g_pMaxPhys);
-+ break;
-+ case DMA_SET_MAX_PHYS:
-+ g_pMaxPhys = (void __user *)arg;
-+ PRINTK(KERN_DEBUG "min/max user/phys bypass set to %p %p\n", g_pMinPhys, g_pMaxPhys);
-+ break;
-+ case DMA_SET_PHYS_OFFSET:
-+ g_physOffset = arg;
-+ PRINTK(KERN_DEBUG "user/phys bypass offset set to %ld\n", g_physOffset);
-+ break;
-+ case DMA_CMA_SET_SIZE:
-+ {
-+ unsigned int pBusAddr;
-+
-+ if (g_cmaHandle)
-+ {
-+ PRINTK(KERN_ERR "memory has already been allocated (handle %d)\n", g_cmaHandle);
-+ return -EINVAL;
-+ }
-+
-+ PRINTK(KERN_INFO "allocating %ld bytes of VC memory\n", arg * 4096);
-+
-+ //get the memory
-+ if (AllocateVcMemory(&g_cmaHandle, arg * 4096, 4096, MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_NO_INIT | MEM_FLAG_HINT_PERMALOCK))
-+ {
-+ PRINTK(KERN_ERR "failed to allocate %ld bytes of VC memory\n", arg * 4096);
-+ g_cmaHandle = 0;
-+ return -EINVAL;
-+ }
-+
-+ //get an address for it
-+ PRINTK(KERN_INFO "trying to map VC memory\n");
-+
-+ if (LockVcMemory(&pBusAddr, g_cmaHandle))
-+ {
-+ PRINTK(KERN_ERR "failed to map CMA handle %d, releasing memory\n", g_cmaHandle);
-+ ReleaseVcMemory(g_cmaHandle);
-+ g_cmaHandle = 0;
-+ }
-+
-+ PRINTK(KERN_INFO "bus address for CMA memory is %x\n", pBusAddr);
-+ return pBusAddr;
-+ }
-+ case DMA_GET_VERSION:
-+ PRINTK(KERN_DEBUG "returning version number, %d\n", VERSION_NUMBER);
-+ return VERSION_NUMBER;
-+ default:
-+ PRINTK(KERN_DEBUG "unknown ioctl: %d\n", cmd);
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static ssize_t Read(struct file *pFile, char __user *pUser, size_t count, loff_t *offp)
-+{
-+ return -EIO;
-+}
-+
-+static int Mmap(struct file *pFile, struct vm_area_struct *pVma)
-+{
-+ struct PageList *pPages;
-+ struct VmaPageList *pVmaList;
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "MMAP vma %p, length %ld (%s %d)\n",
-+ pVma, pVma->vm_end - pVma->vm_start,
-+ current->comm, current->pid);
-+ PRINTK_VERBOSE(KERN_DEBUG "MMAP %p %d (tracked %d)\n", pVma, current->pid, g_trackedPages);
-+
-+ //make a new page list
-+ pPages = (struct PageList *)kmalloc(sizeof(struct PageList), GFP_KERNEL);
-+ if (!pPages)
-+ {
-+ PRINTK(KERN_ERR "couldn\'t allocate a new page list (%s %d)\n",
-+ current->comm, current->pid);
-+ return -ENOMEM;
-+ }
-+
-+ //clear the page list
-+ pPages->m_used = 0;
-+ pPages->m_pNext = 0;
-+
-+ //insert our vma and new page list somewhere
-+ if (!pVma->vm_private_data)
-+ {
-+ struct VmaPageList *pList;
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "new vma list, making new one (%s %d)\n",
-+ current->comm, current->pid);
-+
-+ //make a new vma list
-+ pList = (struct VmaPageList *)kmalloc(sizeof(struct VmaPageList), GFP_KERNEL);
-+ if (!pList)
-+ {
-+ PRINTK(KERN_ERR "couldn\'t allocate vma page list (%s %d)\n",
-+ current->comm, current->pid);
-+ kfree(pPages);
-+ return -ENOMEM;
-+ }
-+
-+ //clear this list
-+ pVma->vm_private_data = (void *)pList;
-+ pList->m_refCount = 0;
-+ }
-+
-+ pVmaList = (struct VmaPageList *)pVma->vm_private_data;
-+
-+ //add it to the vma list
-+ pVmaList->m_pPageHead = pPages;
-+ pVmaList->m_pPageTail = pPages;
-+
-+ pVma->vm_ops = &g_vmOps4k;
-+ pVma->vm_flags |= VM_IO;
-+
-+ VmaOpen4k(pVma);
-+
-+ return 0;
-+}
-+
-+/****** VMA OPERATIONS ******/
-+
-+static void VmaOpen4k(struct vm_area_struct *pVma)
-+{
-+ struct VmaPageList *pVmaList;
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "vma open %p private %p (%s %d), %d live pages\n", pVma, pVma->vm_private_data, current->comm, current->pid, g_trackedPages);
-+ PRINTK_VERBOSE(KERN_DEBUG "OPEN %p %d %ld pages (tracked pages %d)\n",
-+ pVma, current->pid, (pVma->vm_end - pVma->vm_start) >> 12,
-+ g_trackedPages);
-+
-+ pVmaList = (struct VmaPageList *)pVma->vm_private_data;
-+
-+ if (pVmaList)
-+ {
-+ pVmaList->m_refCount++;
-+ PRINTK_VERBOSE(KERN_DEBUG "ref count is now %d\n", pVmaList->m_refCount);
-+ }
-+ else
-+ {
-+ PRINTK_VERBOSE(KERN_DEBUG "err, open but no vma page list\n");
-+ }
-+}
-+
-+static void VmaClose4k(struct vm_area_struct *pVma)
-+{
-+ struct VmaPageList *pVmaList;
-+ int freed = 0;
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "vma close %p private %p (%s %d)\n", pVma, pVma->vm_private_data, current->comm, current->pid);
-+
-+ //wait for any dmas to finish
-+ DmaWaitAll();
-+
-+ //find our vma in the list
-+ pVmaList = (struct VmaPageList *)pVma->vm_private_data;
-+
-+ //may be a fork
-+ if (pVmaList)
-+ {
-+ struct PageList *pPages;
-+
-+ pVmaList->m_refCount--;
-+
-+ if (pVmaList->m_refCount == 0)
-+ {
-+ PRINTK_VERBOSE(KERN_DEBUG "found vma, freeing pages (%s %d)\n",
-+ current->comm, current->pid);
-+
-+ pPages = pVmaList->m_pPageHead;
-+
-+ if (!pPages)
-+ {
-+ PRINTK(KERN_ERR "no page list (%s %d)!\n",
-+ current->comm, current->pid);
-+ return;
-+ }
-+
-+ while (pPages)
-+ {
-+ struct PageList *next;
-+ int count;
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "page list (%s %d)\n",
-+ current->comm, current->pid);
-+
-+ next = pPages->m_pNext;
-+ for (count = 0; count < pPages->m_used; count++)
-+ {
-+ PRINTK_VERBOSE(KERN_DEBUG "freeing page %p (%s %d)\n",
-+ pPages->m_pPages[count],
-+ current->comm, current->pid);
-+ __free_pages(pPages->m_pPages[count], 0);
-+ g_trackedPages--;
-+ freed++;
-+ }
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "freeing page list (%s %d)\n",
-+ current->comm, current->pid);
-+ kfree(pPages);
-+ pPages = next;
-+ }
-+
-+ //remove our vma from the list
-+ kfree(pVmaList);
-+ pVma->vm_private_data = 0;
-+ }
-+ else
-+ {
-+ PRINTK_VERBOSE(KERN_DEBUG "ref count is %d, not closing\n", pVmaList->m_refCount);
-+ }
-+ }
-+ else
-+ {
-+ PRINTK_VERBOSE(KERN_ERR "uh-oh, vma %p not found (%s %d)!\n", pVma, current->comm, current->pid);
-+ PRINTK_VERBOSE(KERN_ERR "CLOSE ERR\n");
-+ }
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "CLOSE %p %d %d pages (tracked pages %d)",
-+ pVma, current->pid, freed, g_trackedPages);
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "%d pages open\n", g_trackedPages);
-+}
-+
-+static int VmaFault4k(struct vm_area_struct *pVma, struct vm_fault *pVmf)
-+{
-+ PRINTK_VERBOSE(KERN_DEBUG "vma fault for vma %p private %p at offset %ld (%s %d)\n", pVma, pVma->vm_private_data, pVmf->pgoff,
-+ current->comm, current->pid);
-+ PRINTK_VERBOSE(KERN_DEBUG "FAULT\n");
-+ pVmf->page = alloc_page(GFP_KERNEL);
-+
-+ if (pVmf->page)
-+ {
-+ PRINTK_VERBOSE(KERN_DEBUG "alloc page virtual %p\n", page_address(pVmf->page));
-+ }
-+
-+ if (!pVmf->page)
-+ {
-+ PRINTK(KERN_ERR "vma fault oom (%s %d)\n", current->comm, current->pid);
-+ return VM_FAULT_OOM;
-+ }
-+ else
-+ {
-+ struct VmaPageList *pVmaList;
-+
-+ get_page(pVmf->page);
-+ g_trackedPages++;
-+
-+ //find our vma in the list
-+ pVmaList = (struct VmaPageList *)pVma->vm_private_data;
-+
-+ if (pVmaList)
-+ {
-+ PRINTK_VERBOSE(KERN_DEBUG "vma found (%s %d)\n", current->comm, current->pid);
-+
-+ if (pVmaList->m_pPageTail->m_used == PAGES_PER_LIST)
-+ {
-+ PRINTK_VERBOSE(KERN_DEBUG "making new page list (%s %d)\n", current->comm, current->pid);
-+ //making a new page list
-+ pVmaList->m_pPageTail->m_pNext = (struct PageList *)kmalloc(sizeof(struct PageList), GFP_KERNEL);
-+ if (!pVmaList->m_pPageTail->m_pNext)
-+ return -ENOMEM;
-+
-+ //update the tail pointer
-+ pVmaList->m_pPageTail = pVmaList->m_pPageTail->m_pNext;
-+ pVmaList->m_pPageTail->m_used = 0;
-+ pVmaList->m_pPageTail->m_pNext = 0;
-+ }
-+
-+ PRINTK_VERBOSE(KERN_DEBUG "adding page to list (%s %d)\n", current->comm, current->pid);
-+
-+ pVmaList->m_pPageTail->m_pPages[pVmaList->m_pPageTail->m_used] = pVmf->page;
-+ pVmaList->m_pPageTail->m_used++;
-+ }
-+ else
-+ PRINTK(KERN_ERR "returned page for vma we don\'t know %p (%s %d)\n", pVma, current->comm, current->pid);
-+
-+ return 0;
-+ }
-+}
-+
-+/****** GENERIC FUNCTIONS ******/
-+static int __init dmaer_init(void)
-+{
-+ int result = alloc_chrdev_region(&g_majorMinor, 0, 1, "dmaer");
-+ if (result < 0)
-+ {
-+ PRINTK(KERN_ERR "unable to get major device number\n");
-+ return result;
-+ }
-+ else
-+ PRINTK(KERN_DEBUG "major device number %d\n", MAJOR(g_majorMinor));
-+
-+ PRINTK(KERN_DEBUG "vma list size %d, page list size %d, page size %ld\n",
-+ sizeof(struct VmaPageList), sizeof(struct PageList), PAGE_SIZE);
-+
-+ //get a dma channel to work with
-+ result = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST, (void **)&g_pDmaChanBase, &g_dmaIrq);
-+
-+ //uncomment to force to channel 0
-+ //result = 0;
-+ //g_pDmaChanBase = 0xce808000;
-+
-+ if (result < 0)
-+ {
-+ PRINTK(KERN_ERR "failed to allocate dma channel\n");
-+ cdev_del(&g_cDev);
-+ unregister_chrdev_region(g_majorMinor, 1);
-+ }
-+
-+ //reset the channel
-+ PRINTK(KERN_DEBUG "allocated dma channel %d (%p), initial state %08x\n", result, g_pDmaChanBase, *g_pDmaChanBase);
-+ *g_pDmaChanBase = 1 << 31;
-+ PRINTK(KERN_DEBUG "post-reset %08x\n", *g_pDmaChanBase);
-+
-+ g_dmaChan = result;
-+
-+ //clear the cache stats
-+ g_cacheHit = 0;
-+ g_cacheMiss = 0;
-+
-+ //register our device - after this we are go go go
-+ cdev_init(&g_cDev, &g_fOps);
-+ g_cDev.owner = THIS_MODULE;
-+ g_cDev.ops = &g_fOps;
-+
-+ result = cdev_add(&g_cDev, g_majorMinor, 1);
-+ if (result < 0)
-+ {
-+ PRINTK(KERN_ERR "failed to add character device\n");
-+ unregister_chrdev_region(g_majorMinor, 1);
-+ bcm_dma_chan_free(g_dmaChan);
-+ return result;
-+ }
-+
-+ return 0;
-+}
-+
-+static void __exit dmaer_exit(void)
-+{
-+ PRINTK(KERN_INFO "closing dmaer device, cache stats: %d hits %d misses\n", g_cacheHit, g_cacheMiss);
-+ //unregister the device
-+ cdev_del(&g_cDev);
-+ unregister_chrdev_region(g_majorMinor, 1);
-+ //free the dma channel
-+ bcm_dma_chan_free(g_dmaChan);
-+}
-+
-+MODULE_LICENSE("Dual BSD/GPL");
-+MODULE_AUTHOR("Simon Hall");
-+module_init(dmaer_init);
-+module_exit(dmaer_exit);
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/arm_control.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_control.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/arm_control.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-rpi/arch/arm/mach-bcm2708/include/mach/arm_control.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/arm_control.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/arm_control.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,419 @@
+/*
+ * linux/arch/arm/mach-bcm2708/arm_control.h
@@ -5941,9 +5128,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-r
+#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c)
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/arm_power.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_power.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/arm_power.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-rpi/arch/arm/mach-bcm2708/include/mach/arm_power.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/arm_power.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/arm_power.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,60 @@
+/*
+ * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h
@@ -6005,9 +5192,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-ras
+};
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/clkdev.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/clkdev.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/clkdev.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-rpi/arch/arm/mach-bcm2708/include/mach/clkdev.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/clkdev.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/clkdev.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
@@ -6016,9 +5203,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-raspbe
+#define __clk_put(clk) do { } while (0)
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/debug-macro.S
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/debug-macro.S 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/debug-macro.S 2014-03-11 17:51:02.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-rpi/arch/arm/mach-bcm2708/include/mach/debug-macro.S
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/debug-macro.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/debug-macro.S 2014-04-24 16:04:30.051029784 +0200
@@ -0,0 +1,22 @@
+/* arch/arm/mach-bcm2708/include/mach/debug-macro.S
+ *
@@ -6042,9 +5229,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-r
+ .endm
+
+#include <debug/pl01x.S>
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/dma.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/dma.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/dma.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/dma.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/dma.h linux-rpi/arch/arm/mach-bcm2708/include/mach/dma.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/dma.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,90 @@
+/*
+ * linux/arch/arm/mach-bcm2708/include/mach/dma.h
@@ -6136,9 +5323,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/dma.h linux-raspberry
+
+
+#endif /* _MACH_BCM2708_DMA_H */
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/entry-macro.S
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/entry-macro.S 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/entry-macro.S 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-rpi/arch/arm/mach-bcm2708/include/mach/entry-macro.S
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/entry-macro.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/entry-macro.S 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,69 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/entry-macro.S
@@ -6209,9 +5396,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-r
+1020: @ EQ will be set if no irqs pending
+
+ .endm
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/frc.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/frc.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/frc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/frc.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/frc.h linux-rpi/arch/arm/mach-bcm2708/include/mach/frc.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/frc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/frc.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/timex.h
@@ -6251,9 +5438,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/frc.h linux-raspberry
+extern unsigned long long frc_clock_ticks63(void);
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/gpio.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/gpio.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/gpio.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/gpio.h 2014-03-11 17:51:02.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/gpio.h linux-rpi/arch/arm/mach-bcm2708/include/mach/gpio.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/gpio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/gpio.h 2014-04-24 16:04:30.051029784 +0200
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/gpio.h
@@ -6266,15 +5453,15 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/gpio.h linux-raspberr
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
-+#define ARCH_NR_GPIOS 54 // number of gpio lines
++#define BCM2708_NR_GPIOS 54 // number of gpio lines
+
+#define gpio_to_irq(x) ((x) + GPIO_IRQ_START)
+#define irq_to_gpio(x) ((x) - GPIO_IRQ_START)
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/hardware.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/hardware.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/hardware.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/hardware.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/hardware.h linux-rpi/arch/arm/mach-bcm2708/include/mach/hardware.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/hardware.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/hardware.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/hardware.h
@@ -6304,9 +5491,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/hardware.h linux-rasp
+#include <mach/platform.h>
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/io.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/io.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/io.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/io.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/io.h linux-rpi/arch/arm/mach-bcm2708/include/mach/io.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/io.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/io.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,27 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/io.h
@@ -6335,10 +5522,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/io.h linux-raspberry-
+#define __io(a) __typesafe_io(a)
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/irqs.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/irqs.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/irqs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/irqs.h 2014-03-11 17:31:43.000000000 +0100
-@@ -0,0 +1,199 @@
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/irqs.h linux-rpi/arch/arm/mach-bcm2708/include/mach/irqs.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/irqs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/irqs.h 2014-04-24 16:04:30.051029784 +0200
+@@ -0,0 +1,200 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/irqs.h
+ *
@@ -6533,14 +5720,15 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/irqs.h linux-raspberr
+#define HARD_IRQS (64 + 21)
+#define FIQ_IRQS (64 + 21)
+#define GPIO_IRQS (32*5)
++#define SPARE_IRQS (64)
+
-+#define NR_IRQS HARD_IRQS+FIQ_IRQS+GPIO_IRQS
++#define NR_IRQS HARD_IRQS+FIQ_IRQS+GPIO_IRQS+SPARE_IRQS
+
+
+#endif /* _BCM2708_IRQS_H_ */
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/memory.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/memory.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/memory.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/memory.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/memory.h linux-rpi/arch/arm/mach-bcm2708/include/mach/memory.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/memory.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/memory.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/memory.h
@@ -6599,9 +5787,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/memory.h linux-raspbe
+#define __bus_to_pfn(x) __phys_to_pfn((x) - (BUS_OFFSET - PLAT_PHYS_OFFSET))
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/platform.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/platform.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/platform.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/platform.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/platform.h linux-rpi/arch/arm/mach-bcm2708/include/mach/platform.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/platform.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/platform.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,228 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/platform.h
@@ -6831,9 +6019,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/platform.h linux-rasp
+#endif
+
+/* END */
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/power.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/power.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/power.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/power.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/power.h linux-rpi/arch/arm/mach-bcm2708/include/mach/power.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/power.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/power.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/mach-bcm2708/power.h
@@ -6861,9 +6049,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/power.h linux-raspber
+extern int bcm_power_close(BCM_POWER_HANDLE_T handle);
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/system.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/system.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/system.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/system.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/system.h linux-rpi/arch/arm/mach-bcm2708/include/mach/system.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/system.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/system.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/system.h
@@ -6903,9 +6091,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/system.h linux-raspbe
+}
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/timex.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/timex.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/timex.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/timex.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/timex.h linux-rpi/arch/arm/mach-bcm2708/include/mach/timex.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/timex.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/timex.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/timex.h
@@ -6930,9 +6118,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/timex.h linux-raspber
+ */
+
+#define CLOCK_TICK_RATE (1000000)
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/uncompress.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/uncompress.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/uncompress.h 2014-03-11 17:51:02.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-rpi/arch/arm/mach-bcm2708/include/mach/uncompress.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/uncompress.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/uncompress.h 2014-04-24 16:04:30.051029784 +0200
@@ -0,0 +1,84 @@
+/*
+ * arch/arm/mach-bcn2708/include/mach/uncompress.h
@@ -7018,9 +6206,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-ra
+ * nothing to do
+ */
+#define arch_decomp_wdog()
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vcio.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vcio.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vcio.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vcio.h 2014-03-11 17:51:02.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vcio.h linux-rpi/arch/arm/mach-bcm2708/include/mach/vcio.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vcio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/vcio.h 2014-04-24 16:04:30.051029784 +0200
@@ -0,0 +1,141 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/vcio.h
@@ -7163,9 +6351,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vcio.h linux-raspberr
+#define DEVICE_FILE_NAME "char_dev"
+
+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vc_mem.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_mem.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vc_mem.h 2014-03-11 17:51:02.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-rpi/arch/arm/mach-bcm2708/include/mach/vc_mem.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vc_mem.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/vc_mem.h 2014-04-24 16:04:30.051029784 +0200
@@ -0,0 +1,35 @@
+/*****************************************************************************
+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
@@ -7202,82 +6390,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-raspbe
+#endif
+
+#endif /* VC_MEM_H */
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_support.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vc_support.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vc_support.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vc_support.h 2014-03-11 17:31:43.000000000 +0100
-@@ -0,0 +1,69 @@
-+#ifndef _VC_SUPPORT_H_
-+#define _VC_SUPPORT_H_
-+
-+/*
-+ * vc_support.h
-+ *
-+ * Created on: 25 Nov 2012
-+ * Author: Simon
-+ */
-+
-+enum {
-+/*
-+ If a MEM_HANDLE_T is discardable, the memory manager may resize it to size
-+ 0 at any time when it is not locked or retained.
-+ */
-+ MEM_FLAG_DISCARDABLE = 1 << 0,
-+
-+ /*
-+ If a MEM_HANDLE_T is allocating (or normal), its block of memory will be
-+ accessed in an allocating fashion through the cache.
-+ */
-+ MEM_FLAG_NORMAL = 0 << 2,
-+ MEM_FLAG_ALLOCATING = MEM_FLAG_NORMAL,
-+
-+ /*
-+ If a MEM_HANDLE_T is direct, its block of memory will be accessed
-+ directly, bypassing the cache.
-+ */
-+ MEM_FLAG_DIRECT = 1 << 2,
-+
-+ /*
-+ If a MEM_HANDLE_T is coherent, its block of memory will be accessed in a
-+ non-allocating fashion through the cache.
-+ */
-+ MEM_FLAG_COHERENT = 2 << 2,
-+
-+ /*
-+ If a MEM_HANDLE_T is L1-nonallocating, its block of memory will be accessed by
-+ the VPU in a fashion which is allocating in L2, but only coherent in L1.
-+ */
-+ MEM_FLAG_L1_NONALLOCATING = (MEM_FLAG_DIRECT | MEM_FLAG_COHERENT),
-+
-+ /*
-+ If a MEM_HANDLE_T is zero'd, its contents are set to 0 rather than
-+ MEM_HANDLE_INVALID on allocation and resize up.
-+ */
-+ MEM_FLAG_ZERO = 1 << 4,
-+
-+ /*
-+ If a MEM_HANDLE_T is uninitialised, it will not be reset to a defined value
-+ (either zero, or all 1's) on allocation.
-+ */
-+ MEM_FLAG_NO_INIT = 1 << 5,
-+
-+ /*
-+ Hints.
-+ */
-+ MEM_FLAG_HINT_PERMALOCK = 1 << 6, /* Likely to be locked for long periods of time. */
-+};
-+
-+unsigned int AllocateVcMemory(unsigned int *pHandle, unsigned int size, unsigned int alignment, unsigned int flags);
-+unsigned int ReleaseVcMemory(unsigned int handle);
-+unsigned int LockVcMemory(unsigned int *pBusAddress, unsigned int handle);
-+unsigned int UnlockVcMemory(unsigned int handle);
-+
-+unsigned int ExecuteVcCode(unsigned int code,
-+ unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5);
-+
-+#endif
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vmalloc.h
---- linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vmalloc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/include/mach/vmalloc.h 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-rpi/arch/arm/mach-bcm2708/include/mach/vmalloc.h
+--- linux-3.12.18/arch/arm/mach-bcm2708/include/mach/vmalloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/include/mach/vmalloc.h 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/mach-bcm2708/include/mach/vmalloc.h
@@ -7299,10 +6414,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-raspb
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#define VMALLOC_END (0xe8000000)
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Kconfig linux-raspberry-pi/arch/arm/mach-bcm2708/Kconfig
---- linux-3.12.13/arch/arm/mach-bcm2708/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/Kconfig 2014-03-11 17:51:02.000000000 +0100
-@@ -0,0 +1,49 @@
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/Kconfig linux-rpi/arch/arm/mach-bcm2708/Kconfig
+--- linux-3.12.18/arch/arm/mach-bcm2708/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/Kconfig 2014-04-24 16:04:30.051029784 +0200
+@@ -0,0 +1,41 @@
+menu "Broadcom BCM2708 Implementations"
+ depends on ARCH_BCM2708
+
@@ -7343,19 +6458,11 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Kconfig linux-raspberry-pi/arch/ar
+ default y
+ help
+ Binds spidev driver to the SPI0 master
-+
-+config BCM2708_DMAER
-+ tristate "BCM2708 DMA helper"
-+ depends on MACH_BCM2708
-+ default n
-+ help
-+ Enable DMA helper for accelerating X composition
-+
+endmenu
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Makefile linux-raspberry-pi/arch/arm/mach-bcm2708/Makefile
---- linux-3.12.13/arch/arm/mach-bcm2708/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/Makefile 2014-03-11 17:51:02.000000000 +0100
-@@ -0,0 +1,10 @@
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/Makefile linux-rpi/arch/arm/mach-bcm2708/Makefile
+--- linux-3.12.18/arch/arm/mach-bcm2708/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/Makefile 2014-04-24 16:04:30.051029784 +0200
+@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
+#
@@ -7363,19 +6470,16 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Makefile linux-raspberry-pi/arch/a
+obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o
+obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o
+obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o
-+
-+obj-$(CONFIG_BCM2708_DMAER) += dmaer_master.o
-+dmaer_master-objs := dmaer.o vc_support.o
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/Makefile.boot linux-raspberry-pi/arch/arm/mach-bcm2708/Makefile.boot
---- linux-3.12.13/arch/arm/mach-bcm2708/Makefile.boot 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/Makefile.boot 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/Makefile.boot linux-rpi/arch/arm/mach-bcm2708/Makefile.boot
+--- linux-3.12.18/arch/arm/mach-bcm2708/Makefile.boot 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/Makefile.boot 2014-04-24 15:35:00.773527891 +0200
@@ -0,0 +1,3 @@
+ zreladdr-y := 0x00008000
+params_phys-y := 0x00000100
+initrd_phys-y := 0x00800000
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/power.c linux-raspberry-pi/arch/arm/mach-bcm2708/power.c
---- linux-3.12.13/arch/arm/mach-bcm2708/power.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/power.c 2014-03-11 17:31:43.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/power.c linux-rpi/arch/arm/mach-bcm2708/power.c
+--- linux-3.12.18/arch/arm/mach-bcm2708/power.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/power.c 2014-04-24 15:35:00.777527936 +0200
@@ -0,0 +1,194 @@
+/*
+ * linux/arch/arm/mach-bcm2708/power.c
@@ -7571,9 +6675,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/power.c linux-raspberry-pi/arch/ar
+MODULE_AUTHOR("Phil Elwell");
+MODULE_DESCRIPTION("Interface to BCM2708 power management");
+MODULE_LICENSE("GPL");
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vcio.c linux-raspberry-pi/arch/arm/mach-bcm2708/vcio.c
---- linux-3.12.13/arch/arm/mach-bcm2708/vcio.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/vcio.c 2014-03-11 17:51:02.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/vcio.c linux-rpi/arch/arm/mach-bcm2708/vcio.c
+--- linux-3.12.18/arch/arm/mach-bcm2708/vcio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/vcio.c 2014-04-24 16:04:30.051029784 +0200
@@ -0,0 +1,474 @@
+/*
+ * linux/arch/arm/mach-bcm2708/vcio.c
@@ -8049,10 +7153,10 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vcio.c linux-raspberry-pi/arch/arm
+MODULE_DESCRIPTION("ARM I/O to VideoCore processor");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bcm-mbox");
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/arm/mach-bcm2708/vc_mem.c
---- linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/vc_mem.c 2014-03-11 17:51:02.000000000 +0100
-@@ -0,0 +1,462 @@
+diff -Nur linux-3.12.18/arch/arm/mach-bcm2708/vc_mem.c linux-rpi/arch/arm/mach-bcm2708/vc_mem.c
+--- linux-3.12.18/arch/arm/mach-bcm2708/vc_mem.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/arch/arm/mach-bcm2708/vc_mem.c 2014-04-24 15:35:00.777527936 +0200
+@@ -0,0 +1,432 @@
+/*****************************************************************************
+* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved.
+*
@@ -8074,7 +7178,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+#include <linux/cdev.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
-+#include <linux/proc_fs.h>
++#include <linux/debugfs.h>
+#include <asm/uaccess.h>
+#include <linux/dma-mapping.h>
+
@@ -8090,24 +7194,15 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+
+#define DRIVER_NAME "vc-mem"
+
-+// Uncomment to enable debug logging
-+// #define ENABLE_DBG
-+
-+#if defined(ENABLE_DBG)
-+#define LOG_DBG( fmt, ... ) printk( KERN_INFO fmt "\n", ##__VA_ARGS__ )
-+#else
-+#define LOG_DBG( fmt, ... )
-+#endif
-+#define LOG_ERR( fmt, ... ) printk( KERN_ERR fmt "\n", ##__VA_ARGS__ )
-+
+// Device (/dev) related variables
+static dev_t vc_mem_devnum = 0;
+static struct class *vc_mem_class = NULL;
+static struct cdev vc_mem_cdev;
+static int vc_mem_inited = 0;
+
-+// Proc entry
-+static struct proc_dir_entry *vc_mem_proc_entry;
++#ifdef CONFIG_DEBUG_FS
++static struct dentry *vc_mem_debugfs_entry;
++#endif
+
+/*
+ * Videocore memory addresses and size
@@ -8149,7 +7244,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ (void) inode;
+ (void) file;
+
-+ LOG_DBG("%s: called file = 0x%p", __func__, file);
++ pr_debug("%s: called file = 0x%p\n", __func__, file);
+
+ return 0;
+}
@@ -8166,7 +7261,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ (void) inode;
+ (void) file;
+
-+ LOG_DBG("%s: called file = 0x%p", __func__, file);
++ pr_debug("%s: called file = 0x%p\n", __func__, file);
+
+ return 0;
+}
@@ -8221,12 +7316,12 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ (void) cmd;
+ (void) arg;
+
-+ LOG_DBG("%s: called file = 0x%p", __func__, file);
++ pr_debug("%s: called file = 0x%p\n", __func__, file);
+
+ switch (cmd) {
+ case VC_MEM_IOC_MEM_PHYS_ADDR:
+ {
-+ LOG_DBG("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p",
++ pr_debug("%s: VC_MEM_IOC_MEM_PHYS_ADDR=0x%p\n",
+ __func__, (void *) mm_vc_mem_phys_addr);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_phys_addr,
@@ -8240,7 +7335,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ // Get the videocore memory size first
+ vc_mem_get_size();
+
-+ LOG_DBG("%s: VC_MEM_IOC_MEM_SIZE=%u", __func__,
++ pr_debug("%s: VC_MEM_IOC_MEM_SIZE=%u\n", __func__,
+ mm_vc_mem_size);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_size,
@@ -8254,7 +7349,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ // Get the videocore memory base
+ vc_mem_get_base();
+
-+ LOG_DBG("%s: VC_MEM_IOC_MEM_BASE=%u", __func__,
++ pr_debug("%s: VC_MEM_IOC_MEM_BASE=%u\n", __func__,
+ mm_vc_mem_base);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_base,
@@ -8268,7 +7363,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ // Get the videocore memory base
+ vc_mem_get_base();
+
-+ LOG_DBG("%s: VC_MEM_IOC_MEM_LOAD=%u", __func__,
++ pr_debug("%s: VC_MEM_IOC_MEM_LOAD=%u\n", __func__,
+ mm_vc_mem_base);
+
+ if (copy_to_user((void *) arg, &mm_vc_mem_base,
@@ -8282,7 +7377,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ return -ENOTTY;
+ }
+ }
-+ LOG_DBG("%s: file = 0x%p returning %d", __func__, file, rc);
++ pr_debug("%s: file = 0x%p returning %d\n", __func__, file, rc);
+
+ return rc;
+}
@@ -8300,12 +7395,12 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ unsigned long length = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
-+ LOG_DBG("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx",
++ pr_debug("%s: vm_start = 0x%08lx vm_end = 0x%08lx vm_pgoff = 0x%08lx\n",
+ __func__, (long) vma->vm_start, (long) vma->vm_end,
+ (long) vma->vm_pgoff);
+
+ if (offset + length > mm_vc_mem_size) {
-+ LOG_ERR("%s: length %ld is too big", __func__, length);
++ pr_err("%s: length %ld is too big\n", __func__, length);
+ return -EINVAL;
+ }
+ // Do not cache the memory map
@@ -8315,7 +7410,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ (mm_vc_mem_phys_addr >> PAGE_SHIFT) +
+ vma->vm_pgoff, length, vma->vm_page_prot);
+ if (rc != 0) {
-+ LOG_ERR("%s: remap_pfn_range failed (rc=%d)", __func__, rc);
++ pr_err("%s: remap_pfn_range failed (rc=%d)\n", __func__, rc);
+ }
+
+ return rc;
@@ -8335,75 +7430,60 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ .mmap = vc_mem_mmap,
+};
+
-+/****************************************************************************
-+*
-+* vc_mem_proc_read
-+*
-+***************************************************************************/
-+
-+static int
-+vc_mem_proc_read(char *buf, char **start, off_t offset, int count, int *eof,
-+ void *data)
++#ifdef CONFIG_DEBUG_FS
++static void vc_mem_debugfs_deinit(void)
+{
-+ char *p = buf;
-+
-+ (void) start;
-+ (void) count;
-+ (void) data;
-+
-+ if (offset > 0) {
-+ *eof = 1;
-+ return 0;
-+ }
-+ // Get the videocore memory size first
-+ vc_mem_get_size();
-+
-+ p += sprintf(p, "Videocore memory:\n");
-+ if (mm_vc_mem_phys_addr != 0)
-+ p += sprintf(p, " Physical address: 0x%p\n",
-+ (void *) mm_vc_mem_phys_addr);
-+ else
-+ p += sprintf(p, " Physical address: 0x00000000\n");
-+ p += sprintf(p, " Length (bytes): %u\n", mm_vc_mem_size);
-+
-+ *eof = 1;
-+ return p - buf;
++ debugfs_remove_recursive(vc_mem_debugfs_entry);
++ vc_mem_debugfs_entry = NULL;
+}
+
-+/****************************************************************************
-+*
-+* vc_mem_proc_write
-+*
-+***************************************************************************/
+
-+static int
-+vc_mem_proc_write(struct file *file, const char __user * buffer,
-+ unsigned long count, void *data)
++static int vc_mem_debugfs_init(
++ struct device *dev)
+{
-+ int rc = -EFAULT;
-+ char input_str[10];
-+
-+ memset(input_str, 0, sizeof (input_str));
++ vc_mem_debugfs_entry = debugfs_create_dir(DRIVER_NAME, NULL);
++ if (!vc_mem_debugfs_entry) {
++ dev_warn(dev, "could not create debugfs entry\n");
++ return -EFAULT;
++ }
+
-+ if (count > sizeof (input_str)) {
-+ LOG_ERR("%s: input string length too long", __func__);
-+ goto out;
++ if (!debugfs_create_x32("vc_mem_phys_addr",
++ 0444,
++ vc_mem_debugfs_entry,
++ (u32 *)&mm_vc_mem_phys_addr)) {
++ dev_warn(dev, "%s:could not create vc_mem_phys entry\n",
++ __func__);
++ goto fail;
+ }
+
-+ if (copy_from_user(input_str, buffer, count - 1)) {
-+ LOG_ERR("%s: failed to get input string", __func__);
-+ goto out;
++ if (!debugfs_create_x32("vc_mem_size",
++ 0444,
++ vc_mem_debugfs_entry,
++ (u32 *)&mm_vc_mem_size)) {
++ dev_warn(dev, "%s:could not create vc_mem_size entry\n",
++ __func__);
++ goto fail;
+ }
+
-+ if (strncmp(input_str, "connect", strlen("connect")) == 0) {
-+ // Get the videocore memory size from the videocore
-+ vc_mem_get_size();
++ if (!debugfs_create_x32("vc_mem_base",
++ 0444,
++ vc_mem_debugfs_entry,
++ (u32 *)&mm_vc_mem_base)) {
++ dev_warn(dev, "%s:could not create vc_mem_base entry\n",
++ __func__);
++ goto fail;
+ }
+
-+ out:
-+ return rc;
++ return 0;
++
++fail:
++ vc_mem_debugfs_deinit();
++ return -EFAULT;
+}
+
++#endif /* CONFIG_DEBUG_FS */
++
++
+/****************************************************************************
+*
+* vc_mem_init
@@ -8416,7 +7496,7 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ int rc = -EFAULT;
+ struct device *dev;
+
-+ LOG_DBG("%s: called", __func__);
++ pr_debug("%s: called\n", __func__);
+
+ mm_vc_mem_phys_addr = phys_addr;
+ mm_vc_mem_size = mem_size;
@@ -8424,24 +7504,25 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+
+ vc_mem_get_size();
+
-+ printk("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",
++ pr_info("vc-mem: phys_addr:0x%08lx mem_base=0x%08x mem_size:0x%08x(%u MiB)\n",
+ mm_vc_mem_phys_addr, mm_vc_mem_base, mm_vc_mem_size, mm_vc_mem_size / (1024 * 1024));
+
+ if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) {
-+ LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc);
++ pr_err("%s: alloc_chrdev_region failed (rc=%d)\n",
++ __func__, rc);
+ goto out_err;
+ }
+
+ cdev_init(&vc_mem_cdev, &vc_mem_fops);
+ if ((rc = cdev_add(&vc_mem_cdev, vc_mem_devnum, 1)) != 0) {
-+ LOG_ERR("%s: cdev_add failed (rc=%d)", __func__, rc);
++ pr_err("%s: cdev_add failed (rc=%d)\n", __func__, rc);
+ goto out_unregister;
+ }
+
+ vc_mem_class = class_create(THIS_MODULE, DRIVER_NAME);
+ if (IS_ERR(vc_mem_class)) {
+ rc = PTR_ERR(vc_mem_class);
-+ LOG_ERR("%s: class_create failed (rc=%d)", __func__, rc);
++ pr_err("%s: class_create failed (rc=%d)\n", __func__, rc);
+ goto out_cdev_del;
+ }
+
@@ -8449,25 +7530,18 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+ DRIVER_NAME);
+ if (IS_ERR(dev)) {
+ rc = PTR_ERR(dev);
-+ LOG_ERR("%s: device_create failed (rc=%d)", __func__, rc);
++ pr_err("%s: device_create failed (rc=%d)\n", __func__, rc);
+ goto out_class_destroy;
+ }
+
-+#if 0
-+ vc_mem_proc_entry = create_proc_entry(DRIVER_NAME, 0444, NULL);
-+ if (vc_mem_proc_entry == NULL) {
-+ rc = -EFAULT;
-+ LOG_ERR("%s: create_proc_entry failed", __func__);
-+ goto out_device_destroy;
-+ }
-+ vc_mem_proc_entry->read_proc = vc_mem_proc_read;
-+ vc_mem_proc_entry->write_proc = vc_mem_proc_write;
++#ifdef CONFIG_DEBUG_FS
++ /* don't fail if the debug entries cannot be created */
++ vc_mem_debugfs_init(dev);
+#endif
+
+ vc_mem_inited = 1;
+ return 0;
+
-+ out_device_destroy:
+ device_destroy(vc_mem_class, vc_mem_devnum);
+
+ out_class_destroy:
@@ -8493,11 +7567,11 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+static void __exit
+vc_mem_exit(void)
+{
-+ LOG_DBG("%s: called", __func__);
++ pr_debug("%s: called\n", __func__);
+
+ if (vc_mem_inited) {
-+#if 0
-+ remove_proc_entry(vc_mem_proc_entry->name, NULL);
++#if CONFIG_DEBUG_FS
++ vc_mem_debugfs_deinit();
+#endif
+ device_destroy(vc_mem_class, vc_mem_devnum);
+ class_destroy(vc_mem_class);
@@ -8515,331 +7589,9 @@ diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_mem.c linux-raspberry-pi/arch/a
+module_param(mem_size, uint, 0644);
+module_param(mem_base, uint, 0644);
+
-diff -Nur linux-3.12.13/arch/arm/mach-bcm2708/vc_support.c linux-raspberry-pi/arch/arm/mach-bcm2708/vc_support.c
---- linux-3.12.13/arch/arm/mach-bcm2708/vc_support.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mach-bcm2708/vc_support.c 2014-03-11 17:51:02.000000000 +0100
-@@ -0,0 +1,318 @@
-+/*
-+ * vc_support.c
-+ *
-+ * Created on: 25 Nov 2012
-+ * Author: Simon
-+ */
-+
-+#include <linux/module.h>
-+#include <mach/vcio.h>
-+
-+#ifdef ECLIPSE_IGNORE
-+
-+#define __user
-+#define __init
-+#define __exit
-+#define __iomem
-+#define KERN_DEBUG
-+#define KERN_ERR
-+#define KERN_WARNING
-+#define KERN_INFO
-+#define _IOWR(a, b, c) b
-+#define _IOW(a, b, c) b
-+#define _IO(a, b) b
-+
-+#endif
-+
-+/****** VC MAILBOX FUNCTIONALITY ******/
-+unsigned int AllocateVcMemory(unsigned int *pHandle, unsigned int size, unsigned int alignment, unsigned int flags)
-+{
-+ struct vc_msg
-+ {
-+ unsigned int m_msgSize;
-+ unsigned int m_response;
-+
-+ struct vc_tag
-+ {
-+ unsigned int m_tagId;
-+ unsigned int m_sendBufferSize;
-+ union {
-+ unsigned int m_sendDataSize;
-+ unsigned int m_recvDataSize;
-+ };
-+
-+ struct args
-+ {
-+ union {
-+ unsigned int m_size;
-+ unsigned int m_handle;
-+ };
-+ unsigned int m_alignment;
-+ unsigned int m_flags;
-+ } m_args;
-+ } m_tag;
-+
-+ unsigned int m_endTag;
-+ } msg;
-+ int s;
-+
-+ msg.m_msgSize = sizeof(msg);
-+ msg.m_response = 0;
-+ msg.m_endTag = 0;
-+
-+ //fill in the tag for the allocation command
-+ msg.m_tag.m_tagId = 0x3000c;
-+ msg.m_tag.m_sendBufferSize = 12;
-+ msg.m_tag.m_sendDataSize = 12;
-+
-+ //fill in our args
-+ msg.m_tag.m_args.m_size = size;
-+ msg.m_tag.m_args.m_alignment = alignment;
-+ msg.m_tag.m_args.m_flags = flags;
-+
-+ //run the command
-+ s = bcm_mailbox_property(&msg, sizeof(msg));
-+
-+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004)
-+ {
-+ *pHandle = msg.m_tag.m_args.m_handle;
-+ return 0;
-+ }
-+ else
-+ {
-+ printk(KERN_ERR "failed to allocate vc memory: s=%d response=%08x recv data size=%08x\n",
-+ s, msg.m_response, msg.m_tag.m_recvDataSize);
-+ return 1;
-+ }
-+}
-+
-+unsigned int ReleaseVcMemory(unsigned int handle)
-+{
-+ struct vc_msg
-+ {
-+ unsigned int m_msgSize;
-+ unsigned int m_response;
-+
-+ struct vc_tag
-+ {
-+ unsigned int m_tagId;
-+ unsigned int m_sendBufferSize;
-+ union {
-+ unsigned int m_sendDataSize;
-+ unsigned int m_recvDataSize;
-+ };
-+
-+ struct args
-+ {
-+ union {
-+ unsigned int m_handle;
-+ unsigned int m_error;
-+ };
-+ } m_args;
-+ } m_tag;
-+
-+ unsigned int m_endTag;
-+ } msg;
-+ int s;
-+
-+ msg.m_msgSize = sizeof(msg);
-+ msg.m_response = 0;
-+ msg.m_endTag = 0;
-+
-+ //fill in the tag for the release command
-+ msg.m_tag.m_tagId = 0x3000f;
-+ msg.m_tag.m_sendBufferSize = 4;
-+ msg.m_tag.m_sendDataSize = 4;
-+
-+ //pass across the handle
-+ msg.m_tag.m_args.m_handle = handle;
-+
-+ s = bcm_mailbox_property(&msg, sizeof(msg));
-+
-+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004 && msg.m_tag.m_args.m_error == 0)
-+ return 0;
-+ else
-+ {
-+ printk(KERN_ERR "failed to release vc memory: s=%d response=%08x recv data size=%08x error=%08x\n",
-+ s, msg.m_response, msg.m_tag.m_recvDataSize, msg.m_tag.m_args.m_error);
-+ return 1;
-+ }
-+}
-+
-+unsigned int LockVcMemory(unsigned int *pBusAddress, unsigned int handle)
-+{
-+ struct vc_msg
-+ {
-+ unsigned int m_msgSize;
-+ unsigned int m_response;
-+
-+ struct vc_tag
-+ {
-+ unsigned int m_tagId;
-+ unsigned int m_sendBufferSize;
-+ union {
-+ unsigned int m_sendDataSize;
-+ unsigned int m_recvDataSize;
-+ };
-+
-+ struct args
-+ {
-+ union {
-+ unsigned int m_handle;
-+ unsigned int m_busAddress;
-+ };
-+ } m_args;
-+ } m_tag;
-+
-+ unsigned int m_endTag;
-+ } msg;
-+ int s;
-+
-+ msg.m_msgSize = sizeof(msg);
-+ msg.m_response = 0;
-+ msg.m_endTag = 0;
-+
-+ //fill in the tag for the lock command
-+ msg.m_tag.m_tagId = 0x3000d;
-+ msg.m_tag.m_sendBufferSize = 4;
-+ msg.m_tag.m_sendDataSize = 4;
-+
-+ //pass across the handle
-+ msg.m_tag.m_args.m_handle = handle;
-+
-+ s = bcm_mailbox_property(&msg, sizeof(msg));
-+
-+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004)
-+ {
-+ //pick out the bus address
-+ *pBusAddress = msg.m_tag.m_args.m_busAddress;
-+ return 0;
-+ }
-+ else
-+ {
-+ printk(KERN_ERR "failed to lock vc memory: s=%d response=%08x recv data size=%08x\n",
-+ s, msg.m_response, msg.m_tag.m_recvDataSize);
-+ return 1;
-+ }
-+}
-+
-+unsigned int UnlockVcMemory(unsigned int handle)
-+{
-+ struct vc_msg
-+ {
-+ unsigned int m_msgSize;
-+ unsigned int m_response;
-+
-+ struct vc_tag
-+ {
-+ unsigned int m_tagId;
-+ unsigned int m_sendBufferSize;
-+ union {
-+ unsigned int m_sendDataSize;
-+ unsigned int m_recvDataSize;
-+ };
-+
-+ struct args
-+ {
-+ union {
-+ unsigned int m_handle;
-+ unsigned int m_error;
-+ };
-+ } m_args;
-+ } m_tag;
-+
-+ unsigned int m_endTag;
-+ } msg;
-+ int s;
-+
-+ msg.m_msgSize = sizeof(msg);
-+ msg.m_response = 0;
-+ msg.m_endTag = 0;
-+
-+ //fill in the tag for the unlock command
-+ msg.m_tag.m_tagId = 0x3000e;
-+ msg.m_tag.m_sendBufferSize = 4;
-+ msg.m_tag.m_sendDataSize = 4;
-+
-+ //pass across the handle
-+ msg.m_tag.m_args.m_handle = handle;
-+
-+ s = bcm_mailbox_property(&msg, sizeof(msg));
-+
-+ //check the error code too
-+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004 && msg.m_tag.m_args.m_error == 0)
-+ return 0;
-+ else
-+ {
-+ printk(KERN_ERR "failed to unlock vc memory: s=%d response=%08x recv data size=%08x error%08x\n",
-+ s, msg.m_response, msg.m_tag.m_recvDataSize, msg.m_tag.m_args.m_error);
-+ return 1;
-+ }
-+}
-+
-+unsigned int ExecuteVcCode(unsigned int code,
-+ unsigned int r0, unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int r5)
-+{
-+ struct vc_msg
-+ {
-+ unsigned int m_msgSize;
-+ unsigned int m_response;
-+
-+ struct vc_tag
-+ {
-+ unsigned int m_tagId;
-+ unsigned int m_sendBufferSize;
-+ union {
-+ unsigned int m_sendDataSize;
-+ unsigned int m_recvDataSize;
-+ };
-+
-+ struct args
-+ {
-+ union {
-+ unsigned int m_pCode;
-+ unsigned int m_return;
-+ };
-+ unsigned int m_r0;
-+ unsigned int m_r1;
-+ unsigned int m_r2;
-+ unsigned int m_r3;
-+ unsigned int m_r4;
-+ unsigned int m_r5;
-+ } m_args;
-+ } m_tag;
-+
-+ unsigned int m_endTag;
-+ } msg;
-+ int s;
-+
-+ msg.m_msgSize = sizeof(msg);
-+ msg.m_response = 0;
-+ msg.m_endTag = 0;
-+
-+ //fill in the tag for the unlock command
-+ msg.m_tag.m_tagId = 0x30010;
-+ msg.m_tag.m_sendBufferSize = 28;
-+ msg.m_tag.m_sendDataSize = 28;
-+
-+ //pass across the handle
-+ msg.m_tag.m_args.m_pCode = code;
-+ msg.m_tag.m_args.m_r0 = r0;
-+ msg.m_tag.m_args.m_r1 = r1;
-+ msg.m_tag.m_args.m_r2 = r2;
-+ msg.m_tag.m_args.m_r3 = r3;
-+ msg.m_tag.m_args.m_r4 = r4;
-+ msg.m_tag.m_args.m_r5 = r5;
-+
-+ s = bcm_mailbox_property(&msg, sizeof(msg));
-+
-+ //check the error code too
-+ if (s == 0 && msg.m_response == 0x80000000 && msg.m_tag.m_recvDataSize == 0x80000004)
-+ return msg.m_tag.m_args.m_return;
-+ else
-+ {
-+ printk(KERN_ERR "failed to execute: s=%d response=%08x recv data size=%08x\n",
-+ s, msg.m_response, msg.m_tag.m_recvDataSize);
-+ return 1;
-+ }
-+}
-diff -Nur linux-3.12.13/arch/arm/Makefile linux-raspberry-pi/arch/arm/Makefile
---- linux-3.12.13/arch/arm/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/Makefile 2014-03-11 17:51:00.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/Makefile linux-rpi/arch/arm/Makefile
+--- linux-3.12.18/arch/arm/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arm/Makefile 2014-04-24 16:04:29.515024597 +0200
@@ -146,6 +146,7 @@
# by CONFIG_* macro name.
machine-$(CONFIG_ARCH_AT91) += at91
@@ -8848,9 +7600,9 @@ diff -Nur linux-3.12.13/arch/arm/Makefile linux-raspberry-pi/arch/arm/Makefile
machine-$(CONFIG_ARCH_BCM2835) += bcm2835
machine-$(CONFIG_ARCH_CLPS711X) += clps711x
machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx
-diff -Nur linux-3.12.13/arch/arm/mm/Kconfig linux-raspberry-pi/arch/arm/mm/Kconfig
---- linux-3.12.13/arch/arm/mm/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mm/Kconfig 2014-03-11 17:51:03.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mm/Kconfig linux-rpi/arch/arm/mm/Kconfig
+--- linux-3.12.18/arch/arm/mm/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arm/mm/Kconfig 2014-04-24 16:04:31.615044915 +0200
@@ -358,7 +358,7 @@
# ARMv6
@@ -8860,9 +7612,9 @@ diff -Nur linux-3.12.13/arch/arm/mm/Kconfig linux-raspberry-pi/arch/arm/mm/Kconf
select CPU_32v6
select CPU_ABRT_EV6
select CPU_CACHE_V6
-diff -Nur linux-3.12.13/arch/arm/mm/proc-v6.S linux-raspberry-pi/arch/arm/mm/proc-v6.S
---- linux-3.12.13/arch/arm/mm/proc-v6.S 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/mm/proc-v6.S 2014-03-11 17:51:03.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/mm/proc-v6.S linux-rpi/arch/arm/mm/proc-v6.S
+--- linux-3.12.18/arch/arm/mm/proc-v6.S 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arm/mm/proc-v6.S 2014-04-24 16:04:31.627045031 +0200
@@ -73,10 +73,19 @@
*
* IRQs are already disabled.
@@ -8886,9 +7638,9 @@ diff -Nur linux-3.12.13/arch/arm/mm/proc-v6.S linux-raspberry-pi/arch/arm/mm/pro
mov pc, lr
ENTRY(cpu_v6_dcache_clean_area)
-diff -Nur linux-3.12.13/arch/arm/tools/mach-types linux-raspberry-pi/arch/arm/tools/mach-types
---- linux-3.12.13/arch/arm/tools/mach-types 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/arch/arm/tools/mach-types 2014-03-11 17:31:54.000000000 +0100
+diff -Nur linux-3.12.18/arch/arm/tools/mach-types linux-rpi/arch/arm/tools/mach-types
+--- linux-3.12.18/arch/arm/tools/mach-types 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/arm/tools/mach-types 2014-04-24 15:35:00.985530254 +0200
@@ -522,6 +522,7 @@
prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103
paz00 MACH_PAZ00 PAZ00 3128
@@ -8897,9 +7649,119 @@ diff -Nur linux-3.12.13/arch/arm/tools/mach-types linux-raspberry-pi/arch/arm/to
ag5evm MACH_AG5EVM AG5EVM 3189
ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206
wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207
-diff -Nur linux-3.12.13/Documentation/video4linux/bcm2835-v4l2.txt linux-raspberry-pi/Documentation/video4linux/bcm2835-v4l2.txt
---- linux-3.12.13/Documentation/video4linux/bcm2835-v4l2.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/Documentation/video4linux/bcm2835-v4l2.txt 2014-03-11 17:31:41.000000000 +0100
+diff -Nur linux-3.12.18/arch/m68k/Kconfig linux-rpi/arch/m68k/Kconfig
+--- linux-3.12.18/arch/m68k/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/m68k/Kconfig 2014-04-24 16:04:32.771056098 +0200
+@@ -16,7 +16,6 @@
+ select FPU if MMU
+ select ARCH_WANT_IPC_PARSE_VERSION
+ select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
+- select HAVE_FUTEX_CMPXCHG if MMU && FUTEX
+ select HAVE_MOD_ARCH_SPECIFIC
+ select MODULES_USE_ELF_REL
+ select MODULES_USE_ELF_RELA
+diff -Nur linux-3.12.18/arch/s390/Kconfig linux-rpi/arch/s390/Kconfig
+--- linux-3.12.18/arch/s390/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/s390/Kconfig 2014-04-24 16:04:33.891066931 +0200
+@@ -116,7 +116,6 @@
+ select HAVE_FUNCTION_GRAPH_TRACER
+ select HAVE_FUNCTION_TRACER
+ select HAVE_FUNCTION_TRACE_MCOUNT_TEST
+- select HAVE_FUTEX_CMPXCHG if FUTEX
+ select HAVE_KERNEL_BZIP2
+ select HAVE_KERNEL_GZIP
+ select HAVE_KERNEL_LZ4
+diff -Nur linux-3.12.18/arch/x86/crypto/ghash-clmulni-intel_asm.S linux-rpi/arch/x86/crypto/ghash-clmulni-intel_asm.S
+--- linux-3.12.18/arch/x86/crypto/ghash-clmulni-intel_asm.S 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/x86/crypto/ghash-clmulni-intel_asm.S 2014-04-24 16:04:34.051068479 +0200
+@@ -24,6 +24,10 @@
+ .align 16
+ .Lbswap_mask:
+ .octa 0x000102030405060708090a0b0c0d0e0f
++.Lpoly:
++ .octa 0xc2000000000000000000000000000001
++.Ltwo_one:
++ .octa 0x00000001000000000000000000000001
+
+ #define DATA %xmm0
+ #define SHASH %xmm1
+@@ -130,3 +134,28 @@
+ .Lupdate_just_ret:
+ ret
+ ENDPROC(clmul_ghash_update)
++
++/*
++ * void clmul_ghash_setkey(be128 *shash, const u8 *key);
++ *
++ * Calculate hash_key << 1 mod poly
++ */
++ENTRY(clmul_ghash_setkey)
++ movaps .Lbswap_mask, BSWAP
++ movups (%rsi), %xmm0
++ PSHUFB_XMM BSWAP %xmm0
++ movaps %xmm0, %xmm1
++ psllq $1, %xmm0
++ psrlq $63, %xmm1
++ movaps %xmm1, %xmm2
++ pslldq $8, %xmm1
++ psrldq $8, %xmm2
++ por %xmm1, %xmm0
++ # reduction
++ pshufd $0b00100100, %xmm2, %xmm1
++ pcmpeqd .Ltwo_one, %xmm1
++ pand .Lpoly, %xmm1
++ pxor %xmm1, %xmm0
++ movups %xmm0, (%rdi)
++ ret
++ENDPROC(clmul_ghash_setkey)
+diff -Nur linux-3.12.18/arch/x86/crypto/ghash-clmulni-intel_glue.c linux-rpi/arch/x86/crypto/ghash-clmulni-intel_glue.c
+--- linux-3.12.18/arch/x86/crypto/ghash-clmulni-intel_glue.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/arch/x86/crypto/ghash-clmulni-intel_glue.c 2014-04-24 16:04:34.051068479 +0200
+@@ -30,6 +30,8 @@
+ void clmul_ghash_update(char *dst, const char *src, unsigned int srclen,
+ const be128 *shash);
+
++void clmul_ghash_setkey(be128 *shash, const u8 *key);
++
+ struct ghash_async_ctx {
+ struct cryptd_ahash *cryptd_tfm;
+ };
+@@ -56,23 +58,13 @@
+ const u8 *key, unsigned int keylen)
+ {
+ struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
+- be128 *x = (be128 *)key;
+- u64 a, b;
+
+ if (keylen != GHASH_BLOCK_SIZE) {
+ crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+
+- /* perform multiplication by 'x' in GF(2^128) */
+- a = be64_to_cpu(x->a);
+- b = be64_to_cpu(x->b);
+-
+- ctx->shash.a = (__be64)((b << 1) | (a >> 63));
+- ctx->shash.b = (__be64)((a << 1) | (b >> 63));
+-
+- if (a >> 63)
+- ctx->shash.b ^= cpu_to_be64(0xc2);
++ clmul_ghash_setkey(&ctx->shash, key);
+
+ return 0;
+ }
+diff -Nur linux-3.12.18/Documentation/devicetree/bindings/net/micrel-ks8851.txt linux-rpi/Documentation/devicetree/bindings/net/micrel-ks8851.txt
+--- linux-3.12.18/Documentation/devicetree/bindings/net/micrel-ks8851.txt 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/Documentation/devicetree/bindings/net/micrel-ks8851.txt 2014-04-24 16:04:28.323013063 +0200
+@@ -7,4 +7,3 @@
+
+ Optional properties:
+ - local-mac-address : Ethernet mac address to use
+-- vdd-supply: supply for Ethernet mac
+diff -Nur linux-3.12.18/Documentation/video4linux/bcm2835-v4l2.txt linux-rpi/Documentation/video4linux/bcm2835-v4l2.txt
+--- linux-3.12.18/Documentation/video4linux/bcm2835-v4l2.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/Documentation/video4linux/bcm2835-v4l2.txt 2014-04-24 15:35:00.565525573 +0200
@@ -0,0 +1,60 @@
+
+BCM2835 (aka Raspberry Pi) V4L2 driver
@@ -8961,9 +7823,96 @@ diff -Nur linux-3.12.13/Documentation/video4linux/bcm2835-v4l2.txt linux-raspber
+List of available formats:
+
+$ v4l2-ctl --list-formats
-diff -Nur linux-3.12.13/drivers/char/broadcom/Kconfig linux-raspberry-pi/drivers/char/broadcom/Kconfig
---- linux-3.12.13/drivers/char/broadcom/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/char/broadcom/Kconfig 2014-03-11 17:51:12.000000000 +0100
+diff -Nur linux-3.12.18/drivers/block/floppy.c linux-rpi/drivers/block/floppy.c
+--- linux-3.12.18/drivers/block/floppy.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/block/floppy.c 2014-04-24 15:35:02.077542424 +0200
+@@ -3691,12 +3691,9 @@
+ if (!(mode & FMODE_NDELAY)) {
+ if (mode & (FMODE_READ|FMODE_WRITE)) {
+ UDRS->last_checked = 0;
+- clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
+ check_disk_change(bdev);
+ if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
+ goto out;
+- if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
+- goto out;
+ }
+ res = -EROFS;
+ if ((mode & FMODE_WRITE) &&
+@@ -3749,29 +3746,17 @@
+ * a disk in the drive, and whether that disk is writable.
+ */
+
+-struct rb0_cbdata {
+- int drive;
+- struct completion complete;
+-};
+-
+-static void floppy_rb0_cb(struct bio *bio, int err)
++static void floppy_rb0_complete(struct bio *bio, int err)
+ {
+- struct rb0_cbdata *cbdata = (struct rb0_cbdata *)bio->bi_private;
+- int drive = cbdata->drive;
+-
+- if (err) {
+- pr_info("floppy: error %d while reading block 0", err);
+- set_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
+- }
+- complete(&cbdata->complete);
++ complete((struct completion *)bio->bi_private);
+ }
+
+-static int __floppy_read_block_0(struct block_device *bdev, int drive)
++static int __floppy_read_block_0(struct block_device *bdev)
+ {
+ struct bio bio;
+ struct bio_vec bio_vec;
++ struct completion complete;
+ struct page *page;
+- struct rb0_cbdata cbdata;
+ size_t size;
+
+ page = alloc_page(GFP_NOIO);
+@@ -3784,8 +3769,6 @@
+ if (!size)
+ size = 1024;
+
+- cbdata.drive = drive;
+-
+ bio_init(&bio);
+ bio.bi_io_vec = &bio_vec;
+ bio_vec.bv_page = page;
+@@ -3796,14 +3779,13 @@
+ bio.bi_bdev = bdev;
+ bio.bi_sector = 0;
+ bio.bi_flags = (1 << BIO_QUIET);
+- bio.bi_private = &cbdata;
+- bio.bi_end_io = floppy_rb0_cb;
++ init_completion(&complete);
++ bio.bi_private = &complete;
++ bio.bi_end_io = floppy_rb0_complete;
+
+ submit_bio(READ, &bio);
+ process_fd_request();
+-
+- init_completion(&cbdata.complete);
+- wait_for_completion(&cbdata.complete);
++ wait_for_completion(&complete);
+
+ __free_page(page);
+
+@@ -3845,7 +3827,7 @@
+ UDRS->generation++;
+ if (drive_no_geom(drive)) {
+ /* auto-sensing */
+- res = __floppy_read_block_0(opened_bdev[drive], drive);
++ res = __floppy_read_block_0(opened_bdev[drive]);
+ } else {
+ if (cf)
+ poll_drive(false, FD_RAW_NEED_DISK);
+diff -Nur linux-3.12.18/drivers/char/broadcom/Kconfig linux-rpi/drivers/char/broadcom/Kconfig
+--- linux-3.12.18/drivers/char/broadcom/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/char/broadcom/Kconfig 2014-04-24 16:04:34.339071265 +0200
@@ -0,0 +1,16 @@
+#
+# Broadcom char driver config
@@ -8981,32 +7930,32 @@ diff -Nur linux-3.12.13/drivers/char/broadcom/Kconfig linux-raspberry-pi/drivers
+ help
+ Helper for videocore CMA access.
+
-diff -Nur linux-3.12.13/drivers/char/broadcom/Makefile linux-raspberry-pi/drivers/char/broadcom/Makefile
---- linux-3.12.13/drivers/char/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/char/broadcom/Makefile 2014-03-11 17:51:12.000000000 +0100
+diff -Nur linux-3.12.18/drivers/char/broadcom/Makefile linux-rpi/drivers/char/broadcom/Makefile
+--- linux-3.12.18/drivers/char/broadcom/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/char/broadcom/Makefile 2014-04-24 16:04:34.339071265 +0200
@@ -0,0 +1 @@
+obj-$(CONFIG_BCM_VC_CMA) += vc_cma/
-diff -Nur linux-3.12.13/drivers/char/broadcom/vc_cma/Makefile linux-raspberry-pi/drivers/char/broadcom/vc_cma/Makefile
---- linux-3.12.13/drivers/char/broadcom/vc_cma/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/char/broadcom/vc_cma/Makefile 2014-03-11 17:51:12.000000000 +0100
+diff -Nur linux-3.12.18/drivers/char/broadcom/vc_cma/Makefile linux-rpi/drivers/char/broadcom/vc_cma/Makefile
+--- linux-3.12.18/drivers/char/broadcom/vc_cma/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/char/broadcom/vc_cma/Makefile 2014-04-24 16:04:34.339071265 +0200
@@ -0,0 +1,14 @@
-+EXTRA_CFLAGS += -Wall -Wstrict-prototypes -Wno-trigraphs
-+EXTRA_CFLAGS += -Werror
-+EXTRA_CFLAGS += -I"include/linux/broadcom"
-+EXTRA_CFLAGS += -I"drivers/misc/vc04_services"
-+EXTRA_CFLAGS += -I"drivers/misc/vc04_services/interface/vchi"
-+EXTRA_CFLAGS += -I"drivers/misc/vc04_services/interface/vchiq_arm"
++ccflags-y += -Wall -Wstrict-prototypes -Wno-trigraphs
++ccflags-y += -Werror
++ccflags-y += -Iinclude/linux/broadcom
++ccflags-y += -Idrivers/misc/vc04_services
++ccflags-y += -Idrivers/misc/vc04_services/interface/vchi
++ccflags-y += -Idrivers/misc/vc04_services/interface/vchiq_arm
+
-+EXTRA_CFLAGS += -D__KERNEL__
-+EXTRA_CFLAGS += -D__linux__
-+EXTRA_CFLAGS += -Werror
++ccflags-y += -D__KERNEL__
++ccflags-y += -D__linux__
++ccflags-y += -Werror
+
+obj-$(CONFIG_BCM_VC_CMA) += vc-cma.o
+
+vc-cma-objs := vc_cma.o
-diff -Nur linux-3.12.13/drivers/char/broadcom/vc_cma/vc_cma.c linux-raspberry-pi/drivers/char/broadcom/vc_cma/vc_cma.c
---- linux-3.12.13/drivers/char/broadcom/vc_cma/vc_cma.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/char/broadcom/vc_cma/vc_cma.c 2014-03-11 17:51:12.000000000 +0100
+diff -Nur linux-3.12.18/drivers/char/broadcom/vc_cma/vc_cma.c linux-rpi/drivers/char/broadcom/vc_cma/vc_cma.c
+--- linux-3.12.18/drivers/char/broadcom/vc_cma/vc_cma.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/char/broadcom/vc_cma/vc_cma.c 2014-04-24 16:04:34.339071265 +0200
@@ -0,0 +1,1143 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -10151,9 +9100,9 @@ diff -Nur linux-3.12.13/drivers/char/broadcom/vc_cma/vc_cma.c linux-raspberry-pi
+module_exit(vc_cma_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Broadcom Corporation");
-diff -Nur linux-3.12.13/drivers/char/hw_random/bcm2708-rng.c linux-raspberry-pi/drivers/char/hw_random/bcm2708-rng.c
---- linux-3.12.13/drivers/char/hw_random/bcm2708-rng.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/char/hw_random/bcm2708-rng.c 2014-03-11 17:32:20.000000000 +0100
+diff -Nur linux-3.12.18/drivers/char/hw_random/bcm2708-rng.c linux-rpi/drivers/char/hw_random/bcm2708-rng.c
+--- linux-3.12.18/drivers/char/hw_random/bcm2708-rng.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/char/hw_random/bcm2708-rng.c 2014-04-24 15:35:02.101542691 +0200
@@ -0,0 +1,117 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -10272,9 +9221,9 @@ diff -Nur linux-3.12.13/drivers/char/hw_random/bcm2708-rng.c linux-raspberry-pi/
+
+MODULE_DESCRIPTION("BCM2708 H/W Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL and additional rights");
-diff -Nur linux-3.12.13/drivers/char/hw_random/Kconfig linux-raspberry-pi/drivers/char/hw_random/Kconfig
---- linux-3.12.13/drivers/char/hw_random/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/char/hw_random/Kconfig 2014-03-11 17:51:12.000000000 +0100
+diff -Nur linux-3.12.18/drivers/char/hw_random/Kconfig linux-rpi/drivers/char/hw_random/Kconfig
+--- linux-3.12.18/drivers/char/hw_random/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/char/hw_random/Kconfig 2014-04-24 16:04:34.339071265 +0200
@@ -314,3 +314,14 @@
module will be called tpm-rng.
@@ -10290,17 +9239,29 @@ diff -Nur linux-3.12.13/drivers/char/hw_random/Kconfig linux-raspberry-pi/driver
+ module will be called bcm2708-rng.
+
+ If unsure, say N.
-diff -Nur linux-3.12.13/drivers/char/hw_random/Makefile linux-raspberry-pi/drivers/char/hw_random/Makefile
---- linux-3.12.13/drivers/char/hw_random/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/char/hw_random/Makefile 2014-03-11 17:32:20.000000000 +0100
+diff -Nur linux-3.12.18/drivers/char/hw_random/Makefile linux-rpi/drivers/char/hw_random/Makefile
+--- linux-3.12.18/drivers/char/hw_random/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/char/hw_random/Makefile 2014-04-24 15:35:02.101542691 +0200
@@ -27,3 +27,4 @@
obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o
obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
+obj-$(CONFIG_HW_RANDOM_BCM2708) += bcm2708-rng.o
-diff -Nur linux-3.12.13/drivers/char/Kconfig linux-raspberry-pi/drivers/char/Kconfig
---- linux-3.12.13/drivers/char/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/char/Kconfig 2014-03-11 17:51:12.000000000 +0100
+diff -Nur linux-3.12.18/drivers/char/ipmi/ipmi_bt_sm.c linux-rpi/drivers/char/ipmi/ipmi_bt_sm.c
+--- linux-3.12.18/drivers/char/ipmi/ipmi_bt_sm.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/char/ipmi/ipmi_bt_sm.c 2014-04-24 15:35:02.105542736 +0200
+@@ -352,7 +352,7 @@
+
+ static inline int read_all_bytes(struct si_sm_data *bt)
+ {
+- unsigned int i;
++ unsigned char i;
+
+ /*
+ * length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode.
+diff -Nur linux-3.12.18/drivers/char/Kconfig linux-rpi/drivers/char/Kconfig
+--- linux-3.12.18/drivers/char/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/char/Kconfig 2014-04-24 16:04:34.335071226 +0200
@@ -574,6 +574,8 @@
source "drivers/s390/char/Kconfig"
@@ -10310,18 +9271,18 @@ diff -Nur linux-3.12.13/drivers/char/Kconfig linux-raspberry-pi/drivers/char/Kco
config MSM_SMD_PKT
bool "Enable device interface for some SMD packet ports"
default n
-diff -Nur linux-3.12.13/drivers/char/Makefile linux-raspberry-pi/drivers/char/Makefile
---- linux-3.12.13/drivers/char/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/char/Makefile 2014-03-11 17:51:12.000000000 +0100
+diff -Nur linux-3.12.18/drivers/char/Makefile linux-rpi/drivers/char/Makefile
+--- linux-3.12.18/drivers/char/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/char/Makefile 2014-04-24 16:04:34.335071226 +0200
@@ -62,3 +62,5 @@
js-rtc-y = rtc.o
obj-$(CONFIG_TILE_SROM) += tile-srom.o
+
+obj-$(CONFIG_BRCM_CHAR_DRIVERS) += broadcom/
-diff -Nur linux-3.12.13/drivers/cpufreq/bcm2835-cpufreq.c linux-raspberry-pi/drivers/cpufreq/bcm2835-cpufreq.c
---- linux-3.12.13/drivers/cpufreq/bcm2835-cpufreq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/cpufreq/bcm2835-cpufreq.c 2014-03-11 17:51:13.000000000 +0100
+diff -Nur linux-3.12.18/drivers/cpufreq/bcm2835-cpufreq.c linux-rpi/drivers/cpufreq/bcm2835-cpufreq.c
+--- linux-3.12.18/drivers/cpufreq/bcm2835-cpufreq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/cpufreq/bcm2835-cpufreq.c 2014-04-24 16:04:34.575073548 +0200
@@ -0,0 +1,239 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -10562,9 +9523,9 @@ diff -Nur linux-3.12.13/drivers/cpufreq/bcm2835-cpufreq.c linux-raspberry-pi/dri
+
+module_init(bcm2835_cpufreq_module_init);
+module_exit(bcm2835_cpufreq_module_exit);
-diff -Nur linux-3.12.13/drivers/cpufreq/Kconfig.arm linux-raspberry-pi/drivers/cpufreq/Kconfig.arm
---- linux-3.12.13/drivers/cpufreq/Kconfig.arm 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/cpufreq/Kconfig.arm 2014-03-11 17:51:13.000000000 +0100
+diff -Nur linux-3.12.18/drivers/cpufreq/Kconfig.arm linux-rpi/drivers/cpufreq/Kconfig.arm
+--- linux-3.12.18/drivers/cpufreq/Kconfig.arm 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/cpufreq/Kconfig.arm 2014-04-24 16:04:34.575073548 +0200
@@ -228,6 +228,14 @@
help
This adds the CPUFreq driver support for SPEAr SOCs.
@@ -10580,9 +9541,9 @@ diff -Nur linux-3.12.13/drivers/cpufreq/Kconfig.arm linux-raspberry-pi/drivers/c
config ARM_TEGRA_CPUFREQ
bool "TEGRA CPUFreq support"
depends on ARCH_TEGRA
-diff -Nur linux-3.12.13/drivers/cpufreq/Makefile linux-raspberry-pi/drivers/cpufreq/Makefile
---- linux-3.12.13/drivers/cpufreq/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/cpufreq/Makefile 2014-03-11 17:51:13.000000000 +0100
+diff -Nur linux-3.12.18/drivers/cpufreq/Makefile linux-rpi/drivers/cpufreq/Makefile
+--- linux-3.12.18/drivers/cpufreq/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/cpufreq/Makefile 2014-04-24 16:04:34.575073548 +0200
@@ -76,6 +76,7 @@
obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
@@ -10591,9 +9552,229 @@ diff -Nur linux-3.12.13/drivers/cpufreq/Makefile linux-raspberry-pi/drivers/cpuf
obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o
##################################################################################
-diff -Nur linux-3.12.13/drivers/dma/bcm2708-dmaengine.c linux-raspberry-pi/drivers/dma/bcm2708-dmaengine.c
---- linux-3.12.13/drivers/dma/bcm2708-dmaengine.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/dma/bcm2708-dmaengine.c 2014-03-11 17:51:13.000000000 +0100
+diff -Nur linux-3.12.18/drivers/cpufreq/powernow-k6.c linux-rpi/drivers/cpufreq/powernow-k6.c
+--- linux-3.12.18/drivers/cpufreq/powernow-k6.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/cpufreq/powernow-k6.c 2014-04-24 16:04:34.587073663 +0200
+@@ -26,108 +26,41 @@
+ static unsigned int busfreq; /* FSB, in 10 kHz */
+ static unsigned int max_multiplier;
+
+-static unsigned int param_busfreq = 0;
+-static unsigned int param_max_multiplier = 0;
+-
+-module_param_named(max_multiplier, param_max_multiplier, uint, S_IRUGO);
+-MODULE_PARM_DESC(max_multiplier, "Maximum multiplier (allowed values: 20 30 35 40 45 50 55 60)");
+-
+-module_param_named(bus_frequency, param_busfreq, uint, S_IRUGO);
+-MODULE_PARM_DESC(bus_frequency, "Bus frequency in kHz");
+
+ /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */
+ static struct cpufreq_frequency_table clock_ratio[] = {
+- {60, /* 110 -> 6.0x */ 0},
+- {55, /* 011 -> 5.5x */ 0},
+- {50, /* 001 -> 5.0x */ 0},
+ {45, /* 000 -> 4.5x */ 0},
++ {50, /* 001 -> 5.0x */ 0},
+ {40, /* 010 -> 4.0x */ 0},
+- {35, /* 111 -> 3.5x */ 0},
+- {30, /* 101 -> 3.0x */ 0},
++ {55, /* 011 -> 5.5x */ 0},
+ {20, /* 100 -> 2.0x */ 0},
++ {30, /* 101 -> 3.0x */ 0},
++ {60, /* 110 -> 6.0x */ 0},
++ {35, /* 111 -> 3.5x */ 0},
+ {0, CPUFREQ_TABLE_END}
+ };
+
+-static const u8 index_to_register[8] = { 6, 3, 1, 0, 2, 7, 5, 4 };
+-static const u8 register_to_index[8] = { 3, 2, 4, 1, 7, 6, 0, 5 };
+-
+-static const struct {
+- unsigned freq;
+- unsigned mult;
+-} usual_frequency_table[] = {
+- { 400000, 40 }, // 100 * 4
+- { 450000, 45 }, // 100 * 4.5
+- { 475000, 50 }, // 95 * 5
+- { 500000, 50 }, // 100 * 5
+- { 506250, 45 }, // 112.5 * 4.5
+- { 533500, 55 }, // 97 * 5.5
+- { 550000, 55 }, // 100 * 5.5
+- { 562500, 50 }, // 112.5 * 5
+- { 570000, 60 }, // 95 * 6
+- { 600000, 60 }, // 100 * 6
+- { 618750, 55 }, // 112.5 * 5.5
+- { 660000, 55 }, // 120 * 5.5
+- { 675000, 60 }, // 112.5 * 6
+- { 720000, 60 }, // 120 * 6
+-};
+-
+-#define FREQ_RANGE 3000
+
+ /**
+ * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier
+ *
+- * Returns the current setting of the frequency multiplier. Core clock
++ * Returns the current setting of the frequency multiplier. Core clock
+ * speed is frequency of the Front-Side Bus multiplied with this value.
+ */
+ static int powernow_k6_get_cpu_multiplier(void)
+ {
+- unsigned long invalue = 0;
++ u64 invalue = 0;
+ u32 msrval;
+
+- local_irq_disable();
+-
+ msrval = POWERNOW_IOPORT + 0x1;
+ wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
+ invalue = inl(POWERNOW_IOPORT + 0x8);
+ msrval = POWERNOW_IOPORT + 0x0;
+ wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
+
+- local_irq_enable();
+-
+- return clock_ratio[register_to_index[(invalue >> 5)&7]].driver_data;
++ return clock_ratio[(invalue >> 5)&7].driver_data;
+ }
+
+-static void powernow_k6_set_cpu_multiplier(unsigned int best_i)
+-{
+- unsigned long outvalue, invalue;
+- unsigned long msrval;
+- unsigned long cr0;
+-
+- /* we now need to transform best_i to the BVC format, see AMD#23446 */
+-
+- /*
+- * The processor doesn't respond to inquiry cycles while changing the
+- * frequency, so we must disable cache.
+- */
+- local_irq_disable();
+- cr0 = read_cr0();
+- write_cr0(cr0 | X86_CR0_CD);
+- wbinvd();
+-
+- outvalue = (1<<12) | (1<<10) | (1<<9) | (index_to_register[best_i]<<5);
+-
+- msrval = POWERNOW_IOPORT + 0x1;
+- wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
+- invalue = inl(POWERNOW_IOPORT + 0x8);
+- invalue = invalue & 0x1f;
+- outvalue = outvalue | invalue;
+- outl(outvalue, (POWERNOW_IOPORT + 0x8));
+- msrval = POWERNOW_IOPORT + 0x0;
+- wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
+-
+- write_cr0(cr0);
+- local_irq_enable();
+-}
+
+ /**
+ * powernow_k6_set_state - set the PowerNow! multiplier
+@@ -138,6 +71,8 @@
+ static void powernow_k6_set_state(struct cpufreq_policy *policy,
+ unsigned int best_i)
+ {
++ unsigned long outvalue = 0, invalue = 0;
++ unsigned long msrval;
+ struct cpufreq_freqs freqs;
+
+ if (clock_ratio[best_i].driver_data > max_multiplier) {
+@@ -150,7 +85,18 @@
+
+ cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+
+- powernow_k6_set_cpu_multiplier(best_i);
++ /* we now need to transform best_i to the BVC format, see AMD#23446 */
++
++ outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5);
++
++ msrval = POWERNOW_IOPORT + 0x1;
++ wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
++ invalue = inl(POWERNOW_IOPORT + 0x8);
++ invalue = invalue & 0xf;
++ outvalue = outvalue | invalue;
++ outl(outvalue , (POWERNOW_IOPORT + 0x8));
++ msrval = POWERNOW_IOPORT + 0x0;
++ wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
+
+ cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+
+@@ -195,57 +141,18 @@
+ return 0;
+ }
+
++
+ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
+ {
+ unsigned int i, f;
+ int result;
+- unsigned khz;
+
+ if (policy->cpu != 0)
+ return -ENODEV;
+
+- max_multiplier = 0;
+- khz = cpu_khz;
+- for (i = 0; i < ARRAY_SIZE(usual_frequency_table); i++) {
+- if (khz >= usual_frequency_table[i].freq - FREQ_RANGE &&
+- khz <= usual_frequency_table[i].freq + FREQ_RANGE) {
+- khz = usual_frequency_table[i].freq;
+- max_multiplier = usual_frequency_table[i].mult;
+- break;
+- }
+- }
+- if (param_max_multiplier) {
+- for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+- if (clock_ratio[i].driver_data == param_max_multiplier) {
+- max_multiplier = param_max_multiplier;
+- goto have_max_multiplier;
+- }
+- }
+- printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n");
+- return -EINVAL;
+- }
+-
+- if (!max_multiplier) {
+- printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz);
+- printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n");
+- return -EOPNOTSUPP;
+- }
+-
+-have_max_multiplier:
+- param_max_multiplier = max_multiplier;
+-
+- if (param_busfreq) {
+- if (param_busfreq >= 50000 && param_busfreq <= 150000) {
+- busfreq = param_busfreq / 10;
+- goto have_busfreq;
+- }
+- printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n");
+- return -EINVAL;
+- }
+-
+- busfreq = khz / max_multiplier;
+-have_busfreq:
+- param_busfreq = busfreq * 10;
++ /* get frequencies */
++ max_multiplier = powernow_k6_get_cpu_multiplier();
++ busfreq = cpu_khz / max_multiplier;
+
+ /* table init */
+ for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+@@ -257,7 +164,7 @@
+ }
+
+ /* cpuinfo and default policy values */
+- policy->cpuinfo.transition_latency = 500000;
++ policy->cpuinfo.transition_latency = 200000;
+ policy->cur = busfreq * max_multiplier;
+
+ result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
+diff -Nur linux-3.12.18/drivers/dma/bcm2708-dmaengine.c linux-rpi/drivers/dma/bcm2708-dmaengine.c
+--- linux-3.12.18/drivers/dma/bcm2708-dmaengine.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/dma/bcm2708-dmaengine.c 2014-04-24 16:04:34.615073934 +0200
@@ -0,0 +1,588 @@
+/*
+ * BCM2708 DMA engine support
@@ -11183,12 +10364,12 @@ diff -Nur linux-3.12.13/drivers/dma/bcm2708-dmaengine.c linux-raspberry-pi/drive
+MODULE_DESCRIPTION("BCM2708 DMA engine driver");
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.13/drivers/dma/Kconfig linux-raspberry-pi/drivers/dma/Kconfig
---- linux-3.12.13/drivers/dma/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/dma/Kconfig 2014-03-11 17:51:13.000000000 +0100
-@@ -296,6 +296,12 @@
- The Communications Port Programming Interface (CPPI) 4.1 DMA engine
- is currently used by the USB driver on AM335x platforms.
+diff -Nur linux-3.12.18/drivers/dma/Kconfig linux-rpi/drivers/dma/Kconfig
+--- linux-3.12.18/drivers/dma/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/dma/Kconfig 2014-04-24 16:04:34.615073934 +0200
+@@ -288,6 +288,12 @@
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+config DMA_BCM2708
+ tristate "BCM2708 DMA engine support"
@@ -11196,12 +10377,12 @@ diff -Nur linux-3.12.13/drivers/dma/Kconfig linux-raspberry-pi/drivers/dma/Kconf
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+
- config MMP_PDMA
- bool "MMP PDMA support"
- depends on (ARCH_MMP || ARCH_PXA)
-diff -Nur linux-3.12.13/drivers/dma/Makefile linux-raspberry-pi/drivers/dma/Makefile
---- linux-3.12.13/drivers/dma/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/dma/Makefile 2014-03-11 17:51:13.000000000 +0100
+ config TI_CPPI41
+ tristate "AM33xx CPPI41 DMA support"
+ depends on ARCH_OMAP
+diff -Nur linux-3.12.18/drivers/dma/Makefile linux-rpi/drivers/dma/Makefile
+--- linux-3.12.18/drivers/dma/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/dma/Makefile 2014-04-24 16:04:34.615073934 +0200
@@ -37,6 +37,7 @@
obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
@@ -11210,9 +10391,309 @@ diff -Nur linux-3.12.13/drivers/dma/Makefile linux-raspberry-pi/drivers/dma/Make
obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o
obj-$(CONFIG_TI_CPPI41) += cppi41.o
-diff -Nur linux-3.12.13/drivers/hwmon/bcm2835-hwmon.c linux-raspberry-pi/drivers/hwmon/bcm2835-hwmon.c
---- linux-3.12.13/drivers/hwmon/bcm2835-hwmon.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/hwmon/bcm2835-hwmon.c 2014-03-11 17:32:22.000000000 +0100
+diff -Nur linux-3.12.18/drivers/gpu/drm/cirrus/cirrus_fbdev.c linux-rpi/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+--- linux-3.12.18/drivers/gpu/drm/cirrus/cirrus_fbdev.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/cirrus/cirrus_fbdev.c 2014-04-24 16:04:34.791075636 +0200
+@@ -233,9 +233,6 @@
+ info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
+ info->apertures->ranges[0].size = cdev->mc.vram_size;
+
+- info->fix.smem_start = cdev->dev->mode_config.fb_base;
+- info->fix.smem_len = cdev->mc.vram_size;
+-
+ info->screen_base = sysram;
+ info->screen_size = size;
+
+diff -Nur linux-3.12.18/drivers/gpu/drm/cirrus/cirrus_mode.c linux-rpi/drivers/gpu/drm/cirrus/cirrus_mode.c
+--- linux-3.12.18/drivers/gpu/drm/cirrus/cirrus_mode.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/cirrus/cirrus_mode.c 2014-04-24 15:35:02.193543716 +0200
+@@ -494,12 +494,13 @@
+
+ int cirrus_vga_get_modes(struct drm_connector *connector)
+ {
+- int count;
+-
+ /* Just add a static list of modes */
+- count = drm_add_modes_noedid(connector, 1280, 1024);
+- drm_set_preferred_mode(connector, 1024, 768);
+- return count;
++ drm_add_modes_noedid(connector, 640, 480);
++ drm_add_modes_noedid(connector, 800, 600);
++ drm_add_modes_noedid(connector, 1024, 768);
++ drm_add_modes_noedid(connector, 1280, 1024);
++
++ return 4;
+ }
+
+ static int cirrus_vga_mode_valid(struct drm_connector *connector,
+diff -Nur linux-3.12.18/drivers/gpu/drm/drm_edid.c linux-rpi/drivers/gpu/drm/drm_edid.c
+--- linux-3.12.18/drivers/gpu/drm/drm_edid.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/drm_edid.c 2014-04-24 16:04:34.795075675 +0200
+@@ -3296,19 +3296,6 @@
+ }
+ EXPORT_SYMBOL(drm_add_modes_noedid);
+
+-void drm_set_preferred_mode(struct drm_connector *connector,
+- int hpref, int vpref)
+-{
+- struct drm_display_mode *mode;
+-
+- list_for_each_entry(mode, &connector->probed_modes, head) {
+- if (drm_mode_width(mode) == hpref &&
+- drm_mode_height(mode) == vpref)
+- mode->type |= DRM_MODE_TYPE_PREFERRED;
+- }
+-}
+-EXPORT_SYMBOL(drm_set_preferred_mode);
+-
+ /**
+ * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with
+ * data from a DRM display mode
+diff -Nur linux-3.12.18/drivers/gpu/drm/drm_fb_helper.c linux-rpi/drivers/gpu/drm/drm_fb_helper.c
+--- linux-3.12.18/drivers/gpu/drm/drm_fb_helper.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/drm_fb_helper.c 2014-04-24 16:04:34.795075675 +0200
+@@ -1163,7 +1163,6 @@
+ {
+ struct drm_cmdline_mode *cmdline_mode;
+ struct drm_display_mode *mode = NULL;
+- bool prefer_non_interlace;
+
+ cmdline_mode = &fb_helper_conn->cmdline_mode;
+ if (cmdline_mode->specified == false)
+@@ -1175,8 +1174,6 @@
+ if (cmdline_mode->rb || cmdline_mode->margins)
+ goto create_mode;
+
+- prefer_non_interlace = !cmdline_mode->interlace;
+- again:
+ list_for_each_entry(mode, &fb_helper_conn->connector->modes, head) {
+ /* check width/height */
+ if (mode->hdisplay != cmdline_mode->xres ||
+@@ -1191,18 +1188,10 @@
+ if (cmdline_mode->interlace) {
+ if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
+ continue;
+- } else if (prefer_non_interlace) {
+- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+- continue;
+ }
+ return mode;
+ }
+
+- if (prefer_non_interlace) {
+- prefer_non_interlace = false;
+- goto again;
+- }
+-
+ create_mode:
+ mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
+ cmdline_mode);
+diff -Nur linux-3.12.18/drivers/gpu/drm/i915/intel_display.c linux-rpi/drivers/gpu/drm/i915/intel_display.c
+--- linux-3.12.18/drivers/gpu/drm/i915/intel_display.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/i915/intel_display.c 2014-04-24 16:04:34.827075985 +0200
+@@ -10073,7 +10073,8 @@
+ /* ThinkPad T60 needs pipe A force quirk (bug #16494) */
+ { 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
+
+- /* 830 needs to leave pipe A & dpll A up */
++ /* 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 },
+
+ /* Lenovo U160 cannot use SSC on LVDS */
+diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/dce6_afmt.c linux-rpi/drivers/gpu/drm/radeon/dce6_afmt.c
+--- linux-3.12.18/drivers/gpu/drm/radeon/dce6_afmt.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/radeon/dce6_afmt.c 2014-04-24 16:04:34.959077261 +0200
+@@ -226,15 +226,13 @@
+ return !ASIC_IS_NODCE(rdev);
+ }
+
+-void dce6_audio_enable(struct radeon_device *rdev,
+- struct r600_audio_pin *pin,
+- bool enable)
++static void dce6_audio_enable(struct radeon_device *rdev,
++ struct r600_audio_pin *pin,
++ bool enable)
+ {
+- if (!pin)
+- return;
+-
+ WREG32_ENDPOINT(pin->offset, AZ_F0_CODEC_PIN_CONTROL_HOTPLUG_CONTROL,
+ enable ? AUDIO_ENABLED : 0);
++ DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
+ }
+
+ static const u32 pin_offsets[7] =
+@@ -271,8 +269,7 @@
+ rdev->audio.pin[i].connected = false;
+ rdev->audio.pin[i].offset = pin_offsets[i];
+ rdev->audio.pin[i].id = i;
+- /* disable audio. it will be set up later */
+- dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
++ dce6_audio_enable(rdev, &rdev->audio.pin[i], true);
+ }
+
+ return 0;
+diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/evergreen_hdmi.c linux-rpi/drivers/gpu/drm/radeon/evergreen_hdmi.c
+--- linux-3.12.18/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/radeon/evergreen_hdmi.c 2014-04-24 16:04:34.959077261 +0200
+@@ -257,15 +257,6 @@
+ return;
+ offset = dig->afmt->offset;
+
+- /* disable audio prior to setting up hw */
+- if (ASIC_IS_DCE6(rdev)) {
+- dig->afmt->pin = dce6_audio_get_pin(rdev);
+- dce6_audio_enable(rdev, dig->afmt->pin, false);
+- } else {
+- dig->afmt->pin = r600_audio_get_pin(rdev);
+- r600_audio_enable(rdev, dig->afmt->pin, false);
+- }
+-
+ evergreen_audio_set_dto(encoder, mode->clock);
+
+ WREG32(HDMI_VBI_PACKET_CONTROL + offset,
+@@ -367,16 +358,12 @@
+ WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF);
+ WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001);
+ WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001);
+-
+- /* enable audio after to setting up hw */
+- if (ASIC_IS_DCE6(rdev))
+- dce6_audio_enable(rdev, dig->afmt->pin, true);
+- else
+- r600_audio_enable(rdev, dig->afmt->pin, true);
+ }
+
+ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable)
+ {
++ struct drm_device *dev = encoder->dev;
++ struct radeon_device *rdev = dev->dev_private;
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+@@ -389,6 +376,15 @@
+ if (!enable && !dig->afmt->enabled)
+ return;
+
++ if (enable) {
++ if (ASIC_IS_DCE6(rdev))
++ dig->afmt->pin = dce6_audio_get_pin(rdev);
++ else
++ dig->afmt->pin = r600_audio_get_pin(rdev);
++ } else {
++ dig->afmt->pin = NULL;
++ }
++
+ dig->afmt->enabled = enable;
+
+ DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
+diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/r600_audio.c linux-rpi/drivers/gpu/drm/radeon/r600_audio.c
+--- linux-3.12.18/drivers/gpu/drm/radeon/r600_audio.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/radeon/r600_audio.c 2014-04-24 16:04:34.967077338 +0200
+@@ -142,15 +142,12 @@
+ }
+
+ /* enable the audio stream */
+-void r600_audio_enable(struct radeon_device *rdev,
+- struct r600_audio_pin *pin,
+- bool enable)
++static void r600_audio_enable(struct radeon_device *rdev,
++ struct r600_audio_pin *pin,
++ bool enable)
+ {
+ u32 value = 0;
+
+- if (!pin)
+- return;
+-
+ if (ASIC_IS_DCE4(rdev)) {
+ if (enable) {
+ value |= 0x81000000; /* Required to enable audio */
+@@ -161,6 +158,7 @@
+ WREG32_P(R600_AUDIO_ENABLE,
+ enable ? 0x81000000 : 0x0, ~0x81000000);
+ }
++ DRM_INFO("%s audio %d support\n", enable ? "Enabling" : "Disabling", pin->id);
+ }
+
+ /*
+@@ -180,8 +178,8 @@
+ rdev->audio.pin[0].status_bits = 0;
+ rdev->audio.pin[0].category_code = 0;
+ rdev->audio.pin[0].id = 0;
+- /* disable audio. it will be set up later */
+- r600_audio_enable(rdev, &rdev->audio.pin[0], false);
++
++ r600_audio_enable(rdev, &rdev->audio.pin[0], true);
+
+ return 0;
+ }
+diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/r600_hdmi.c linux-rpi/drivers/gpu/drm/radeon/r600_hdmi.c
+--- linux-3.12.18/drivers/gpu/drm/radeon/r600_hdmi.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/radeon/r600_hdmi.c 2014-04-24 16:04:34.967077338 +0200
+@@ -329,6 +329,9 @@
+ u8 *sadb;
+ int sad_count;
+
++ /* XXX: setting this register causes hangs on some asics */
++ return;
++
+ list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) {
+ if (connector->encoder == encoder)
+ radeon_connector = to_radeon_connector(connector);
+@@ -443,10 +446,6 @@
+ return;
+ offset = dig->afmt->offset;
+
+- /* disable audio prior to setting up hw */
+- dig->afmt->pin = r600_audio_get_pin(rdev);
+- r600_audio_enable(rdev, dig->afmt->pin, false);
+-
+ r600_audio_set_dto(encoder, mode->clock);
+
+ WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
+@@ -518,9 +517,6 @@
+ WREG32(HDMI0_RAMP_CONTROL3 + offset, 0x00000001);
+
+ r600_hdmi_audio_workaround(encoder);
+-
+- /* enable audio after to setting up hw */
+- r600_audio_enable(rdev, dig->afmt->pin, true);
+ }
+
+ /*
+@@ -641,6 +637,11 @@
+ if (!enable && !dig->afmt->enabled)
+ return;
+
++ if (enable)
++ dig->afmt->pin = r600_audio_get_pin(rdev);
++ else
++ dig->afmt->pin = NULL;
++
+ /* Older chipsets require setting HDMI and routing manually */
+ if (!ASIC_IS_DCE3(rdev)) {
+ if (enable)
+diff -Nur linux-3.12.18/drivers/gpu/drm/radeon/radeon.h linux-rpi/drivers/gpu/drm/radeon/radeon.h
+--- linux-3.12.18/drivers/gpu/drm/radeon/radeon.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/gpu/drm/radeon/radeon.h 2014-04-24 16:04:34.971077377 +0200
+@@ -2717,12 +2717,6 @@
+ void r600_audio_update_hdmi(struct work_struct *work);
+ struct r600_audio_pin *r600_audio_get_pin(struct radeon_device *rdev);
+ struct r600_audio_pin *dce6_audio_get_pin(struct radeon_device *rdev);
+-void r600_audio_enable(struct radeon_device *rdev,
+- struct r600_audio_pin *pin,
+- bool enable);
+-void dce6_audio_enable(struct radeon_device *rdev,
+- struct r600_audio_pin *pin,
+- bool enable);
+
+ /*
+ * R600 vram scratch functions
+diff -Nur linux-3.12.18/drivers/hwmon/bcm2835-hwmon.c linux-rpi/drivers/hwmon/bcm2835-hwmon.c
+--- linux-3.12.18/drivers/hwmon/bcm2835-hwmon.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/hwmon/bcm2835-hwmon.c 2014-04-24 15:35:02.349545454 +0200
@@ -0,0 +1,219 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -11433,9 +10914,9 @@ diff -Nur linux-3.12.13/drivers/hwmon/bcm2835-hwmon.c linux-raspberry-pi/drivers
+MODULE_DESCRIPTION("HW Monitor driver for bcm2835 chip");
+
+module_platform_driver(bcm2835_hwmon_driver);
-diff -Nur linux-3.12.13/drivers/hwmon/Kconfig linux-raspberry-pi/drivers/hwmon/Kconfig
---- linux-3.12.13/drivers/hwmon/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/hwmon/Kconfig 2014-03-11 17:51:14.000000000 +0100
+diff -Nur linux-3.12.18/drivers/hwmon/Kconfig linux-rpi/drivers/hwmon/Kconfig
+--- linux-3.12.18/drivers/hwmon/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/hwmon/Kconfig 2014-04-24 16:04:35.299080549 +0200
@@ -1553,6 +1553,16 @@
help
Support for the A/D converter on MC13783 and MC13892 PMIC.
@@ -11453,9 +10934,9 @@ diff -Nur linux-3.12.13/drivers/hwmon/Kconfig linux-raspberry-pi/drivers/hwmon/K
if ACPI
comment "ACPI drivers"
-diff -Nur linux-3.12.13/drivers/hwmon/Makefile linux-raspberry-pi/drivers/hwmon/Makefile
---- linux-3.12.13/drivers/hwmon/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/hwmon/Makefile 2014-03-11 17:51:14.000000000 +0100
+diff -Nur linux-3.12.18/drivers/hwmon/Makefile linux-rpi/drivers/hwmon/Makefile
+--- linux-3.12.18/drivers/hwmon/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/hwmon/Makefile 2014-04-24 16:04:35.299080549 +0200
@@ -142,6 +142,7 @@
obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o
obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o
@@ -11464,9 +10945,9 @@ diff -Nur linux-3.12.13/drivers/hwmon/Makefile linux-raspberry-pi/drivers/hwmon/
obj-$(CONFIG_PMBUS) += pmbus/
-diff -Nur linux-3.12.13/drivers/i2c/busses/i2c-bcm2708.c linux-raspberry-pi/drivers/i2c/busses/i2c-bcm2708.c
---- linux-3.12.13/drivers/i2c/busses/i2c-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/i2c/busses/i2c-bcm2708.c 2014-03-11 17:51:14.000000000 +0100
+diff -Nur linux-3.12.18/drivers/i2c/busses/i2c-bcm2708.c linux-rpi/drivers/i2c/busses/i2c-bcm2708.c
+--- linux-3.12.18/drivers/i2c/busses/i2c-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/i2c/busses/i2c-bcm2708.c 2014-04-24 16:04:35.311080666 +0200
@@ -0,0 +1,408 @@
+/*
+ * Driver for Broadcom BCM2708 BSC Controllers
@@ -11876,10 +11357,10 @@ diff -Nur linux-3.12.13/drivers/i2c/busses/i2c-bcm2708.c linux-raspberry-pi/driv
+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
-diff -Nur linux-3.12.13/drivers/i2c/busses/Kconfig linux-raspberry-pi/drivers/i2c/busses/Kconfig
---- linux-3.12.13/drivers/i2c/busses/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/i2c/busses/Kconfig 2014-03-11 17:51:14.000000000 +0100
-@@ -346,6 +346,25 @@
+diff -Nur linux-3.12.18/drivers/i2c/busses/Kconfig linux-rpi/drivers/i2c/busses/Kconfig
+--- linux-3.12.18/drivers/i2c/busses/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/i2c/busses/Kconfig 2014-04-24 16:04:35.311080666 +0200
+@@ -347,6 +347,25 @@
This support is also available as a module. If so, the module
will be called i2c-bcm2835.
@@ -11892,22 +11373,22 @@ diff -Nur linux-3.12.13/drivers/i2c/busses/Kconfig linux-raspberry-pi/drivers/i2
+ with I2C/TWI/SMBus.
+
+config I2C_BCM2708_BAUDRATE
-+ prompt "BCM2708 I2C baudrate"
++ prompt "BCM2708 I2C baudrate"
+ depends on I2C_BCM2708
-+ int
-+ default 100000
-+ help
-+ Set the I2C baudrate. This will alter the default value. A
-+ different baudrate can be set by using a module parameter as well. If
-+ no parameter is provided when loading, this is the value that will be
-+ used.
++ int
++ default 100000
++ help
++ Set the I2C baudrate. This will alter the default value. A
++ different baudrate can be set by using a module parameter as well. If
++ no parameter is provided when loading, this is the value that will be
++ used.
+
config I2C_BLACKFIN_TWI
tristate "Blackfin TWI I2C support"
depends on BLACKFIN
-diff -Nur linux-3.12.13/drivers/i2c/busses/Makefile linux-raspberry-pi/drivers/i2c/busses/Makefile
---- linux-3.12.13/drivers/i2c/busses/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/i2c/busses/Makefile 2014-03-11 17:51:14.000000000 +0100
+diff -Nur linux-3.12.18/drivers/i2c/busses/Makefile linux-rpi/drivers/i2c/busses/Makefile
+--- linux-3.12.18/drivers/i2c/busses/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/i2c/busses/Makefile 2014-04-24 16:04:35.311080666 +0200
@@ -32,6 +32,7 @@
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
@@ -11916,21 +11397,79 @@ diff -Nur linux-3.12.13/drivers/i2c/busses/Makefile linux-raspberry-pi/drivers/i
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o
obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
-diff -Nur linux-3.12.13/drivers/media/dvb-core/dvb-usb-ids.h linux-raspberry-pi/drivers/media/dvb-core/dvb-usb-ids.h
---- linux-3.12.13/drivers/media/dvb-core/dvb-usb-ids.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/dvb-core/dvb-usb-ids.h 2014-03-11 17:51:15.000000000 +0100
-@@ -366,6 +366,7 @@
- #define USB_PID_TERRATEC_DVBS2CI_V2 0x10ac
- #define USB_PID_TECHNISAT_USB2_HDCI_V1 0x0001
- #define USB_PID_TECHNISAT_USB2_HDCI_V2 0x0002
-+#define USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI 0x0003
- #define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2 0x0004
- #define USB_PID_TECHNISAT_USB2_DVB_S2 0x0500
- #define USB_PID_CPYTO_REDI_PC50A 0xa803
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-raspberry-pi/drivers/media/platform/bcm2835/bcm2835-camera.c
---- linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/bcm2835-camera.c 2014-03-11 17:51:15.000000000 +0100
-@@ -0,0 +1,1622 @@
+diff -Nur linux-3.12.18/drivers/isdn/isdnloop/isdnloop.c linux-rpi/drivers/isdn/isdnloop/isdnloop.c
+--- linux-3.12.18/drivers/isdn/isdnloop/isdnloop.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/isdn/isdnloop/isdnloop.c 2014-04-24 16:04:36.039087706 +0200
+@@ -518,9 +518,9 @@
+ static void
+ isdnloop_fake_err(isdnloop_card *card)
+ {
+- char buf[64];
++ char buf[60];
+
+- snprintf(buf, sizeof(buf), "E%s", card->omsg);
++ sprintf(buf, "E%s", card->omsg);
+ isdnloop_fake(card, buf, -1);
+ isdnloop_fake(card, "NAK", -1);
+ }
+@@ -903,8 +903,6 @@
+ case 7:
+ /* 0x;EAZ */
+ p += 3;
+- if (strlen(p) >= sizeof(card->eazlist[0]))
+- break;
+ strcpy(card->eazlist[ch - 1], p);
+ break;
+ case 8:
+@@ -1072,12 +1070,6 @@
+ return -EBUSY;
+ if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef)))
+ return -EFAULT;
+-
+- for (i = 0; i < 3; i++) {
+- if (!memchr(sdef.num[i], 0, sizeof(sdef.num[i])))
+- return -EINVAL;
+- }
+-
+ spin_lock_irqsave(&card->isdnloop_lock, flags);
+ switch (sdef.ptype) {
+ case ISDN_PTYPE_EURO:
+@@ -1135,7 +1127,7 @@
+ {
+ ulong a;
+ int i;
+- char cbuf[80];
++ char cbuf[60];
+ isdn_ctrl cmd;
+ isdnloop_cdef cdef;
+
+@@ -1200,6 +1192,7 @@
+ break;
+ if ((c->arg & 255) < ISDNLOOP_BCH) {
+ char *p;
++ char dial[50];
+ char dcode[4];
+
+ a = c->arg;
+@@ -1211,10 +1204,10 @@
+ } else
+ /* Normal Dial */
+ strcpy(dcode, "CAL");
+- snprintf(cbuf, sizeof(cbuf),
+- "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
+- dcode, p, c->parm.setup.si1,
+- c->parm.setup.si2, c->parm.setup.eazmsn);
++ strcpy(dial, p);
++ sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
++ dcode, dial, c->parm.setup.si1,
++ c->parm.setup.si2, c->parm.setup.eazmsn);
+ i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
+ }
+ break;
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/bcm2835-camera.c linux-rpi/drivers/media/platform/bcm2835/bcm2835-camera.c
+--- linux-3.12.18/drivers/media/platform/bcm2835/bcm2835-camera.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/bcm2835-camera.c 2014-04-24 16:04:36.447091651 +0200
+@@ -0,0 +1,1719 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -11969,7 +11508,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+
+#define BM2835_MMAL_VERSION "0.0.2"
+#define BM2835_MMAL_MODULE_NAME "bcm2835-v4l2"
-+
++#define MIN_WIDTH 16
++#define MIN_HEIGHT 16
+#define MAX_WIDTH 2592
+#define MAX_HEIGHT 1944
+#define MIN_BUFFER_SIZE (80*1024)
@@ -11989,7 +11529,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+static struct bm2835_mmal_dev *gdev; /* global device data */
+
+#define FPS_MIN 1
-+#define FPS_MAX 30
++#define FPS_MAX 90
+
+/* timeperframe: min/max and default */
+static const struct v4l2_fract
@@ -12002,6 +11542,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ {
+ .name = "4:2:0, packed YUV",
+ .fourcc = V4L2_PIX_FMT_YUV420,
++ .flags = 0,
+ .mmal = MMAL_ENCODING_I420,
+ .depth = 12,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
@@ -12009,13 +11550,15 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ {
+ .name = "4:2:2, packed, YUYV",
+ .fourcc = V4L2_PIX_FMT_YUYV,
++ .flags = 0,
+ .mmal = MMAL_ENCODING_YUYV,
+ .depth = 16,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
+ },
+ {
-+ .name = "RGB24 (BE)",
-+ .fourcc = V4L2_PIX_FMT_BGR24,
++ .name = "RGB24 (LE)",
++ .fourcc = V4L2_PIX_FMT_RGB24,
++ .flags = 0,
+ .mmal = MMAL_ENCODING_BGR24,
+ .depth = 24,
+ .mmal_component = MMAL_COMPONENT_CAMERA,
@@ -12023,6 +11566,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ {
+ .name = "JPEG",
+ .fourcc = V4L2_PIX_FMT_JPEG,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal = MMAL_ENCODING_JPEG,
+ .depth = 8,
+ .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
@@ -12030,10 +11574,75 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ {
+ .name = "H264",
+ .fourcc = V4L2_PIX_FMT_H264,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
+ .mmal = MMAL_ENCODING_H264,
+ .depth = 8,
+ .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
-+ }
++ },
++ {
++ .name = "MJPEG",
++ .fourcc = V4L2_PIX_FMT_MJPEG,
++ .flags = V4L2_FMT_FLAG_COMPRESSED,
++ .mmal = MMAL_ENCODING_MJPEG,
++ .depth = 8,
++ .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
++ },
++ {
++ .name = "4:2:2, packed, YVYU",
++ .fourcc = V4L2_PIX_FMT_YVYU,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_YVYU,
++ .depth = 16,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:2, packed, VYUY",
++ .fourcc = V4L2_PIX_FMT_VYUY,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_VYUY,
++ .depth = 16,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:2, packed, UYVY",
++ .fourcc = V4L2_PIX_FMT_UYVY,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_UYVY,
++ .depth = 16,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:0, packed, NV12",
++ .fourcc = V4L2_PIX_FMT_NV12,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_NV12,
++ .depth = 12,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "RGB24 (BE)",
++ .fourcc = V4L2_PIX_FMT_BGR24,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_RGB24,
++ .depth = 24,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:0, packed YVU",
++ .fourcc = V4L2_PIX_FMT_YVU420,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_YV12,
++ .depth = 12,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
++ {
++ .name = "4:2:0, packed, NV21",
++ .fourcc = V4L2_PIX_FMT_NV21,
++ .flags = 0,
++ .mmal = MMAL_ENCODING_NV21,
++ .depth = 12,
++ .mmal_component = MMAL_COMPONENT_CAMERA,
++ },
+};
+
+static struct mmal_fmt *get_format(struct v4l2_format *f)
@@ -12481,6 +12090,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+
+ strlcpy(f->description, fmt->name, sizeof(f->description));
+ f->pixelformat = fmt->fourcc;
++ f->flags = fmt->flags;
+
+ return 0;
+}
@@ -12609,7 +12219,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ a->fmt.bytesperline = (preview_port->es.video.width * 3)>>1;
+ a->fmt.sizeimage = (preview_port->es.video.width *
+ preview_port->es.video.height * 3)>>1;
-+ a->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
++ a->fmt.colorspace = V4L2_COLORSPACE_JPEG;
+
+ return 0;
+}
@@ -12676,6 +12286,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+
+ strlcpy(f->description, fmt->name, sizeof(f->description));
+ f->pixelformat = fmt->fourcc;
++ f->flags = fmt->flags;
++
+ return 0;
+}
+
@@ -12820,10 +12432,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ camera_port->es.video.crop.y = 0;
+ camera_port->es.video.crop.width = f->fmt.pix.width;
+ camera_port->es.video.crop.height = f->fmt.pix.height;
-+ camera_port->es.video.frame_rate.num =
-+ dev->capture.timeperframe.denominator;
-+ camera_port->es.video.frame_rate.den =
-+ dev->capture.timeperframe.numerator;
++ camera_port->es.video.frame_rate.num = 0;
++ camera_port->es.video.frame_rate.den = 1;
+
+ ret = vchiq_mmal_port_set_format(dev->instance, camera_port);
+
@@ -12857,8 +12467,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ preview_port->es.video.crop.y = 0;
+ preview_port->es.video.crop.width = f->fmt.pix.width;
+ preview_port->es.video.crop.height = f->fmt.pix.height;
-+ preview_port->es.video.frame_rate.num = 30;
-+ preview_port->es.video.frame_rate.den = 1;
++ preview_port->es.video.frame_rate.num =
++ dev->capture.timeperframe.denominator;
++ preview_port->es.video.frame_rate.den =
++ dev->capture.timeperframe.numerator;
+ ret = vchiq_mmal_port_set_format(dev->instance, preview_port);
+ if (overlay_enabled) {
+ ret = vchiq_mmal_port_connect_tunnel(
@@ -13033,22 +12645,56 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ }
+
+ ret = mmal_setup_components(dev, f);
-+ if (ret != 0)
++ if (ret != 0) {
+ v4l2_err(&dev->v4l2_dev,
+ "%s: failed to setup mmal components: %d\n",
+ __func__, ret);
++ ret = -EINVAL;
++ }
+
+ return ret;
+}
+
++int vidioc_enum_framesizes(struct file *file, void *fh,
++ struct v4l2_frmsizeenum *fsize)
++{
++ static const struct v4l2_frmsize_stepwise sizes = {
++ MIN_WIDTH, MAX_WIDTH, 2,
++ MIN_HEIGHT, MAX_HEIGHT, 2
++ };
++ int i;
++
++ if (fsize->index)
++ return -EINVAL;
++ for (i = 0; i < ARRAY_SIZE(formats); i++)
++ if (formats[i].fourcc == fsize->pixel_format)
++ break;
++ if (i == ARRAY_SIZE(formats))
++ return -EINVAL;
++ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
++ fsize->stepwise = sizes;
++ return 0;
++}
++
+/* timeperframe is arbitrary and continous */
+static int vidioc_enum_frameintervals(struct file *file, void *priv,
+ struct v4l2_frmivalenum *fival)
+{
++ int i;
++
+ if (fival->index)
+ return -EINVAL;
+
-+ /* regarding width & height - we support any */
++ for (i = 0; i < ARRAY_SIZE(formats); i++)
++ if (formats[i].fourcc == fival->pixel_format)
++ break;
++ if (i == ARRAY_SIZE(formats))
++ return -EINVAL;
++
++ /* regarding width & height - we support any within range */
++ if (fival->width < MIN_WIDTH || fival->width > MAX_WIDTH ||
++ fival->height < MIN_HEIGHT || fival->height > MAX_HEIGHT)
++ return -EINVAL;
+
+ fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
+
@@ -13084,7 +12730,6 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ struct bm2835_mmal_dev *dev = video_drvdata(file);
+ struct v4l2_fract tpf;
+ struct mmal_parameter_rational fps_param;
-+ int ret;
+
+ if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ return -EINVAL;
@@ -13100,27 +12745,11 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ parm->parm.capture.timeperframe = tpf;
+ parm->parm.capture.readbuffers = 1;
+
-+ fps_param.num = dev->capture.timeperframe.denominator;
-+ fps_param.den = dev->capture.timeperframe.numerator;
-+ ret = vchiq_mmal_port_parameter_set(dev->instance,
-+ &dev->component[MMAL_COMPONENT_CAMERA]->
-+ output[MMAL_CAMERA_PORT_PREVIEW],
-+ MMAL_PARAMETER_VIDEO_FRAME_RATE,
-+ &fps_param, sizeof(fps_param));
-+ ret += vchiq_mmal_port_parameter_set(dev->instance,
-+ &dev->component[MMAL_COMPONENT_CAMERA]->
-+ output[MMAL_CAMERA_PORT_VIDEO],
-+ MMAL_PARAMETER_VIDEO_FRAME_RATE,
-+ &fps_param, sizeof(fps_param));
-+ ret += vchiq_mmal_port_parameter_set(dev->instance,
-+ &dev->component[MMAL_COMPONENT_CAMERA]->
-+ output[MMAL_CAMERA_PORT_CAPTURE],
-+ MMAL_PARAMETER_VIDEO_FRAME_RATE,
-+ &fps_param, sizeof(fps_param));
-+ if (ret)
-+ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+ "Failed to set fps ret %d\n",
-+ ret);
++ fps_param.num = 0; /* Select variable fps, and then use
++ * FPS_RANGE to select the actual limits.
++ */
++ fps_param.den = 1;
++ set_framerate_params(dev);
+
+ return 0;
+}
@@ -13153,6 +12782,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
++ .vidioc_enum_framesizes = vidioc_enum_framesizes,
+ .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
+ .vidioc_g_parm = vidioc_g_parm,
+ .vidioc_s_parm = vidioc_s_parm,
@@ -13248,10 +12878,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ format->es->video.crop.y = 0;
+ format->es->video.crop.width = 1024;
+ format->es->video.crop.height = 768;
-+ format->es->video.frame_rate.num =
-+ dev->capture.timeperframe.denominator;
-+ format->es->video.frame_rate.den =
-+ dev->capture.timeperframe.numerator;
++ format->es->video.frame_rate.num = 0; /* Rely on fps_range */
++ format->es->video.frame_rate.den = 1;
+
+ format =
+ &dev->component[MMAL_COMPONENT_CAMERA]->
@@ -13266,10 +12894,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ format->es->video.crop.y = 0;
+ format->es->video.crop.width = 1024;
+ format->es->video.crop.height = 768;
-+ format->es->video.frame_rate.num =
-+ dev->capture.timeperframe.denominator;
-+ format->es->video.frame_rate.den =
-+ dev->capture.timeperframe.numerator;
++ format->es->video.frame_rate.num = 0; /* Rely on fps_range */
++ format->es->video.frame_rate.den = 1;
+
+ format =
+ &dev->component[MMAL_COMPONENT_CAMERA]->
@@ -13283,7 +12909,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ format->es->video.crop.y = 0;
+ format->es->video.crop.width = 2592;
+ format->es->video.crop.height = 1944;
-+ format->es->video.frame_rate.num = 30;
++ format->es->video.frame_rate.num = 0; /* Rely on fps_range */
+ format->es->video.frame_rate.den = 1;
+
+ dev->capture.width = format->es->video.width;
@@ -13291,6 +12917,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ dev->capture.fmt = &formats[0];
+ dev->capture.encode_component = NULL;
+ dev->capture.timeperframe = tpf_default;
++ dev->capture.enc_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
++ dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
+
+ /* get the preview component ready */
+ ret = vchiq_mmal_component_init(
@@ -13337,6 +12965,14 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+ }
+
+ {
++ struct vchiq_mmal_port *encoder_port =
++ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
++ encoder_port->format.encoding = MMAL_ENCODING_H264;
++ ret = vchiq_mmal_port_set_format(dev->instance,
++ encoder_port);
++ }
++
++ {
+ unsigned int enable = 1;
+ vchiq_mmal_port_parameter_set(
+ dev->instance,
@@ -13553,10 +13189,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.c linux-ra
+
+module_init(bm2835_mmal_init);
+module_exit(bm2835_mmal_exit);
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-raspberry-pi/drivers/media/platform/bcm2835/bcm2835-camera.h
---- linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/bcm2835-camera.h 2014-03-11 17:51:15.000000000 +0100
-@@ -0,0 +1,113 @@
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/bcm2835-camera.h linux-rpi/drivers/media/platform/bcm2835/bcm2835-camera.h
+--- linux-3.12.18/drivers/media/platform/bcm2835/bcm2835-camera.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/bcm2835-camera.h 2014-04-24 15:35:02.713549510 +0200
+@@ -0,0 +1,125 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -13574,7 +13210,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra
+ * core driver device
+ */
+
-+#define V4L2_CTRL_COUNT 21 /* number of v4l controls */
++#define V4L2_CTRL_COUNT 27 /* number of v4l controls */
+
+enum {
+ MMAL_COMPONENT_CAMERA = 0,
@@ -13604,11 +13240,19 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra
+ /* controls */
+ struct v4l2_ctrl_handler ctrl_handler;
+ struct v4l2_ctrl *ctrls[V4L2_CTRL_COUNT];
++ enum v4l2_scene_mode scene_mode;
+ struct mmal_colourfx colourfx;
+ int hflip;
+ int vflip;
-+ enum mmal_parameter_exposuremode exposure_mode;
++ int red_gain;
++ int blue_gain;
++ enum mmal_parameter_exposuremode exposure_mode_user;
++ enum v4l2_exposure_auto_type exposure_mode_v4l2_user;
++ /* active exposure mode may differ if selected via a scene mode */
++ enum mmal_parameter_exposuremode exposure_mode_active;
++ enum mmal_parameter_exposuremeteringmode metering_mode;
+ unsigned int manual_shutter_speed;
++ bool exp_auto_priority;
+
+ /* allocated mmal instance and components */
+ struct vchiq_mmal_instance *instance;
@@ -13622,12 +13266,16 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra
+ unsigned int height; /* height */
+ unsigned int stride; /* stride */
+ struct mmal_fmt *fmt;
-+ struct v4l2_fract timeperframe;
++ struct v4l2_fract timeperframe;
+
+ /* H264 encode bitrate */
+ int encode_bitrate;
+ /* H264 bitrate mode. CBR/VBR */
+ int encode_bitrate_mode;
++ /* H264 profile */
++ enum v4l2_mpeg_video_h264_profile enc_profile;
++ /* H264 level */
++ enum v4l2_mpeg_video_h264_level enc_level;
+ /* JPEG Q-factor */
+ int q_factor;
+
@@ -13657,7 +13305,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra
+ struct v4l2_ctrl_handler *hdl);
+
+int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev);
-+
++int set_framerate_params(struct bm2835_mmal_dev *dev);
+
+/* Debug helpers */
+
@@ -13670,10 +13318,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/bcm2835-camera.h linux-ra
+ (pix_fmt)->pixelformat, (pix_fmt)->bytesperline, \
+ (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \
+}
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberry-pi/drivers/media/platform/bcm2835/controls.c
---- linux-3.12.13/drivers/media/platform/bcm2835/controls.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/controls.c 2014-03-11 17:51:15.000000000 +0100
-@@ -0,0 +1,902 @@
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/controls.c linux-rpi/drivers/media/platform/bcm2835/controls.c
+--- linux-3.12.18/drivers/media/platform/bcm2835/controls.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/controls.c 2014-04-24 15:35:02.713549510 +0200
+@@ -0,0 +1,1315 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -13745,7 +13393,6 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+};
+
-+
+enum bm2835_mmal_ctrl_type {
+ MMAL_CONTROL_TYPE_STD,
+ MMAL_CONTROL_TYPE_STD_MENU,
@@ -13822,6 +13469,25 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ 1, 1, 0, 0, 0, {0, 0, 0, 0, 0} }
+};
+
++struct v4l2_mmal_scene_config {
++ enum v4l2_scene_mode v4l2_scene;
++ enum mmal_parameter_exposuremode exposure_mode;
++ enum mmal_parameter_exposuremeteringmode metering_mode;
++};
++
++static const struct v4l2_mmal_scene_config scene_configs[] = {
++ /* V4L2_SCENE_MODE_NONE automatically added */
++ {
++ V4L2_SCENE_MODE_NIGHT,
++ MMAL_PARAM_EXPOSUREMODE_NIGHT,
++ MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE
++ },
++ {
++ V4L2_SCENE_MODE_SPORTS,
++ MMAL_PARAM_EXPOSUREMODE_SPORTS,
++ MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE
++ },
++};
+
+/* control handlers*/
+
@@ -13973,7 +13639,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ struct v4l2_ctrl *ctrl,
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+{
-+ enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode;
++ enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode_user;
+ u32 shutter_speed = 0;
+ struct vchiq_mmal_port *control;
+ int ret = 0;
@@ -13994,28 +13660,34 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ case V4L2_EXPOSURE_MANUAL:
+ exp_mode = MMAL_PARAM_EXPOSUREMODE_OFF;
+ break;
-+
-+ case V4L2_EXPOSURE_SHUTTER_PRIORITY:
-+ exp_mode = MMAL_PARAM_EXPOSUREMODE_SPORTS;
-+ break;
-+
-+ case V4L2_EXPOSURE_APERTURE_PRIORITY:
-+ exp_mode = MMAL_PARAM_EXPOSUREMODE_NIGHT;
-+ break;
-+
+ }
-+ dev->exposure_mode = exp_mode;
-+ }
-+
-+ if (dev->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF)
-+ shutter_speed = dev->manual_shutter_speed;
++ dev->exposure_mode_user = exp_mode;
++ dev->exposure_mode_v4l2_user = ctrl->val;
++ } else if (mmal_ctrl->id == V4L2_CID_EXPOSURE_AUTO_PRIORITY) {
++ dev->exp_auto_priority = ctrl->val;
++ }
++
++ if (dev->scene_mode == V4L2_SCENE_MODE_NONE) {
++ if (exp_mode == MMAL_PARAM_EXPOSUREMODE_OFF)
++ shutter_speed = dev->manual_shutter_speed;
++
++ ret = vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_SHUTTER_SPEED,
++ &shutter_speed,
++ sizeof(shutter_speed));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ &exp_mode,
++ sizeof(u32));
++ dev->exposure_mode_active = exp_mode;
++ }
++ /* exposure_dynamic_framerate (V4L2_CID_EXPOSURE_AUTO_PRIORITY) should
++ * always apply irrespective of scene mode.
++ */
++ ret += set_framerate_params(dev);
+
-+ ret = vchiq_mmal_port_parameter_set(dev->instance, control,
-+ MMAL_PARAMETER_SHUTTER_SPEED,
-+ &shutter_speed, sizeof(shutter_speed));
-+ ret += vchiq_mmal_port_parameter_set(dev->instance, control,
-+ MMAL_PARAMETER_EXPOSURE_MODE,
-+ &exp_mode, sizeof(u32));
+ return ret;
+}
+
@@ -14023,35 +13695,38 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ struct v4l2_ctrl *ctrl,
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
+{
-+ u32 u32_value;
-+ struct vchiq_mmal_port *control;
-+
-+ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
-+
+ switch (ctrl->val) {
+ case V4L2_EXPOSURE_METERING_AVERAGE:
-+ u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
+ break;
+
+ case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
-+ u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
+ break;
+
+ case V4L2_EXPOSURE_METERING_SPOT:
-+ u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
+ break;
+
+ /* todo matrix weighting not added to Linux API till 3.9
+ case V4L2_EXPOSURE_METERING_MATRIX:
-+ u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
++ dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
+ break;
+ */
+
+ }
+
-+ return vchiq_mmal_port_parameter_set(dev->instance, control,
++ if (dev->scene_mode == V4L2_SCENE_MODE_NONE) {
++ struct vchiq_mmal_port *control;
++ u32 u32_value = dev->metering_mode;
++
++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++
++ return vchiq_mmal_port_parameter_set(dev->instance, control,
+ mmal_ctrl->mmal_id,
+ &u32_value, sizeof(u32_value));
++ } else
++ return 0;
+}
+
+static int ctrl_set_flicker_avoidance(struct bm2835_mmal_dev *dev,
@@ -14140,6 +13815,29 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ &u32_value, sizeof(u32_value));
+}
+
++static int ctrl_set_awb_gains(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
++ struct vchiq_mmal_port *control;
++ struct mmal_parameter_awbgains gains;
++
++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++
++ if (ctrl->id == V4L2_CID_RED_BALANCE)
++ dev->red_gain = ctrl->val;
++ else if (ctrl->id == V4L2_CID_BLUE_BALANCE)
++ dev->blue_gain = ctrl->val;
++
++ gains.r_gain.num = dev->red_gain;
++ gains.b_gain.num = dev->blue_gain;
++ gains.r_gain.den = gains.b_gain.den = 1000;
++
++ return vchiq_mmal_port_parameter_set(dev->instance, control,
++ mmal_ctrl->mmal_id,
++ &gains, sizeof(gains));
++}
++
+static int ctrl_set_image_effect(struct bm2835_mmal_dev *dev,
+ struct v4l2_ctrl *ctrl,
+ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
@@ -14216,8 +13914,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ &dev->colourfx, sizeof(dev->colourfx));
+
+ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
-+ "After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n",
-+ mmal_ctrl, ctrl->id, ctrl->val, ret,
++ "%s: After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n",
++ __func__, mmal_ctrl, ctrl->id, ctrl->val, ret,
+ (ret == 0 ? 0 : -EINVAL));
+ return (ret == 0 ? 0 : EINVAL);
+}
@@ -14299,6 +13997,224 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ &u32_value, sizeof(u32_value));
+}
+
++static int ctrl_set_video_encode_profile_level(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
++ struct mmal_parameter_video_profile param;
++ int ret = 0;
++
++ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
++ switch (ctrl->val) {
++ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
++ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
++ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
++ dev->capture.enc_profile = ctrl->val;
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++ } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
++ switch (ctrl->val) {
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
++ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
++ dev->capture.enc_level = ctrl->val;
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++ }
++
++ if (!ret) {
++ switch (dev->capture.enc_profile) {
++ case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
++ param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE;
++ break;
++ case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
++ param.profile =
++ MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE;
++ break;
++ case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
++ param.profile = MMAL_VIDEO_PROFILE_H264_MAIN;
++ break;
++ case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
++ param.profile = MMAL_VIDEO_PROFILE_H264_HIGH;
++ break;
++ default:
++ /* Should never get here */
++ break;
++ }
++
++ switch (dev->capture.enc_level) {
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
++ param.level = MMAL_VIDEO_LEVEL_H264_1;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
++ param.level = MMAL_VIDEO_LEVEL_H264_1b;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
++ param.level = MMAL_VIDEO_LEVEL_H264_11;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
++ param.level = MMAL_VIDEO_LEVEL_H264_12;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
++ param.level = MMAL_VIDEO_LEVEL_H264_13;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
++ param.level = MMAL_VIDEO_LEVEL_H264_2;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
++ param.level = MMAL_VIDEO_LEVEL_H264_21;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
++ param.level = MMAL_VIDEO_LEVEL_H264_22;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
++ param.level = MMAL_VIDEO_LEVEL_H264_3;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
++ param.level = MMAL_VIDEO_LEVEL_H264_31;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
++ param.level = MMAL_VIDEO_LEVEL_H264_32;
++ break;
++ case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
++ param.level = MMAL_VIDEO_LEVEL_H264_4;
++ break;
++ default:
++ /* Should never get here */
++ break;
++ }
++
++ ret = vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0],
++ mmal_ctrl->mmal_id,
++ &param, sizeof(param));
++ }
++ return ret;
++}
++
++static int ctrl_set_scene_mode(struct bm2835_mmal_dev *dev,
++ struct v4l2_ctrl *ctrl,
++ const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
++{
++ int ret = 0;
++ int shutter_speed;
++ struct vchiq_mmal_port *control;
++
++ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "scene mode selected %d, was %d\n", ctrl->val,
++ dev->scene_mode);
++ control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
++
++ if (ctrl->val == dev->scene_mode)
++ return 0;
++
++ if (ctrl->val == V4L2_SCENE_MODE_NONE) {
++ /* Restore all user selections */
++ dev->scene_mode = V4L2_SCENE_MODE_NONE;
++
++ if (dev->exposure_mode_user == MMAL_PARAM_EXPOSUREMODE_OFF)
++ shutter_speed = dev->manual_shutter_speed;
++ else
++ shutter_speed = 0;
++
++ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n",
++ __func__, shutter_speed, dev->exposure_mode_user,
++ dev->metering_mode);
++ ret = vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_SHUTTER_SPEED,
++ &shutter_speed,
++ sizeof(shutter_speed));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ &dev->exposure_mode_user,
++ sizeof(u32));
++ dev->exposure_mode_active = dev->exposure_mode_user;
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_EXP_METERING_MODE,
++ &dev->metering_mode,
++ sizeof(u32));
++ ret += set_framerate_params(dev);
++ } else {
++ /* Set up scene mode */
++ int i;
++ const struct v4l2_mmal_scene_config *scene = NULL;
++ int shutter_speed;
++ enum mmal_parameter_exposuremode exposure_mode;
++ enum mmal_parameter_exposuremeteringmode metering_mode;
++
++ for (i = 0; i < ARRAY_SIZE(scene_configs); i++) {
++ if (scene_configs[i].v4l2_scene ==
++ ctrl->val) {
++ scene = &scene_configs[i];
++ break;
++ }
++ }
++ if (i >= ARRAY_SIZE(scene_configs))
++ return -EINVAL;
++
++ /* Set all the values */
++ dev->scene_mode = ctrl->val;
++
++ if (scene->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF)
++ shutter_speed = dev->manual_shutter_speed;
++ else
++ shutter_speed = 0;
++ exposure_mode = scene->exposure_mode;
++ metering_mode = scene->metering_mode;
++
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n",
++ __func__, shutter_speed, exposure_mode, metering_mode);
++
++ ret = vchiq_mmal_port_parameter_set(dev->instance, control,
++ MMAL_PARAMETER_SHUTTER_SPEED,
++ &shutter_speed,
++ sizeof(shutter_speed));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ control,
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ &exposure_mode,
++ sizeof(u32));
++ dev->exposure_mode_active = exposure_mode;
++ ret += vchiq_mmal_port_parameter_set(dev->instance, control,
++ MMAL_PARAMETER_EXPOSURE_MODE,
++ &exposure_mode,
++ sizeof(u32));
++ ret += vchiq_mmal_port_parameter_set(dev->instance, control,
++ MMAL_PARAMETER_EXP_METERING_MODE,
++ &metering_mode,
++ sizeof(u32));
++ ret += set_framerate_params(dev);
++ }
++ if (ret) {
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "%s: Setting scene to %d, ret=%d\n",
++ __func__, ctrl->val, ret);
++ ret = -EINVAL;
++ }
++ return 0;
++}
++
+static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct bm2835_mmal_dev *dev =
@@ -14315,6 +14231,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ }
+
+ ret = mmal_ctrl->setter(dev, ctrl, mmal_ctrl);
++ if (ret)
++ pr_warn("ctrl id:%d/MMAL param %08X- returned ret %d\n",
++ ctrl->id, mmal_ctrl->mmal_id, ret);
+ if (mmal_ctrl->ignore_errors)
+ ret = 0;
+ return ret;
@@ -14401,6 +14320,14 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ false
+ },
+ {
++ V4L2_CID_EXPOSURE_AUTO_PRIORITY, MMAL_CONTROL_TYPE_STD,
++ 0, 1,
++ 0, 1, NULL,
++ 0, /* Dummy MMAL ID as it gets mapped into FPS range*/
++ &ctrl_set_exposure,
++ false
++ },
++ {
+ V4L2_CID_EXPOSURE_METERING,
+ MMAL_CONTROL_TYPE_STD_MENU,
+ ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
@@ -14411,12 +14338,26 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ {
+ V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
+ MMAL_CONTROL_TYPE_STD_MENU,
-+ ~0x3fe, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
++ ~0x3ff, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
+ MMAL_PARAMETER_AWB_MODE,
+ &ctrl_set_awb_mode,
+ false
+ },
+ {
++ V4L2_CID_RED_BALANCE, MMAL_CONTROL_TYPE_STD,
++ 1, 7999, 1000, 1, NULL,
++ MMAL_PARAMETER_CUSTOM_AWB_GAINS,
++ &ctrl_set_awb_gains,
++ false
++ },
++ {
++ V4L2_CID_BLUE_BALANCE, MMAL_CONTROL_TYPE_STD,
++ 1, 7999, 1000, 1, NULL,
++ MMAL_PARAMETER_CUSTOM_AWB_GAINS,
++ &ctrl_set_awb_gains,
++ false
++ },
++ {
+ V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU,
+ 0, 15, V4L2_COLORFX_NONE, 0, NULL,
+ MMAL_PARAMETER_IMAGE_EFFECT,
@@ -14490,6 +14431,48 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ &ctrl_set_video_encode_param_output,
+ true /* Errors ignored as requires latest firmware to work */
+ },
++ {
++ V4L2_CID_MPEG_VIDEO_H264_PROFILE,
++ MMAL_CONTROL_TYPE_STD_MENU,
++ ~((1<<V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
++ (1<<V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
++ (1<<V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
++ (1<<V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
++ V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, 1, NULL,
++ MMAL_PARAMETER_PROFILE,
++ &ctrl_set_video_encode_profile_level,
++ false
++ },
++ {
++ V4L2_CID_MPEG_VIDEO_H264_LEVEL, MMAL_CONTROL_TYPE_STD_MENU,
++ ~((1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1B) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_1) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_2) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_1_3) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_1) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_2_2) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
++ (1<<V4L2_MPEG_VIDEO_H264_LEVEL_4_0)),
++ V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
++ V4L2_MPEG_VIDEO_H264_LEVEL_4_0, 1, NULL,
++ MMAL_PARAMETER_PROFILE,
++ &ctrl_set_video_encode_profile_level,
++ false
++ },
++ {
++ V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
++ -1, /* Min is computed at runtime */
++ V4L2_SCENE_MODE_TEXT,
++ V4L2_SCENE_MODE_NONE, 1, NULL,
++ MMAL_PARAMETER_PROFILE,
++ &ctrl_set_scene_mode,
++ false
++ },
+};
+
+int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
@@ -14501,13 +14484,71 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ if ((dev->ctrls[c]) && (v4l2_ctrls[c].setter)) {
+ ret = v4l2_ctrls[c].setter(dev, dev->ctrls[c],
+ &v4l2_ctrls[c]);
-+ if (!v4l2_ctrls[c]. ignore_errors && ret)
++ if (!v4l2_ctrls[c].ignore_errors && ret) {
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Failed when setting default values for ctrl %d\n",
++ c);
+ break;
++ }
+ }
+ }
+ return ret;
+}
+
++int set_framerate_params(struct bm2835_mmal_dev *dev)
++{
++ struct mmal_parameter_fps_range fps_range;
++ int ret;
++
++ if ((dev->exposure_mode_active != MMAL_PARAM_EXPOSUREMODE_OFF) &&
++ (dev->exp_auto_priority)) {
++ /* Variable FPS. Define min FPS as 1fps.
++ * Max as max defined FPS.
++ */
++ fps_range.fps_low.num = 1;
++ fps_range.fps_low.den = 1;
++ fps_range.fps_high.num = dev->capture.timeperframe.denominator;
++ fps_range.fps_high.den = dev->capture.timeperframe.numerator;
++ } else {
++ /* Fixed FPS - set min and max to be the same */
++ fps_range.fps_low.num = fps_range.fps_high.num =
++ dev->capture.timeperframe.denominator;
++ fps_range.fps_low.den = fps_range.fps_high.den =
++ dev->capture.timeperframe.numerator;
++ }
++
++ v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Set fps range to %d/%d to %d/%d\n",
++ fps_range.fps_low.num,
++ fps_range.fps_low.den,
++ fps_range.fps_high.num,
++ fps_range.fps_high.den
++ );
++
++ ret = vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_PREVIEW],
++ MMAL_PARAMETER_FPS_RANGE,
++ &fps_range, sizeof(fps_range));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_VIDEO],
++ MMAL_PARAMETER_FPS_RANGE,
++ &fps_range, sizeof(fps_range));
++ ret += vchiq_mmal_port_parameter_set(dev->instance,
++ &dev->component[MMAL_COMPONENT_CAMERA]->
++ output[MMAL_CAMERA_PORT_CAPTURE],
++ MMAL_PARAMETER_FPS_RANGE,
++ &fps_range, sizeof(fps_range));
++ if (ret)
++ v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
++ "Failed to set fps ret %d\n",
++ ret);
++
++ return ret;
++
++}
++
+int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
+ struct v4l2_ctrl_handler *hdl)
+{
@@ -14527,10 +14568,30 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+ break;
+
+ case MMAL_CONTROL_TYPE_STD_MENU:
++ {
++ int mask = ctrl->min;
++
++ if (ctrl->id == V4L2_CID_SCENE_MODE) {
++ /* Special handling to work out the mask
++ * value based on the scene_configs array
++ * at runtime. Reduces the chance of
++ * mismatches.
++ */
++ int i;
++ mask = 1<<V4L2_SCENE_MODE_NONE;
++ for (i = 0;
++ i < ARRAY_SIZE(scene_configs);
++ i++) {
++ mask |= 1<<scene_configs[i].v4l2_scene;
++ }
++ mask = ~mask;
++ }
++
+ dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl,
+ &bm2835_mmal_ctrl_ops, ctrl->id,
-+ ctrl->max, ctrl->min, ctrl->def);
++ ctrl->max, mask, ctrl->def);
+ break;
++ }
+
+ case MMAL_CONTROL_TYPE_INT_MENU:
+ dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl,
@@ -14576,9 +14637,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/controls.c linux-raspberr
+
+ return 0;
+}
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/Kconfig linux-raspberry-pi/drivers/media/platform/bcm2835/Kconfig
---- linux-3.12.13/drivers/media/platform/bcm2835/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/Kconfig 2014-03-11 17:32:31.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/Kconfig linux-rpi/drivers/media/platform/bcm2835/Kconfig
+--- linux-3.12.18/drivers/media/platform/bcm2835/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/Kconfig 2014-04-24 15:35:02.713549510 +0200
@@ -0,0 +1,25 @@
+# Broadcom VideoCore IV v4l2 camera support
+
@@ -14605,19 +14666,19 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/Kconfig linux-raspberry-p
+
+
+endif # VIDEO_BM2835
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/Makefile linux-raspberry-pi/drivers/media/platform/bcm2835/Makefile
---- linux-3.12.13/drivers/media/platform/bcm2835/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/Makefile 2014-03-11 17:32:31.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/Makefile linux-rpi/drivers/media/platform/bcm2835/Makefile
+--- linux-3.12.18/drivers/media/platform/bcm2835/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/Makefile 2014-04-24 15:35:02.713549510 +0200
@@ -0,0 +1,5 @@
+bcm2835-v4l2-objs := bcm2835-camera.o controls.o mmal-vchiq.o
+
+obj-$(CONFIG_VIDEO_BCM2835_MMAL) += bcm2835-v4l2.o
+
+ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-common.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-common.h
---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-common.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-common.h 2014-03-11 17:51:15.000000000 +0100
-@@ -0,0 +1,52 @@
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-common.h linux-rpi/drivers/media/platform/bcm2835/mmal-common.h
+--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/mmal-common.h 2014-04-24 15:35:02.713549510 +0200
+@@ -0,0 +1,53 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -14646,6 +14707,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-common.h linux-raspb
+struct mmal_fmt {
+ char *name;
+ u32 fourcc; /* v4l2 format id */
++ int flags; /* v4l2 flags field */
+ u32 mmal;
+ int depth;
+ u32 mmal_component; /* MMAL component index to be used to encode */
@@ -14670,10 +14732,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-common.h linux-raspb
+ u32 v;
+};
+
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-encodings.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-encodings.h
---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-encodings.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-encodings.h 2014-03-11 17:51:15.000000000 +0100
-@@ -0,0 +1,93 @@
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-encodings.h linux-rpi/drivers/media/platform/bcm2835/mmal-encodings.h
+--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-encodings.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/mmal-encodings.h 2014-04-24 15:35:02.713549510 +0200
+@@ -0,0 +1,94 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -14703,6 +14765,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-encodings.h linux-ra
+#define MMAL_ENCODING_VP6 MMAL_FOURCC('V', 'P', '6', ' ')
+#define MMAL_ENCODING_THEORA MMAL_FOURCC('T', 'H', 'E', 'O')
+#define MMAL_ENCODING_SPARK MMAL_FOURCC('S', 'P', 'R', 'K')
++#define MMAL_ENCODING_MJPEG MMAL_FOURCC('M', 'J', 'P', 'G')
+
+#define MMAL_ENCODING_JPEG MMAL_FOURCC('J', 'P', 'E', 'G')
+#define MMAL_ENCODING_GIF MMAL_FOURCC('G', 'I', 'F', ' ')
@@ -14767,9 +14830,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-encodings.h linux-ra
+#define MMAL_ENCODING_VARIANT_H264_AVC1 MMAL_FOURCC('A', 'V', 'C', '1')
+/** Implicitly delineated NAL units without emulation prevention */
+#define MMAL_ENCODING_VARIANT_H264_RAW MMAL_FOURCC('R', 'A', 'W', ' ')
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-common.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-common.h
---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-common.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-common.h 2014-03-11 17:32:31.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-common.h linux-rpi/drivers/media/platform/bcm2835/mmal-msg-common.h
+--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/mmal-msg-common.h 2014-04-24 15:35:02.713549510 +0200
@@ -0,0 +1,50 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -14821,9 +14884,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-common.h linux-r
+};
+
+#endif /* MMAL_MSG_COMMON_H */
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-format.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-format.h
---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-format.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-format.h 2014-03-11 17:32:31.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-format.h linux-rpi/drivers/media/platform/bcm2835/mmal-msg-format.h
+--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-format.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/mmal-msg-format.h 2014-04-24 15:35:02.713549510 +0200
@@ -0,0 +1,81 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -14906,9 +14969,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-format.h linux-r
+};
+
+#endif /* MMAL_MSG_FORMAT_H */
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg.h
---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg.h 2014-03-11 17:32:31.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg.h linux-rpi/drivers/media/platform/bcm2835/mmal-msg.h
+--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/mmal-msg.h 2014-04-24 15:35:02.713549510 +0200
@@ -0,0 +1,404 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -15314,9 +15377,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg.h linux-raspberr
+ u8 payload[MMAL_MSG_MAX_PAYLOAD];
+ } u;
+};
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-port.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-port.h
---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-port.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-msg-port.h 2014-03-11 17:32:31.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-port.h linux-rpi/drivers/media/platform/bcm2835/mmal-msg-port.h
+--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-msg-port.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/mmal-msg-port.h 2014-04-24 15:35:02.713549510 +0200
@@ -0,0 +1,107 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -15425,10 +15488,10 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-msg-port.h linux-ras
+ */
+
+};
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-parameters.h
---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-parameters.h 2014-03-11 17:51:15.000000000 +0100
-@@ -0,0 +1,562 @@
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-parameters.h linux-rpi/drivers/media/platform/bcm2835/mmal-parameters.h
+--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-parameters.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/mmal-parameters.h 2014-04-24 15:35:02.713549510 +0200
+@@ -0,0 +1,655 @@
+/*
+ * Broadcom BM2835 V4L2 driver
+ *
@@ -15592,7 +15655,8 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r
+ MMAL_PARAMETER_SW_SHARPEN_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_FLASH_REQUIRED, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
+ MMAL_PARAMETER_SW_SATURATION_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
-+ MMAL_PARAMETER_SHUTTER_SPEED /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_SHUTTER_SPEED, /**< Takes a @ref MMAL_PARAMETER_UINT32_T */
++ MMAL_PARAMETER_CUSTOM_AWB_GAINS, /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */
+};
+
+struct mmal_parameter_rational {
@@ -15613,6 +15677,14 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r
+ */
+};
+
++struct mmal_parameter_fps_range {
++ /**< Low end of the permitted framerate range */
++ struct mmal_parameter_rational fps_low;
++ /**< High end of the permitted framerate range */
++ struct mmal_parameter_rational fps_high;
++};
++
++
+/* camera configuration parameter */
+struct mmal_parameter_camera_config {
+ /* Parameters for setting up the image pools */
@@ -15715,6 +15787,11 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r
+ MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF
+};
+
++struct mmal_parameter_awbgains {
++ struct mmal_parameter_rational r_gain; /**< Red gain */
++ struct mmal_parameter_rational b_gain; /**< Blue gain */
++};
++
+/** Manner of video rate control */
+enum mmal_parameter_rate_control_mode {
+ MMAL_VIDEO_RATECONTROL_DEFAULT,
@@ -15724,6 +15801,85 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r
+ MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
+};
+
++enum mmal_video_profile {
++ MMAL_VIDEO_PROFILE_H263_BASELINE,
++ MMAL_VIDEO_PROFILE_H263_H320CODING,
++ MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE,
++ MMAL_VIDEO_PROFILE_H263_ISWV2,
++ MMAL_VIDEO_PROFILE_H263_ISWV3,
++ MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION,
++ MMAL_VIDEO_PROFILE_H263_INTERNET,
++ MMAL_VIDEO_PROFILE_H263_INTERLACE,
++ MMAL_VIDEO_PROFILE_H263_HIGHLATENCY,
++ MMAL_VIDEO_PROFILE_MP4V_SIMPLE,
++ MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE,
++ MMAL_VIDEO_PROFILE_MP4V_CORE,
++ MMAL_VIDEO_PROFILE_MP4V_MAIN,
++ MMAL_VIDEO_PROFILE_MP4V_NBIT,
++ MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE,
++ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE,
++ MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA,
++ MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED,
++ MMAL_VIDEO_PROFILE_MP4V_HYBRID,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME,
++ MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE,
++ MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE,
++ MMAL_VIDEO_PROFILE_H264_BASELINE,
++ MMAL_VIDEO_PROFILE_H264_MAIN,
++ MMAL_VIDEO_PROFILE_H264_EXTENDED,
++ MMAL_VIDEO_PROFILE_H264_HIGH,
++ MMAL_VIDEO_PROFILE_H264_HIGH10,
++ MMAL_VIDEO_PROFILE_H264_HIGH422,
++ MMAL_VIDEO_PROFILE_H264_HIGH444,
++ MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE,
++ MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF
++};
++
++enum mmal_video_level {
++ MMAL_VIDEO_LEVEL_H263_10,
++ MMAL_VIDEO_LEVEL_H263_20,
++ MMAL_VIDEO_LEVEL_H263_30,
++ MMAL_VIDEO_LEVEL_H263_40,
++ MMAL_VIDEO_LEVEL_H263_45,
++ MMAL_VIDEO_LEVEL_H263_50,
++ MMAL_VIDEO_LEVEL_H263_60,
++ MMAL_VIDEO_LEVEL_H263_70,
++ MMAL_VIDEO_LEVEL_MP4V_0,
++ MMAL_VIDEO_LEVEL_MP4V_0b,
++ MMAL_VIDEO_LEVEL_MP4V_1,
++ MMAL_VIDEO_LEVEL_MP4V_2,
++ MMAL_VIDEO_LEVEL_MP4V_3,
++ MMAL_VIDEO_LEVEL_MP4V_4,
++ MMAL_VIDEO_LEVEL_MP4V_4a,
++ MMAL_VIDEO_LEVEL_MP4V_5,
++ MMAL_VIDEO_LEVEL_MP4V_6,
++ MMAL_VIDEO_LEVEL_H264_1,
++ MMAL_VIDEO_LEVEL_H264_1b,
++ MMAL_VIDEO_LEVEL_H264_11,
++ MMAL_VIDEO_LEVEL_H264_12,
++ MMAL_VIDEO_LEVEL_H264_13,
++ MMAL_VIDEO_LEVEL_H264_2,
++ MMAL_VIDEO_LEVEL_H264_21,
++ MMAL_VIDEO_LEVEL_H264_22,
++ MMAL_VIDEO_LEVEL_H264_3,
++ MMAL_VIDEO_LEVEL_H264_31,
++ MMAL_VIDEO_LEVEL_H264_32,
++ MMAL_VIDEO_LEVEL_H264_4,
++ MMAL_VIDEO_LEVEL_H264_41,
++ MMAL_VIDEO_LEVEL_H264_42,
++ MMAL_VIDEO_LEVEL_H264_5,
++ MMAL_VIDEO_LEVEL_H264_51,
++ MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF
++};
++
++struct mmal_parameter_video_profile {
++ enum mmal_video_profile profile;
++ enum mmal_video_level level;
++};
++
+/* video parameters */
+
+enum mmal_parameter_video_type {
@@ -15991,9 +16147,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-parameters.h linux-r
+ u32 num_effect_params;
+ u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
+};
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.c linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-vchiq.c
---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-vchiq.c 2014-03-11 17:51:15.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-vchiq.c linux-rpi/drivers/media/platform/bcm2835/mmal-vchiq.c
+--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-vchiq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/mmal-vchiq.c 2014-04-24 16:04:36.447091651 +0200
@@ -0,0 +1,1916 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -17323,7 +17479,7 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.c linux-raspbe
+ memcpy(value, &rmsg->u.port_parameter_get_reply.value,
+ rmsg->u.port_parameter_get_reply.size);
+
-+ pr_info("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
++ pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
+ ret, port->component->handle, port->handle, parameter_id);
+
+release_msg:
@@ -17911,9 +18067,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.c linux-raspbe
+ kfree(instance);
+ return -ENODEV;
+}
-diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.h linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-vchiq.h
---- linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/bcm2835/mmal-vchiq.h 2014-03-11 17:32:31.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/bcm2835/mmal-vchiq.h linux-rpi/drivers/media/platform/bcm2835/mmal-vchiq.h
+--- linux-3.12.18/drivers/media/platform/bcm2835/mmal-vchiq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/media/platform/bcm2835/mmal-vchiq.h 2014-04-24 15:35:02.713549510 +0200
@@ -0,0 +1,178 @@
+/*
+ * Broadcom BM2835 V4L2 driver
@@ -18093,9 +18249,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/bcm2835/mmal-vchiq.h linux-raspbe
+ struct mmal_buffer *buf);
+
+#endif /* MMAL_VCHIQ_H */
-diff -Nur linux-3.12.13/drivers/media/platform/Kconfig linux-raspberry-pi/drivers/media/platform/Kconfig
---- linux-3.12.13/drivers/media/platform/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/Kconfig 2014-03-11 17:51:15.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/Kconfig linux-rpi/drivers/media/platform/Kconfig
+--- linux-3.12.18/drivers/media/platform/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/media/platform/Kconfig 2014-04-24 16:04:36.447091651 +0200
@@ -124,6 +124,7 @@
source "drivers/media/platform/soc_camera/Kconfig"
source "drivers/media/platform/exynos4-is/Kconfig"
@@ -18104,9 +18260,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/Kconfig linux-raspberry-pi/driver
endif # V4L_PLATFORM_DRIVERS
-diff -Nur linux-3.12.13/drivers/media/platform/Makefile linux-raspberry-pi/drivers/media/platform/Makefile
---- linux-3.12.13/drivers/media/platform/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/platform/Makefile 2014-03-11 17:51:15.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/platform/Makefile linux-rpi/drivers/media/platform/Makefile
+--- linux-3.12.18/drivers/media/platform/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/media/platform/Makefile 2014-04-24 16:04:36.447091651 +0200
@@ -52,4 +52,6 @@
obj-$(CONFIG_ARCH_OMAP) += omap/
@@ -18114,99 +18270,9 @@ diff -Nur linux-3.12.13/drivers/media/platform/Makefile linux-raspberry-pi/drive
+obj-$(CONFIG_VIDEO_BCM2835) += bcm2835/
+
ccflags-y += -I$(srctree)/drivers/media/i2c
-diff -Nur linux-3.12.13/drivers/media/usb/dvb-usb-v2/az6007.c linux-raspberry-pi/drivers/media/usb/dvb-usb-v2/az6007.c
---- linux-3.12.13/drivers/media/usb/dvb-usb-v2/az6007.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/usb/dvb-usb-v2/az6007.c 2014-03-11 17:32:32.000000000 +0100
-@@ -68,6 +68,19 @@
- .microcode_name = "dvb-usb-terratec-h7-drxk.fw",
- };
-
-+static struct drxk_config cablestar_hdci_drxk = {
-+ .adr = 0x29,
-+ .parallel_ts = true,
-+ .dynamic_clk = true,
-+ .single_master = true,
-+ .enable_merr_cfg = true,
-+ .no_i2c_bridge = false,
-+ .chunk_size = 64,
-+ .mpeg_out_clk_strength = 0x02,
-+ .qam_demod_parameter_count = 2,
-+ .microcode_name = "dvb-usb-technisat-cablestar-hdci-drxk.fw",
-+};
-+
- static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
- {
- struct az6007_device_state *st = fe_to_priv(fe);
-@@ -630,6 +643,27 @@
- return 0;
- }
-
-+static int az6007_cablestar_hdci_frontend_attach(struct dvb_usb_adapter *adap)
-+{
-+ struct az6007_device_state *st = adap_to_priv(adap);
-+ struct dvb_usb_device *d = adap_to_d(adap);
-+
-+ pr_debug("attaching demod drxk\n");
-+
-+ adap->fe[0] = dvb_attach(drxk_attach, &cablestar_hdci_drxk,
-+ &d->i2c_adap);
-+ if (!adap->fe[0])
-+ return -EINVAL;
-+
-+ adap->fe[0]->sec_priv = adap;
-+ st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl;
-+ adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
-+
-+ az6007_ci_init(adap);
-+
-+ return 0;
-+}
-+
- static int az6007_tuner_attach(struct dvb_usb_adapter *adap)
- {
- struct dvb_usb_device *d = adap_to_d(adap);
-@@ -868,6 +902,29 @@
- }
- };
-
-+static struct dvb_usb_device_properties az6007_cablestar_hdci_props = {
-+ .driver_name = KBUILD_MODNAME,
-+ .owner = THIS_MODULE,
-+ .firmware = AZ6007_FIRMWARE,
-+
-+ .adapter_nr = adapter_nr,
-+ .size_of_priv = sizeof(struct az6007_device_state),
-+ .i2c_algo = &az6007_i2c_algo,
-+ .tuner_attach = az6007_tuner_attach,
-+ .frontend_attach = az6007_cablestar_hdci_frontend_attach,
-+ .streaming_ctrl = az6007_streaming_ctrl,
-+/* ditch get_rc_config as it can't work (TS35 remote, I believe it's rc5) */
-+ .get_rc_config = NULL,
-+ .read_mac_address = az6007_read_mac_addr,
-+ .download_firmware = az6007_download_firmware,
-+ .identify_state = az6007_identify_state,
-+ .power_ctrl = az6007_power_ctrl,
-+ .num_adapters = 1,
-+ .adapter = {
-+ { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), }
-+ }
-+};
-+
- static struct usb_device_id az6007_usb_table[] = {
- {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007,
- &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)},
-@@ -875,6 +932,8 @@
- &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
- {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2,
- &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
-+ {DVB_USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_CABLESTAR_HDCI,
-+ &az6007_cablestar_hdci_props, "Technisat CableStar Combo HD CI", RC_MAP_EMPTY)},
- {0},
- };
-
-diff -Nur linux-3.12.13/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-raspberry-pi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
---- linux-3.12.13/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-rpi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+--- linux-3.12.18/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2014-04-24 16:04:36.559092734 +0200
@@ -1384,6 +1384,10 @@
&rtl2832u_props, "Compro VideoMate U620F", NULL) },
{ DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394,
@@ -18218,26 +18284,26 @@ diff -Nur linux-3.12.13/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-raspberry-
{ DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a03,
&rtl2832u_props, "Leadtek WinFast DTV Dongle mini", NULL) },
{ DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_CPYTO_REDI_PC50A,
-diff -Nur linux-3.12.13/drivers/misc/Kconfig linux-raspberry-pi/drivers/misc/Kconfig
---- linux-3.12.13/drivers/misc/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/Kconfig 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/Kconfig linux-rpi/drivers/misc/Kconfig
+--- linux-3.12.18/drivers/misc/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/misc/Kconfig 2014-04-24 16:04:36.711094204 +0200
@@ -537,4 +537,5 @@
source "drivers/misc/altera-stapl/Kconfig"
source "drivers/misc/mei/Kconfig"
source "drivers/misc/vmw_vmci/Kconfig"
+source "drivers/misc/vc04_services/Kconfig"
endmenu
-diff -Nur linux-3.12.13/drivers/misc/Makefile linux-raspberry-pi/drivers/misc/Makefile
---- linux-3.12.13/drivers/misc/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/Makefile 2014-03-11 17:32:36.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/Makefile linux-rpi/drivers/misc/Makefile
+--- linux-3.12.18/drivers/misc/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/misc/Makefile 2014-04-24 15:35:02.873551293 +0200
@@ -53,3 +53,4 @@
obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
+obj-$(CONFIG_BCM2708_VCHIQ) += vc04_services/
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/connections/connection.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/connections/connection.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/connections/connection.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/connections/connection.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/connections/connection.h linux-rpi/drivers/misc/vc04_services/interface/vchi/connections/connection.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/connections/connection.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/connections/connection.h 2014-04-24 15:35:02.889551471 +0200
@@ -0,0 +1,328 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -18567,9 +18633,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/connections/co
+#endif /* CONNECTION_H_ */
+
+/****************************** End of file **********************************/
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h linux-rpi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 2014-04-24 15:35:02.889551471 +0200
@@ -0,0 +1,204 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -18775,9 +18841,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/message_driver
+#endif // _VCHI_MESSAGE_H_
+
+/****************************** End of file ***********************************/
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 2014-04-24 15:35:02.889551471 +0200
@@ -0,0 +1,224 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -19003,9 +19069,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h lin
+#endif /* VCHI_CFG_H_ */
+
+/****************************** End of file **********************************/
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 2014-04-24 15:35:02.889551471 +0200
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -19078,9 +19144,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_cfg_inter
+//#define VCHI_RX_NANOLOCKS
+
+#endif /*VCHI_CFG_INTERNAL_H_*/
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_common.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_common.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_common.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_common.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_common.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_common.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_common.h 2014-04-24 15:35:02.889551471 +0200
@@ -0,0 +1,163 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -19245,9 +19311,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_common.h
+
+
+#endif // VCHI_COMMON_H_
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi.h 2014-04-24 15:35:02.889551471 +0200
@@ -0,0 +1,373 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -19622,9 +19688,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi.h linux-r
+#endif /* VCHI_H_ */
+
+/****************************** End of file **********************************/
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -19668,9 +19734,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linu
+#define VCHI_MEM_HANDLE_INVALID 0
+
+#endif
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,561 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -20233,9 +20299,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_283
+
+ kfree(pagelist);
+}
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -20279,9 +20345,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_283
+#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1
+
+#endif /* VCHIQ_2835_H */
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,2813 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -23096,9 +23162,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm
+module_exit(vchiq_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Broadcom Corporation");
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,212 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -23312,9 +23378,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm
+
+
+#endif /* VCHIQ_ARM_H */
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_build_info.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -23353,9 +23419,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_bui
+const char *vchiq_get_build_version(void);
+const char *vchiq_get_build_time(void);
+const char *vchiq_get_build_date(void);
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -23417,9 +23483,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg
+#endif
+
+#endif /* VCHIQ_CFG_H */
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -23540,9 +23606,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_con
+ mutex_unlock(&g_connected_mutex);
+}
+EXPORT_SYMBOL(vchiq_add_connected_callback);
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 2014-04-24 16:04:36.831095364 +0200
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -23594,9 +23660,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_con
+void vchiq_call_connected_callbacks(void);
+
+#endif /* VCHIQ_CONNECTED_H */
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,3824 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -27422,9 +27488,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cor
+ numBytes = 0;
+ }
+}
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,706 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -28132,9 +28198,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cor
+ size_t numBytes);
+
+#endif
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_genversion 2014-04-24 16:04:36.831095364 +0200
@@ -0,0 +1,87 @@
+#!/usr/bin/perl -w
+
@@ -28223,9 +28289,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_gen
+ return vchiq_build_time;
+}
+EOF
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 2014-04-24 16:04:36.831095364 +0200
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -28267,9 +28333,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h l
+#include "vchiq_util.h"
+
+#endif
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -28459,9 +28525,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.
+ short *peer_version);
+
+#endif /* VCHIQ_IF_H */
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,129 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -28592,9 +28658,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioc
+#define VCHIQ_IOC_MAX 15
+
+#endif
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,456 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -29052,9 +29118,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ker
+
+ return status;
+}
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -29127,9 +29193,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_mem
+ const VCHIQ_PLATFORM_DATA_T * platform_data);
+
+#endif
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -29189,9 +29255,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pag
+} FRAGMENTS_T;
+
+#endif /* VCHIQ_PAGELIST_H */
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c 2014-04-24 16:04:36.831095364 +0200
@@ -0,0 +1,253 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -29446,9 +29512,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pro
+}
+
+#endif
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,828 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -30278,9 +30344,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shi
+ return ret;
+}
+EXPORT_SYMBOL(vchi_service_release);
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -30433,9 +30499,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_uti
+
+ return header;
+}
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 2014-04-24 16:04:36.831095364 +0200
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -30518,9 +30584,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_uti
+extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue);
+
+#endif
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c
---- linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 2014-03-11 17:32:37.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c
+--- linux-3.12.18/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c 2014-04-24 15:35:02.893551516 +0200
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2010-2012 Broadcom. All rights reserved.
@@ -30581,9 +30647,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ver
+{
+ return vchiq_build_time;
+}
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/Kconfig linux-raspberry-pi/drivers/misc/vc04_services/Kconfig
---- linux-3.12.13/drivers/misc/vc04_services/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/Kconfig 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/Kconfig linux-rpi/drivers/misc/vc04_services/Kconfig
+--- linux-3.12.18/drivers/misc/vc04_services/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/Kconfig 2014-04-24 16:04:36.831095364 +0200
@@ -0,0 +1,9 @@
+config BCM2708_VCHIQ
+ tristate "Videocore VCHIQ"
@@ -30594,9 +30660,9 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/Kconfig linux-raspberry-pi/dr
+ BCM2708 family of products.
+ Defaults to Y when the Broadcom Videocore services
+ are included in the build, N otherwise.
-diff -Nur linux-3.12.13/drivers/misc/vc04_services/Makefile linux-raspberry-pi/drivers/misc/vc04_services/Makefile
---- linux-3.12.13/drivers/misc/vc04_services/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/misc/vc04_services/Makefile 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/misc/vc04_services/Makefile linux-rpi/drivers/misc/vc04_services/Makefile
+--- linux-3.12.18/drivers/misc/vc04_services/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/misc/vc04_services/Makefile 2014-04-24 16:04:36.831095364 +0200
@@ -0,0 +1,17 @@
+ifeq ($(CONFIG_MACH_BCM2708),y)
+
@@ -30612,12 +30678,12 @@ diff -Nur linux-3.12.13/drivers/misc/vc04_services/Makefile linux-raspberry-pi/d
+ interface/vchiq_arm/vchiq_util.o \
+ interface/vchiq_arm/vchiq_connected.o \
+
-+EXTRA_CFLAGS += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000
++ccflags-y += -DVCOS_VERIFY_BKPTS=1 -Idrivers/misc/vc04_services -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000
+
+endif
-diff -Nur linux-3.12.13/drivers/mmc/card/block.c linux-raspberry-pi/drivers/mmc/card/block.c
---- linux-3.12.13/drivers/mmc/card/block.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/mmc/card/block.c 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/mmc/card/block.c linux-rpi/drivers/mmc/card/block.c
+--- linux-3.12.18/drivers/mmc/card/block.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/mmc/card/block.c 2014-04-24 16:04:36.835095403 +0200
@@ -1361,7 +1361,7 @@
brq->data.blocks = 1;
}
@@ -30627,9 +30693,9 @@ diff -Nur linux-3.12.13/drivers/mmc/card/block.c linux-raspberry-pi/drivers/mmc/
/* SPI multiblock writes terminate using a special
* token, not a STOP_TRANSMISSION request.
*/
-diff -Nur linux-3.12.13/drivers/mmc/core/sd.c linux-raspberry-pi/drivers/mmc/core/sd.c
---- linux-3.12.13/drivers/mmc/core/sd.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/mmc/core/sd.c 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/mmc/core/sd.c linux-rpi/drivers/mmc/core/sd.c
+--- linux-3.12.18/drivers/mmc/core/sd.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/mmc/core/sd.c 2014-04-24 16:04:36.839095442 +0200
@@ -14,6 +14,8 @@
#include <linux/sizes.h>
#include <linux/slab.h>
@@ -30784,9 +30850,9 @@ diff -Nur linux-3.12.13/drivers/mmc/core/sd.c linux-raspberry-pi/drivers/mmc/cor
return err;
/*
-diff -Nur linux-3.12.13/drivers/mmc/host/Kconfig linux-raspberry-pi/drivers/mmc/host/Kconfig
---- linux-3.12.13/drivers/mmc/host/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/mmc/host/Kconfig 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/mmc/host/Kconfig linux-rpi/drivers/mmc/host/Kconfig
+--- linux-3.12.18/drivers/mmc/host/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/mmc/host/Kconfig 2014-04-24 16:04:36.839095442 +0200
@@ -260,6 +260,27 @@
If you have a controller with this interface, say Y or M here.
@@ -30815,9 +30881,9 @@ diff -Nur linux-3.12.13/drivers/mmc/host/Kconfig linux-raspberry-pi/drivers/mmc/
config MMC_SDHCI_BCM2835
tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
depends on ARCH_BCM2835
-diff -Nur linux-3.12.13/drivers/mmc/host/Makefile linux-raspberry-pi/drivers/mmc/host/Makefile
---- linux-3.12.13/drivers/mmc/host/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/mmc/host/Makefile 2014-03-11 17:51:16.000000000 +0100
+diff -Nur linux-3.12.18/drivers/mmc/host/Makefile linux-rpi/drivers/mmc/host/Makefile
+--- linux-3.12.18/drivers/mmc/host/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/mmc/host/Makefile 2014-04-24 16:04:36.839095442 +0200
@@ -15,6 +15,7 @@
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o
@@ -30826,9 +30892,9 @@ diff -Nur linux-3.12.13/drivers/mmc/host/Makefile linux-raspberry-pi/drivers/mmc
obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
obj-$(CONFIG_MMC_OMAP) += omap.o
-diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/drivers/mmc/host/sdhci-bcm2708.c
---- linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/mmc/host/sdhci-bcm2708.c 2014-03-11 17:51:21.000000000 +0100
+diff -Nur linux-3.12.18/drivers/mmc/host/sdhci-bcm2708.c linux-rpi/drivers/mmc/host/sdhci-bcm2708.c
+--- linux-3.12.18/drivers/mmc/host/sdhci-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/mmc/host/sdhci-bcm2708.c 2014-04-24 16:04:36.847095519 +0200
@@ -0,0 +1,1410 @@
+/*
+ * sdhci-bcm2708.c Support for SDHCI device on BCM2708
@@ -31095,7 +31161,7 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/driv
+ {
+ /* we must have waited at least this many ns: */
+ unsigned int ns_wait = HPTIME_CLK_NS *
-+ (last_write_hpt - now - 1);
++ (now - last_write_hpt - 1);
+ if (ns_wait < ns_2clk)
+ ndelay(ns_2clk - ns_wait);
+ }
@@ -31909,7 +31975,7 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/driv
+ int ret = 0;
+
+ if (host->mmc) {
-+ ret = mmc_suspend_host(host->mmc);
++ //ret = mmc_suspend_host(host->mmc);
+ }
+
+ return ret;
@@ -31922,7 +31988,7 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/driv
+ int ret = 0;
+
+ if (host->mmc) {
-+ ret = mmc_resume_host(host->mmc);
++ //ret = mmc_resume_host(host->mmc);
+ }
+
+ return ret;
@@ -32240,9 +32306,9 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci-bcm2708.c linux-raspberry-pi/driv
+MODULE_PARM_DESC(extra_messages, "Enable more sdcard warning messages");
+
+
-diff -Nur linux-3.12.13/drivers/mmc/host/sdhci.c linux-raspberry-pi/drivers/mmc/host/sdhci.c
---- linux-3.12.13/drivers/mmc/host/sdhci.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/mmc/host/sdhci.c 2014-03-11 17:51:21.000000000 +0100
+diff -Nur linux-3.12.18/drivers/mmc/host/sdhci.c linux-rpi/drivers/mmc/host/sdhci.c
+--- linux-3.12.18/drivers/mmc/host/sdhci.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/mmc/host/sdhci.c 2014-04-24 16:04:36.851095558 +0200
@@ -28,6 +28,7 @@
#include <linux/mmc/mmc.h>
#include <linux/mmc/host.h>
@@ -33084,9 +33150,9 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci.c linux-raspberry-pi/drivers/mmc/
}
sdhci_disable_card_detection(host);
-diff -Nur linux-3.12.13/drivers/mmc/host/sdhci.h linux-raspberry-pi/drivers/mmc/host/sdhci.h
---- linux-3.12.13/drivers/mmc/host/sdhci.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/mmc/host/sdhci.h 2014-03-11 17:51:21.000000000 +0100
+diff -Nur linux-3.12.18/drivers/mmc/host/sdhci.h linux-rpi/drivers/mmc/host/sdhci.h
+--- linux-3.12.18/drivers/mmc/host/sdhci.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/mmc/host/sdhci.h 2014-04-24 16:04:36.851095558 +0200
@@ -289,6 +289,18 @@
void (*platform_reset_enter)(struct sdhci_host *host, u8 mask);
void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
@@ -33145,9 +33211,234 @@ diff -Nur linux-3.12.13/drivers/mmc/host/sdhci.h linux-raspberry-pi/drivers/mmc/
+
+
#endif /* __SDHCI_HW_H */
-diff -Nur linux-3.12.13/drivers/net/usb/smsc95xx.c linux-raspberry-pi/drivers/net/usb/smsc95xx.c
---- linux-3.12.13/drivers/net/usb/smsc95xx.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/net/usb/smsc95xx.c 2014-03-11 17:51:24.000000000 +0100
+diff -Nur linux-3.12.18/drivers/net/bonding/bond_alb.c linux-rpi/drivers/net/bonding/bond_alb.c
+--- linux-3.12.18/drivers/net/bonding/bond_alb.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/bonding/bond_alb.c 2014-04-24 16:04:36.879095829 +0200
+@@ -694,7 +694,7 @@
+ client_info->ntt = 0;
+ }
+
+- if (vlan_get_tag(skb, &client_info->vlan_id))
++ if (!vlan_get_tag(skb, &client_info->vlan_id))
+ client_info->vlan_id = 0;
+
+ if (!client_info->assigned) {
+diff -Nur linux-3.12.18/drivers/net/ethernet/broadcom/bnx2.c linux-rpi/drivers/net/ethernet/broadcom/bnx2.c
+--- linux-3.12.18/drivers/net/ethernet/broadcom/bnx2.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/ethernet/broadcom/bnx2.c 2014-04-24 16:04:36.911096138 +0200
+@@ -2490,7 +2490,6 @@
+
+ bp->fw_wr_seq++;
+ msg_data |= bp->fw_wr_seq;
+- bp->fw_last_msg = msg_data;
+
+ bnx2_shmem_wr(bp, BNX2_DRV_MB, msg_data);
+
+@@ -3983,23 +3982,8 @@
+ wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
+ }
+
+- if (!(bp->flags & BNX2_FLAG_NO_WOL)) {
+- u32 val;
+-
+- wol_msg |= BNX2_DRV_MSG_DATA_WAIT3;
+- if (bp->fw_last_msg || BNX2_CHIP(bp) != BNX2_CHIP_5709) {
+- bnx2_fw_sync(bp, wol_msg, 1, 0);
+- return;
+- }
+- /* Tell firmware not to power down the PHY yet, otherwise
+- * the chip will take a long time to respond to MMIO reads.
+- */
+- val = bnx2_shmem_rd(bp, BNX2_PORT_FEATURE);
+- bnx2_shmem_wr(bp, BNX2_PORT_FEATURE,
+- val | BNX2_PORT_FEATURE_ASF_ENABLED);
+- bnx2_fw_sync(bp, wol_msg, 1, 0);
+- bnx2_shmem_wr(bp, BNX2_PORT_FEATURE, val);
+- }
++ if (!(bp->flags & BNX2_FLAG_NO_WOL))
++ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg, 1, 0);
+
+ }
+
+@@ -4031,22 +4015,9 @@
+
+ if (bp->wol)
+ pci_set_power_state(bp->pdev, PCI_D3hot);
+- break;
+-
+- }
+- if (!bp->fw_last_msg && BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+- u32 val;
+-
+- /* Tell firmware not to power down the PHY yet,
+- * otherwise the other port may not respond to
+- * MMIO reads.
+- */
+- val = bnx2_shmem_rd(bp, BNX2_BC_STATE_CONDITION);
+- val &= ~BNX2_CONDITION_PM_STATE_MASK;
+- val |= BNX2_CONDITION_PM_STATE_UNPREP;
+- bnx2_shmem_wr(bp, BNX2_BC_STATE_CONDITION, val);
++ } else {
++ pci_set_power_state(bp->pdev, PCI_D3hot);
+ }
+- pci_set_power_state(bp->pdev, PCI_D3hot);
+
+ /* No more memory access after this point until
+ * device is brought back to D0.
+diff -Nur linux-3.12.18/drivers/net/ethernet/broadcom/bnx2.h linux-rpi/drivers/net/ethernet/broadcom/bnx2.h
+--- linux-3.12.18/drivers/net/ethernet/broadcom/bnx2.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/ethernet/broadcom/bnx2.h 2014-04-24 16:04:36.915096177 +0200
+@@ -6890,7 +6890,6 @@
+
+ u16 fw_wr_seq;
+ u16 fw_drv_pulse_wr_seq;
+- u32 fw_last_msg;
+
+ int rx_max_ring;
+ int rx_ring_size;
+@@ -7397,10 +7396,6 @@
+ #define BNX2_CONDITION_MFW_RUN_NCSI 0x00006000
+ #define BNX2_CONDITION_MFW_RUN_NONE 0x0000e000
+ #define BNX2_CONDITION_MFW_RUN_MASK 0x0000e000
+-#define BNX2_CONDITION_PM_STATE_MASK 0x00030000
+-#define BNX2_CONDITION_PM_STATE_FULL 0x00030000
+-#define BNX2_CONDITION_PM_STATE_PREP 0x00020000
+-#define BNX2_CONDITION_PM_STATE_UNPREP 0x00010000
+
+ #define BNX2_BC_STATE_DEBUG_CMD 0x1dc
+ #define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000
+diff -Nur linux-3.12.18/drivers/net/ethernet/broadcom/tg3.c linux-rpi/drivers/net/ethernet/broadcom/tg3.c
+--- linux-3.12.18/drivers/net/ethernet/broadcom/tg3.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/ethernet/broadcom/tg3.c 2014-04-24 16:04:36.935096370 +0200
+@@ -17480,6 +17480,8 @@
+
+ tg3_init_bufmgr_config(tp);
+
++ features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
++
+ /* 5700 B0 chips do not support checksumming correctly due
+ * to hardware bugs.
+ */
+@@ -17511,8 +17513,7 @@
+ features |= NETIF_F_TSO_ECN;
+ }
+
+- dev->features |= features | NETIF_F_HW_VLAN_CTAG_TX |
+- NETIF_F_HW_VLAN_CTAG_RX;
++ dev->features |= features;
+ dev->vlan_features |= features;
+
+ /*
+diff -Nur linux-3.12.18/drivers/net/ethernet/freescale/fec_main.c linux-rpi/drivers/net/ethernet/freescale/fec_main.c
+--- linux-3.12.18/drivers/net/ethernet/freescale/fec_main.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/ethernet/freescale/fec_main.c 2014-04-24 16:04:37.143098381 +0200
+@@ -525,6 +525,13 @@
+ /* Clear any outstanding interrupt. */
+ writel(0xffc00000, fep->hwp + FEC_IEVENT);
+
++ /* Setup multicast filter. */
++ set_multicast_list(ndev);
++#ifndef CONFIG_M5272
++ writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
++ writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
++#endif
++
+ /* Set maximum receive buffer size. */
+ writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
+
+@@ -645,13 +652,6 @@
+
+ writel(rcntl, fep->hwp + FEC_R_CNTRL);
+
+- /* Setup multicast filter. */
+- set_multicast_list(ndev);
+-#ifndef CONFIG_M5272
+- writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
+- writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
+-#endif
+-
+ if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+ /* enable ENET endian swap */
+ ecntl |= (1 << 8);
+diff -Nur linux-3.12.18/drivers/net/ethernet/micrel/ks8851.c linux-rpi/drivers/net/ethernet/micrel/ks8851.c
+--- linux-3.12.18/drivers/net/ethernet/micrel/ks8851.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/ethernet/micrel/ks8851.c 2014-04-24 15:35:03.105553878 +0200
+@@ -23,7 +23,6 @@
+ #include <linux/crc32.h>
+ #include <linux/mii.h>
+ #include <linux/eeprom_93cx6.h>
+-#include <linux/regulator/consumer.h>
+
+ #include <linux/spi/spi.h>
+
+@@ -84,7 +83,6 @@
+ * @rc_rxqcr: Cached copy of KS_RXQCR.
+ * @eeprom_size: Companion eeprom size in Bytes, 0 if no eeprom
+ * @eeprom: 93CX6 EEPROM state for accessing on-board EEPROM.
+- * @vdd_reg: Optional regulator supplying the chip
+ *
+ * The @lock ensures that the chip is protected when certain operations are
+ * in progress. When the read or write packet transfer is in progress, most
+@@ -132,7 +130,6 @@
+ struct spi_transfer spi_xfer2[2];
+
+ struct eeprom_93cx6 eeprom;
+- struct regulator *vdd_reg;
+ };
+
+ static int msg_enable;
+@@ -1417,21 +1414,6 @@
+ ks->spidev = spi;
+ ks->tx_space = 6144;
+
+- ks->vdd_reg = regulator_get_optional(&spi->dev, "vdd");
+- if (IS_ERR(ks->vdd_reg)) {
+- ret = PTR_ERR(ks->vdd_reg);
+- if (ret == -EPROBE_DEFER)
+- goto err_reg;
+- } else {
+- ret = regulator_enable(ks->vdd_reg);
+- if (ret) {
+- dev_err(&spi->dev, "regulator enable fail: %d\n",
+- ret);
+- goto err_reg_en;
+- }
+- }
+-
+-
+ mutex_init(&ks->lock);
+ spin_lock_init(&ks->statelock);
+
+@@ -1526,14 +1508,8 @@
+ err_netdev:
+ free_irq(ndev->irq, ks);
+
+-err_irq:
+ err_id:
+- if (!IS_ERR(ks->vdd_reg))
+- regulator_disable(ks->vdd_reg);
+-err_reg_en:
+- if (!IS_ERR(ks->vdd_reg))
+- regulator_put(ks->vdd_reg);
+-err_reg:
++err_irq:
+ free_netdev(ndev);
+ return ret;
+ }
+@@ -1547,10 +1523,6 @@
+
+ unregister_netdev(priv->netdev);
+ free_irq(spi->irq, priv);
+- if (!IS_ERR(priv->vdd_reg)) {
+- regulator_disable(priv->vdd_reg);
+- regulator_put(priv->vdd_reg);
+- }
+ free_netdev(priv->netdev);
+
+ return 0;
+diff -Nur linux-3.12.18/drivers/net/usb/smsc95xx.c linux-rpi/drivers/net/usb/smsc95xx.c
+--- linux-3.12.18/drivers/net/usb/smsc95xx.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/usb/smsc95xx.c 2014-04-24 15:35:03.209555036 +0200
@@ -61,6 +61,7 @@
#define SUSPEND_SUSPEND3 (0x08)
#define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
@@ -33227,9 +33518,448 @@ diff -Nur linux-3.12.13/drivers/net/usb/smsc95xx.c linux-raspberry-pi/drivers/ne
/* try reading mac address from EEPROM */
if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
dev->net->dev_addr) == 0) {
-diff -Nur linux-3.12.13/drivers/spi/Kconfig linux-raspberry-pi/drivers/spi/Kconfig
---- linux-3.12.13/drivers/spi/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/spi/Kconfig 2014-03-11 17:51:25.000000000 +0100
+diff -Nur linux-3.12.18/drivers/net/usb/usbnet.c linux-rpi/drivers/net/usb/usbnet.c
+--- linux-3.12.18/drivers/net/usb/usbnet.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/usb/usbnet.c 2014-04-24 16:04:37.631103100 +0200
+@@ -753,12 +753,14 @@
+ // precondition: never called in_interrupt
+ static void usbnet_terminate_urbs(struct usbnet *dev)
+ {
++ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
+ DECLARE_WAITQUEUE(wait, current);
+ int temp;
+
+ /* ensure there are no more active urbs */
+- add_wait_queue(&dev->wait, &wait);
++ add_wait_queue(&unlink_wakeup, &wait);
+ set_current_state(TASK_UNINTERRUPTIBLE);
++ dev->wait = &unlink_wakeup;
+ temp = unlink_urbs(dev, &dev->txq) +
+ unlink_urbs(dev, &dev->rxq);
+
+@@ -772,14 +774,15 @@
+ "waited for %d urb completions\n", temp);
+ }
+ set_current_state(TASK_RUNNING);
+- remove_wait_queue(&dev->wait, &wait);
++ dev->wait = NULL;
++ remove_wait_queue(&unlink_wakeup, &wait);
+ }
+
+ int usbnet_stop (struct net_device *net)
+ {
+ struct usbnet *dev = netdev_priv(net);
+ struct driver_info *info = dev->driver_info;
+- int retval, pm;
++ int retval;
+
+ clear_bit(EVENT_DEV_OPEN, &dev->flags);
+ netif_stop_queue (net);
+@@ -789,8 +792,6 @@
+ net->stats.rx_packets, net->stats.tx_packets,
+ net->stats.rx_errors, net->stats.tx_errors);
+
+- /* to not race resume */
+- pm = usb_autopm_get_interface(dev->intf);
+ /* allow minidriver to stop correctly (wireless devices to turn off
+ * radio etc) */
+ if (info->stop) {
+@@ -817,9 +818,6 @@
+ dev->flags = 0;
+ del_timer_sync (&dev->delay);
+ tasklet_kill (&dev->bh);
+- if (!pm)
+- usb_autopm_put_interface(dev->intf);
+-
+ if (info->manage_power &&
+ !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags))
+ info->manage_power(dev, 0);
+@@ -1440,12 +1438,11 @@
+ /* restart RX again after disabling due to high error rate */
+ clear_bit(EVENT_RX_KILL, &dev->flags);
+
+- /* waiting for all pending urbs to complete?
+- * only then can we forgo submitting anew
+- */
+- if (waitqueue_active(&dev->wait)) {
+- if (dev->txq.qlen + dev->rxq.qlen + dev->done.qlen == 0)
+- wake_up_all(&dev->wait);
++ // waiting for all pending urbs to complete?
++ if (dev->wait) {
++ if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
++ wake_up (dev->wait);
++ }
+
+ // or are we maybe short a few urbs?
+ } else if (netif_running (dev->net) &&
+@@ -1584,7 +1581,6 @@
+ dev->driver_name = name;
+ dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
+ | NETIF_MSG_PROBE | NETIF_MSG_LINK);
+- init_waitqueue_head(&dev->wait);
+ skb_queue_head_init (&dev->rxq);
+ skb_queue_head_init (&dev->txq);
+ skb_queue_head_init (&dev->done);
+@@ -1796,10 +1792,9 @@
+ spin_unlock_irq(&dev->txq.lock);
+
+ if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+- /* handle remote wakeup ASAP
+- * we cannot race against stop
+- */
+- if (netif_device_present(dev->net) &&
++ /* handle remote wakeup ASAP */
++ if (!dev->wait &&
++ netif_device_present(dev->net) &&
+ !timer_pending(&dev->delay) &&
+ !test_bit(EVENT_RX_HALT, &dev->flags))
+ rx_alloc_submit(dev, GFP_NOIO);
+diff -Nur linux-3.12.18/drivers/net/vxlan.c linux-rpi/drivers/net/vxlan.c
+--- linux-3.12.18/drivers/net/vxlan.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/vxlan.c 2014-04-24 16:04:37.631103100 +0200
+@@ -781,9 +781,6 @@
+ if (err)
+ return err;
+
+- if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family)
+- return -EAFNOSUPPORT;
+-
+ spin_lock_bh(&vxlan->hash_lock);
+ err = vxlan_fdb_create(vxlan, addr, &ip, ndm->ndm_state, flags,
+ port, vni, ifindex, ndm->ndm_flags);
+@@ -1215,9 +1212,6 @@
+
+ neigh_release(n);
+
+- if (reply == NULL)
+- goto out;
+-
+ skb_reset_mac_header(reply);
+ __skb_pull(reply, skb_network_offset(reply));
+ reply->ip_summed = CHECKSUM_UNNECESSARY;
+@@ -1239,103 +1233,15 @@
+ }
+
+ #if IS_ENABLED(CONFIG_IPV6)
+-
+-static struct sk_buff *vxlan_na_create(struct sk_buff *request,
+- struct neighbour *n, bool isrouter)
+-{
+- struct net_device *dev = request->dev;
+- struct sk_buff *reply;
+- struct nd_msg *ns, *na;
+- struct ipv6hdr *pip6;
+- u8 *daddr;
+- int na_olen = 8; /* opt hdr + ETH_ALEN for target */
+- int ns_olen;
+- int i, len;
+-
+- if (dev == NULL)
+- return NULL;
+-
+- len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
+- sizeof(*na) + na_olen + dev->needed_tailroom;
+- reply = alloc_skb(len, GFP_ATOMIC);
+- if (reply == NULL)
+- return NULL;
+-
+- reply->protocol = htons(ETH_P_IPV6);
+- reply->dev = dev;
+- skb_reserve(reply, LL_RESERVED_SPACE(request->dev));
+- skb_push(reply, sizeof(struct ethhdr));
+- skb_set_mac_header(reply, 0);
+-
+- ns = (struct nd_msg *)skb_transport_header(request);
+-
+- daddr = eth_hdr(request)->h_source;
+- ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns);
+- for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
+- if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
+- daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
+- break;
+- }
+- }
+-
+- /* Ethernet header */
+- memcpy(eth_hdr(reply)->h_dest, daddr, ETH_ALEN);
+- memcpy(eth_hdr(reply)->h_source, n->ha, ETH_ALEN);
+- eth_hdr(reply)->h_proto = htons(ETH_P_IPV6);
+- reply->protocol = htons(ETH_P_IPV6);
+-
+- skb_pull(reply, sizeof(struct ethhdr));
+- skb_set_network_header(reply, 0);
+- skb_put(reply, sizeof(struct ipv6hdr));
+-
+- /* IPv6 header */
+-
+- pip6 = ipv6_hdr(reply);
+- memset(pip6, 0, sizeof(struct ipv6hdr));
+- pip6->version = 6;
+- pip6->priority = ipv6_hdr(request)->priority;
+- pip6->nexthdr = IPPROTO_ICMPV6;
+- pip6->hop_limit = 255;
+- pip6->daddr = ipv6_hdr(request)->saddr;
+- pip6->saddr = *(struct in6_addr *)n->primary_key;
+-
+- skb_pull(reply, sizeof(struct ipv6hdr));
+- skb_set_transport_header(reply, 0);
+-
+- na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen);
+-
+- /* Neighbor Advertisement */
+- memset(na, 0, sizeof(*na)+na_olen);
+- na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
+- na->icmph.icmp6_router = isrouter;
+- na->icmph.icmp6_override = 1;
+- na->icmph.icmp6_solicited = 1;
+- na->target = ns->target;
+- memcpy(&na->opt[2], n->ha, ETH_ALEN);
+- na->opt[0] = ND_OPT_TARGET_LL_ADDR;
+- na->opt[1] = na_olen >> 3;
+-
+- na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr,
+- &pip6->daddr, sizeof(*na)+na_olen, IPPROTO_ICMPV6,
+- csum_partial(na, sizeof(*na)+na_olen, 0));
+-
+- pip6->payload_len = htons(sizeof(*na)+na_olen);
+-
+- skb_push(reply, sizeof(struct ipv6hdr));
+-
+- reply->ip_summed = CHECKSUM_UNNECESSARY;
+-
+- return reply;
+-}
+-
+ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
+ {
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+- struct nd_msg *msg;
++ struct neighbour *n;
++ union vxlan_addr ipa;
+ const struct ipv6hdr *iphdr;
+ const struct in6_addr *saddr, *daddr;
+- struct neighbour *n;
+- struct inet6_dev *in6_dev;
++ struct nd_msg *msg;
++ struct inet6_dev *in6_dev = NULL;
+
+ in6_dev = __in6_dev_get(dev);
+ if (!in6_dev)
+@@ -1348,20 +1254,19 @@
+ saddr = &iphdr->saddr;
+ daddr = &iphdr->daddr;
+
++ if (ipv6_addr_loopback(daddr) ||
++ ipv6_addr_is_multicast(daddr))
++ goto out;
++
+ msg = (struct nd_msg *)skb_transport_header(skb);
+ if (msg->icmph.icmp6_code != 0 ||
+ msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
+ goto out;
+
+- if (ipv6_addr_loopback(daddr) ||
+- ipv6_addr_is_multicast(&msg->target))
+- goto out;
+-
+- n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev);
++ n = neigh_lookup(ipv6_stub->nd_tbl, daddr, dev);
+
+ if (n) {
+ struct vxlan_fdb *f;
+- struct sk_buff *reply;
+
+ if (!(n->nud_state & NUD_CONNECTED)) {
+ neigh_release(n);
+@@ -1375,23 +1280,13 @@
+ goto out;
+ }
+
+- reply = vxlan_na_create(skb, n,
+- !!(f ? f->flags & NTF_ROUTER : 0));
+-
++ ipv6_stub->ndisc_send_na(dev, n, saddr, &msg->target,
++ !!in6_dev->cnf.forwarding,
++ true, false, false);
+ neigh_release(n);
+-
+- if (reply == NULL)
+- goto out;
+-
+- if (netif_rx_ni(reply) == NET_RX_DROP)
+- dev->stats.rx_dropped++;
+-
+ } else if (vxlan->flags & VXLAN_F_L3MISS) {
+- union vxlan_addr ipa = {
+- .sin6.sin6_addr = msg->target,
+- .sa.sa_family = AF_INET6,
+- };
+-
++ ipa.sin6.sin6_addr = *daddr;
++ ipa.sa.sa_family = AF_INET6;
+ vxlan_ip_miss(dev, &ipa);
+ }
+
+@@ -2488,10 +2383,9 @@
+ vni = nla_get_u32(data[IFLA_VXLAN_ID]);
+ dst->remote_vni = vni;
+
+- /* Unless IPv6 is explicitly requested, assume IPv4 */
+- dst->remote_ip.sa.sa_family = AF_INET;
+ if (data[IFLA_VXLAN_GROUP]) {
+ dst->remote_ip.sin.sin_addr.s_addr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
++ dst->remote_ip.sa.sa_family = AF_INET;
+ } else if (data[IFLA_VXLAN_GROUP6]) {
+ if (!IS_ENABLED(CONFIG_IPV6))
+ return -EPFNOSUPPORT;
+diff -Nur linux-3.12.18/drivers/net/xen-netback/common.h linux-rpi/drivers/net/xen-netback/common.h
+--- linux-3.12.18/drivers/net/xen-netback/common.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/xen-netback/common.h 2014-04-24 16:04:37.763104376 +0200
+@@ -102,11 +102,6 @@
+ domid_t domid;
+ unsigned int handle;
+
+- /* Is this interface disabled? True when backend discovers
+- * frontend is rogue.
+- */
+- bool disabled;
+-
+ /* Use NAPI for guest TX */
+ struct napi_struct napi;
+ /* When feature-split-event-channels = 0, tx_irq = rx_irq. */
+diff -Nur linux-3.12.18/drivers/net/xen-netback/interface.c linux-rpi/drivers/net/xen-netback/interface.c
+--- linux-3.12.18/drivers/net/xen-netback/interface.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/xen-netback/interface.c 2014-04-24 16:04:37.763104376 +0200
+@@ -66,15 +66,6 @@
+ struct xenvif *vif = container_of(napi, struct xenvif, napi);
+ int work_done;
+
+- /* This vif is rogue, we pretend we've there is nothing to do
+- * for this vif to deschedule it from NAPI. But this interface
+- * will be turned off in thread context later.
+- */
+- if (unlikely(vif->disabled)) {
+- napi_complete(napi);
+- return 0;
+- }
+-
+ work_done = xenvif_tx_action(vif, budget);
+
+ if (work_done < budget) {
+@@ -318,8 +309,6 @@
+ vif->csum = 1;
+ vif->dev = dev;
+
+- vif->disabled = false;
+-
+ vif->credit_bytes = vif->remaining_credit = ~0UL;
+ vif->credit_usec = 0UL;
+ init_timer(&vif->credit_timeout);
+diff -Nur linux-3.12.18/drivers/net/xen-netback/netback.c linux-rpi/drivers/net/xen-netback/netback.c
+--- linux-3.12.18/drivers/net/xen-netback/netback.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/net/xen-netback/netback.c 2014-04-24 16:04:37.763104376 +0200
+@@ -206,8 +206,8 @@
+ * into multiple copies tend to give large frags their
+ * own buffers as before.
+ */
+- BUG_ON(size > MAX_BUFFER_OFFSET);
+- if ((offset + size > MAX_BUFFER_OFFSET) && offset && !head)
++ if ((offset + size > MAX_BUFFER_OFFSET) &&
++ (size <= MAX_BUFFER_OFFSET) && offset && !head)
+ return true;
+
+ return false;
+@@ -731,8 +731,7 @@
+ static void xenvif_fatal_tx_err(struct xenvif *vif)
+ {
+ netdev_err(vif->dev, "fatal error; disabling device\n");
+- vif->disabled = true;
+- xenvif_kick_thread(vif);
++ xenvif_carrier_off(vif);
+ }
+
+ static int xenvif_count_requests(struct xenvif *vif,
+@@ -1243,7 +1242,7 @@
+ vif->tx.sring->req_prod, vif->tx.req_cons,
+ XEN_NETIF_TX_RING_SIZE);
+ xenvif_fatal_tx_err(vif);
+- break;
++ continue;
+ }
+
+ RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do);
+@@ -1643,18 +1642,7 @@
+ while (!kthread_should_stop()) {
+ wait_event_interruptible(vif->wq,
+ rx_work_todo(vif) ||
+- vif->disabled ||
+ kthread_should_stop());
+-
+- /* This frontend is found to be rogue, disable it in
+- * kthread context. Currently this is only set when
+- * netback finds out frontend sends malformed packet,
+- * but we cannot disable the interface in softirq
+- * context so we defer it here.
+- */
+- if (unlikely(vif->disabled && netif_carrier_ok(vif->dev)))
+- xenvif_carrier_off(vif);
+-
+ if (kthread_should_stop())
+ break;
+
+diff -Nur linux-3.12.18/drivers/pci/host/pci-mvebu.c linux-rpi/drivers/pci/host/pci-mvebu.c
+--- linux-3.12.18/drivers/pci/host/pci-mvebu.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/pci/host/pci-mvebu.c 2014-04-24 16:04:37.847105188 +0200
+@@ -866,23 +866,11 @@
+ continue;
+ }
+
+- port->clk = of_clk_get_by_name(child, NULL);
+- if (IS_ERR(port->clk)) {
+- dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
+- port->port, port->lane);
+- continue;
+- }
+-
+- ret = clk_prepare_enable(port->clk);
+- if (ret)
+- continue;
+-
+ port->base = mvebu_pcie_map_registers(pdev, child, port);
+ if (IS_ERR(port->base)) {
+ dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
+ port->port, port->lane);
+ port->base = NULL;
+- clk_disable_unprepare(port->clk);
+ continue;
+ }
+
+@@ -898,9 +886,22 @@
+ port->port, port->lane);
+ }
+
++ port->clk = of_clk_get_by_name(child, NULL);
++ if (IS_ERR(port->clk)) {
++ dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
++ port->port, port->lane);
++ iounmap(port->base);
++ port->haslink = 0;
++ continue;
++ }
++
+ port->dn = child;
++
++ clk_prepare_enable(port->clk);
+ spin_lock_init(&port->conf_lock);
++
+ mvebu_sw_pci_bridge_init(port);
++
+ i++;
+ }
+
+diff -Nur linux-3.12.18/drivers/spi/Kconfig linux-rpi/drivers/spi/Kconfig
+--- linux-3.12.18/drivers/spi/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/spi/Kconfig 2014-04-24 16:04:38.875115127 +0200
@@ -85,6 +85,14 @@
is for the regular SPI controller. Slave mode operation is not also
not supported.
@@ -33245,9 +33975,9 @@ diff -Nur linux-3.12.13/drivers/spi/Kconfig linux-raspberry-pi/drivers/spi/Kconf
config SPI_BFIN5XX
tristate "SPI controller driver for ADI Blackfin5xx"
depends on BLACKFIN && !BF60x
-diff -Nur linux-3.12.13/drivers/spi/Makefile linux-raspberry-pi/drivers/spi/Makefile
---- linux-3.12.13/drivers/spi/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/spi/Makefile 2014-03-11 17:51:25.000000000 +0100
+diff -Nur linux-3.12.18/drivers/spi/Makefile linux-rpi/drivers/spi/Makefile
+--- linux-3.12.18/drivers/spi/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/spi/Makefile 2014-04-24 16:04:38.875115127 +0200
@@ -18,6 +18,7 @@
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
@@ -33256,9 +33986,9 @@ diff -Nur linux-3.12.13/drivers/spi/Makefile linux-raspberry-pi/drivers/spi/Make
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
-diff -Nur linux-3.12.13/drivers/spi/spi-bcm2708.c linux-raspberry-pi/drivers/spi/spi-bcm2708.c
---- linux-3.12.13/drivers/spi/spi-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/spi/spi-bcm2708.c 2014-03-11 17:33:04.000000000 +0100
+diff -Nur linux-3.12.18/drivers/spi/spi-bcm2708.c linux-rpi/drivers/spi/spi-bcm2708.c
+--- linux-3.12.18/drivers/spi/spi-bcm2708.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/spi/spi-bcm2708.c 2014-04-24 15:35:03.781561409 +0200
@@ -0,0 +1,626 @@
+/*
+ * Driver for Broadcom BCM2708 SPI Controllers
@@ -33886,9 +34616,9 @@ diff -Nur linux-3.12.13/drivers/spi/spi-bcm2708.c linux-raspberry-pi/drivers/spi
+MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
-diff -Nur linux-3.12.13/drivers/staging/media/lirc/Kconfig linux-raspberry-pi/drivers/staging/media/lirc/Kconfig
---- linux-3.12.13/drivers/staging/media/lirc/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/staging/media/lirc/Kconfig 2014-03-11 17:33:05.000000000 +0100
+diff -Nur linux-3.12.18/drivers/staging/media/lirc/Kconfig linux-rpi/drivers/staging/media/lirc/Kconfig
+--- linux-3.12.18/drivers/staging/media/lirc/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/staging/media/lirc/Kconfig 2014-04-24 15:35:03.925563013 +0200
@@ -38,6 +38,12 @@
help
Driver for Homebrew Parallel Port Receivers
@@ -33902,9 +34632,9 @@ diff -Nur linux-3.12.13/drivers/staging/media/lirc/Kconfig linux-raspberry-pi/dr
config LIRC_SASEM
tristate "Sasem USB IR Remote"
depends on LIRC && USB
-diff -Nur linux-3.12.13/drivers/staging/media/lirc/lirc_rpi.c linux-raspberry-pi/drivers/staging/media/lirc/lirc_rpi.c
---- linux-3.12.13/drivers/staging/media/lirc/lirc_rpi.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/staging/media/lirc/lirc_rpi.c 2014-03-11 17:33:05.000000000 +0100
+diff -Nur linux-3.12.18/drivers/staging/media/lirc/lirc_rpi.c linux-rpi/drivers/staging/media/lirc/lirc_rpi.c
+--- linux-3.12.18/drivers/staging/media/lirc/lirc_rpi.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/staging/media/lirc/lirc_rpi.c 2014-04-24 15:35:03.925563013 +0200
@@ -0,0 +1,693 @@
+/*
+ * lirc_rpi.c
@@ -33988,8 +34718,8 @@ diff -Nur linux-3.12.13/drivers/staging/media/lirc/lirc_rpi.c linux-raspberry-pi
+static void send_space(long length);
+static void lirc_rpi_exit(void);
+
-+int valid_gpio_pins[] = { 0, 1, 4, 8, 7, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23,
-+ 24, 25 };
++int valid_gpio_pins[] = { 0, 1, 2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21,
++ 22, 23, 24, 25 ,27, 28, 29, 30, 31 };
+
+static struct platform_device *lirc_rpi_dev;
+static struct timeval lasttv = { 0, 0 };
@@ -34599,9 +35329,9 @@ diff -Nur linux-3.12.13/drivers/staging/media/lirc/lirc_rpi.c linux-raspberry-pi
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");
-diff -Nur linux-3.12.13/drivers/staging/media/lirc/Makefile linux-raspberry-pi/drivers/staging/media/lirc/Makefile
---- linux-3.12.13/drivers/staging/media/lirc/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/staging/media/lirc/Makefile 2014-03-11 17:33:05.000000000 +0100
+diff -Nur linux-3.12.18/drivers/staging/media/lirc/Makefile linux-rpi/drivers/staging/media/lirc/Makefile
+--- linux-3.12.18/drivers/staging/media/lirc/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/staging/media/lirc/Makefile 2014-04-24 15:35:03.925563013 +0200
@@ -7,6 +7,7 @@
obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o
obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
@@ -34610,9 +35340,9 @@ diff -Nur linux-3.12.13/drivers/staging/media/lirc/Makefile linux-raspberry-pi/d
obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o
obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o
obj-$(CONFIG_LIRC_SIR) += lirc_sir.o
-diff -Nur linux-3.12.13/drivers/thermal/bcm2835-thermal.c linux-raspberry-pi/drivers/thermal/bcm2835-thermal.c
---- linux-3.12.13/drivers/thermal/bcm2835-thermal.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/thermal/bcm2835-thermal.c 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/thermal/bcm2835-thermal.c linux-rpi/drivers/thermal/bcm2835-thermal.c
+--- linux-3.12.18/drivers/thermal/bcm2835-thermal.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/thermal/bcm2835-thermal.c 2014-04-24 15:35:04.089564840 +0200
@@ -0,0 +1,184 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -34798,9 +35528,9 @@ diff -Nur linux-3.12.13/drivers/thermal/bcm2835-thermal.c linux-raspberry-pi/dri
+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
+
+module_platform_driver(bcm2835_thermal_driver);
-diff -Nur linux-3.12.13/drivers/thermal/Kconfig linux-raspberry-pi/drivers/thermal/Kconfig
---- linux-3.12.13/drivers/thermal/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/thermal/Kconfig 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/thermal/Kconfig linux-rpi/drivers/thermal/Kconfig
+--- linux-3.12.18/drivers/thermal/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/thermal/Kconfig 2014-04-24 16:04:39.655122669 +0200
@@ -181,6 +181,12 @@
enforce idle time which results in more package C-state residency. The
user interface is exposed via generic thermal framework.
@@ -34814,9 +35544,9 @@ diff -Nur linux-3.12.13/drivers/thermal/Kconfig linux-raspberry-pi/drivers/therm
config X86_PKG_TEMP_THERMAL
tristate "X86 package temperature thermal driver"
depends on X86_THERMAL_VECTOR
-diff -Nur linux-3.12.13/drivers/thermal/Makefile linux-raspberry-pi/drivers/thermal/Makefile
---- linux-3.12.13/drivers/thermal/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/thermal/Makefile 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/thermal/Makefile linux-rpi/drivers/thermal/Makefile
+--- linux-3.12.18/drivers/thermal/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/thermal/Makefile 2014-04-24 16:04:39.655122669 +0200
@@ -27,5 +27,6 @@
obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
@@ -34824,9 +35554,9 @@ diff -Nur linux-3.12.13/drivers/thermal/Makefile linux-raspberry-pi/drivers/ther
+obj-$(CONFIG_THERMAL_BCM2835) += bcm2835-thermal.o
obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
-diff -Nur linux-3.12.13/drivers/tty/serial/amba-pl011.c linux-raspberry-pi/drivers/tty/serial/amba-pl011.c
---- linux-3.12.13/drivers/tty/serial/amba-pl011.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/tty/serial/amba-pl011.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/tty/serial/amba-pl011.c linux-rpi/drivers/tty/serial/amba-pl011.c
+--- linux-3.12.18/drivers/tty/serial/amba-pl011.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/tty/serial/amba-pl011.c 2014-04-24 16:04:39.667122784 +0200
@@ -84,7 +84,7 @@
static unsigned int get_fifosize_arm(struct amba_device *dev)
@@ -34836,9 +35566,9 @@ diff -Nur linux-3.12.13/drivers/tty/serial/amba-pl011.c linux-raspberry-pi/drive
}
static struct vendor_data vendor_arm = {
-diff -Nur linux-3.12.13/drivers/usb/core/generic.c linux-raspberry-pi/drivers/usb/core/generic.c
---- linux-3.12.13/drivers/usb/core/generic.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/core/generic.c 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/core/generic.c linux-rpi/drivers/usb/core/generic.c
+--- linux-3.12.18/drivers/usb/core/generic.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/usb/core/generic.c 2014-04-24 15:35:04.137565375 +0200
@@ -152,6 +152,7 @@
dev_warn(&udev->dev,
"no configuration chosen from %d choice%s\n",
@@ -34847,9 +35577,9 @@ diff -Nur linux-3.12.13/drivers/usb/core/generic.c linux-raspberry-pi/drivers/us
}
return i;
}
-diff -Nur linux-3.12.13/drivers/usb/core/message.c linux-raspberry-pi/drivers/usb/core/message.c
---- linux-3.12.13/drivers/usb/core/message.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/core/message.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/core/message.c linux-rpi/drivers/usb/core/message.c
+--- linux-3.12.18/drivers/usb/core/message.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/usb/core/message.c 2014-04-24 16:04:39.763123712 +0200
@@ -1885,6 +1885,85 @@
if (cp->string == NULL &&
!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
@@ -34936,9 +35666,9 @@ diff -Nur linux-3.12.13/drivers/usb/core/message.c linux-raspberry-pi/drivers/us
/* Now that the interfaces are installed, re-enable LPM. */
usb_unlocked_enable_lpm(dev);
-diff -Nur linux-3.12.13/drivers/usb/core/otg_whitelist.h linux-raspberry-pi/drivers/usb/core/otg_whitelist.h
---- linux-3.12.13/drivers/usb/core/otg_whitelist.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/core/otg_whitelist.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/core/otg_whitelist.h linux-rpi/drivers/usb/core/otg_whitelist.h
+--- linux-3.12.18/drivers/usb/core/otg_whitelist.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/usb/core/otg_whitelist.h 2014-04-24 16:04:39.763123712 +0200
@@ -19,33 +19,82 @@
static struct usb_device_id whitelist_table [] = {
@@ -35154,9 +35884,9 @@ diff -Nur linux-3.12.13/drivers/usb/core/otg_whitelist.h linux-raspberry-pi/driv
#endif
}
-diff -Nur linux-3.12.13/drivers/usb/gadget/file_storage.c linux-raspberry-pi/drivers/usb/gadget/file_storage.c
---- linux-3.12.13/drivers/usb/gadget/file_storage.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/gadget/file_storage.c 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/gadget/file_storage.c linux-rpi/drivers/usb/gadget/file_storage.c
+--- linux-3.12.18/drivers/usb/gadget/file_storage.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/gadget/file_storage.c 2014-04-24 15:35:04.153565553 +0200
@@ -0,0 +1,3676 @@
+/*
+ * file_storage.c -- File-backed USB Storage Gadget, for USB development
@@ -38834,9 +39564,9 @@ diff -Nur linux-3.12.13/drivers/usb/gadget/file_storage.c linux-raspberry-pi/dri
+ kref_put(&fsg->ref, fsg_release);
+}
+module_exit(fsg_cleanup);
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/changes.txt linux-raspberry-pi/drivers/usb/host/dwc_common_port/changes.txt
---- linux-3.12.13/drivers/usb/host/dwc_common_port/changes.txt 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/changes.txt 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/changes.txt linux-rpi/drivers/usb/host/dwc_common_port/changes.txt
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/changes.txt 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/changes.txt 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,174 @@
+
+dwc_read_reg32() and friends now take an additional parameter, a pointer to an
@@ -39012,9 +39742,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/changes.txt linux-raspb
+A DWC_LIBMODULE #define has also been added. If this is not defined, then the
+module code in dwc_common_linux.c is not compiled in. This allows linking the
+library code directly into a driver module, instead of as a standalone module.
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-raspberry-pi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
---- linux-3.12.13/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-rpi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/doc/doxygen.cfg 2014-04-24 16:04:39.811124176 +0200
@@ -0,0 +1,270 @@
+# Doxyfile 1.4.5
+
@@ -39286,9 +40016,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/doc/doxygen.cfg linux-r
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_cc.c
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_cc.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_cc.c
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_cc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_cc.c 2014-04-24 16:04:39.811124176 +0200
@@ -0,0 +1,532 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $
@@ -39822,9 +40552,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.c linux-raspberr
+}
+
+#endif /* DWC_CCLIB */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_cc.h
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_cc.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_cc.h
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_cc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_cc.h 2014-04-24 16:04:39.811124176 +0200
@@ -0,0 +1,224 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $
@@ -40050,9 +40780,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_cc.h linux-raspberr
+#endif
+
+#endif /* _DWC_CC_H_ */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,1308 @@
+#include "dwc_os.h"
+#include "dwc_list.h"
@@ -41362,10 +42092,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c linux
+{
+ return wq->pending;
+}
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_linux.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_linux.c
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_linux.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_linux.c 2014-03-11 17:33:06.000000000 +0100
-@@ -0,0 +1,1431 @@
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_linux.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_linux.c
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_linux.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_linux.c 2014-04-24 16:04:39.811124176 +0200
+@@ -0,0 +1,1432 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
@@ -41953,6 +42683,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu
+ local_irq_save(flags);
+ local_fiq_disable();
+ writel((readl(reg) & ~clear_mask) | set_mask, reg);
++ local_fiq_enable();
+ local_irq_restore(flags);
+}
+
@@ -42797,9 +43528,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu
+MODULE_LICENSE ("GPL");
+
+#endif /* DWC_LIBMODULE */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,1275 @@
+#include "dwc_os.h"
+#include "dwc_list.h"
@@ -44076,9 +44807,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c linux
+{
+ return wq->pending;
+}
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_crypto.c
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_crypto.c 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.c
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_crypto.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.c 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,308 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
@@ -44388,9 +45119,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.c linux-rasp
+}
+
+#endif /* DWC_CRYPTOLIB */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_crypto.h
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_crypto.h 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.h
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_crypto.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_crypto.h 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,111 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $
@@ -44503,9 +45234,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_crypto.h linux-rasp
+#endif
+
+#endif /* _DWC_CRYPTO_H_ */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_dh.c
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_dh.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_dh.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_dh.c
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_dh.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_dh.c 2014-04-24 16:04:39.811124176 +0200
@@ -0,0 +1,291 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $
@@ -44798,9 +45529,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.c linux-raspberr
+#endif /* !CONFIG_MACH_IPMATE */
+
+#endif /* DWC_CRYPTOLIB */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_dh.h
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_dh.h 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_dh.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_dh.h
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_dh.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_dh.h 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,106 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.h $
@@ -44908,9 +45639,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_dh.h linux-raspberr
+#endif
+
+#endif /* _DWC_DH_H_ */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_list.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_list.h
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_list.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_list.h 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_list.h
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_list.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_list.h 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,594 @@
+/* $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $ */
+/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
@@ -45506,9 +46237,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_list.h linux-raspbe
+#endif
+
+#endif /* _DWC_LIST_H_ */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_mem.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_mem.c
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_mem.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_mem.c 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_mem.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_mem.c
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_mem.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_mem.c 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,245 @@
+/* Memory Debugging */
+#ifdef DWC_DEBUG_MEMORY
@@ -45755,9 +46486,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_mem.c linux-raspber
+}
+
+#endif /* DWC_DEBUG_MEMORY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_modpow.c
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_modpow.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.c
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_modpow.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.c 2014-04-24 16:04:39.811124176 +0200
@@ -0,0 +1,636 @@
+/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows.
+ *
@@ -46395,9 +47126,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.c linux-rasp
+#endif /* CONFIG_MACH_IPMATE */
+
+#endif /*DWC_CRYPTOLIB */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_modpow.h
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_modpow.h 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.h
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_modpow.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_modpow.h 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,34 @@
+/*
+ * dwc_modpow.h
@@ -46433,9 +47164,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_modpow.h linux-rasp
+#endif
+
+#endif /* _LINUX_BIGNUM_H */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_notifier.c
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_notifier.c 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.c
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_notifier.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.c 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,319 @@
+#ifdef DWC_NOTIFYLIB
+
@@ -46756,9 +47487,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-ra
+}
+
+#endif /* DWC_NOTIFYLIB */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_notifier.h
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_notifier.h 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.h
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_notifier.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_notifier.h 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,122 @@
+
+#ifndef __DWC_NOTIFIER_H__
@@ -46882,9 +47613,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-ra
+#endif
+
+#endif /* __DWC_NOTIFIER_H__ */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_os.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_os.h
---- linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_os.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/dwc_os.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi/drivers/usb/host/dwc_common_port/dwc_os.h
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/dwc_os.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/dwc_os.h 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,1262 @@
+/* =========================================================================
+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $
@@ -48148,9 +48879,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/dwc_os.h linux-raspberr
+#endif
+
+#endif /* _DWC_OS_H_ */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile
---- linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile linux-rpi/drivers/usb/host/dwc_common_port/Makefile
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/Makefile 2014-04-24 16:04:39.811124176 +0200
@@ -0,0 +1,58 @@
+#
+# Makefile for DWC_common library
@@ -48158,16 +48889,16 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile linux-raspberr
+
+ifneq ($(KERNELRELEASE),)
+
-+EXTRA_CFLAGS += -DDWC_LINUX
-+#EXTRA_CFLAGS += -DDEBUG
-+#EXTRA_CFLAGS += -DDWC_DEBUG_REGS
-+#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY
++ccflags-y += -DDWC_LINUX
++#ccflags-y += -DDEBUG
++#ccflags-y += -DDWC_DEBUG_REGS
++#ccflags-y += -DDWC_DEBUG_MEMORY
+
-+EXTRA_CFLAGS += -DDWC_LIBMODULE
-+EXTRA_CFLAGS += -DDWC_CCLIB
-+#EXTRA_CFLAGS += -DDWC_CRYPTOLIB
-+EXTRA_CFLAGS += -DDWC_NOTIFYLIB
-+EXTRA_CFLAGS += -DDWC_UTFLIB
++ccflags-y += -DDWC_LIBMODULE
++ccflags-y += -DDWC_CCLIB
++#ccflags-y += -DDWC_CRYPTOLIB
++ccflags-y += -DDWC_NOTIFYLIB
++ccflags-y += -DDWC_UTFLIB
+
+obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o
+dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
@@ -48178,8 +48909,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile linux-raspberr
+kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
+
+ifneq ($(kernrel3),2.6.20)
-+# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually
-+EXTRA_CFLAGS += $(CPPFLAGS)
++# grayg - I only know that we use ccflags-y in 2.6.31 actually
++ccflags-y += $(CPPFLAGS)
+endif
+
+else
@@ -48210,9 +48941,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile linux-raspberr
+
+clean:
+ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile.fbsd
---- linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.fbsd 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile.fbsd 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-rpi/drivers/usb/host/dwc_common_port/Makefile.fbsd
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile.fbsd 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/Makefile.fbsd 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,17 @@
+CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include
+CFLAGS += -DDWC_FREEBSD
@@ -48231,25 +48962,25 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.fbsd linux-ras
+ dwc_common_fbsd.c dwc_mem.c
+
+.include <bsd.kmod.mk>
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.linux linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile.linux
---- linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.linux 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/Makefile.linux 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile.linux linux-rpi/drivers/usb/host/dwc_common_port/Makefile.linux
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/Makefile.linux 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/Makefile.linux 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,49 @@
+#
+# Makefile for DWC_common library
+#
+ifneq ($(KERNELRELEASE),)
+
-+EXTRA_CFLAGS += -DDWC_LINUX
-+#EXTRA_CFLAGS += -DDEBUG
-+#EXTRA_CFLAGS += -DDWC_DEBUG_REGS
-+#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY
++ccflags-y += -DDWC_LINUX
++#ccflags-y += -DDEBUG
++#ccflags-y += -DDWC_DEBUG_REGS
++#ccflags-y += -DDWC_DEBUG_MEMORY
+
-+EXTRA_CFLAGS += -DDWC_LIBMODULE
-+EXTRA_CFLAGS += -DDWC_CCLIB
-+EXTRA_CFLAGS += -DDWC_CRYPTOLIB
-+EXTRA_CFLAGS += -DDWC_NOTIFYLIB
-+EXTRA_CFLAGS += -DDWC_UTFLIB
++ccflags-y += -DDWC_LIBMODULE
++ccflags-y += -DDWC_CCLIB
++ccflags-y += -DDWC_CRYPTOLIB
++ccflags-y += -DDWC_NOTIFYLIB
++ccflags-y += -DDWC_UTFLIB
+
+obj-m := dwc_common_port_lib.o
+dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \
@@ -48284,9 +49015,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/Makefile.linux linux-ra
+
+clean:
+ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/usb.h linux-raspberry-pi/drivers/usb/host/dwc_common_port/usb.h
---- linux-3.12.13/drivers/usb/host/dwc_common_port/usb.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_common_port/usb.h 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_common_port/usb.h linux-rpi/drivers/usb/host/dwc_common_port/usb.h
+--- linux-3.12.18/drivers/usb/host/dwc_common_port/usb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_common_port/usb.h 2014-04-24 15:35:04.169565731 +0200
@@ -0,0 +1,946 @@
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -49234,9 +49965,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_common_port/usb.h linux-raspberry-p
+#endif
+
+#endif /* _USB_H_ */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-raspberry-pi/drivers/usb/host/dwc_otg/doc/doxygen.cfg
---- linux-3.12.13/drivers/usb/host/dwc_otg/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/doc/doxygen.cfg 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-rpi/drivers/usb/host/dwc_otg/doc/doxygen.cfg
+--- linux-3.12.18/drivers/usb/host/dwc_otg/doc/doxygen.cfg 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/doc/doxygen.cfg 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,224 @@
+# Doxyfile 1.3.9.1
+
@@ -49462,9 +50193,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/doc/doxygen.cfg linux-raspberry
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dummy_audio.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dummy_audio.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dummy_audio.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dummy_audio.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dummy_audio.c linux-rpi/drivers/usb/host/dwc_otg/dummy_audio.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dummy_audio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dummy_audio.c 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,1575 @@
+/*
+ * zero.c -- Gadget Zero, for USB development
@@ -51041,9 +51772,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dummy_audio.c linux-raspberry-p
+ remove_proc_entry("isoc_test", NULL);
+}
+module_exit (cleanup);
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_cfi_common.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_cfi_common.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_cfi_common.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-rpi/drivers/usb/host/dwc_otg/dwc_cfi_common.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_cfi_common.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_cfi_common.h 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,142 @@
+/* ==========================================================================
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
@@ -51187,9 +51918,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-raspberr
+typedef struct cfi_string cfi_string_t;
+
+#endif
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_adp.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_adp.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_adp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.c 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,854 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $
@@ -52045,9 +52776,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.c linux-raspberry-p
+#endif
+ return 1;
+}
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_adp.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_adp.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_adp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_adp.h 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,80 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $
@@ -52129,9 +52860,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_adp.h linux-raspberry-p
+extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if);
+
+#endif //__DWC_OTG_ADP_H__
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_attr.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_attr.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_attr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.c 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,1210 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $
@@ -53343,9 +54074,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-raspberry-
+ device_remove_file(&dev->dev, &dev_attr_sleep_status);
+#endif
+}
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_attr.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_attr.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_attr.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_attr.h 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,89 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $
@@ -53436,9 +54167,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-raspberry-
+#endif
+ );
+#endif
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,1876 @@
+/* ==========================================================================
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
@@ -55316,9 +56047,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-raspberry-p
+}
+
+#endif //DWC_UTE_CFI
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,320 @@
+/* ==========================================================================
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
@@ -55640,9 +56371,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-raspberry-p
+int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl);
+
+#endif /* (__DWC_OTG_CFI_H__) */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.c 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,7151 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $
@@ -62795,9 +63526,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-raspberry-p
+ dwc_otg_pcd_start_srp_timer(core_if);
+ return;
+}
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil.h 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,1464 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $
@@ -64263,10 +64994,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-raspberry-p
+//////////////////////////////////////////////////////////////////////
+
+#endif
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,1588 @@
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 2014-04-24 16:04:39.815124215 +0200
+@@ -0,0 +1,1595 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $
+ * $Revision: #32 $
@@ -64314,7 +65045,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe
+#include "dwc_otg_driver.h"
+#include "dwc_otg_pcd.h"
+#include "dwc_otg_hcd.h"
-+#include "dwc_otg_mphi_fix.h"
+
+#ifdef DEBUG
+inline const char *op_state_str(dwc_otg_core_if_t * core_if)
@@ -65588,7 +66318,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe
+/**
+ * This function returns the Core Interrupt register.
+ */
-+static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk)
++static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk, dwc_otg_hcd_t *hcd)
+{
+ gahbcfg_data_t gahbcfg = {.d32 = 0 };
+ gintsts_data_t gintsts;
@@ -65614,16 +66344,15 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe
+ }
+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
+ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
-+ {
-+ unsigned long flags;
-+
-+ // Re-enable the saved interrupts
-+ local_irq_save(flags);
++ if(fiq_enable) {
+ local_fiq_disable();
-+ gintmsk.d32 |= gintmsk_common.d32;
-+ gintsts_saved.d32 &= ~gintmsk_common.d32;
-+ reenable_gintmsk->d32 = gintmsk.d32;
-+ local_irq_restore(flags);
++ /* Pull in the interrupts that the FIQ has masked */
++ gintmsk.d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
++ /* for the upstairs function to reenable - have to read it here in case FIQ triggers again */
++ reenable_gintmsk->d32 |= gintmsk.d32;
++ reenable_gintmsk->d32 |= ~(hcd->fiq_state->gintmsk_saved.d32);
++ reenable_gintmsk->d32 &= gintmsk_common.d32;
++ local_fiq_enable();
+ }
+
+ gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg);
@@ -65635,13 +66364,15 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe
+ gintsts.d32, gintmsk.d32);
+ }
+#endif
-+ if (!fiq_fix_enable){
++ if (!fiq_enable){
+ if (gahbcfg.b.glblintrmsk)
+ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
+ else
+ return 0;
-+ }
-+ else {
++ } else {
++ /* Our IRQ kicker is no longer the USB hardware, it's the MPHI interface.
++ * Can't trust the global interrupt mask bit in this case.
++ */
+ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32);
+ }
+
@@ -65675,7 +66406,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe
+{
+ int retval = 0;
+ gintsts_data_t gintsts;
-+ gintmsk_data_t reenable_gintmsk;
++ gintmsk_data_t gintmsk_reenable = { .d32 = 0 };
+ gpwrdn_data_t gpwrdn = {.d32 = 0 };
+ dwc_otg_device_t *otg_dev = dev;
+ dwc_otg_core_if_t *core_if = otg_dev->core_if;
@@ -65697,7 +66428,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe
+ }
+
+ if (core_if->hibernation_suspend <= 0) {
-+ gintsts.d32 = dwc_otg_read_common_intr(core_if, &reenable_gintmsk);
++ /* read_common will have to poke the FIQ's saved mask. We must then clear this mask at the end
++ * of this handler - god only knows why it's done like this
++ */
++ gintsts.d32 = dwc_otg_read_common_intr(core_if, &gintmsk_reenable, otg_dev->hcd);
+
+ if (gintsts.b.modemismatch) {
+ retval |= dwc_otg_handle_mode_mismatch_intr(core_if);
@@ -65794,11 +66528,16 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe
+ gintsts.b.portintr = 1;
+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32);
+ retval |= 1;
-+ reenable_gintmsk.b.portintr = 1;
++ gintmsk_reenable.b.portintr = 1;
+
+ }
-+
-+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, reenable_gintmsk.d32);
++ /* Did we actually handle anything? if so, unmask the interrupt */
++// fiq_print(FIQDBG_INT, otg_dev->hcd->fiq_state, "CILOUT %1d", retval);
++// fiq_print(FIQDBG_INT, otg_dev->hcd->fiq_state, "%08x", gintsts.d32);
++// fiq_print(FIQDBG_INT, otg_dev->hcd->fiq_state, "%08x", gintmsk_reenable.d32);
++ if (retval) {
++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_reenable.d32);
++ }
+
+ } else {
+ DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32);
@@ -65852,12 +66591,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-raspbe
+ }
+ if (core_if->lock)
+ DWC_SPINUNLOCK(core_if->lock);
-+
+ return retval;
+}
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,705 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
@@ -66564,9 +67302,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-raspber
+/** @} */
+
+#endif /* __DWC_CORE_IF_H__ */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 2014-04-24 16:04:39.815124215 +0200
@@ -0,0 +1,117 @@
+/* ==========================================================================
+ *
@@ -66685,10 +67423,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-raspberry-p
+
+#endif /*DEBUG*/
+#endif
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_driver.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_driver.c 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,1742 @@
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_driver.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.c 2014-04-24 16:04:39.815124215 +0200
+@@ -0,0 +1,1749 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
+ * $Revision: #92 $
@@ -66747,6 +67485,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr
+#include "dwc_otg_core_if.h"
+#include "dwc_otg_pcd_if.h"
+#include "dwc_otg_hcd_if.h"
++#include "dwc_otg_fiq_fsm.h"
+
+#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012"
+#define DWC_DRIVER_DESC "HS OTG USB Controller driver"
@@ -66755,7 +67494,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr
+
+static const char dwc_driver_name[] = "dwc_otg";
+
-+extern void* dummy_send;
+
+extern int pcd_init(
+#ifdef LM_INTERFACE
@@ -66931,13 +67669,14 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr
+ .adp_enable = -1,
+};
+
-+//Global variable to switch the fiq fix on or off (declared in bcm2708.c)
-+extern bool fiq_fix_enable;
++//Global variable to switch the fiq fix on or off
++bool fiq_enable = 1;
+// Global variable to enable the split transaction fix
-+bool fiq_split_enable = true;
-+//Global variable to switch the nak holdoff on or off
-+bool nak_holdoff_enable = true;
++bool fiq_fsm_enable = false;
++//Bulk split-transaction NAK holdoff in microframes
++uint16_t nak_holdoff = 8;
+
++unsigned short fiq_fsm_mask = 0x01;
+
+/**
+ * This function shows the Driver Version.
@@ -67491,7 +68230,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr
+ dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start,
+ _dev->resource[0].end -
+ _dev->resource[0].start+1);
-+ if (fiq_fix_enable)
++ if (fiq_enable)
+ {
+ if (!request_mem_region(_dev->resource[1].start,
+ _dev->resource[1].end - _dev->resource[1].start + 1,
@@ -67504,7 +68243,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr
+ dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
+ _dev->resource[1].end -
+ _dev->resource[1].start + 1);
-+ dummy_send = (void *) kmalloc(16, GFP_ATOMIC);
+ }
+
+#else
@@ -67762,9 +68500,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr
+ int error;
+ struct device_driver *drv;
+
-+ if(fiq_split_enable && !fiq_fix_enable) {
-+ printk(KERN_WARNING "dwc_otg: fiq_split_enable was set without fiq_fix_enable! Correcting.\n");
-+ fiq_fix_enable = 1;
++ if(fiq_fsm_enable && !fiq_enable) {
++ printk(KERN_WARNING "dwc_otg: fiq_fsm_enable was set without fiq_enable! Correcting.\n");
++ fiq_enable = 1;
+ }
+
+ printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
@@ -67786,9 +68524,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr
+ printk(KERN_ERR "%s retval=%d\n", __func__, retval);
+ return retval;
+ }
-+ printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");
-+ printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled");
-+ printk(KERN_DEBUG "dwc_otg: FIQ split fix %s\n", fiq_split_enable ? "enabled":"disabled");
++ printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_enable ? "enabled":"disabled");
++ printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff ? "enabled":"disabled");
++ printk(KERN_DEBUG "dwc_otg: FIQ split-transaction FSM %s\n", fiq_fsm_enable ? "enabled":"disabled");
+
+ error = driver_create_file(drv, &driver_attr_version);
+#ifdef DEBUG
@@ -68069,12 +68807,19 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr
+module_param(microframe_schedule, bool, 0444);
+MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");
+
-+module_param(fiq_fix_enable, bool, 0444);
-+MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");
-+module_param(nak_holdoff_enable, bool, 0444);
-+MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff");
-+module_param(fiq_split_enable, bool, 0444);
-+MODULE_PARM_DESC(fiq_split_enable, "Enable the FIQ fix on split transactions");
++module_param(fiq_enable, bool, 0444);
++MODULE_PARM_DESC(fiq_enable, "Enable the FIQ");
++module_param(nak_holdoff, ushort, 0644);
++MODULE_PARM_DESC(nak_holdoff, "Throttle duration for bulk split-transaction endpoints on a NAK. Default 8");
++module_param(fiq_fsm_enable, bool, 0444);
++MODULE_PARM_DESC(fiq_fsm_enable, "Enable the FIQ to perform split transactions as defined by fiq_fsm_mask");
++module_param(fiq_fsm_mask, ushort, 0444);
++MODULE_PARM_DESC(fiq_fsm_mask, "Bitmask of transactions to perform in the FIQ.\n"
++ "Bit 0 : Non-periodic split transactions\n"
++ "Bit 1 : Periodic split transactions\n"
++ "Bit 2 : High-speed multi-transfer isochronous\n"
++ "All other bits should be set 0.");
++
+
+/** @page "Module Parameters"
+ *
@@ -68431,9 +69176,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-raspberr
+ </td></tr>
+
+*/
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_driver.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_driver.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_driver.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_driver.h 2014-04-24 16:04:39.819124254 +0200
@@ -0,0 +1,86 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $
@@ -68521,10 +69266,1745 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-raspberr
+#endif
+
+#endif
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,3685 @@
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c 2014-04-24 16:04:39.819124254 +0200
+@@ -0,0 +1,1289 @@
++/*
++ * dwc_otg_fiq_fsm.c - The finite state machine FIQ
++ *
++ * Copyright (c) 2013 Raspberry Pi Foundation
++ *
++ * Author: Jonathan Bell <jonathan@raspberrypi.org>
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * * Neither the name of Raspberry Pi nor the
++ * names of its contributors may be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This FIQ implements functionality that performs split transactions on
++ * the dwc_otg hardware without any outside intervention. A split transaction
++ * is "queued" by nominating a specific host channel to perform the entirety
++ * of a split transaction. This FIQ will then perform the microframe-precise
++ * scheduling required in each phase of the transaction until completion.
++ *
++ * The FIQ functionality is glued into the Synopsys driver via the entry point
++ * in the FSM enqueue function, and at the exit point in handling a HC interrupt
++ * for a FSM-enabled channel.
++ *
++ * NB: Large parts of this implementation have architecture-specific code.
++ * For porting this functionality to other ARM machines, the minimum is required:
++ * - An interrupt controller allowing the top-level dwc USB interrupt to be routed
++ * to the FIQ
++ * - A method of forcing a software generated interrupt from FIQ mode that then
++ * triggers an IRQ entry (with the dwc USB handler called by this IRQ number)
++ * - Guaranteed interrupt routing such that both the FIQ and SGI occur on the same
++ * processor core - there is no locking between the FIQ and IRQ (aside from
++ * local_fiq_disable)
++ *
++ */
++
++#include "dwc_otg_fiq_fsm.h"
++
++
++char buffer[1000*16];
++int wptr;
++void notrace _fiq_print(enum fiq_debug_level dbg_lvl, volatile struct fiq_state *state, char *fmt, ...)
++{
++ enum fiq_debug_level dbg_lvl_req = FIQDBG_ERR;
++ va_list args;
++ char text[17];
++ hfnum_data_t hfnum = { .d32 = FIQ_READ(state->dwc_regs_base + 0x408) };
++
++ if((dbg_lvl & dbg_lvl_req) || dbg_lvl == FIQDBG_ERR)
++ {
++ snprintf(text, 9, " %4d:%1u ", hfnum.b.frnum/8, hfnum.b.frnum & 7);
++ va_start(args, fmt);
++ vsnprintf(text+8, 9, fmt, args);
++ va_end(args);
++
++ memcpy(buffer + wptr, text, 16);
++ wptr = (wptr + 16) % sizeof(buffer);
++ }
++}
++
++/**
++ * fiq_fsm_restart_channel() - Poke channel enable bit for a split transaction
++ * @channel: channel to re-enable
++ */
++static void fiq_fsm_restart_channel(struct fiq_state *st, int n, int force)
++{
++ hcchar_data_t hcchar = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR) };
++
++ hcchar.b.chen = 0;
++ if (st->channel[n].hcchar_copy.b.eptype & 0x1) {
++ hfnum_data_t hfnum = { .d32 = FIQ_READ(st->dwc_regs_base + HFNUM) };
++ /* Hardware bug workaround: update the ssplit index */
++ if (st->channel[n].hcsplt_copy.b.spltena)
++ st->channel[n].expected_uframe = (hfnum.b.frnum + 1) & 0x3FFF;
++
++ hcchar.b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
++ }
++
++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR, hcchar.d32);
++ hcchar.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR);
++ hcchar.b.chen = 1;
++
++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR, hcchar.d32);
++ fiq_print(FIQDBG_INT, st, "HCGO %01d %01d", n, force);
++}
++
++/**
++ * fiq_fsm_setup_csplit() - Prepare a host channel for a CSplit transaction stage
++ * @st: Pointer to the channel's state
++ * @n : channel number
++ *
++ * Change host channel registers to perform a complete-split transaction. Being mindful of the
++ * endpoint direction, set control regs up correctly.
++ */
++static void notrace fiq_fsm_setup_csplit(struct fiq_state *st, int n)
++{
++ hcsplt_data_t hcsplt = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCSPLT) };
++ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ) };
++
++ hcsplt.b.compsplt = 1;
++ if (st->channel[n].hcchar_copy.b.epdir == 1) {
++ // If IN, the CSPLIT result contains the data or a hub handshake. hctsiz = maxpacket.
++ hctsiz.b.xfersize = st->channel[n].hctsiz_copy.b.xfersize;
++ } else {
++ // If OUT, the CSPLIT result contains handshake only.
++ hctsiz.b.xfersize = 0;
++ }
++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCSPLT, hcsplt.d32);
++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ, hctsiz.d32);
++ mb();
++}
++
++static inline int notrace fiq_get_xfer_len(struct fiq_state *st, int n)
++{
++ /* The xfersize register is a bit wonky. For IN transfers, it decrements by the packet size. */
++ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ) };
++
++ if (st->channel[n].hcchar_copy.b.epdir == 0) {
++ return st->channel[n].hctsiz_copy.b.xfersize;
++ } else {
++ return st->channel[n].hctsiz_copy.b.xfersize - hctsiz.b.xfersize;
++ }
++
++}
++
++
++/**
++ * fiq_increment_dma_buf() - update DMA address for bounce buffers after a CSPLIT
++ *
++ * Of use only for IN periodic transfers.
++ */
++static int notrace fiq_increment_dma_buf(struct fiq_state *st, int num_channels, int n)
++{
++ hcdma_data_t hcdma;
++ int i = st->channel[n].dma_info.index;
++ int len;
++ struct fiq_dma_blob *blob = (struct fiq_dma_blob *) st->dma_base;
++
++ len = fiq_get_xfer_len(st, n);
++ fiq_print(FIQDBG_INT, st, "LEN: %03d", len);
++ st->channel[n].dma_info.slot_len[i] = len;
++ i++;
++ if (i > 6)
++ BUG();
++
++ hcdma.d32 = (dma_addr_t) &blob->channel[n].index[i].buf[0];
++ FIQ_WRITE(st->dwc_regs_base + HC_DMA + (HC_OFFSET * n), hcdma.d32);
++ st->channel[n].dma_info.index = i;
++ return 0;
++}
++
++/**
++ * fiq_reload_hctsiz() - for IN transactions, reset HCTSIZ
++ */
++static void notrace fiq_fsm_reload_hctsiz(struct fiq_state *st, int n)
++{
++ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ) };
++ hctsiz.b.xfersize = st->channel[n].hctsiz_copy.b.xfersize;
++ hctsiz.b.pktcnt = 1;
++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ, hctsiz.d32);
++}
++
++/**
++ * fiq_iso_out_advance() - update DMA address and split position bits
++ * for isochronous OUT transactions.
++ *
++ * Returns 1 if this is the last packet queued, 0 otherwise. Split-ALL and
++ * Split-BEGIN states are not handled - this is done when the transaction was queued.
++ *
++ * This function must only be called from the FIQ_ISO_OUT_ACTIVE state.
++ */
++static int notrace fiq_iso_out_advance(struct fiq_state *st, int num_channels, int n)
++{
++ hcsplt_data_t hcsplt;
++ hctsiz_data_t hctsiz;
++ hcdma_data_t hcdma;
++ struct fiq_dma_blob *blob = (struct fiq_dma_blob *) st->dma_base;
++ int last = 0;
++ int i = st->channel[n].dma_info.index;
++
++ fiq_print(FIQDBG_INT, st, "ADV %01d %01d ", n, i);
++ i++;
++ if (i == 4)
++ last = 1;
++ if (st->channel[n].dma_info.slot_len[i+1] == 255)
++ last = 1;
++
++ /* New DMA address - address of bounce buffer referred to in index */
++ hcdma.d32 = (uint32_t) &blob->channel[n].index[i].buf[0];
++ //hcdma.d32 = FIQ_READ(st->dwc_regs_base + HC_DMA + (HC_OFFSET * n));
++ //hcdma.d32 += st->channel[n].dma_info.slot_len[i];
++ fiq_print(FIQDBG_INT, st, "LAST: %01d ", last);
++ fiq_print(FIQDBG_INT, st, "LEN: %03d", st->channel[n].dma_info.slot_len[i]);
++ hcsplt.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCSPLT);
++ hctsiz.d32 = FIQ_READ(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ);
++ hcsplt.b.xactpos = (last) ? ISOC_XACTPOS_END : ISOC_XACTPOS_MID;
++ /* Set up new packet length */
++ hctsiz.b.pktcnt = 1;
++ hctsiz.b.xfersize = st->channel[n].dma_info.slot_len[i];
++ fiq_print(FIQDBG_INT, st, "%08x", hctsiz.d32);
++
++ st->channel[n].dma_info.index++;
++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCSPLT, hcsplt.d32);
++ FIQ_WRITE(st->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ, hctsiz.d32);
++ FIQ_WRITE(st->dwc_regs_base + HC_DMA + (HC_OFFSET * n), hcdma.d32);
++ return last;
++}
++
++/**
++ * fiq_fsm_tt_next_isoc() - queue next pending isochronous out start-split on a TT
++ *
++ * Despite the limitations of the DWC core, we can force a microframe pipeline of
++ * isochronous OUT start-split transactions while waiting for a corresponding other-type
++ * of endpoint to finish its CSPLITs. TTs have big periodic buffers therefore it
++ * is very unlikely that filling the start-split FIFO will cause data loss.
++ * This allows much better interleaving of transactions in an order-independent way-
++ * there is no requirement to prioritise isochronous, just a state-space search has
++ * to be performed on each periodic start-split complete interrupt.
++ */
++static int notrace fiq_fsm_tt_next_isoc(struct fiq_state *st, int num_channels, int n)
++{
++ int hub_addr = st->channel[n].hub_addr;
++ int port_addr = st->channel[n].port_addr;
++ int i, poked = 0;
++ for (i = 0; i < num_channels; i++) {
++ if (i == n || st->channel[i].fsm == FIQ_PASSTHROUGH)
++ continue;
++ if (st->channel[i].hub_addr == hub_addr &&
++ st->channel[i].port_addr == port_addr) {
++ switch (st->channel[i].fsm) {
++ case FIQ_PER_ISO_OUT_PENDING:
++ if (st->channel[i].nrpackets == 1) {
++ st->channel[i].fsm = FIQ_PER_ISO_OUT_LAST;
++ } else {
++ st->channel[i].fsm = FIQ_PER_ISO_OUT_ACTIVE;
++ }
++ fiq_fsm_restart_channel(st, i, 0);
++ poked = 1;
++ break;
++
++ default:
++ break;
++ }
++ }
++ if (poked)
++ break;
++ }
++ return poked;
++}
++
++/**
++ * fiq_fsm_tt_in_use() - search for host channels using this TT
++ * @n: Channel to use as reference
++ *
++ */
++int notrace noinline fiq_fsm_tt_in_use(struct fiq_state *st, int num_channels, int n)
++{
++ int hub_addr = st->channel[n].hub_addr;
++ int port_addr = st->channel[n].port_addr;
++ int i, in_use = 0;
++ for (i = 0; i < num_channels; i++) {
++ if (i == n || st->channel[i].fsm == FIQ_PASSTHROUGH)
++ continue;
++ switch (st->channel[i].fsm) {
++ /* TT is reserved for channels that are in the middle of a periodic
++ * split transaction.
++ */
++ case FIQ_PER_SSPLIT_STARTED:
++ case FIQ_PER_CSPLIT_WAIT:
++ case FIQ_PER_CSPLIT_NYET1:
++ //case FIQ_PER_CSPLIT_POLL:
++ case FIQ_PER_ISO_OUT_ACTIVE:
++ if (st->channel[i].hub_addr == hub_addr &&
++ st->channel[i].port_addr == port_addr) {
++ in_use = 1;
++ }
++ break;
++ default:
++ break;
++ }
++ if (in_use)
++ break;
++ }
++ return in_use;
++}
++
++/**
++ * fiq_fsm_more_csplits() - determine whether additional CSPLITs need
++ * to be issued for this IN transaction.
++ *
++ * We cannot tell the inbound PID of a data packet due to hardware limitations.
++ * we need to make an educated guess as to whether we need to queue another CSPLIT
++ * or not. A no-brainer is when we have received enough data to fill the endpoint
++ * size, but for endpoints that give variable-length data then we have to resort
++ * to heuristics.
++ *
++ * We also return whether this is the last CSPLIT to be queued, again based on
++ * heuristics. This is to allow a 1-uframe overlap of periodic split transactions.
++ * Note: requires at least 1 CSPLIT to have been performed prior to being called.
++ */
++
++/*
++ * We need some way of guaranteeing if a returned periodic packet of size X
++ * has a DATA0 PID.
++ * The heuristic value of 144 bytes assumes that the received data has maximal
++ * bit-stuffing and the clock frequency of the transmitting device is at the lowest
++ * permissible limit. If the transfer length results in a final packet size
++ * 144 < p <= 188, then an erroneous CSPLIT will be issued.
++ * Also used to ensure that an endpoint will nominally only return a single
++ * complete-split worth of data.
++ */
++#define DATA0_PID_HEURISTIC 144
++
++static int notrace noinline fiq_fsm_more_csplits(struct fiq_state *state, int n, int *probably_last)
++{
++
++ int i;
++ int total_len = 0;
++ int more_needed = 1;
++ struct fiq_channel_state *st = &state->channel[n];
++
++ for (i = 0; i < st->dma_info.index; i++) {
++ total_len += st->dma_info.slot_len[i];
++ }
++
++ *probably_last = 0;
++
++ if (st->hcchar_copy.b.eptype == 0x3) {
++ /*
++ * An interrupt endpoint will take max 2 CSPLITs. if we are receiving data
++ * then this is definitely the last CSPLIT.
++ */
++ *probably_last = 1;
++ } else {
++ /* Isoc IN. This is a bit risky if we are the first transaction:
++ * we may have been held off slightly. */
++ if (i > 1 && st->dma_info.slot_len[st->dma_info.index-1] <= DATA0_PID_HEURISTIC) {
++ more_needed = 0;
++ }
++ /* If in the next uframe we will receive enough data to fill the endpoint,
++ * then only issue 1 more csplit.
++ */
++ if (st->hctsiz_copy.b.xfersize - total_len <= DATA0_PID_HEURISTIC)
++ *probably_last = 1;
++ }
++
++ if (total_len >= st->hctsiz_copy.b.xfersize ||
++ i == 6 || total_len == 0)
++ /* Note: due to bit stuffing it is possible to have > 6 CSPLITs for
++ * a single endpoint. Accepting more would completely break our scheduling mechanism though
++ * - in these extreme cases we will pass through a truncated packet.
++ */
++ more_needed = 0;
++
++ return more_needed;
++}
++
++/**
++ * fiq_fsm_too_late() - Test transaction for lateness
++ *
++ * If a SSPLIT for a large IN transaction is issued too late in a frame,
++ * the hub will disable the port to the device and respond with ERR handshakes.
++ * The hub status endpoint will not reflect this change.
++ * Returns 1 if we will issue a SSPLIT that will result in a device babble.
++ */
++int notrace fiq_fsm_too_late(struct fiq_state *st, int n)
++{
++ int uframe;
++ hfnum_data_t hfnum = { .d32 = FIQ_READ(st->dwc_regs_base + HFNUM) };
++ uframe = hfnum.b.frnum & 0x7;
++ if ((uframe < 6) && (st->channel[n].nrpackets + 1 + uframe > 7)) {
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++
++/**
++ * fiq_fsm_start_next_periodic() - A half-arsed attempt at a microframe pipeline
++ *
++ * Search pending transactions in the start-split pending state and queue them.
++ * Don't queue packets in uframe .5 (comes out in .6) (USB2.0 11.18.4).
++ * Note: we specifically don't do isochronous OUT transactions first because better
++ * use of the TT's start-split fifo can be achieved by pipelining an IN before an OUT.
++ */
++static void notrace noinline fiq_fsm_start_next_periodic(struct fiq_state *st, int num_channels)
++{
++ int n;
++ hfnum_data_t hfnum = { .d32 = FIQ_READ(st->dwc_regs_base + HFNUM) };
++ if ((hfnum.b.frnum & 0x7) == 5)
++ return;
++ for (n = 0; n < num_channels; n++) {
++ if (st->channel[n].fsm == FIQ_PER_SSPLIT_QUEUED) {
++ /* Check to see if any other transactions are using this TT */
++ if(!fiq_fsm_tt_in_use(st, num_channels, n)) {
++ if (!fiq_fsm_too_late(st, n)) {
++ st->channel[n].fsm = FIQ_PER_SSPLIT_STARTED;
++ fiq_print(FIQDBG_INT, st, "NEXTPER ");
++ fiq_fsm_restart_channel(st, n, 0);
++ } else {
++ st->channel[n].fsm = FIQ_PER_SPLIT_TIMEOUT;
++ }
++ break;
++ }
++ }
++ }
++ for (n = 0; n < num_channels; n++) {
++ if (st->channel[n].fsm == FIQ_PER_ISO_OUT_PENDING) {
++ if (!fiq_fsm_tt_in_use(st, num_channels, n)) {
++ fiq_print(FIQDBG_INT, st, "NEXTISO ");
++ st->channel[n].fsm = FIQ_PER_ISO_OUT_ACTIVE;
++ fiq_fsm_restart_channel(st, n, 0);
++ break;
++ }
++ }
++ }
++}
++
++/**
++ * fiq_fsm_update_hs_isoc() - update isochronous frame and transfer data
++ * @state: Pointer to fiq_state
++ * @n: Channel transaction is active on
++ * @hcint: Copy of host channel interrupt register
++ *
++ * Returns 0 if there are no more transactions for this HC to do, 1
++ * otherwise.
++ */
++static int notrace noinline fiq_fsm_update_hs_isoc(struct fiq_state *state, int n, hcint_data_t hcint)
++{
++ struct fiq_channel_state *st = &state->channel[n];
++ int xfer_len = 0, nrpackets = 0;
++ hcdma_data_t hcdma;
++ fiq_print(FIQDBG_INT, state, "HSISO %02d", n);
++
++ xfer_len = fiq_get_xfer_len(state, n);
++ st->hs_isoc_info.iso_desc[st->hs_isoc_info.index].actual_length = xfer_len;
++
++ st->hs_isoc_info.iso_desc[st->hs_isoc_info.index].status = hcint.d32;
++
++ st->hs_isoc_info.index++;
++ if (st->hs_isoc_info.index == st->hs_isoc_info.nrframes) {
++ return 0;
++ }
++
++ /* grab the next DMA address offset from the array */
++ hcdma.d32 = st->hcdma_copy.d32 + st->hs_isoc_info.iso_desc[st->hs_isoc_info.index].offset;
++ FIQ_WRITE(state->dwc_regs_base + HC_DMA + (HC_OFFSET * n), hcdma.d32);
++
++ /* We need to set multi_count. This is a bit tricky - has to be set per-transaction as
++ * the core needs to be told to send the correct number. Caution: for IN transfers,
++ * this is always set to the maximum size of the endpoint. */
++ xfer_len = st->hs_isoc_info.iso_desc[st->hs_isoc_info.index].length;
++ /* Integer divide in a FIQ: fun. FIXME: make this not suck */
++ nrpackets = (xfer_len + st->hcchar_copy.b.mps - 1) / st->hcchar_copy.b.mps;
++ if (nrpackets == 0)
++ nrpackets = 1;
++ st->hcchar_copy.b.multicnt = nrpackets;
++ st->hctsiz_copy.b.pktcnt = nrpackets;
++
++ /* Initial PID also needs to be set */
++ if (st->hcchar_copy.b.epdir == 0) {
++ st->hctsiz_copy.b.xfersize = xfer_len;
++ switch (st->hcchar_copy.b.multicnt) {
++ case 1:
++ st->hctsiz_copy.b.pid = DWC_PID_DATA0;
++ break;
++ case 2:
++ case 3:
++ st->hctsiz_copy.b.pid = DWC_PID_MDATA;
++ break;
++ }
++
++ } else {
++ switch (st->hcchar_copy.b.multicnt) {
++ st->hctsiz_copy.b.xfersize = nrpackets * st->hcchar_copy.b.mps;
++ case 1:
++ st->hctsiz_copy.b.pid = DWC_PID_DATA0;
++ break;
++ case 2:
++ st->hctsiz_copy.b.pid = DWC_PID_DATA1;
++ break;
++ case 3:
++ st->hctsiz_copy.b.pid = DWC_PID_DATA2;
++ break;
++ }
++ }
++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCTSIZ, st->hctsiz_copy.d32);
++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR, st->hcchar_copy.d32);
++ /* Channel is enabled on hcint handler exit */
++ fiq_print(FIQDBG_INT, state, "HSISOOUT");
++ return 1;
++}
++
++
++/**
++ * fiq_fsm_do_sof() - FSM start-of-frame interrupt handler
++ * @state: Pointer to the state struct passed from banked FIQ mode registers.
++ * @num_channels: set according to the DWC hardware configuration
++ *
++ * The SOF handler in FSM mode has two functions
++ * 1. Hold off SOF from causing schedule advancement in IRQ context if there's
++ * nothing to do
++ * 2. Advance certain FSM states that require either a microframe delay, or a microframe
++ * of holdoff.
++ *
++ * The second part is architecture-specific to mach-bcm2835 -
++ * a sane interrupt controller would have a mask register for ARM interrupt sources
++ * to be promoted to the nFIQ line, but it doesn't. Instead a single interrupt
++ * number (USB) can be enabled. This means that certain parts of the USB specification
++ * that require "wait a little while, then issue another packet" cannot be fulfilled with
++ * the timing granularity required to achieve optimal throughout. The workaround is to use
++ * the SOF "timer" (125uS) to perform this task.
++ */
++static int notrace noinline fiq_fsm_do_sof(struct fiq_state *state, int num_channels)
++{
++ hfnum_data_t hfnum = { .d32 = FIQ_READ(state->dwc_regs_base + HFNUM) };
++ int n;
++ int kick_irq = 0;
++
++ if ((hfnum.b.frnum & 0x7) == 1) {
++ /* We cannot issue csplits for transactions in the last frame past (n+1).1
++ * Check to see if there are any transactions that are stale.
++ * Boot them out.
++ */
++ for (n = 0; n < num_channels; n++) {
++ switch (state->channel[n].fsm) {
++ case FIQ_PER_CSPLIT_WAIT:
++ case FIQ_PER_CSPLIT_NYET1:
++ case FIQ_PER_CSPLIT_POLL:
++ case FIQ_PER_CSPLIT_LAST:
++ /* Check if we are no longer in the same full-speed frame. */
++ if (((state->channel[n].expected_uframe & 0x3FFF) & ~0x7) <
++ (hfnum.b.frnum & ~0x7))
++ state->channel[n].fsm = FIQ_PER_SPLIT_TIMEOUT;
++ break;
++ default:
++ break;
++ }
++ }
++ }
++
++ for (n = 0; n < num_channels; n++) {
++ switch (state->channel[n].fsm) {
++
++ case FIQ_NP_SSPLIT_RETRY:
++ case FIQ_NP_IN_CSPLIT_RETRY:
++ case FIQ_NP_OUT_CSPLIT_RETRY:
++ fiq_fsm_restart_channel(state, n, 0);
++ break;
++
++ case FIQ_HS_ISOC_SLEEPING:
++ state->channel[n].fsm = FIQ_HS_ISOC_TURBO;
++ fiq_fsm_restart_channel(state, n, 0);
++ break;
++
++ case FIQ_PER_SSPLIT_QUEUED:
++ if ((hfnum.b.frnum & 0x7) == 5)
++ break;
++ if(!fiq_fsm_tt_in_use(state, num_channels, n)) {
++ if (!fiq_fsm_too_late(state, n)) {
++ fiq_print(FIQDBG_INT, st, "SOF GO %01d", n);
++ fiq_fsm_restart_channel(state, n, 0);
++ state->channel[n].fsm = FIQ_PER_SSPLIT_STARTED;
++ } else {
++ state->channel[n].fsm = FIQ_PER_SPLIT_TIMEOUT;
++ state->haintmsk_saved.b2.chint &= ~(1 << n);
++ kick_irq |= 1;
++ }
++ }
++ break;
++
++ case FIQ_PER_ISO_OUT_PENDING:
++ /* Ordinarily, this should be poked after the SSPLIT
++ * complete interrupt for a competing transfer on the same
++ * TT. Doesn't happen for aborted transactions though.
++ */
++ if ((hfnum.b.frnum & 0x7) >= 5)
++ break;
++ if (!fiq_fsm_tt_in_use(state, num_channels, n)) {
++ /* Hardware bug. SOF can sometimes occur after the channel halt interrupt
++ * that caused this.
++ */
++ fiq_fsm_restart_channel(state, n, 0);
++ fiq_print(FIQDBG_INT, state, "SOF ISOC");
++ if (state->channel[n].nrpackets == 1) {
++ state->channel[n].fsm = FIQ_PER_ISO_OUT_LAST;
++ } else {
++ state->channel[n].fsm = FIQ_PER_ISO_OUT_ACTIVE;
++ }
++ }
++ break;
++
++ case FIQ_PER_CSPLIT_WAIT:
++ /* we are guaranteed to be in this state if and only if the SSPLIT interrupt
++ * occurred when the bus transaction occurred. The SOF interrupt reversal bug
++ * will utterly bugger this up though.
++ */
++ if (hfnum.b.frnum != state->channel[n].expected_uframe) {
++ fiq_print(FIQDBG_INT, state, "SOFCS %d ", n);
++ state->channel[n].fsm = FIQ_PER_CSPLIT_POLL;
++ fiq_fsm_restart_channel(state, n, 0);
++ fiq_fsm_start_next_periodic(state, num_channels);
++
++ }
++ break;
++
++ case FIQ_PER_SPLIT_TIMEOUT:
++ /* Ugly: we have to force a HCD interrupt.
++ * Poke the mask for the channel in question.
++ * We will take a fake SOF because of this, but
++ * that's OK.
++ */
++ state->haintmsk_saved.b2.chint &= ~(1 << n);
++ kick_irq |= 1;
++ break;
++
++ default:
++ break;
++ }
++ }
++
++ if (state->kick_np_queues ||
++ dwc_frame_num_le(state->next_sched_frame, hfnum.b.frnum))
++ kick_irq |= 1;
++
++ return !kick_irq;
++}
++
++
++/**
++ * fiq_fsm_do_hcintr() - FSM host channel interrupt handler
++ * @state: Pointer to the FIQ state struct
++ * @num_channels: Number of channels as per hardware config
++ * @n: channel for which HAINT(i) was raised
++ *
++ * An important property is that only the CHHLT interrupt is unmasked. Unfortunately, AHBerr is as well.
++ */
++static int notrace noinline fiq_fsm_do_hcintr(struct fiq_state *state, int num_channels, int n)
++{
++ hcint_data_t hcint;
++ hcintmsk_data_t hcintmsk;
++ hcint_data_t hcint_probe;
++ hcchar_data_t hcchar;
++ int handled = 0;
++ int restart = 0;
++ int last_csplit = 0;
++ int start_next_periodic = 0;
++ struct fiq_channel_state *st = &state->channel[n];
++ hfnum_data_t hfnum;
++
++ hcint.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINT);
++ hcintmsk.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINTMSK);
++ hcint_probe.d32 = hcint.d32 & hcintmsk.d32;
++
++ if (st->fsm != FIQ_PASSTHROUGH) {
++ fiq_print(FIQDBG_INT, state, "HC%01d ST%02d", n, st->fsm);
++ fiq_print(FIQDBG_INT, state, "%08x", hcint.d32);
++ }
++
++ switch (st->fsm) {
++
++ case FIQ_PASSTHROUGH:
++ case FIQ_DEQUEUE_ISSUED:
++ /* doesn't belong to us, kick it upstairs */
++ break;
++
++ case FIQ_PASSTHROUGH_ERRORSTATE:
++ /* We are here to emulate the error recovery mechanism of the dwc HCD.
++ * Several interrupts are unmasked if a previous transaction failed - it's
++ * death for the FIQ to attempt to handle them as the channel isn't halted.
++ * Emulate what the HCD does in this situation: mask and continue.
++ * The FSM has no other state setup so this has to be handled out-of-band.
++ */
++ fiq_print(FIQDBG_ERR, state, "ERRST %02d", n);
++ if (hcint_probe.b.nak || hcint_probe.b.ack || hcint_probe.b.datatglerr) {
++ fiq_print(FIQDBG_ERR, state, "RESET %02d", n);
++ st->nr_errors = 0;
++ hcintmsk.b.nak = 0;
++ hcintmsk.b.ack = 0;
++ hcintmsk.b.datatglerr = 0;
++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINTMSK, hcintmsk.d32);
++ return 1;
++ }
++ if (hcint_probe.b.chhltd) {
++ fiq_print(FIQDBG_ERR, state, "CHHLT %02d", n);
++ fiq_print(FIQDBG_ERR, state, "%08x", hcint.d32);
++ return 0;
++ }
++ break;
++
++ /* Non-periodic state groups */
++ case FIQ_NP_SSPLIT_STARTED:
++ case FIQ_NP_SSPLIT_RETRY:
++ /* Got a HCINT for a NP SSPLIT. Expected ACK / NAK / fail */
++ if (hcint.b.ack) {
++ /* SSPLIT complete. For OUT, the data has been sent. For IN, the LS transaction
++ * will start shortly. SOF needs to kick the transaction to prevent a NYET flood.
++ */
++ if(st->hcchar_copy.b.epdir == 1)
++ st->fsm = FIQ_NP_IN_CSPLIT_RETRY;
++ else
++ st->fsm = FIQ_NP_OUT_CSPLIT_RETRY;
++ st->nr_errors = 0;
++ handled = 1;
++ fiq_fsm_setup_csplit(state, n);
++ } else if (hcint.b.nak) {
++ // No buffer space in TT. Retry on a uframe boundary.
++ st->fsm = FIQ_NP_SSPLIT_RETRY;
++ handled = 1;
++ } else if (hcint.b.xacterr) {
++ // The only other one we care about is xacterr. This implies HS bus error - retry.
++ st->nr_errors++;
++ st->fsm = FIQ_NP_SSPLIT_RETRY;
++ if (st->nr_errors >= 3) {
++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED;
++ } else {
++ handled = 1;
++ restart = 1;
++ }
++ } else {
++ st->fsm = FIQ_NP_SPLIT_LS_ABORTED;
++ handled = 0;
++ restart = 0;
++ }
++ break;
++
++ case FIQ_NP_IN_CSPLIT_RETRY:
++ /* Received a CSPLIT done interrupt.
++ * Expected Data/NAK/STALL/NYET for IN.
++ */
++ if (hcint.b.xfercomp) {
++ /* For IN, data is present. */
++ st->fsm = FIQ_NP_SPLIT_DONE;
++ } else if (hcint.b.nak) {
++ /* no endpoint data. Punt it upstairs */
++ st->fsm = FIQ_NP_SPLIT_DONE;
++ } else if (hcint.b.nyet) {
++ /* CSPLIT NYET - retry on a uframe boundary. */
++ handled = 1;
++ st->nr_errors = 0;
++ } else if (hcint.b.datatglerr) {
++ /* data toggle errors do not set the xfercomp bit. */
++ st->fsm = FIQ_NP_SPLIT_LS_ABORTED;
++ } else if (hcint.b.xacterr) {
++ /* HS error. Retry immediate */
++ st->fsm = FIQ_NP_IN_CSPLIT_RETRY;
++ st->nr_errors++;
++ if (st->nr_errors >= 3) {
++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED;
++ } else {
++ handled = 1;
++ restart = 1;
++ }
++ } else if (hcint.b.stall) {
++ /* A STALL implies either a LS bus error or a genuine STALL. */
++ st->fsm = FIQ_NP_SPLIT_LS_ABORTED;
++ } else {
++ /* Hardware bug. It's possible in some cases to
++ * get a channel halt with nothing else set when
++ * the response was a NYET. Treat as local 3-strikes retry.
++ */
++ hcint_data_t hcint_test = hcint;
++ hcint_test.b.chhltd = 0;
++ if (!hcint_test.d32) {
++ st->nr_errors++;
++ if (st->nr_errors >= 3) {
++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED;
++ } else {
++ handled = 1;
++ }
++ } else {
++ /* Bail out if something unexpected happened */
++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED;
++ }
++ }
++ break;
++
++ case FIQ_NP_OUT_CSPLIT_RETRY:
++ /* Received a CSPLIT done interrupt.
++ * Expected ACK/NAK/STALL/NYET/XFERCOMP for OUT.*/
++ if (hcint.b.xfercomp) {
++ st->fsm = FIQ_NP_SPLIT_DONE;
++ } else if (hcint.b.nak) {
++ // The HCD will implement the holdoff on frame boundaries.
++ st->fsm = FIQ_NP_SPLIT_DONE;
++ } else if (hcint.b.nyet) {
++ // Hub still processing.
++ st->fsm = FIQ_NP_OUT_CSPLIT_RETRY;
++ handled = 1;
++ st->nr_errors = 0;
++ //restart = 1;
++ } else if (hcint.b.xacterr) {
++ /* HS error. retry immediate */
++ st->fsm = FIQ_NP_OUT_CSPLIT_RETRY;
++ st->nr_errors++;
++ if (st->nr_errors >= 3) {
++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED;
++ } else {
++ handled = 1;
++ restart = 1;
++ }
++ } else if (hcint.b.stall) {
++ /* LS bus error or genuine stall */
++ st->fsm = FIQ_NP_SPLIT_LS_ABORTED;
++ } else {
++ /*
++ * Hardware bug. It's possible in some cases to get a
++ * channel halt with nothing else set when the response was a NYET.
++ * Treat as local 3-strikes retry.
++ */
++ hcint_data_t hcint_test = hcint;
++ hcint_test.b.chhltd = 0;
++ if (!hcint_test.d32) {
++ st->nr_errors++;
++ if (st->nr_errors >= 3) {
++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED;
++ } else {
++ handled = 1;
++ }
++ } else {
++ // Something unexpected happened. AHBerror or babble perhaps. Let the IRQ deal with it.
++ st->fsm = FIQ_NP_SPLIT_HS_ABORTED;
++ }
++ }
++ break;
++
++ /* Periodic split states (except isoc out) */
++ case FIQ_PER_SSPLIT_STARTED:
++ /* Expect an ACK or failure for SSPLIT */
++ if (hcint.b.ack) {
++ /*
++ * SSPLIT transfer complete interrupt - the generation of this interrupt is fraught with bugs.
++ * For a packet queued in microframe n-3 to appear in n-2, if the channel is enabled near the EOF1
++ * point for microframe n-3, the packet will not appear on the bus until microframe n.
++ * Additionally, the generation of the actual interrupt is dodgy. For a packet appearing on the bus
++ * in microframe n, sometimes the interrupt is generated immediately. Sometimes, it appears in n+1
++ * coincident with SOF for n+1.
++ * SOF is also buggy. It can sometimes be raised AFTER the first bus transaction has taken place.
++ * These appear to be caused by timing/clock crossing bugs within the core itself.
++ * State machine workaround.
++ */
++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM);
++ hcchar.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR);
++ fiq_fsm_setup_csplit(state, n);
++ /* Poke the oddfrm bit. If we are equivalent, we received the interrupt at the correct
++ * time. If not, then we're in the next SOF.
++ */
++ if ((hfnum.b.frnum & 0x1) == hcchar.b.oddfrm) {
++ fiq_print(FIQDBG_INT, state, "CSWAIT %01d", n);
++ st->expected_uframe = hfnum.b.frnum;
++ st->fsm = FIQ_PER_CSPLIT_WAIT;
++ } else {
++ fiq_print(FIQDBG_INT, state, "CSPOL %01d", n);
++ /* For isochronous IN endpoints,
++ * we need to hold off if we are expecting a lot of data */
++ if (st->hcchar_copy.b.mps < DATA0_PID_HEURISTIC) {
++ start_next_periodic = 1;
++ }
++ /* Danger will robinson: we are in a broken state. If our first interrupt after
++ * this is a NYET, it will be delayed by 1 uframe and result in an unrecoverable
++ * lag. Unmask the NYET interrupt.
++ */
++ st->expected_uframe = (hfnum.b.frnum + 1) & 0x3FFF;
++ st->fsm = FIQ_PER_CSPLIT_BROKEN_NYET1;
++ restart = 1;
++ }
++ handled = 1;
++ } else if (hcint.b.xacterr) {
++ /* 3-strikes retry is enabled, we have hit our max nr_errors */
++ st->fsm = FIQ_PER_SPLIT_HS_ABORTED;
++ start_next_periodic = 1;
++ } else {
++ st->fsm = FIQ_PER_SPLIT_HS_ABORTED;
++ start_next_periodic = 1;
++ }
++ /* We can now queue the next isochronous OUT transaction, if one is pending. */
++ if(fiq_fsm_tt_next_isoc(state, num_channels, n)) {
++ fiq_print(FIQDBG_INT, state, "NEXTISO ");
++ }
++ break;
++
++ case FIQ_PER_CSPLIT_NYET1:
++ /* First CSPLIT attempt was a NYET. If we get a subsequent NYET,
++ * we are too late and the TT has dropped its CSPLIT fifo.
++ */
++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM);
++ hcchar.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR);
++ start_next_periodic = 1;
++ if (hcint.b.nak) {
++ st->fsm = FIQ_PER_SPLIT_DONE;
++ } else if (hcint.b.xfercomp) {
++ fiq_increment_dma_buf(state, num_channels, n);
++ st->fsm = FIQ_PER_CSPLIT_POLL;
++ st->nr_errors = 0;
++ if (fiq_fsm_more_csplits(state, n, &last_csplit)) {
++ handled = 1;
++ restart = 1;
++ if (!last_csplit)
++ start_next_periodic = 0;
++ } else {
++ st->fsm = FIQ_PER_SPLIT_DONE;
++ }
++ } else if (hcint.b.nyet) {
++ /* Doh. Data lost. */
++ st->fsm = FIQ_PER_SPLIT_NYET_ABORTED;
++ } else if (hcint.b.xacterr || hcint.b.stall) {
++ st->fsm = FIQ_PER_SPLIT_LS_ABORTED;
++ } else {
++ st->fsm = FIQ_PER_SPLIT_HS_ABORTED;
++ }
++ break;
++
++ case FIQ_PER_CSPLIT_BROKEN_NYET1:
++ /*
++ * we got here because our host channel is in the delayed-interrupt
++ * state and we cannot take a NYET interrupt any later than when it
++ * occurred. Disable then re-enable the channel if this happens to force
++ * CSPLITs to occur at the right time.
++ */
++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM);
++ hcchar.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR);
++ fiq_print(FIQDBG_INT, state, "BROK: %01d ", n);
++ if (hcint.b.nak) {
++ st->fsm = FIQ_PER_SPLIT_DONE;
++ start_next_periodic = 1;
++ } else if (hcint.b.xfercomp) {
++ fiq_increment_dma_buf(state, num_channels, n);
++ if (fiq_fsm_more_csplits(state, n, &last_csplit)) {
++ st->fsm = FIQ_PER_CSPLIT_POLL;
++ handled = 1;
++ restart = 1;
++ start_next_periodic = 1;
++ /* Reload HCTSIZ for the next transfer */
++ fiq_fsm_reload_hctsiz(state, n);
++ if (!last_csplit)
++ start_next_periodic = 0;
++ } else {
++ st->fsm = FIQ_PER_SPLIT_DONE;
++ }
++ } else if (hcint.b.nyet) {
++ st->fsm = FIQ_PER_SPLIT_NYET_ABORTED;
++ start_next_periodic = 1;
++ } else if (hcint.b.xacterr) {
++ /* Local 3-strikes retry is handled by the core. This is a ERR response.*/
++ st->fsm = FIQ_PER_SPLIT_LS_ABORTED;
++ } else {
++ fiq_print(FIQDBG_INT, state, "TOGGLES");
++ BUG();
++ }
++ break;
++
++ case FIQ_PER_CSPLIT_POLL:
++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM);
++ hcchar.d32 = FIQ_READ(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCCHAR);
++ start_next_periodic = 1;
++ if (hcint.b.nak) {
++ st->fsm = FIQ_PER_SPLIT_DONE;
++ } else if (hcint.b.xfercomp) {
++ fiq_increment_dma_buf(state, num_channels, n);
++ if (fiq_fsm_more_csplits(state, n, &last_csplit)) {
++ handled = 1;
++ restart = 1;
++ /* Reload HCTSIZ for the next transfer */
++ fiq_fsm_reload_hctsiz(state, n);
++ if (!last_csplit)
++ start_next_periodic = 0;
++ } else {
++ st->fsm = FIQ_PER_SPLIT_DONE;
++ }
++ } else if (hcint.b.nyet) {
++ /* Are we a NYET after the first data packet? */
++ if (st->nrpackets == 0) {
++ st->fsm = FIQ_PER_CSPLIT_NYET1;
++ handled = 1;
++ restart = 1;
++ } else {
++ /* We got a NYET when polling CSPLITs. Can happen
++ * if our heuristic fails, or if someone disables us
++ * for any significant length of time.
++ */
++ if (st->nr_errors >= 3) {
++ st->fsm = FIQ_PER_SPLIT_NYET_ABORTED;
++ } else {
++ st->fsm = FIQ_PER_SPLIT_DONE;
++ }
++ }
++ } else if (hcint.b.xacterr || hcint.b.stall) {
++ /* For xacterr, Local 3-strikes retry is handled by the core. This is a ERR response.*/
++ st->fsm = FIQ_PER_SPLIT_LS_ABORTED;
++ } else if (hcint.b.datatglerr) {
++ fiq_print(FIQDBG_INT, state, "TOGGLES");
++ BUG();
++ } else {
++ st->fsm = FIQ_PER_SPLIT_HS_ABORTED;
++ }
++ break;
++
++ case FIQ_HS_ISOC_TURBO:
++ if (fiq_fsm_update_hs_isoc(state, n, hcint)) {
++ /* more transactions to come */
++ handled = 1;
++ restart = 1;
++ fiq_print(FIQDBG_INT, state, "HSISO M ");
++ } else {
++ st->fsm = FIQ_HS_ISOC_DONE;
++ fiq_print(FIQDBG_INT, state, "HSISO F ");
++ }
++ break;
++
++ case FIQ_HS_ISOC_ABORTED:
++ /* This abort is called by the driver rewriting the state mid-transaction
++ * which allows the dequeue mechanism to work more effectively.
++ */
++ break;
++
++ case FIQ_PER_ISO_OUT_ACTIVE:
++ if (hcint.b.ack) {
++ if(fiq_iso_out_advance(state, num_channels, n)) {
++ /* last OUT transfer */
++ st->fsm = FIQ_PER_ISO_OUT_LAST;
++ /*
++ * Assuming the periodic FIFO in the dwc core
++ * actually does its job properly, we can queue
++ * the next ssplit now and in theory, the wire
++ * transactions will be in-order.
++ */
++ // No it doesn't. It appears to process requests in host channel order.
++ //start_next_periodic = 1;
++ }
++ handled = 1;
++ restart = 1;
++ } else {
++ /*
++ * Isochronous transactions carry on regardless. Log the error
++ * and continue.
++ */
++ //explode += 1;
++ st->nr_errors++;
++ if(fiq_iso_out_advance(state, num_channels, n)) {
++ st->fsm = FIQ_PER_ISO_OUT_LAST;
++ //start_next_periodic = 1;
++ }
++ handled = 1;
++ restart = 1;
++ }
++ break;
++
++ case FIQ_PER_ISO_OUT_LAST:
++ if (hcint.b.ack) {
++ /* All done here */
++ st->fsm = FIQ_PER_ISO_OUT_DONE;
++ } else {
++ st->fsm = FIQ_PER_ISO_OUT_DONE;
++ st->nr_errors++;
++ }
++ start_next_periodic = 1;
++ break;
++
++ case FIQ_PER_SPLIT_TIMEOUT:
++ /* SOF kicked us because we overran. */
++ start_next_periodic = 1;
++ break;
++
++ default:
++ break;
++ }
++
++ if (handled) {
++ FIQ_WRITE(state->dwc_regs_base + HC_START + (HC_OFFSET * n) + HCINT, hcint.d32);
++ } else {
++ /* Copy the regs into the state so the IRQ knows what to do */
++ st->hcint_copy.d32 = hcint.d32;
++ }
++
++ if (restart) {
++ /* Restart always implies handled. */
++ if (restart == 2) {
++ /* For complete-split INs, the show must go on.
++ * Force a channel restart */
++ fiq_fsm_restart_channel(state, n, 1);
++ } else {
++ fiq_fsm_restart_channel(state, n, 0);
++ }
++ }
++ if (start_next_periodic) {
++ fiq_fsm_start_next_periodic(state, num_channels);
++ }
++ if (st->fsm != FIQ_PASSTHROUGH)
++ fiq_print(FIQDBG_INT, state, "FSMOUT%02d", st->fsm);
++
++ return handled;
++}
++
++
++/**
++ * dwc_otg_fiq_fsm() - Flying State Machine (monster) FIQ
++ * @state: pointer to state struct passed from the banked FIQ mode registers.
++ * @num_channels: set according to the DWC hardware configuration
++ * @dma: pointer to DMA bounce buffers for split transaction slots
++ *
++ * The FSM FIQ performs the low-level tasks that normally would be performed by the microcode
++ * inside an EHCI or similar host controller regarding split transactions. The DWC core
++ * interrupts each and every time a split transaction packet is received or sent successfully.
++ * This results in either an interrupt storm when everything is working "properly", or
++ * the interrupt latency of the system in general breaks time-sensitive periodic split
++ * transactions. Pushing the low-level, but relatively easy state machine work into the FIQ
++ * solves these problems.
++ *
++ * Return: void
++ */
++void notrace dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels)
++{
++ gintsts_data_t gintsts, gintsts_handled;
++ gintmsk_data_t gintmsk;
++ //hfnum_data_t hfnum;
++ haint_data_t haint, haint_handled;
++ haintmsk_data_t haintmsk;
++ int kick_irq = 0;
++
++ gintsts_handled.d32 = 0;
++ haint_handled.d32 = 0;
++
++ gintsts.d32 = FIQ_READ(state->dwc_regs_base + GINTSTS);
++ gintmsk.d32 = FIQ_READ(state->dwc_regs_base + GINTMSK);
++ gintsts.d32 &= gintmsk.d32;
++
++ if (gintsts.b.sofintr) {
++ /* For FSM mode, SOF is required to keep the state machine advance for
++ * certain stages of the periodic pipeline. It's death to mask this
++ * interrupt in that case.
++ */
++
++ if (!fiq_fsm_do_sof(state, num_channels)) {
++ /* Kick IRQ once. Queue advancement means that all pending transactions
++ * will get serviced when the IRQ finally executes.
++ */
++ if (state->gintmsk_saved.b.sofintr == 1)
++ kick_irq |= 1;
++ state->gintmsk_saved.b.sofintr = 0;
++ }
++ gintsts_handled.b.sofintr = 1;
++ }
++
++ if (gintsts.b.hcintr) {
++ int i;
++ haint.d32 = FIQ_READ(state->dwc_regs_base + HAINT);
++ haintmsk.d32 = FIQ_READ(state->dwc_regs_base + HAINTMSK);
++ haint.d32 &= haintmsk.d32;
++ haint_handled.d32 = 0;
++ for (i=0; i<num_channels; i++) {
++ if (haint.b2.chint & (1 << i)) {
++ if(!fiq_fsm_do_hcintr(state, num_channels, i)) {
++ /* HCINT was not handled in FIQ
++ * HAINT is level-sensitive, leading to level-sensitive ginststs.b.hcint bit.
++ * Mask HAINT(i) but keep top-level hcint unmasked.
++ */
++ state->haintmsk_saved.b2.chint &= ~(1 << i);
++ } else {
++ /* do_hcintr cleaned up after itself, but clear haint */
++ haint_handled.b2.chint |= (1 << i);
++ }
++ }
++ }
++
++ if (haint_handled.b2.chint) {
++ FIQ_WRITE(state->dwc_regs_base + HAINT, haint_handled.d32);
++ }
++
++ if (haintmsk.d32 != (haintmsk.d32 & state->haintmsk_saved.d32)) {
++ /*
++ * This is necessary to avoid multiple retriggers of the MPHI in the case
++ * where interrupts are held off and HCINTs start to pile up.
++ * Only wake up the IRQ if a new interrupt came in, was not handled and was
++ * masked.
++ */
++ haintmsk.d32 &= state->haintmsk_saved.d32;
++ FIQ_WRITE(state->dwc_regs_base + HAINTMSK, haintmsk.d32);
++ kick_irq |= 1;
++ }
++ /* Top-Level interrupt - always handled because it's level-sensitive */
++ gintsts_handled.b.hcintr = 1;
++ }
++
++
++ /* Clear the bits in the saved register that were not handled but were triggered. */
++ state->gintmsk_saved.d32 &= ~(gintsts.d32 & ~gintsts_handled.d32);
++
++ /* FIQ didn't handle something - mask has changed - write new mask */
++ if (gintmsk.d32 != (gintmsk.d32 & state->gintmsk_saved.d32)) {
++ gintmsk.d32 &= state->gintmsk_saved.d32;
++ gintmsk.b.sofintr = 1;
++ FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
++// fiq_print(FIQDBG_INT, state, "KICKGINT");
++// fiq_print(FIQDBG_INT, state, "%08x", gintmsk.d32);
++// fiq_print(FIQDBG_INT, state, "%08x", state->gintmsk_saved.d32);
++ kick_irq |= 1;
++ }
++
++ if (gintsts_handled.d32) {
++ /* Only applies to edge-sensitive bits in GINTSTS */
++ FIQ_WRITE(state->dwc_regs_base + GINTSTS, gintsts_handled.d32);
++ }
++
++ /* We got an interrupt, didn't handle it. */
++ if (kick_irq) {
++ state->mphi_int_count++;
++ FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
++ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
++
++ }
++ state->fiq_done++;
++ mb();
++}
++
++
++/**
++ * dwc_otg_fiq_nop() - FIQ "lite"
++ * @state: pointer to state struct passed from the banked FIQ mode registers.
++ *
++ * The "nop" handler does not intervene on any interrupts other than SOF.
++ * It is limited in scope to deciding at each SOF if the IRQ SOF handler (which deals
++ * with non-periodic/periodic queues) needs to be kicked.
++ *
++ * This is done to hold off the SOF interrupt, which occurs at a rate of 8000 per second.
++ *
++ * Return: void
++ */
++void notrace dwc_otg_fiq_nop(struct fiq_state *state)
++{
++ gintsts_data_t gintsts, gintsts_handled;
++ gintmsk_data_t gintmsk;
++ hfnum_data_t hfnum;
++
++ hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM);
++ gintsts.d32 = FIQ_READ(state->dwc_regs_base + GINTSTS);
++ gintmsk.d32 = FIQ_READ(state->dwc_regs_base + GINTMSK);
++ gintsts.d32 &= gintmsk.d32;
++ gintsts_handled.d32 = 0;
++
++ if (gintsts.b.sofintr) {
++ if (!state->kick_np_queues &&
++ dwc_frame_num_gt(state->next_sched_frame, hfnum.b.frnum)) {
++ /* SOF handled, no work to do, just ACK interrupt */
++ gintsts_handled.b.sofintr = 1;
++ } else {
++ /* Kick IRQ */
++ state->gintmsk_saved.b.sofintr = 0;
++ }
++ }
++
++ /* Reset handled interrupts */
++ if(gintsts_handled.d32) {
++ FIQ_WRITE(state->dwc_regs_base + GINTSTS, gintsts_handled.d32);
++ }
++
++ /* Clear the bits in the saved register that were not handled but were triggered. */
++ state->gintmsk_saved.d32 &= ~(gintsts.d32 & ~gintsts_handled.d32);
++
++ /* We got an interrupt, didn't handle it and want to mask it */
++ if (~(state->gintmsk_saved.d32)) {
++ state->mphi_int_count++;
++ gintmsk.d32 &= state->gintmsk_saved.d32;
++ FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32);
++ /* Force a clear before another dummy send */
++ FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
++ FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send);
++ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
++
++ }
++ state->fiq_done++;
++ mb();
++}
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h 2014-04-24 16:04:39.819124254 +0200
+@@ -0,0 +1,353 @@
++/*
++ * dwc_otg_fiq_fsm.h - Finite state machine FIQ header definitions
++ *
++ * Copyright (c) 2013 Raspberry Pi Foundation
++ *
++ * Author: Jonathan Bell <jonathan@raspberrypi.org>
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * * Neither the name of Raspberry Pi nor the
++ * names of its contributors may be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * This FIQ implements functionality that performs split transactions on
++ * the dwc_otg hardware without any outside intervention. A split transaction
++ * is "queued" by nominating a specific host channel to perform the entirety
++ * of a split transaction. This FIQ will then perform the microframe-precise
++ * scheduling required in each phase of the transaction until completion.
++ *
++ * The FIQ functionality has been surgically implanted into the Synopsys
++ * vendor-provided driver.
++ *
++ */
++
++#ifndef DWC_OTG_FIQ_FSM_H_
++#define DWC_OTG_FIQ_FSM_H_
++
++#include "dwc_otg_regs.h"
++#include "dwc_otg_cil.h"
++#include "dwc_otg_hcd.h"
++#include <linux/kernel.h>
++#include <linux/irqflags.h>
++#include <linux/string.h>
++#include <asm/barrier.h>
++
++#if 0
++#define FLAME_ON(x) \
++do { \
++ int gpioreg; \
++ \
++ gpioreg = readl(__io_address(0x20200000+0x8)); \
++ gpioreg &= ~(7 << (x-20)*3); \
++ gpioreg |= 0x1 << (x-20)*3; \
++ writel(gpioreg, __io_address(0x20200000+0x8)); \
++ \
++ writel(1<<x, __io_address(0x20200000+(0x1C))); \
++} while (0)
++
++#define FLAME_OFF(x) \
++do { \
++ writel(1<<x, __io_address(0x20200000+(0x28))); \
++} while (0)
++#else
++#define FLAME_ON(x) do { } while (0)
++#define FLAME_OFF(X) do { } while (0)
++#endif
++
++/* This is a quick-and-dirty arch-specific register read/write. We know that
++ * writes to a peripheral on BCM2835 will always arrive in-order, also that
++ * reads and writes are executed in-order therefore the need for memory barriers
++ * is obviated if we're only talking to USB.
++ */
++#define FIQ_WRITE(_addr_,_data_) (*(volatile unsigned int *) (_addr_) = (_data_))
++#define FIQ_READ(_addr_) (*(volatile unsigned int *) (_addr_))
++
++/* FIQ-ified register definitions. Offsets are from dwc_regs_base. */
++#define GINTSTS 0x014
++#define GINTMSK 0x018
++/* Debug register. Poll the top of the received packets FIFO. */
++#define GRXSTSR 0x01C
++#define HFNUM 0x408
++#define HAINT 0x414
++#define HAINTMSK 0x418
++#define HPRT0 0x440
++
++/* HC_regs start from an offset of 0x500 */
++#define HC_START 0x500
++#define HC_OFFSET 0x020
++
++#define HC_DMA 0x514
++
++#define HCCHAR 0x00
++#define HCSPLT 0x04
++#define HCINT 0x08
++#define HCINTMSK 0x0C
++#define HCTSIZ 0x10
++
++#define ISOC_XACTPOS_ALL 0b11
++#define ISOC_XACTPOS_BEGIN 0b10
++#define ISOC_XACTPOS_MID 0b00
++#define ISOC_XACTPOS_END 0b01
++
++#define DWC_PID_DATA2 0b01
++#define DWC_PID_MDATA 0b11
++#define DWC_PID_DATA1 0b10
++#define DWC_PID_DATA0 0b00
++
++typedef struct {
++ volatile void* base;
++ volatile void* ctrl;
++ volatile void* outdda;
++ volatile void* outddb;
++ volatile void* intstat;
++} mphi_regs_t;
++
++
++enum fiq_debug_level {
++ FIQDBG_SCHED = (1 << 0),
++ FIQDBG_INT = (1 << 1),
++ FIQDBG_ERR = (1 << 2),
++ FIQDBG_PORTHUB = (1 << 3),
++};
++
++struct fiq_state;
++
++extern void _fiq_print (enum fiq_debug_level dbg_lvl, volatile struct fiq_state *state, char *fmt, ...);
++#if 0
++#define fiq_print _fiq_print
++#else
++#define fiq_print(x, y, ...)
++#endif
++
++extern bool fiq_enable, fiq_fsm_enable;
++extern ushort nak_holdoff;
++
++/**
++ * enum fiq_fsm_state - The FIQ FSM states.
++ *
++ * This is the "core" of the FIQ FSM. Broadly, the FSM states follow the
++ * USB2.0 specification for host responses to various transaction states.
++ * There are modifications to this host state machine because of a variety of
++ * quirks and limitations in the dwc_otg hardware.
++ *
++ * The fsm state is also used to communicate back to the driver on completion of
++ * a split transaction. The end states are used in conjunction with the interrupts
++ * raised by the final transaction.
++ */
++enum fiq_fsm_state {
++ /* FIQ isn't enabled for this host channel */
++ FIQ_PASSTHROUGH = 0,
++ /* For the first interrupt received for this channel,
++ * the FIQ has to ack any interrupts indicating success. */
++ FIQ_PASSTHROUGH_ERRORSTATE = 31,
++ /* Nonperiodic state groups */
++ FIQ_NP_SSPLIT_STARTED = 1,
++ FIQ_NP_SSPLIT_RETRY = 2,
++ FIQ_NP_OUT_CSPLIT_RETRY = 3,
++ FIQ_NP_IN_CSPLIT_RETRY = 4,
++ FIQ_NP_SPLIT_DONE = 5,
++ FIQ_NP_SPLIT_LS_ABORTED = 6,
++ /* This differentiates a HS transaction error from a LS one
++ * (handling the hub state is different) */
++ FIQ_NP_SPLIT_HS_ABORTED = 7,
++
++ /* Periodic state groups */
++ /* Periodic transactions are either started directly by the IRQ handler
++ * or deferred if the TT is already in use.
++ */
++ FIQ_PER_SSPLIT_QUEUED = 8,
++ FIQ_PER_SSPLIT_STARTED = 9,
++ FIQ_PER_SSPLIT_LAST = 10,
++
++
++ FIQ_PER_ISO_OUT_PENDING = 11,
++ FIQ_PER_ISO_OUT_ACTIVE = 12,
++ FIQ_PER_ISO_OUT_LAST = 13,
++ FIQ_PER_ISO_OUT_DONE = 27,
++
++ FIQ_PER_CSPLIT_WAIT = 14,
++ FIQ_PER_CSPLIT_NYET1 = 15,
++ FIQ_PER_CSPLIT_BROKEN_NYET1 = 28,
++ FIQ_PER_CSPLIT_NYET_FAFF = 29,
++ /* For multiple CSPLITs (large isoc IN, or delayed interrupt) */
++ FIQ_PER_CSPLIT_POLL = 16,
++ /* The last CSPLIT for a transaction has been issued, differentiates
++ * for the state machine to queue the next packet.
++ */
++ FIQ_PER_CSPLIT_LAST = 17,
++
++ FIQ_PER_SPLIT_DONE = 18,
++ FIQ_PER_SPLIT_LS_ABORTED = 19,
++ FIQ_PER_SPLIT_HS_ABORTED = 20,
++ FIQ_PER_SPLIT_NYET_ABORTED = 21,
++ /* Frame rollover has occurred without the transaction finishing. */
++ FIQ_PER_SPLIT_TIMEOUT = 22,
++
++ /* FIQ-accelerated HS Isochronous state groups */
++ FIQ_HS_ISOC_TURBO = 23,
++ /* For interval > 1, SOF wakes up the isochronous FSM */
++ FIQ_HS_ISOC_SLEEPING = 24,
++ FIQ_HS_ISOC_DONE = 25,
++ FIQ_HS_ISOC_ABORTED = 26,
++ FIQ_DEQUEUE_ISSUED = 30,
++ FIQ_TEST = 32,
++};
++
++struct fiq_stack {
++ int magic1;
++ uint8_t stack[2048];
++ int magic2;
++};
++
++
++/**
++ * struct fiq_dma_info - DMA bounce buffer utilisation information (per-channel)
++ * @index: Number of slots reported used for IN transactions / number of slots
++ * transmitted for an OUT transaction
++ * @slot_len[6]: Number of actual transfer bytes in each slot (255 if unused)
++ *
++ * Split transaction transfers can have variable length depending on other bus
++ * traffic. The OTG core DMA engine requires 4-byte aligned addresses therefore
++ * each transaction needs a guaranteed aligned address. A maximum of 6 split transfers
++ * can happen per-frame.
++ */
++struct fiq_dma_info {
++ u8 index;
++ u8 slot_len[6];
++};
++
++struct __attribute__((packed)) fiq_split_dma_slot {
++ u8 buf[188];
++};
++
++struct fiq_dma_channel {
++ struct __attribute__((packed)) fiq_split_dma_slot index[6];
++};
++
++struct fiq_dma_blob {
++ struct __attribute__((packed)) fiq_dma_channel channel[0];
++};
++
++/**
++ * struct fiq_hs_isoc_info - USB2.0 isochronous data
++ * @iso_frame: Pointer to the array of OTG URB iso_frame_descs.
++ * @nrframes: Total length of iso_frame_desc array
++ * @index: Current index (FIQ-maintained)
++ *
++ */
++struct fiq_hs_isoc_info {
++ struct dwc_otg_hcd_iso_packet_desc *iso_desc;
++ unsigned int nrframes;
++ unsigned int index;
++};
++
++/**
++ * struct fiq_channel_state - FIQ state machine storage
++ * @fsm: Current state of the channel as understood by the FIQ
++ * @nr_errors: Number of transaction errors on this split-transaction
++ * @hub_addr: SSPLIT/CSPLIT destination hub
++ * @port_addr: SSPLIT/CSPLIT destination port - always 1 if single TT hub
++ * @nrpackets: For isoc OUT, the number of split-OUT packets to transmit. For
++ * split-IN, number of CSPLIT data packets that were received.
++ * @hcchar_copy:
++ * @hcsplt_copy:
++ * @hcintmsk_copy:
++ * @hctsiz_copy: Copies of the host channel registers.
++ * For use as scratch, or for returning state.
++ *
++ * The fiq_channel_state is state storage between interrupts for a host channel. The
++ * FSM state is stored here. Members of this structure must only be set up by the
++ * driver prior to enabling the FIQ for this host channel, and not touched until the FIQ
++ * has updated the state to either a COMPLETE state group or ABORT state group.
++ */
++
++struct fiq_channel_state {
++ enum fiq_fsm_state fsm;
++ unsigned int nr_errors;
++ unsigned int hub_addr;
++ unsigned int port_addr;
++ /* Hardware bug workaround: sometimes channel halt interrupts are
++ * delayed until the next SOF. Keep track of when we expected to get interrupted. */
++ unsigned int expected_uframe;
++ /* in/out for communicating number of dma buffers used, or number of ISOC to do */
++ unsigned int nrpackets;
++ struct fiq_dma_info dma_info;
++ struct fiq_hs_isoc_info hs_isoc_info;
++ /* Copies of HC registers - in/out communication from/to IRQ handler
++ * and for ease of channel setup. A bit of mungeing is performed - for
++ * example the hctsiz.b.maxp is _always_ the max packet size of the endpoint.
++ */
++ hcchar_data_t hcchar_copy;
++ hcsplt_data_t hcsplt_copy;
++ hcint_data_t hcint_copy;
++ hcintmsk_data_t hcintmsk_copy;
++ hctsiz_data_t hctsiz_copy;
++ hcdma_data_t hcdma_copy;
++};
++
++/**
++ * struct fiq_state - top-level FIQ state machine storage
++ * @mphi_regs: virtual address of the MPHI peripheral register file
++ * @dwc_regs_base: virtual address of the base of the DWC core register file
++ * @dma_base: physical address for the base of the DMA bounce buffers
++ * @dummy_send: Scratch area for sending a fake message to the MPHI peripheral
++ * @gintmsk_saved: Top-level mask of interrupts that the FIQ has not handled.
++ * Used for determining which interrupts fired to set off the IRQ handler.
++ * @haintmsk_saved: Mask of interrupts from host channels that the FIQ did not handle internally.
++ * @np_count: Non-periodic transactions in the active queue
++ * @np_sent: Count of non-periodic transactions that have completed
++ * @next_sched_frame: For periodic transactions handled by the driver's SOF-driven queuing mechanism,
++ * this is the next frame on which a SOF interrupt is required. Used to hold off
++ * passing SOF through to the driver until necessary.
++ * @channel[n]: Per-channel FIQ state. Allocated during init depending on the number of host
++ * channels configured into the core logic.
++ *
++ * This is passed as the first argument to the dwc_otg_fiq_fsm top-level FIQ handler from the asm stub.
++ * It contains top-level state information.
++ */
++struct fiq_state {
++ mphi_regs_t mphi_regs;
++ void *dwc_regs_base;
++ dma_addr_t dma_base;
++ struct fiq_dma_blob *fiq_dmab;
++ void *dummy_send;
++ gintmsk_data_t gintmsk_saved;
++ haintmsk_data_t haintmsk_saved;
++ int mphi_int_count;
++ unsigned int fiq_done;
++ unsigned int kick_np_queues;
++ unsigned int next_sched_frame;
++#ifdef FIQ_DEBUG
++ char * buffer;
++ unsigned int bufsiz;
++#endif
++ struct fiq_channel_state channel[0];
++};
++
++extern int fiq_fsm_too_late(struct fiq_state *st, int n);
++
++extern int fiq_fsm_tt_in_use(struct fiq_state *st, int num_channels, int n);
++
++extern void dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels);
++
++extern void dwc_otg_fiq_nop(struct fiq_state *state);
++
++#endif /* DWC_OTG_FIQ_FSM_H_ */
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_fiq_stub.S 2014-04-24 16:04:39.819124254 +0200
+@@ -0,0 +1,81 @@
++/*
++ * dwc_otg_fiq_fsm.S - assembly stub for the FSM FIQ
++ *
++ * Copyright (c) 2013 Raspberry Pi Foundation
++ *
++ * Author: Jonathan Bell <jonathan@raspberrypi.org>
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ * * Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * * Neither the name of Raspberry Pi nor the
++ * names of its contributors may be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ */
++
++
++#include <asm/assembler.h>
++#include <linux/linkage.h>
++
++
++.text
++
++.global _dwc_otg_fiq_stub_end;
++
++/**
++ * _dwc_otg_fiq_stub() - entry copied to the FIQ vector page to allow
++ * a C-style function call with arguments from the FIQ banked registers.
++ * r0 = &hcd->fiq_state
++ * r1 = &hcd->num_channels
++ * r2 = &hcd->dma_buffers
++ * Tramples: r0, r1, r2, r4, fp, ip
++ */
++
++ENTRY(_dwc_otg_fiq_stub)
++ /* Stash unbanked regs - SP will have been set up for us */
++ mov ip, sp;
++ stmdb sp!, {r0-r12, lr};
++#ifdef FIQ_DEBUG
++ // Cycle profiling - read cycle counter at start
++ mrc p15, 0, r5, c15, c12, 1;
++#endif
++ /* r11 = fp, don't trample it */
++ mov r4, fp;
++ /* set EABI frame size */
++ sub fp, ip, #512;
++
++ /* for fiq NOP mode - just need state */
++ mov r0, r8;
++ /* r9 = num_channels */
++ mov r1, r9;
++ /* r10 = struct *dma_bufs */
++// mov r2, r10;
++
++ /* r4 = &fiq_c_function */
++ blx r4;
++#ifdef FIQ_DEBUG
++ mrc p15, 0, r4, c15, c12, 1;
++ subs r5, r5, r4;
++ // r5 is now the cycle count time for executing the FIQ. Store it somewhere?
++#endif
++ ldmia sp!, {r0-r12, lr};
++ subs pc, lr, #4;
++_dwc_otg_fiq_stub_end:
++END(_dwc_otg_fiq_stub)
++
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 2014-04-24 16:04:39.819124254 +0200
+@@ -0,0 +1,4188 @@
+
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $
@@ -68572,9 +71052,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+
+#include "dwc_otg_hcd.h"
+#include "dwc_otg_regs.h"
-+#include "dwc_otg_mphi_fix.h"
++#include "dwc_otg_fiq_fsm.h"
+
-+extern bool microframe_schedule, nak_holdoff_enable;
++extern bool microframe_schedule;
++extern uint16_t fiq_fsm_mask, nak_holdoff;
+
+//#define DEBUG_HOST_CHANNELS
+#ifdef DEBUG_HOST_CHANNELS
@@ -68584,12 +71065,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+static int last_sel_trans_num_avail_hc_at_end = 0;
+#endif /* DEBUG_HOST_CHANNELS */
+
-+extern int g_next_sched_frame, g_np_count, g_np_sent;
-+
-+extern haint_data_t haint_saved;
-+extern hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
-+extern hcint_data_t hcint_saved[MAX_EPS_CHANNELS];
-+extern gintsts_data_t ginsts_saved;
+
+dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
+{
@@ -68822,7 +71297,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ */
+ dwc_otg_hcd->flags.b.port_connect_status_change = 1;
+ dwc_otg_hcd->flags.b.port_connect_status = 0;
-+ if(fiq_fix_enable)
++ if(fiq_enable)
+ local_fiq_disable();
+ /*
+ * Shutdown any transfers in process by clearing the Tx FIFO Empty
@@ -68919,20 +71394,15 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ channel->qh = NULL;
+ }
+ }
-+ if(fiq_split_enable) {
++ if(fiq_fsm_enable) {
+ for(i=0; i < 128; i++) {
+ dwc_otg_hcd->hub_port[i] = 0;
+ }
-+ haint_saved.d32 = 0;
-+ for(i=0; i < MAX_EPS_CHANNELS; i++) {
-+ hcint_saved[i].d32 = 0;
-+ hcintmsk_saved[i].d32 = 0;
-+ }
+ }
+
+ }
+
-+ if(fiq_fix_enable)
++ if(fiq_enable)
+ local_fiq_enable();
+
+ if (dwc_otg_hcd->fops->disconnect) {
@@ -69069,7 +71539,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ }
+#endif
+ intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk);
-+ if(!intr_mask.b.sofintr) needs_scheduling = 1;
++ if(!intr_mask.b.sofintr || fiq_enable) needs_scheduling = 1;
+ if((((dwc_otg_qh_t *)ep_handle)->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP))
+ /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */
+ needs_scheduling = 0;
@@ -69140,6 +71610,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ if (urb_qtd->in_process && qh->channel) {
+ /* The QTD is in process (it has been assigned to a channel). */
+ if (hcd->flags.b.port_connect_status) {
++ int n = qh->channel->hc_num;
+ /*
+ * If still connected (i.e. in host mode), halt the
+ * channel so it can be used for other transfers. If
@@ -69147,10 +71618,14 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ * written to halt the channel since the core is in
+ * device mode.
+ */
++ /* In FIQ FSM mode, we need to shut down carefully.
++ * The FIQ may attempt to restart a disabled channel */
++ if (fiq_fsm_enable && (hcd->fiq_state->channel[n].fsm != FIQ_PASSTHROUGH)) {
++ hcd->fiq_state->channel[n].fsm = FIQ_DEQUEUE_ISSUED;
++ }
+ dwc_otg_hc_halt(hcd->core_if, qh->channel,
+ DWC_OTG_HC_XFER_URB_DEQUEUE);
+
-+ dwc_otg_hcd_release_port(hcd, qh);
+ }
+ }
+
@@ -69286,7 +71761,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+
+ usb_hcd_giveback_urb(hcd->priv, urb, urb->status);
+
-+ fiq_print(FIQDBG_PORTHUB, "COMPLETE");
+
+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
+ }
@@ -69381,6 +71855,34 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ cil_hcd_start(core_if);
+}
+
++void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num)
++{
++ struct fiq_channel_state *st = &hcd->fiq_state->channel[num];
++ struct fiq_dma_blob *blob = hcd->fiq_dmab;
++ int i;
++
++ st->fsm = FIQ_PASSTHROUGH;
++ st->hcchar_copy.d32 = 0;
++ st->hcsplt_copy.d32 = 0;
++ st->hcint_copy.d32 = 0;
++ st->hcintmsk_copy.d32 = 0;
++ st->hctsiz_copy.d32 = 0;
++ st->hcdma_copy.d32 = 0;
++ st->nr_errors = 0;
++ st->hub_addr = 0;
++ st->port_addr = 0;
++ st->expected_uframe = 0;
++ st->nrpackets = 0;
++ st->dma_info.index = 0;
++ for (i = 0; i < 6; i++)
++ st->dma_info.slot_len[i] = 255;
++ st->hs_isoc_info.index = 0;
++ st->hs_isoc_info.iso_desc = NULL;
++ st->hs_isoc_info.nrframes = 0;
++
++ DWC_MEMSET(&blob->channel[num].index[0], 0x6b, 1128);
++}
++
+/**
+ * Frees secondary storage associated with the dwc_otg_hcd structure contained
+ * in the struct usb_hcd field.
@@ -69434,6 +71936,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
+ DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
+ DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
++ DWC_FREE(dwc_otg_hcd->fiq_state);
+
+#ifdef DWC_DEV_SRPCAP
+ if (dwc_otg_hcd->core_if->power_down == 2 &&
@@ -69506,6 +72009,59 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ channel);
+ }
+
++ if (fiq_enable) {
++ hcd->fiq_state = DWC_ALLOC(sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels));
++ if (!hcd->fiq_state) {
++ retval = -DWC_E_NO_MEMORY;
++ DWC_ERROR("%s: cannot allocate fiq_state structure\n", __func__);
++ dwc_otg_hcd_free(hcd);
++ goto out;
++ }
++ DWC_MEMSET(hcd->fiq_state, 0, (sizeof(struct fiq_state) + (sizeof(struct fiq_channel_state) * num_channels)));
++
++ for (i = 0; i < num_channels; i++) {
++ hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH;
++ }
++ hcd->fiq_state->dummy_send = DWC_ALLOC_ATOMIC(16);
++
++ hcd->fiq_stack = DWC_ALLOC(sizeof(struct fiq_stack));
++ if (!hcd->fiq_stack) {
++ retval = -DWC_E_NO_MEMORY;
++ DWC_ERROR("%s: cannot allocate fiq_stack structure\n", __func__);
++ dwc_otg_hcd_free(hcd);
++ goto out;
++ }
++ hcd->fiq_stack->magic1 = 0xDEADBEEF;
++ hcd->fiq_stack->magic2 = 0xD00DFEED;
++ hcd->fiq_state->gintmsk_saved.d32 = ~0;
++ hcd->fiq_state->haintmsk_saved.b2.chint = ~0;
++
++ /* This bit is terrible and uses no API, but necessary. The FIQ has no concept of DMA pools
++ * (and if it did, would be a lot slower). This allocates a chunk of memory (~9kiB for 8 host channels)
++ * for use as transaction bounce buffers in a 2-D array. Our access into this chunk is done by some
++ * moderately readable array casts.
++ */
++ hcd->fiq_dmab = DWC_DMA_ALLOC((sizeof(struct fiq_dma_channel) * num_channels), &hcd->fiq_state->dma_base);
++ DWC_WARN("FIQ DMA bounce buffers: virt = 0x%08x dma = 0x%08x len=%d",
++ (unsigned int)hcd->fiq_dmab, (unsigned int)hcd->fiq_state->dma_base,
++ sizeof(struct fiq_dma_channel) * num_channels);
++
++ DWC_MEMSET(hcd->fiq_dmab, 0x6b, 9024);
++
++ /* pointer for debug in fiq_print */
++ hcd->fiq_state->fiq_dmab = hcd->fiq_dmab;
++ if (fiq_fsm_enable) {
++ int i;
++ for (i=0; i < hcd->core_if->core_params->host_channels; i++) {
++ dwc_otg_cleanup_fiq_channel(hcd, i);
++ }
++ DWC_PRINTF("FIQ FSM acceleration enabled for :\n%s%s%s",
++ (fiq_fsm_mask & 0x1) ? "Non-periodic Split Transactions\n" : "",
++ (fiq_fsm_mask & 0x2) ? "Periodic Split Transactions\n" : "",
++ (fiq_fsm_mask & 0x4) ? "High-Speed Isochronous Endpoints\n" : "");
++ }
++ }
++
+ /* Initialize the Connection timeout timer. */
+ hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer",
+ dwc_otg_hcd_connect_timeout, 0);
@@ -69703,7 +72259,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ hc->do_split = 1;
+ hc->xact_pos = qtd->isoc_split_pos;
+ /* We don't need to do complete splits anymore */
-+ if(fiq_split_enable)
++// if(fiq_fsm_enable)
++ if (0)
+ hc->complete_split = qtd->complete_split = 0;
+ else
+ hc->complete_split = qtd->complete_split;
@@ -69854,62 +72411,487 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ hc->qh = qh;
+}
+
-+/*
-+** Check the transaction to see if the port / hub has already been assigned for
-+** a split transaction
-+**
-+** Return 0 - Port is already in use
-+*/
-+int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
++
++/**
++ * fiq_fsm_transaction_suitable() - Test a QH for compatibility with the FIQ
++ * @qh: pointer to the endpoint's queue head
++ *
++ * Transaction start/end control flow is grafted onto the existing dwc_otg
++ * mechanisms, to avoid spaghettifying the functions more than they already are.
++ * This function's eligibility check is altered by debug parameter.
++ *
++ * Returns: 0 for unsuitable, 1 implies the FIQ can be enabled for this transaction.
++ */
++
++int fiq_fsm_transaction_suitable(dwc_otg_qh_t *qh)
+{
-+ uint32_t hub_addr, port_addr;
++ if (qh->do_split) {
++ switch (qh->ep_type) {
++ case UE_CONTROL:
++ case UE_BULK:
++ if (fiq_fsm_mask & (1 << 0))
++ return 1;
++ break;
++ case UE_INTERRUPT:
++ case UE_ISOCHRONOUS:
++ if (fiq_fsm_mask & (1 << 1))
++ return 1;
++ break;
++ default:
++ break;
++ }
++ } else if (qh->ep_type == UE_ISOCHRONOUS) {
++ if (fiq_fsm_mask & (1 << 2)) {
++ /* HS ISOCH support. We test for compatibility:
++ * - DWORD aligned buffers
++ * - Must be at least 2 transfers (otherwise pointless to use the FIQ)
++ * If yes, then the fsm enqueue function will handle the state machine setup.
++ */
++ dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
++ dwc_otg_hcd_urb_t *urb = qtd->urb;
++ struct dwc_otg_hcd_iso_packet_desc (*iso_descs)[0] = &urb->iso_descs;
++ int nr_iso_frames = urb->packet_count;
++ int i;
++ uint32_t ptr;
+
-+ if(!fiq_split_enable)
-+ return 0;
++ if (nr_iso_frames < 2)
++ return 0;
++ for (i = 0; i < nr_iso_frames; i++) {
++ ptr = urb->dma + iso_descs[i]->offset;
++ if (ptr & 0x3) {
++ printk_ratelimited("%s: Non-Dword aligned isochronous frame offset."
++ " Cannot queue FIQ-accelerated transfer to device %d endpoint %d\n",
++ __FUNCTION__, qh->channel->dev_addr, qh->channel->ep_num);
++ return 0;
++ }
++ }
++ return 1;
++ }
++ }
++ return 0;
++}
+
-+ hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
++/**
++ * fiq_fsm_setup_periodic_dma() - Set up DMA bounce buffers
++ * @hcd: Pointer to the dwc_otg_hcd struct
++ * @qh: Pointer to the endpoint's queue head
++ *
++ * Periodic split transactions are transmitted modulo 188 bytes.
++ * This necessitates slicing data up into buckets for isochronous out
++ * and fixing up the DMA address for all IN transfers.
++ *
++ * Returns 1 if the DMA bounce buffers have been used, 0 if the default
++ * HC buffer has been used.
++ */
++int fiq_fsm_setup_periodic_dma(dwc_otg_hcd_t *hcd, struct fiq_channel_state *st, dwc_otg_qh_t *qh)
++ {
++ int frame_length, i = 0;
++ uint8_t *ptr = NULL;
++ dwc_hc_t *hc = qh->channel;
++ struct fiq_dma_blob *blob;
++ struct dwc_otg_hcd_iso_packet_desc *frame_desc;
+
-+ if(hcd->hub_port[hub_addr] & (1 << port_addr))
-+ {
-+ fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count);
++ for (i = 0; i < 6; i++) {
++ st->dma_info.slot_len[i] = 255;
++ }
++ st->dma_info.index = 0;
++ i = 0;
++ if (hc->ep_is_in) {
++ /*
++ * Set dma_regs to bounce buffer. FIQ will update the
++ * state depending on transaction progress.
++ */
++ blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
++ st->hcdma_copy.d32 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
++ /* Calculate the max number of CSPLITS such that the FIQ can time out
++ * a transaction if it fails.
++ */
++ frame_length = st->hcchar_copy.b.mps;
++ do {
++ i++;
++ frame_length -= 188;
++ } while (frame_length >= 0);
++ st->nrpackets = i;
++ return 1;
++ } else {
++ if (qh->ep_type == UE_ISOCHRONOUS) {
+
-+ qh->skip_count++;
++ dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
+
-+ if(qh->skip_count > 40000)
-+ {
-+ printk_once(KERN_ERR "Error: Having to skip port allocation");
-+ local_fiq_disable();
-+ BUG();
++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
++ frame_length = frame_desc->length;
++
++ /* Virtual address for bounce buffers */
++ blob = hcd->fiq_dmab;
++
++ ptr = qtd->urb->buf + frame_desc->offset;
++ if (frame_length == 0) {
++ /*
++ * for isochronous transactions, we must still transmit a packet
++ * even if the length is zero.
++ */
++ st->dma_info.slot_len[0] = 0;
++ st->nrpackets = 1;
++ } else {
++ do {
++ if (frame_length <= 188) {
++ dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, frame_length);
++ st->dma_info.slot_len[i] = frame_length;
++ ptr += frame_length;
++ } else {
++ dwc_memcpy(&blob->channel[hc->hc_num].index[i].buf[0], ptr, 188);
++ st->dma_info.slot_len[i] = 188;
++ ptr += 188;
++ }
++ i++;
++ frame_length -= 188;
++ } while (frame_length > 0);
++ st->nrpackets = i;
++ }
++ ptr = qtd->urb->buf + frame_desc->offset;
++ /* Point the HC at the DMA address of the bounce buffers */
++ blob = (struct fiq_dma_blob *) hcd->fiq_state->dma_base;
++ st->hcdma_copy.d32 = (uint32_t) &blob->channel[hc->hc_num].index[0].buf[0];
++
++ /* fixup xfersize to the actual packet size */
++ st->hctsiz_copy.b.pid = 0;
++ st->hctsiz_copy.b.xfersize = st->dma_info.slot_len[0];
++ return 1;
++ } else {
++ /* For interrupt, single OUT packet required, goes in the SSPLIT from hc_buff. */
+ return 0;
+ }
-+ return 1;
+ }
-+ else
-+ {
-+ qh->skip_count = 0;
-+ hcd->hub_port[hub_addr] |= 1 << port_addr;
-+ fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
-+#ifdef FIQ_DEBUG
-+ hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd);
-+#endif
++}
++
++/*
++ * Pushing a periodic request into the queue near the EOF1 point
++ * in a microframe causes erroneous behaviour (frmovrun) interrupt.
++ * Usually, the request goes out on the bus causing a transfer but
++ * the core does not transfer the data to memory.
++ * This guard interval (in number of 60MHz clocks) is required which
++ * must cater for CPU latency between reading the value and enabling
++ * the channel.
++ */
++#define PERIODIC_FRREM_BACKOFF 1000
++
++int fiq_fsm_queue_isoc_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
++{
++ dwc_hc_t *hc = qh->channel;
++ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
++ dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
++ int frame;
++ struct fiq_channel_state *st = &hcd->fiq_state->channel[hc->hc_num];
++ int xfer_len, nrpackets;
++ hcdma_data_t hcdma;
++ hfnum_data_t hfnum;
++
++ if (st->fsm != FIQ_PASSTHROUGH)
+ return 0;
++
++ st->nr_errors = 0;
++
++ st->hcchar_copy.d32 = 0;
++ st->hcchar_copy.b.mps = hc->max_packet;
++ st->hcchar_copy.b.epdir = hc->ep_is_in;
++ st->hcchar_copy.b.devaddr = hc->dev_addr;
++ st->hcchar_copy.b.epnum = hc->ep_num;
++ st->hcchar_copy.b.eptype = hc->ep_type;
++
++ st->hcintmsk_copy.b.chhltd = 1;
++
++ frame = dwc_otg_hcd_get_frame_number(hcd);
++ st->hcchar_copy.b.oddfrm = (frame & 0x1) ? 0 : 1;
++
++ st->hcchar_copy.b.lspddev = 0;
++ /* Enable the channel later as a final register write. */
++
++ st->hcsplt_copy.d32 = 0;
++
++ st->hs_isoc_info.iso_desc = (struct dwc_otg_hcd_iso_packet_desc *) &qtd->urb->iso_descs;
++ st->hs_isoc_info.nrframes = qtd->urb->packet_count;
++ /* grab the next DMA address offset from the array */
++ st->hcdma_copy.d32 = qtd->urb->dma;
++ hcdma.d32 = st->hcdma_copy.d32 + st->hs_isoc_info.iso_desc[0].offset;
++
++ /* We need to set multi_count. This is a bit tricky - has to be set per-transaction as
++ * the core needs to be told to send the correct number. Caution: for IN transfers,
++ * this is always set to the maximum size of the endpoint. */
++ xfer_len = st->hs_isoc_info.iso_desc[0].length;
++ nrpackets = (xfer_len + st->hcchar_copy.b.mps - 1) / st->hcchar_copy.b.mps;
++ if (nrpackets == 0)
++ nrpackets = 1;
++ st->hcchar_copy.b.multicnt = nrpackets;
++ st->hctsiz_copy.b.pktcnt = nrpackets;
++
++ /* Initial PID also needs to be set */
++ if (st->hcchar_copy.b.epdir == 0) {
++ st->hctsiz_copy.b.xfersize = xfer_len;
++ switch (st->hcchar_copy.b.multicnt) {
++ case 1:
++ st->hctsiz_copy.b.pid = DWC_PID_DATA0;
++ break;
++ case 2:
++ case 3:
++ st->hctsiz_copy.b.pid = DWC_PID_MDATA;
++ break;
++ }
++
++ } else {
++ st->hctsiz_copy.b.xfersize = nrpackets * st->hcchar_copy.b.mps;
++ switch (st->hcchar_copy.b.multicnt) {
++ case 1:
++ st->hctsiz_copy.b.pid = DWC_PID_DATA0;
++ break;
++ case 2:
++ st->hctsiz_copy.b.pid = DWC_PID_DATA1;
++ break;
++ case 3:
++ st->hctsiz_copy.b.pid = DWC_PID_DATA2;
++ break;
++ }
+ }
++
++ fiq_print(FIQDBG_INT, hcd->fiq_state, "FSMQ %01d ", hc->hc_num);
++ fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcchar_copy.d32);
++ fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hctsiz_copy.d32);
++ fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcdma_copy.d32);
++ hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
++ local_fiq_disable();
++ DWC_WRITE_REG32(&hc_regs->hctsiz, st->hctsiz_copy.d32);
++ DWC_WRITE_REG32(&hc_regs->hcsplt, st->hcsplt_copy.d32);
++ DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32);
++ DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32);
++ DWC_WRITE_REG32(&hc_regs->hcintmsk, st->hcintmsk_copy.d32);
++ if (hfnum.b.frrem < PERIODIC_FRREM_BACKOFF) {
++ /* Prevent queueing near EOF1. Bad things happen if a periodic
++ * split transaction is queued very close to EOF.
++ */
++ st->fsm = FIQ_HS_ISOC_SLEEPING;
++ } else {
++ st->fsm = FIQ_HS_ISOC_TURBO;
++ st->hcchar_copy.b.chen = 1;
++ DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32);
++ }
++ mb();
++ st->hcchar_copy.b.chen = 0;
++ local_fiq_enable();
++ return 0;
+}
-+void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh)
++
++
++/**
++ * fiq_fsm_queue_split_transaction() - Set up a host channel and FIQ state
++ * @hcd: Pointer to the dwc_otg_hcd struct
++ * @qh: Pointer to the endpoint's queue head
++ *
++ * This overrides the dwc_otg driver's normal method of queueing a transaction.
++ * Called from dwc_otg_hcd_queue_transactions(), this performs specific setup
++ * for the nominated host channel.
++ *
++ * For periodic transfers, it also peeks at the FIQ state to see if an immediate
++ * start is possible. If not, then the FIQ is left to start the transfer.
++ */
++int fiq_fsm_queue_split_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh)
+{
-+ uint32_t hub_addr, port_addr;
++ int start_immediate = 1, i;
++ hfnum_data_t hfnum;
++ dwc_hc_t *hc = qh->channel;
++ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num];
++ /* Program HC registers, setup FIQ_state, examine FIQ if periodic, start transfer (not if uframe 5) */
++ int hub_addr, port_addr, frame, uframe;
++ struct fiq_channel_state *st = &hcd->fiq_state->channel[hc->hc_num];
+
-+ if(!fiq_split_enable)
-+ return;
++ if (st->fsm != FIQ_PASSTHROUGH)
++ return 0;
++ st->nr_errors = 0;
++
++ st->hcchar_copy.d32 = 0;
++ st->hcchar_copy.b.mps = hc->max_packet;
++ st->hcchar_copy.b.epdir = hc->ep_is_in;
++ st->hcchar_copy.b.devaddr = hc->dev_addr;
++ st->hcchar_copy.b.epnum = hc->ep_num;
++ st->hcchar_copy.b.eptype = hc->ep_type;
++ if (hc->ep_type & 0x1) {
++ if (hc->ep_is_in)
++ st->hcchar_copy.b.multicnt = 3;
++ else
++ /* Docs say set this to 1, but driver sets to 0! */
++ st->hcchar_copy.b.multicnt = 0;
++ } else {
++ st->hcchar_copy.b.multicnt = 1;
++ st->hcchar_copy.b.oddfrm = 0;
++ }
++ st->hcchar_copy.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW) ? 1 : 0;
++ /* Enable the channel later as a final register write. */
++
++ st->hcsplt_copy.d32 = 0;
++ if(qh->do_split) {
++ hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
++ st->hcsplt_copy.b.compsplt = 0;
++ st->hcsplt_copy.b.spltena = 1;
++ // XACTPOS is for isoc-out only but needs initialising anyway.
++ st->hcsplt_copy.b.xactpos = ISOC_XACTPOS_ALL;
++ if((qh->ep_type == DWC_OTG_EP_TYPE_ISOC) && (!qh->ep_is_in)) {
++ /* For packetsize 0 < L < 188, ISOC_XACTPOS_ALL.
++ * for longer than this, ISOC_XACTPOS_BEGIN and the FIQ
++ * will update as necessary.
++ */
++ if (hc->xfer_len > 188) {
++ st->hcsplt_copy.b.xactpos = ISOC_XACTPOS_BEGIN;
++ }
++ }
++ st->hcsplt_copy.b.hubaddr = (uint8_t) hub_addr;
++ st->hcsplt_copy.b.prtaddr = (uint8_t) port_addr;
++ st->hub_addr = hub_addr;
++ st->port_addr = port_addr;
++ }
+
-+ hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr);
++ st->hctsiz_copy.d32 = 0;
++ st->hctsiz_copy.b.dopng = 0;
++ st->hctsiz_copy.b.pid = hc->data_pid_start;
+
-+ hcd->hub_port[hub_addr] &= ~(1 << port_addr);
-+#ifdef FIQ_DEBUG
-+ hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1;
-+#endif
-+ fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num);
++ if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) {
++ hc->xfer_len = hc->max_packet;
++ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) {
++ hc->xfer_len = 188;
++ }
++ st->hctsiz_copy.b.xfersize = hc->xfer_len;
++
++ st->hctsiz_copy.b.pktcnt = 1;
++
++ if (hc->ep_type & 0x1) {
++ /*
++ * For potentially multi-packet transfers, must use the DMA bounce buffers. For IN transfers,
++ * the DMA address is the address of the first 188byte slot buffer in the bounce buffer array.
++ * For multi-packet OUT transfers, we need to copy the data into the bounce buffer array so the FIQ can punt
++ * the right address out as necessary. hc->xfer_buff and hc->xfer_len have already been set
++ * in assign_and_init_hc(), but this is for the eventual transaction completion only. The FIQ
++ * must not touch internal driver state.
++ */
++ if(!fiq_fsm_setup_periodic_dma(hcd, st, qh)) {
++ if (hc->align_buff) {
++ st->hcdma_copy.d32 = hc->align_buff;
++ } else {
++ st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF);
++ }
++ }
++ } else {
++ if (hc->align_buff) {
++ st->hcdma_copy.d32 = hc->align_buff;
++ } else {
++ st->hcdma_copy.d32 = ((unsigned long) hc->xfer_buff & 0xFFFFFFFF);
++ }
++ }
++ /* The FIQ depends upon no other interrupts being enabled except channel halt.
++ * Fixup channel interrupt mask. */
++ st->hcintmsk_copy.d32 = 0;
++ st->hcintmsk_copy.b.chhltd = 1;
++ st->hcintmsk_copy.b.ahberr = 1;
++
++ DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32);
++ DWC_WRITE_REG32(&hc_regs->hctsiz, st->hctsiz_copy.d32);
++ DWC_WRITE_REG32(&hc_regs->hcsplt, st->hcsplt_copy.d32);
++ DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32);
++ DWC_WRITE_REG32(&hc_regs->hcintmsk, st->hcintmsk_copy.d32);
++
++ local_fiq_disable();
++ mb();
+
++ if (hc->ep_type & 0x1) {
++ hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
++ frame = (hfnum.b.frnum & ~0x7) >> 3;
++ uframe = hfnum.b.frnum & 0x7;
++ if (hfnum.b.frrem < PERIODIC_FRREM_BACKOFF) {
++ /* Prevent queueing near EOF1. Bad things happen if a periodic
++ * split transaction is queued very close to EOF.
++ */
++ start_immediate = 0;
++ } else if (uframe == 5) {
++ start_immediate = 0;
++ } else if (hc->ep_type == UE_ISOCHRONOUS && !hc->ep_is_in) {
++ start_immediate = 0;
++ } else if (hc->ep_is_in && fiq_fsm_too_late(hcd->fiq_state, hc->hc_num)) {
++ start_immediate = 0;
++ } else {
++ /* Search through all host channels to determine if a transaction
++ * is currently in progress */
++ for (i = 0; i < hcd->core_if->core_params->host_channels; i++) {
++ if (i == hc->hc_num || hcd->fiq_state->channel[i].fsm == FIQ_PASSTHROUGH)
++ continue;
++ switch (hcd->fiq_state->channel[i].fsm) {
++ /* TT is reserved for channels that are in the middle of a periodic
++ * split transaction.
++ */
++ case FIQ_PER_SSPLIT_STARTED:
++ case FIQ_PER_CSPLIT_WAIT:
++ case FIQ_PER_CSPLIT_NYET1:
++ case FIQ_PER_CSPLIT_POLL:
++ case FIQ_PER_ISO_OUT_ACTIVE:
++ case FIQ_PER_ISO_OUT_LAST:
++ if (hcd->fiq_state->channel[i].hub_addr == hub_addr &&
++ hcd->fiq_state->channel[i].port_addr == port_addr) {
++ start_immediate = 0;
++ }
++ break;
++ default:
++ break;
++ }
++ if (!start_immediate)
++ break;
++ }
++ }
++ }
++ fiq_print(FIQDBG_INT, hcd->fiq_state, "FSMQ %01d %01d", hc->hc_num, start_immediate);
++ fiq_print(FIQDBG_INT, hcd->fiq_state, "%08d", hfnum.b.frrem);
++ //fiq_print(FIQDBG_INT, hcd->fiq_state, "H:%02dP:%02d", hub_addr, port_addr);
++ //fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hctsiz_copy.d32);
++ //fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcdma_copy.d32);
++ switch (hc->ep_type) {
++ case UE_CONTROL:
++ case UE_BULK:
++ st->fsm = FIQ_NP_SSPLIT_STARTED;
++ break;
++ case UE_ISOCHRONOUS:
++ if (hc->ep_is_in) {
++ if (start_immediate) {
++ st->fsm = FIQ_PER_SSPLIT_STARTED;
++ } else {
++ st->fsm = FIQ_PER_SSPLIT_QUEUED;
++ }
++ } else {
++ if (start_immediate) {
++ /* Single-isoc OUT packets don't require FIQ involvement */
++ if (st->nrpackets == 1) {
++ st->fsm = FIQ_PER_ISO_OUT_LAST;
++ } else {
++ st->fsm = FIQ_PER_ISO_OUT_ACTIVE;
++ }
++ } else {
++ st->fsm = FIQ_PER_ISO_OUT_PENDING;
++ }
++ }
++ break;
++ case UE_INTERRUPT:
++ if (start_immediate) {
++ st->fsm = FIQ_PER_SSPLIT_STARTED;
++ } else {
++ st->fsm = FIQ_PER_SSPLIT_QUEUED;
++ }
++ default:
++ break;
++ }
++ if (start_immediate) {
++ /* Set the oddfrm bit as close as possible to actual queueing */
++ frame = dwc_otg_hcd_get_frame_number(hcd);
++ st->expected_uframe = (frame + 1) & 0x3FFF;
++ st->hcchar_copy.b.oddfrm = (frame & 0x1) ? 0 : 1;
++ st->hcchar_copy.b.chen = 1;
++ DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32);
++ }
++ mb();
++ local_fiq_enable();
++ return 0;
+}
+
+
@@ -69926,16 +72908,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+{
+ dwc_list_link_t *qh_ptr;
+ dwc_otg_qh_t *qh;
-+ dwc_otg_qtd_t *qtd;
+ int num_channels;
+ dwc_irqflags_t flags;
+ dwc_spinlock_t *channel_lock = hcd->channel_lock;
+ dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE;
+
-+#ifdef DEBUG_SOF
-+ DWC_DEBUGPL(DBG_HCD, " Select Transactions\n");
-+#endif
-+
+#ifdef DEBUG_HOST_CHANNELS
+ last_sel_trans_num_per_scheduled = 0;
+ last_sel_trans_num_nonper_scheduled = 0;
@@ -69950,26 +72927,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+
+ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
+
-+ if(qh->do_split) {
-+ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
-+ if(!(qh->ep_type == UE_ISOCHRONOUS &&
-+ (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
-+ qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END))) {
-+ if(dwc_otg_hcd_allocate_port(hcd, qh))
-+ {
-+ qh_ptr = DWC_LIST_NEXT(qh_ptr);
-+ g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1);
-+ continue;
-+ }
-+ }
-+ }
-+
+ if (microframe_schedule) {
+ // Make sure we leave one channel for non periodic transactions.
+ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
+ if (hcd->available_host_channels <= 1) {
+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
-+ if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh);
+ break;
+ }
+ hcd->available_host_channels--;
@@ -70005,27 +72967,24 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {
+
+ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
-+
+ /*
+ * Check to see if this is a NAK'd retransmit, in which case ignore for retransmission
+ * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed
+ * cheeky devices that just hold off using NAKs
+ */
-+ if (nak_holdoff_enable && qh->do_split) {
-+ if (qh->nak_frame != 0xffff &&
-+ dwc_full_frame_num(qh->nak_frame) ==
-+ dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
-+ /*
-+ * Revisit: Need to avoid trampling on periodic scheduling.
-+ * Currently we are safe because g_np_count != g_np_sent whenever we hit this,
-+ * but if this behaviour is changed then periodic endpoints will get a slower
-+ * polling rate.
-+ */
-+ g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
-+ qh_ptr = DWC_LIST_NEXT(qh_ptr);
-+ continue;
-+ } else {
-+ qh->nak_frame = 0xffff;
++ if (nak_holdoff && qh->do_split) {
++ if (qh->nak_frame != 0xffff) {
++ uint16_t next_frame = dwc_frame_num_inc(qh->nak_frame, (qh->ep_type == UE_BULK) ? nak_holdoff : 8);
++ uint16_t frame = dwc_otg_hcd_get_frame_number(hcd);
++ if (dwc_frame_num_le(frame, next_frame)) {
++ if(dwc_frame_num_le(next_frame, hcd->fiq_state->next_sched_frame)) {
++ hcd->fiq_state->next_sched_frame = next_frame;
++ }
++ qh_ptr = DWC_LIST_NEXT(qh_ptr);
++ continue;
++ } else {
++ qh->nak_frame = 0xFFFF;
++ }
+ }
+ }
+
@@ -70054,12 +73013,29 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ &qh->qh_list_entry);
+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
+
-+ g_np_sent++;
+
+ if (!microframe_schedule)
+ hcd->non_periodic_channels++;
+ }
-+
++ /* we moved a non-periodic QH to the active schedule. If the inactive queue is empty,
++ * stop the FIQ from kicking us. We could potentially still have elements here if we
++ * ran out of host channels.
++ */
++ if (DWC_LIST_EMPTY(&hcd->non_periodic_sched_inactive)) {
++ hcd->fiq_state->kick_np_queues = 0;
++ } else {
++ /* For each entry remaining in the NP inactive queue,
++ * if this a NAK'd retransmit then don't set the kick flag.
++ */
++ if(nak_holdoff) {
++ DWC_LIST_FOREACH(qh_ptr, &hcd->non_periodic_sched_inactive) {
++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);
++ if (qh->nak_frame == 0xFFFF) {
++ hcd->fiq_state->kick_np_queues = 1;
++ }
++ }
++ }
++ }
+ if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned))
+ ret_val |= DWC_OTG_TRANSACTION_PERIODIC;
+
@@ -70104,6 +73080,12 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ hc->qh->ping_state = 0;
+ }
+ } else if (!hc->xfer_started) {
++ if (fiq_fsm_enable && hc->error_state) {
++ hcd->fiq_state->channel[hc->hc_num].nr_errors =
++ DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list)->error_count;
++ hcd->fiq_state->channel[hc->hc_num].fsm =
++ FIQ_PASSTHROUGH_ERRORSTATE;
++ }
+ dwc_otg_hc_start_transfer(hcd->core_if, hc);
+ hc->qh->ping_state = 0;
+ }
@@ -70156,7 +73138,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ hptxsts_data_t tx_status;
+ dwc_list_link_t *qh_ptr;
+ dwc_otg_qh_t *qh;
-+ int status;
++ int status = 0;
+ int no_queue_space = 0;
+ int no_fifo_space = 0;
+
@@ -70185,27 +73167,34 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+
+ // Do not send a split start transaction any later than frame .6
+ // Note, we have to schedule a periodic in .5 to make it go in .6
-+ if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
++ if(fiq_fsm_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
+ {
+ qh_ptr = qh_ptr->next;
-+ g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
++ hcd->fiq_state->next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
+ continue;
+ }
+
-+ /*
-+ * Set a flag if we're queuing high-bandwidth in slave mode.
-+ * The flag prevents any halts to get into the request queue in
-+ * the middle of multiple high-bandwidth packets getting queued.
-+ */
-+ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
-+ hcd->core_if->queuing_high_bandwidth = 1;
-+ }
-+ status =
-+ queue_transaction(hcd, qh->channel,
-+ tx_status.b.ptxfspcavail);
-+ if (status < 0) {
-+ no_fifo_space = 1;
-+ break;
++ if (fiq_fsm_enable && fiq_fsm_transaction_suitable(qh)) {
++ if (qh->do_split)
++ fiq_fsm_queue_split_transaction(hcd, qh);
++ else
++ fiq_fsm_queue_isoc_transaction(hcd, qh);
++ } else {
++
++ /*
++ * Set a flag if we're queueing high-bandwidth in slave mode.
++ * The flag prevents any halts to get into the request queue in
++ * the middle of multiple high-bandwidth packets getting queued.
++ */
++ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) {
++ hcd->core_if->queuing_high_bandwidth = 1;
++ }
++ status = queue_transaction(hcd, qh->channel,
++ tx_status.b.ptxfspcavail);
++ if (status < 0) {
++ no_fifo_space = 1;
++ break;
++ }
+ }
+
+ /*
@@ -70322,25 +73311,19 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+ qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t,
+ qh_list_entry);
+
-+ // Do not send a split start transaction any later than frame .5
-+ // non periodic transactions will start immediately in this uframe
-+ if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6)
-+ {
-+ g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7;
-+ break;
-+ }
-+
-+ status =
-+ queue_transaction(hcd, qh->channel,
-+ tx_status.b.nptxfspcavail);
++ if(fiq_fsm_enable && fiq_fsm_transaction_suitable(qh)) {
++ fiq_fsm_queue_split_transaction(hcd, qh);
++ } else {
++ status = queue_transaction(hcd, qh->channel,
++ tx_status.b.nptxfspcavail);
+
-+ if (status > 0) {
-+ more_to_do = 1;
-+ } else if (status < 0) {
-+ no_fifo_space = 1;
-+ break;
++ if (status > 0) {
++ more_to_do = 1;
++ } else if (status < 0) {
++ no_fifo_space = 1;
++ break;
++ }
+ }
-+
+ /* Advance to next QH, skipping start-of-list entry. */
+ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next;
+ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) {
@@ -72210,9 +75193,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-raspberry-p
+}
+
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 2014-04-24 16:04:39.819124254 +0200
@@ -0,0 +1,1132 @@
+/*==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $
@@ -73346,10 +76329,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-raspbe
+}
+
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,851 @@
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 2014-04-24 16:04:39.819124254 +0200
+@@ -0,0 +1,862 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $
+ * $Revision: #58 $
@@ -73392,6 +76375,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-p
+#include "dwc_otg_core_if.h"
+#include "dwc_list.h"
+#include "dwc_otg_cil.h"
++#include "dwc_otg_fiq_fsm.h"
++
+
+/**
+ * @file
@@ -73937,6 +76922,12 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-p
+ /** Frame List DMA address */
+ dma_addr_t frame_list_dma;
+
++ struct fiq_stack *fiq_stack;
++ struct fiq_state *fiq_state;
++
++ /** Virtual address for split transaction DMA bounce buffers */
++ struct fiq_dma_blob *fiq_dmab;
++
+#ifdef DEBUG
+ uint32_t frrem_samples;
+ uint64_t frrem_accum;
@@ -73967,6 +76958,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-p
+int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh);
+void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh);
+
++extern int fiq_fsm_queue_transaction(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh);
++extern int fiq_fsm_transaction_suitable(dwc_otg_qh_t *qh);
++extern void dwc_otg_cleanup_fiq_channel(dwc_otg_hcd_t *hcd, uint32_t num);
+
+/** @} */
+
@@ -74201,9 +77195,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-raspberry-p
+#endif
+#endif
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 2014-04-24 16:04:39.819124254 +0200
@@ -0,0 +1,417 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $
@@ -74622,10 +77616,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-raspberr
+
+#endif /* __DWC_HCD_IF_H__ */
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,2741 @@
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 2014-04-24 16:04:39.819124254 +0200
+@@ -0,0 +1,2681 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
+ * $Revision: #89 $
@@ -74662,7 +77656,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+
+#include "dwc_otg_hcd.h"
+#include "dwc_otg_regs.h"
-+#include "dwc_otg_mphi_fix.h"
+
+#include <linux/jiffies.h>
+#include <mach/hardware.h>
@@ -74675,33 +77668,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ * This file contains the implementation of the HCD Interrupt handlers.
+ */
+
-+/*
-+ * Some globals to communicate between the FIQ and INTERRUPT
-+ */
-+
-+void * dummy_send;
-+mphi_regs_t c_mphi_regs;
-+volatile void *dwc_regs_base;
+int fiq_done, int_done;
+
-+gintsts_data_t gintsts_saved = {.d32 = 0};
-+hcint_data_t hcint_saved[MAX_EPS_CHANNELS];
-+hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
-+int split_out_xfersize[MAX_EPS_CHANNELS];
-+haint_data_t haint_saved;
-+
-+int g_next_sched_frame, g_np_count, g_np_sent;
-+static int mphi_int_count = 0 ;
-+
-+hcchar_data_t nak_hcchar;
-+hctsiz_data_t nak_hctsiz;
-+hcsplt_data_t nak_hcsplt;
-+int nak_count;
-+
-+int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
-+int split_start_frame[MAX_EPS_CHANNELS];
-+int queued_port[MAX_EPS_CHANNELS];
-+
+#ifdef FIQ_DEBUG
+char buffer[1000*16];
+int wptr;
@@ -74711,12 +77679,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ va_list args;
+ char text[17];
+ hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) };
-+ unsigned long flags;
+
-+ local_irq_save(flags);
-+ local_fiq_disable();
+ if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR)
+ {
++ local_fiq_disable();
+ snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937);
+ va_start(args, fmt);
+ vsnprintf(text+8, 9, fmt, args);
@@ -74724,410 +77690,21 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+
+ memcpy(buffer + wptr, text, 16);
+ wptr = (wptr + 16) % sizeof(buffer);
++ local_fiq_enable();
+ }
-+ local_irq_restore(flags);
+}
+#endif
+
-+void notrace fiq_queue_request(int channel, int odd_frame)
-+{
-+ hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };
-+ hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };
-+ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10) };
-+
-+ if(hcsplt.b.spltena == 0)
-+ {
-+ fiq_print(FIQDBG_ERR, "SPLTENA ");
-+ BUG();
-+ }
-+
-+ if(hcchar.b.epdir == 1)
-+ {
-+ fiq_print(FIQDBG_SCHED, "IN Ch %d", channel);
-+ }
-+ else
-+ {
-+ hctsiz.b.xfersize = 0;
-+ fiq_print(FIQDBG_SCHED, "OUT Ch %d", channel);
-+ }
-+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x10), hctsiz.d32);
-+
-+ hcsplt.b.compsplt = 1;
-+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x4), hcsplt.d32);
-+
-+ // Send the Split complete
-+ hcchar.b.chen = 1;
-+ hcchar.b.oddfrm = odd_frame ? 1 : 0;
-+
-+ // Post this for transmit on the next frame for periodic or this frame for non-periodic
-+ fiq_print(FIQDBG_SCHED, "SND_%s", odd_frame ? "ODD " : "EVEN");
-+
-+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x0), hcchar.d32);
-+}
-+
-+static int last_sof = -1;
-+
-+/*
-+** Function to handle the start of frame interrupt, choose whether we need to do anything and
-+** therefore trigger the main interrupt
-+**
-+** returns int != 0 - interrupt has been handled
-+*/
-+int diff;
-+
-+int notrace fiq_sof_handle(hfnum_data_t hfnum)
-+{
-+ int handled = 0;
-+ int i;
-+
-+ // Just check that once we're running we don't miss a SOF
-+ /*if(last_sof != -1 && (hfnum.b.frnum != ((last_sof + 1) & 0x3fff)))
-+ {
-+ fiq_print(FIQDBG_ERR, "LASTSOF ");
-+ fiq_print(FIQDBG_ERR, "%4d%d ", last_sof / 8, last_sof & 7);
-+ fiq_print(FIQDBG_ERR, "%4d%d ", hfnum.b.frnum / 8, hfnum.b.frnum & 7);
-+ BUG();
-+ }*/
-+
-+ // Only start remembering the last sof when the interrupt has been
-+ // enabled (we don't check the mask to come in here...)
-+ if(last_sof != -1 || FIQ_READ(dwc_regs_base + 0x18) & (1<<3))
-+ last_sof = hfnum.b.frnum;
-+
-+ for(i = 0; i < MAX_EPS_CHANNELS; i++)
-+ {
-+ if(complete_sched[i] != -1)
-+ {
-+ if(complete_sched[i] <= hfnum.b.frnum || (complete_sched[i] > 0x3f00 && hfnum.b.frnum < 0xf0))
-+ {
-+ fiq_queue_request(i, hfnum.b.frnum & 1);
-+ complete_sched[i] = -1;
-+ }
-+ }
-+
-+ if(complete_sched[i] != -1)
-+ {
-+ // This is because we've seen a split complete occur with no start...
-+ // most likely because missed the complete 0x3fff frames ago!
-+
-+ diff = (hfnum.b.frnum + 0x3fff - complete_sched[i]) & 0x3fff ;
-+ if(diff > 32 && diff < 0x3f00)
-+ {
-+ fiq_print(FIQDBG_ERR, "SPLTMISS");
-+ BUG();
-+ }
-+ }
-+ }
-+
-+ if(g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
-+ {
-+ /*
-+ * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet
-+ * g_next_sched_frame is the next frame we have periodic packets for
-+ *
-+ * if neither of these are required for this frame then just clear the interrupt
-+ */
-+ handled = 1;
-+
-+ }
-+
-+ return handled;
-+}
-+
-+int notrace port_id(hcsplt_data_t hcsplt)
-+{
-+ return hcsplt.b.prtaddr + (hcsplt.b.hubaddr << 8);
-+}
-+
-+int notrace fiq_hcintr_handle(int channel, hfnum_data_t hfnum)
-+{
-+ hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) };
-+ hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) };
-+ hcint_data_t hcint = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x8) };
-+ hcintmsk_data_t hcintmsk = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0xc) };
-+ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10)};
-+
-+ hcint_saved[channel].d32 |= hcint.d32;
-+ hcintmsk_saved[channel].d32 = hcintmsk.d32;
-+
-+ if(hcsplt.b.spltena)
-+ {
-+ fiq_print(FIQDBG_PORTHUB, "ph: %4x", port_id(hcsplt));
-+ if(hcint.b.chhltd)
-+ {
-+ fiq_print(FIQDBG_SCHED, "CH HLT %d", channel);
-+ fiq_print(FIQDBG_SCHED, "%08x", hcint_saved[channel]);
-+ }
-+ if(hcint.b.stall || hcint.b.xacterr || hcint.b.bblerr || hcint.b.frmovrun || hcint.b.datatglerr)
-+ {
-+ queued_port[channel] = 0;
-+ fiq_print(FIQDBG_ERR, "CHAN ERR");
-+ }
-+ if(hcint.b.xfercomp)
-+ {
-+ // Clear the port allocation and transmit anything also on this port
-+ queued_port[channel] = 0;
-+ fiq_print(FIQDBG_SCHED, "XFERCOMP");
-+ }
-+ if(hcint.b.nak)
-+ {
-+ queued_port[channel] = 0;
-+ fiq_print(FIQDBG_SCHED, "NAK");
-+ }
-+ if(hcint.b.ack && !hcsplt.b.compsplt)
-+ {
-+ int i;
-+
-+ // Do not complete isochronous out transactions
-+ if(hcchar.b.eptype == 1 && hcchar.b.epdir == 0)
-+ {
-+ queued_port[channel] = 0;
-+ fiq_print(FIQDBG_SCHED, "ISOC_OUT");
-+ }
-+ else
-+ {
-+ // Make sure we check the port / hub combination that we sent this split on.
-+ // Do not queue a second request to the same port
-+ for(i = 0; i < MAX_EPS_CHANNELS; i++)
-+ {
-+ if(port_id(hcsplt) == queued_port[i])
-+ {
-+ fiq_print(FIQDBG_ERR, "PORTERR ");
-+ //BUG();
-+ }
-+ }
-+
-+ split_start_frame[channel] = (hfnum.b.frnum + 1) & ~7;
-+
-+ // Note, the size of an OUT is in the start split phase, not
-+ // the complete split
-+ split_out_xfersize[channel] = hctsiz.b.xfersize;
-+
-+ hcint_saved[channel].b.chhltd = 0;
-+ hcint_saved[channel].b.ack = 0;
-+
-+ queued_port[channel] = port_id(hcsplt);
-+
-+ if(hcchar.b.eptype & 1)
-+ {
-+ // Send the periodic complete in the same oddness frame as the ACK went...
-+ fiq_queue_request(channel, !(hfnum.b.frnum & 1));
-+ // complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
-+ }
-+ else
-+ {
-+ // Schedule the split complete to occur later
-+ complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 2);
-+ fiq_print(FIQDBG_SCHED, "ACK%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
-+ }
-+ }
-+ }
-+ if(hcint.b.nyet)
-+ {
-+ fiq_print(FIQDBG_ERR, "NYETERR1");
-+ //BUG();
-+ // Can transmit a split complete up to uframe .0 of the next frame
-+ if(hfnum.b.frnum <= dwc_frame_num_inc(split_start_frame[channel], 8))
-+ {
-+ // Send it next frame
-+ if(hcchar.b.eptype & 1) // type 1 & 3 are interrupt & isoc
-+ {
-+ fiq_print(FIQDBG_SCHED, "NYT:SEND");
-+ fiq_queue_request(channel, !(hfnum.b.frnum & 1));
-+ }
-+ else
-+ {
-+ // Schedule non-periodic access for next frame (the odd-even bit doesn't effect NP)
-+ complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1);
-+ fiq_print(FIQDBG_SCHED, "NYT%04d%d", complete_sched[channel]/8, complete_sched[channel]%8);
-+ }
-+ hcint_saved[channel].b.chhltd = 0;
-+ hcint_saved[channel].b.nyet = 0;
-+ }
-+ else
-+ {
-+ queued_port[channel] = 0;
-+ fiq_print(FIQDBG_ERR, "NYETERR2");
-+ //BUG();
-+ }
-+ }
-+ }
-+ else
-+ {
-+ /*
-+ * If we have any of NAK, ACK, Datatlgerr active on a
-+ * non-split channel, the sole reason is to reset error
-+ * counts for a previously broken transaction. The FIQ
-+ * will thrash on NAK IN and ACK OUT in particular so
-+ * handle it "once" and allow the IRQ to do the rest.
-+ */
-+ hcint.d32 &= hcintmsk.d32;
-+ if(hcint.b.nak)
-+ {
-+ hcintmsk.b.nak = 0;
-+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);
-+ }
-+ if (hcint.b.ack)
-+ {
-+ hcintmsk.b.ack = 0;
-+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0xc), hcintmsk.d32);
-+ }
-+ }
-+
-+ // Clear the interrupt, this will also clear the HAINT bit
-+ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32);
-+ return hcint_saved[channel].d32 == 0;
-+}
-+
-+gintsts_data_t gintsts;
-+gintmsk_data_t gintmsk;
-+// triggered: The set of interrupts that were triggered
-+// handled: The set of interrupts that have been handled (no IRQ is
-+// required)
-+// keep: The set of interrupts we want to keep unmasked even though we
-+// want to trigger an IRQ to handle it (SOF and HCINTR)
-+gintsts_data_t triggered, handled, keep;
-+hfnum_data_t hfnum;
-+
-+void __attribute__ ((naked)) notrace dwc_otg_hcd_handle_fiq(void)
-+{
-+
-+ /* entry takes care to store registers we will be treading on here */
-+ asm __volatile__ (
-+ "mov ip, sp ;"
-+ /* stash FIQ and normal regs */
-+ "stmdb sp!, {r0-r12, lr};"
-+ /* !! THIS SETS THE FRAME, adjust to > sizeof locals */
-+ "sub fp, ip, #512 ;"
-+ );
-+
-+ // Cannot put local variables at the beginning of the function
-+ // because otherwise 'C' will play with the stack pointer. any locals
-+ // need to be inside the following block
-+ do
-+ {
-+ fiq_done++;
-+ gintsts.d32 = FIQ_READ(dwc_regs_base + 0x14);
-+ gintmsk.d32 = FIQ_READ(dwc_regs_base + 0x18);
-+ hfnum.d32 = FIQ_READ(dwc_regs_base + 0x408);
-+ triggered.d32 = gintsts.d32 & gintmsk.d32;
-+ handled.d32 = 0;
-+ keep.d32 = 0;
-+ fiq_print(FIQDBG_INT, "FIQ ");
-+ fiq_print(FIQDBG_INT, "%08x", gintsts.d32);
-+ fiq_print(FIQDBG_INT, "%08x", gintmsk.d32);
-+ if(gintsts.d32)
-+ {
-+ // If port enabled
-+ if((FIQ_READ(dwc_regs_base + 0x440) & 0xf) == 0x5)
-+ {
-+ if(gintsts.b.sofintr)
-+ {
-+ if(fiq_sof_handle(hfnum))
-+ {
-+ handled.b.sofintr = 1; /* Handled in FIQ */
-+ }
-+ else
-+ {
-+ /* Keer interrupt unmasked */
-+ keep.b.sofintr = 1;
-+ }
-+ {
-+ // Need to make sure the read and clearing of the SOF interrupt is as close as possible to avoid the possibility of missing
-+ // a start of frame interrupt
-+ gintsts_data_t gintsts = { .b.sofintr = 1 };
-+ FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
-+ }
-+ }
-+
-+ if(fiq_split_enable && gintsts.b.hcintr)
-+ {
-+ int i;
-+ haint_data_t haint;
-+ haintmsk_data_t haintmsk;
-+
-+ haint.d32 = FIQ_READ(dwc_regs_base + 0x414);
-+ haintmsk.d32 = FIQ_READ(dwc_regs_base + 0x418);
-+ haint.d32 &= haintmsk.d32;
-+ haint_saved.d32 |= haint.d32;
-+
-+ fiq_print(FIQDBG_INT, "hcintr");
-+ fiq_print(FIQDBG_INT, "%08x", FIQ_READ(dwc_regs_base + 0x414));
-+
-+ // Go through each channel that has an enabled interrupt
-+ for(i = 0; i < 16; i++)
-+ if((haint.d32 >> i) & 1)
-+ if(fiq_hcintr_handle(i, hfnum))
-+ haint_saved.d32 &= ~(1 << i); /* this was handled */
-+
-+ /* If we've handled all host channel interrupts then don't trigger the interrupt */
-+ if(haint_saved.d32 == 0)
-+ {
-+ handled.b.hcintr = 1;
-+ }
-+ else
-+ {
-+ /* Make sure we keep the channel interrupt unmasked when triggering the IRQ */
-+ keep.b.hcintr = 1;
-+ }
-+
-+ {
-+ gintsts_data_t gintsts = { .b.hcintr = 1 };
-+
-+ // Always clear the channel interrupt
-+ FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32);
-+ }
-+ }
-+ }
-+ else
-+ {
-+ last_sof = -1;
-+ }
-+ }
-+
-+ // Mask out the interrupts triggered - those handled - don't mask out the ones we want to keep
-+ gintmsk.d32 = keep.d32 | (gintmsk.d32 & ~(triggered.d32 & ~handled.d32));
-+ // Save those that were triggered but not handled
-+ gintsts_saved.d32 |= triggered.d32 & ~handled.d32;
-+ FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
-+
-+ // Clear and save any unhandled interrupts and trigger the interrupt
-+ if(gintsts_saved.d32)
-+ {
-+ /* To enable the MPHI interrupt (INT 32)
-+ */
-+ FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send);
-+ FIQ_WRITE( c_mphi_regs.outddb, (1 << 29));
-+
-+ mphi_int_count++;
-+ }
-+ }
-+ while(0);
-+
-+ mb();
-+
-+ /* exit back to normal mode restoring everything */
-+ asm __volatile__ (
-+ /* return FIQ regs back to pristine state
-+ * and get normal regs back
-+ */
-+ "ldmia sp!, {r0-r12, lr};"
-+
-+ /* return */
-+ "subs pc, lr, #4;"
-+ );
-+}
-+
+/** This function handles interrupts for the HCD. */
+int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
+{
+ int retval = 0;
+ static int last_time;
-+
+ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
+ gintsts_data_t gintsts;
+ gintmsk_data_t gintmsk;
+ hfnum_data_t hfnum;
++ haintmsk_data_t haintmsk;
+
+#ifdef DEBUG
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
@@ -75145,14 +77722,25 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ /* Check if HOST Mode */
+ if (dwc_otg_is_host_mode(core_if)) {
+ local_fiq_disable();
-+ gintmsk.d32 |= gintsts_saved.d32;
-+ gintsts.d32 |= gintsts_saved.d32;
-+ gintsts_saved.d32 = 0;
++ /* Pull in from the FIQ's disabled mask */
++ gintmsk.d32 = gintmsk.d32 | ~(dwc_otg_hcd->fiq_state->gintmsk_saved.d32);
++ dwc_otg_hcd->fiq_state->gintmsk_saved.d32 = ~0;
++
++
++ if (fiq_fsm_enable && ( 0x0000FFFF & ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint))) {
++ gintsts.b.hcintr = 1;
++ }
++
++ /* Danger will robinson: fake a SOF if necessary */
++ if (fiq_fsm_enable && (dwc_otg_hcd->fiq_state->gintmsk_saved.b.sofintr == 1)) {
++ gintsts.b.sofintr = 1;
++ }
++ gintsts.d32 &= gintmsk.d32;
++
+ local_fiq_enable();
+ if (!gintsts.d32) {
+ goto exit_handler_routine;
+ }
-+ gintsts.d32 &= gintmsk.d32;
+
+#ifdef DEBUG
+ // We should be OK doing this because the common interrupts should already have been serviced
@@ -75172,12 +77760,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ gintsts.d32, core_if);
+#endif
+ hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum);
-+ if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum))
-+ {
-+ /* Note, we should never get here if the FIQ is doing it's job properly*/
-+ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
-+ }
-+ else if (gintsts.b.sofintr) {
++ if (gintsts.b.sofintr) {
+ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
+ }
+
@@ -75232,37 +77815,43 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ }
+
+exit_handler_routine:
-+
-+ if (fiq_fix_enable)
-+ {
++ if (fiq_enable) {
++ gintmsk_data_t gintmsk_new;
++ haintmsk_data_t haintmsk_new;
+ local_fiq_disable();
-+ // Make sure that we don't clear the interrupt if we've still got pending work to do
-+ if(gintsts_saved.d32 == 0)
-+ {
-+ /* Clear the MPHI interrupt */
-+ DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16));
-+ if (mphi_int_count >= 60)
-+ {
-+ DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16)));
-+ while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17)))
-+ ;
-+ DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
-+ mphi_int_count = 0;
-+ }
-+ int_done++;
++ gintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->gintmsk_saved.d32;
++ if(fiq_fsm_enable)
++ haintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->haintmsk_saved.d32;
++ else
++ haintmsk_new.d32 = 0x0000FFFF;
++
++ /* The FIQ could have sneaked another interrupt in. If so, don't clear MPHI */
++ if ((gintmsk_new.d32 == ~0) && (haintmsk_new.d32 == 0x0000FFFF)) {
++ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.intstat, (1<<16));
++ if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
++ fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
++ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, ((1<<31) + (1<<16)));
++ while (!(DWC_READ_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & (1 << 17)))
++ ;
++ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, (1<<31));
++ dwc_otg_hcd->fiq_state->mphi_int_count = 0;
++ }
++ int_done++;
+ }
-+
-+ // Unmask handled interrupts
-+ FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32);
-+ //DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1);
-+
++ haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
++ /* Re-enable interrupts that the FIQ masked (first time round) */
++ FIQ_WRITE(dwc_otg_hcd->fiq_state->dwc_regs_base + GINTMSK, gintmsk.d32);
+ local_fiq_enable();
+
-+ if((jiffies / HZ) > last_time)
-+ {
++ if ((jiffies / HZ) > last_time) {
++ //dwc_otg_qh_t *qh;
++ //dwc_list_link_t *cur;
+ /* Once a second output the fiq and irq numbers, useful for debug */
+ last_time = jiffies / HZ;
-+ DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done);
++ // DWC_WARN("np_kick=%d AHC=%d sched_frame=%d cur_frame=%d int_done=%d fiq_done=%d",
++ // dwc_otg_hcd->fiq_state->kick_np_queues, dwc_otg_hcd->available_host_channels,
++ // dwc_otg_hcd->fiq_state->next_sched_frame, hfnum.b.frnum, int_done, dwc_otg_hcd->fiq_state->fiq_done);
++ //printk(KERN_WARNING "Periodic queues:\n");
+ }
+ }
+
@@ -75314,6 +77903,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
+{
+ hfnum_data_t hfnum;
++ gintsts_data_t gintsts = { .d32 = 0 };
+ dwc_list_link_t *qh_entry;
+ dwc_otg_qh_t *qh;
+ dwc_otg_transaction_type_e tr_type;
@@ -75361,7 +77951,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ }
+ }
+
-+ g_next_sched_frame = next_sched_frame;
++ hcd->fiq_state->next_sched_frame = next_sched_frame;
+
+ tr_type = dwc_otg_hcd_select_transactions(hcd);
+ if (tr_type != DWC_OTG_TRANSACTION_NONE) {
@@ -75369,10 +77959,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ did_something = 1;
+ }
+
-+ /* Clear interrupt */
-+ gintsts.b.sofintr = 1;
-+ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
-+
++ /* Clear interrupt - but do not trample on the FIQ sof */
++ if (!fiq_fsm_enable) {
++ gintsts.b.sofintr = 1;
++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
++ }
+ return 1;
+}
+
@@ -75648,19 +78239,21 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+{
+ int i;
+ int retval = 0;
-+ haint_data_t haint;
++ haint_data_t haint = { .d32 = 0 } ;
+
+ /* Clear appropriate bits in HCINTn to clear the interrupt bit in
+ * GINTSTS */
+
-+ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
++ if (!fiq_fsm_enable)
++ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
+
+ // Overwrite with saved interrupts from fiq handler
-+ if(fiq_split_enable)
++ if(fiq_fsm_enable)
+ {
++ /* check the mask? */
+ local_fiq_disable();
-+ haint.d32 = haint_saved.d32;
-+ haint_saved.d32 = 0;
++ haint.b2.chint |= ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint);
++ dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint = ~0;
+ local_fiq_enable();
+ }
+
@@ -75704,9 +78297,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ *short_read = (hctsiz.b.xfersize != 0);
+ }
+ } else if (hc->qh->do_split) {
-+ if(fiq_split_enable)
-+ length = split_out_xfersize[hc->hc_num];
-+ else
++ //length = split_out_xfersize[hc->hc_num];
+ length = qtd->ssplit_out_xfer_count;
+ } else {
+ length = hc->xfer_len;
@@ -75953,19 +78544,17 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ int free_qtd;
+ dwc_irqflags_t flags;
+ dwc_spinlock_t *channel_lock = hcd->channel_lock;
-+#ifdef FIQ_DEBUG
-+ int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0;
-+#endif
++
+ int hog_port = 0;
+
+ DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n",
+ __func__, hc->hc_num, halt_status, hc->xfer_len);
+
-+ if(fiq_split_enable && hc->do_split) {
++ if(fiq_fsm_enable && hc->do_split) {
+ if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) {
+ if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID ||
+ hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) {
-+ hog_port = 1;
++ hog_port = 0;
+ }
+ }
+ }
@@ -76022,6 +78611,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ * function clears the channel interrupt enables and conditions, so
+ * there's no need to clear the Channel Halted interrupt separately.
+ */
++ if (fiq_fsm_enable && hcd->fiq_state->channel[hc->hc_num].fsm != FIQ_PASSTHROUGH)
++ dwc_otg_cleanup_fiq_channel(hcd, hc->hc_num);
+ dwc_otg_hc_cleanup(hcd->core_if, hc);
+ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
+
@@ -76044,27 +78635,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+
+ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
+ hcd->available_host_channels++;
-+ fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels);
++ fiq_print(FIQDBG_INT, hcd->fiq_state, "AHC = %d ", hcd->available_host_channels);
+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags);
+ }
+
-+ if(fiq_split_enable && hc->do_split)
-+ {
-+ if(!(hcd->hub_port[hc->hub_addr] & (1 << hc->port_addr)))
-+ {
-+ fiq_print(FIQDBG_ERR, "PRTNOTAL");
-+ //BUG();
-+ }
-+ if(!hog_port && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC ||
-+ hc->ep_type == DWC_OTG_EP_TYPE_INTR)) {
-+ hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr);
-+#ifdef FIQ_DEBUG
-+ hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1;
-+#endif
-+ fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp);
-+ }
-+ }
-+
+ /* Try to queue more transfers now that there's a free channel. */
+ tr_type = dwc_otg_hcd_select_transactions(hcd);
+ if (tr_type != DWC_OTG_TRANSACTION_NONE) {
@@ -76486,7 +79060,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
+ case UE_BULK:
+ case UE_CONTROL:
-+ if (nak_holdoff_enable)
++ if (nak_holdoff && qtd->qh->do_split)
+ hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd);
+ }
+
@@ -76702,7 +79276,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ // With the FIQ running we only ever see the failed NYET
+ if (dwc_full_frame_num(frnum) !=
+ dwc_full_frame_num(hc->qh->sched_frame) ||
-+ fiq_split_enable) {
++ fiq_fsm_enable) {
+ /*
+ * No longer in the same full speed frame.
+ * Treat this as a transaction error.
@@ -77088,12 +79662,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
+ dwc_hc_t * hc,
+ dwc_otg_hc_regs_t * hc_regs,
-+ dwc_otg_qtd_t * qtd,
-+ hcint_data_t hcint,
-+ hcintmsk_data_t hcintmsk)
++ dwc_otg_qtd_t * qtd)
+{
+ int out_nak_enh = 0;
-+
++ hcint_data_t hcint;
++ hcintmsk_data_t hcintmsk;
+ /* For core with OUT NAK enhancement, the flow for high-
+ * speed CONTROL/BULK OUT is handled a little differently.
+ */
@@ -77123,11 +79696,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ }
+
+ /* Read the HCINTn register to determine the cause for the halt. */
-+ if(!fiq_split_enable)
-+ {
-+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
-+ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
-+ }
++
++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
+
+ if (hcint.b.xfercomp) {
+ /** @todo This is here because of a possible hardware bug. Spec
@@ -77252,15 +79823,13 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
+ dwc_hc_t * hc,
+ dwc_otg_hc_regs_t * hc_regs,
-+ dwc_otg_qtd_t * qtd,
-+ hcint_data_t hcint,
-+ hcintmsk_data_t hcintmsk)
++ dwc_otg_qtd_t * qtd)
+{
+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
+ "Channel Halted--\n", hc->hc_num);
+
+ if (hcd->core_if->dma_enable) {
-+ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd, hcint, hcintmsk);
++ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
+ } else {
+#ifdef DEBUG
+ if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
@@ -77273,11 +79842,368 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ return 1;
+}
+
++
++/**
++ * dwc_otg_fiq_unmangle_isoc() - Update the iso_frame_desc structure on
++ * FIQ transfer completion
++ * @hcd: Pointer to dwc_otg_hcd struct
++ * @num: Host channel number
++ *
++ * 1. Un-mangle the status as recorded in each iso_frame_desc status
++ * 2. Copy it from the dwc_otg_urb into the real URB
++ */
++void dwc_otg_fiq_unmangle_isoc(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, dwc_otg_qtd_t *qtd, uint32_t num)
++{
++ struct dwc_otg_hcd_urb *dwc_urb = qtd->urb;
++ int nr_frames = dwc_urb->packet_count;
++ int i;
++ hcint_data_t frame_hcint;
++
++ for (i = 0; i < nr_frames; i++) {
++ frame_hcint.d32 = dwc_urb->iso_descs[i].status;
++ if (frame_hcint.b.xfercomp) {
++ dwc_urb->iso_descs[i].status = 0;
++ dwc_urb->actual_length += dwc_urb->iso_descs[i].actual_length;
++ } else if (frame_hcint.b.frmovrun) {
++ if (qh->ep_is_in)
++ dwc_urb->iso_descs[i].status = -DWC_E_NO_STREAM_RES;
++ else
++ dwc_urb->iso_descs[i].status = -DWC_E_COMMUNICATION;
++ dwc_urb->error_count++;
++ dwc_urb->iso_descs[i].actual_length = 0;
++ } else if (frame_hcint.b.xacterr) {
++ dwc_urb->iso_descs[i].status = -DWC_E_PROTOCOL;
++ dwc_urb->error_count++;
++ dwc_urb->iso_descs[i].actual_length = 0;
++ } else if (frame_hcint.b.bblerr) {
++ dwc_urb->iso_descs[i].status = -DWC_E_OVERFLOW;
++ dwc_urb->error_count++;
++ dwc_urb->iso_descs[i].actual_length = 0;
++ } else {
++ /* Something went wrong */
++ dwc_urb->iso_descs[i].status = -1;
++ dwc_urb->iso_descs[i].actual_length = 0;
++ dwc_urb->error_count++;
++ }
++ }
++ //printk_ratelimited(KERN_INFO "%s: HS isochronous of %d/%d frames with %d errors complete\n",
++ // __FUNCTION__, i, dwc_urb->packet_count, dwc_urb->error_count);
++ hcd->fops->complete(hcd, dwc_urb->priv, dwc_urb, 0);
++ release_channel(hcd, qh->channel, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
++}
++
++/**
++ * dwc_otg_fiq_unsetup_per_dma() - Remove data from bounce buffers for split transactions
++ * @hcd: Pointer to dwc_otg_hcd struct
++ * @num: Host channel number
++ *
++ * Copies data from the FIQ bounce buffers into the URB's transfer buffer. Does not modify URB state.
++ * Returns total length of data or -1 if the buffers were not used.
++ *
++ */
++int dwc_otg_fiq_unsetup_per_dma(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, dwc_otg_qtd_t *qtd, uint32_t num)
++{
++ dwc_hc_t *hc = qh->channel;
++ struct fiq_dma_blob *blob = hcd->fiq_dmab;
++ struct fiq_channel_state *st = &hcd->fiq_state->channel[num];
++ uint8_t *ptr = NULL;
++ int index = 0, len = 0;
++ int i = 0;
++ if (hc->ep_is_in) {
++ /* Copy data out of the DMA bounce buffers to the URB's buffer.
++ * The align_buf is ignored as this is ignored on FSM enqueue. */
++ ptr = qtd->urb->buf;
++ if (qh->ep_type == UE_ISOCHRONOUS) {
++ /* Isoc IN transactions - grab the offset of the iso_frame_desc into the URB transfer buffer */
++ index = qtd->isoc_frame_index;
++ ptr += qtd->urb->iso_descs[index].offset;
++ } else {
++ /* Need to increment by actual_length for interrupt IN */
++ ptr += qtd->urb->actual_length;
++ }
++
++ for (i = 0; i < st->dma_info.index; i++) {
++ len += st->dma_info.slot_len[i];
++ dwc_memcpy(ptr, &blob->channel[num].index[i].buf[0], st->dma_info.slot_len[i]);
++ ptr += st->dma_info.slot_len[i];
++ }
++ return len;
++ } else {
++ /* OUT endpoints - nothing to do. */
++ return -1;
++ }
++
++}
++/**
++ * dwc_otg_hcd_handle_hc_fsm() - handle an unmasked channel interrupt
++ * from a channel handled in the FIQ
++ * @hcd: Pointer to dwc_otg_hcd struct
++ * @num: Host channel number
++ *
++ * If a host channel interrupt was received by the IRQ and this was a channel
++ * used by the FIQ, the execution flow for transfer completion is substantially
++ * different from the normal (messy) path. This function and its friends handles
++ * channel cleanup and transaction completion from a FIQ transaction.
++ */
++int32_t dwc_otg_hcd_handle_hc_fsm(dwc_otg_hcd_t *hcd, uint32_t num)
++{
++ struct fiq_channel_state *st = &hcd->fiq_state->channel[num];
++ dwc_hc_t *hc = hcd->hc_ptr_array[num];
++ dwc_otg_qtd_t *qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
++ dwc_otg_qh_t *qh = hc->qh;
++ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[num];
++ hcint_data_t hcint = hcd->fiq_state->channel[num].hcint_copy;
++ int hostchannels = 0;
++ int ret = 0;
++ fiq_print(FIQDBG_INT, hcd->fiq_state, "OUT %01d %01d ", num , st->fsm);
++
++ hostchannels = hcd->available_host_channels;
++ switch (st->fsm) {
++ case FIQ_TEST:
++ break;
++
++ case FIQ_DEQUEUE_ISSUED:
++ /* hc_halt was called. QTD no longer exists. */
++ /* TODO: for a nonperiodic split transaction, need to issue a
++ * CLEAR_TT_BUFFER hub command if we were in the start-split phase.
++ */
++ release_channel(hcd, hc, NULL, hc->halt_status);
++ ret = 1;
++ break;
++
++ case FIQ_NP_SPLIT_DONE:
++ /* Nonperiodic transaction complete. */
++ if (!hc->ep_is_in) {
++ qtd->ssplit_out_xfer_count = hc->xfer_len;
++ }
++ if (hcint.b.xfercomp) {
++ handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
++ } else if (hcint.b.nak) {
++ handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
++ }
++ ret = 1;
++ break;
++
++ case FIQ_NP_SPLIT_HS_ABORTED:
++ /* A HS abort is a 3-strikes on the HS bus at any point in the transaction.
++ * Normally a CLEAR_TT_BUFFER hub command would be required: we can't do that
++ * because there's no guarantee which order a non-periodic split happened in.
++ * We could end up clearing a perfectly good transaction out of the buffer.
++ */
++ if (hcint.b.xacterr) {
++ qtd->error_count += st->nr_errors;
++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
++ } else if (hcint.b.ahberr) {
++ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
++ } else {
++ local_fiq_disable();
++ BUG();
++ }
++ break;
++
++ case FIQ_NP_SPLIT_LS_ABORTED:
++ /* A few cases can cause this - either an unknown state on a SSPLIT or
++ * STALL/data toggle error response on a CSPLIT */
++ if (hcint.b.stall) {
++ handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
++ } else if (hcint.b.datatglerr) {
++ handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd);
++ } else if (hcint.b.ahberr) {
++ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
++ } else {
++ local_fiq_disable();
++ BUG();
++ }
++ break;
++
++ case FIQ_PER_SPLIT_DONE:
++ /* Isoc IN or Interrupt IN/OUT */
++
++ /* Flow control here is different from the normal execution by the driver.
++ * We need to completely ignore most of the driver's method of handling
++ * split transactions and do it ourselves.
++ */
++ if (hc->ep_type == UE_INTERRUPT) {
++ if (hcint.b.nak) {
++ handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
++ } else if (hc->ep_is_in) {
++ int len;
++ len = dwc_otg_fiq_unsetup_per_dma(hcd, hc->qh, qtd, num);
++ //printk(KERN_NOTICE "FIQ Transaction: hc=%d len=%d urb_len = %d\n", num, len, qtd->urb->length);
++ qtd->urb->actual_length += len;
++ if (qtd->urb->actual_length >= qtd->urb->length) {
++ qtd->urb->status = 0;
++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, qtd->urb->status);
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
++ } else {
++ /* Interrupt transfer not complete yet - is it a short read? */
++ if (len < hc->max_packet) {
++ /* Interrupt transaction complete */
++ qtd->urb->status = 0;
++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, qtd->urb->status);
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
++ } else {
++ /* Further transactions required */
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
++ }
++ }
++ } else {
++ /* Interrupt OUT complete. */
++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
++ qtd->urb->actual_length += hc->xfer_len;
++ if (qtd->urb->actual_length >= qtd->urb->length) {
++ qtd->urb->status = 0;
++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, qtd->urb->status);
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
++ } else {
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
++ }
++ }
++ } else {
++ /* ISOC IN complete. */
++ struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
++ int len = 0;
++ /* Record errors, update qtd. */
++ if (st->nr_errors) {
++ frame_desc->actual_length = 0;
++ frame_desc->status = -DWC_E_PROTOCOL;
++ } else {
++ frame_desc->status = 0;
++ /* Unswizzle dma */
++ len = dwc_otg_fiq_unsetup_per_dma(hcd, qh, qtd, num);
++ frame_desc->actual_length = len;
++ }
++ qtd->isoc_frame_index++;
++ if (qtd->isoc_frame_index == qtd->urb->packet_count) {
++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
++ } else {
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
++ }
++ }
++ break;
++
++ case FIQ_PER_ISO_OUT_DONE: {
++ struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
++ /* Record errors, update qtd. */
++ if (st->nr_errors) {
++ frame_desc->actual_length = 0;
++ frame_desc->status = -DWC_E_PROTOCOL;
++ } else {
++ frame_desc->status = 0;
++ frame_desc->actual_length = frame_desc->length;
++ }
++ qtd->isoc_frame_index++;
++ qtd->isoc_split_offset = 0;
++ if (qtd->isoc_frame_index == qtd->urb->packet_count) {
++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
++ } else {
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
++ }
++ }
++ break;
++
++ case FIQ_PER_SPLIT_NYET_ABORTED:
++ /* Doh. lost the data. */
++ printk_ratelimited(KERN_INFO "Transfer to device %d endpoint 0x%x frame %d failed "
++ "- FIQ reported NYET. Data may have been lost.\n",
++ hc->dev_addr, hc->ep_num, dwc_otg_hcd_get_frame_number(hcd) >> 3);
++ if (hc->ep_type == UE_ISOCHRONOUS) {
++ struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
++ /* Record errors, update qtd. */
++ frame_desc->actual_length = 0;
++ frame_desc->status = -DWC_E_PROTOCOL;
++ qtd->isoc_frame_index++;
++ qtd->isoc_split_offset = 0;
++ if (qtd->isoc_frame_index == qtd->urb->packet_count) {
++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
++ } else {
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
++ }
++ } else {
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
++ }
++ break;
++
++ case FIQ_HS_ISOC_DONE:
++ /* The FIQ has performed a whole pile of isochronous transactions.
++ * The status is recorded as the interrupt state should the transaction
++ * fail.
++ */
++ dwc_otg_fiq_unmangle_isoc(hcd, qh, qtd, num);
++ break;
++
++ case FIQ_PER_SPLIT_LS_ABORTED:
++ if (hcint.b.xacterr) {
++ /* Hub has responded with an ERR packet. Device
++ * has been unplugged or the port has been disabled.
++ * TODO: need to issue a reset to the hub port. */
++ qtd->error_count += 3;
++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
++ } else if (hcint.b.stall) {
++ handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
++ } else {
++ printk_ratelimited(KERN_INFO "Transfer to device %d endpoint 0x%x failed "
++ "- FIQ reported FSM=%d. Data may have been lost.\n",
++ st->fsm, hc->dev_addr, hc->ep_num);
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
++ }
++ break;
++
++ case FIQ_PER_SPLIT_HS_ABORTED:
++ /* Either the SSPLIT phase suffered transaction errors or something
++ * unexpected happened.
++ */
++ qtd->error_count += 3;
++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
++ break;
++
++ case FIQ_PER_SPLIT_TIMEOUT:
++ /* Couldn't complete in the nominated frame */
++ printk(KERN_INFO "Transfer to device %d endpoint 0x%x frame %d failed "
++ "- FIQ timed out. Data may have been lost.\n",
++ hc->dev_addr, hc->ep_num, dwc_otg_hcd_get_frame_number(hcd) >> 3);
++ if (hc->ep_type == UE_ISOCHRONOUS) {
++ struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
++ /* Record errors, update qtd. */
++ frame_desc->actual_length = 0;
++ if (hc->ep_is_in) {
++ frame_desc->status = -DWC_E_NO_STREAM_RES;
++ } else {
++ frame_desc->status = -DWC_E_COMMUNICATION;
++ }
++ qtd->isoc_frame_index++;
++ if (qtd->isoc_frame_index == qtd->urb->packet_count) {
++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
++ } else {
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
++ }
++ } else {
++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
++ }
++ break;
++
++ default:
++ local_fiq_disable();
++ DWC_WARN("unexpected state received on hc=%d fsm=%d", hc->hc_num, st->fsm);
++ BUG();
++ }
++ //if (hostchannels != hcd->available_host_channels) {
++ /* should have incremented by now! */
++ // BUG();
++// }
++ return ret;
++}
++
+/** Handles interrupt for a specific Host Channel */
+int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
+{
+ int retval = 0;
-+ hcint_data_t hcint, hcint_orig;
++ hcint_data_t hcint;
+ hcintmsk_data_t hcintmsk;
+ dwc_hc_t *hc;
+ dwc_otg_hc_regs_t *hc_regs;
@@ -77296,24 +80222,32 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ }
+ qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
+
++ /*
++ * FSM mode: Check to see if this is a HC interrupt from a channel handled by the FIQ.
++ * Execution path is fundamentally different for the channels after a FIQ has completed
++ * a split transaction.
++ */
++ if (fiq_fsm_enable) {
++ switch (dwc_otg_hcd->fiq_state->channel[num].fsm) {
++ case FIQ_PASSTHROUGH:
++ break;
++ case FIQ_PASSTHROUGH_ERRORSTATE:
++ /* Hook into the error count */
++ fiq_print(FIQDBG_ERR, dwc_otg_hcd->fiq_state, "HCDERR%02d", num);
++ if (dwc_otg_hcd->fiq_state->channel[num].nr_errors) {
++ qtd->error_count = 0;
++ fiq_print(FIQDBG_ERR, dwc_otg_hcd->fiq_state, "RESET ");
++ }
++ break;
++ default:
++ dwc_otg_hcd_handle_hc_fsm(dwc_otg_hcd, num);
++ return 1;
++ }
++ }
++
+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
-+ hcint_orig = hcint;
+ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
-+ DWC_DEBUGPL(DBG_HCDV,
-+ " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",
-+ hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32));
+ hcint.d32 = hcint.d32 & hcintmsk.d32;
-+
-+ if(fiq_split_enable)
-+ {
-+ // replace with the saved interrupts from the fiq handler
-+ local_fiq_disable();
-+ hcint_orig.d32 = hcint_saved[num].d32;
-+ hcint.d32 = hcint_orig.d32 & hcintmsk_saved[num].d32;
-+ hcint_saved[num].d32 = 0;
-+ local_fiq_enable();
-+ }
-+
+ if (!dwc_otg_hcd->core_if->dma_enable) {
+ if (hcint.b.chhltd && hcint.d32 != 0x2) {
+ hcint.b.chhltd = 0;
@@ -77331,7 +80265,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ hcint.b.nyet = 0;
+ }
+ if (hcint.b.chhltd) {
-+ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd, hcint_orig, hcintmsk_saved[num]);
++ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
+ }
+ if (hcint.b.ahberr) {
+ retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
@@ -77367,10 +80301,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-raspbe
+ return retval;
+}
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,972 @@
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 2014-04-24 16:04:39.819124254 +0200
+@@ -0,0 +1,985 @@
+
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
@@ -77431,6 +80365,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+#else
+#include <linux/usb/hcd.h>
+#endif
++#include <asm/bug.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
+#define USB_URB_EP_LINKING 1
@@ -77442,7 +80377,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+#include "dwc_otg_dbg.h"
+#include "dwc_otg_driver.h"
+#include "dwc_otg_hcd.h"
-+#include "dwc_otg_mphi_fix.h"
++
++extern unsigned char _dwc_otg_fiq_stub, _dwc_otg_fiq_stub_end;
+
+/**
+ * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
@@ -77453,7 +80389,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+
+static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
+
-+extern bool fiq_fix_enable;
++extern bool fiq_enable;
+
+/** @name Linux HC Driver API Functions */
+/** @{ */
@@ -77724,7 +80660,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+ urb);
+ }
+ }
-+
+ DWC_FREE(dwc_otg_urb);
+ if (!new_entry) {
+ DWC_ERROR("dwc_otg_hcd: complete: cannot allocate URB TQ entry\n");
@@ -77768,13 +80703,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+static struct fiq_handler fh = {
+ .name = "usb_fiq",
+};
-+struct fiq_stack_s {
-+ int magic1;
-+ uint8_t stack[2048];
-+ int magic2;
-+} fiq_stack;
+
-+extern mphi_regs_t c_mphi_regs;
++
++
+/**
+ * Initializes the HCD. This function allocates memory for and initializes the
+ * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the
@@ -77806,20 +80737,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+ pci_set_consistent_dma_mask(_dev, dmamask);
+#endif
+
-+ if (fiq_fix_enable)
-+ {
-+ // Set up fiq
-+ claim_fiq(&fh);
-+ set_fiq_handler(__FIQ_Branch, 4);
-+ memset(&regs,0,sizeof(regs));
-+ regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq;
-+ regs.ARM_r9 = (long)0;
-+ regs.ARM_sp = (long)fiq_stack.stack + sizeof(fiq_stack.stack) - 4;
-+ set_fiq_regs(&regs);
-+ fiq_stack.magic1 = 0xdeadbeef;
-+ fiq_stack.magic2 = 0xaa995566;
-+ }
-+
+ /*
+ * Allocate memory for the base HCD plus the DWC OTG HCD.
+ * Initialize the base HCD.
@@ -77839,30 +80756,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+
+ hcd->regs = otg_dev->os_dep.base;
+
-+ if (fiq_fix_enable)
-+ {
-+ volatile extern void *dwc_regs_base;
-+
-+ //Set the mphi periph to the required registers
-+ c_mphi_regs.base = otg_dev->os_dep.mphi_base;
-+ c_mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
-+ c_mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
-+ c_mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
-+ c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
+
-+ dwc_regs_base = otg_dev->os_dep.base;
-+
-+ //Enable mphi peripheral
-+ writel((1<<31),c_mphi_regs.ctrl);
-+#ifdef DEBUG
-+ if (readl(c_mphi_regs.ctrl) & 0x80000000)
-+ DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n");
-+ else
-+ DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n");
-+#endif
-+ // Enable FIQ interrupt from USB peripheral
-+ enable_fiq(INTERRUPT_VC_USB);
-+ }
+ /* Initialize the DWC OTG HCD. */
+ dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
+ if (!dwc_otg_hcd) {
@@ -77876,6 +80770,55 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+ goto error2;
+ }
+
++ if (fiq_enable)
++ {
++ if (claim_fiq(&fh)) {
++ DWC_ERROR("Can't claim FIQ");
++ goto error2;
++ }
++
++ DWC_WARN("FIQ at 0x%08x", (fiq_fsm_enable ? (int)&dwc_otg_fiq_fsm : (int)&dwc_otg_fiq_nop));
++ DWC_WARN("FIQ ASM at 0x%08x length %d", (int)&_dwc_otg_fiq_stub, (int)(&_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub));
++
++ set_fiq_handler((void *) &_dwc_otg_fiq_stub, &_dwc_otg_fiq_stub_end - &_dwc_otg_fiq_stub);
++ memset(&regs,0,sizeof(regs));
++
++ regs.ARM_r8 = (long) dwc_otg_hcd->fiq_state;
++ if (fiq_fsm_enable) {
++ regs.ARM_r9 = dwc_otg_hcd->core_if->core_params->host_channels;
++ //regs.ARM_r10 = dwc_otg_hcd->dma;
++ regs.ARM_fp = (long) dwc_otg_fiq_fsm;
++ } else {
++ regs.ARM_fp = (long) dwc_otg_fiq_nop;
++ }
++
++ regs.ARM_sp = (long) dwc_otg_hcd->fiq_stack + (sizeof(struct fiq_stack) - 4);
++
++// __show_regs(&regs);
++ set_fiq_regs(&regs);
++
++ //Set the mphi periph to the required registers
++ dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base;
++ dwc_otg_hcd->fiq_state->mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
++ dwc_otg_hcd->fiq_state->mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
++ dwc_otg_hcd->fiq_state->mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
++ dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
++ dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
++ DWC_WARN("MPHI regs_base at 0x%08x", (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
++ //Enable mphi peripheral
++ writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
++#ifdef DEBUG
++ if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
++ DWC_WARN("MPHI periph has been enabled");
++ else
++ DWC_WARN("MPHI periph has NOT been enabled");
++#endif
++ // Enable FIQ interrupt from USB peripheral
++ enable_fiq(INTERRUPT_VC_USB);
++ local_fiq_enable();
++ }
++
++
+ otg_dev->hcd->otg_dev = otg_dev;
+ hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)
@@ -77990,9 +80933,13 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+/** Returns the current frame number. */
+static int get_frame_number(struct usb_hcd *hcd)
+{
++ hprt0_data_t hprt0;
+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
-+
-+ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
++ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
++ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED)
++ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd) >> 3;
++ else
++ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
+}
+
+#ifdef DEBUG
@@ -78343,10 +81290,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-raspb
+}
+
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,959 @@
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 2014-04-24 16:04:39.819124254 +0200
+@@ -0,0 +1,942 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $
+ * $Revision: #44 $
@@ -78390,7 +81337,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb
+
+#include "dwc_otg_hcd.h"
+#include "dwc_otg_regs.h"
-+#include "dwc_otg_mphi_fix.h"
+
+extern bool microframe_schedule;
+
@@ -78925,7 +81871,6 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb
+}
+
+
-+extern int g_next_sched_frame, g_np_count, g_np_sent;
+
+/**
+ * Schedules an interrupt or isochronous transfer in the periodic schedule.
@@ -78985,9 +81930,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb
+ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry);
+ }
+ else {
-+ if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame))
++ if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, hcd->fiq_state->next_sched_frame))
+ {
-+ g_next_sched_frame = qh->sched_frame;
++ hcd->fiq_state->next_sched_frame = qh->sched_frame;
+
+ }
+ /* Always start in the inactive schedule. */
@@ -79028,7 +81973,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb
+ /* Always start in the inactive schedule. */
+ DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive,
+ &qh->qh_list_entry);
-+ g_np_count++;
++ //hcd->fiq_state->kick_np_queues = 1;
+ } else {
+ status = schedule_periodic(hcd, qh);
+ if ( !hcd->periodic_qh_count ) {
@@ -79088,13 +82033,12 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb
+ hcd->non_periodic_qh_ptr->next;
+ }
+ DWC_LIST_REMOVE_INIT(&qh->qh_list_entry);
-+
-+ // If we've removed the last non-periodic entry then there are none left!
-+ g_np_count = g_np_sent;
++ //if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_inactive))
++ // hcd->fiq_state->kick_np_queues = 1;
+ } else {
+ deschedule_periodic(hcd, qh);
+ hcd->periodic_qh_count--;
-+ if( !hcd->periodic_qh_count ) {
++ if( !hcd->periodic_qh_count && !fiq_fsm_enable ) {
+ intr_mask.b.sofintr = 1;
+ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk,
+ intr_mask.d32, 0);
@@ -79119,28 +82063,11 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb
+ int sched_next_periodic_split)
+{
+ if (dwc_qh_is_non_per(qh)) {
-+
-+ dwc_otg_qh_t *qh_tmp;
-+ dwc_list_link_t *qh_list;
-+ DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive)
-+ {
-+ qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry);
-+ if(qh_tmp == qh)
-+ {
-+ /*
-+ * FIQ is being disabled because this one nevers gets a np_count increment
-+ * This is still not absolutely correct, but it should fix itself with
-+ * just an unnecessary extra interrupt
-+ */
-+ g_np_sent = g_np_count;
-+ }
-+ }
-+
-+
+ dwc_otg_hcd_qh_remove(hcd, qh);
+ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
+ /* Add back to inactive non-periodic schedule. */
+ dwc_otg_hcd_qh_add(hcd, qh);
++ //hcd->fiq_state->kick_np_queues = 1;
+ }
+ } else {
+ uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd);
@@ -79199,9 +82126,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb
+ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
+ &qh->qh_list_entry);
+ } else {
-+ if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame))
++ if(!dwc_frame_num_le(hcd->fiq_state->next_sched_frame, qh->sched_frame))
+ {
-+ g_next_sched_frame = qh->sched_frame;
++ hcd->fiq_state->next_sched_frame = qh->sched_frame;
+ }
+
+ DWC_LIST_MOVE_HEAD
@@ -79292,6 +82219,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb
+ if (*qh == NULL) {
+ retval = -DWC_E_NO_MEMORY;
+ goto done;
++ } else {
++ if (fiq_enable)
++ hcd->fiq_state->kick_np_queues = 1;
+ }
+ }
+ retval = dwc_otg_hcd_qh_add(hcd, *qh);
@@ -79306,178 +82236,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-raspb
+}
+
+#endif /* DWC_DEVICE_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,113 @@
-+#include "dwc_otg_regs.h"
-+#include "dwc_otg_dbg.h"
-+
-+void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name)
-+{
-+ DWC_DEBUGPL(DBG_USER, "*** Debugging from within the %s function: ***\n"
-+ "curmode: %1i Modemismatch: %1i otgintr: %1i sofintr: %1i\n"
-+ "rxstsqlvl: %1i nptxfempty : %1i ginnakeff: %1i goutnakeff: %1i\n"
-+ "ulpickint: %1i i2cintr: %1i erlysuspend:%1i usbsuspend: %1i\n"
-+ "usbreset: %1i enumdone: %1i isooutdrop: %1i eopframe: %1i\n"
-+ "restoredone: %1i epmismatch: %1i inepint: %1i outepintr: %1i\n"
-+ "incomplisoin:%1i incomplisoout:%1i fetsusp: %1i resetdet: %1i\n"
-+ "portintr: %1i hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i\n"
-+ "conidstschng:%1i disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
-+ function_name,
-+ gintsts.b.curmode,
-+ gintsts.b.modemismatch,
-+ gintsts.b.otgintr,
-+ gintsts.b.sofintr,
-+ gintsts.b.rxstsqlvl,
-+ gintsts.b.nptxfempty,
-+ gintsts.b.ginnakeff,
-+ gintsts.b.goutnakeff,
-+ gintsts.b.ulpickint,
-+ gintsts.b.i2cintr,
-+ gintsts.b.erlysuspend,
-+ gintsts.b.usbsuspend,
-+ gintsts.b.usbreset,
-+ gintsts.b.enumdone,
-+ gintsts.b.isooutdrop,
-+ gintsts.b.eopframe,
-+ gintsts.b.restoredone,
-+ gintsts.b.epmismatch,
-+ gintsts.b.inepint,
-+ gintsts.b.outepintr,
-+ gintsts.b.incomplisoin,
-+ gintsts.b.incomplisoout,
-+ gintsts.b.fetsusp,
-+ gintsts.b.resetdet,
-+ gintsts.b.portintr,
-+ gintsts.b.hcintr,
-+ gintsts.b.ptxfempty,
-+ gintsts.b.lpmtranrcvd,
-+ gintsts.b.conidstschng,
-+ gintsts.b.disconnect,
-+ gintsts.b.sessreqintr,
-+ gintsts.b.wkupintr);
-+ return;
-+}
-+
-+void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name)
-+{
-+ DWC_DEBUGPL(DBG_USER, "Interrupt Mask status (called from %s) :\n"
-+ "modemismatch: %1i otgintr: %1i sofintr: %1i rxstsqlvl: %1i\n"
-+ "nptxfempty: %1i ginnakeff: %1i goutnakeff: %1i ulpickint: %1i\n"
-+ "i2cintr: %1i erlysuspend:%1i usbsuspend: %1i usbreset: %1i\n"
-+ "enumdone: %1i isooutdrop: %1i eopframe: %1i restoredone: %1i\n"
-+ "epmismatch: %1i inepintr: %1i outepintr: %1i incomplisoin:%1i\n"
-+ "incomplisoout:%1i fetsusp: %1i resetdet: %1i portintr: %1i\n"
-+ "hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i conidstschng:%1i\n"
-+ "disconnect: %1i sessreqintr:%1i wkupintr: %1i\n",
-+ function_name,
-+ gintmsk.b.modemismatch,
-+ gintmsk.b.otgintr,
-+ gintmsk.b.sofintr,
-+ gintmsk.b.rxstsqlvl,
-+ gintmsk.b.nptxfempty,
-+ gintmsk.b.ginnakeff,
-+ gintmsk.b.goutnakeff,
-+ gintmsk.b.ulpickint,
-+ gintmsk.b.i2cintr,
-+ gintmsk.b.erlysuspend,
-+ gintmsk.b.usbsuspend,
-+ gintmsk.b.usbreset,
-+ gintmsk.b.enumdone,
-+ gintmsk.b.isooutdrop,
-+ gintmsk.b.eopframe,
-+ gintmsk.b.restoredone,
-+ gintmsk.b.epmismatch,
-+ gintmsk.b.inepintr,
-+ gintmsk.b.outepintr,
-+ gintmsk.b.incomplisoin,
-+ gintmsk.b.incomplisoout,
-+ gintmsk.b.fetsusp,
-+ gintmsk.b.resetdet,
-+ gintmsk.b.portintr,
-+ gintmsk.b.hcintr,
-+ gintmsk.b.ptxfempty,
-+ gintmsk.b.lpmtranrcvd,
-+ gintmsk.b.conidstschng,
-+ gintmsk.b.disconnect,
-+ gintmsk.b.sessreqintr,
-+ gintmsk.b.wkupintr);
-+ return;
-+}
-+
-+void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name)
-+{
-+ DWC_DEBUGPL(DBG_USER, "otg int register (from %s function):\n"
-+ "sesenddet:%1i sesreqsucstschung:%2i hstnegsucstschng:%1i\n"
-+ "hstnegdet:%1i adevtoutchng: %2i debdone: %1i\n"
-+ "mvic: %1i\n",
-+ function_name,
-+ gotgint.b.sesenddet,
-+ gotgint.b.sesreqsucstschng,
-+ gotgint.b.hstnegsucstschng,
-+ gotgint.b.hstnegdet,
-+ gotgint.b.adevtoutchng,
-+ gotgint.b.debdone,
-+ gotgint.b.mvic);
-+
-+ return;
-+}
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h 2014-03-11 17:33:06.000000000 +0100
-@@ -0,0 +1,48 @@
-+#ifndef __DWC_OTG_MPHI_FIX_H__
-+#define __DWC_OTG_MPHI_FIX_H__
-+#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_))
-+#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_))
-+
-+typedef struct {
-+ volatile void* base;
-+ volatile void* ctrl;
-+ volatile void* outdda;
-+ volatile void* outddb;
-+ volatile void* intstat;
-+} mphi_regs_t;
-+
-+void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name);
-+void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name);
-+void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name);
-+
-+extern gintsts_data_t gintsts_saved;
-+
-+#ifdef DEBUG
-+#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__)
-+#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__)
-+#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__)
-+
-+#else
-+#define DWC_DBG_PRINT_CORE_INT(_arg_)
-+#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_)
-+#define DWC_DBG_PRINT_OTG_INT(_arg_)
-+
-+#endif
-+
-+typedef enum {
-+ FIQDBG_SCHED = (1 << 0),
-+ FIQDBG_INT = (1 << 1),
-+ FIQDBG_ERR = (1 << 2),
-+ FIQDBG_PORTHUB = (1 << 3),
-+} FIQDBG_T;
-+
-+void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...);
-+#ifdef FIQ_DEBUG
-+#define fiq_print _fiq_print
-+#else
-+#define fiq_print(x, y, ...)
-+#endif
-+
-+extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable;
-+
-+#endif
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h 2014-04-24 16:04:39.819124254 +0200
@@ -0,0 +1,188 @@
+#ifndef _DWC_OS_DEP_H_
+#define _DWC_OS_DEP_H_
@@ -79667,9 +82428,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h linux-raspberr
+
+
+#endif /* _DWC_OS_DEP_H_ */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 2014-04-24 16:04:39.819124254 +0200
@@ -0,0 +1,2708 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $
@@ -82379,9 +85140,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-raspberry-p
+}
+
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 2014-04-24 15:35:04.177565820 +0200
@@ -0,0 +1,266 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $
@@ -82649,9 +85410,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-raspberry-p
+extern void do_test_mode(void *data);
+#endif
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 2014-04-24 15:35:04.177565820 +0200
@@ -0,0 +1,360 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $
@@ -83013,9 +85774,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-raspberr
+#endif /* __DWC_PCD_IF_H__ */
+
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 2014-04-24 16:04:39.823124292 +0200
@@ -0,0 +1,5147 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $
@@ -88164,9 +90925,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-raspbe
+}
+
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 2014-04-24 16:04:39.823124292 +0200
@@ -0,0 +1,1358 @@
+ /* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
@@ -89526,9 +92287,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-raspb
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+#endif /* DWC_HOST_ONLY */
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_regs.h
---- linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_regs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/dwc_otg_regs.h 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_regs.h
+--- linux-3.12.18/drivers/usb/host/dwc_otg/dwc_otg_regs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/dwc_otg_regs.h 2014-04-24 16:04:39.823124292 +0200
@@ -0,0 +1,2550 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
@@ -92080,10 +94841,10 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-raspberry-
+} gpwrdn_data_t;
+
+#endif
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/drivers/usb/host/dwc_otg/Makefile
---- linux-3.12.13/drivers/usb/host/dwc_otg/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/Makefile 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,81 @@
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/Makefile linux-rpi/drivers/usb/host/dwc_otg/Makefile
+--- linux-3.12.18/drivers/usb/host/dwc_otg/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/Makefile 2014-04-24 16:04:39.815124215 +0200
+@@ -0,0 +1,82 @@
+#
+# Makefile for DWC_otg Highspeed USB controller driver
+#
@@ -92098,22 +94859,22 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/dri
+ BUS_INTERFACE = -DPLATFORM_INTERFACE
+endif
+
-+#EXTRA_CFLAGS += -DDEBUG
-+#EXTRA_CFLAGS += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs
++#ccflags-y += -DDEBUG
++#ccflags-y += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs
+
+# Use one of the following flags to compile the software in host-only or
+# device-only mode.
-+#EXTRA_CFLAGS += -DDWC_HOST_ONLY
-+#EXTRA_CFLAGS += -DDWC_DEVICE_ONLY
-+
-+EXTRA_CFLAGS += -Dlinux -DDWC_HS_ELECT_TST
-+#EXTRA_CFLAGS += -DDWC_EN_ISOC
-+EXTRA_CFLAGS += -I$(obj)/../dwc_common_port
-+#EXTRA_CFLAGS += -I$(PORTLIB)
-+EXTRA_CFLAGS += -DDWC_LINUX
-+EXTRA_CFLAGS += $(CFI)
-+EXTRA_CFLAGS += $(BUS_INTERFACE)
-+#EXTRA_CFLAGS += -DDWC_DEV_SRPCAP
++#ccflags-y += -DDWC_HOST_ONLY
++#ccflags-y += -DDWC_DEVICE_ONLY
++
++ccflags-y += -Dlinux -DDWC_HS_ELECT_TST
++#ccflags-y += -DDWC_EN_ISOC
++ccflags-y += -I$(obj)/../dwc_common_port
++#ccflags-y += -I$(PORTLIB)
++ccflags-y += -DDWC_LINUX
++ccflags-y += $(CFI)
++ccflags-y += $(BUS_INTERFACE)
++#ccflags-y += -DDWC_DEV_SRPCAP
+
+obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o
+
@@ -92122,7 +94883,8 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/dri
+dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o
+dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o
+dwc_otg-objs += dwc_otg_adp.o
-+dwc_otg-objs += dwc_otg_mphi_fix.o
++dwc_otg-objs += dwc_otg_fiq_fsm.o
++dwc_otg-objs += dwc_otg_fiq_stub.o
+ifneq ($(CFI),)
+dwc_otg-objs += dwc_otg_cfi.o
+endif
@@ -92131,7 +94893,7 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/dri
+kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd))
+
+ifneq ($(kernrel3),2.6.20)
-+EXTRA_CFLAGS += $(CPPFLAGS)
++ccflags-y += $(CPPFLAGS)
+endif
+
+else
@@ -92165,9 +94927,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/Makefile linux-raspberry-pi/dri
+ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers
+
+endif
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-raspberry-pi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
---- linux-3.12.13/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-rpi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm
+--- linux-3.12.18/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 2014-04-24 16:04:39.823124292 +0200
@@ -0,0 +1,337 @@
+package dwc_otg_test;
+
@@ -92506,9 +95268,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-rasp
+);
+
+1;
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/Makefile linux-raspberry-pi/drivers/usb/host/dwc_otg/test/Makefile
---- linux-3.12.13/drivers/usb/host/dwc_otg/test/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/test/Makefile 2014-03-11 17:33:06.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/test/Makefile linux-rpi/drivers/usb/host/dwc_otg/test/Makefile
+--- linux-3.12.18/drivers/usb/host/dwc_otg/test/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/test/Makefile 2014-04-24 15:35:04.177565820 +0200
@@ -0,0 +1,16 @@
+
+PERL=/usr/bin/perl
@@ -92526,9 +95288,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/Makefile linux-raspberry-p
+ else echo "=======> $$test, FAILED" ; \
+ fi \
+ done
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-raspberry-pi/drivers/usb/host/dwc_otg/test/test_mod_param.pl
---- linux-3.12.13/drivers/usb/host/dwc_otg/test/test_mod_param.pl 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/test/test_mod_param.pl 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-rpi/drivers/usb/host/dwc_otg/test/test_mod_param.pl
+--- linux-3.12.18/drivers/usb/host/dwc_otg/test/test_mod_param.pl 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/test/test_mod_param.pl 2014-04-24 16:04:39.823124292 +0200
@@ -0,0 +1,133 @@
+#!/usr/bin/perl -w
+#
@@ -92663,9 +95425,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-ra
+
+test_main();
+0;
-diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-raspberry-pi/drivers/usb/host/dwc_otg/test/test_sysfs.pl
---- linux-3.12.13/drivers/usb/host/dwc_otg/test/test_sysfs.pl 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/dwc_otg/test/test_sysfs.pl 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-rpi/drivers/usb/host/dwc_otg/test/test_sysfs.pl
+--- linux-3.12.18/drivers/usb/host/dwc_otg/test/test_sysfs.pl 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/usb/host/dwc_otg/test/test_sysfs.pl 2014-04-24 16:04:39.823124292 +0200
@@ -0,0 +1,193 @@
+#!/usr/bin/perl -w
+#
@@ -92860,9 +95622,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-raspbe
+
+test_main();
+0;
-diff -Nur linux-3.12.13/drivers/usb/host/Kconfig linux-raspberry-pi/drivers/usb/host/Kconfig
---- linux-3.12.13/drivers/usb/host/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/Kconfig 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/Kconfig linux-rpi/drivers/usb/host/Kconfig
+--- linux-3.12.18/drivers/usb/host/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/usb/host/Kconfig 2014-04-24 16:04:39.811124176 +0200
@@ -650,6 +650,19 @@
To compile this driver a module, choose M here: the module
will be called "hwa-hc".
@@ -92883,9 +95645,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/Kconfig linux-raspberry-pi/drivers/usb/
config USB_IMX21_HCD
tristate "i.MX21 HCD support"
depends on ARM && ARCH_MXC
-diff -Nur linux-3.12.13/drivers/usb/host/Makefile linux-raspberry-pi/drivers/usb/host/Makefile
---- linux-3.12.13/drivers/usb/host/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/host/Makefile 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/host/Makefile linux-rpi/drivers/usb/host/Makefile
+--- linux-3.12.18/drivers/usb/host/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/usb/host/Makefile 2014-04-24 16:04:39.811124176 +0200
@@ -56,6 +56,8 @@
obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o
@@ -92895,9 +95657,9 @@ diff -Nur linux-3.12.13/drivers/usb/host/Makefile linux-raspberry-pi/drivers/usb
obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o
obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o
-diff -Nur linux-3.12.13/drivers/usb/Makefile linux-raspberry-pi/drivers/usb/Makefile
---- linux-3.12.13/drivers/usb/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/usb/Makefile 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/usb/Makefile linux-rpi/drivers/usb/Makefile
+--- linux-3.12.18/drivers/usb/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/usb/Makefile 2014-04-24 16:04:39.695123055 +0200
@@ -23,6 +23,7 @@
obj-$(CONFIG_USB_R8A66597_HCD) += host/
obj-$(CONFIG_USB_HWA_HCD) += host/
@@ -92906,10 +95668,56 @@ diff -Nur linux-3.12.13/drivers/usb/Makefile linux-raspberry-pi/drivers/usb/Make
obj-$(CONFIG_USB_IMX21_HCD) += host/
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/
obj-$(CONFIG_USB_FUSBH200_HCD) += host/
-diff -Nur linux-3.12.13/drivers/video/bcm2708_fb.c linux-raspberry-pi/drivers/video/bcm2708_fb.c
---- linux-3.12.13/drivers/video/bcm2708_fb.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/video/bcm2708_fb.c 2014-03-11 17:51:27.000000000 +0100
-@@ -0,0 +1,765 @@
+diff -Nur linux-3.12.18/drivers/vhost/net.c linux-rpi/drivers/vhost/net.c
+--- linux-3.12.18/drivers/vhost/net.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/vhost/net.c 2014-04-24 16:04:39.911125143 +0200
+@@ -501,13 +501,9 @@
+ r = -ENOBUFS;
+ goto err;
+ }
+- r = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg,
++ d = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg,
+ ARRAY_SIZE(vq->iov) - seg, &out,
+ &in, log, log_num);
+- if (unlikely(r < 0))
+- goto err;
+-
+- d = r;
+ if (d == vq->num) {
+ r = 0;
+ goto err;
+@@ -532,12 +528,6 @@
+ *iovcount = seg;
+ if (unlikely(log))
+ *log_num = nlogs;
+-
+- /* Detect overrun */
+- if (unlikely(datalen > 0)) {
+- r = UIO_MAXIOV + 1;
+- goto err;
+- }
+ return headcount;
+ err:
+ vhost_discard_vq_desc(vq, headcount);
+@@ -593,14 +583,6 @@
+ /* On error, stop handling until the next kick. */
+ if (unlikely(headcount < 0))
+ break;
+- /* On overrun, truncate and discard */
+- if (unlikely(headcount > UIO_MAXIOV)) {
+- msg.msg_iovlen = 1;
+- err = sock->ops->recvmsg(NULL, sock, &msg,
+- 1, MSG_DONTWAIT | MSG_TRUNC);
+- pr_debug("Discarded rx packet: len %zd\n", sock_len);
+- continue;
+- }
+ /* OK, now we need to know about added descriptors. */
+ if (!headcount) {
+ if (unlikely(vhost_enable_notify(&net->dev, vq))) {
+diff -Nur linux-3.12.18/drivers/video/bcm2708_fb.c linux-rpi/drivers/video/bcm2708_fb.c
+--- linux-3.12.18/drivers/video/bcm2708_fb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/video/bcm2708_fb.c 2014-04-24 16:04:39.919125220 +0200
+@@ -0,0 +1,762 @@
+/*
+ * linux/drivers/video/bcm2708_fb.c
+ *
@@ -93563,9 +96371,6 @@ diff -Nur linux-3.12.13/drivers/video/bcm2708_fb.c linux-raspberry-pi/drivers/vi
+
+ bcm2708_fb_debugfs_init(fb);
+
-+
-+ bcm2708_fb_debugfs_init(fb);
-+
+ fb->cb_base = dma_alloc_writecombine(&dev->dev, SZ_64K,
+ &fb->cb_handle, GFP_KERNEL);
+ if (!fb->cb_base) {
@@ -93675,9 +96480,9 @@ diff -Nur linux-3.12.13/drivers/video/bcm2708_fb.c linux-raspberry-pi/drivers/vi
+MODULE_PARM_DESC(fbheight, "Height of ARM Framebuffer");
+MODULE_PARM_DESC(fbdepth, "Bit depth of ARM Framebuffer");
+MODULE_PARM_DESC(fbswap, "Swap order of red and blue in 24 and 32 bit modes");
-diff -Nur linux-3.12.13/drivers/video/cfbimgblt.c linux-raspberry-pi/drivers/video/cfbimgblt.c
---- linux-3.12.13/drivers/video/cfbimgblt.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/video/cfbimgblt.c 2014-03-11 17:33:07.000000000 +0100
+diff -Nur linux-3.12.18/drivers/video/cfbimgblt.c linux-rpi/drivers/video/cfbimgblt.c
+--- linux-3.12.18/drivers/video/cfbimgblt.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/video/cfbimgblt.c 2014-04-24 15:35:04.265566801 +0200
@@ -28,6 +28,11 @@
*
* Also need to add code to deal with cards endians that are different than
@@ -93851,9 +96656,9 @@ diff -Nur linux-3.12.13/drivers/video/cfbimgblt.c linux-raspberry-pi/drivers/vid
slow_imageblit(image, p, dst1, fgcolor, bgcolor,
start_index, pitch_index);
} else
-diff -Nur linux-3.12.13/drivers/video/fbmem.c linux-raspberry-pi/drivers/video/fbmem.c
---- linux-3.12.13/drivers/video/fbmem.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/video/fbmem.c 2014-03-11 17:51:27.000000000 +0100
+diff -Nur linux-3.12.18/drivers/video/fbmem.c linux-rpi/drivers/video/fbmem.c
+--- linux-3.12.18/drivers/video/fbmem.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/video/fbmem.c 2014-04-24 16:04:39.923125259 +0200
@@ -1083,6 +1083,25 @@
}
EXPORT_SYMBOL(fb_blank);
@@ -93888,9 +96693,75 @@ diff -Nur linux-3.12.13/drivers/video/fbmem.c linux-raspberry-pi/drivers/video/f
void __user *argp = (void __user *)arg;
long ret = 0;
-@@ -1202,6 +1222,15 @@
+@@ -1108,16 +1128,14 @@
+ case FBIOPUT_VSCREENINFO:
+ if (copy_from_user(&var, argp, sizeof(var)))
+ return -EFAULT;
+- console_lock();
+- if (!lock_fb_info(info)) {
+- console_unlock();
++ if (!lock_fb_info(info))
+ return -ENODEV;
+- }
++ console_lock();
+ info->flags |= FBINFO_MISC_USEREVENT;
+ ret = fb_set_var(info, &var);
+ info->flags &= ~FBINFO_MISC_USEREVENT;
+- unlock_fb_info(info);
+ console_unlock();
++ unlock_fb_info(info);
+ if (!ret && copy_to_user(argp, &var, sizeof(var)))
+ ret = -EFAULT;
+ break;
+@@ -1146,14 +1164,12 @@
+ case FBIOPAN_DISPLAY:
+ if (copy_from_user(&var, argp, sizeof(var)))
+ return -EFAULT;
+- console_lock();
+- if (!lock_fb_info(info)) {
+- console_unlock();
++ if (!lock_fb_info(info))
+ return -ENODEV;
+- }
++ console_lock();
+ ret = fb_pan_display(info, &var);
+- unlock_fb_info(info);
console_unlock();
- unlock_fb_info(info);
++ unlock_fb_info(info);
+ if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
+ return -EFAULT;
+ break;
+@@ -1188,28 +1204,33 @@
+ break;
+ }
+ event.data = &con2fb;
+- console_lock();
+- if (!lock_fb_info(info)) {
+- console_unlock();
++ if (!lock_fb_info(info))
+ return -ENODEV;
+- }
++ console_lock();
+ event.info = info;
+ ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
+- unlock_fb_info(info);
+ console_unlock();
++ unlock_fb_info(info);
+ break;
+ case FBIOBLANK:
+- console_lock();
+- if (!lock_fb_info(info)) {
+- console_unlock();
++ if (!lock_fb_info(info))
+ return -ENODEV;
+- }
++ console_lock();
+ info->flags |= FBINFO_MISC_USEREVENT;
+ ret = fb_blank(info, arg);
+ info->flags &= ~FBINFO_MISC_USEREVENT;
+- unlock_fb_info(info);
+ console_unlock();
++ unlock_fb_info(info);
break;
+ case FBIOCOPYAREA:
+ if (info->flags & FBINFO_HWACCEL_COPYAREA) {
@@ -93904,7 +96775,7 @@ diff -Nur linux-3.12.13/drivers/video/fbmem.c linux-raspberry-pi/drivers/video/f
default:
if (!lock_fb_info(info))
return -ENODEV;
-@@ -1356,6 +1385,7 @@
+@@ -1364,6 +1385,7 @@
case FBIOPAN_DISPLAY:
case FBIOGET_CON2FBMAP:
case FBIOPUT_CON2FBMAP:
@@ -93912,9 +96783,168 @@ diff -Nur linux-3.12.13/drivers/video/fbmem.c linux-raspberry-pi/drivers/video/f
arg = (unsigned long) compat_ptr(arg);
case FBIOBLANK:
ret = do_fb_ioctl(info, cmd, arg);
-diff -Nur linux-3.12.13/drivers/video/Kconfig linux-raspberry-pi/drivers/video/Kconfig
---- linux-3.12.13/drivers/video/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/video/Kconfig 2014-03-11 17:51:27.000000000 +0100
+@@ -1577,10 +1599,10 @@
+ static int do_unregister_framebuffer(struct fb_info *fb_info);
+
+ #define VGA_FB_PHYS 0xA0000
+-static int do_remove_conflicting_framebuffers(struct apertures_struct *a,
+- const char *name, bool primary)
++static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
++ const char *name, bool primary)
+ {
+- int i, ret;
++ int i;
+
+ /* check all firmware fbs and kick off if the base addr overlaps */
+ for (i = 0 ; i < FB_MAX; i++) {
+@@ -1596,31 +1618,25 @@
+ (primary && gen_aper && gen_aper->count &&
+ gen_aper->ranges[0].base == VGA_FB_PHYS)) {
+
+- printk(KERN_INFO "fb: switching to %s from %s\n",
++ printk(KERN_INFO "fb: conflicting fb hw usage "
++ "%s vs %s - removing generic driver\n",
+ name, registered_fb[i]->fix.id);
+- ret = do_unregister_framebuffer(registered_fb[i]);
+- if (ret)
+- return ret;
++ do_unregister_framebuffer(registered_fb[i]);
+ }
+ }
+-
+- return 0;
+ }
+
+ static int do_register_framebuffer(struct fb_info *fb_info)
+ {
+- int i, ret;
++ int i;
+ struct fb_event event;
+ struct fb_videomode mode;
+
+ if (fb_check_foreignness(fb_info))
+ return -ENOSYS;
+
+- ret = do_remove_conflicting_framebuffers(fb_info->apertures,
+- fb_info->fix.id,
+- fb_is_primary_device(fb_info));
+- if (ret)
+- return ret;
++ do_remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
++ fb_is_primary_device(fb_info));
+
+ if (num_registered_fb == FB_MAX)
+ return -ENXIO;
+@@ -1674,15 +1690,12 @@
+ registered_fb[i] = fb_info;
+
+ event.info = fb_info;
+- console_lock();
+- if (!lock_fb_info(fb_info)) {
+- console_unlock();
++ if (!lock_fb_info(fb_info))
+ return -ENODEV;
+- }
+-
++ console_lock();
+ fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
+- unlock_fb_info(fb_info);
+ console_unlock();
++ unlock_fb_info(fb_info);
+ return 0;
+ }
+
+@@ -1695,16 +1708,13 @@
+ if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
+ return -EINVAL;
+
+- console_lock();
+- if (!lock_fb_info(fb_info)) {
+- console_unlock();
++ if (!lock_fb_info(fb_info))
+ return -ENODEV;
+- }
+-
++ console_lock();
+ event.info = fb_info;
+ ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
+- unlock_fb_info(fb_info);
+ console_unlock();
++ unlock_fb_info(fb_info);
+
+ if (ret)
+ return -EINVAL;
+@@ -1745,16 +1755,12 @@
+ }
+ EXPORT_SYMBOL(unlink_framebuffer);
+
+-int remove_conflicting_framebuffers(struct apertures_struct *a,
+- const char *name, bool primary)
++void remove_conflicting_framebuffers(struct apertures_struct *a,
++ const char *name, bool primary)
+ {
+- int ret;
+-
+ mutex_lock(&registration_lock);
+- ret = do_remove_conflicting_framebuffers(a, name, primary);
++ do_remove_conflicting_framebuffers(a, name, primary);
+ mutex_unlock(&registration_lock);
+-
+- return ret;
+ }
+ EXPORT_SYMBOL(remove_conflicting_framebuffers);
+
+diff -Nur linux-3.12.18/drivers/video/fbsysfs.c linux-rpi/drivers/video/fbsysfs.c
+--- linux-3.12.18/drivers/video/fbsysfs.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/video/fbsysfs.c 2014-04-24 15:35:04.277566935 +0200
+@@ -177,12 +177,9 @@
+ if (i * sizeof(struct fb_videomode) != count)
+ return -EINVAL;
+
+- console_lock();
+- if (!lock_fb_info(fb_info)) {
+- console_unlock();
++ if (!lock_fb_info(fb_info))
+ return -ENODEV;
+- }
+-
++ console_lock();
+ list_splice(&fb_info->modelist, &old_list);
+ fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
+ &fb_info->modelist);
+@@ -192,8 +189,8 @@
+ } else
+ fb_destroy_modelist(&old_list);
+
+- unlock_fb_info(fb_info);
+ console_unlock();
++ unlock_fb_info(fb_info);
+
+ return 0;
+ }
+@@ -407,16 +404,12 @@
+
+ state = simple_strtoul(buf, &last, 0);
+
+- console_lock();
+- if (!lock_fb_info(fb_info)) {
+- console_unlock();
++ if (!lock_fb_info(fb_info))
+ return -ENODEV;
+- }
+-
++ console_lock();
+ fb_set_suspend(fb_info, (int)state);
+-
+- unlock_fb_info(fb_info);
+ console_unlock();
++ unlock_fb_info(fb_info);
+
+ return count;
+ }
+diff -Nur linux-3.12.18/drivers/video/Kconfig linux-rpi/drivers/video/Kconfig
+--- linux-3.12.18/drivers/video/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/video/Kconfig 2014-04-24 16:04:39.911125143 +0200
@@ -310,6 +310,20 @@
help
Support the Permedia2 FIFO disconnect feature.
@@ -93936,9 +96966,9 @@ diff -Nur linux-3.12.13/drivers/video/Kconfig linux-raspberry-pi/drivers/video/K
config FB_ARMCLCD
tristate "ARM PrimeCell PL110 support"
depends on FB && ARM && ARM_AMBA
-diff -Nur linux-3.12.13/drivers/video/logo/logo_linux_clut224.ppm linux-raspberry-pi/drivers/video/logo/logo_linux_clut224.ppm
---- linux-3.12.13/drivers/video/logo/logo_linux_clut224.ppm 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/video/logo/logo_linux_clut224.ppm 2014-03-11 17:33:08.000000000 +0100
+diff -Nur linux-3.12.18/drivers/video/logo/logo_linux_clut224.ppm linux-rpi/drivers/video/logo/logo_linux_clut224.ppm
+--- linux-3.12.18/drivers/video/logo/logo_linux_clut224.ppm 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/video/logo/logo_linux_clut224.ppm 2014-04-24 15:35:04.285567024 +0200
@@ -1,1604 +1,883 @@
P3
-# Standard 224-color Linux logo
@@ -96425,9 +99455,9 @@ diff -Nur linux-3.12.13/drivers/video/logo/logo_linux_clut224.ppm linux-raspberr
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0
-diff -Nur linux-3.12.13/drivers/video/Makefile linux-raspberry-pi/drivers/video/Makefile
---- linux-3.12.13/drivers/video/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/video/Makefile 2014-03-11 17:33:07.000000000 +0100
+diff -Nur linux-3.12.18/drivers/video/Makefile linux-rpi/drivers/video/Makefile
+--- linux-3.12.18/drivers/video/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/video/Makefile 2014-04-24 15:35:04.249566623 +0200
@@ -100,6 +100,7 @@
obj-$(CONFIG_FB_VOODOO1) += sstfb.o
obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
@@ -96436,9 +99466,47 @@ diff -Nur linux-3.12.13/drivers/video/Makefile linux-raspberry-pi/drivers/video/
obj-$(CONFIG_FB_68328) += 68328fb.o
obj-$(CONFIG_FB_GBE) += gbefb.o
obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
-diff -Nur linux-3.12.13/drivers/w1/masters/w1-gpio.c linux-raspberry-pi/drivers/w1/masters/w1-gpio.c
---- linux-3.12.13/drivers/w1/masters/w1-gpio.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/w1/masters/w1-gpio.c 2014-03-11 17:51:32.000000000 +0100
+diff -Nur linux-3.12.18/drivers/video/sh_mobile_lcdcfb.c linux-rpi/drivers/video/sh_mobile_lcdcfb.c
+--- linux-3.12.18/drivers/video/sh_mobile_lcdcfb.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/video/sh_mobile_lcdcfb.c 2014-04-24 15:35:04.325567469 +0200
+@@ -574,9 +574,8 @@
+ switch (event) {
+ case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
+ /* HDMI plug in */
+- console_lock();
+ if (lock_fb_info(info)) {
+-
++ console_lock();
+
+ ch->display.width = monspec->max_x * 10;
+ ch->display.height = monspec->max_y * 10;
+@@ -595,20 +594,19 @@
+ fb_set_suspend(info, 0);
+ }
+
+-
++ console_unlock();
+ unlock_fb_info(info);
+ }
+- console_unlock();
+ break;
+
+ case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
+ /* HDMI disconnect */
+- console_lock();
+ if (lock_fb_info(info)) {
++ console_lock();
+ fb_set_suspend(info, 1);
++ console_unlock();
+ unlock_fb_info(info);
+ }
+- console_unlock();
+ break;
+
+ case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
+diff -Nur linux-3.12.18/drivers/w1/masters/w1-gpio.c linux-rpi/drivers/w1/masters/w1-gpio.c
+--- linux-3.12.18/drivers/w1/masters/w1-gpio.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/w1/masters/w1-gpio.c 2014-04-24 16:04:39.951125530 +0200
@@ -22,6 +22,9 @@
#include "../w1.h"
#include "../w1_int.h"
@@ -96480,9 +99548,9 @@ diff -Nur linux-3.12.13/drivers/w1/masters/w1-gpio.c linux-raspberry-pi/drivers/
err = w1_add_master_device(master);
if (err) {
dev_err(&pdev->dev, "w1_add_master device failed\n");
-diff -Nur linux-3.12.13/drivers/w1/w1.h linux-raspberry-pi/drivers/w1/w1.h
---- linux-3.12.13/drivers/w1/w1.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/w1/w1.h 2014-03-11 17:33:12.000000000 +0100
+diff -Nur linux-3.12.18/drivers/w1/w1.h linux-rpi/drivers/w1/w1.h
+--- linux-3.12.18/drivers/w1/w1.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/w1/w1.h 2014-04-24 15:35:04.349567736 +0200
@@ -148,6 +148,12 @@
*/
u8 (*set_pullup)(void *, int);
@@ -96496,29 +99564,21 @@ diff -Nur linux-3.12.13/drivers/w1/w1.h linux-raspberry-pi/drivers/w1/w1.h
/** Really nice hardware can handles the different types of ROM search
* w1_master* is passed to the slave found callback.
*/
-diff -Nur linux-3.12.13/drivers/w1/w1_int.c linux-raspberry-pi/drivers/w1/w1_int.c
---- linux-3.12.13/drivers/w1/w1_int.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/w1/w1_int.c 2014-03-11 17:33:12.000000000 +0100
-@@ -117,19 +117,21 @@
- printk(KERN_ERR "w1_add_master_device: invalid function set\n");
- return(-EINVAL);
- }
-- /* While it would be electrically possible to make a device that
-- * generated a strong pullup in bit bang mode, only hardware that
-- * controls 1-wire time frames are even expected to support a strong
-- * pullup. w1_io.c would need to support calling set_pullup before
-- * the last write_bit operation of a w1_write_8 which it currently
-- * doesn't.
-- */
-+
-+ /* bitbanging hardware uses bitbang_pullup, other hardware uses set_pullup
-+ * and takes care of timing itself */
- if (!master->write_byte && !master->touch_bit && master->set_pullup) {
- printk(KERN_ERR "w1_add_master_device: set_pullup requires "
- "write_byte or touch_bit, disabling\n");
+diff -Nur linux-3.12.18/drivers/w1/w1_int.c linux-rpi/drivers/w1/w1_int.c
+--- linux-3.12.18/drivers/w1/w1_int.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/w1/w1_int.c 2014-04-24 16:04:39.955125569 +0200
+@@ -130,6 +130,20 @@
master->set_pullup = NULL;
}
++ /* bitbanging hardware uses bitbang_pullup, other hardware uses set_pullup
++ * and takes care of timing itself */
++ if (!master->write_byte && !master->touch_bit && master->set_pullup) {
++ printk(KERN_ERR "w1_add_master_device: set_pullup requires "
++ "write_byte or touch_bit, disabling\n");
++ master->set_pullup = NULL;
++ }
++
+ if (master->set_pullup && master->bitbang_pullup) {
+ printk(KERN_ERR "w1_add_master_device: set_pullup should not "
+ "be set when bitbang_pullup is used, disabling\n");
@@ -96528,9 +99588,9 @@ diff -Nur linux-3.12.13/drivers/w1/w1_int.c linux-raspberry-pi/drivers/w1/w1_int
/* Lock until the device is added (or not) to w1_masters. */
mutex_lock(&w1_mlock);
/* Search for the first available id (starting at 1). */
-diff -Nur linux-3.12.13/drivers/w1/w1_io.c linux-raspberry-pi/drivers/w1/w1_io.c
---- linux-3.12.13/drivers/w1/w1_io.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/w1/w1_io.c 2014-03-11 17:33:12.000000000 +0100
+diff -Nur linux-3.12.18/drivers/w1/w1_io.c linux-rpi/drivers/w1/w1_io.c
+--- linux-3.12.18/drivers/w1/w1_io.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/w1/w1_io.c 2014-04-24 15:35:04.349567736 +0200
@@ -127,10 +127,22 @@
static void w1_post_write(struct w1_master *dev)
{
@@ -96557,9 +99617,9 @@ diff -Nur linux-3.12.13/drivers/w1/w1_io.c linux-raspberry-pi/drivers/w1/w1_io.c
dev->pullup_duration = 0;
}
}
-diff -Nur linux-3.12.13/drivers/watchdog/bcm2708_wdog.c linux-raspberry-pi/drivers/watchdog/bcm2708_wdog.c
---- linux-3.12.13/drivers/watchdog/bcm2708_wdog.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/drivers/watchdog/bcm2708_wdog.c 2014-03-11 17:51:32.000000000 +0100
+diff -Nur linux-3.12.18/drivers/watchdog/bcm2708_wdog.c linux-rpi/drivers/watchdog/bcm2708_wdog.c
+--- linux-3.12.18/drivers/watchdog/bcm2708_wdog.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/drivers/watchdog/bcm2708_wdog.c 2014-04-24 16:04:39.955125569 +0200
@@ -0,0 +1,384 @@
+/*
+ * Broadcom BCM2708 watchdog driver.
@@ -96945,9 +100005,9 @@ diff -Nur linux-3.12.13/drivers/watchdog/bcm2708_wdog.c linux-raspberry-pi/drive
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
+MODULE_LICENSE("GPL");
-diff -Nur linux-3.12.13/drivers/watchdog/Kconfig linux-raspberry-pi/drivers/watchdog/Kconfig
---- linux-3.12.13/drivers/watchdog/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/watchdog/Kconfig 2014-03-11 17:51:32.000000000 +0100
+diff -Nur linux-3.12.18/drivers/watchdog/Kconfig linux-rpi/drivers/watchdog/Kconfig
+--- linux-3.12.18/drivers/watchdog/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/watchdog/Kconfig 2014-04-24 16:04:39.955125569 +0200
@@ -392,6 +392,12 @@
To compile this driver as a module, choose M here: the
module will be called retu_wdt.
@@ -96961,9 +100021,9 @@ diff -Nur linux-3.12.13/drivers/watchdog/Kconfig linux-raspberry-pi/drivers/watc
# AVR32 Architecture
config AT32AP700X_WDT
-diff -Nur linux-3.12.13/drivers/watchdog/Makefile linux-raspberry-pi/drivers/watchdog/Makefile
---- linux-3.12.13/drivers/watchdog/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/drivers/watchdog/Makefile 2014-03-11 17:51:32.000000000 +0100
+diff -Nur linux-3.12.18/drivers/watchdog/Makefile linux-rpi/drivers/watchdog/Makefile
+--- linux-3.12.18/drivers/watchdog/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/drivers/watchdog/Makefile 2014-04-24 16:04:39.955125569 +0200
@@ -54,6 +54,7 @@
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o
@@ -96972,9 +100032,102 @@ diff -Nur linux-3.12.13/drivers/watchdog/Makefile linux-raspberry-pi/drivers/wat
obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o
# AVR32 Architecture
-diff -Nur linux-3.12.13/include/linux/broadcom/vc_cma.h linux-raspberry-pi/include/linux/broadcom/vc_cma.h
---- linux-3.12.13/include/linux/broadcom/vc_cma.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/include/linux/broadcom/vc_cma.h 2014-03-11 17:51:38.000000000 +0100
+diff -Nur linux-3.12.18/fs/ext4/inode.c linux-rpi/fs/ext4/inode.c
+--- linux-3.12.18/fs/ext4/inode.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/fs/ext4/inode.c 2014-04-24 16:04:40.039126380 +0200
+@@ -4447,12 +4447,7 @@
+ return -EIO;
+ }
+
+- /*
+- * No need to force transaction in WB_SYNC_NONE mode. Also
+- * ext4_sync_fs() will force the commit after everything is
+- * written.
+- */
+- if (wbc->sync_mode != WB_SYNC_ALL || wbc->for_sync)
++ if (wbc->sync_mode != WB_SYNC_ALL)
+ return 0;
+
+ err = ext4_force_commit(inode->i_sb);
+@@ -4462,11 +4457,7 @@
+ err = __ext4_get_inode_loc(inode, &iloc, 0);
+ if (err)
+ return err;
+- /*
+- * sync(2) will flush the whole buffer cache. No need to do
+- * it here separately for each inode.
+- */
+- if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync)
++ if (wbc->sync_mode == WB_SYNC_ALL)
+ sync_dirty_buffer(iloc.bh);
+ if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) {
+ EXT4_ERROR_INODE_BLOCK(inode, iloc.bh->b_blocknr,
+diff -Nur linux-3.12.18/fs/nfs/nfs3acl.c linux-rpi/fs/nfs/nfs3acl.c
+--- linux-3.12.18/fs/nfs/nfs3acl.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/fs/nfs/nfs3acl.c 2014-04-24 15:35:04.557570053 +0200
+@@ -289,8 +289,8 @@
+ return acl;
+ }
+
+-static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+- struct posix_acl *dfacl)
++static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
++ struct posix_acl *dfacl)
+ {
+ struct nfs_server *server = NFS_SERVER(inode);
+ struct nfs_fattr *fattr;
+@@ -373,15 +373,6 @@
+ return status;
+ }
+
+-int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+- struct posix_acl *dfacl)
+-{
+- int ret;
+- ret = __nfs3_proc_setacls(inode, acl, dfacl);
+- return (ret == -EOPNOTSUPP) ? 0 : ret;
+-
+-}
+-
+ int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
+ {
+ struct posix_acl *alloc = NULL, *dfacl = NULL;
+@@ -415,7 +406,7 @@
+ if (IS_ERR(alloc))
+ goto fail;
+ }
+- status = __nfs3_proc_setacls(inode, acl, dfacl);
++ status = nfs3_proc_setacls(inode, acl, dfacl);
+ posix_acl_release(alloc);
+ return status;
+
+diff -Nur linux-3.12.18/fs/nfs/nfs4xdr.c linux-rpi/fs/nfs/nfs4xdr.c
+--- linux-3.12.18/fs/nfs/nfs4xdr.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/fs/nfs/nfs4xdr.c 2014-04-24 16:04:40.091126883 +0200
+@@ -3405,7 +3405,7 @@
+ {
+ __be32 *p;
+
+- *res = 0;
++ *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL;
+ if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
+ return -EIO;
+ if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
+diff -Nur linux-3.12.18/include/drm/drm_crtc.h linux-rpi/include/drm/drm_crtc.h
+--- linux-3.12.18/include/drm/drm_crtc.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/drm/drm_crtc.h 2014-04-24 16:04:40.179127734 +0200
+@@ -1108,8 +1108,6 @@
+ int GTF_2C, int GTF_K, int GTF_2J);
+ extern int drm_add_modes_noedid(struct drm_connector *connector,
+ int hdisplay, int vdisplay);
+-extern void drm_set_preferred_mode(struct drm_connector *connector,
+- int hpref, int vpref);
+
+ extern int drm_edid_header_is_valid(const u8 *raw_edid);
+ extern bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid);
+diff -Nur linux-3.12.18/include/linux/broadcom/vc_cma.h linux-rpi/include/linux/broadcom/vc_cma.h
+--- linux-3.12.18/include/linux/broadcom/vc_cma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/include/linux/broadcom/vc_cma.h 2014-04-24 16:04:40.687132644 +0200
@@ -0,0 +1,29 @@
+/*****************************************************************************
+* Copyright 2012 Broadcom Corporation. All rights reserved.
@@ -97005,9 +100158,38 @@ diff -Nur linux-3.12.13/include/linux/broadcom/vc_cma.h linux-raspberry-pi/inclu
+#endif
+
+#endif /* VC_CMA_H */
-diff -Nur linux-3.12.13/include/linux/mmc/host.h linux-raspberry-pi/include/linux/mmc/host.h
---- linux-3.12.13/include/linux/mmc/host.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/include/linux/mmc/host.h 2014-03-11 17:51:40.000000000 +0100
+diff -Nur linux-3.12.18/include/linux/fb.h linux-rpi/include/linux/fb.h
+--- linux-3.12.18/include/linux/fb.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/linux/fb.h 2014-04-24 16:04:40.731133070 +0200
+@@ -613,8 +613,8 @@
+ extern int register_framebuffer(struct fb_info *fb_info);
+ extern int unregister_framebuffer(struct fb_info *fb_info);
+ extern int unlink_framebuffer(struct fb_info *fb_info);
+-extern int remove_conflicting_framebuffers(struct apertures_struct *a,
+- const char *name, bool primary);
++extern void remove_conflicting_framebuffers(struct apertures_struct *a,
++ const char *name, bool primary);
+ extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
+ extern int fb_show_logo(struct fb_info *fb_info, int rotate);
+ extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
+diff -Nur linux-3.12.18/include/linux/futex.h linux-rpi/include/linux/futex.h
+--- linux-3.12.18/include/linux/futex.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/linux/futex.h 2014-04-24 16:04:40.751133263 +0200
+@@ -55,11 +55,7 @@
+ #ifdef CONFIG_FUTEX
+ extern void exit_robust_list(struct task_struct *curr);
+ extern void exit_pi_state_list(struct task_struct *curr);
+-#ifdef CONFIG_HAVE_FUTEX_CMPXCHG
+-#define futex_cmpxchg_enabled 1
+-#else
+ extern int futex_cmpxchg_enabled;
+-#endif
+ #else
+ static inline void exit_robust_list(struct task_struct *curr)
+ {
+diff -Nur linux-3.12.18/include/linux/mmc/host.h linux-rpi/include/linux/mmc/host.h
+--- linux-3.12.18/include/linux/mmc/host.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/linux/mmc/host.h 2014-04-24 16:04:40.819133921 +0200
@@ -281,6 +281,7 @@
MMC_CAP2_PACKED_WR)
#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */
@@ -97016,9 +100198,9 @@ diff -Nur linux-3.12.13/include/linux/mmc/host.h linux-raspberry-pi/include/linu
mmc_pm_flag_t pm_caps; /* supported pm features */
-diff -Nur linux-3.12.13/include/linux/mmc/sdhci.h linux-raspberry-pi/include/linux/mmc/sdhci.h
---- linux-3.12.13/include/linux/mmc/sdhci.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/include/linux/mmc/sdhci.h 2014-03-11 17:51:40.000000000 +0100
+diff -Nur linux-3.12.18/include/linux/mmc/sdhci.h linux-rpi/include/linux/mmc/sdhci.h
+--- linux-3.12.18/include/linux/mmc/sdhci.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/linux/mmc/sdhci.h 2014-04-24 16:04:40.819133921 +0200
@@ -100,6 +100,7 @@
#define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5)
@@ -97043,9 +100225,66 @@ diff -Nur linux-3.12.13/include/linux/mmc/sdhci.h linux-raspberry-pi/include/lin
struct mmc_data *data; /* Current data request */
unsigned int data_early:1; /* Data finished before cmd */
-diff -Nur linux-3.12.13/include/sound/soc-dai.h linux-raspberry-pi/include/sound/soc-dai.h
---- linux-3.12.13/include/sound/soc-dai.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/include/sound/soc-dai.h 2014-03-11 17:33:22.000000000 +0100
+diff -Nur linux-3.12.18/include/linux/usb/usbnet.h linux-rpi/include/linux/usb/usbnet.h
+--- linux-3.12.18/include/linux/usb/usbnet.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/linux/usb/usbnet.h 2014-04-24 16:04:40.871134423 +0200
+@@ -30,7 +30,7 @@
+ struct driver_info *driver_info;
+ const char *driver_name;
+ void *driver_priv;
+- wait_queue_head_t wait;
++ wait_queue_head_t *wait;
+ struct mutex phy_mutex;
+ unsigned char suspend_count;
+ unsigned char pkt_cnt, pkt_err;
+diff -Nur linux-3.12.18/include/net/sock.h linux-rpi/include/net/sock.h
+--- linux-3.12.18/include/net/sock.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/net/sock.h 2014-04-24 16:04:41.511140609 +0200
+@@ -1459,11 +1459,6 @@
+ */
+ #define sock_owned_by_user(sk) ((sk)->sk_lock.owned)
+
+-static inline void sock_release_ownership(struct sock *sk)
+-{
+- sk->sk_lock.owned = 0;
+-}
+-
+ /*
+ * Macro so as to not evaluate some arguments when
+ * lockdep is not enabled.
+diff -Nur linux-3.12.18/include/net/tcp.h linux-rpi/include/net/tcp.h
+--- linux-3.12.18/include/net/tcp.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/net/tcp.h 2014-04-24 16:04:41.511140609 +0200
+@@ -484,21 +484,20 @@
+ #ifdef CONFIG_SYN_COOKIES
+ #include <linux/ktime.h>
+
+-/* Syncookies use a monotonic timer which increments every 60 seconds.
++/* Syncookies use a monotonic timer which increments every 64 seconds.
+ * This counter is used both as a hash input and partially encoded into
+ * the cookie value. A cookie is only validated further if the delta
+ * between the current counter value and the encoded one is less than this,
+- * i.e. a sent cookie is valid only at most for 2*60 seconds (or less if
++ * i.e. a sent cookie is valid only at most for 128 seconds (or less if
+ * the counter advances immediately after a cookie is generated).
+ */
+ #define MAX_SYNCOOKIE_AGE 2
+
+ static inline u32 tcp_cookie_time(void)
+ {
+- u64 val = get_jiffies_64();
+-
+- do_div(val, 60 * HZ);
+- return val;
++ struct timespec now;
++ getnstimeofday(&now);
++ return now.tv_sec >> 6; /* 64 seconds granularity */
+ }
+
+ extern u32 __cookie_v4_init_sequence(const struct iphdr *iph,
+diff -Nur linux-3.12.18/include/sound/soc-dai.h linux-rpi/include/sound/soc-dai.h
+--- linux-3.12.18/include/sound/soc-dai.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/sound/soc-dai.h 2014-04-24 15:35:04.921574108 +0200
@@ -105,6 +105,8 @@
int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int pll_id, int source, unsigned int freq_in, unsigned int freq_out);
@@ -97063,9 +100302,9 @@ diff -Nur linux-3.12.13/include/sound/soc-dai.h linux-raspberry-pi/include/sound
/*
* DAI format configuration
-diff -Nur linux-3.12.13/include/uapi/linux/fb.h linux-raspberry-pi/include/uapi/linux/fb.h
---- linux-3.12.13/include/uapi/linux/fb.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/include/uapi/linux/fb.h 2014-03-11 17:33:22.000000000 +0100
+diff -Nur linux-3.12.18/include/uapi/linux/fb.h linux-rpi/include/uapi/linux/fb.h
+--- linux-3.12.18/include/uapi/linux/fb.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/uapi/linux/fb.h 2014-04-24 15:35:04.941574330 +0200
@@ -34,6 +34,11 @@
#define FBIOPUT_MODEINFO 0x4617
#define FBIOGET_DISPINFO 0x4618
@@ -97078,10 +100317,1198 @@ diff -Nur linux-3.12.13/include/uapi/linux/fb.h linux-raspberry-pi/include/uapi/
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
#define FB_TYPE_PLANES 1 /* Non interleaved planes */
-diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835.c
---- linux-3.12.13/sound/arm/bcm2835.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/arm/bcm2835.c 2014-03-11 17:51:48.000000000 +0100
-@@ -0,0 +1,413 @@
+diff -Nur linux-3.12.18/include/uapi/linux/fd.h linux-rpi/include/uapi/linux/fd.h
+--- linux-3.12.18/include/uapi/linux/fd.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/include/uapi/linux/fd.h 2014-04-24 15:35:04.945574375 +0200
+@@ -185,8 +185,7 @@
+ * to clear media change status */
+ FD_UNUSED_BIT,
+ FD_DISK_CHANGED_BIT, /* disk has been changed since last i/o */
+- FD_DISK_WRITABLE_BIT, /* disk is writable */
+- FD_OPEN_SHOULD_FAIL_BIT
++ FD_DISK_WRITABLE_BIT /* disk is writable */
+ };
+
+ #define FDSETDRVPRM _IOW(2, 0x90, struct floppy_drive_params)
+diff -Nur linux-3.12.18/init/Kconfig linux-rpi/init/Kconfig
+--- linux-3.12.18/init/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/init/Kconfig 2014-04-24 16:04:41.543140918 +0200
+@@ -1406,13 +1406,6 @@
+ support for "fast userspace mutexes". The resulting kernel may not
+ run glibc-based applications correctly.
+
+-config HAVE_FUTEX_CMPXCHG
+- bool
+- help
+- Architectures should select this if futex_atomic_cmpxchg_inatomic()
+- is implemented and always working. This removes a couple of runtime
+- checks.
+-
+ config EPOLL
+ bool "Enable eventpoll support" if EXPERT
+ default y
+diff -Nur linux-3.12.18/kernel/cgroup.c linux-rpi/kernel/cgroup.c
+--- linux-3.12.18/kernel/cgroup.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/kernel/cgroup.c 2014-04-24 16:04:41.547140957 +0200
+@@ -5558,6 +5558,33 @@
+ }
+ __setup("cgroup_disable=", cgroup_disable);
+
++static int __init cgroup_enable(char *str)
++{
++ struct cgroup_subsys *ss;
++ char *token;
++ int i;
++
++ while ((token = strsep(&str, ",")) != NULL) {
++ if (!*token)
++ continue;
++
++ /*
++ * cgroup_disable, being at boot time, can't know about
++ * module subsystems, so we don't worry about them.
++ */
++ for_each_builtin_subsys(ss, i) {
++ if (!strcmp(token, ss->name)) {
++ ss->disabled = 0;
++ printk(KERN_INFO "Disabling %s control group"
++ " subsystem\n", ss->name);
++ break;
++ }
++ }
++ }
++ return 1;
++}
++__setup("cgroup_enable=", cgroup_enable);
++
+ /*
+ * Functons for CSS ID.
+ */
+diff -Nur linux-3.12.18/kernel/futex.c linux-rpi/kernel/futex.c
+--- linux-3.12.18/kernel/futex.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/kernel/futex.c 2014-04-24 16:04:41.551140996 +0200
+@@ -68,9 +68,7 @@
+
+ #include "rtmutex_common.h"
+
+-#ifndef CONFIG_HAVE_FUTEX_CMPXCHG
+ int __read_mostly futex_cmpxchg_enabled;
+-#endif
+
+ #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
+
+@@ -2733,10 +2731,10 @@
+ return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
+ }
+
+-static void __init futex_detect_cmpxchg(void)
++static int __init futex_init(void)
+ {
+-#ifndef CONFIG_HAVE_FUTEX_CMPXCHG
+ u32 curval;
++ int i;
+
+ /*
+ * This will fail and we want it. Some arch implementations do
+@@ -2750,14 +2748,6 @@
+ */
+ if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
+ futex_cmpxchg_enabled = 1;
+-#endif
+-}
+-
+-static int __init futex_init(void)
+-{
+- int i;
+-
+- futex_detect_cmpxchg();
+
+ for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
+ plist_head_init(&futex_queues[i].chain);
+diff -Nur linux-3.12.18/lib/nlattr.c linux-rpi/lib/nlattr.c
+--- linux-3.12.18/lib/nlattr.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/lib/nlattr.c 2014-04-24 16:04:41.611141576 +0200
+@@ -303,15 +303,9 @@
+ */
+ int nla_strcmp(const struct nlattr *nla, const char *str)
+ {
+- int len = strlen(str);
+- char *buf = nla_data(nla);
+- int attrlen = nla_len(nla);
+- int d;
++ int len = strlen(str) + 1;
++ int d = nla_len(nla) - len;
+
+- if (attrlen > 0 && buf[attrlen - 1] == '\0')
+- attrlen--;
+-
+- d = attrlen - len;
+ if (d == 0)
+ d = memcmp(nla_data(nla), str, len);
+
+diff -Nur linux-3.12.18/mm/memcontrol.c linux-rpi/mm/memcontrol.c
+--- linux-3.12.18/mm/memcontrol.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/mm/memcontrol.c 2014-04-24 16:04:41.619141653 +0200
+@@ -7030,6 +7030,7 @@
+ .base_cftypes = mem_cgroup_files,
+ .early_init = 0,
+ .use_id = 1,
++ .disabled = 1,
+ };
+
+ #ifdef CONFIG_MEMCG_SWAP
+diff -Nur linux-3.12.18/net/8021q/vlan.c linux-rpi/net/8021q/vlan.c
+--- linux-3.12.18/net/8021q/vlan.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/8021q/vlan.c 2014-04-24 16:04:41.635141808 +0200
+@@ -307,11 +307,9 @@
+ static void vlan_transfer_features(struct net_device *dev,
+ struct net_device *vlandev)
+ {
+- struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
+-
+ vlandev->gso_max_size = dev->gso_max_size;
+
+- if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
++ if (dev->features & NETIF_F_HW_VLAN_CTAG_TX)
+ vlandev->hard_header_len = dev->hard_header_len;
+ else
+ vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
+diff -Nur linux-3.12.18/net/8021q/vlan_dev.c linux-rpi/net/8021q/vlan_dev.c
+--- linux-3.12.18/net/8021q/vlan_dev.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/8021q/vlan_dev.c 2014-04-24 16:04:41.635141808 +0200
+@@ -557,9 +557,6 @@
+ struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
+ struct net_device *real_dev = vlan->real_dev;
+
+- if (saddr == NULL)
+- saddr = dev->dev_addr;
+-
+ return dev_hard_header(skb, real_dev, type, daddr, saddr, len);
+ }
+
+@@ -611,8 +608,7 @@
+ #endif
+
+ dev->needed_headroom = real_dev->needed_headroom;
+- if (vlan_hw_offload_capable(real_dev->features,
+- vlan_dev_priv(dev)->vlan_proto)) {
++ if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
+ dev->header_ops = &vlan_passthru_header_ops;
+ dev->hard_header_len = real_dev->hard_header_len;
+ } else {
+diff -Nur linux-3.12.18/net/bridge/br_multicast.c linux-rpi/net/bridge/br_multicast.c
+--- linux-3.12.18/net/bridge/br_multicast.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/bridge/br_multicast.c 2014-04-24 16:04:41.647141924 +0200
+@@ -1129,10 +1129,9 @@
+ struct net_bridge_port *port,
+ struct bridge_mcast_querier *querier,
+ int saddr,
+- bool is_general_query,
+ unsigned long max_delay)
+ {
+- if (saddr && is_general_query)
++ if (saddr)
+ br_multicast_update_querier_timer(br, querier, max_delay);
+ else if (timer_pending(&querier->timer))
+ return;
+@@ -1184,16 +1183,8 @@
+ IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
+ }
+
+- /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer
+- * all-systems destination addresses (224.0.0.1) for general queries
+- */
+- if (!group && iph->daddr != htonl(INADDR_ALLHOSTS_GROUP)) {
+- err = -EINVAL;
+- goto out;
+- }
+-
+ br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr,
+- !group, max_delay);
++ max_delay);
+
+ if (!group)
+ goto out;
+@@ -1239,7 +1230,6 @@
+ unsigned long max_delay;
+ unsigned long now = jiffies;
+ const struct in6_addr *group = NULL;
+- bool is_general_query;
+ int err = 0;
+ u16 vid = 0;
+
+@@ -1248,12 +1238,6 @@
+ (port && port->state == BR_STATE_DISABLED))
+ goto out;
+
+- /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */
+- if (!(ipv6_addr_type(&ip6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
+- err = -EINVAL;
+- goto out;
+- }
+-
+ if (skb->len == sizeof(*mld)) {
+ if (!pskb_may_pull(skb, sizeof(*mld))) {
+ err = -EINVAL;
+@@ -1275,19 +1259,8 @@
+ max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL);
+ }
+
+- is_general_query = group && ipv6_addr_any(group);
+-
+- /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer
+- * all-nodes destination address (ff02::1) for general queries
+- */
+- if (is_general_query && !ipv6_addr_is_ll_all_nodes(&ip6h->daddr)) {
+- err = -EINVAL;
+- goto out;
+- }
+-
+ br_multicast_query_received(br, port, &br->ip6_querier,
+- !ipv6_addr_any(&ip6h->saddr),
+- is_general_query, max_delay);
++ !ipv6_addr_any(&ip6h->saddr), max_delay);
+
+ if (!group)
+ goto out;
+diff -Nur linux-3.12.18/net/core/netpoll.c linux-rpi/net/core/netpoll.c
+--- linux-3.12.18/net/core/netpoll.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/core/netpoll.c 2014-04-24 16:04:41.659142040 +0200
+@@ -740,7 +740,7 @@
+ struct nd_msg *msg;
+ struct ipv6hdr *hdr;
+
+- if (skb->protocol != htons(ETH_P_IPV6))
++ if (skb->protocol != htons(ETH_P_ARP))
+ return false;
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg)))
+ return false;
+diff -Nur linux-3.12.18/net/core/rtnetlink.c linux-rpi/net/core/rtnetlink.c
+--- linux-3.12.18/net/core/rtnetlink.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/core/rtnetlink.c 2014-04-24 16:04:41.659142040 +0200
+@@ -2014,13 +2014,12 @@
+ static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
+ struct net_device *dev,
+ u8 *addr, u32 pid, u32 seq,
+- int type, unsigned int flags,
+- int nlflags)
++ int type, unsigned int flags)
+ {
+ struct nlmsghdr *nlh;
+ struct ndmsg *ndm;
+
+- nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), nlflags);
++ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI);
+ if (!nlh)
+ return -EMSGSIZE;
+
+@@ -2058,7 +2057,7 @@
+ if (!skb)
+ goto errout;
+
+- err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF, 0);
++ err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF);
+ if (err < 0) {
+ kfree_skb(skb);
+ goto errout;
+@@ -2283,8 +2282,7 @@
+
+ err = nlmsg_populate_fdb_fill(skb, dev, ha->addr,
+ portid, seq,
+- RTM_NEWNEIGH, NTF_SELF,
+- NLM_F_MULTI);
++ RTM_NEWNEIGH, NTF_SELF);
+ if (err < 0)
+ return err;
+ skip:
+diff -Nur linux-3.12.18/net/core/sock.c linux-rpi/net/core/sock.c
+--- linux-3.12.18/net/core/sock.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/core/sock.c 2014-04-24 16:04:41.659142040 +0200
+@@ -2359,13 +2359,10 @@
+ if (sk->sk_backlog.tail)
+ __release_sock(sk);
+
+- /* Warning : release_cb() might need to release sk ownership,
+- * ie call sock_release_ownership(sk) before us.
+- */
+ if (sk->sk_prot->release_cb)
+ sk->sk_prot->release_cb(sk);
+
+- sock_release_ownership(sk);
++ sk->sk_lock.owned = 0;
+ if (waitqueue_active(&sk->sk_lock.wq))
+ wake_up(&sk->sk_lock.wq);
+ spin_unlock_bh(&sk->sk_lock.slock);
+diff -Nur linux-3.12.18/net/ipv4/gre_demux.c linux-rpi/net/ipv4/gre_demux.c
+--- linux-3.12.18/net/ipv4/gre_demux.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv4/gre_demux.c 2014-04-24 16:04:41.667142117 +0200
+@@ -211,14 +211,6 @@
+ int i;
+ bool csum_err = false;
+
+-#ifdef CONFIG_NET_IPGRE_BROADCAST
+- if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
+- /* Looped back packet, drop it! */
+- if (rt_is_output_route(skb_rtable(skb)))
+- goto drop;
+- }
+-#endif
+-
+ if (parse_gre_header(skb, &tpi, &csum_err) < 0)
+ goto drop;
+
+diff -Nur linux-3.12.18/net/ipv4/inet_fragment.c linux-rpi/net/ipv4/inet_fragment.c
+--- linux-3.12.18/net/ipv4/inet_fragment.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv4/inet_fragment.c 2014-04-24 16:04:41.667142117 +0200
+@@ -211,7 +211,7 @@
+ }
+
+ work = frag_mem_limit(nf) - nf->low_thresh;
+- while (work > 0 || force) {
++ while (work > 0) {
+ spin_lock(&nf->lru_lock);
+
+ if (list_empty(&nf->lru_list)) {
+@@ -281,10 +281,9 @@
+
+ atomic_inc(&qp->refcnt);
+ hlist_add_head(&qp->list, &hb->chain);
+- inet_frag_lru_add(nf, qp);
+ spin_unlock(&hb->chain_lock);
+ read_unlock(&f->lock);
+-
++ inet_frag_lru_add(nf, qp);
+ return qp;
+ }
+
+diff -Nur linux-3.12.18/net/ipv4/ipmr.c linux-rpi/net/ipv4/ipmr.c
+--- linux-3.12.18/net/ipv4/ipmr.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv4/ipmr.c 2014-04-24 16:04:41.671142156 +0200
+@@ -2253,14 +2253,13 @@
+ }
+
+ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
+- u32 portid, u32 seq, struct mfc_cache *c, int cmd,
+- int flags)
++ u32 portid, u32 seq, struct mfc_cache *c, int cmd)
+ {
+ struct nlmsghdr *nlh;
+ struct rtmsg *rtm;
+ int err;
+
+- nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
++ nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI);
+ if (nlh == NULL)
+ return -EMSGSIZE;
+
+@@ -2328,7 +2327,7 @@
+ if (skb == NULL)
+ goto errout;
+
+- err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
++ err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd);
+ if (err < 0)
+ goto errout;
+
+@@ -2367,8 +2366,7 @@
+ if (ipmr_fill_mroute(mrt, skb,
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+- mfc, RTM_NEWROUTE,
+- NLM_F_MULTI) < 0)
++ mfc, RTM_NEWROUTE) < 0)
+ goto done;
+ next_entry:
+ e++;
+@@ -2382,8 +2380,7 @@
+ if (ipmr_fill_mroute(mrt, skb,
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+- mfc, RTM_NEWROUTE,
+- NLM_F_MULTI) < 0) {
++ mfc, RTM_NEWROUTE) < 0) {
+ spin_unlock_bh(&mfc_unres_lock);
+ goto done;
+ }
+diff -Nur linux-3.12.18/net/ipv4/ip_tunnel.c linux-rpi/net/ipv4/ip_tunnel.c
+--- linux-3.12.18/net/ipv4/ip_tunnel.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv4/ip_tunnel.c 2014-04-24 16:04:41.667142117 +0200
+@@ -411,6 +411,9 @@
+
+ #ifdef CONFIG_NET_IPGRE_BROADCAST
+ if (ipv4_is_multicast(iph->daddr)) {
++ /* Looped back packet, drop it! */
++ if (rt_is_output_route(skb_rtable(skb)))
++ goto drop;
+ tunnel->dev->stats.multicast++;
+ skb->pkt_type = PACKET_BROADCAST;
+ }
+diff -Nur linux-3.12.18/net/ipv4/ip_tunnel_core.c linux-rpi/net/ipv4/ip_tunnel_core.c
+--- linux-3.12.18/net/ipv4/ip_tunnel_core.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv4/ip_tunnel_core.c 2014-04-24 16:04:41.671142156 +0200
+@@ -109,7 +109,6 @@
+ secpath_reset(skb);
+ if (!skb->l4_rxhash)
+ skb->rxhash = 0;
+- skb_dst_drop(skb);
+ skb->vlan_tci = 0;
+ skb_set_queue_mapping(skb, 0);
+ skb->pkt_type = PACKET_HOST;
+diff -Nur linux-3.12.18/net/ipv4/tcp_output.c linux-rpi/net/ipv4/tcp_output.c
+--- linux-3.12.18/net/ipv4/tcp_output.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv4/tcp_output.c 2014-04-24 16:04:41.683142272 +0200
+@@ -765,17 +765,6 @@
+ if (flags & (1UL << TCP_TSQ_DEFERRED))
+ tcp_tsq_handler(sk);
+
+- /* Here begins the tricky part :
+- * We are called from release_sock() with :
+- * 1) BH disabled
+- * 2) sk_lock.slock spinlock held
+- * 3) socket owned by us (sk->sk_lock.owned == 1)
+- *
+- * But following code is meant to be called from BH handlers,
+- * so we should keep BH disabled, but early release socket ownership
+- */
+- sock_release_ownership(sk);
+-
+ if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) {
+ tcp_write_timer_handler(sk);
+ __sock_put(sk);
+diff -Nur linux-3.12.18/net/ipv6/addrconf.c linux-rpi/net/ipv6/addrconf.c
+--- linux-3.12.18/net/ipv6/addrconf.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv6/addrconf.c 2014-04-24 16:04:41.687142311 +0200
+@@ -1079,11 +1079,8 @@
+ * Lifetime is greater than REGEN_ADVANCE time units. In particular,
+ * an implementation must not create a temporary address with a zero
+ * Preferred Lifetime.
+- * Use age calculation as in addrconf_verify to avoid unnecessary
+- * temporary addresses being generated.
+ */
+- age = (now - tmp_tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
+- if (tmp_prefered_lft <= regen_advance + age) {
++ if (tmp_prefered_lft <= regen_advance) {
+ in6_ifa_put(ifp);
+ in6_dev_put(idev);
+ ret = -1;
+diff -Nur linux-3.12.18/net/ipv6/exthdrs_offload.c linux-rpi/net/ipv6/exthdrs_offload.c
+--- linux-3.12.18/net/ipv6/exthdrs_offload.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv6/exthdrs_offload.c 2014-04-24 16:04:41.687142311 +0200
+@@ -25,11 +25,11 @@
+ int ret;
+
+ ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING);
+- if (ret)
++ if (!ret)
+ goto out;
+
+ ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS);
+- if (ret)
++ if (!ret)
+ goto out_rt;
+
+ out:
+diff -Nur linux-3.12.18/net/ipv6/icmp.c linux-rpi/net/ipv6/icmp.c
+--- linux-3.12.18/net/ipv6/icmp.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv6/icmp.c 2014-04-24 16:04:41.687142311 +0200
+@@ -516,7 +516,7 @@
+ np->tclass, NULL, &fl6, (struct rt6_info *)dst,
+ MSG_DONTWAIT, np->dontfrag);
+ if (err) {
+- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS);
++ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
+ ip6_flush_pending_frames(sk);
+ } else {
+ err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
+diff -Nur linux-3.12.18/net/ipv6/ip6mr.c linux-rpi/net/ipv6/ip6mr.c
+--- linux-3.12.18/net/ipv6/ip6mr.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv6/ip6mr.c 2014-04-24 16:04:41.691142349 +0200
+@@ -2349,14 +2349,13 @@
+ }
+
+ static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
+- u32 portid, u32 seq, struct mfc6_cache *c, int cmd,
+- int flags)
++ u32 portid, u32 seq, struct mfc6_cache *c, int cmd)
+ {
+ struct nlmsghdr *nlh;
+ struct rtmsg *rtm;
+ int err;
+
+- nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), flags);
++ nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI);
+ if (nlh == NULL)
+ return -EMSGSIZE;
+
+@@ -2424,7 +2423,7 @@
+ if (skb == NULL)
+ goto errout;
+
+- err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd, 0);
++ err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd);
+ if (err < 0)
+ goto errout;
+
+@@ -2463,8 +2462,7 @@
+ if (ip6mr_fill_mroute(mrt, skb,
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+- mfc, RTM_NEWROUTE,
+- NLM_F_MULTI) < 0)
++ mfc, RTM_NEWROUTE) < 0)
+ goto done;
+ next_entry:
+ e++;
+@@ -2478,8 +2476,7 @@
+ if (ip6mr_fill_mroute(mrt, skb,
+ NETLINK_CB(cb->skb).portid,
+ cb->nlh->nlmsg_seq,
+- mfc, RTM_NEWROUTE,
+- NLM_F_MULTI) < 0) {
++ mfc, RTM_NEWROUTE) < 0) {
+ spin_unlock_bh(&mfc_unres_lock);
+ goto done;
+ }
+diff -Nur linux-3.12.18/net/ipv6/ip6_output.c linux-rpi/net/ipv6/ip6_output.c
+--- linux-3.12.18/net/ipv6/ip6_output.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv6/ip6_output.c 2014-04-24 16:04:41.691142349 +0200
+@@ -1088,19 +1088,21 @@
+ unsigned int fragheaderlen,
+ struct sk_buff *skb,
+ struct rt6_info *rt,
+- unsigned int orig_mtu)
++ bool pmtuprobe)
+ {
+ if (!(rt->dst.flags & DST_XFRM_TUNNEL)) {
+ if (skb == NULL) {
+ /* first fragment, reserve header_len */
+- *mtu = orig_mtu - rt->dst.header_len;
++ *mtu = *mtu - rt->dst.header_len;
+
+ } else {
+ /*
+ * this fragment is not first, the headers
+ * space is regarded as data space.
+ */
+- *mtu = orig_mtu;
++ *mtu = min(*mtu, pmtuprobe ?
++ rt->dst.dev->mtu :
++ dst_mtu(rt->dst.path));
+ }
+ *maxfraglen = ((*mtu - fragheaderlen) & ~7)
+ + fragheaderlen - sizeof(struct frag_hdr);
+@@ -1117,7 +1119,7 @@
+ struct ipv6_pinfo *np = inet6_sk(sk);
+ struct inet_cork *cork;
+ struct sk_buff *skb, *skb_prev = NULL;
+- unsigned int maxfraglen, fragheaderlen, mtu, orig_mtu;
++ unsigned int maxfraglen, fragheaderlen, mtu;
+ int exthdrlen;
+ int dst_exthdrlen;
+ int hh_len;
+@@ -1199,7 +1201,6 @@
+ dst_exthdrlen = 0;
+ mtu = cork->fragsize;
+ }
+- orig_mtu = mtu;
+
+ hh_len = LL_RESERVED_SPACE(rt->dst.dev);
+
+@@ -1279,7 +1280,8 @@
+ if (skb == NULL || skb_prev == NULL)
+ ip6_append_data_mtu(&mtu, &maxfraglen,
+ fragheaderlen, skb, rt,
+- orig_mtu);
++ np->pmtudisc ==
++ IPV6_PMTUDISC_PROBE);
+
+ skb_prev = skb;
+
+@@ -1535,8 +1537,8 @@
+ if (proto == IPPROTO_ICMPV6) {
+ struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
+
+- ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type);
+- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
++ ICMP6MSGOUT_INC_STATS_BH(net, idev, icmp6_hdr(skb)->icmp6_type);
++ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
+ }
+
+ err = ip6_local_out(skb);
+diff -Nur linux-3.12.18/net/ipv6/mcast.c linux-rpi/net/ipv6/mcast.c
+--- linux-3.12.18/net/ipv6/mcast.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv6/mcast.c 2014-04-24 16:04:41.691142349 +0200
+@@ -1620,12 +1620,11 @@
+ dst_output);
+ out:
+ if (!err) {
+- ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT);
+- ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
+- IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
+- } else {
+- IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
+- }
++ ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT);
++ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
++ IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
++ } else
++ IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
+
+ rcu_read_unlock();
+ return;
+diff -Nur linux-3.12.18/net/ipv6/ping.c linux-rpi/net/ipv6/ping.c
+--- linux-3.12.18/net/ipv6/ping.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv6/ping.c 2014-04-24 16:04:41.695142388 +0200
+@@ -182,8 +182,8 @@
+ MSG_DONTWAIT, np->dontfrag);
+
+ if (err) {
+- ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev,
+- ICMP6_MIB_OUTERRORS);
++ ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev,
++ ICMP6_MIB_OUTERRORS);
+ ip6_flush_pending_frames(sk);
+ } else {
+ err = icmpv6_push_pending_frames(sk, &fl6,
+diff -Nur linux-3.12.18/net/ipv6/route.c linux-rpi/net/ipv6/route.c
+--- linux-3.12.18/net/ipv6/route.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/ipv6/route.c 2014-04-24 16:04:41.699142427 +0200
+@@ -1500,7 +1500,7 @@
+ if (!table)
+ goto out;
+
+- rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table);
++ rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT, table);
+
+ if (!rt) {
+ err = -ENOMEM;
+diff -Nur linux-3.12.18/net/rds/iw.c linux-rpi/net/rds/iw.c
+--- linux-3.12.18/net/rds/iw.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/rds/iw.c 2014-04-24 16:04:42.255147800 +0200
+@@ -239,8 +239,7 @@
+ ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
+ /* due to this, we will claim to support IB devices unless we
+ check node_type. */
+- if (ret || !cm_id->device ||
+- cm_id->device->node_type != RDMA_NODE_RNIC)
++ if (ret || cm_id->device->node_type != RDMA_NODE_RNIC)
+ ret = -EADDRNOTAVAIL;
+
+ rdsdebug("addr %pI4 ret %d node type %d\n",
+diff -Nur linux-3.12.18/net/sched/sch_fq.c linux-rpi/net/sched/sch_fq.c
+--- linux-3.12.18/net/sched/sch_fq.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/sched/sch_fq.c 2014-04-24 16:04:42.255147800 +0200
+@@ -577,11 +577,9 @@
+ q->stat_gc_flows += fcnt;
+ }
+
+-static int fq_resize(struct Qdisc *sch, u32 log)
++static int fq_resize(struct fq_sched_data *q, u32 log)
+ {
+- struct fq_sched_data *q = qdisc_priv(sch);
+ struct rb_root *array;
+- void *old_fq_root;
+ u32 idx;
+
+ if (q->fq_root && log == q->fq_trees_log)
+@@ -594,19 +592,13 @@
+ for (idx = 0; idx < (1U << log); idx++)
+ array[idx] = RB_ROOT;
+
+- sch_tree_lock(sch);
+-
+- old_fq_root = q->fq_root;
+- if (old_fq_root)
+- fq_rehash(q, old_fq_root, q->fq_trees_log, array, log);
+-
++ if (q->fq_root) {
++ fq_rehash(q, q->fq_root, q->fq_trees_log, array, log);
++ kfree(q->fq_root);
++ }
+ q->fq_root = array;
+ q->fq_trees_log = log;
+
+- sch_tree_unlock(sch);
+-
+- kfree(old_fq_root);
+-
+ return 0;
+ }
+
+@@ -682,11 +674,9 @@
+ q->flow_refill_delay = usecs_to_jiffies(usecs_delay);
+ }
+
+- if (!err) {
+- sch_tree_unlock(sch);
+- err = fq_resize(sch, fq_log);
+- sch_tree_lock(sch);
+- }
++ if (!err)
++ err = fq_resize(q, fq_log);
++
+ while (sch->q.qlen > sch->limit) {
+ struct sk_buff *skb = fq_dequeue(sch);
+
+@@ -732,7 +722,7 @@
+ if (opt)
+ err = fq_change(sch, opt);
+ else
+- err = fq_resize(sch, q->fq_trees_log);
++ err = fq_resize(q, q->fq_trees_log);
+
+ return err;
+ }
+diff -Nur linux-3.12.18/net/sctp/sm_make_chunk.c linux-rpi/net/sctp/sm_make_chunk.c
+--- linux-3.12.18/net/sctp/sm_make_chunk.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/sctp/sm_make_chunk.c 2014-04-24 16:04:42.263147878 +0200
+@@ -1433,8 +1433,8 @@
+ BUG_ON(!list_empty(&chunk->list));
+ list_del_init(&chunk->transmitted_list);
+
+- consume_skb(chunk->skb);
+- consume_skb(chunk->auth_chunk);
++ /* Free the chunk skb data and the SCTP_chunk stub itself. */
++ dev_kfree_skb(chunk->skb);
+
+ SCTP_DBG_OBJCNT_DEC(chunk);
+ kmem_cache_free(sctp_chunk_cachep, chunk);
+diff -Nur linux-3.12.18/net/sctp/sm_statefuns.c linux-rpi/net/sctp/sm_statefuns.c
+--- linux-3.12.18/net/sctp/sm_statefuns.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/sctp/sm_statefuns.c 2014-04-24 16:04:42.263147878 +0200
+@@ -761,6 +761,7 @@
+
+ /* Make sure that we and the peer are AUTH capable */
+ if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) {
++ kfree_skb(chunk->auth_chunk);
+ sctp_association_free(new_asoc);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+ }
+@@ -775,6 +776,10 @@
+ auth.transport = chunk->transport;
+
+ ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth);
++
++ /* We can now safely free the auth_chunk clone */
++ kfree_skb(chunk->auth_chunk);
++
+ if (ret != SCTP_IERROR_NO_ERROR) {
+ sctp_association_free(new_asoc);
+ return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+diff -Nur linux-3.12.18/net/socket.c linux-rpi/net/socket.c
+--- linux-3.12.18/net/socket.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/socket.c 2014-04-24 16:04:42.275147994 +0200
+@@ -1972,10 +1972,6 @@
+ {
+ if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
+ return -EFAULT;
+-
+- if (kmsg->msg_namelen < 0)
+- return -EINVAL;
+-
+ if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
+ kmsg->msg_namelen = sizeof(struct sockaddr_storage);
+ return 0;
+diff -Nur linux-3.12.18/net/sunrpc/backchannel_rqst.c linux-rpi/net/sunrpc/backchannel_rqst.c
+--- linux-3.12.18/net/sunrpc/backchannel_rqst.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/sunrpc/backchannel_rqst.c 2014-04-24 15:35:05.273578028 +0200
+@@ -64,6 +64,7 @@
+ free_page((unsigned long)xbufp->head[0].iov_base);
+ xbufp = &req->rq_snd_buf;
+ free_page((unsigned long)xbufp->head[0].iov_base);
++ list_del(&req->rq_bc_pa_list);
+ kfree(req);
+ }
+
+@@ -167,10 +168,8 @@
+ /*
+ * Memory allocation failed, free the temporary list
+ */
+- list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) {
+- list_del(&req->rq_bc_pa_list);
++ list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list)
+ xprt_free_allocation(req);
+- }
+
+ dprintk("RPC: setup backchannel transport failed\n");
+ return -ENOMEM;
+@@ -199,7 +198,6 @@
+ xprt_dec_alloc_count(xprt, max_reqs);
+ list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) {
+ dprintk("RPC: req=%p\n", req);
+- list_del(&req->rq_bc_pa_list);
+ xprt_free_allocation(req);
+ if (--max_reqs == 0)
+ break;
+diff -Nur linux-3.12.18/net/tipc/config.c linux-rpi/net/tipc/config.c
+--- linux-3.12.18/net/tipc/config.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/tipc/config.c 2014-04-24 16:04:42.275147994 +0200
+@@ -376,6 +376,7 @@
+ struct tipc_cfg_msg_hdr *req_hdr;
+ struct tipc_cfg_msg_hdr *rep_hdr;
+ struct sk_buff *rep_buf;
++ int ret;
+
+ /* Validate configuration message header (ignore invalid message) */
+ req_hdr = (struct tipc_cfg_msg_hdr *)buf;
+@@ -397,8 +398,12 @@
+ memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr));
+ rep_hdr->tcm_len = htonl(rep_buf->len);
+ rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST);
+- tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data,
+- rep_buf->len);
++
++ ret = tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data,
++ rep_buf->len);
++ if (ret < 0)
++ pr_err("Sending cfg reply message failed, no memory\n");
++
+ kfree_skb(rep_buf);
+ }
+ }
+diff -Nur linux-3.12.18/net/tipc/handler.c linux-rpi/net/tipc/handler.c
+--- linux-3.12.18/net/tipc/handler.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/tipc/handler.c 2014-04-24 15:35:05.285578162 +0200
+@@ -57,6 +57,7 @@
+ struct queue_item *item;
+
+ if (!handler_enabled) {
++ pr_err("Signal request ignored by handler\n");
+ return -ENOPROTOOPT;
+ }
+
+diff -Nur linux-3.12.18/net/tipc/name_table.c linux-rpi/net/tipc/name_table.c
+--- linux-3.12.18/net/tipc/name_table.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/tipc/name_table.c 2014-04-24 16:04:42.275147994 +0200
+@@ -942,51 +942,20 @@
+ return 0;
+ }
+
+-/**
+- * tipc_purge_publications - remove all publications for a given type
+- *
+- * tipc_nametbl_lock must be held when calling this function
+- */
+-static void tipc_purge_publications(struct name_seq *seq)
+-{
+- struct publication *publ, *safe;
+- struct sub_seq *sseq;
+- struct name_info *info;
+-
+- if (!seq->sseqs) {
+- nameseq_delete_empty(seq);
+- return;
+- }
+- sseq = seq->sseqs;
+- info = sseq->info;
+- list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) {
+- tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node,
+- publ->ref, publ->key);
+- }
+-}
+-
+ void tipc_nametbl_stop(void)
+ {
+ u32 i;
+- struct name_seq *seq;
+- struct hlist_head *seq_head;
+- struct hlist_node *safe;
+
+ if (!table.types)
+ return;
+
+- /* Verify name table is empty and purge any lingering
+- * publications, then release the name table
+- */
++ /* Verify name table is empty, then release it */
+ write_lock_bh(&tipc_nametbl_lock);
+ for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
+ if (hlist_empty(&table.types[i]))
+ continue;
+- seq_head = &table.types[i];
+- hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) {
+- tipc_purge_publications(seq);
+- }
+- continue;
++ pr_err("nametbl_stop(): orphaned hash chain detected\n");
++ break;
+ }
+ kfree(table.types);
+ table.types = NULL;
+diff -Nur linux-3.12.18/net/tipc/server.c linux-rpi/net/tipc/server.c
+--- linux-3.12.18/net/tipc/server.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/tipc/server.c 2014-04-24 16:04:42.279148031 +0200
+@@ -87,6 +87,7 @@
+ static void tipc_conn_kref_release(struct kref *kref)
+ {
+ struct tipc_conn *con = container_of(kref, struct tipc_conn, kref);
++ struct tipc_server *s = con->server;
+
+ if (con->sock) {
+ tipc_sock_release_local(con->sock);
+@@ -94,6 +95,10 @@
+ }
+
+ tipc_clean_outqueues(con);
++
++ if (con->conid)
++ s->tipc_conn_shutdown(con->conid, con->usr_data);
++
+ kfree(con);
+ }
+
+@@ -176,9 +181,6 @@
+ struct tipc_server *s = con->server;
+
+ if (test_and_clear_bit(CF_CONNECTED, &con->flags)) {
+- if (con->conid)
+- s->tipc_conn_shutdown(con->conid, con->usr_data);
+-
+ spin_lock_bh(&s->idr_lock);
+ idr_remove(&s->conn_idr, con->conid);
+ s->idr_in_use--;
+@@ -427,12 +429,10 @@
+ list_add_tail(&e->list, &con->outqueue);
+ spin_unlock_bh(&con->outqueue_lock);
+
+- if (test_bit(CF_CONNECTED, &con->flags)) {
++ if (test_bit(CF_CONNECTED, &con->flags))
+ if (!queue_work(s->send_wq, &con->swork))
+ conn_put(con);
+- } else {
+- conn_put(con);
+- }
++
+ return 0;
+ }
+
+diff -Nur linux-3.12.18/net/tipc/subscr.c linux-rpi/net/tipc/subscr.c
+--- linux-3.12.18/net/tipc/subscr.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/tipc/subscr.c 2014-04-24 16:04:42.279148031 +0200
+@@ -96,16 +96,20 @@
+ {
+ struct tipc_subscriber *subscriber = sub->subscriber;
+ struct kvec msg_sect;
++ int ret;
+
+ msg_sect.iov_base = (void *)&sub->evt;
+ msg_sect.iov_len = sizeof(struct tipc_event);
++
+ sub->evt.event = htohl(event, sub->swap);
+ sub->evt.found_lower = htohl(found_lower, sub->swap);
+ sub->evt.found_upper = htohl(found_upper, sub->swap);
+ sub->evt.port.ref = htohl(port_ref, sub->swap);
+ sub->evt.port.node = htohl(node, sub->swap);
+- tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL, msg_sect.iov_base,
+- msg_sect.iov_len);
++ ret = tipc_conn_sendmsg(&topsrv, subscriber->conid, NULL,
++ msg_sect.iov_base, msg_sect.iov_len);
++ if (ret < 0)
++ pr_err("Sending subscription event failed, no memory\n");
+ }
+
+ /**
+@@ -149,6 +153,14 @@
+ /* The spin lock per subscriber is used to protect its members */
+ spin_lock_bh(&subscriber->lock);
+
++ /* Validate if the connection related to the subscriber is
++ * closed (in case subscriber is terminating)
++ */
++ if (subscriber->conid == 0) {
++ spin_unlock_bh(&subscriber->lock);
++ return;
++ }
++
+ /* Validate timeout (in case subscription is being cancelled) */
+ if (sub->timeout == TIPC_WAIT_FOREVER) {
+ spin_unlock_bh(&subscriber->lock);
+@@ -203,6 +215,9 @@
+
+ spin_lock_bh(&subscriber->lock);
+
++ /* Invalidate subscriber reference */
++ subscriber->conid = 0;
++
+ /* Destroy any existing subscriptions for subscriber */
+ list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list,
+ subscription_list) {
+@@ -263,9 +278,9 @@
+ *
+ * Called with subscriber lock held.
+ */
+-static int subscr_subscribe(struct tipc_subscr *s,
+- struct tipc_subscriber *subscriber,
+- struct tipc_subscription **sub_p) {
++static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s,
++ struct tipc_subscriber *subscriber)
++{
+ struct tipc_subscription *sub;
+ int swap;
+
+@@ -276,21 +291,23 @@
+ if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) {
+ s->filter &= ~htohl(TIPC_SUB_CANCEL, swap);
+ subscr_cancel(s, subscriber);
+- return 0;
++ return NULL;
+ }
+
+ /* Refuse subscription if global limit exceeded */
+ if (atomic_read(&subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) {
+ pr_warn("Subscription rejected, limit reached (%u)\n",
+ TIPC_MAX_SUBSCRIPTIONS);
+- return -EINVAL;
++ subscr_terminate(subscriber);
++ return NULL;
+ }
+
+ /* Allocate subscription object */
+ sub = kmalloc(sizeof(*sub), GFP_ATOMIC);
+ if (!sub) {
+ pr_warn("Subscription rejected, no memory\n");
+- return -ENOMEM;
++ subscr_terminate(subscriber);
++ return NULL;
+ }
+
+ /* Initialize subscription object */
+@@ -304,7 +321,8 @@
+ (sub->seq.lower > sub->seq.upper)) {
+ pr_warn("Subscription rejected, illegal request\n");
+ kfree(sub);
+- return -EINVAL;
++ subscr_terminate(subscriber);
++ return NULL;
+ }
+ INIT_LIST_HEAD(&sub->nameseq_list);
+ list_add(&sub->subscription_list, &subscriber->subscription_list);
+@@ -317,8 +335,8 @@
+ (Handler)subscr_timeout, (unsigned long)sub);
+ k_start_timer(&sub->timer, sub->timeout);
+ }
+- *sub_p = sub;
+- return 0;
++
++ return sub;
+ }
+
+ /* Handle one termination request for the subscriber */
+@@ -332,14 +350,10 @@
+ void *usr_data, void *buf, size_t len)
+ {
+ struct tipc_subscriber *subscriber = usr_data;
+- struct tipc_subscription *sub = NULL;
++ struct tipc_subscription *sub;
+
+ spin_lock_bh(&subscriber->lock);
+- if (subscr_subscribe((struct tipc_subscr *)buf, subscriber, &sub) < 0) {
+- spin_unlock_bh(&subscriber->lock);
+- subscr_terminate(subscriber);
+- return;
+- }
++ sub = subscr_subscribe((struct tipc_subscr *)buf, subscriber);
+ if (sub)
+ tipc_nametbl_subscribe(sub);
+ spin_unlock_bh(&subscriber->lock);
+diff -Nur linux-3.12.18/net/unix/af_unix.c linux-rpi/net/unix/af_unix.c
+--- linux-3.12.18/net/unix/af_unix.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/net/unix/af_unix.c 2014-04-24 16:04:42.279148031 +0200
+@@ -1785,11 +1785,8 @@
+ goto out;
+
+ err = mutex_lock_interruptible(&u->readlock);
+- if (unlikely(err)) {
+- /* recvmsg() in non blocking mode is supposed to return -EAGAIN
+- * sk_rcvtimeo is not honored by mutex_lock_interruptible()
+- */
+- err = noblock ? -EAGAIN : -ERESTARTSYS;
++ if (err) {
++ err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
+ goto out;
+ }
+
+@@ -1914,7 +1911,6 @@
+ struct unix_sock *u = unix_sk(sk);
+ struct sockaddr_un *sunaddr = msg->msg_name;
+ int copied = 0;
+- int noblock = flags & MSG_DONTWAIT;
+ int check_creds = 0;
+ int target;
+ int err = 0;
+@@ -1930,7 +1926,7 @@
+ goto out;
+
+ target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
+- timeo = sock_rcvtimeo(sk, noblock);
++ timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
+
+ /* Lock the socket to prevent queue disordering
+ * while sleeps in memcpy_tomsg
+@@ -1942,11 +1938,8 @@
+ }
+
+ err = mutex_lock_interruptible(&u->readlock);
+- if (unlikely(err)) {
+- /* recvmsg() in non blocking mode is supposed to return -EAGAIN
+- * sk_rcvtimeo is not honored by mutex_lock_interruptible()
+- */
+- err = noblock ? -EAGAIN : -ERESTARTSYS;
++ if (err) {
++ err = sock_intr_errno(timeo);
+ goto out;
+ }
+
+diff -Nur linux-3.12.18/security/selinux/hooks.c linux-rpi/security/selinux/hooks.c
+--- linux-3.12.18/security/selinux/hooks.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/security/selinux/hooks.c 2014-04-24 16:04:42.731152400 +0200
+@@ -1386,33 +1386,15 @@
+ isec->sid = sbsec->sid;
+
+ if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
+- /* We must have a dentry to determine the label on
+- * procfs inodes */
+- if (opt_dentry)
+- /* Called from d_instantiate or
+- * d_splice_alias. */
+- dentry = dget(opt_dentry);
+- else
+- /* Called from selinux_complete_init, try to
+- * find a dentry. */
+- dentry = d_find_alias(inode);
+- /*
+- * This can be hit on boot when a file is accessed
+- * before the policy is loaded. When we load policy we
+- * may find inodes that have no dentry on the
+- * sbsec->isec_head list. No reason to complain as
+- * these will get fixed up the next time we go through
+- * inode_doinit() with a dentry, before these inodes
+- * could be used again by userspace.
+- */
+- if (!dentry)
+- goto out_unlock;
+- isec->sclass = inode_mode_to_security_class(inode->i_mode);
+- rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
+- dput(dentry);
+- if (rc)
+- goto out_unlock;
+- isec->sid = sid;
++ if (opt_dentry) {
++ isec->sclass = inode_mode_to_security_class(inode->i_mode);
++ rc = selinux_proc_get_sid(opt_dentry,
++ isec->sclass,
++ &sid);
++ if (rc)
++ goto out_unlock;
++ isec->sid = sid;
++ }
+ }
+ break;
+ }
+diff -Nur linux-3.12.18/sound/arm/bcm2835.c linux-rpi/sound/arm/bcm2835.c
+--- linux-3.12.18/sound/arm/bcm2835.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/arm/bcm2835.c 2014-04-24 16:04:42.735152438 +0200
+@@ -0,0 +1,420 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
+*
@@ -97188,7 +101615,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835
+ goto out;
+
+ snd_card_set_dev(g_card, &pdev->dev);
-+ strcpy(g_card->driver, "BRCM bcm2835 ALSA Driver");
++ strcpy(g_card->driver, "bcm2835");
+ strcpy(g_card->shortname, "bcm2835 ALSA");
+ sprintf(g_card->longname, "%s", g_card->shortname);
+
@@ -97205,6 +101632,12 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835
+ goto out_bcm2835_new_pcm;
+ }
+
++ err = snd_bcm2835_new_spdif_pcm(chip);
++ if (err < 0) {
++ dev_err(&pdev->dev, "Failed to create new BCM2835 spdif pcm device\n");
++ goto out_bcm2835_new_spdif;
++ }
++
+ err = snd_bcm2835_new_ctl(chip);
+ if (err < 0) {
+ dev_err(&pdev->dev, "Failed to create new BCM2835 ctl\n");
@@ -97240,6 +101673,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835
+
+out_card_register:
+out_bcm2835_new_ctl:
++out_bcm2835_new_spdif:
+out_bcm2835_new_pcm:
+out_bcm2835_create:
+ BUG_ON(!g_card);
@@ -97495,10 +101929,10 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.c linux-raspberry-pi/sound/arm/bcm2835
+MODULE_DESCRIPTION("Alsa driver for BCM2835 chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bcm2835_alsa");
-diff -Nur linux-3.12.13/sound/arm/bcm2835-ctl.c linux-raspberry-pi/sound/arm/bcm2835-ctl.c
---- linux-3.12.13/sound/arm/bcm2835-ctl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/arm/bcm2835-ctl.c 2014-03-11 17:51:48.000000000 +0100
-@@ -0,0 +1,200 @@
+diff -Nur linux-3.12.18/sound/arm/bcm2835-ctl.c linux-rpi/sound/arm/bcm2835-ctl.c
+--- linux-3.12.18/sound/arm/bcm2835-ctl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/arm/bcm2835-ctl.c 2014-04-24 16:04:42.735152438 +0200
+@@ -0,0 +1,323 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
+*
@@ -97531,6 +101965,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-ctl.c linux-raspberry-pi/sound/arm/bcm
+#include <sound/rawmidi.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
++#include <sound/asoundef.h>
+
+#include "bcm2835.h"
+
@@ -97684,6 +102119,122 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-ctl.c linux-raspberry-pi/sound/arm/bcm
+ },
+};
+
++static int snd_bcm2835_spdif_default_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
++ uinfo->count = 1;
++ return 0;
++}
++
++static int snd_bcm2835_spdif_default_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
++ int i;
++
++ for (i = 0; i < 4; i++)
++ ucontrol->value.iec958.status[i] =
++ (chip->spdif_status >> (i * 8)) && 0xff;
++
++ return 0;
++}
++
++static int snd_bcm2835_spdif_default_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
++ unsigned int val = 0;
++ int i, change;
++
++ for (i = 0; i < 4; i++)
++ val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
++
++ change = val != chip->spdif_status;
++ chip->spdif_status = val;
++
++ return change;
++}
++
++static int snd_bcm2835_spdif_mask_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
++ uinfo->count = 1;
++ return 0;
++}
++
++static int snd_bcm2835_spdif_mask_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ /* bcm2835 supports only consumer mode and sets all other format flags
++ * automatically. So the only thing left is signalling non-audio
++ * content */
++ ucontrol->value.iec958.status[0] = IEC958_AES0_NONAUDIO;
++ return 0;
++}
++
++static int snd_bcm2835_spdif_stream_info(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_info *uinfo)
++{
++ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
++ uinfo->count = 1;
++ return 0;
++}
++
++static int snd_bcm2835_spdif_stream_get(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
++ int i;
++
++ for (i = 0; i < 4; i++)
++ ucontrol->value.iec958.status[i] =
++ (chip->spdif_status >> (i * 8)) & 0xff;
++ return 0;
++}
++
++static int snd_bcm2835_spdif_stream_put(struct snd_kcontrol *kcontrol,
++ struct snd_ctl_elem_value *ucontrol)
++{
++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol);
++ unsigned int val = 0;
++ int i, change;
++
++ for (i = 0; i < 4; i++)
++ val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
++ change = val != chip->spdif_status;
++ chip->spdif_status = val;
++
++ return change;
++}
++
++static struct snd_kcontrol_new snd_bcm2835_spdif[] = {
++ {
++ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
++ .info = snd_bcm2835_spdif_default_info,
++ .get = snd_bcm2835_spdif_default_get,
++ .put = snd_bcm2835_spdif_default_put
++ },
++ {
++ .access = SNDRV_CTL_ELEM_ACCESS_READ,
++ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
++ .info = snd_bcm2835_spdif_mask_info,
++ .get = snd_bcm2835_spdif_mask_get,
++ },
++ {
++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++ SNDRV_CTL_ELEM_ACCESS_INACTIVE,
++ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
++ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
++ .info = snd_bcm2835_spdif_stream_info,
++ .get = snd_bcm2835_spdif_stream_get,
++ .put = snd_bcm2835_spdif_stream_put,
++ },
++};
++
+int snd_bcm2835_new_ctl(bcm2835_chip_t * chip)
+{
+ int err;
@@ -97697,12 +102248,18 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-ctl.c linux-raspberry-pi/sound/arm/bcm
+ if (err < 0)
+ return err;
+ }
++ for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_spdif); idx++) {
++ err = snd_ctl_add(chip->card,
++ snd_ctl_new1(&snd_bcm2835_spdif[idx], chip));
++ if (err < 0)
++ return err;
++ }
+ return 0;
+}
-diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835.h
---- linux-3.12.13/sound/arm/bcm2835.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/arm/bcm2835.h 2014-03-11 17:51:48.000000000 +0100
-@@ -0,0 +1,157 @@
+diff -Nur linux-3.12.18/sound/arm/bcm2835.h linux-rpi/sound/arm/bcm2835.h
+--- linux-3.12.18/sound/arm/bcm2835.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/arm/bcm2835.h 2014-04-24 16:04:42.735152438 +0200
+@@ -0,0 +1,166 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
+*
@@ -97802,6 +102359,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835
+typedef struct bcm2835_chip {
+ struct snd_card *card;
+ struct snd_pcm *pcm;
++ struct snd_pcm *pcm_spdif;
+ /* Bitmat for valid reg_base and irq numbers */
+ uint32_t avail_substreams;
+ struct platform_device *pdev[MAX_SUBSTREAMS];
@@ -97811,6 +102369,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835
+ int old_volume; /* stores the volume value whist muted */
+ int dest;
+ int mute;
++
++ unsigned int opened;
++ unsigned int spdif_status;
+} bcm2835_chip_t;
+
+typedef struct bcm2835_alsa_stream {
@@ -97828,6 +102389,10 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835
+ int running;
+ int draining;
+
++ int channels;
++ int params_rate;
++ int pcm_format_width;
++
+ unsigned int pos;
+ unsigned int buffer_size;
+ unsigned int period_size;
@@ -97843,6 +102408,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835
+
+int snd_bcm2835_new_ctl(bcm2835_chip_t * chip);
+int snd_bcm2835_new_pcm(bcm2835_chip_t * chip);
++int snd_bcm2835_new_spdif_pcm(bcm2835_chip_t * chip);
+
+int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream);
+int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream);
@@ -97860,10 +102426,10 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835.h linux-raspberry-pi/sound/arm/bcm2835
+void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream);
+
+#endif /* __SOUND_ARM_BCM2835_H */
-diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm2835-pcm.c
---- linux-3.12.13/sound/arm/bcm2835-pcm.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/arm/bcm2835-pcm.c 2014-03-11 17:51:48.000000000 +0100
-@@ -0,0 +1,426 @@
+diff -Nur linux-3.12.18/sound/arm/bcm2835-pcm.c linux-rpi/sound/arm/bcm2835-pcm.c
+--- linux-3.12.18/sound/arm/bcm2835-pcm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/arm/bcm2835-pcm.c 2014-04-24 16:04:42.735152438 +0200
+@@ -0,0 +1,518 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
+*
@@ -97881,6 +102447,8 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
++#include <sound/asoundef.h>
++
+#include "bcm2835.h"
+
+/* hardware definition */
@@ -97900,6 +102468,23 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+ .periods_max = 128,
+};
+
++static struct snd_pcm_hardware snd_bcm2835_playback_spdif_hw = {
++ .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
++ SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID),
++ .formats = SNDRV_PCM_FMTBIT_S16_LE,
++ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_44100 |
++ SNDRV_PCM_RATE_48000,
++ .rate_min = 44100,
++ .rate_max = 48000,
++ .channels_min = 2,
++ .channels_max = 2,
++ .buffer_bytes_max = 128 * 1024,
++ .period_bytes_min = 1 * 1024,
++ .period_bytes_max = 128 * 1024,
++ .periods_min = 1,
++ .periods_max = 128,
++};
++
+static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime)
+{
+ audio_info("Freeing up alsa stream here ..\n");
@@ -97955,7 +102540,8 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+}
+
+/* open callback */
-+static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream)
++static int snd_bcm2835_playback_open_generic(
++ struct snd_pcm_substream *substream, int spdif)
+{
+ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
@@ -97968,6 +102554,11 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+ audio_info("Alsa open (%d)\n", substream->number);
+ idx = substream->number;
+
++ if (spdif && chip->opened != 0)
++ return -EBUSY;
++ else if (!spdif && (chip->opened & (1 << idx)))
++ return -EBUSY;
++
+ if (idx > MAX_SUBSTREAMS) {
+ audio_error
+ ("substream(%d) device doesn't exist max(%d) substreams allowed\n",
@@ -97993,7 +102584,6 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+ alsa_stream->chip = chip;
+ alsa_stream->substream = substream;
+ alsa_stream->idx = idx;
-+ chip->alsa_stream[idx] = alsa_stream;
+
+ sema_init(&alsa_stream->buffers_update_sem, 0);
+ sema_init(&alsa_stream->control_sem, 0);
@@ -98005,7 +102595,13 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+
+ runtime->private_data = alsa_stream;
+ runtime->private_free = snd_bcm2835_playback_free;
-+ runtime->hw = snd_bcm2835_playback_hw;
++ if (spdif) {
++ runtime->hw = snd_bcm2835_playback_spdif_hw;
++ } else {
++ /* clear spdif status, as we are not in spdif mode */
++ chip->spdif_status = 0;
++ runtime->hw = snd_bcm2835_playback_hw;
++ }
+ /* minimum 16 bytes alignment (for vchiq bulk transfers) */
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+ 16);
@@ -98015,7 +102611,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+ kfree(alsa_stream);
+ return err;
+ }
++ chip->alsa_stream[idx] = alsa_stream;
+
++ chip->opened |= (1 << idx);
+ alsa_stream->open = 1;
+ alsa_stream->draining = 1;
+
@@ -98025,6 +102623,16 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+ return err;
+}
+
++static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream)
++{
++ return snd_bcm2835_playback_open_generic(substream, 0);
++}
++
++static int snd_bcm2835_playback_spdif_open(struct snd_pcm_substream *substream)
++{
++ return snd_bcm2835_playback_open_generic(substream, 1);
++}
++
+/* close callback */
+static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream)
+{
@@ -98032,6 +102640,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
++ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream);
+
+ audio_info(" .. IN\n");
+ audio_info("Alsa close\n");
@@ -98062,6 +102671,8 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+ * runtime->private_free callback we registered in *_open above
+ */
+
++ chip->opened &= ~(1 << substream->number);
++
+ audio_info(" .. OUT\n");
+
+ return 0;
@@ -98071,10 +102682,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
-+ int err;
+ struct snd_pcm_runtime *runtime = substream->runtime;
-+ bcm2835_alsa_stream_t *alsa_stream =
-+ (bcm2835_alsa_stream_t *) runtime->private_data;
++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
++ int err;
+
+ audio_info(" .. IN\n");
+
@@ -98085,19 +102695,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+ return err;
+ }
+
-+ err = bcm2835_audio_set_params(alsa_stream, params_channels(params),
-+ params_rate(params),
-+ snd_pcm_format_width(params_format
-+ (params)));
-+ if (err < 0) {
-+ audio_error(" error setting hw params\n");
-+ }
-+
-+ bcm2835_audio_setup(alsa_stream);
-+
-+ /* in preparation of the stream, set the controls (volume level) of the stream */
-+ bcm2835_audio_set_ctls(alsa_stream->chip);
-+
++ alsa_stream->channels = params_channels(params);
++ alsa_stream->params_rate = params_rate(params);
++ alsa_stream->pcm_format_width = snd_pcm_format_width(params_format (params));
+ audio_info(" .. OUT\n");
+
+ return err;
@@ -98113,11 +102713,35 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+/* prepare callback */
+static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream)
+{
++ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data;
++ int channels;
++ int err;
+
+ audio_info(" .. IN\n");
+
++ /* notify the vchiq that it should enter spdif passthrough mode by
++ * setting channels=0 (see
++ * https://github.com/raspberrypi/linux/issues/528) */
++ if (chip->spdif_status & IEC958_AES0_NONAUDIO)
++ channels = 0;
++ else
++ channels = alsa_stream->channels;
++
++ err = bcm2835_audio_set_params(alsa_stream, channels,
++ alsa_stream->params_rate,
++ alsa_stream->pcm_format_width);
++ if (err < 0) {
++ audio_error(" error setting hw params\n");
++ }
++
++ bcm2835_audio_setup(alsa_stream);
++
++ /* in preparation of the stream, set the controls (volume level) of the stream */
++ bcm2835_audio_set_ctls(alsa_stream->chip);
++
++
+ memset(&alsa_stream->pcm_indirect, 0, sizeof(alsa_stream->pcm_indirect));
+
+ alsa_stream->pcm_indirect.hw_buffer_size =
@@ -98258,6 +102882,18 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+ .ack = snd_bcm2835_pcm_ack,
+};
+
++static struct snd_pcm_ops snd_bcm2835_playback_spdif_ops = {
++ .open = snd_bcm2835_playback_spdif_open,
++ .close = snd_bcm2835_playback_close,
++ .ioctl = snd_bcm2835_pcm_lib_ioctl,
++ .hw_params = snd_bcm2835_pcm_hw_params,
++ .hw_free = snd_bcm2835_pcm_hw_free,
++ .prepare = snd_bcm2835_pcm_prepare,
++ .trigger = snd_bcm2835_pcm_trigger,
++ .pointer = snd_bcm2835_pcm_pointer,
++ .ack = snd_bcm2835_pcm_ack,
++};
++
+/* create a pcm device */
+int snd_bcm2835_new_pcm(bcm2835_chip_t * chip)
+{
@@ -98290,9 +102926,31 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-pcm.c linux-raspberry-pi/sound/arm/bcm
+
+ return 0;
+}
-diff -Nur linux-3.12.13/sound/arm/bcm2835-vchiq.c linux-raspberry-pi/sound/arm/bcm2835-vchiq.c
---- linux-3.12.13/sound/arm/bcm2835-vchiq.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/arm/bcm2835-vchiq.c 2014-03-11 17:51:48.000000000 +0100
++
++int snd_bcm2835_new_spdif_pcm(bcm2835_chip_t * chip)
++{
++ struct snd_pcm *pcm;
++ int err;
++
++ err = snd_pcm_new(chip->card, "bcm2835 ALSA", 1, 1, 0, &pcm);
++ if (err < 0)
++ return err;
++
++ pcm->private_data = chip;
++ strcpy(pcm->name, "bcm2835 IEC958/HDMI");
++ chip->pcm_spdif = pcm;
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ &snd_bcm2835_playback_spdif_ops);
++
++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
++ snd_dma_continuous_data (GFP_KERNEL),
++ 64 * 1024, 64 * 1024);
++
++ return 0;
++}
+diff -Nur linux-3.12.18/sound/arm/bcm2835-vchiq.c linux-rpi/sound/arm/bcm2835-vchiq.c
+--- linux-3.12.18/sound/arm/bcm2835-vchiq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/arm/bcm2835-vchiq.c 2014-04-24 16:04:42.735152438 +0200
@@ -0,0 +1,879 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -98474,7 +103132,7 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-vchiq.c linux-raspberry-pi/sound/arm/b
+
+void my_workqueue_init(bcm2835_alsa_stream_t * alsa_stream)
+{
-+ alsa_stream->my_wq = create_workqueue("my_queue");
++ alsa_stream->my_wq = alloc_workqueue("my_queue", WQ_HIGHPRI, 1);
+ return;
+}
+
@@ -99173,9 +103831,9 @@ diff -Nur linux-3.12.13/sound/arm/bcm2835-vchiq.c linux-raspberry-pi/sound/arm/b
+
+module_param(force_bulk, bool, 0444);
+MODULE_PARM_DESC(force_bulk, "Force use of vchiq bulk for audio");
-diff -Nur linux-3.12.13/sound/arm/Kconfig linux-raspberry-pi/sound/arm/Kconfig
---- linux-3.12.13/sound/arm/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/sound/arm/Kconfig 2014-03-11 17:33:39.000000000 +0100
+diff -Nur linux-3.12.18/sound/arm/Kconfig linux-rpi/sound/arm/Kconfig
+--- linux-3.12.18/sound/arm/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/sound/arm/Kconfig 2014-04-24 15:35:05.357578964 +0200
@@ -39,5 +39,12 @@
Say Y or M if you want to support any AC97 codec attached to
the PXA2xx AC97 interface.
@@ -99189,9 +103847,9 @@ diff -Nur linux-3.12.13/sound/arm/Kconfig linux-raspberry-pi/sound/arm/Kconfig
+
endif # SND_ARM
-diff -Nur linux-3.12.13/sound/arm/Makefile linux-raspberry-pi/sound/arm/Makefile
---- linux-3.12.13/sound/arm/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/sound/arm/Makefile 2014-03-11 17:51:47.000000000 +0100
+diff -Nur linux-3.12.18/sound/arm/Makefile linux-rpi/sound/arm/Makefile
+--- linux-3.12.18/sound/arm/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/sound/arm/Makefile 2014-04-24 16:04:42.735152438 +0200
@@ -14,3 +14,8 @@
obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o
@@ -99200,10 +103858,10 @@ diff -Nur linux-3.12.13/sound/arm/Makefile linux-raspberry-pi/sound/arm/Makefile
+obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o
+snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o
+
-+EXTRA_CFLAGS += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000
-diff -Nur linux-3.12.13/sound/arm/vc_vchi_audioserv_defs.h linux-raspberry-pi/sound/arm/vc_vchi_audioserv_defs.h
---- linux-3.12.13/sound/arm/vc_vchi_audioserv_defs.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/arm/vc_vchi_audioserv_defs.h 2014-03-11 17:33:39.000000000 +0100
++ccflags-y += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000
+diff -Nur linux-3.12.18/sound/arm/vc_vchi_audioserv_defs.h linux-rpi/sound/arm/vc_vchi_audioserv_defs.h
+--- linux-3.12.18/sound/arm/vc_vchi_audioserv_defs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/arm/vc_vchi_audioserv_defs.h 2014-04-24 15:35:05.365579053 +0200
@@ -0,0 +1,116 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation. All rights reserved.
@@ -99321,9 +103979,9 @@ diff -Nur linux-3.12.13/sound/arm/vc_vchi_audioserv_defs.h linux-raspberry-pi/so
+} VC_AUDIO_MSG_T;
+
+#endif // _VC_AUDIO_DEFS_H_
-diff -Nur linux-3.12.13/sound/soc/bcm/bcm2708-i2s.c linux-raspberry-pi/sound/soc/bcm/bcm2708-i2s.c
---- linux-3.12.13/sound/soc/bcm/bcm2708-i2s.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/bcm/bcm2708-i2s.c 2014-03-11 17:33:43.000000000 +0100
+diff -Nur linux-3.12.18/sound/soc/bcm/bcm2708-i2s.c linux-rpi/sound/soc/bcm/bcm2708-i2s.c
+--- linux-3.12.18/sound/soc/bcm/bcm2708-i2s.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/bcm/bcm2708-i2s.c 2014-04-24 16:04:43.363158508 +0200
@@ -0,0 +1,945 @@
+/*
+ * ALSA SoC I2S Audio Layer for Broadcom BCM2708 SoC
@@ -100045,7 +104703,7 @@ diff -Nur linux-3.12.13/sound/soc/bcm/bcm2708-i2s.c linux-raspberry-pi/sound/soc
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE
-+ | SNDRV_PCM_FMTBIT_S24_LE
++ // | SNDRV_PCM_FMTBIT_S24_LE : disable for now, it causes white noise with xbmc
+ | SNDRV_PCM_FMTBIT_S32_LE
+ },
+ .capture = {
@@ -100270,9 +104928,9 @@ diff -Nur linux-3.12.13/sound/soc/bcm/bcm2708-i2s.c linux-raspberry-pi/sound/soc
+MODULE_DESCRIPTION("BCM2708 I2S interface");
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.13/sound/soc/bcm/hifiberry_dac.c linux-raspberry-pi/sound/soc/bcm/hifiberry_dac.c
---- linux-3.12.13/sound/soc/bcm/hifiberry_dac.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/bcm/hifiberry_dac.c 2014-03-11 17:33:43.000000000 +0100
+diff -Nur linux-3.12.18/sound/soc/bcm/hifiberry_dac.c linux-rpi/sound/soc/bcm/hifiberry_dac.c
+--- linux-3.12.18/sound/soc/bcm/hifiberry_dac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/bcm/hifiberry_dac.c 2014-04-24 15:35:05.481580345 +0200
@@ -0,0 +1,100 @@
+/*
+ * ASoC Driver for HifiBerry DAC
@@ -100374,9 +105032,9 @@ diff -Nur linux-3.12.13/sound/soc/bcm/hifiberry_dac.c linux-raspberry-pi/sound/s
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_DESCRIPTION("ASoC Driver for HifiBerry DAC");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.13/sound/soc/bcm/hifiberry_digi.c linux-raspberry-pi/sound/soc/bcm/hifiberry_digi.c
---- linux-3.12.13/sound/soc/bcm/hifiberry_digi.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/bcm/hifiberry_digi.c 2014-03-11 17:51:48.000000000 +0100
+diff -Nur linux-3.12.18/sound/soc/bcm/hifiberry_digi.c linux-rpi/sound/soc/bcm/hifiberry_digi.c
+--- linux-3.12.18/sound/soc/bcm/hifiberry_digi.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/bcm/hifiberry_digi.c 2014-04-24 16:04:43.363158508 +0200
@@ -0,0 +1,153 @@
+/*
+ * ASoC Driver for HifiBerry Digi
@@ -100531,10 +105189,125 @@ diff -Nur linux-3.12.13/sound/soc/bcm/hifiberry_digi.c linux-raspberry-pi/sound/
+MODULE_AUTHOR("Daniel Matuschek <info@crazy-audio.com>");
+MODULE_DESCRIPTION("ASoC Driver for HifiBerry Digi");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.13/sound/soc/bcm/Kconfig linux-raspberry-pi/sound/soc/bcm/Kconfig
---- linux-3.12.13/sound/soc/bcm/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/bcm/Kconfig 2014-03-11 17:33:43.000000000 +0100
-@@ -0,0 +1,31 @@
+diff -Nur linux-3.12.18/sound/soc/bcm/iqaudio-dac.c linux-rpi/sound/soc/bcm/iqaudio-dac.c
+--- linux-3.12.18/sound/soc/bcm/iqaudio-dac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/bcm/iqaudio-dac.c 2014-04-24 16:04:43.363158508 +0200
+@@ -0,0 +1,111 @@
++/*
++ * ASoC Driver for IQaudIO DAC
++ *
++ * Author: Florian Meier <florian.meier@koalo.de>
++ * Copyright 2013
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/jack.h>
++
++static int snd_rpi_iqaudio_dac_init(struct snd_soc_pcm_runtime *rtd)
++{
++// NOT USED struct snd_soc_codec *codec = rtd->codec;
++
++ return 0;
++}
++
++static int snd_rpi_iqaudio_dac_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++// NOT USED struct snd_soc_dai *codec_dai = rtd->codec_dai;
++// NOT USED struct snd_soc_codec *codec = rtd->codec;
++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++
++ unsigned int sample_bits =
++ snd_pcm_format_physical_width(params_format(params));
++
++ return snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2);
++}
++
++/* machine stream operations */
++static struct snd_soc_ops snd_rpi_iqaudio_dac_ops = {
++ .hw_params = snd_rpi_iqaudio_dac_hw_params,
++};
++
++static struct snd_soc_dai_link snd_rpi_iqaudio_dac_dai[] = {
++{
++ .name = "IQaudIO DAC",
++ .stream_name = "IQaudIO DAC HiFi",
++ .cpu_dai_name = "bcm2708-i2s.0",
++ .codec_dai_name = "pcm512x-hifi",
++ .platform_name = "bcm2708-i2s.0",
++ .codec_name = "pcm512x.1-004c",
++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++ SND_SOC_DAIFMT_CBS_CFS,
++ .ops = &snd_rpi_iqaudio_dac_ops,
++ .init = snd_rpi_iqaudio_dac_init,
++},
++};
++
++/* audio machine driver */
++static struct snd_soc_card snd_rpi_iqaudio_dac = {
++ .name = "snd_rpi_iqaudio_dac",
++ .dai_link = snd_rpi_iqaudio_dac_dai,
++ .num_links = ARRAY_SIZE(snd_rpi_iqaudio_dac_dai),
++};
++
++static int snd_rpi_iqaudio_dac_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++
++ snd_rpi_iqaudio_dac.dev = &pdev->dev;
++ ret = snd_soc_register_card(&snd_rpi_iqaudio_dac);
++ if (ret)
++ dev_err(&pdev->dev,
++ "snd_soc_register_card() failed: %d\n", ret);
++
++ return ret;
++}
++
++static int snd_rpi_iqaudio_dac_remove(struct platform_device *pdev)
++{
++ return snd_soc_unregister_card(&snd_rpi_iqaudio_dac);
++}
++
++static const struct of_device_id iqaudio_of_match[] = {
++ { .compatible = "iqaudio,iqaudio-dac", },
++ {},
++};
++
++static struct platform_driver snd_rpi_iqaudio_dac_driver = {
++ .driver = {
++ .name = "snd-rpi-iqaudio-dac",
++ .owner = THIS_MODULE,
++ .of_match_table = iqaudio_of_match,
++ },
++ .probe = snd_rpi_iqaudio_dac_probe,
++ .remove = snd_rpi_iqaudio_dac_remove,
++};
++
++module_platform_driver(snd_rpi_iqaudio_dac_driver);
++
++MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
++MODULE_DESCRIPTION("ASoC Driver for IQAudio DAC");
++MODULE_LICENSE("GPL v2");
+diff -Nur linux-3.12.18/sound/soc/bcm/Kconfig linux-rpi/sound/soc/bcm/Kconfig
+--- linux-3.12.18/sound/soc/bcm/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/bcm/Kconfig 2014-04-24 15:35:05.481580345 +0200
+@@ -0,0 +1,38 @@
+config SND_BCM2708_SOC_I2S
+ tristate "SoC Audio support for the Broadcom BCM2708 I2S module"
+ depends on MACH_BCM2708
@@ -100566,10 +105339,17 @@ diff -Nur linux-3.12.13/sound/soc/bcm/Kconfig linux-raspberry-pi/sound/soc/bcm/K
+ select SND_SOC_PCM1794A
+ help
+ Say Y or M if you want to add support for RPi-DAC.
-diff -Nur linux-3.12.13/sound/soc/bcm/Makefile linux-raspberry-pi/sound/soc/bcm/Makefile
---- linux-3.12.13/sound/soc/bcm/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/bcm/Makefile 2014-03-11 17:33:43.000000000 +0100
-@@ -0,0 +1,13 @@
++
++config SND_BCM2708_SOC_IQAUDIO_DAC
++ tristate "Support for IQaudIO-DAC"
++ depends on SND_BCM2708_SOC_I2S
++ select SND_SOC_PCM512x
++ help
++ Say Y or M if you want to add support for IQaudIO-DAC.
+diff -Nur linux-3.12.18/sound/soc/bcm/Makefile linux-rpi/sound/soc/bcm/Makefile
+--- linux-3.12.18/sound/soc/bcm/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/bcm/Makefile 2014-04-24 16:04:43.363158508 +0200
+@@ -0,0 +1,15 @@
+# BCM2708 Platform Support
+snd-soc-bcm2708-i2s-objs := bcm2708-i2s.o
+
@@ -100579,13 +105359,15 @@ diff -Nur linux-3.12.13/sound/soc/bcm/Makefile linux-raspberry-pi/sound/soc/bcm/
+snd-soc-hifiberry-dac-objs := hifiberry_dac.o
+snd-soc-hifiberry-digi-objs := hifiberry_digi.o
+snd-soc-rpi-dac-objs := rpi-dac.o
++snd-soc-iqaudio-dac-objs := iqaudio-dac.o
+
+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o
+obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o
+obj-$(CONFIG_SND_BCM2708_SOC_RPI_DAC) += snd-soc-rpi-dac.o
-diff -Nur linux-3.12.13/sound/soc/bcm/rpi-dac.c linux-raspberry-pi/sound/soc/bcm/rpi-dac.c
---- linux-3.12.13/sound/soc/bcm/rpi-dac.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/bcm/rpi-dac.c 2014-03-11 17:33:43.000000000 +0100
++obj-$(CONFIG_SND_BCM2708_SOC_IQAUDIO_DAC) += snd-soc-iqaudio-dac.o
+diff -Nur linux-3.12.18/sound/soc/bcm/rpi-dac.c linux-rpi/sound/soc/bcm/rpi-dac.c
+--- linux-3.12.18/sound/soc/bcm/rpi-dac.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/bcm/rpi-dac.c 2014-04-24 15:35:05.481580345 +0200
@@ -0,0 +1,97 @@
+/*
+ * ASoC Driver for RPi-DAC.
@@ -100684,19 +105466,20 @@ diff -Nur linux-3.12.13/sound/soc/bcm/rpi-dac.c linux-raspberry-pi/sound/soc/bcm
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_DESCRIPTION("ASoC Driver for RPi-DAC");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.13/sound/soc/codecs/Kconfig linux-raspberry-pi/sound/soc/codecs/Kconfig
---- linux-3.12.13/sound/soc/codecs/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/codecs/Kconfig 2014-03-11 17:51:48.000000000 +0100
-@@ -59,6 +59,8 @@
+diff -Nur linux-3.12.18/sound/soc/codecs/Kconfig linux-rpi/sound/soc/codecs/Kconfig
+--- linux-3.12.18/sound/soc/codecs/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/sound/soc/codecs/Kconfig 2014-04-24 16:04:43.367158547 +0200
+@@ -59,6 +59,9 @@
select SND_SOC_PCM1681 if I2C
select SND_SOC_PCM1792A if SPI_MASTER
select SND_SOC_PCM3008
+ select SND_SOC_PCM1794A
+ select SND_SOC_PCM5102A
++ select SND_SOC_PCM512x if SND_SOC_I2C_AND_SPI
select SND_SOC_RT5631 if I2C
select SND_SOC_RT5640 if I2C
select SND_SOC_SGTL5000 if I2C
-@@ -311,6 +313,12 @@
+@@ -311,6 +314,15 @@
config SND_SOC_PCM3008
tristate
@@ -100706,33 +105489,38 @@ diff -Nur linux-3.12.13/sound/soc/codecs/Kconfig linux-raspberry-pi/sound/soc/co
+config SND_SOC_PCM5102A
+ tristate
+
++config SND_SOC_PCM512x
++ tristate
++
config SND_SOC_RT5631
tristate
-diff -Nur linux-3.12.13/sound/soc/codecs/Makefile linux-raspberry-pi/sound/soc/codecs/Makefile
---- linux-3.12.13/sound/soc/codecs/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/codecs/Makefile 2014-03-11 17:51:48.000000000 +0100
-@@ -46,6 +46,8 @@
+diff -Nur linux-3.12.18/sound/soc/codecs/Makefile linux-rpi/sound/soc/codecs/Makefile
+--- linux-3.12.18/sound/soc/codecs/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/sound/soc/codecs/Makefile 2014-04-24 16:04:43.367158547 +0200
+@@ -46,6 +46,9 @@
snd-soc-pcm1681-objs := pcm1681.o
snd-soc-pcm1792a-codec-objs := pcm1792a.o
snd-soc-pcm3008-objs := pcm3008.o
+snd-soc-pcm1794a-objs := pcm1794a.o
+snd-soc-pcm5102a-objs := pcm5102a.o
++snd-soc-pcm512x-objs := pcm512x.o
snd-soc-rt5631-objs := rt5631.o
snd-soc-rt5640-objs := rt5640.o
snd-soc-sgtl5000-objs := sgtl5000.o
-@@ -179,6 +181,8 @@
+@@ -179,6 +182,9 @@
obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o
obj-$(CONFIG_SND_SOC_PCM1792A) += snd-soc-pcm1792a-codec.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
+obj-$(CONFIG_SND_SOC_PCM1794A) += snd-soc-pcm1794a.o
+obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o
++obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o
obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
-diff -Nur linux-3.12.13/sound/soc/codecs/pcm1794a.c linux-raspberry-pi/sound/soc/codecs/pcm1794a.c
---- linux-3.12.13/sound/soc/codecs/pcm1794a.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/codecs/pcm1794a.c 2014-03-11 17:33:43.000000000 +0100
+diff -Nur linux-3.12.18/sound/soc/codecs/pcm1794a.c linux-rpi/sound/soc/codecs/pcm1794a.c
+--- linux-3.12.18/sound/soc/codecs/pcm1794a.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/codecs/pcm1794a.c 2014-04-24 15:35:05.493580478 +0200
@@ -0,0 +1,62 @@
+/*
+ * Driver for the PCM1794A codec
@@ -100796,9 +105584,9 @@ diff -Nur linux-3.12.13/sound/soc/codecs/pcm1794a.c linux-raspberry-pi/sound/soc
+MODULE_DESCRIPTION("ASoC PCM1794A codec driver");
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.13/sound/soc/codecs/pcm5102a.c linux-raspberry-pi/sound/soc/codecs/pcm5102a.c
---- linux-3.12.13/sound/soc/codecs/pcm5102a.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/codecs/pcm5102a.c 2014-03-11 17:51:49.000000000 +0100
+diff -Nur linux-3.12.18/sound/soc/codecs/pcm5102a.c linux-rpi/sound/soc/codecs/pcm5102a.c
+--- linux-3.12.18/sound/soc/codecs/pcm5102a.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/codecs/pcm5102a.c 2014-04-24 15:35:05.493580478 +0200
@@ -0,0 +1,63 @@
+/*
+ * Driver for the PCM5102A codec
@@ -100830,7 +105618,7 @@ diff -Nur linux-3.12.13/sound/soc/codecs/pcm5102a.c linux-raspberry-pi/sound/soc
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
-+ SNDRV_PCM_FMTBIT_S24_LE |
++ // SNDRV_PCM_FMTBIT_S24_LE | : disable for now, it causes white noise with xbmc
+ SNDRV_PCM_FMTBIT_S32_LE
+ },
+};
@@ -100863,9 +105651,837 @@ diff -Nur linux-3.12.13/sound/soc/codecs/pcm5102a.c linux-raspberry-pi/sound/soc
+MODULE_DESCRIPTION("ASoC PCM5102A codec driver");
+MODULE_AUTHOR("Florian Meier <florian.meier@koalo.de>");
+MODULE_LICENSE("GPL v2");
-diff -Nur linux-3.12.13/sound/soc/codecs/wm8804.c linux-raspberry-pi/sound/soc/codecs/wm8804.c
---- linux-3.12.13/sound/soc/codecs/wm8804.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/codecs/wm8804.c 2014-03-11 17:33:43.000000000 +0100
+diff -Nur linux-3.12.18/sound/soc/codecs/pcm512x.c linux-rpi/sound/soc/codecs/pcm512x.c
+--- linux-3.12.18/sound/soc/codecs/pcm512x.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/codecs/pcm512x.c 2014-04-24 16:04:43.375158625 +0200
+@@ -0,0 +1,678 @@
++/*
++ * Driver for the PCM512x CODECs
++ *
++ * Author: Mark Brown <broonie@linaro.org>
++ * Copyright 2014 Linaro Ltd
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ */
++
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <linux/i2c.h>
++#include <linux/pm_runtime.h>
++#include <linux/regmap.h>
++#include <linux/regulator/consumer.h>
++#include <linux/spi/spi.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++#include <sound/tlv.h>
++
++#include "pcm512x.h"
++
++#define PCM512x_NUM_SUPPLIES 3
++static const char *pcm512x_supply_names[PCM512x_NUM_SUPPLIES] = {
++ "AVDD",
++ "DVDD",
++ "CPVDD",
++};
++
++struct pcm512x_priv {
++ struct regmap *regmap;
++ struct clk *sclk;
++ struct regulator_bulk_data supplies[PCM512x_NUM_SUPPLIES];
++ struct notifier_block supply_nb[PCM512x_NUM_SUPPLIES];
++};
++
++/*
++ * We can't use the same notifier block for more than one supply and
++ * there's no way I can see to get from a callback to the caller
++ * except container_of().
++ */
++#define PCM512x_REGULATOR_EVENT(n) \
++static int pcm512x_regulator_event_##n(struct notifier_block *nb, \
++ unsigned long event, void *data) \
++{ \
++ struct pcm512x_priv *pcm512x = container_of(nb, struct pcm512x_priv, \
++ supply_nb[n]); \
++ if (event & REGULATOR_EVENT_DISABLE) { \
++ regcache_mark_dirty(pcm512x->regmap); \
++ regcache_cache_only(pcm512x->regmap, true); \
++ } \
++ return 0; \
++}
++
++PCM512x_REGULATOR_EVENT(0)
++PCM512x_REGULATOR_EVENT(1)
++PCM512x_REGULATOR_EVENT(2)
++
++static const struct reg_default pcm512x_reg_defaults[] = {
++ { PCM512x_RESET, 0x00 },
++ { PCM512x_POWER, 0x00 },
++ { PCM512x_MUTE, 0x00 },
++ { PCM512x_DSP, 0x00 },
++ { PCM512x_PLL_REF, 0x00 },
++ { PCM512x_DAC_ROUTING, 0x11 },
++ { PCM512x_DSP_PROGRAM, 0x01 },
++ { PCM512x_CLKDET, 0x00 },
++ { PCM512x_AUTO_MUTE, 0x00 },
++ { PCM512x_ERROR_DETECT, 0x00 },
++ { PCM512x_DIGITAL_VOLUME_1, 0x00 },
++ { PCM512x_DIGITAL_VOLUME_2, 0x30 },
++ { PCM512x_DIGITAL_VOLUME_3, 0x30 },
++ { PCM512x_DIGITAL_MUTE_1, 0x22 },
++ { PCM512x_DIGITAL_MUTE_2, 0x00 },
++ { PCM512x_DIGITAL_MUTE_3, 0x07 },
++};
++
++static bool pcm512x_readable(struct device *dev, unsigned int reg)
++{
++ switch (reg) {
++ case PCM512x_RESET:
++ case PCM512x_POWER:
++ case PCM512x_MUTE:
++ case PCM512x_PLL_EN:
++ case PCM512x_SPI_MISO_FUNCTION:
++ case PCM512x_DSP:
++ case PCM512x_GPIO_EN:
++ case PCM512x_BCLK_LRCLK_CFG:
++ case PCM512x_DSP_GPIO_INPUT:
++ case PCM512x_MASTER_MODE:
++ case PCM512x_PLL_REF:
++ case PCM512x_PLL_COEFF_0:
++ case PCM512x_PLL_COEFF_1:
++ case PCM512x_PLL_COEFF_2:
++ case PCM512x_PLL_COEFF_3:
++ case PCM512x_PLL_COEFF_4:
++ case PCM512x_DSP_CLKDIV:
++ case PCM512x_DAC_CLKDIV:
++ case PCM512x_NCP_CLKDIV:
++ case PCM512x_OSR_CLKDIV:
++ case PCM512x_MASTER_CLKDIV_1:
++ case PCM512x_MASTER_CLKDIV_2:
++ case PCM512x_FS_SPEED_MODE:
++ case PCM512x_IDAC_1:
++ case PCM512x_IDAC_2:
++ case PCM512x_ERROR_DETECT:
++ case PCM512x_I2S_1:
++ case PCM512x_I2S_2:
++ case PCM512x_DAC_ROUTING:
++ case PCM512x_DSP_PROGRAM:
++ case PCM512x_CLKDET:
++ case PCM512x_AUTO_MUTE:
++ case PCM512x_DIGITAL_VOLUME_1:
++ case PCM512x_DIGITAL_VOLUME_2:
++ case PCM512x_DIGITAL_VOLUME_3:
++ case PCM512x_DIGITAL_MUTE_1:
++ case PCM512x_DIGITAL_MUTE_2:
++ case PCM512x_DIGITAL_MUTE_3:
++ case PCM512x_GPIO_OUTPUT_1:
++ case PCM512x_GPIO_OUTPUT_2:
++ case PCM512x_GPIO_OUTPUT_3:
++ case PCM512x_GPIO_OUTPUT_4:
++ case PCM512x_GPIO_OUTPUT_5:
++ case PCM512x_GPIO_OUTPUT_6:
++ case PCM512x_GPIO_CONTROL_1:
++ case PCM512x_GPIO_CONTROL_2:
++ case PCM512x_OVERFLOW:
++ case PCM512x_RATE_DET_1:
++ case PCM512x_RATE_DET_2:
++ case PCM512x_RATE_DET_3:
++ case PCM512x_RATE_DET_4:
++ case PCM512x_ANALOG_MUTE_DET:
++ case PCM512x_GPIN:
++ case PCM512x_DIGITAL_MUTE_DET:
++ return true;
++ default:
++ return false;
++ }
++}
++
++static bool pcm512x_volatile(struct device *dev, unsigned int reg)
++{
++ switch (reg) {
++ case PCM512x_PLL_EN:
++ case PCM512x_OVERFLOW:
++ case PCM512x_RATE_DET_1:
++ case PCM512x_RATE_DET_2:
++ case PCM512x_RATE_DET_3:
++ case PCM512x_RATE_DET_4:
++ case PCM512x_ANALOG_MUTE_DET:
++ case PCM512x_GPIN:
++ case PCM512x_DIGITAL_MUTE_DET:
++ return true;
++ default:
++ return false;
++ }
++}
++
++static const DECLARE_TLV_DB_SCALE(digital_tlv, -10350, 50, 1);
++
++static const char *pcm512x_dsp_program_texts[] = {
++ "FIR interpolation with de-emphasis",
++ "Low latency IIR with de-emphasis",
++ "High attenuation with de-emphasis",
++ "Ringing-less low latency FIR",
++};
++
++static const unsigned int pcm512x_dsp_program_values[] = {
++ 1,
++ 2,
++ 3,
++ 5,
++ 7,
++};
++
++static const SOC_VALUE_ENUM_SINGLE_DECL(pcm512x_dsp_program,
++ PCM512x_DSP_PROGRAM, 0, 0x1f,
++ pcm512x_dsp_program_texts,
++ pcm512x_dsp_program_values);
++
++static const char *pcm512x_clk_missing_text[] = {
++ "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s"
++};
++
++static const struct soc_enum pcm512x_clk_missing =
++ SOC_ENUM_SINGLE(PCM512x_CLKDET, 0, 7, pcm512x_clk_missing_text);
++
++static const char *pcm512x_autom_text[] = {
++ "21ms", "106ms", "213ms", "533ms", "1.07s", "2.13s", "5.33s", "10.66s"
++};
++
++static const struct soc_enum pcm512x_autom_l =
++ SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATML_SHIFT, 7,
++ pcm512x_autom_text);
++
++static const struct soc_enum pcm512x_autom_r =
++ SOC_ENUM_SINGLE(PCM512x_AUTO_MUTE, PCM512x_ATMR_SHIFT, 7,
++ pcm512x_autom_text);
++
++static const char *pcm512x_ramp_rate_text[] = {
++ "1 sample/update", "2 samples/update", "4 samples/update",
++ "Immediate"
++};
++
++static const struct soc_enum pcm512x_vndf =
++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDF_SHIFT, 4,
++ pcm512x_ramp_rate_text);
++
++static const struct soc_enum pcm512x_vnuf =
++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUF_SHIFT, 4,
++ pcm512x_ramp_rate_text);
++
++static const struct soc_enum pcm512x_vedf =
++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDF_SHIFT, 4,
++ pcm512x_ramp_rate_text);
++
++static const char *pcm512x_ramp_step_text[] = {
++ "4dB/step", "2dB/step", "1dB/step", "0.5dB/step"
++};
++
++static const struct soc_enum pcm512x_vnds =
++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNDS_SHIFT, 4,
++ pcm512x_ramp_step_text);
++
++static const struct soc_enum pcm512x_vnus =
++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_1, PCM512x_VNUS_SHIFT, 4,
++ pcm512x_ramp_step_text);
++
++static const struct soc_enum pcm512x_veds =
++ SOC_ENUM_SINGLE(PCM512x_DIGITAL_MUTE_2, PCM512x_VEDS_SHIFT, 4,
++ pcm512x_ramp_step_text);
++
++/* Don't let the DAC go into clipping by limiting the alsa volume control range */
++static const struct snd_kcontrol_new pcm512x_controls[] = {
++SOC_DOUBLE_R_RANGE_TLV("Playback Digital Volume", PCM512x_DIGITAL_VOLUME_2,
++ PCM512x_DIGITAL_VOLUME_3, 0, 40, 255, 1, digital_tlv),
++SOC_DOUBLE("Playback Digital Switch", PCM512x_MUTE, PCM512x_RQML_SHIFT,
++ PCM512x_RQMR_SHIFT, 1, 1),
++
++SOC_SINGLE("Deemphasis Switch", PCM512x_DSP, PCM512x_DEMP_SHIFT, 1, 1),
++SOC_VALUE_ENUM("DSP Program", pcm512x_dsp_program),
++
++SOC_ENUM("Clock Missing Period", pcm512x_clk_missing),
++SOC_ENUM("Auto Mute Time Left", pcm512x_autom_l),
++SOC_ENUM("Auto Mute Time Right", pcm512x_autom_r),
++SOC_SINGLE("Auto Mute Mono Switch", PCM512x_DIGITAL_MUTE_3,
++ PCM512x_ACTL_SHIFT, 1, 0),
++SOC_DOUBLE("Auto Mute Switch", PCM512x_DIGITAL_MUTE_3, PCM512x_AMLE_SHIFT,
++ PCM512x_AMLR_SHIFT, 1, 0),
++
++SOC_ENUM("Volume Ramp Down Rate", pcm512x_vndf),
++SOC_ENUM("Volume Ramp Down Step", pcm512x_vnds),
++SOC_ENUM("Volume Ramp Up Rate", pcm512x_vnuf),
++SOC_ENUM("Volume Ramp Up Step", pcm512x_vnus),
++SOC_ENUM("Volume Ramp Down Emergency Rate", pcm512x_vedf),
++SOC_ENUM("Volume Ramp Down Emergency Step", pcm512x_veds),
++};
++
++static const struct snd_soc_dapm_widget pcm512x_dapm_widgets[] = {
++SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
++SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
++
++SND_SOC_DAPM_OUTPUT("OUTL"),
++SND_SOC_DAPM_OUTPUT("OUTR"),
++};
++
++static const struct snd_soc_dapm_route pcm512x_dapm_routes[] = {
++ { "DACL", NULL, "Playback" },
++ { "DACR", NULL, "Playback" },
++
++ { "OUTL", NULL, "DACL" },
++ { "OUTR", NULL, "DACR" },
++};
++
++static int pcm512x_set_bias_level(struct snd_soc_codec *codec,
++ enum snd_soc_bias_level level)
++{
++ struct pcm512x_priv *pcm512x = dev_get_drvdata(codec->dev);
++ int ret;
++
++ switch (level) {
++ case SND_SOC_BIAS_ON:
++ case SND_SOC_BIAS_PREPARE:
++ break;
++
++ case SND_SOC_BIAS_STANDBY:
++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
++ PCM512x_RQST, 0);
++ if (ret != 0) {
++ dev_err(codec->dev, "Failed to remove standby: %d\n",
++ ret);
++ return ret;
++ }
++ break;
++
++ case SND_SOC_BIAS_OFF:
++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
++ PCM512x_RQST, PCM512x_RQST);
++ if (ret != 0) {
++ dev_err(codec->dev, "Failed to request standby: %d\n",
++ ret);
++ return ret;
++ }
++ break;
++ }
++
++ codec->dapm.bias_level = level;
++
++ return 0;
++}
++
++static struct snd_soc_dai_driver pcm512x_dai = {
++ .name = "pcm512x-hifi",
++ .playback = {
++ .stream_name = "Playback",
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = SNDRV_PCM_RATE_8000_192000,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE |
++ SNDRV_PCM_FMTBIT_S24_LE |
++ SNDRV_PCM_FMTBIT_S32_LE
++ },
++};
++
++static struct snd_soc_codec_driver pcm512x_codec_driver = {
++ .set_bias_level = pcm512x_set_bias_level,
++ .idle_bias_off = true,
++
++ .controls = pcm512x_controls,
++ .num_controls = ARRAY_SIZE(pcm512x_controls),
++ .dapm_widgets = pcm512x_dapm_widgets,
++ .num_dapm_widgets = ARRAY_SIZE(pcm512x_dapm_widgets),
++ .dapm_routes = pcm512x_dapm_routes,
++ .num_dapm_routes = ARRAY_SIZE(pcm512x_dapm_routes),
++};
++
++static const struct regmap_config pcm512x_regmap = {
++ .reg_bits = 8,
++ .val_bits = 8,
++
++ .readable_reg = pcm512x_readable,
++ .volatile_reg = pcm512x_volatile,
++
++ .max_register = PCM512x_MAX_REGISTER,
++ .reg_defaults = pcm512x_reg_defaults,
++ .num_reg_defaults = ARRAY_SIZE(pcm512x_reg_defaults),
++ .cache_type = REGCACHE_RBTREE,
++};
++
++static const struct of_device_id pcm512x_of_match[] = {
++ { .compatible = "ti,pcm5121", },
++ { .compatible = "ti,pcm5122", },
++ { }
++};
++MODULE_DEVICE_TABLE(of, pcm512x_of_match);
++
++static int pcm512x_probe(struct device *dev, struct regmap *regmap)
++{
++ struct pcm512x_priv *pcm512x;
++ int i, ret;
++
++ pcm512x = devm_kzalloc(dev, sizeof(struct pcm512x_priv), GFP_KERNEL);
++ if (!pcm512x)
++ return -ENOMEM;
++
++ dev_set_drvdata(dev, pcm512x);
++ pcm512x->regmap = regmap;
++
++ for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++)
++ pcm512x->supplies[i].supply = pcm512x_supply_names[i];
++
++ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(pcm512x->supplies),
++ pcm512x->supplies);
++ if (ret != 0) {
++ dev_err(dev, "Failed to get supplies: %d\n", ret);
++ return ret;
++ }
++
++ pcm512x->supply_nb[0].notifier_call = pcm512x_regulator_event_0;
++ pcm512x->supply_nb[1].notifier_call = pcm512x_regulator_event_1;
++ pcm512x->supply_nb[2].notifier_call = pcm512x_regulator_event_2;
++
++ for (i = 0; i < ARRAY_SIZE(pcm512x->supplies); i++) {
++ ret = regulator_register_notifier(pcm512x->supplies[i].consumer,
++ &pcm512x->supply_nb[i]);
++ if (ret != 0) {
++ dev_err(dev,
++ "Failed to register regulator notifier: %d\n",
++ ret);
++ }
++ }
++
++ ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
++ pcm512x->supplies);
++ if (ret != 0) {
++ dev_err(dev, "Failed to enable supplies: %d\n", ret);
++ return ret;
++ }
++
++ /* Reset the device, verifying I/O in the process for I2C */
++ ret = regmap_write(regmap, PCM512x_RESET,
++ PCM512x_RSTM | PCM512x_RSTR);
++ if (ret != 0) {
++ dev_err(dev, "Failed to reset device: %d\n", ret);
++ goto err;
++ }
++
++ ret = regmap_write(regmap, PCM512x_RESET, 0);
++ if (ret != 0) {
++ dev_err(dev, "Failed to reset device: %d\n", ret);
++ goto err;
++ }
++
++ pcm512x->sclk = devm_clk_get(dev, NULL);
++ if (IS_ERR(pcm512x->sclk)) {
++ if (PTR_ERR(pcm512x->sclk) == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++
++ dev_info(dev, "No SCLK, using BCLK: %ld\n",
++ PTR_ERR(pcm512x->sclk));
++
++ /* Disable reporting of missing SCLK as an error */
++ regmap_update_bits(regmap, PCM512x_ERROR_DETECT,
++ PCM512x_IDCH, PCM512x_IDCH);
++
++ /* Switch PLL input to BCLK */
++ regmap_update_bits(regmap, PCM512x_PLL_REF,
++ PCM512x_SREF, PCM512x_SREF);
++ } else {
++ ret = clk_prepare_enable(pcm512x->sclk);
++ if (ret != 0) {
++ dev_err(dev, "Failed to enable SCLK: %d\n", ret);
++ return ret;
++ }
++ }
++
++ /* Default to standby mode */
++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
++ PCM512x_RQST, PCM512x_RQST);
++ if (ret != 0) {
++ dev_err(dev, "Failed to request standby: %d\n",
++ ret);
++ goto err_clk;
++ }
++
++ pm_runtime_set_active(dev);
++ pm_runtime_enable(dev);
++ pm_runtime_idle(dev);
++
++ ret = snd_soc_register_codec(dev, &pcm512x_codec_driver,
++ &pcm512x_dai, 1);
++ if (ret != 0) {
++ dev_err(dev, "Failed to register CODEC: %d\n", ret);
++ goto err_pm;
++ }
++
++ dev_info(dev, "Completed initialisation - pcm512x_probe");
++
++ return 0;
++
++err_pm:
++ pm_runtime_disable(dev);
++err_clk:
++ if (!IS_ERR(pcm512x->sclk))
++ clk_disable_unprepare(pcm512x->sclk);
++err:
++ regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
++ pcm512x->supplies);
++ return ret;
++}
++
++static void pcm512x_remove(struct device *dev)
++{
++ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
++
++ snd_soc_unregister_codec(dev);
++ pm_runtime_disable(dev);
++ if (!IS_ERR(pcm512x->sclk))
++ clk_disable_unprepare(pcm512x->sclk);
++ regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
++ pcm512x->supplies);
++}
++
++/* TODO
++static int pcm512x_suspend(struct device *dev)
++{
++ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
++ int ret;
++
++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
++ PCM512x_RQPD, PCM512x_RQPD);
++ if (ret != 0) {
++ dev_err(dev, "Failed to request power down: %d\n", ret);
++ return ret;
++ }
++
++ ret = regulator_bulk_disable(ARRAY_SIZE(pcm512x->supplies),
++ pcm512x->supplies);
++ if (ret != 0) {
++ dev_err(dev, "Failed to disable supplies: %d\n", ret);
++ return ret;
++ }
++
++ if (!IS_ERR(pcm512x->sclk))
++ clk_disable_unprepare(pcm512x->sclk);
++
++ return 0;
++}
++
++static int pcm512x_resume(struct device *dev)
++{
++ struct pcm512x_priv *pcm512x = dev_get_drvdata(dev);
++ int ret;
++
++ if (!IS_ERR(pcm512x->sclk)) {
++ ret = clk_prepare_enable(pcm512x->sclk);
++ if (ret != 0) {
++ dev_err(dev, "Failed to enable SCLK: %d\n", ret);
++ return ret;
++ }
++ }
++
++ ret = regulator_bulk_enable(ARRAY_SIZE(pcm512x->supplies),
++ pcm512x->supplies);
++ if (ret != 0) {
++ dev_err(dev, "Failed to enable supplies: %d\n", ret);
++ return ret;
++ }
++
++ regcache_cache_only(pcm512x->regmap, false);
++ ret = regcache_sync(pcm512x->regmap);
++ if (ret != 0) {
++ dev_err(dev, "Failed to sync cache: %d\n", ret);
++ return ret;
++ }
++
++ ret = regmap_update_bits(pcm512x->regmap, PCM512x_POWER,
++ PCM512x_RQPD, 0);
++ if (ret != 0) {
++ dev_err(dev, "Failed to remove power down: %d\n", ret);
++ return ret;
++ }
++
++ return 0;
++}
++
++// END OF PCM512x_suspend and resume calls TODO
++*/
++
++static const struct dev_pm_ops pcm512x_pm_ops = {
++ SET_RUNTIME_PM_OPS(pcm512x_suspend, pcm512x_resume, NULL)
++};
++
++#if IS_ENABLED(CONFIG_I2C)
++static int pcm512x_i2c_probe(struct i2c_client *i2c,
++ const struct i2c_device_id *id)
++{
++ struct regmap *regmap;
++
++ regmap = devm_regmap_init_i2c(i2c, &pcm512x_regmap);
++ if (IS_ERR(regmap))
++ return PTR_ERR(regmap);
++
++ return pcm512x_probe(&i2c->dev, regmap);
++}
++
++static int pcm512x_i2c_remove(struct i2c_client *i2c)
++{
++ pcm512x_remove(&i2c->dev);
++ return 0;
++}
++
++static const struct i2c_device_id pcm512x_i2c_id[] = {
++ { "pcm5121", },
++ { "pcm5122", },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id);
++
++static struct i2c_driver pcm512x_i2c_driver = {
++ .probe = pcm512x_i2c_probe,
++ .remove = pcm512x_i2c_remove,
++ .id_table = pcm512x_i2c_id,
++ .driver = {
++ .name = "pcm512x",
++ .owner = THIS_MODULE,
++ .of_match_table = pcm512x_of_match,
++ .pm = &pcm512x_pm_ops,
++ },
++};
++#endif
++
++#if defined(CONFIG_SPI_MASTER)
++static int pcm512x_spi_probe(struct spi_device *spi)
++{
++ struct regmap *regmap;
++ int ret;
++
++ regmap = devm_regmap_init_spi(spi, &pcm512x_regmap);
++ if (IS_ERR(regmap)) {
++ ret = PTR_ERR(regmap);
++ return ret;
++ }
++
++ return pcm512x_probe(&spi->dev, regmap);
++}
++
++static int pcm512x_spi_remove(struct spi_device *spi)
++{
++ pcm512x_remove(&spi->dev);
++ return 0;
++}
++
++static const struct spi_device_id pcm512x_spi_id[] = {
++ { "pcm5121", },
++ { "pcm5122", },
++ { },
++};
++MODULE_DEVICE_TABLE(spi, pcm512x_spi_id);
++
++static struct spi_driver pcm512x_spi_driver = {
++ .probe = pcm512x_spi_probe,
++ .remove = pcm512x_spi_remove,
++ .id_table = pcm512x_spi_id,
++ .driver = {
++ .name = "pcm512x",
++ .owner = THIS_MODULE,
++ .of_match_table = pcm512x_of_match,
++ .pm = &pcm512x_pm_ops,
++ },
++};
++#endif
++
++static int __init pcm512x_modinit(void)
++{
++ int ret = 0;
++
++#if IS_ENABLED(CONFIG_I2C)
++ ret = i2c_add_driver(&pcm512x_i2c_driver);
++ if (ret) {
++ printk(KERN_ERR "Failed to register pcm512x I2C driver: %d\n",
++ ret);
++ }
++#endif
++#if defined(CONFIG_SPI_MASTER)
++ ret = spi_register_driver(&pcm512x_spi_driver);
++ if (ret != 0) {
++ printk(KERN_ERR "Failed to register pcm512x SPI driver: %d\n",
++ ret);
++ }
++#endif
++ return ret;
++}
++module_init(pcm512x_modinit);
++
++static void __exit pcm512x_exit(void)
++{
++#if IS_ENABLED(CONFIG_I2C)
++ i2c_del_driver(&pcm512x_i2c_driver);
++#endif
++#if defined(CONFIG_SPI_MASTER)
++ spi_unregister_driver(&pcm512x_spi_driver);
++#endif
++}
++module_exit(pcm512x_exit);
++
++MODULE_DESCRIPTION("ASoC PCM512x codec driver");
++MODULE_AUTHOR("Mark Brown <broonie@linaro.org>");
++MODULE_LICENSE("GPL v2");
+diff -Nur linux-3.12.18/sound/soc/codecs/pcm512x.h linux-rpi/sound/soc/codecs/pcm512x.h
+--- linux-3.12.18/sound/soc/codecs/pcm512x.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-rpi/sound/soc/codecs/pcm512x.h 2014-04-24 15:35:05.493580478 +0200
+@@ -0,0 +1,142 @@
++/*
++ * Driver for the PCM512x CODECs
++ *
++ * Author: Mark Brown <broonie@linaro.org>
++ * Copyright 2014 Linaro Ltd
++ *
++ * 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.
++ *
++ * 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 _SND_SOC_PCM512X
++#define _SND_SOC_PCM512X
++
++#define PCM512x_PAGE_0_BASE 0
++
++#define PCM512x_PAGE 0
++
++#define PCM512x_RESET (PCM512x_PAGE_0_BASE + 1)
++#define PCM512x_POWER (PCM512x_PAGE_0_BASE + 2)
++#define PCM512x_MUTE (PCM512x_PAGE_0_BASE + 3)
++#define PCM512x_PLL_EN (PCM512x_PAGE_0_BASE + 4)
++#define PCM512x_SPI_MISO_FUNCTION (PCM512x_PAGE_0_BASE + 6)
++#define PCM512x_DSP (PCM512x_PAGE_0_BASE + 7)
++#define PCM512x_GPIO_EN (PCM512x_PAGE_0_BASE + 8)
++#define PCM512x_BCLK_LRCLK_CFG (PCM512x_PAGE_0_BASE + 9)
++#define PCM512x_DSP_GPIO_INPUT (PCM512x_PAGE_0_BASE + 10)
++#define PCM512x_MASTER_MODE (PCM512x_PAGE_0_BASE + 12)
++#define PCM512x_PLL_REF (PCM512x_PAGE_0_BASE + 13)
++#define PCM512x_PLL_COEFF_0 (PCM512x_PAGE_0_BASE + 20)
++#define PCM512x_PLL_COEFF_1 (PCM512x_PAGE_0_BASE + 21)
++#define PCM512x_PLL_COEFF_2 (PCM512x_PAGE_0_BASE + 22)
++#define PCM512x_PLL_COEFF_3 (PCM512x_PAGE_0_BASE + 23)
++#define PCM512x_PLL_COEFF_4 (PCM512x_PAGE_0_BASE + 24)
++#define PCM512x_DSP_CLKDIV (PCM512x_PAGE_0_BASE + 27)
++#define PCM512x_DAC_CLKDIV (PCM512x_PAGE_0_BASE + 28)
++#define PCM512x_NCP_CLKDIV (PCM512x_PAGE_0_BASE + 29)
++#define PCM512x_OSR_CLKDIV (PCM512x_PAGE_0_BASE + 30)
++#define PCM512x_MASTER_CLKDIV_1 (PCM512x_PAGE_0_BASE + 32)
++#define PCM512x_MASTER_CLKDIV_2 (PCM512x_PAGE_0_BASE + 33)
++#define PCM512x_FS_SPEED_MODE (PCM512x_PAGE_0_BASE + 34)
++#define PCM512x_IDAC_1 (PCM512x_PAGE_0_BASE + 35)
++#define PCM512x_IDAC_2 (PCM512x_PAGE_0_BASE + 36)
++#define PCM512x_ERROR_DETECT (PCM512x_PAGE_0_BASE + 37)
++#define PCM512x_I2S_1 (PCM512x_PAGE_0_BASE + 40)
++#define PCM512x_I2S_2 (PCM512x_PAGE_0_BASE + 41)
++#define PCM512x_DAC_ROUTING (PCM512x_PAGE_0_BASE + 42)
++#define PCM512x_DSP_PROGRAM (PCM512x_PAGE_0_BASE + 43)
++#define PCM512x_CLKDET (PCM512x_PAGE_0_BASE + 44)
++#define PCM512x_AUTO_MUTE (PCM512x_PAGE_0_BASE + 59)
++#define PCM512x_DIGITAL_VOLUME_1 (PCM512x_PAGE_0_BASE + 60)
++#define PCM512x_DIGITAL_VOLUME_2 (PCM512x_PAGE_0_BASE + 61)
++#define PCM512x_DIGITAL_VOLUME_3 (PCM512x_PAGE_0_BASE + 62)
++#define PCM512x_DIGITAL_MUTE_1 (PCM512x_PAGE_0_BASE + 63)
++#define PCM512x_DIGITAL_MUTE_2 (PCM512x_PAGE_0_BASE + 64)
++#define PCM512x_DIGITAL_MUTE_3 (PCM512x_PAGE_0_BASE + 65)
++#define PCM512x_GPIO_OUTPUT_1 (PCM512x_PAGE_0_BASE + 80)
++#define PCM512x_GPIO_OUTPUT_2 (PCM512x_PAGE_0_BASE + 81)
++#define PCM512x_GPIO_OUTPUT_3 (PCM512x_PAGE_0_BASE + 82)
++#define PCM512x_GPIO_OUTPUT_4 (PCM512x_PAGE_0_BASE + 83)
++#define PCM512x_GPIO_OUTPUT_5 (PCM512x_PAGE_0_BASE + 84)
++#define PCM512x_GPIO_OUTPUT_6 (PCM512x_PAGE_0_BASE + 85)
++#define PCM512x_GPIO_CONTROL_1 (PCM512x_PAGE_0_BASE + 86)
++#define PCM512x_GPIO_CONTROL_2 (PCM512x_PAGE_0_BASE + 87)
++#define PCM512x_OVERFLOW (PCM512x_PAGE_0_BASE + 90)
++#define PCM512x_RATE_DET_1 (PCM512x_PAGE_0_BASE + 91)
++#define PCM512x_RATE_DET_2 (PCM512x_PAGE_0_BASE + 92)
++#define PCM512x_RATE_DET_3 (PCM512x_PAGE_0_BASE + 93)
++#define PCM512x_RATE_DET_4 (PCM512x_PAGE_0_BASE + 94)
++#define PCM512x_ANALOG_MUTE_DET (PCM512x_PAGE_0_BASE + 108)
++#define PCM512x_GPIN (PCM512x_PAGE_0_BASE + 119)
++#define PCM512x_DIGITAL_MUTE_DET (PCM512x_PAGE_0_BASE + 120)
++
++#define PCM512x_MAX_REGISTER (PCM512x_PAGE_0_BASE + 120)
++
++/* Page 0, Register 1 - reset */
++#define PCM512x_RSTR (1 << 0)
++#define PCM512x_RSTM (1 << 4)
++
++/* Page 0, Register 2 - power */
++#define PCM512x_RQPD (1 << 0)
++#define PCM512x_RQPD_SHIFT 0
++#define PCM512x_RQST (1 << 4)
++#define PCM512x_RQST_SHIFT 4
++
++/* Page 0, Register 3 - mute */
++#define PCM512x_RQMR_SHIFT 0
++#define PCM512x_RQML_SHIFT 4
++
++/* Page 0, Register 4 - PLL */
++#define PCM512x_PLCE (1 << 0)
++#define PCM512x_RLCE_SHIFT 0
++#define PCM512x_PLCK (1 << 4)
++#define PCM512x_PLCK_SHIFT 4
++
++/* Page 0, Register 7 - DSP */
++#define PCM512x_SDSL (1 << 0)
++#define PCM512x_SDSL_SHIFT 0
++#define PCM512x_DEMP (1 << 4)
++#define PCM512x_DEMP_SHIFT 4
++
++/* Page 0, Register 13 - PLL reference */
++#define PCM512x_SREF (1 << 4)
++
++/* Page 0, Register 37 - Error detection */
++#define PCM512x_IPLK (1 << 0)
++#define PCM512x_DCAS (1 << 1)
++#define PCM512x_IDCM (1 << 2)
++#define PCM512x_IDCH (1 << 3)
++#define PCM512x_IDSK (1 << 4)
++#define PCM512x_IDBK (1 << 5)
++#define PCM512x_IDFS (1 << 6)
++
++/* Page 0, Register 42 - DAC routing */
++#define PCM512x_AUPR_SHIFT 0
++#define PCM512x_AUPL_SHIFT 4
++
++/* Page 0, Register 59 - auto mute */
++#define PCM512x_ATMR_SHIFT 0
++#define PCM512x_ATML_SHIFT 4
++
++/* Page 0, Register 63 - ramp rates */
++#define PCM512x_VNDF_SHIFT 6
++#define PCM512x_VNDS_SHIFT 4
++#define PCM512x_VNUF_SHIFT 2
++#define PCM512x_VNUS_SHIFT 0
++
++/* Page 0, Register 64 - emergency ramp rates */
++#define PCM512x_VEDF_SHIFT 6
++#define PCM512x_VEDS_SHIFT 4
++
++/* Page 0, Register 65 - Digital mute enables */
++#define PCM512x_ACTL_SHIFT 2
++#define PCM512x_AMLE_SHIFT 1
++#define PCM512x_AMLR_SHIFT 0
++
++#endif
+diff -Nur linux-3.12.18/sound/soc/codecs/wm8804.c linux-rpi/sound/soc/codecs/wm8804.c
+--- linux-3.12.18/sound/soc/codecs/wm8804.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/sound/soc/codecs/wm8804.c 2014-04-24 15:35:05.509580657 +0200
@@ -63,6 +63,7 @@
struct regmap *regmap;
struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
@@ -100951,9 +106567,9 @@ diff -Nur linux-3.12.13/sound/soc/codecs/wm8804.c linux-raspberry-pi/sound/soc/c
.controls = wm8804_snd_controls,
.num_controls = ARRAY_SIZE(wm8804_snd_controls),
-diff -Nur linux-3.12.13/sound/soc/codecs/wm8804.h linux-raspberry-pi/sound/soc/codecs/wm8804.h
---- linux-3.12.13/sound/soc/codecs/wm8804.h 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/codecs/wm8804.h 2014-03-11 17:33:43.000000000 +0100
+diff -Nur linux-3.12.18/sound/soc/codecs/wm8804.h linux-rpi/sound/soc/codecs/wm8804.h
+--- linux-3.12.18/sound/soc/codecs/wm8804.h 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/sound/soc/codecs/wm8804.h 2014-04-24 15:35:05.509580657 +0200
@@ -57,5 +57,9 @@
#define WM8804_CLKOUT_SRC_OSCCLK 4
@@ -100964,9 +106580,9 @@ diff -Nur linux-3.12.13/sound/soc/codecs/wm8804.h linux-raspberry-pi/sound/soc/c
+#define WM8804_MCLKDIV_128FS 1
#endif /* _WM8804_H */
-diff -Nur linux-3.12.13/sound/soc/Kconfig linux-raspberry-pi/sound/soc/Kconfig
---- linux-3.12.13/sound/soc/Kconfig 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/Kconfig 2014-03-11 17:51:48.000000000 +0100
+diff -Nur linux-3.12.18/sound/soc/Kconfig linux-rpi/sound/soc/Kconfig
+--- linux-3.12.18/sound/soc/Kconfig 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/sound/soc/Kconfig 2014-04-24 16:04:42.783152901 +0200
@@ -33,6 +33,7 @@
# All the supported SoCs
source "sound/soc/atmel/Kconfig"
@@ -100975,9 +106591,9 @@ diff -Nur linux-3.12.13/sound/soc/Kconfig linux-raspberry-pi/sound/soc/Kconfig
source "sound/soc/blackfin/Kconfig"
source "sound/soc/cirrus/Kconfig"
source "sound/soc/davinci/Kconfig"
-diff -Nur linux-3.12.13/sound/soc/Makefile linux-raspberry-pi/sound/soc/Makefile
---- linux-3.12.13/sound/soc/Makefile 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/Makefile 2014-03-11 17:51:48.000000000 +0100
+diff -Nur linux-3.12.18/sound/soc/Makefile linux-rpi/sound/soc/Makefile
+--- linux-3.12.18/sound/soc/Makefile 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/sound/soc/Makefile 2014-04-24 16:04:42.783152901 +0200
@@ -10,6 +10,7 @@
obj-$(CONFIG_SND_SOC) += generic/
obj-$(CONFIG_SND_SOC) += atmel/
@@ -100986,10 +106602,68 @@ diff -Nur linux-3.12.13/sound/soc/Makefile linux-raspberry-pi/sound/soc/Makefile
obj-$(CONFIG_SND_SOC) += blackfin/
obj-$(CONFIG_SND_SOC) += cirrus/
obj-$(CONFIG_SND_SOC) += davinci/
-diff -Nur linux-3.12.13/sound/soc/soc-core.c linux-raspberry-pi/sound/soc/soc-core.c
---- linux-3.12.13/sound/soc/soc-core.c 2014-02-22 22:32:50.000000000 +0100
-+++ linux-raspberry-pi/sound/soc/soc-core.c 2014-03-11 17:51:55.000000000 +0100
-@@ -3576,6 +3576,22 @@
+diff -Nur linux-3.12.18/sound/soc/soc-core.c linux-rpi/sound/soc/soc-core.c
+--- linux-3.12.18/sound/soc/soc-core.c 2014-04-18 11:14:28.000000000 +0200
++++ linux-rpi/sound/soc/soc-core.c 2014-04-24 16:04:54.819269165 +0200
+@@ -3038,8 +3038,8 @@
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
+- uinfo->value.integer.min = 0;
+- uinfo->value.integer.max = platform_max - min;
++ uinfo->value.integer.min = min;
++ uinfo->value.integer.max = platform_max;
+
+ return 0;
+ }
+@@ -3070,9 +3070,10 @@
+ unsigned int val, val_mask;
+ int ret;
+
+- val = ((ucontrol->value.integer.value[0] + min) & mask);
+ if (invert)
+- val = max - val;
++ val = ((max - ucontrol->value.integer.value[0] + min) & mask);
++ else
++ val = (ucontrol->value.integer.value[0] & mask);
+ val_mask = mask << shift;
+ val = val << shift;
+
+@@ -3081,9 +3082,10 @@
+ return ret;
+
+ if (snd_soc_volsw_is_stereo(mc)) {
+- val = ((ucontrol->value.integer.value[1] + min) & mask);
+ if (invert)
+- val = max - val;
++ val = ((max - ucontrol->value.integer.value[1] + min) & mask);
++ else
++ val = (ucontrol->value.integer.value[1] & mask);
+ val_mask = mask << shift;
+ val = val << shift;
+
+@@ -3121,18 +3123,14 @@
+ (snd_soc_read(codec, reg) >> shift) & mask;
+ if (invert)
+ ucontrol->value.integer.value[0] =
+- max - ucontrol->value.integer.value[0];
+- ucontrol->value.integer.value[0] =
+- ucontrol->value.integer.value[0] - min;
++ max - ucontrol->value.integer.value[0] + min;
+
+ if (snd_soc_volsw_is_stereo(mc)) {
+ ucontrol->value.integer.value[1] =
+ (snd_soc_read(codec, rreg) >> shift) & mask;
+ if (invert)
+ ucontrol->value.integer.value[1] =
+- max - ucontrol->value.integer.value[1];
+- ucontrol->value.integer.value[1] =
+- ucontrol->value.integer.value[1] - min;
++ max - ucontrol->value.integer.value[1] + min;
+ }
+
+ return 0;
+@@ -3576,6 +3574,22 @@
EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
/**
diff --git a/target/linux/config/Config.in.netfilter.ip4 b/target/linux/config/Config.in.netfilter.ip4
index 7b898ba9b..019c5890c 100644
--- a/target/linux/config/Config.in.netfilter.ip4
+++ b/target/linux/config/Config.in.netfilter.ip4
@@ -39,8 +39,8 @@ config ADK_KPACKAGE_KMOD_FULL_NAT
select ADK_KPACKAGE_KMOD_NF_NAT if ADK_KERNEL_VERSION_3_4_84
select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_10_36
select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_11_10
- select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_12_14
- select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_13_7
+ select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_12_18
+ select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_13_11
select ADK_KPACKAGE_KMOD_NF_NAT_IPV4 if ADK_KERNEL_VERSION_3_14_1
config ADK_KPACKAGE_KMOD_NF_NAT
@@ -57,8 +57,8 @@ config ADK_KPACKAGE_KMOD_NF_NAT_IPV4
depends on ADK_KPACKAGE_KMOD_IP_NF_IPTABLES
depends on ADK_KERNEL_VERSION_3_10_36 \
|| ADK_KERNEL_VERSION_3_11_10 \
- || ADK_KERNEL_VERSION_3_12_14 \
- || ADK_KERNEL_VERSION_3_13_7 \
+ || ADK_KERNEL_VERSION_3_12_18 \
+ || ADK_KERNEL_VERSION_3_13_11 \
|| ADK_KERNEL_VERSION_3_14_1
help
The Full NAT option allows masquerading, port forwarding and other
diff --git a/target/linux/patches/3.12.14/bsd-compatibility.patch b/target/linux/patches/3.12.18/bsd-compatibility.patch
index b954b658f..b954b658f 100644
--- a/target/linux/patches/3.12.14/bsd-compatibility.patch
+++ b/target/linux/patches/3.12.18/bsd-compatibility.patch
diff --git a/target/linux/patches/3.12.14/defaults.patch b/target/linux/patches/3.12.18/defaults.patch
index 6cdca084e..6cdca084e 100644
--- a/target/linux/patches/3.12.14/defaults.patch
+++ b/target/linux/patches/3.12.18/defaults.patch
diff --git a/target/linux/patches/3.12.14/disable-netfilter.patch b/target/linux/patches/3.12.18/disable-netfilter.patch
index 7b1ca013a..7b1ca013a 100644
--- a/target/linux/patches/3.12.14/disable-netfilter.patch
+++ b/target/linux/patches/3.12.18/disable-netfilter.patch
diff --git a/target/linux/patches/3.12.14/export-symbol-for-exmap.patch b/target/linux/patches/3.12.18/export-symbol-for-exmap.patch
index 4f0fc8449..4f0fc8449 100644
--- a/target/linux/patches/3.12.14/export-symbol-for-exmap.patch
+++ b/target/linux/patches/3.12.18/export-symbol-for-exmap.patch
diff --git a/target/linux/patches/3.12.14/gemalto.patch b/target/linux/patches/3.12.18/gemalto.patch
index 65f7af1d7..65f7af1d7 100644
--- a/target/linux/patches/3.12.14/gemalto.patch
+++ b/target/linux/patches/3.12.18/gemalto.patch
diff --git a/target/linux/patches/3.12.14/lemote-rfkill.patch b/target/linux/patches/3.12.18/lemote-rfkill.patch
index a61488434..a61488434 100644
--- a/target/linux/patches/3.12.14/lemote-rfkill.patch
+++ b/target/linux/patches/3.12.18/lemote-rfkill.patch
diff --git a/target/linux/patches/3.12.14/microblaze-ethernet.patch b/target/linux/patches/3.12.18/microblaze-ethernet.patch
index 742ab477e..742ab477e 100644
--- a/target/linux/patches/3.12.14/microblaze-ethernet.patch
+++ b/target/linux/patches/3.12.18/microblaze-ethernet.patch
diff --git a/target/linux/patches/3.12.14/microblaze-setup.patch b/target/linux/patches/3.12.18/microblaze-setup.patch
index 43815f274..43815f274 100644
--- a/target/linux/patches/3.12.14/microblaze-setup.patch
+++ b/target/linux/patches/3.12.18/microblaze-setup.patch
diff --git a/target/linux/patches/3.12.14/mips-lzo-fix.patch b/target/linux/patches/3.12.18/mips-lzo-fix.patch
index 0740bdc6a..0740bdc6a 100644
--- a/target/linux/patches/3.12.14/mips-lzo-fix.patch
+++ b/target/linux/patches/3.12.18/mips-lzo-fix.patch
diff --git a/target/linux/patches/3.12.14/mtd-rootfs.patch b/target/linux/patches/3.12.18/mtd-rootfs.patch
index 775d5fc80..775d5fc80 100644
--- a/target/linux/patches/3.12.14/mtd-rootfs.patch
+++ b/target/linux/patches/3.12.18/mtd-rootfs.patch
diff --git a/target/linux/patches/3.12.14/non-static.patch b/target/linux/patches/3.12.18/non-static.patch
index a967703d0..a967703d0 100644
--- a/target/linux/patches/3.12.14/non-static.patch
+++ b/target/linux/patches/3.12.18/non-static.patch
diff --git a/target/linux/patches/3.12.14/ppc64-missing-zlib.patch b/target/linux/patches/3.12.18/ppc64-missing-zlib.patch
index c6e0616be..c6e0616be 100644
--- a/target/linux/patches/3.12.14/ppc64-missing-zlib.patch
+++ b/target/linux/patches/3.12.18/ppc64-missing-zlib.patch
diff --git a/target/linux/patches/3.12.14/startup.patch b/target/linux/patches/3.12.18/startup.patch
index 4cd477da1..4cd477da1 100644
--- a/target/linux/patches/3.12.14/startup.patch
+++ b/target/linux/patches/3.12.18/startup.patch
diff --git a/target/linux/patches/3.12.14/usb-defaults-off.patch b/target/linux/patches/3.12.18/usb-defaults-off.patch
index 54dff2bd4..54dff2bd4 100644
--- a/target/linux/patches/3.12.14/usb-defaults-off.patch
+++ b/target/linux/patches/3.12.18/usb-defaults-off.patch
diff --git a/target/linux/patches/3.12.14/uuid.patch b/target/linux/patches/3.12.18/uuid.patch
index ca23accdf..ca23accdf 100644
--- a/target/linux/patches/3.12.14/uuid.patch
+++ b/target/linux/patches/3.12.18/uuid.patch
diff --git a/target/linux/patches/3.12.14/vga-cons-default-off.patch b/target/linux/patches/3.12.18/vga-cons-default-off.patch
index 08a57f783..08a57f783 100644
--- a/target/linux/patches/3.12.14/vga-cons-default-off.patch
+++ b/target/linux/patches/3.12.18/vga-cons-default-off.patch
diff --git a/target/linux/patches/3.12.14/wlan-cf.patch b/target/linux/patches/3.12.18/wlan-cf.patch
index fc20759e2..fc20759e2 100644
--- a/target/linux/patches/3.12.14/wlan-cf.patch
+++ b/target/linux/patches/3.12.18/wlan-cf.patch
diff --git a/target/linux/patches/3.12.14/xargs.patch b/target/linux/patches/3.12.18/xargs.patch
index 2c7b3df59..2c7b3df59 100644
--- a/target/linux/patches/3.12.14/xargs.patch
+++ b/target/linux/patches/3.12.18/xargs.patch
diff --git a/target/linux/patches/3.12.14/zlib-inflate.patch b/target/linux/patches/3.12.18/zlib-inflate.patch
index 58e1f6d21..58e1f6d21 100644
--- a/target/linux/patches/3.12.14/zlib-inflate.patch
+++ b/target/linux/patches/3.12.18/zlib-inflate.patch
diff --git a/toolchain/kernel-headers/patches/3.12.14/cleankernel.patch b/toolchain/kernel-headers/patches/3.12.18/cleankernel.patch
index d8c055dc3..d8c055dc3 100644
--- a/toolchain/kernel-headers/patches/3.12.14/cleankernel.patch
+++ b/toolchain/kernel-headers/patches/3.12.18/cleankernel.patch
diff --git a/toolchain/kernel-headers/patches/3.12.14/mkpiggy.patch b/toolchain/kernel-headers/patches/3.12.18/mkpiggy.patch
index d4e815cd2..d4e815cd2 100644
--- a/toolchain/kernel-headers/patches/3.12.14/mkpiggy.patch
+++ b/toolchain/kernel-headers/patches/3.12.18/mkpiggy.patch
diff --git a/toolchain/kernel-headers/patches/3.12.14/relocs.patch b/toolchain/kernel-headers/patches/3.12.18/relocs.patch
index 649b9e73e..649b9e73e 100644
--- a/toolchain/kernel-headers/patches/3.12.14/relocs.patch
+++ b/toolchain/kernel-headers/patches/3.12.18/relocs.patch
diff --git a/toolchain/kernel-headers/patches/3.12.14/sgidefs.patch b/toolchain/kernel-headers/patches/3.12.18/sgidefs.patch
index f00a284d9..f00a284d9 100644
--- a/toolchain/kernel-headers/patches/3.12.14/sgidefs.patch
+++ b/toolchain/kernel-headers/patches/3.12.18/sgidefs.patch
diff --git a/toolchain/kernel-headers/patches/3.12.14/sortext.patch b/toolchain/kernel-headers/patches/3.12.18/sortext.patch
index 8fd4e1d6b..8fd4e1d6b 100644
--- a/toolchain/kernel-headers/patches/3.12.14/sortext.patch
+++ b/toolchain/kernel-headers/patches/3.12.18/sortext.patch